mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Allow to select X.509 certificates using the keygrip.
This commit is contained in:
parent
11935a4c18
commit
58785c880d
3
NEWS
3
NEWS
@ -1,6 +1,9 @@
|
||||
Noteworthy changes in version 1.9.94
|
||||
-------------------------------------------------
|
||||
|
||||
* Keys for gpgsm may now be specified using a keygrip. A keygrip is
|
||||
indicated by a prefixing it with an ampersand.
|
||||
|
||||
|
||||
Noteworthy changes in version 1.9.93 (2006-10-18)
|
||||
-------------------------------------------------
|
||||
|
@ -1,3 +1,7 @@
|
||||
2006-10-20 Werner Koch <wk@g10code.com>
|
||||
|
||||
* convert.c (hex2bin): New.
|
||||
|
||||
2006-10-17 Werner Koch <wk@g10code.com>
|
||||
|
||||
* estream.c (struct estream_internal, es_initialize)
|
||||
|
@ -30,6 +30,35 @@
|
||||
#define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
|
||||
|
||||
|
||||
/* Convert STRING consisting of hex characters into its binary
|
||||
representation and store that at BUFFER. BUFFER needs to be of
|
||||
LENGTH bytes. The function check that the STRING will convert
|
||||
exactly to LENGTH bytes. The string is delimited by either end of
|
||||
string or a white space character. The function returns -1 on
|
||||
error or the length of the parsed string. */
|
||||
int
|
||||
hex2bin (const char *string, void *buffer, size_t length)
|
||||
{
|
||||
int i;
|
||||
const char *s = string;
|
||||
|
||||
for (i=0; i < length; )
|
||||
{
|
||||
if (!hexdigitp (s) || !hexdigitp (s+1))
|
||||
return -1; /* Invalid hex digits. */
|
||||
((unsigned char*)buffer)[i++] = xtoi_2 (s);
|
||||
s += 2;
|
||||
}
|
||||
if (*s && (!isascii (*s) || !isspace (*s)) )
|
||||
return -1; /* Not followed by Nul or white space. */
|
||||
if (i != length)
|
||||
return -1; /* Not of expected length. */
|
||||
if (*s)
|
||||
s++; /* Skip the delimiter. */
|
||||
return s - string;
|
||||
}
|
||||
|
||||
|
||||
/* Convert STRING consisting of hex characters into its binary representation
|
||||
and store that at BUFFER. BUFFER needs to be of LENGTH bytes. The
|
||||
function check that the STRING will convert exactly to LENGTH
|
||||
@ -73,7 +102,6 @@ hexcolon2bin (const char *string, void *buffer, size_t length)
|
||||
}
|
||||
|
||||
|
||||
|
||||
static char *
|
||||
do_bin2hex (const void *buffer, size_t length, char *stringbuf, int with_colon)
|
||||
{
|
||||
|
@ -32,6 +32,93 @@
|
||||
} while(0)
|
||||
|
||||
|
||||
static void
|
||||
test_hex2bin (void)
|
||||
{
|
||||
static const char *valid[] = {
|
||||
"00112233445566778899aabbccddeeff11223344",
|
||||
"00112233445566778899AABBCCDDEEFF11223344",
|
||||
"00112233445566778899AABBCCDDEEFF11223344 blah",
|
||||
"00112233445566778899AABBCCDDEEFF11223344\tblah",
|
||||
"00112233445566778899AABBCCDDEEFF11223344\nblah",
|
||||
NULL
|
||||
};
|
||||
static const char *invalid[] = {
|
||||
"00112233445566778899aabbccddeeff1122334",
|
||||
"00112233445566778899AABBCCDDEEFF1122334",
|
||||
"00112233445566778899AABBCCDDEEFG11223344",
|
||||
"00 112233445566778899aabbccddeeff11223344",
|
||||
"00:112233445566778899aabbccddeeff11223344",
|
||||
":00112233445566778899aabbccddeeff11223344",
|
||||
"0:0112233445566778899aabbccddeeff11223344",
|
||||
"00112233445566778899aabbccddeeff11223344:",
|
||||
"00112233445566778899aabbccddeeff112233445",
|
||||
"00112233445566778899aabbccddeeff1122334455",
|
||||
"00112233445566778899aabbccddeeff11223344blah",
|
||||
NULL
|
||||
};
|
||||
static const char *valid2[] = {
|
||||
"00",
|
||||
"00 x",
|
||||
NULL
|
||||
};
|
||||
static const char *invalid2[] = {
|
||||
"",
|
||||
"0",
|
||||
"00:",
|
||||
"00x",
|
||||
" 00",
|
||||
NULL
|
||||
};
|
||||
unsigned char buffer[20];
|
||||
int len;
|
||||
int i;
|
||||
|
||||
|
||||
for (i=0; valid[i]; i++)
|
||||
{
|
||||
len = hex2bin (valid[i], buffer, sizeof buffer);
|
||||
if (len < 0)
|
||||
fail (i);
|
||||
if (memcmp (buffer, ("\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa"
|
||||
"\xbb\xcc\xdd\xee\xff\x11\x22\x33\x44"), 20))
|
||||
fail (i);
|
||||
}
|
||||
if (hex2bin (valid[0], buffer, sizeof buffer) != 40)
|
||||
fail (0);
|
||||
if (hex2bin (valid[2], buffer, sizeof buffer) != 41)
|
||||
fail (0);
|
||||
|
||||
for (i=0; invalid[i]; i++)
|
||||
{
|
||||
len = hex2bin (invalid[i], buffer, sizeof buffer);
|
||||
if (!(len < 0))
|
||||
fail (i);
|
||||
}
|
||||
|
||||
for (i=0; valid2[i]; i++)
|
||||
{
|
||||
len = hex2bin (valid2[i], buffer, 1);
|
||||
if (len < 0)
|
||||
fail (i);
|
||||
if (memcmp (buffer, "\x00", 1))
|
||||
fail (i);
|
||||
}
|
||||
if (hex2bin (valid2[0], buffer, 1) != 2)
|
||||
fail (0);
|
||||
if (hex2bin (valid2[1], buffer, 1) != 3)
|
||||
fail (0);
|
||||
|
||||
for (i=0; invalid2[i]; i++)
|
||||
{
|
||||
len = hex2bin (invalid2[i], buffer, 1);
|
||||
if (!(len < 0))
|
||||
fail (i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
test_hexcolon2bin (void)
|
||||
{
|
||||
@ -195,6 +282,7 @@ int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
|
||||
test_hex2bin ();
|
||||
test_hexcolon2bin ();
|
||||
test_bin2hex ();
|
||||
test_bin2hexcolon ();
|
||||
|
@ -157,6 +157,7 @@ unsigned char *make_simple_sexp_from_hexstr (const char *line,
|
||||
size_t *nscanned);
|
||||
|
||||
/*-- convert.c --*/
|
||||
int hex2bin (const char *string, void *buffer, size_t length);
|
||||
int hexcolon2bin (const char *string, void *buffer, size_t length);
|
||||
char *bin2hex (const void *buffer, size_t length, char *stringbuf);
|
||||
char *bin2hexcolon (const void *buffer, size_t length, char *stringbuf);
|
||||
|
@ -131,6 +131,17 @@ RFC-2253 encoded DN of the issuer. See note above.
|
||||
@end example
|
||||
@end cartouche
|
||||
|
||||
@item By keygrip
|
||||
This is indicated by an ampersand followed by the 40 hex digits of a
|
||||
keygrip. @command{gpgsm} prints the keygrip when using the command
|
||||
@option{--dump-cert}. It does not yet work for OpenPGP keys.
|
||||
|
||||
@cartouche
|
||||
@example
|
||||
&D75F22C3F86E355877348498CDC92BD21010A480
|
||||
@end example
|
||||
@end cartouche
|
||||
|
||||
|
||||
@item By substring match.
|
||||
This is the default mode but applications may want to explicitly
|
||||
|
@ -1,3 +1,7 @@
|
||||
2006-10-20 Werner Koch <wk@g10code.com>
|
||||
|
||||
* getkey.c (classify_user_id): Reserve '&' for search by keygrip.
|
||||
|
||||
2006-10-19 Werner Koch <wk@g10code.com>
|
||||
|
||||
* keygen.c (get_parameter_algo): Add special case for ELG_E which
|
||||
|
@ -578,6 +578,7 @@ seckey_available( u32 *keyid )
|
||||
* Words are delimited by white space or "()<>[]{}.@-+_,;/&!"
|
||||
* (note that you can't search for these characters). Compare
|
||||
* is not case sensitive.
|
||||
* - If the userid starts with a '&' a 40 hex digits keygrip is expected.
|
||||
*/
|
||||
|
||||
int
|
||||
@ -644,7 +645,7 @@ classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc )
|
||||
#endif
|
||||
|
||||
case '#': /* local user id */
|
||||
return 0; /* This is now obsolete and van't not be used anymore*/
|
||||
return 0; /* This is now obsolete and can't not be used anymore*/
|
||||
|
||||
case ':': /*Unified fingerprint */
|
||||
{
|
||||
@ -669,6 +670,9 @@ classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc )
|
||||
}
|
||||
break;
|
||||
|
||||
case '&': /* keygrip */
|
||||
return 0; /* Not yet implememted. */
|
||||
|
||||
default:
|
||||
if (s[0] == '0' && s[1] == 'x') {
|
||||
hexprefix = 1;
|
||||
|
@ -1,3 +1,10 @@
|
||||
2006-10-20 Werner Koch <wk@g10code.com>
|
||||
|
||||
* keybox-search.c (blob_x509_has_grip, has_keygrip): New.
|
||||
(keybox_search): Implement new search mode.
|
||||
* keybox-search-desc.h (KEYDB_SEARCH_MODE_KEYGRIP): New.
|
||||
(keydb_search_desc): New member GRIP.
|
||||
|
||||
2006-09-20 Werner Koch <wk@g10code.com>
|
||||
|
||||
* Makefile.am ($(PROGRAMS): New.
|
||||
|
@ -45,6 +45,7 @@ typedef enum {
|
||||
KEYDB_SEARCH_MODE_ISSUER_SN,
|
||||
KEYDB_SEARCH_MODE_SN,
|
||||
KEYDB_SEARCH_MODE_SUBJECT,
|
||||
KEYDB_SEARCH_MODE_KEYGRIP,
|
||||
KEYDB_SEARCH_MODE_FIRST,
|
||||
KEYDB_SEARCH_MODE_NEXT
|
||||
} KeydbSearchMode;
|
||||
@ -59,6 +60,7 @@ struct keydb_search_desc {
|
||||
const char *name;
|
||||
unsigned char fpr[24];
|
||||
unsigned char kid[8];
|
||||
unsigned char grip[20];
|
||||
} u;
|
||||
};
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "../jnlib/stringhelp.h" /* ascii_xxxx() */
|
||||
|
||||
#include "keybox-defs.h"
|
||||
#include <gcrypt.h>
|
||||
|
||||
|
||||
#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
|
||||
@ -456,6 +457,75 @@ blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen, int substr)
|
||||
}
|
||||
|
||||
|
||||
#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 wen need to parse the
|
||||
certificate. Fixme: We might wat to return proper error codes
|
||||
instead of failing a search for invalid certificates etc. */
|
||||
static int
|
||||
blob_x509_has_grip (KEYBOXBLOB blob, const unsigned char *grip)
|
||||
{
|
||||
int rc;
|
||||
const unsigned char *buffer;
|
||||
size_t length;
|
||||
size_t cert_off, cert_len;
|
||||
ksba_reader_t reader = NULL;
|
||||
ksba_cert_t cert = NULL;
|
||||
ksba_sexp_t p = NULL;
|
||||
gcry_sexp_t s_pkey;
|
||||
unsigned char array[20];
|
||||
unsigned char *rcp;
|
||||
size_t n;
|
||||
|
||||
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 (cert_off+cert_len > length)
|
||||
return 0; /* Too short. */
|
||||
|
||||
rc = ksba_reader_new (&reader);
|
||||
if (rc)
|
||||
return 0; /* Problem with ksba. */
|
||||
rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
|
||||
if (rc)
|
||||
goto failed;
|
||||
rc = ksba_cert_new (&cert);
|
||||
if (rc)
|
||||
goto failed;
|
||||
rc = ksba_cert_read_der (cert, reader);
|
||||
if (rc)
|
||||
goto failed;
|
||||
p = ksba_cert_get_public_key (cert);
|
||||
if (!p)
|
||||
goto failed;
|
||||
n = gcry_sexp_canon_len (p, 0, NULL, NULL);
|
||||
if (!n)
|
||||
goto failed;
|
||||
rc = gcry_sexp_sscan (&s_pkey, NULL, (char*)p, n);
|
||||
if (rc)
|
||||
{
|
||||
gcry_sexp_release (s_pkey);
|
||||
goto failed;
|
||||
}
|
||||
rcp = gcry_pk_get_keygrip (s_pkey, array);
|
||||
gcry_sexp_release (s_pkey);
|
||||
if (!rcp)
|
||||
goto failed; /* Can't calculate keygrip. */
|
||||
|
||||
xfree (p);
|
||||
ksba_cert_release (cert);
|
||||
ksba_reader_release (reader);
|
||||
return !memcmp (array, grip, 20);
|
||||
failed:
|
||||
xfree (p);
|
||||
ksba_cert_release (cert);
|
||||
ksba_reader_release (reader);
|
||||
return 0;
|
||||
}
|
||||
#endif /*KEYBOX_WITH_X509*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
@ -479,6 +549,16 @@ has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr)
|
||||
return blob_cmp_fpr (blob, fpr);
|
||||
}
|
||||
|
||||
static inline int
|
||||
has_keygrip (KEYBOXBLOB blob, const unsigned char *grip)
|
||||
{
|
||||
#ifdef KEYBOX_WITH_X509
|
||||
if (blob_get_type (blob) == BLOBTYPE_X509)
|
||||
return blob_x509_has_grip (blob, grip);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static inline int
|
||||
has_issuer (KEYBOXBLOB blob, const char *name)
|
||||
@ -809,6 +889,10 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc)
|
||||
if (has_fingerprint (blob, desc[n].u.fpr))
|
||||
goto found;
|
||||
break;
|
||||
case KEYDB_SEARCH_MODE_KEYGRIP:
|
||||
if (has_keygrip (blob, desc[n].u.grip))
|
||||
goto found;
|
||||
break;
|
||||
case KEYDB_SEARCH_MODE_FIRST:
|
||||
goto found;
|
||||
break;
|
||||
|
@ -1,3 +1,7 @@
|
||||
2006-10-20 Werner Koch <wk@g10code.com>
|
||||
|
||||
* keydb.c (classify_user_id): Parse keygrip for the '&' identifier.
|
||||
|
||||
2006-10-18 Werner Koch <wk@g10code.com>
|
||||
|
||||
* keylist.c (list_cert_raw): Also test for GPG_ERR_NO_VALUE when
|
||||
|
10
sm/keydb.c
10
sm/keydb.c
@ -1140,7 +1140,15 @@ classify_user_id (const char *name,
|
||||
mode = KEYDB_SEARCH_MODE_FPR;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case '&': /* Keygrip*/
|
||||
{
|
||||
if (hex2bin (s+1, desc->u.grip, 20) < 0)
|
||||
return 0; /* Invalid. */
|
||||
mode = KEYDB_SEARCH_MODE_KEYGRIP;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (s[0] == '0' && s[1] == 'x')
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user