Coverage Report

Created: 2026-06-07 06:25

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
20.2k
#define get32(a) buf32_to_ulong ((a))
45
627k
#define get16(a) buf16_to_ulong ((a))
46
47
48
static inline unsigned int
49
blob_get_blob_flags (KEYBOXBLOB blob)
50
184k
{
51
184k
  const unsigned char *buffer;
52
184k
  size_t length;
53
54
184k
  buffer = _keybox_get_blob_image (blob, &length);
55
184k
  if (length < 8)
56
0
    return 0; /* oops */
57
58
184k
  return get16 (buffer + 6);
59
184k
}
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
10.1k
{
106
10.1k
  size_t pos;
107
10.1k
  size_t nkeys, keyinfolen;
108
10.1k
  size_t nuids, uidinfolen;
109
10.1k
  size_t nserial;
110
10.1k
  size_t nsigs, siginfolen, siginfooff;
111
112
10.1k
  switch (what)
113
10.1k
    {
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
10.1k
    case KEYBOX_FLAG_SIG_INFO:
125
10.1k
      if (length < 20)
126
0
        return GPG_ERR_INV_OBJ;
127
      /* Key info. */
128
10.1k
      nkeys = get16 (buffer + 16);
129
10.1k
      keyinfolen = get16 (buffer + 18 );
130
10.1k
      if (keyinfolen < 28)
131
0
        return GPG_ERR_INV_OBJ;
132
10.1k
      pos = 20 + keyinfolen*nkeys;
133
10.1k
      if (pos+2 > length)
134
0
        return GPG_ERR_INV_OBJ; /* Out of bounds. */
135
      /* Serial number. */
136
10.1k
      nserial = get16 (buffer+pos);
137
10.1k
      pos += 2 + nserial;
138
10.1k
      if (pos+4 > length)
139
0
        return GPG_ERR_INV_OBJ; /* Out of bounds. */
140
      /* User IDs. */
141
10.1k
      nuids = get16 (buffer + pos); pos += 2;
142
10.1k
      uidinfolen = get16 (buffer + pos); pos += 2;
143
10.1k
      if (uidinfolen < 12 )
144
0
        return GPG_ERR_INV_OBJ;
145
10.1k
      pos += uidinfolen*nuids;
146
10.1k
      if (pos+4 > length)
147
0
        return GPG_ERR_INV_OBJ ; /* Out of bounds. */
148
      /* Signature info. */
149
10.1k
      siginfooff = pos;
150
10.1k
      nsigs = get16 (buffer + pos); pos += 2;
151
10.1k
      siginfolen = get16 (buffer + pos); pos += 2;
152
10.1k
      if (siginfolen < 4 )
153
0
        return GPG_ERR_INV_OBJ;
154
10.1k
      pos += siginfolen*nsigs;
155
10.1k
      if (pos+1+1+2+4+4+4+4 > length)
156
0
        return GPG_ERR_INV_OBJ ; /* Out of bounds. */
157
10.1k
      *flag_size = 1;
158
10.1k
      *flag_off = pos;
159
10.1k
      switch (what)
160
10.1k
        {
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
10.1k
        case KEYBOX_FLAG_SIG_INFO:
169
10.1k
          *flag_size = siginfolen * nsigs;
170
10.1k
          *flag_off = siginfooff;
171
10.1k
          break;
172
0
        default:
173
0
          break;
174
10.1k
        }
175
10.1k
      break;
176
177
10.1k
    default:
178
0
      return GPG_ERR_INV_FLAG;
179
10.1k
    }
180
10.1k
  return 0;
181
10.1k
}
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
54.8k
{
247
54.8k
  const unsigned char *buffer;
248
54.8k
  size_t length;
249
54.8k
  size_t pos, off;
250
54.8k
  size_t nkeys, keyinfolen;
251
54.8k
  int idx, fpr32, storedfprlen;
252
253
54.8k
  buffer = _keybox_get_blob_image (blob, &length);
254
54.8k
  if (length < 40)
255
0
    return 0; /* blob too short */
256
54.8k
  fpr32 = buffer[5] == 2;
257
258
  /*keys*/
259
54.8k
  nkeys = get16 (buffer + 16);
260
54.8k
  keyinfolen = get16 (buffer + 18 );
261
54.8k
  if (keyinfolen < (fpr32?56:28))
262
0
    return 0; /* invalid blob */
263
54.8k
  pos = 20;
264
54.8k
  if (pos + (uint64_t)keyinfolen*nkeys > (uint64_t)length)
265
0
    return 0; /* out of bounds */
266
267
399k
  for (idx=0; idx < nkeys; idx++)
268
351k
    {
269
351k
      off = pos + idx*keyinfolen;
270
351k
      if (fpr32)
271
3.89k
        storedfprlen = (get16 (buffer + off + 32) & 0x80)? 32:20;
272
347k
      else
273
347k
        storedfprlen = 20;
274
351k
      if (storedfprlen == fprlen
275
335k
          && !memcmp (buffer + off, fpr, storedfprlen))
276
6.10k
        return idx+1; /* found */
277
351k
    }
278
48.7k
  return 0; /* not found */
279
54.8k
}
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
683k
  for (idx=0; idx < nkeys; idx++)
310
560k
    {
311
560k
      off = pos + idx*keyinfolen;
312
560k
      if (!fpr32)
313
549k
        {
314
          /* Blob has only 20 fingerprints - use the FPROFF.    */
315
549k
          if (!memcmp (buffer + off + fproff, fpr, fprlen))
316
6.15k
            return idx+1; /* found */
317
549k
        }
318
10.2k
      else if ((buffer[off + 32 + 1] & 0x80))
319
10.2k
        {
320
          /* This (sub)key has a 32 byte fpr -> use 0 as offset. */
321
10.2k
          if (!memcmp (buffer + off, fpr, fprlen))
322
5
            return idx+1; /* found */
323
10.2k
        }
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
560k
    }
331
123k
  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
54.8k
{
739
54.8k
  return blob_cmp_fpr (blob, fpr, fprlen);
740
54.8k
}
741
742
static inline int
743
has_keygrip (KEYBOXBLOB blob, const unsigned char *grip)
744
0
{
745
0
  if (blob_get_type (blob) == KEYBOX_BLOBTYPE_PGP)
746
0
    return blob_openpgp_has_grip (blob, grip);
747
#ifdef KEYBOX_WITH_X509
748
  if (blob_get_type (blob) == KEYBOX_BLOBTYPE_X509)
749
    return blob_x509_has_grip (blob, grip);
750
#endif
751
0
  return 0;
752
0
}
753
754
755
/* The UBID is the primary fingerprint.  For OpenPGP v5 keys only the
756
 * leftmost 20 bytes (UBID_LEN) are used.  */
757
static inline int
758
has_ubid (KEYBOXBLOB blob, const unsigned char *ubid)
759
0
{
760
0
  return blob_cmp_ubid (blob, ubid);
761
0
}
762
763
764
static inline int
765
has_issuer (KEYBOXBLOB blob, const char *name)
766
0
{
767
0
  size_t namelen;
768
769
0
  return_val_if_fail (name, 0);
770
771
0
  if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
772
0
    return 0;
773
774
0
  namelen = strlen (name);
775
0
  return blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0, 1);
776
0
}
777
778
static inline int
779
has_issuer_sn (KEYBOXBLOB blob, const char *name,
780
               const unsigned char *sn, int snlen)
781
0
{
782
0
  size_t namelen;
783
784
0
  return_val_if_fail (name, 0);
785
0
  return_val_if_fail (sn, 0);
786
787
0
  if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
788
0
    return 0;
789
790
0
  namelen = strlen (name);
791
792
0
  return (blob_cmp_sn (blob, sn, snlen)
793
0
          && blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0, 1));
794
0
}
795
796
static inline int
797
has_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
798
0
{
799
0
  return_val_if_fail (sn, 0);
800
801
0
  if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
802
0
    return 0;
803
0
  return blob_cmp_sn (blob, sn, snlen);
804
0
}
805
806
static inline int
807
has_subject (KEYBOXBLOB blob, const char *name)
808
0
{
809
0
  size_t namelen;
810
811
0
  return_val_if_fail (name, 0);
812
813
0
  if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
814
0
    return 0;
815
816
0
  namelen = strlen (name);
817
0
  return blob_cmp_name (blob, 1 /* subject */, name, namelen, 0, 1);
818
0
}
819
820
821
static inline int
822
has_username (KEYBOXBLOB blob, const char *name, int substr)
823
0
{
824
0
  size_t namelen;
825
0
  int btype;
826
827
0
  return_val_if_fail (name, 0);
828
829
0
  btype = blob_get_type (blob);
830
0
  if (btype != KEYBOX_BLOBTYPE_PGP && btype != KEYBOX_BLOBTYPE_X509)
831
0
    return 0;
832
833
0
  namelen = strlen (name);
834
0
  return blob_cmp_name (blob, -1 /* all subject/user names */, name,
835
0
                        namelen, substr, (btype == KEYBOX_BLOBTYPE_X509));
836
0
}
837
838
839
static inline int
840
has_mail (KEYBOXBLOB blob, const char *name, int substr)
841
0
{
842
0
  size_t namelen;
843
0
  int btype;
844
845
0
  return_val_if_fail (name, 0);
846
847
0
  btype = blob_get_type (blob);
848
0
  if (btype != KEYBOX_BLOBTYPE_PGP && btype != KEYBOX_BLOBTYPE_X509)
849
0
    return 0;
850
851
0
  if (btype == KEYBOX_BLOBTYPE_PGP && *name == '<')
852
0
    name++; /* Hack to remove the leading '<' for gpg.  */
853
854
0
  namelen = strlen (name);
855
0
  if (namelen && name[namelen-1] == '>')
856
0
    namelen--;
857
0
  return blob_cmp_mail (blob, name, namelen, substr,
858
0
                        (btype == KEYBOX_BLOBTYPE_X509));
859
0
}
860
861
862
static void
863
release_sn_array (struct sn_array_s *array, size_t size)
864
0
{
865
0
  size_t n;
866
867
0
  for (n=0; n < size; n++)
868
0
    xfree (array[n].sn);
869
0
  xfree (array);
870
0
}
871
872
873

874
/*
875
 *
876
 * The search API
877
 *
878
 */
879
880
gpg_error_t
881
keybox_search_reset (KEYBOX_HANDLE hd)
882
1.24M
{
883
1.24M
  if (!hd)
884
0
    return gpg_error (GPG_ERR_INV_VALUE);
885
886
1.24M
  if (hd->found.blob)
887
5.77k
    {
888
5.77k
      _keybox_release_blob (hd->found.blob);
889
5.77k
      hd->found.blob = NULL;
890
5.77k
    }
891
892
1.24M
  if (hd->fp)
893
45.6k
    {
894
45.6k
      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
45.6k
    }
902
1.24M
  hd->error = 0;
903
1.24M
  hd->eof = 0;
904
1.24M
  return 0;
905
1.24M
}
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
25.0k
{
918
25.0k
  gpg_error_t rc;
919
25.0k
  size_t n;
920
25.0k
  int need_words, any_skip;
921
25.0k
  KEYBOXBLOB blob = NULL;
922
25.0k
  struct sn_array_s *sn_array = NULL;
923
25.0k
  int pk_no, uid_no;
924
25.0k
  off_t lastfoundoff;
925
926
25.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
25.0k
  if (hd->found.blob)
932
2.32k
    {
933
2.32k
      lastfoundoff = _keybox_get_blob_fileoffset (hd->found.blob);
934
2.32k
      _keybox_release_blob (hd->found.blob);
935
2.32k
      hd->found.blob = NULL;
936
2.32k
    }
937
22.7k
  else
938
22.7k
    lastfoundoff = 0;
939
940
25.0k
  if (hd->error)
941
0
    return hd->error; /* still in error state */
942
25.0k
  if (hd->eof)
943
0
    return -1; /* still EOF */
944
945
  /* figure out what information we need */
946
25.0k
  need_words = any_skip = 0;
947
50.1k
  for (n=0; n < ndesc; n++)
948
25.0k
    {
949
25.0k
      switch (desc[n].mode)
950
25.0k
        {
951
0
        case KEYDB_SEARCH_MODE_WORDS:
952
0
          need_words = 1;
953
0
          break;
954
3.86k
        case KEYDB_SEARCH_MODE_FIRST:
955
          /* always restart the search in this mode */
956
3.86k
          keybox_search_reset (hd);
957
3.86k
          lastfoundoff = 0;
958
3.86k
          break;
959
21.1k
        default:
960
21.1k
          break;
961
25.0k
  }
962
25.0k
      if (desc[n].skipfnc)
963
0
        any_skip = 1;
964
25.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
25.0k
    }
971
972
25.0k
  (void)need_words;  /* Not yet implemented.  */
973
974
25.0k
  if (!hd->fp)
975
15.7k
    {
976
15.7k
      rc = _keybox_ll_open (&hd->fp, hd->kb->fname, 0);
977
15.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
15.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
15.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
25.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
25.0k
  pk_no = uid_no = 0;
1072
25.0k
  for (;;)
1073
219k
    {
1074
219k
      unsigned int blobflags;
1075
219k
      int blobtype;
1076
1077
219k
      _keybox_release_blob (blob); blob = NULL;
1078
219k
      rc = _keybox_read_blob (&blob, hd->fp, NULL);
1079
219k
      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
219k
      if (rc)
1087
12.7k
        break;
1088
1089
206k
      blobtype = blob_get_type (blob);
1090
206k
      if (blobtype == KEYBOX_BLOBTYPE_HEADER)
1091
22.7k
        continue;
1092
184k
      if (want_blobtype && blobtype != want_blobtype)
1093
0
        continue;
1094
1095
184k
      blobflags = blob_get_blob_flags (blob);
1096
184k
      if (!hd->ephemeral && (blobflags & 2))
1097
0
        continue; /* Not in ephemeral mode but blob is flagged ephemeral.  */
1098
1099
356k
      for (n=0; n < ndesc; n++)
1100
184k
        {
1101
184k
          switch (desc[n].mode)
1102
184k
            {
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
6.15k
                goto found;
1158
123k
              break;
1159
1160
123k
            case KEYDB_SEARCH_MODE_FPR:
1161
54.8k
              pk_no = has_fingerprint (blob, desc[n].u.fpr, desc[n].fprlen);
1162
54.8k
              if (pk_no)
1163
6.10k
                goto found;
1164
48.7k
              break;
1165
1166
48.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
184k
            }
1184
184k
  }
1185
171k
      continue;
1186
171k
    found:
1187
      /* Record which DESC we matched on.  Note this value is only
1188
   meaningful if this function returns with no errors. */
1189
12.2k
      if(r_descindex)
1190
0
  *r_descindex = n;
1191
12.2k
      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
12.2k
      if (n == ndesc)
1201
12.2k
        break; /* got it */
1202
12.2k
    }
1203
1204
25.0k
  if (!rc)
1205
12.2k
    {
1206
12.2k
      hd->found.blob = blob;
1207
12.2k
      hd->found.pk_no = pk_no;
1208
12.2k
      hd->found.uid_no = uid_no;
1209
12.2k
    }
1210
12.7k
  else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
1211
12.7k
    {
1212
12.7k
      _keybox_release_blob (blob);
1213
12.7k
      hd->eof = 1;
1214
12.7k
    }
1215
0
  else
1216
0
    {
1217
0
      _keybox_release_blob (blob);
1218
0
      hd->error = rc;
1219
0
    }
1220
1221
25.0k
  if (sn_array)
1222
0
    release_sn_array (sn_array, ndesc);
1223
1224
25.0k
  return rc;
1225
25.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
10.1k
{
1318
10.1k
  gpg_error_t err;
1319
10.1k
  const unsigned char *buffer;
1320
10.1k
  size_t length;
1321
10.1k
  size_t image_off, image_len;
1322
10.1k
  size_t siginfo_off, siginfo_len;
1323
1324
10.1k
  *r_iobuf = NULL;
1325
1326
10.1k
  if (!hd)
1327
0
    return gpg_error (GPG_ERR_INV_VALUE);
1328
10.1k
  if (!hd->found.blob)
1329
0
    return gpg_error (GPG_ERR_NOTHING_FOUND);
1330
1331
10.1k
  if (blob_get_type (hd->found.blob) != KEYBOX_BLOBTYPE_PGP)
1332
0
    return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
1333
1334
10.1k
  buffer = _keybox_get_blob_image (hd->found.blob, &length);
1335
10.1k
  if (length < 40)
1336
0
    return gpg_error (GPG_ERR_TOO_SHORT);
1337
10.1k
  image_off = get32 (buffer+8);
1338
10.1k
  image_len = get32 (buffer+12);
1339
10.1k
  if ((uint64_t)image_off+(uint64_t)image_len > (uint64_t)length)
1340
0
    return gpg_error (GPG_ERR_TOO_SHORT);
1341
1342
10.1k
  err = _keybox_get_flag_location (buffer, length, KEYBOX_FLAG_SIG_INFO,
1343
10.1k
                                   &siginfo_off, &siginfo_len);
1344
10.1k
  if (err)
1345
0
    return err;
1346
1347
10.1k
  *r_pk_no  = hd->found.pk_no;
1348
10.1k
  *r_uid_no = hd->found.uid_no;
1349
10.1k
  *r_iobuf = iobuf_temp_with_content (buffer+image_off, image_len);
1350
10.1k
  return 0;
1351
10.1k
}
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.49k
{
1454
1.49k
  if (!hd->fp)
1455
0
    return 0;
1456
1.49k
  return es_ftello (hd->fp);
1457
1.49k
}
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
}