1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

Merge branch 'master' into switch-to-gpgk

--
This commit is contained in:
Werner Koch 2019-03-18 19:41:07 +01:00
commit a52d883fdb
No known key found for this signature in database
GPG key ID: E3FDFF218E45B72B
237 changed files with 21268 additions and 4575 deletions

View file

@ -329,6 +329,18 @@ dump_fpr (const unsigned char *buffer, size_t len)
}
static void
dump_grip (const unsigned char *buffer, size_t len)
{
int i;
for (i=0; i < len; i++, buffer++)
{
printf ("%02X", buffer[0]);
}
}
static void
dump_openpgp_key (keybox_openpgp_info_t info, const unsigned char *image)
{
@ -338,6 +350,9 @@ dump_openpgp_key (keybox_openpgp_info_t info, const unsigned char *image)
info->primary.keyid[6], info->primary.keyid[7] );
dump_fpr (info->primary.fpr, info->primary.fprlen);
putchar ('\n');
fputs ("grp ", stdout);
dump_grip (info->primary.grip, 20);
putchar ('\n');
if (info->nsubkeys)
{
struct _keybox_openpgp_key_info *k;
@ -351,6 +366,9 @@ dump_openpgp_key (keybox_openpgp_info_t info, const unsigned char *image)
k->keyid[6], k->keyid[7] );
dump_fpr (k->fpr, k->fprlen);
putchar ('\n');
fputs ("grp ", stdout);
dump_grip (k->grip, 20);
putchar ('\n');
k = k->next;
}
while (k);

View file

@ -62,7 +62,8 @@
2 = OpenPGP
3 = X509
- byte Version number of this blob type
1 = The only defined value
1 = Blob with 20 byte fingerprints
2 = Blob with 32 byte fingerprints and no keyids.
- u16 Blob flags
bit 0 = contains secret key material (not used)
bit 1 = ephemeral blob (e.g. used while querying external resources)
@ -70,19 +71,36 @@
certificate
- u32 The length of the keyblock or certificate
- u16 [NKEYS] Number of keys (at least 1!) [X509: always 1]
- u16 Size of the key information structure (at least 28).
- u16 Size of the key information structure (at least 28 or 56).
- NKEYS times:
Version 1 blob:
- b20 The fingerprint of the key.
Fingerprints are always 20 bytes, MD5 left padded with zeroes.
- u32 Offset to the n-th key's keyID (a keyID is always 8 byte)
or 0 if not known which is the case only for X.509.
Note that this separate keyid is not anymore used by
gnupg since the support for v3 keys has been removed.
We create this field anyway for backward compatibility with
old EOL-ed versions. Eventually we will completely move
to the version 2 blob format.
- u16 Key flags
bit 0 = qualified signature (not yet implemented}
- u16 RFU
- bN Optional filler up to the specified length of this
structure.
Version 2 blob:
- b32 The fingerprint of the key. This fingerprint is
either 20 or 32 bytes. A 20 byte fingerprint is
right filled with zeroes.
- u16 Key flags
bit 0 = qualified signature (not yet implemented}
bit 7 = 32 byte fingerprint in use.
- u16 RFU
- b20 keygrip
- bN Optional filler up to the specified length of this
structure.
- u16 Size of the serial number (may be zero)
- bN The serial number. N as giiven above.
- bN The serial number. N as given above.
- u16 Number of user IDs
- u16 [NUIDS] Size of user ID information structure
- NUIDS times:
@ -172,15 +190,12 @@ struct membuf {
};
/* #if MAX_FINGERPRINT_LEN < 20 */
/* #error fingerprints are 20 bytes */
/* #endif */
struct keyboxblob_key {
char fpr[20];
char fpr[32];
u32 off_kid;
ulong off_kid_addr;
u16 flags;
u16 fprlen; /* Either 20 or 32 */
};
struct keyboxblob_uid {
u32 off;
@ -380,10 +395,9 @@ pgp_create_key_part_single (KEYBOXBLOB blob, int n,
int off;
fprlen = kinfo->fprlen;
if (fprlen > 20)
fprlen = 20;
memcpy (blob->keys[n].fpr, kinfo->fpr, fprlen);
if (fprlen != 20) /* v3 fpr - shift right and fill with zeroes. */
blob->keys[n].fprlen = fprlen;
if (fprlen < 20) /* v3 fpr - shift right and fill with zeroes. */
{
memmove (blob->keys[n].fpr + 20 - fprlen, blob->keys[n].fpr, fprlen);
memset (blob->keys[n].fpr, 0, 20 - fprlen);
@ -533,30 +547,51 @@ release_kid_list (struct keyid_list *kl)
}
/* Create a new blob header. If WANT_FPR32 is set a version 2 blob is
* created. */
static int
create_blob_header (KEYBOXBLOB blob, int blobtype, int as_ephemeral)
create_blob_header (KEYBOXBLOB blob, int blobtype, int as_ephemeral,
int want_fpr32)
{
struct membuf *a = blob->buf;
int i;
put32 ( a, 0 ); /* blob length, needs fixup */
put8 ( a, blobtype);
put8 ( a, 1 ); /* blob type version */
put8 ( a, want_fpr32? 2:1 ); /* blob type version */
put16 ( a, as_ephemeral? 2:0 ); /* blob flags */
put32 ( a, 0 ); /* offset to the raw data, needs fixup */
put32 ( a, 0 ); /* length of the raw data, needs fixup */
put16 ( a, blob->nkeys );
put16 ( a, 20 + 4 + 2 + 2 ); /* size of key info */
if (want_fpr32)
put16 ( a, 32 + 2 + 2 + 20); /* size of key info */
else
put16 ( a, 20 + 4 + 2 + 2 ); /* size of key info */
for ( i=0; i < blob->nkeys; i++ )
{
put_membuf (a, blob->keys[i].fpr, 20);
blob->keys[i].off_kid_addr = a->len;
put32 ( a, 0 ); /* offset to keyid, fixed up later */
put16 ( a, blob->keys[i].flags );
put16 ( a, 0 ); /* reserved */
if (want_fpr32)
{
put_membuf (a, blob->keys[i].fpr, blob->keys[i].fprlen);
blob->keys[i].off_kid_addr = a->len;
if (blob->keys[i].fprlen == 32)
put16 ( a, (blob->keys[i].flags | 0x80));
else
put16 ( a, blob->keys[i].flags);
put16 ( a, 0 ); /* reserved */
/* FIXME: Put the real grip here instead of the filler. */
put_membuf (a, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20);
}
else
{
log_assert (blob->keys[i].fprlen <= 20);
put_membuf (a, blob->keys[i].fpr, 20);
blob->keys[i].off_kid_addr = a->len;
put32 ( a, 0 ); /* offset to keyid, fixed up later */
put16 ( a, blob->keys[i].flags );
put16 ( a, 0 ); /* reserved */
}
}
put16 (a, blob->seriallen); /*fixme: check that it fits into 16 bits*/
@ -593,11 +628,14 @@ create_blob_header (KEYBOXBLOB blob, int blobtype, int as_ephemeral)
/* space where we write keyIDs and other stuff so that the
pointers can actually point to somewhere */
if (blobtype == KEYBOX_BLOBTYPE_PGP)
if (blobtype == KEYBOX_BLOBTYPE_PGP && !want_fpr32)
{
/* We need to store the keyids for all pgp v3 keys because those key
IDs are not part of the fingerprint. While we are doing that, we
fixup all the keyID offsets */
/* For version 1 blobs, we need to store the keyids for all v3
* keys because those key IDs are not part of the fingerprint.
* While we are doing that, we fixup all the keyID offsets. For
* version 2 blobs (which can't carry v3 keys) we compute the
* keyids in the fly because they are just stripped down
* fingerprints. */
for (i=0; i < blob->nkeys; i++ )
{
if (blob->keys[i].off_kid)
@ -616,7 +654,7 @@ create_blob_header (KEYBOXBLOB blob, int blobtype, int as_ephemeral)
if (blobtype == KEYBOX_BLOBTYPE_X509)
{
/* We don't want to point to ASN.1 encoded UserIDs (DNs) but to
the utf-8 string represenation of them */
the utf-8 string representation of them */
for (i=0; i < blob->nuids; i++ )
{
if (blob->uids[i].name)
@ -711,9 +749,27 @@ _keybox_create_openpgp_blob (KEYBOXBLOB *r_blob,
{
gpg_error_t err;
KEYBOXBLOB blob;
int need_fpr32 = 0;
*r_blob = NULL;
/* Check whether we need a blob with 32 bit fingerprints. We could
* use this always but for backward compatiblity we do this only for
* v5 keys. */
if (info->primary.version == 5)
need_fpr32 = 1;
else
{
struct _keybox_openpgp_key_info *kinfo;
for (kinfo = &info->subkeys; kinfo; kinfo = kinfo->next)
if (kinfo->version == 5)
{
need_fpr32 = 1;
break;
}
}
blob = xtrycalloc (1, sizeof *blob);
if (!blob)
return gpg_error_from_syserror ();
@ -756,7 +812,8 @@ _keybox_create_openpgp_blob (KEYBOXBLOB *r_blob,
init_membuf (&blob->bufbuf, 1024);
blob->buf = &blob->bufbuf;
err = create_blob_header (blob, KEYBOX_BLOBTYPE_PGP, as_ephemeral);
err = create_blob_header (blob, KEYBOX_BLOBTYPE_PGP,
as_ephemeral, need_fpr32);
if (err)
goto leave;
err = pgp_create_blob_keyblock (blob, image, imagelen);
@ -943,7 +1000,7 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert,
init_membuf (&blob->bufbuf, 1024);
blob->buf = &blob->bufbuf;
/* write out what we already have */
rc = create_blob_header (blob, KEYBOX_BLOBTYPE_X509, as_ephemeral);
rc = create_blob_header (blob, KEYBOX_BLOBTYPE_X509, as_ephemeral, 0);
if (rc)
goto leave;
rc = x509_create_blob_cert (blob, cert);

View file

@ -94,14 +94,16 @@ struct keybox_handle {
};
/* Openpgp helper structures. */
/* OpenPGP helper structures. */
struct _keybox_openpgp_key_info
{
struct _keybox_openpgp_key_info *next;
int algo;
int version;
unsigned char grip[20];
unsigned char keyid[8];
int fprlen; /* Either 16 or 20 */
unsigned char fpr[20];
int fprlen; /* Either 16, 20 or 32 */
unsigned char fpr[32];
};
struct _keybox_openpgp_uid_info

View file

@ -170,6 +170,7 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
ulong nserial;
ulong unhashed;
const byte *p;
int is_fpr32; /* blob ersion 2 */
buffer = _keybox_get_blob_image (blob, &length);
@ -207,7 +208,9 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
fprintf (fp, "[can't dump this blob type]\n");
return 0;
}
/* Here we have either BLOGTYPE_X509 or BLOBTYPE_OPENPGP */
fprintf (fp, "Version: %d\n", buffer[5]);
is_fpr32 = buffer[5] == 2;
if (length < 40)
{
@ -267,15 +270,24 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
ulong kidoff, kflags;
fprintf (fp, "Key-Fpr[%lu]: ", n );
for (i=0; i < 20; i++ )
fprintf (fp, "%02X", p[i]);
kidoff = get32 (p + 20);
fprintf (fp, "\nKey-Kid-Off[%lu]: %lu\n", n, kidoff );
fprintf (fp, "Key-Kid[%lu]: ", n );
/* fixme: check bounds */
for (i=0; i < 8; i++ )
fprintf (fp, "%02X", buffer[kidoff+i] );
kflags = get16 (p + 24 );
if (is_fpr32)
{
kflags = get16 (p + 32 );
for (i=0; i < ((kflags & 0x80)?32:20); i++ )
fprintf (fp, "%02X", p[i]);
}
else
{
for (i=0; i < 20; i++ )
fprintf (fp, "%02X", p[i]);
kidoff = get32 (p + 20);
fprintf (fp, "\nKey-Kid-Off[%lu]: %lu\n", n, kidoff );
fprintf (fp, "Key-Kid[%lu]: ", n );
/* fixme: check bounds */
for (i=0; i < 8; i++ )
fprintf (fp, "%02X", buffer[kidoff+i] );
kflags = get16 (p + 24 );
}
fprintf( fp, "\nKey-Flags[%lu]: %04lX\n", n, kflags);
}

View file

@ -8,7 +8,7 @@
* keybox_strerror:
* @err: Error code
*
* This function returns a textual representaion of the given
* This function returns a textual representation of the given
* errorcode. If this is an unknown value, a string with the value
* is returned (Beware: it is hold in a static buffer).
*

View file

@ -38,6 +38,13 @@
#include "../common/openpgpdefs.h"
#include "../common/host2net.h"
struct keyparm_s
{
const char *mpi;
int len; /* int to avoid a cast in gcry_sexp_build. */
};
/* Assume a valid OpenPGP packet at the address pointed to by BUFBTR
which has a maximum length as stored at BUFLEN. Return the header
information of that packet and advance the pointer stored at BUFPTR
@ -165,6 +172,86 @@ next_packet (unsigned char const **bufptr, size_t *buflen,
}
/* Take a list of key parameters KP for the OpenPGP ALGO and compute
* the keygrip which will be stored at GRIP. GRIP needs to be a
* buffer of 20 bytes. */
static gpg_error_t
keygrip_from_keyparm (int algo, struct keyparm_s *kp, unsigned char *grip)
{
gpg_error_t err;
gcry_sexp_t s_pkey = NULL;
switch (algo)
{
case PUBKEY_ALGO_DSA:
err = gcry_sexp_build (&s_pkey, NULL,
"(public-key(dsa(p%b)(q%b)(g%b)(y%b)))",
kp[0].len, kp[0].mpi,
kp[1].len, kp[1].mpi,
kp[2].len, kp[2].mpi,
kp[3].len, kp[3].mpi);
break;
case PUBKEY_ALGO_ELGAMAL:
case PUBKEY_ALGO_ELGAMAL_E:
err = gcry_sexp_build (&s_pkey, NULL,
"(public-key(elg(p%b)(g%b)(y%b)))",
kp[0].len, kp[0].mpi,
kp[1].len, kp[1].mpi,
kp[2].len, kp[2].mpi);
break;
case PUBKEY_ALGO_RSA:
case PUBKEY_ALGO_RSA_S:
case PUBKEY_ALGO_RSA_E:
err = gcry_sexp_build (&s_pkey, NULL,
"(public-key(rsa(n%b)(e%b)))",
kp[0].len, kp[0].mpi,
kp[1].len, kp[1].mpi);
break;
case PUBKEY_ALGO_EDDSA:
case PUBKEY_ALGO_ECDSA:
case PUBKEY_ALGO_ECDH:
{
char *curve = openpgp_oidbuf_to_str (kp[0].mpi, kp[0].len);
if (!curve)
err = gpg_error_from_syserror ();
else
{
err = gcry_sexp_build
(&s_pkey, NULL,
(algo == PUBKEY_ALGO_EDDSA)?
"(public-key(ecc(curve%s)(flags eddsa)(q%b)))":
(algo == PUBKEY_ALGO_ECDH
&& openpgp_oidbuf_is_cv25519 (kp[0].mpi, kp[0].len))?
"(public-key(ecc(curve%s)(flags djb-tweak)(q%b)))":
"(public-key(ecc(curve%s)(q%b)))",
curve, kp[1].len, kp[1].mpi);
xfree (curve);
}
}
break;
default:
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
break;
}
if (!err && !gcry_pk_get_keygrip (s_pkey, grip))
{
log_info ("kbx: error computing keygrip\n");
err = gpg_error (GPG_ERR_GENERAL);
}
gcry_sexp_release (s_pkey);
if (err)
memset (grip, 0, 20);
return err;
}
/* Parse a key packet and store the information in KI. */
static gpg_error_t
parse_key (const unsigned char *data, size_t datalen,
@ -176,16 +263,19 @@ parse_key (const unsigned char *data, size_t datalen,
size_t n;
int npkey;
unsigned char hashbuffer[768];
const unsigned char *mpi_n = NULL;
size_t mpi_n_len = 0, mpi_e_len = 0;
gcry_md_hd_t md;
int is_ecc = 0;
int is_v5;
/* unsigned int pkbytes; for v5: # of octets of the public key params. */
struct keyparm_s keyparm[OPENPGP_MAX_NPKEY];
unsigned char *helpmpibuf[OPENPGP_MAX_NPKEY] = { NULL };
if (datalen < 5)
return gpg_error (GPG_ERR_INV_PACKET);
version = *data++; datalen--;
if (version < 2 || version > 4 )
if (version < 2 || version > 5 )
return gpg_error (GPG_ERR_INV_PACKET); /* Invalid version. */
is_v5 = version == 5;
/*timestamp = ((data[0]<<24)|(data[1]<<16)|(data[2]<<8)|(data[3]));*/
data +=4; datalen -=4;
@ -201,6 +291,15 @@ parse_key (const unsigned char *data, size_t datalen,
return gpg_error (GPG_ERR_INV_PACKET);
algorithm = *data++; datalen--;
if (is_v5)
{
if (datalen < 4)
return gpg_error (GPG_ERR_INV_PACKET);
/* pkbytes = buf32_to_uint (data); */
data += 4;
datalen -= 4;
}
switch (algorithm)
{
case PUBKEY_ALGO_RSA:
@ -228,6 +327,7 @@ parse_key (const unsigned char *data, size_t datalen,
return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
}
ki->version = version;
ki->algo = algorithm;
for (i=0; i < npkey; i++ )
@ -245,6 +345,9 @@ parse_key (const unsigned char *data, size_t datalen,
nbytes++; /* The size byte itself. */
if (datalen < nbytes)
return gpg_error (GPG_ERR_INV_PACKET);
keyparm[i].mpi = data;
keyparm[i].len = nbytes;
}
else
{
@ -254,21 +357,40 @@ parse_key (const unsigned char *data, size_t datalen,
nbytes = (nbits+7) / 8;
if (datalen < nbytes)
return gpg_error (GPG_ERR_INV_PACKET);
/* For use by v3 fingerprint calculation we need to know the RSA
modulus and exponent. */
if (i==0)
{
mpi_n = data;
mpi_n_len = nbytes;
}
else if (i==1)
mpi_e_len = nbytes;
keyparm[i].mpi = data;
keyparm[i].len = nbytes;
}
data += nbytes; datalen -= nbytes;
}
n = data - data_start;
/* Note: Starting here we need to jump to leave on error. */
/* Make sure the MPIs are unsigned. */
for (i=0; i < npkey; i++)
{
if (!keyparm[i].len || (keyparm[i].mpi[0] & 0x80))
{
helpmpibuf[i] = xtrymalloc (1+keyparm[i].len);
if (!helpmpibuf[i])
{
err = gpg_error_from_syserror ();
goto leave;
}
helpmpibuf[i][0] = 0;
memcpy (helpmpibuf[i]+1, keyparm[i].mpi, keyparm[i].len);
keyparm[i].mpi = helpmpibuf[i];
keyparm[i].len++;
}
}
err = keygrip_from_keyparm (algorithm, keyparm, ki->grip);
if (err)
goto leave;
if (version < 4)
{
/* We do not support any other algorithm than RSA in v3
@ -279,20 +401,20 @@ parse_key (const unsigned char *data, size_t datalen,
err = gcry_md_open (&md, GCRY_MD_MD5, 0);
if (err)
return err; /* Oops */
gcry_md_write (md, mpi_n, mpi_n_len);
gcry_md_write (md, mpi_n+mpi_n_len+2, mpi_e_len);
gcry_md_write (md, keyparm[0].mpi, keyparm[0].len);
gcry_md_write (md, keyparm[1].mpi, keyparm[1].len);
memcpy (ki->fpr, gcry_md_read (md, 0), 16);
gcry_md_close (md);
ki->fprlen = 16;
if (mpi_n_len < 8)
if (keyparm[0].len < 8)
{
/* Moduli less than 64 bit are out of the specs scope. Zero
them out because this is what gpg does too. */
memset (ki->keyid, 0, 8);
}
else
memcpy (ki->keyid, mpi_n + mpi_n_len - 8, 8);
memcpy (ki->keyid, keyparm[0].mpi + keyparm[0].len - 8, 8);
}
else
{
@ -302,32 +424,70 @@ parse_key (const unsigned char *data, size_t datalen,
have a scatter-gather enabled hash function. What we do here
is to use a static buffer if this one is large enough and
only use the regular hash functions if this buffer is not
large enough. */
if ( 3 + n < sizeof hashbuffer )
large enough.
FIXME: Factor this out to a shared fingerprint function.
*/
if (version == 5)
{
hashbuffer[0] = 0x99; /* CTB */
hashbuffer[1] = (n >> 8); /* 2 byte length header. */
hashbuffer[2] = n;
memcpy (hashbuffer + 3, data_start, n);
gcry_md_hash_buffer (GCRY_MD_SHA1, ki->fpr, hashbuffer, 3 + n);
if ( 5 + n < sizeof hashbuffer )
{
hashbuffer[0] = 0x9a; /* CTB */
hashbuffer[1] = (n >> 24);/* 4 byte length header. */
hashbuffer[2] = (n >> 16);
hashbuffer[3] = (n >> 8);
hashbuffer[4] = (n );
memcpy (hashbuffer + 5, data_start, n);
gcry_md_hash_buffer (GCRY_MD_SHA256, ki->fpr, hashbuffer, 5 + n);
}
else
{
err = gcry_md_open (&md, GCRY_MD_SHA256, 0);
if (err)
return err; /* Oops */
gcry_md_putc (md, 0x9a ); /* CTB */
gcry_md_putc (md, (n >> 24)); /* 4 byte length header. */
gcry_md_putc (md, (n >> 16));
gcry_md_putc (md, (n >> 8));
gcry_md_putc (md, (n ));
gcry_md_write (md, data_start, n);
memcpy (ki->fpr, gcry_md_read (md, 0), 32);
gcry_md_close (md);
}
ki->fprlen = 32;
memcpy (ki->keyid, ki->fpr, 8);
}
else
{
err = gcry_md_open (&md, GCRY_MD_SHA1, 0);
if (err)
return err; /* Oops */
gcry_md_putc (md, 0x99 ); /* CTB */
gcry_md_putc (md, (n >> 8) ); /* 2 byte length header. */
gcry_md_putc (md, n );
gcry_md_write (md, data_start, n);
memcpy (ki->fpr, gcry_md_read (md, 0), 20);
gcry_md_close (md);
if ( 3 + n < sizeof hashbuffer )
{
hashbuffer[0] = 0x99; /* CTB */
hashbuffer[1] = (n >> 8); /* 2 byte length header. */
hashbuffer[2] = (n );
memcpy (hashbuffer + 3, data_start, n);
gcry_md_hash_buffer (GCRY_MD_SHA1, ki->fpr, hashbuffer, 3 + n);
}
else
{
err = gcry_md_open (&md, GCRY_MD_SHA1, 0);
if (err)
return err; /* Oops */
gcry_md_putc (md, 0x99 ); /* CTB */
gcry_md_putc (md, (n >> 8)); /* 2 byte length header. */
gcry_md_putc (md, (n ));
gcry_md_write (md, data_start, n);
memcpy (ki->fpr, gcry_md_read (md, 0), 20);
gcry_md_close (md);
}
ki->fprlen = 20;
memcpy (ki->keyid, ki->fpr+12, 8);
}
ki->fprlen = 20;
memcpy (ki->keyid, ki->fpr+12, 8);
}
return 0;
leave:
for (i=0; i < npkey; i++)
xfree (helpmpibuf[i]);
return err;
}

View file

@ -36,9 +36,7 @@ typedef enum {
KEYDB_SEARCH_MODE_WORDS,
KEYDB_SEARCH_MODE_SHORT_KID,
KEYDB_SEARCH_MODE_LONG_KID,
KEYDB_SEARCH_MODE_FPR16,
KEYDB_SEARCH_MODE_FPR20,
KEYDB_SEARCH_MODE_FPR,
KEYDB_SEARCH_MODE_FPR, /* (Length of fpr in .fprlen) */
KEYDB_SEARCH_MODE_ISSUER,
KEYDB_SEARCH_MODE_ISSUER_SN,
KEYDB_SEARCH_MODE_SN,
@ -49,7 +47,7 @@ typedef enum {
} KeydbSearchMode;
/* Forwward declaration. See g10/packet.h. */
/* Forward declaration. See g10/packet.h. */
struct gpg_pkt_user_id_s;
typedef struct gpg_pkt_user_id_s *gpg_pkt_user_id_t;
@ -69,10 +67,11 @@ struct keydb_search_desc
int snlen; /* -1 := sn is a hex string */
union {
const char *name;
unsigned char fpr[24];
unsigned char fpr[32];
u32 kid[2]; /* Note that this is in native endianness. */
unsigned char grip[20];
} u;
byte fprlen; /* Only used with KEYDB_SEARCH_MODE_FPR. */
int exact; /* Use exactly this key ('!' suffix in gpg). */
};

View file

@ -66,18 +66,31 @@ blob_get_first_keyid (KEYBOXBLOB blob, u32 *kid)
{
const unsigned char *buffer;
size_t length, nkeys, keyinfolen;
int fpr32;
buffer = _keybox_get_blob_image (blob, &length);
if (length < 48)
return 0; /* blob too short */
fpr32 = buffer[5] == 2;
if (fpr32 && length < 56)
return 0; /* blob to short */
nkeys = get16 (buffer + 16);
keyinfolen = get16 (buffer + 18);
if (!nkeys || keyinfolen < 28)
if (!nkeys || keyinfolen < (fpr32?56:28))
return 0; /* invalid blob */
kid[0] = get32 (buffer + 32);
kid[1] = get32 (buffer + 36);
if (fpr32 && (get16 (buffer + 20 + 32) & 0x80))
{
/* 32 byte fingerprint. */
kid[0] = get32 (buffer + 20);
kid[1] = get32 (buffer + 20 + 4);
}
else /* 20 byte fingerprint. */
{
kid[0] = get32 (buffer + 20 + 12);
kid[1] = get32 (buffer + 20 + 16);
}
return 1;
}
@ -229,22 +242,23 @@ blob_cmp_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
For X.509 this is always 1, for OpenPGP this is 1 for the primary
key and 2 and more for the subkeys. */
static int
blob_cmp_fpr (KEYBOXBLOB blob, const unsigned char *fpr)
blob_cmp_fpr (KEYBOXBLOB blob, const unsigned char *fpr, unsigned int fprlen)
{
const unsigned char *buffer;
size_t length;
size_t pos, off;
size_t nkeys, keyinfolen;
int idx;
int idx, fpr32, storedfprlen;
buffer = _keybox_get_blob_image (blob, &length);
if (length < 40)
return 0; /* blob too short */
fpr32 = buffer[5] == 2;
/*keys*/
nkeys = get16 (buffer + 16);
keyinfolen = get16 (buffer + 18 );
if (keyinfolen < 28)
if (keyinfolen < (fpr32?56:28))
return 0; /* invalid blob */
pos = 20;
if (pos + (uint64_t)keyinfolen*nkeys > (uint64_t)length)
@ -253,12 +267,19 @@ blob_cmp_fpr (KEYBOXBLOB blob, const unsigned char *fpr)
for (idx=0; idx < nkeys; idx++)
{
off = pos + idx*keyinfolen;
if (!memcmp (buffer + off, fpr, 20))
if (fpr32)
storedfprlen = (get16 (buffer + off + 32) & 0x80)? 32:20;
else
storedfprlen = 20;
if (storedfprlen == fprlen
&& !memcmp (buffer + off, fpr, storedfprlen))
return idx+1; /* found */
}
return 0; /* not found */
}
/* Helper for has_short_kid and has_long_kid. */
static int
blob_cmp_fpr_part (KEYBOXBLOB blob, const unsigned char *fpr,
int fproff, int fprlen)
@ -267,25 +288,33 @@ blob_cmp_fpr_part (KEYBOXBLOB blob, const unsigned char *fpr,
size_t length;
size_t pos, off;
size_t nkeys, keyinfolen;
int idx;
int idx, fpr32, storedfprlen;
buffer = _keybox_get_blob_image (blob, &length);
if (length < 40)
return 0; /* blob too short */
fpr32 = buffer[5] == 2;
/*keys*/
nkeys = get16 (buffer + 16);
keyinfolen = get16 (buffer + 18 );
if (keyinfolen < 28)
if (keyinfolen < (fpr32?56:28))
return 0; /* invalid blob */
pos = 20;
if (pos + (uint64_t)keyinfolen*nkeys > (uint64_t)length)
return 0; /* out of bounds */
if (fpr32)
fproff = 0; /* keyid are the high-order bits. */
for (idx=0; idx < nkeys; idx++)
{
off = pos + idx*keyinfolen;
if (!memcmp (buffer + off + fproff, fpr, fprlen))
if (fpr32)
storedfprlen = (get16 (buffer + off + 32) & 0x80)? 32:20;
else
storedfprlen = 20;
if (storedfprlen == fproff + fprlen
&& !memcmp (buffer + off + fproff, fpr, fprlen))
return idx+1; /* found */
}
return 0; /* not found */
@ -497,6 +526,58 @@ blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen, int substr,
}
/* Return true if the key in BLOB matches the 20 bytes keygrip GRIP.
* We don't have the keygrips as meta data, thus we need to parse the
* certificate. Fixme: We might want to return proper error codes
* instead of failing a search for invalid certificates etc. */
static int
blob_openpgp_has_grip (KEYBOXBLOB blob, const unsigned char *grip)
{
int rc = 0;
const unsigned char *buffer;
size_t length;
size_t cert_off, cert_len;
struct _keybox_openpgp_info info;
struct _keybox_openpgp_key_info *k;
buffer = _keybox_get_blob_image (blob, &length);
if (length < 40)
return 0; /* Too short. */
cert_off = get32 (buffer+8);
cert_len = get32 (buffer+12);
if ((uint64_t)cert_off+(uint64_t)cert_len > (uint64_t)length)
return 0; /* Too short. */
if (_keybox_parse_openpgp (buffer + cert_off, cert_len, NULL, &info))
return 0; /* Parse error. */
if (!memcmp (info.primary.grip, grip, 20))
{
rc = 1;
goto leave;
}
if (info.nsubkeys)
{
k = &info.subkeys;
do
{
if (!memcmp (k->grip, grip, 20))
{
rc = 1;
goto leave;
}
k = k->next;
}
while (k);
}
leave:
_keybox_destroy_openpgp_info (&info);
return rc;
}
#ifdef KEYBOX_WITH_X509
/* Return true if the key in BLOB matches the 20 bytes keygrip GRIP.
We don't have the keygrips as meta data, thus we need to parse the
@ -598,20 +679,19 @@ has_long_kid (KEYBOXBLOB blob, u32 mkid, u32 lkid)
}
static inline int
has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr)
has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr, unsigned int fprlen)
{
return blob_cmp_fpr (blob, fpr);
return blob_cmp_fpr (blob, fpr, fprlen);
}
static inline int
has_keygrip (KEYBOXBLOB blob, const unsigned char *grip)
{
if (blob_get_type (blob) == KEYBOX_BLOBTYPE_PGP)
return blob_openpgp_has_grip (blob, grip);
#ifdef KEYBOX_WITH_X509
if (blob_get_type (blob) == KEYBOX_BLOBTYPE_X509)
return blob_x509_has_grip (blob, grip);
#else
(void)blob;
(void)grip;
#endif
return 0;
}
@ -996,12 +1076,13 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc,
if (pk_no)
goto found;
break;
case KEYDB_SEARCH_MODE_FPR:
case KEYDB_SEARCH_MODE_FPR20:
pk_no = has_fingerprint (blob, desc[n].u.fpr);
pk_no = has_fingerprint (blob, desc[n].u.fpr, desc[n].fprlen);
if (pk_no)
goto found;
break;
case KEYDB_SEARCH_MODE_KEYGRIP:
if (has_keygrip (blob, desc[n].u.grip))
goto found;
@ -1069,7 +1150,7 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc,
/* Return the last found keyblock. Returns 0 on success and stores a
* new iobuf at R_IOBUF. R_UID_NO and R_PK_NO are used to retun the
* new iobuf at R_IOBUF. R_UID_NO and R_PK_NO are used to return the
* number of the key or user id which was matched the search criteria;
* if not known they are set to 0. */
gpg_error_t

View file

@ -29,7 +29,7 @@ cat <<EOF
* keybox_strerror:
* @err: Error code
*
* This function returns a textual representaion of the given
* This function returns a textual representation of the given
* errorcode. If this is an unknown value, a string with the value
* is returned (Beware: it is hold in a static buffer).
*