Merge branch 'master' into key-storage-work

--
This commit is contained in:
Werner Koch 2013-03-20 10:00:12 +01:00
commit eaa6dc3a8b
26 changed files with 484 additions and 261 deletions

4
.gitignore vendored
View File

@ -154,7 +154,5 @@ tools/mk-tdata
tools/symcryptrun tools/symcryptrun
tools/watchgnupg tools/watchgnupg
tools/gpgtar tools/gpgtar
private-keys-v1.d/
x.parm x.parm
private-keys-v1.d/

View File

@ -405,7 +405,8 @@ void agent_reload_trustlist (void);
/*-- divert-scd.c --*/ /*-- divert-scd.c --*/
int divert_pksign (ctrl_t ctrl, int divert_pksign (ctrl_t ctrl,
const unsigned char *digest, size_t digestlen, int algo, const unsigned char *digest, size_t digestlen, int algo,
const unsigned char *shadow_info, unsigned char **r_sig); const unsigned char *shadow_info, unsigned char **r_sig,
size_t *r_siglen);
int divert_pkdecrypt (ctrl_t ctrl, int divert_pkdecrypt (ctrl_t ctrl,
const unsigned char *cipher, const unsigned char *cipher,
const unsigned char *shadow_info, const unsigned char *shadow_info,

View File

@ -596,18 +596,15 @@ static gpg_error_t
inq_quality (void *opaque, const char *line) inq_quality (void *opaque, const char *line)
{ {
assuan_context_t ctx = opaque; assuan_context_t ctx = opaque;
const char *s;
char *pin; char *pin;
int rc; int rc;
int percent; int percent;
char numbuf[20]; char numbuf[20];
if (!strncmp (line, "QUALITY", 7) && (line[7] == ' ' || !line[7])) if ((s = has_leading_keyword (line, "QUALITY")))
{ {
line += 7; pin = unescape_passphrase_string (s);
while (*line == ' ')
line++;
pin = unescape_passphrase_string (line);
if (!pin) if (!pin)
rc = gpg_error_from_syserror (); rc = gpg_error_from_syserror ();
else else

View File

@ -701,17 +701,15 @@ static gpg_error_t
inq_needpin (void *opaque, const char *line) inq_needpin (void *opaque, const char *line)
{ {
struct inq_needpin_s *parm = opaque; struct inq_needpin_s *parm = opaque;
const char *s;
char *pin; char *pin;
size_t pinlen; size_t pinlen;
int rc; int rc;
parm->any_inq_seen = 1; parm->any_inq_seen = 1;
if (!strncmp (line, "NEEDPIN", 7) && (line[7] == ' ' || !line[7])) if ((s = has_leading_keyword (line, "NEEDPIN")))
{ {
line += 7; line = s;
while (*line == ' ')
line++;
pinlen = 90; pinlen = 90;
pin = gcry_malloc_secure (pinlen); pin = gcry_malloc_secure (pinlen);
if (!pin) if (!pin)
@ -722,17 +720,11 @@ inq_needpin (void *opaque, const char *line)
rc = assuan_send_data (parm->ctx, pin, pinlen); rc = assuan_send_data (parm->ctx, pin, pinlen);
xfree (pin); xfree (pin);
} }
else if (!strncmp (line, "POPUPPINPADPROMPT", 17) else if ((s = has_leading_keyword (line, "POPUPPINPADPROMPT")))
&& (line[17] == ' ' || !line[17]))
{ {
line += 17; rc = parm->getpin_cb (parm->getpin_cb_arg, s, NULL, 1);
while (*line == ' ')
line++;
rc = parm->getpin_cb (parm->getpin_cb_arg, line, NULL, 1);
} }
else if (!strncmp (line, "DISMISSPINPADPROMPT", 19) else if ((s = has_leading_keyword (line, "DISMISSPINPADPROMPT")))
&& (line[19] == ' ' || !line[19]))
{ {
rc = parm->getpin_cb (parm->getpin_cb_arg, "", NULL, 0); rc = parm->getpin_cb (parm->getpin_cb_arg, "", NULL, 0);
} }
@ -833,10 +825,6 @@ agent_card_pksign (ctrl_t ctrl,
char *p, line[ASSUAN_LINELENGTH]; char *p, line[ASSUAN_LINELENGTH];
membuf_t data; membuf_t data;
struct inq_needpin_s inqparm; struct inq_needpin_s inqparm;
size_t len;
unsigned char *sigbuf;
size_t sigbuflen;
int prepend_nul;
*r_buf = NULL; *r_buf = NULL;
rc = start_scd (ctrl); rc = start_scd (ctrl);
@ -876,32 +864,13 @@ agent_card_pksign (ctrl_t ctrl,
if (rc) if (rc)
{ {
size_t len;
xfree (get_membuf (&data, &len)); xfree (get_membuf (&data, &len));
return unlock_scd (ctrl, rc); return unlock_scd (ctrl, rc);
} }
sigbuf = get_membuf (&data, &sigbuflen);
/* Create an S-expression from it which is formatted like this: *r_buf = get_membuf (&data, r_buflen);
"(7:sig-val(3:rsa(1:sSIGBUFLEN:SIGBUF)))". We better make sure
that this won't be interpreted as a negative number. */
prepend_nul = (sigbuflen && (*sigbuf & 0x80));
*r_buflen = 21 + 11 + prepend_nul + sigbuflen + 4;
p = xtrymalloc (*r_buflen);
*r_buf = (unsigned char*)p;
if (!p)
return unlock_scd (ctrl, out_of_core ());
p = stpcpy (p, "(7:sig-val(3:rsa(1:s" );
sprintf (p, "%u:", (unsigned int)sigbuflen + prepend_nul);
p += strlen (p);
if (prepend_nul)
*p++ = 0;
memcpy (p, sigbuf, sigbuflen);
p += sigbuflen;
strcpy (p, ")))");
xfree (sigbuf);
assert (gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL));
return unlock_scd (ctrl, 0); return unlock_scd (ctrl, 0);
} }
@ -1069,7 +1038,7 @@ inq_writekey_parms (void *opaque, const char *line)
{ {
struct writekey_parm_s *parm = opaque; struct writekey_parm_s *parm = opaque;
if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7])) if (has_leading_keyword (line, "KEYDATA"))
return assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen); return assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
else else
return inq_needpin (opaque, line); return inq_needpin (opaque, line);

View File

@ -1247,6 +1247,8 @@ ssh_signature_encoder_ecdsa (ssh_key_type_spec_t *spec,
gpg_error_t err; gpg_error_t err;
int i; int i;
(void)spec;
innerlen = 0; innerlen = 0;
for (i = 0; i < DIM(data); i++) for (i = 0; i < DIM(data); i++)
{ {

View File

@ -2197,6 +2197,7 @@ cmd_keytocard (assuan_context_t ctx, char *line)
gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, keydata, keydatalen); gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, keydata, keydatalen);
gcry_sexp_release (s_skey); gcry_sexp_release (s_skey);
keydatalen--; /* Decrement for last '\0'. */
/* Add timestamp "created-at" in the private key */ /* Add timestamp "created-at" in the private key */
timestamp = isotime2epoch (timestamp_str); timestamp = isotime2epoch (timestamp_str);
snprintf (keydata+keydatalen-1, 30, "(10:created-at10:%010lu))", timestamp); snprintf (keydata+keydatalen-1, 30, "(10:created-at10:%010lu))", timestamp);

View File

@ -335,7 +335,8 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
int int
divert_pksign (ctrl_t ctrl, divert_pksign (ctrl_t ctrl,
const unsigned char *digest, size_t digestlen, int algo, const unsigned char *digest, size_t digestlen, int algo,
const unsigned char *shadow_info, unsigned char **r_sig) const unsigned char *shadow_info, unsigned char **r_sig,
size_t *r_siglen)
{ {
int rc; int rc;
char *kid; char *kid;
@ -369,7 +370,10 @@ divert_pksign (ctrl_t ctrl,
} }
if (!rc) if (!rc)
*r_sig = sigval; {
*r_sig = sigval;
*r_siglen = siglen;
}
xfree (kid); xfree (kid);

View File

@ -828,7 +828,7 @@ agent_public_key_from_file (ctrl_t ctrl,
int i, idx; int i, idx;
gcry_sexp_t s_skey; gcry_sexp_t s_skey;
char algoname[6]; char algoname[6];
char elems[6]; char elems[7];
gcry_sexp_t uri_sexp, comment_sexp; gcry_sexp_t uri_sexp, comment_sexp;
const char *uri, *comment; const char *uri, *comment;
size_t uri_length, comment_length; size_t uri_length, comment_length;

View File

@ -278,24 +278,104 @@ agent_pksign_do (ctrl_t ctrl, const char *cache_nonce,
if (!s_skey) if (!s_skey)
{ {
/* Divert operation to the smartcard */ /* Divert operation to the smartcard */
gcry_sexp_t s_pkey, l;
const char *name;
size_t len;
unsigned char *buf = NULL; unsigned char *buf = NULL;
size_t len = 0; int is_RSA = 0;
int is_ECDSA = 0;
/* Check keytype by public key */
rc = agent_public_key_from_file (ctrl, ctrl->keygrip, &s_pkey);
if (rc)
{
log_error ("failed to read the public key\n");
goto leave;
}
l = gcry_sexp_cadr (s_pkey);
name = gcry_sexp_nth_data (l, 0, &len);
if (len == 3 && !memcmp (name, "rsa", 3))
is_RSA = 1;
else if (len == 5 && !memcmp (name, "ecdsa", 5))
is_ECDSA = 1;
gcry_sexp_release (l);
gcry_sexp_release (s_pkey);
rc = divert_pksign (ctrl, rc = divert_pksign (ctrl,
ctrl->digest.value, ctrl->digest.value,
ctrl->digest.valuelen, ctrl->digest.valuelen,
ctrl->digest.algo, ctrl->digest.algo,
shadow_info, &buf); shadow_info, &buf, &len);
if (rc) if (rc)
{ {
log_error ("smartcard signing failed: %s\n", gpg_strerror (rc)); log_error ("smartcard signing failed: %s\n", gpg_strerror (rc));
goto leave; goto leave;
} }
len = gcry_sexp_canon_len (buf, 0, NULL, NULL);
assert (len);
rc = gcry_sexp_sscan (&s_sig, NULL, (char*)buf, len); if (is_RSA)
{
if (*buf & 0x80)
{
len++;
buf = xtryrealloc (buf, len);
if (!buf)
goto leave;
memmove (buf + 1, buf, len - 1);
*buf = 0;
}
rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s%b)))", len, buf);
}
else if (is_ECDSA)
{
unsigned char *r_buf_allocated = NULL;
unsigned char *s_buf_allocated = NULL;
unsigned char *r_buf, *s_buf;
int r_buflen, s_buflen;
r_buflen = s_buflen = len/2;
if (*buf & 0x80)
{
r_buflen++;
r_buf_allocated = xtrymalloc (r_buflen);
if (!r_buf_allocated)
goto leave;
r_buf = r_buf_allocated;
memcpy (r_buf + 1, buf, len/2);
*r_buf = 0;
}
else
r_buf = buf;
if (*(buf + len/2) & 0x80)
{
s_buflen++;
s_buf_allocated = xtrymalloc (s_buflen);
if (!s_buf_allocated)
{
xfree (r_buf_allocated);
goto leave;
}
s_buf = s_buf_allocated;
memcpy (s_buf + 1, buf + len/2, len/2);
*s_buf = 0;
}
else
s_buf = buf + len/2;
rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(ecdsa(r%b)(s%b)))",
r_buflen, r_buf,
s_buflen, s_buf);
xfree (r_buf_allocated);
xfree (s_buf_allocated);
}
else
rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
xfree (buf); xfree (buf);
if (rc) if (rc)
{ {

View File

@ -34,16 +34,6 @@
#include <gcrypt.h> /* We need this for the memory function protos. */ #include <gcrypt.h> /* We need this for the memory function protos. */
#include <errno.h> /* We need errno. */ #include <errno.h> /* We need errno. */
#include <gpg-error.h> /* We need gpg_error_t. */ #include <gpg-error.h> /* We need gpg_error_t. */
/* Add error codes available only in newer versions of libgpg-error. */
#ifndef GPG_ERR_NO_KEYSERVER
#define GPG_ERR_NO_KEYSERVER 186
#endif
#ifndef GPG_ERR_INV_CURVE
#define GPG_ERR_INV_CURVE 187
#endif
#ifndef GPG_ERR_UNKNOWN_CURVE
#define GPG_ERR_UNKNOWN_CURVE 188
#endif
/* Hash function used with libksba. */ /* Hash function used with libksba. */

View File

@ -43,7 +43,7 @@ m4_define([mym4_full_version],[mym4_version[]mym4_betastring])
AC_INIT([gnupg],[mym4_full_version], [http://bugs.gnupg.org]) AC_INIT([gnupg],[mym4_full_version], [http://bugs.gnupg.org])
NEED_GPG_ERROR_VERSION=1.10 NEED_GPG_ERROR_VERSION=1.11
NEED_LIBGCRYPT_API=1 NEED_LIBGCRYPT_API=1
NEED_LIBGCRYPT_VERSION=1.5.0 NEED_LIBGCRYPT_VERSION=1.5.0

View File

@ -161,6 +161,7 @@ described here.
- s :: Sign - s :: Sign
- c :: Certify - c :: Certify
- a :: Authentication - a :: Authentication
- ? :: Unknown capability
A key may have any combination of them in any order. In addition A key may have any combination of them in any order. In addition
to these letters, the primary key has uppercase versions of the to these letters, the primary key has uppercase versions of the

View File

@ -2418,7 +2418,7 @@ check. @code{value} may be any printable string; it will be encoded in
UTF8, so you should check that your @option{--display-charset} is set UTF8, so you should check that your @option{--display-charset} is set
correctly. If you prefix @code{name} with an exclamation mark (!), the correctly. If you prefix @code{name} with an exclamation mark (!), the
notation data will be flagged as critical notation data will be flagged as critical
(rfc2440:5.2.3.15). @option{--sig-notation} sets a notation for data (rfc4880:5.2.3.16). @option{--sig-notation} sets a notation for data
signatures. @option{--cert-notation} sets a notation for key signatures signatures. @option{--cert-notation} sets a notation for key signatures
(certifications). @option{--set-notation} sets both. (certifications). @option{--set-notation} sets both.
@ -2440,7 +2440,7 @@ meaningful when using the OpenPGP smartcard.
@opindex sig-policy-url @opindex sig-policy-url
@opindex cert-policy-url @opindex cert-policy-url
@opindex set-policy-url @opindex set-policy-url
Use @code{string} as a Policy URL for signatures (rfc2440:5.2.3.19). If Use @code{string} as a Policy URL for signatures (rfc4880:5.2.3.20). If
you prefix it with an exclamation mark (!), the policy URL packet will you prefix it with an exclamation mark (!), the policy URL packet will
be flagged as critical. @option{--sig-policy-url} sets a policy url for be flagged as critical. @option{--sig-policy-url} sets a policy url for
data signatures. @option{--cert-policy-url} sets a policy url for key data signatures. @option{--cert-policy-url} sets a policy url for key

View File

@ -607,6 +607,10 @@ agent_keytocard (const char *hexgrip, int keyno, int force,
{ {
int rc; int rc;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
struct default_inq_parm_s parm;
memset (&parm, 0, sizeof parm);
parm.ctx = agent_ctx;
snprintf (line, DIM(line)-1, "KEYTOCARD %s%s %s OPENPGP.%d %s", snprintf (line, DIM(line)-1, "KEYTOCARD %s%s %s OPENPGP.%d %s",
force?"--force ": "", hexgrip, serialno, keyno, timestamp); force?"--force ": "", hexgrip, serialno, keyno, timestamp);
@ -616,8 +620,8 @@ agent_keytocard (const char *hexgrip, int keyno, int force,
if (rc) if (rc)
return rc; return rc;
rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, &parm,
NULL, NULL, NULL); NULL, NULL);
if (rc) if (rc)
return rc; return rc;
@ -721,7 +725,7 @@ inq_writecert_parms (void *opaque, const char *line)
int rc; int rc;
struct writecert_parm_s *parm = opaque; struct writecert_parm_s *parm = opaque;
if (!strncmp (line, "CERTDATA", 8) && (line[8]==' '||!line[8])) if (has_leading_keyword (line, "CERTDATA"))
{ {
rc = assuan_send_data (parm->dflt->ctx, rc = assuan_send_data (parm->dflt->ctx,
parm->certdata, parm->certdatalen); parm->certdata, parm->certdatalen);
@ -774,7 +778,7 @@ inq_writekey_parms (void *opaque, const char *line)
int rc; int rc;
struct writekey_parm_s *parm = opaque; struct writekey_parm_s *parm = opaque;
if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7])) if (has_leading_keyword (line, "KEYDATA"))
{ {
rc = assuan_send_data (parm->dflt->ctx, parm->keydata, parm->keydatalen); rc = assuan_send_data (parm->dflt->ctx, parm->keydata, parm->keydatalen);
} }
@ -1467,9 +1471,9 @@ keyinfo_status_cb (void *opaque, const char *line)
char **serialno = opaque; char **serialno = opaque;
const char *s, *s2; const char *s, *s2;
if (!strncmp (line, "KEYINFO ", 8) && !*serialno) if ((s = has_leading_keyword (line, "KEYINFO ")) && !*serialno)
{ {
s = strchr (line+8, ' '); s = strchr (s, ' ');
if (s && s[1] == 'T' && s[2] == ' ' && s[3]) if (s && s[1] == 'T' && s[2] == ' ' && s[3])
{ {
s += 3; s += 3;
@ -1571,7 +1575,7 @@ inq_genkey_parms (void *opaque, const char *line)
struct genkey_parm_s *parm = opaque; struct genkey_parm_s *parm = opaque;
gpg_error_t err; gpg_error_t err;
if (!strncmp (line, "KEYPARAM", 8) && (line[8]==' '||!line[8])) if (has_leading_keyword (line, "KEYPARAM"))
{ {
err = assuan_send_data (parm->dflt->ctx, err = assuan_send_data (parm->dflt->ctx,
parm->keyparms, strlen (parm->keyparms)); parm->keyparms, strlen (parm->keyparms));
@ -1798,7 +1802,7 @@ inq_ciphertext_cb (void *opaque, const char *line)
struct cipher_parm_s *parm = opaque; struct cipher_parm_s *parm = opaque;
int rc; int rc;
if (!strncmp (line, "CIPHERTEXT", 10) && (line[10]==' '||!line[10])) if (has_leading_keyword (line, "CIPHERTEXT"))
{ {
assuan_begin_confidential (parm->ctx); assuan_begin_confidential (parm->ctx);
rc = assuan_send_data (parm->dflt->ctx, rc = assuan_send_data (parm->dflt->ctx,
@ -1980,7 +1984,7 @@ inq_import_key_parms (void *opaque, const char *line)
struct import_key_parm_s *parm = opaque; struct import_key_parm_s *parm = opaque;
gpg_error_t err; gpg_error_t err;
if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7])) if (has_leading_keyword (line, "KEYDATA"))
{ {
err = assuan_send_data (parm->dflt->ctx, parm->key, parm->keylen); err = assuan_send_data (parm->dflt->ctx, parm->key, parm->keylen);
} }

View File

@ -515,12 +515,12 @@ ks_put_inq_cb (void *opaque, const char *line)
struct ks_put_parm_s *parm = opaque; struct ks_put_parm_s *parm = opaque;
gpg_error_t err = 0; gpg_error_t err = 0;
if (!strncmp (line, "KEYBLOCK", 8) && (line[8] == ' ' || !line[8])) if (has_leading_keyword (line, "KEYBLOCK"))
{ {
if (parm->data) if (parm->data)
err = assuan_send_data (parm->ctx, parm->data, parm->datalen); err = assuan_send_data (parm->ctx, parm->data, parm->datalen);
} }
else if (!strncmp (line, "KEYBLOCK_INFO", 13) && (line[13]==' ' || !line[13])) else if (has_leading_keyword (line, "KEYBLOCK_INFO"))
{ {
kbnode_t node; kbnode_t node;
estream_t fp; estream_t fp;

View File

@ -550,7 +550,9 @@ card_status (estream_t fp, char *serialno, size_t serialnobuflen)
tty_fprintf (fp, " %u%c", tty_fprintf (fp, " %u%c",
info.key_attr[i].nbits, info.key_attr[i].nbits,
info.key_attr[i].algo == 1? 'R': info.key_attr[i].algo == 1? 'R':
info.key_attr[i].algo == 17? 'D': '?'); info.key_attr[i].algo == 17? 'D':
info.key_attr[i].algo == 18? 'e':
info.key_attr[i].algo == 19? 'E': '?');
tty_fprintf (fp, "\n"); tty_fprintf (fp, "\n");
} }
tty_fprintf (fp, "Max. PIN lengths .: %d %d %d\n", tty_fprintf (fp, "Max. PIN lengths .: %d %d %d\n",
@ -1560,7 +1562,7 @@ card_store_subkey (KBNODE node, int use)
nbits = nbits_from_pk (pk); nbits = nbits_from_pk (pk);
if (!is_RSA (pk->pubkey_algo) || (!info.is_v2 && nbits != 1024) ) if (!info.is_v2 && nbits != 1024)
{ {
tty_printf ("You may only store a 1024 bit RSA key on the card\n"); tty_printf ("You may only store a 1024 bit RSA key on the card\n");
tty_printf ("\n"); tty_printf ("\n");

View File

@ -1291,13 +1291,19 @@ parse_key_usage (PKT_signature * sig)
if (flags) if (flags)
key_usage |= PUBKEY_USAGE_UNKNOWN; key_usage |= PUBKEY_USAGE_UNKNOWN;
if (!key_usage)
key_usage |= PUBKEY_USAGE_NONE;
} }
else if (p) /* Key flags of length zero. */
key_usage |= PUBKEY_USAGE_NONE;
/* We set PUBKEY_USAGE_UNKNOWN to indicate that this key has a /* We set PUBKEY_USAGE_UNKNOWN to indicate that this key has a
capability that we do not handle. This serves to distinguish capability that we do not handle. This serves to distinguish
between a zero key usage which we handle as the default between a zero key usage which we handle as the default
capabilities for that algorithm, and a usage that we do not capabilities for that algorithm, and a usage that we do not
handle. */ handle. Likewise we use PUBKEY_USAGE_NONE to indicate that
key_flags have been given but they do not specify any usage. */
return key_usage; return key_usage;
} }

View File

@ -216,9 +216,6 @@ do_add_key_flags (PKT_signature *sig, unsigned int use)
if (use & PUBKEY_USAGE_AUTH) if (use & PUBKEY_USAGE_AUTH)
buf[0] |= 0x20; buf[0] |= 0x20;
if (!buf[0])
return;
build_sig_subpkt (sig, SIGSUBPKT_KEY_FLAGS, buf, 1); build_sig_subpkt (sig, SIGSUBPKT_KEY_FLAGS, buf, 1);
} }

View File

@ -627,6 +627,9 @@ print_capabilities (PKT_public_key *pk, KBNODE keyblock)
if ((use & PUBKEY_USAGE_AUTH)) if ((use & PUBKEY_USAGE_AUTH))
es_putc ('a', es_stdout); es_putc ('a', es_stdout);
if ((use & PUBKEY_USAGE_UNKNOWN))
es_putc ('?', es_stdout);
if (keyblock) if (keyblock)
{ {
/* Figure out the usable capabilities. */ /* Figure out the usable capabilities. */

View File

@ -323,7 +323,7 @@ main ( int argc, char **argv)
int orig_argc; int orig_argc;
char **orig_argv; char **orig_argv;
gpg_error_t err = 0; gpg_error_t err = 0;
const char *fname; /* const char *fname; */
int may_coredump; int may_coredump;
FILE *configfp = NULL; FILE *configfp = NULL;
char *configname = NULL; char *configname = NULL;
@ -334,10 +334,10 @@ main ( int argc, char **argv)
char *logfile = NULL; char *logfile = NULL;
int greeting = 0; int greeting = 0;
int nogreeting = 0; int nogreeting = 0;
int debug_wait = 0; /* int debug_wait = 0; */
int use_random_seed = 1; int use_random_seed = 1;
int nodetach = 0; /* int nodetach = 0; */
int nokeysetup = 0; /* int nokeysetup = 0; */
enum cmd_and_opt_values cmd = 0; enum cmd_and_opt_values cmd = 0;
struct server_control_s ctrl; struct server_control_s ctrl;
strlist_t recipients = NULL; strlist_t recipients = NULL;
@ -473,13 +473,13 @@ main ( int argc, char **argv)
case aGPGConfTest: case aGPGConfTest:
set_cmd (&cmd, pargs.r_opt); set_cmd (&cmd, pargs.r_opt);
nogreeting = 1; nogreeting = 1;
nokeysetup = 1; /* nokeysetup = 1; */
break; break;
case aServer: case aServer:
case aMount: case aMount:
case aUmount: case aUmount:
nokeysetup = 1; /* nokeysetup = 1; */
case aCreate: case aCreate:
set_cmd (&cmd, pargs.r_opt); set_cmd (&cmd, pargs.r_opt);
break; break;
@ -504,13 +504,13 @@ main ( int argc, char **argv)
case oLogFile: logfile = pargs.r.ret_str; break; case oLogFile: logfile = pargs.r.ret_str; break;
case oNoLogFile: logfile = NULL; break; case oNoLogFile: logfile = NULL; break;
case oNoDetach: nodetach = 1; break; case oNoDetach: /*nodetach = 1; */break;
case oDebug: debug_value |= pargs.r.ret_ulong; break; case oDebug: debug_value |= pargs.r.ret_ulong; break;
case oDebugAll: debug_value = ~0; break; case oDebugAll: debug_value = ~0; break;
case oDebugNone: debug_value = 0; break; case oDebugNone: debug_value = 0; break;
case oDebugLevel: debug_level = pargs.r.ret_str; break; case oDebugLevel: debug_level = pargs.r.ret_str; break;
case oDebugWait: debug_wait = pargs.r.ret_int; break; case oDebugWait: /*debug_wait = pargs.r.ret_int; */break;
case oDebugAllowCoreDump: case oDebugAllowCoreDump:
may_coredump = enable_core_dumps (); may_coredump = enable_core_dumps ();
break; break;
@ -653,7 +653,7 @@ main ( int argc, char **argv)
} }
/* Store given filename into FNAME. */ /* Store given filename into FNAME. */
fname = argc? *argv : NULL; /* fname = argc? *argv : NULL; */
/* Parse all given encryption keys. This does a lookup of the keys /* Parse all given encryption keys. This does a lookup of the keys
and stops if any of the given keys was not found. */ and stops if any of the given keys was not found. */

View File

@ -54,9 +54,14 @@
#define PUBKEY_USAGE_SIG GCRY_PK_USAGE_SIGN /* Good for signatures. */ #define PUBKEY_USAGE_SIG GCRY_PK_USAGE_SIGN /* Good for signatures. */
#define PUBKEY_USAGE_ENC GCRY_PK_USAGE_ENCR /* Good for encryption. */ #define PUBKEY_USAGE_ENC GCRY_PK_USAGE_ENCR /* Good for encryption. */
#define PUBKEY_USAGE_CERT GCRY_PK_USAGE_CERT /* Also good to certify keys. */ #define PUBKEY_USAGE_CERT GCRY_PK_USAGE_CERT /* Also good to certify keys.*/
#define PUBKEY_USAGE_AUTH GCRY_PK_USAGE_AUTH /* Good for authentication. */ #define PUBKEY_USAGE_AUTH GCRY_PK_USAGE_AUTH /* Good for authentication. */
#define PUBKEY_USAGE_UNKNOWN GCRY_PK_USAGE_UNKN /* Unknown usage flag. */ #define PUBKEY_USAGE_UNKNOWN GCRY_PK_USAGE_UNKN /* Unknown usage flag. */
#define PUBKEY_USAGE_NONE 256 /* No usage given. */
#if (GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR | GCRY_PK_USAGE_CERT \
| GCRY_PK_USAGE_AUTH | GCRY_PK_USAGE_UNKN) >= 256
# error Please choose another value for PUBKEY_USAGE_NONE
#endif
#define DIGEST_ALGO_MD5 /* 1 */ GCRY_MD_MD5 #define DIGEST_ALGO_MD5 /* 1 */ GCRY_MD_MD5
#define DIGEST_ALGO_SHA1 /* 2 */ GCRY_MD_SHA1 #define DIGEST_ALGO_SHA1 /* 2 */ GCRY_MD_SHA1

View File

@ -116,6 +116,16 @@ static struct {
}; };
/* Type of keys. */
typedef enum
{
KEY_TYPE_ECDH,
KEY_TYPE_ECDSA,
KEY_TYPE_RSA,
}
key_type_t;
/* The format of RSA private keys. */ /* The format of RSA private keys. */
typedef enum typedef enum
{ {
@ -128,6 +138,15 @@ typedef enum
rsa_key_format_t; rsa_key_format_t;
/* Elliptic Curves. */
enum
{
CURVE_NIST_P256,
CURVE_NIST_P384,
CURVE_NIST_P521
};
/* One cache item for DOs. */ /* One cache item for DOs. */
struct cache_s { struct cache_s {
struct cache_s *next; struct cache_s *next;
@ -199,15 +218,27 @@ struct app_local_s {
int fixedlen_admin; int fixedlen_admin;
} pinpad; } pinpad;
struct struct
{ {
unsigned int n_bits; /* Size of the modulus in bits. The rest key_type_t key_type;
of this strucuire is only valid if union {
this is not 0. */ struct {
unsigned int e_bits; /* Size of the public exponent in bits. */ unsigned int n_bits; /* Size of the modulus in bits. The rest
rsa_key_format_t format; of this strucuire is only valid if
} keyattr[3]; this is not 0. */
unsigned int e_bits; /* Size of the public exponent in bits. */
rsa_key_format_t format;
} rsa;
struct {
int curve;
} ecdsa;
struct {
int curve;
int hashalgo;
int cipheralgo;
} ecdh;
};
} keyattr[3];
}; };
@ -844,19 +875,60 @@ send_key_data (ctrl_t ctrl, const char *name,
} }
static void
get_ecc_key_parameters (int curve, int *r_n_bits, const char **r_curve_oid)
{
if (curve == CURVE_NIST_P256)
{
*r_n_bits = 256;
*r_curve_oid = "1.2.840.10045.3.1.7";
}
else if (curve == CURVE_NIST_P384)
{
*r_n_bits = 384;
*r_curve_oid = "1.3.132.0.34";
}
else
{
*r_n_bits = 521;
*r_curve_oid = "1.3.132.0.35";
}
}
static void static void
send_key_attr (ctrl_t ctrl, app_t app, const char *keyword, int number) send_key_attr (ctrl_t ctrl, app_t app, const char *keyword, int number)
{ {
char buffer[200]; char buffer[200];
int n_bits;
const char *curve_oid;
assert (number >=0 && number < DIM(app->app_local->keyattr)); assert (number >=0 && number < DIM(app->app_local->keyattr));
/* We only support RSA thus the algo identifier is fixed to 1. */ if (app->app_local->keyattr[number].key_type == KEY_TYPE_RSA)
snprintf (buffer, sizeof buffer, "%d 1 %u %u %d", snprintf (buffer, sizeof buffer, "%d 1 %u %u %d",
number+1, number+1,
app->app_local->keyattr[number].n_bits, app->app_local->keyattr[number].rsa.n_bits,
app->app_local->keyattr[number].e_bits, app->app_local->keyattr[number].rsa.e_bits,
app->app_local->keyattr[number].format); app->app_local->keyattr[number].rsa.format);
else if (app->app_local->keyattr[number].key_type == KEY_TYPE_ECDSA)
{
get_ecc_key_parameters (app->app_local->keyattr[number].ecdsa.curve,
&n_bits, &curve_oid);
snprintf (buffer, sizeof buffer, "%d 19 %u %s",
number+1, n_bits, curve_oid);
}
else if (app->app_local->keyattr[number].key_type == KEY_TYPE_ECDH)
{
get_ecc_key_parameters (app->app_local->keyattr[number].ecdh.curve,
&n_bits, &curve_oid);
snprintf (buffer, sizeof buffer, "%d 18 %u %s %d %d",
number+1, n_bits, curve_oid,
app->app_local->keyattr[number].ecdh.hashalgo,
app->app_local->keyattr[number].ecdh.cipheralgo);
}
else
snprintf (buffer, sizeof buffer, "0 0 UNKNOWN");
send_status_direct (ctrl, keyword, buffer); send_status_direct (ctrl, keyword, buffer);
} }
@ -1154,6 +1226,18 @@ retrieve_key_material (FILE *fp, const char *hexkeyid,
#endif /*GNUPG_MAJOR_VERSION > 1*/ #endif /*GNUPG_MAJOR_VERSION > 1*/
static const char *
get_curve_name (int curve)
{
if (curve == CURVE_NIST_P256)
return "NIST P-256";
else if (curve == CURVE_NIST_P384)
return "NIST P-384";
else
return "NIST P-521";
}
/* Get the public key for KEYNO and store it as an S-expresion with /* Get the public key for KEYNO and store it as an S-expresion with
the APP handle. On error that field gets cleared. If we already the APP handle. On error that field gets cleared. If we already
know about the public key we will just return. Note that this does know about the public key we will just return. Note that this does
@ -1171,11 +1255,14 @@ get_public_key (app_t app, int keyno)
gpg_error_t err = 0; gpg_error_t err = 0;
unsigned char *buffer; unsigned char *buffer;
const unsigned char *keydata, *m, *e; const unsigned char *keydata, *m, *e;
size_t buflen, keydatalen, mlen, elen; size_t buflen, keydatalen;
size_t mlen = 0;
size_t elen = 0;
unsigned char *mbuf = NULL; unsigned char *mbuf = NULL;
unsigned char *ebuf = NULL; unsigned char *ebuf = NULL;
char *keybuf = NULL; char *keybuf = NULL;
char *keybuf_p; gcry_sexp_t s_pkey;
size_t len;
if (keyno < 1 || keyno > 3) if (keyno < 1 || keyno > 3)
return gpg_error (GPG_ERR_INV_ID); return gpg_error (GPG_ERR_INV_ID);
@ -1227,51 +1314,34 @@ get_public_key (app_t app, int keyno)
goto leave; goto leave;
} }
m = find_tlv (keydata, keydatalen, 0x0081, &mlen); if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_RSA)
if (!m)
{ {
err = gpg_error (GPG_ERR_CARD); m = find_tlv (keydata, keydatalen, 0x0081, &mlen);
log_error (_("response does not contain the RSA modulus\n")); if (!m)
goto leave;
}
e = find_tlv (keydata, keydatalen, 0x0082, &elen);
if (!e)
{
err = gpg_error (GPG_ERR_CARD);
log_error (_("response does not contain the RSA public exponent\n"));
goto leave;
}
/* Prepend numbers with a 0 if needed. */
if (mlen && (*m & 0x80))
{
mbuf = xtrymalloc ( mlen + 1);
if (!mbuf)
{ {
err = gpg_error_from_syserror (); err = gpg_error (GPG_ERR_CARD);
log_error (_("response does not contain the RSA modulus\n"));
goto leave; goto leave;
} }
*mbuf = 0;
memcpy (mbuf+1, m, mlen); e = find_tlv (keydata, keydatalen, 0x0082, &elen);
mlen++; if (!e)
m = mbuf;
}
if (elen && (*e & 0x80))
{
ebuf = xtrymalloc ( elen + 1);
if (!ebuf)
{ {
err = gpg_error_from_syserror (); err = gpg_error (GPG_ERR_CARD);
log_error (_("response does not contain the RSA public exponent\n"));
goto leave;
}
}
else
{
m = find_tlv (keydata, keydatalen, 0x0086, &mlen);
if (!m)
{
err = gpg_error (GPG_ERR_CARD);
log_error (_("response does not contain the EC public point\n"));
goto leave; goto leave;
} }
*ebuf = 0;
memcpy (ebuf+1, e, elen);
elen++;
e = ebuf;
} }
} }
else else
{ {
@ -1328,29 +1398,88 @@ get_public_key (app_t app, int keyno)
} }
} }
/* Allocate a buffer to construct the S-expression. */
/* FIXME: We should provide a generalized S-expression creation mbuf = xtrymalloc ( mlen + 1);
mechanism. */ if (!mbuf)
keybuf = xtrymalloc (50 + 2*35 + mlen + elen + 1);
if (!keybuf)
{ {
err = gpg_error_from_syserror (); err = gpg_error_from_syserror ();
goto leave; goto leave;
} }
/* Prepend numbers with a 0 if needed. */
if (mlen && (*m & 0x80))
{
*mbuf = 0;
memcpy (mbuf+1, m, mlen);
mlen++;
}
else
memcpy (mbuf, m, mlen);
sprintf (keybuf, "(10:public-key(3:rsa(1:n%u:", (unsigned int) mlen); ebuf = xtrymalloc ( elen + 1);
keybuf_p = keybuf + strlen (keybuf); if (!ebuf)
memcpy (keybuf_p, m, mlen); {
keybuf_p += mlen; err = gpg_error_from_syserror ();
sprintf (keybuf_p, ")(1:e%u:", (unsigned int)elen); goto leave;
keybuf_p += strlen (keybuf_p); }
memcpy (keybuf_p, e, elen); /* Prepend numbers with a 0 if needed. */
keybuf_p += elen; if (elen && (*e & 0x80))
strcpy (keybuf_p, ")))"); {
keybuf_p += strlen (keybuf_p); *ebuf = 0;
memcpy (ebuf+1, e, elen);
elen++;
}
else
memcpy (ebuf, e, elen);
if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_RSA)
{
err = gcry_sexp_build (&s_pkey, NULL, "(public-key(rsa(n%b)(e%b)))",
mlen, mbuf, elen, ebuf);
if (err)
goto leave;
len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
keybuf = xtrymalloc (len);
if (!keybuf)
{
gcry_sexp_release (s_pkey);
err = gpg_error_from_syserror ();
goto leave;
}
gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, keybuf, len);
gcry_sexp_release (s_pkey);
}
else if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_ECDSA)
{
const char *curve_name
= get_curve_name (app->app_local->keyattr[keyno].ecdsa.curve);
err = gcry_sexp_build (&s_pkey, NULL,
"(public-key(ecdsa(curve%s)(q%b)))",
curve_name, mlen, mbuf);
if (err)
goto leave;
len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
keybuf = xtrymalloc (len);
if (!keybuf)
{
gcry_sexp_release (s_pkey);
err = gpg_error_from_syserror ();
goto leave;
}
gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, keybuf, len);
gcry_sexp_release (s_pkey);
}
else
{
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
goto leave;
}
app->app_local->pk[keyno].key = (unsigned char*)keybuf; app->app_local->pk[keyno].key = (unsigned char*)keybuf;
app->app_local->pk[keyno].keylen = (keybuf_p - keybuf); app->app_local->pk[keyno].keylen = len - 1; /* Decrement for trailing '\0' */
leave: leave:
/* Set a flag to indicate that we tried to read the key. */ /* Set a flag to indicate that we tried to read the key. */
@ -2395,7 +2524,7 @@ build_privkey_template (app_t app, int keyno,
*result = NULL; *result = NULL;
*resultlen = 0; *resultlen = 0;
switch (app->app_local->keyattr[keyno].format) switch (app->app_local->keyattr[keyno].rsa.format)
{ {
case RSA_STD: case RSA_STD:
case RSA_STD_N: case RSA_STD_N:
@ -2409,7 +2538,7 @@ build_privkey_template (app_t app, int keyno,
} }
/* Get the required length for E. */ /* Get the required length for E. */
rsa_e_reqlen = app->app_local->keyattr[keyno].e_bits/8; rsa_e_reqlen = app->app_local->keyattr[keyno].rsa.e_bits/8;
assert (rsa_e_len <= rsa_e_reqlen); assert (rsa_e_len <= rsa_e_reqlen);
/* Build the 7f48 cardholder private key template. */ /* Build the 7f48 cardholder private key template. */
@ -2425,8 +2554,8 @@ build_privkey_template (app_t app, int keyno,
tp += add_tlv (tp, 0x93, rsa_q_len); tp += add_tlv (tp, 0x93, rsa_q_len);
datalen += rsa_q_len; datalen += rsa_q_len;
if (app->app_local->keyattr[keyno].format == RSA_STD_N if (app->app_local->keyattr[keyno].rsa.format == RSA_STD_N
|| app->app_local->keyattr[keyno].format == RSA_CRT_N) || app->app_local->keyattr[keyno].rsa.format == RSA_CRT_N)
{ {
tp += add_tlv (tp, 0x97, rsa_n_len); tp += add_tlv (tp, 0x97, rsa_n_len);
datalen += rsa_n_len; datalen += rsa_n_len;
@ -2478,8 +2607,8 @@ build_privkey_template (app_t app, int keyno,
memcpy (tp, rsa_q, rsa_q_len); memcpy (tp, rsa_q, rsa_q_len);
tp += rsa_q_len; tp += rsa_q_len;
if (app->app_local->keyattr[keyno].format == RSA_STD_N if (app->app_local->keyattr[keyno].rsa.format == RSA_STD_N
|| app->app_local->keyattr[keyno].format == RSA_CRT_N) || app->app_local->keyattr[keyno].rsa.format == RSA_CRT_N)
{ {
memcpy (tp, rsa_n, rsa_n_len); memcpy (tp, rsa_n, rsa_n_len);
tp += rsa_n_len; tp += rsa_n_len;
@ -2764,7 +2893,7 @@ do_writekey (app_t app, ctrl_t ctrl,
goto leave; goto leave;
} }
maxbits = app->app_local->keyattr[keyno].n_bits; maxbits = app->app_local->keyattr[keyno].rsa.n_bits;
nbits = rsa_n? count_bits (rsa_n, rsa_n_len) : 0; nbits = rsa_n? count_bits (rsa_n, rsa_n_len) : 0;
if (opt.verbose) if (opt.verbose)
log_info ("RSA modulus size is %u bits (%u bytes)\n", log_info ("RSA modulus size is %u bits (%u bytes)\n",
@ -2775,7 +2904,7 @@ do_writekey (app_t app, ctrl_t ctrl,
/* Try to switch the key to a new length. */ /* Try to switch the key to a new length. */
err = change_keyattr (app, keyno, nbits, pincb, pincb_arg); err = change_keyattr (app, keyno, nbits, pincb, pincb_arg);
if (!err) if (!err)
maxbits = app->app_local->keyattr[keyno].n_bits; maxbits = app->app_local->keyattr[keyno].rsa.n_bits;
} }
if (nbits != maxbits) if (nbits != maxbits)
{ {
@ -2785,7 +2914,7 @@ do_writekey (app_t app, ctrl_t ctrl,
goto leave; goto leave;
} }
maxbits = app->app_local->keyattr[keyno].e_bits; maxbits = app->app_local->keyattr[keyno].rsa.e_bits;
if (maxbits > 32 && !app->app_local->extcap.is_v2) if (maxbits > 32 && !app->app_local->extcap.is_v2)
maxbits = 32; /* Our code for v1 does only support 32 bits. */ maxbits = 32; /* Our code for v1 does only support 32 bits. */
nbits = rsa_e? count_bits (rsa_e, rsa_e_len) : 0; nbits = rsa_e? count_bits (rsa_e, rsa_e_len) : 0;
@ -2797,7 +2926,7 @@ do_writekey (app_t app, ctrl_t ctrl,
goto leave; goto leave;
} }
maxbits = app->app_local->keyattr[keyno].n_bits/2; maxbits = app->app_local->keyattr[keyno].rsa.n_bits/2;
nbits = rsa_p? count_bits (rsa_p, rsa_p_len) : 0; nbits = rsa_p? count_bits (rsa_p, rsa_p_len) : 0;
if (nbits != maxbits) if (nbits != maxbits)
{ {
@ -2966,7 +3095,7 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
to put a limit on the max. allowed keysize. 2048 bit will to put a limit on the max. allowed keysize. 2048 bit will
already lead to a 527 byte long status line and thus a 4096 bit already lead to a 527 byte long status line and thus a 4096 bit
key would exceed the Assuan line length limit. */ key would exceed the Assuan line length limit. */
keybits = app->app_local->keyattr[keyno].n_bits; keybits = app->app_local->keyattr[keyno].rsa.n_bits;
if (keybits > 4096) if (keybits > 4096)
return gpg_error (GPG_ERR_TOO_LARGE); return gpg_error (GPG_ERR_TOO_LARGE);
@ -3287,14 +3416,23 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
memcpy (data + sizeof b ## _prefix, indata, indatalen); \ memcpy (data + sizeof b ## _prefix, indata, indatalen); \
} }
X(SHA1, sha1, 1) if (use_auth
else X(RMD160, rmd160, 1) || app->app_local->keyattr[use_auth? 2: 0].key_type == KEY_TYPE_RSA)
else X(SHA224, sha224, app->app_local->extcap.is_v2) {
else X(SHA256, sha256, app->app_local->extcap.is_v2) X(SHA1, sha1, 1)
else X(SHA384, sha384, app->app_local->extcap.is_v2) else X(RMD160, rmd160, 1)
else X(SHA512, sha512, app->app_local->extcap.is_v2) else X(SHA224, sha224, app->app_local->extcap.is_v2)
else X(SHA256, sha256, app->app_local->extcap.is_v2)
else X(SHA384, sha384, app->app_local->extcap.is_v2)
else X(SHA512, sha512, app->app_local->extcap.is_v2)
else
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
}
else else
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); {
datalen = indatalen;
memcpy (data, indata, indatalen);
}
#undef X #undef X
/* Redirect to the AUTH command if asked to. */ /* Redirect to the AUTH command if asked to. */
@ -3386,6 +3524,14 @@ do_auth (app_t app, const char *keyidstr,
if (indatalen > 101) /* For a 2048 bit key. */ if (indatalen > 101) /* For a 2048 bit key. */
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_VALUE);
if (app->app_local->keyattr[2].key_type == KEY_TYPE_ECDSA
&& (indatalen == 51 || indatalen == 67 || indatalen == 83))
{
const char *p = (const char *)indata + 19;
indata = p;
indatalen -= 19;
}
/* Check whether an OpenPGP card of any version has been requested. */ /* Check whether an OpenPGP card of any version has been requested. */
if (!strcmp (keyidstr, "OPENPGP.3")) if (!strcmp (keyidstr, "OPENPGP.3"))
; ;
@ -3753,6 +3899,22 @@ parse_historical (struct app_local_s *apploc,
} }
static int
parse_ecc_curve (const unsigned char *buffer, size_t buflen)
{
int curve;
if (buflen == 6 && buffer[5] == 0x22)
curve = CURVE_NIST_P384;
else if (buflen == 6 && buffer[5] == 0x23)
curve = CURVE_NIST_P521;
else
curve = CURVE_NIST_P256;
return curve;
}
/* Parse and optionally show the algorithm attributes for KEYNO. /* Parse and optionally show the algorithm attributes for KEYNO.
KEYNO must be in the range 0..2. */ KEYNO must be in the range 0..2. */
static void static void
@ -3765,7 +3927,8 @@ parse_algorithm_attribute (app_t app, int keyno)
assert (keyno >=0 && keyno <= 2); assert (keyno >=0 && keyno <= 2);
app->app_local->keyattr[keyno].n_bits = 0; app->app_local->keyattr[keyno].key_type = KEY_TYPE_RSA;
app->app_local->keyattr[keyno].rsa.n_bits = 0;
relptr = get_one_do (app, 0xC1+keyno, &buffer, &buflen, NULL); relptr = get_one_do (app, 0xC1+keyno, &buffer, &buflen, NULL);
if (!relptr) if (!relptr)
@ -3784,27 +3947,41 @@ parse_algorithm_attribute (app_t app, int keyno)
log_info ("Key-Attr-%s ..: ", desc[keyno]); log_info ("Key-Attr-%s ..: ", desc[keyno]);
if (*buffer == 1 && (buflen == 5 || buflen == 6)) if (*buffer == 1 && (buflen == 5 || buflen == 6))
{ {
app->app_local->keyattr[keyno].n_bits = (buffer[1]<<8 | buffer[2]); app->app_local->keyattr[keyno].rsa.n_bits = (buffer[1]<<8 | buffer[2]);
app->app_local->keyattr[keyno].e_bits = (buffer[3]<<8 | buffer[4]); app->app_local->keyattr[keyno].rsa.e_bits = (buffer[3]<<8 | buffer[4]);
app->app_local->keyattr[keyno].format = 0; app->app_local->keyattr[keyno].rsa.format = 0;
if (buflen < 6) if (buflen < 6)
app->app_local->keyattr[keyno].format = RSA_STD; app->app_local->keyattr[keyno].rsa.format = RSA_STD;
else else
app->app_local->keyattr[keyno].format = (buffer[5] == 0? RSA_STD : app->app_local->keyattr[keyno].rsa.format = (buffer[5] == 0? RSA_STD :
buffer[5] == 1? RSA_STD_N : buffer[5] == 1? RSA_STD_N :
buffer[5] == 2? RSA_CRT : buffer[5] == 2? RSA_CRT :
buffer[5] == 3? RSA_CRT_N : buffer[5] == 3? RSA_CRT_N :
RSA_UNKNOWN_FMT); RSA_UNKNOWN_FMT);
if (opt.verbose) if (opt.verbose)
log_printf log_printf
("RSA, n=%u, e=%u, fmt=%s\n", ("RSA, n=%u, e=%u, fmt=%s\n",
app->app_local->keyattr[keyno].n_bits, app->app_local->keyattr[keyno].rsa.n_bits,
app->app_local->keyattr[keyno].e_bits, app->app_local->keyattr[keyno].rsa.e_bits,
app->app_local->keyattr[keyno].format == RSA_STD? "std" : app->app_local->keyattr[keyno].rsa.format == RSA_STD? "std" :
app->app_local->keyattr[keyno].format == RSA_STD_N?"std+n": app->app_local->keyattr[keyno].rsa.format == RSA_STD_N?"std+n":
app->app_local->keyattr[keyno].format == RSA_CRT? "crt" : app->app_local->keyattr[keyno].rsa.format == RSA_CRT? "crt" :
app->app_local->keyattr[keyno].format == RSA_CRT_N?"crt+n":"?"); app->app_local->keyattr[keyno].rsa.format == RSA_CRT_N?"crt+n":"?");
}
else if (*buffer == 19) /* ECDSA */
{
app->app_local->keyattr[keyno].key_type = KEY_TYPE_ECDSA;
app->app_local->keyattr[keyno].ecdsa.curve
= parse_ecc_curve (buffer + 1, buflen - 1);
}
else if (*buffer == 18 && buflen == 11) /* ECDH */
{
app->app_local->keyattr[keyno].key_type = KEY_TYPE_ECDH;
app->app_local->keyattr[keyno].ecdh.curve
= parse_ecc_curve (buffer + 1, buflen - 1);
app->app_local->keyattr[keyno].ecdh.hashalgo = buffer[1];
app->app_local->keyattr[keyno].ecdh.cipheralgo = buffer[2];
} }
else if (opt.verbose) else if (opt.verbose)
log_printhex ("", buffer, buflen); log_printhex ("", buffer, buflen);

View File

@ -2839,7 +2839,7 @@ ccid_transceive_apdu_level (ccid_driver_t handle,
/* The maximum length for a short APDU T=1 block is 261. For an /* The maximum length for a short APDU T=1 block is 261. For an
extended APDU T=1 block the maximum length 65544; however extended APDU T=1 block the maximum length 65544; however
extended APDU exchange level is not fully supported yet. */ extended APDU exchange level is not fully supported yet. */
if (apdulen > 289) if (apdulen > sizeof (send_buffer) - 10)
return CCID_DRIVER_ERR_INV_VALUE; /* Invalid length. */ return CCID_DRIVER_ERR_INV_VALUE; /* Invalid length. */
msg[0] = PC_to_RDR_XfrBlock; msg[0] = PC_to_RDR_XfrBlock;

View File

@ -138,7 +138,7 @@ default_inq_cb (void *opaque, const char *line)
gpg_error_t err; gpg_error_t err;
ctrl_t ctrl = opaque; ctrl_t ctrl = opaque;
if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17])) if (has_leading_keyword (line, "PINENTRY_LAUNCHED"))
{ {
err = gpgsm_proxy_pinentry_notify (ctrl, line); err = gpgsm_proxy_pinentry_notify (ctrl, line);
if (err) if (err)
@ -315,7 +315,7 @@ inq_ciphertext_cb (void *opaque, const char *line)
struct cipher_parm_s *parm = opaque; struct cipher_parm_s *parm = opaque;
int rc; int rc;
if (!strncmp (line, "CIPHERTEXT", 10) && (line[10]==' '||!line[10])) if (has_leading_keyword (line, "CIPHERTEXT"))
{ {
assuan_begin_confidential (parm->ctx); assuan_begin_confidential (parm->ctx);
rc = assuan_send_data (parm->ctx, parm->ciphertext, parm->ciphertextlen); rc = assuan_send_data (parm->ctx, parm->ciphertext, parm->ciphertextlen);
@ -437,7 +437,7 @@ inq_genkey_parms (void *opaque, const char *line)
struct genkey_parm_s *parm = opaque; struct genkey_parm_s *parm = opaque;
int rc; int rc;
if (!strncmp (line, "KEYPARAM", 8) && (line[8]==' '||!line[8])) if (has_leading_keyword (line, "KEYPARAM"))
{ {
rc = assuan_send_data (parm->ctx, parm->sexp, parm->sexplen); rc = assuan_send_data (parm->ctx, parm->sexp, parm->sexplen);
} }
@ -693,14 +693,14 @@ static gpg_error_t
istrusted_status_cb (void *opaque, const char *line) istrusted_status_cb (void *opaque, const char *line)
{ {
struct rootca_flags_s *flags = opaque; struct rootca_flags_s *flags = opaque;
const char *s;
if (!strncmp (line, "TRUSTLISTFLAG", 13) && (line[13]==' ' || !line[13])) if ((s = has_leading_keyword (line, "TRUSTLISTFLAG")))
{ {
for (line += 13; *line == ' '; line++) line = s;
; if (has_leading_keyword (line, "relax"))
if (!strncmp (line, "relax", 5) && (line[5] == ' ' || !line[5]))
flags->relax = 1; flags->relax = 1;
else if (!strncmp (line, "cm", 2) && (line[2] == ' ' || !line[2])) else if (has_leading_keyword (line, "cm"))
flags->chain_model = 1; flags->chain_model = 1;
} }
return 0; return 0;
@ -824,14 +824,14 @@ static gpg_error_t
learn_status_cb (void *opaque, const char *line) learn_status_cb (void *opaque, const char *line)
{ {
struct learn_parm_s *parm = opaque; struct learn_parm_s *parm = opaque;
const char *s;
/* Pass progress data to the caller. */ /* Pass progress data to the caller. */
if (!strncmp (line, "PROGRESS", 8) && (line[8]==' ' || !line[8])) if ((s = has_leading_keyword (line, "PROGRESS")))
{ {
line = s;
if (parm->ctrl) if (parm->ctrl)
{ {
for (line += 8; *line == ' '; line++)
;
if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line)) if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line))
return gpg_error (GPG_ERR_ASS_CANCELED); return gpg_error (GPG_ERR_ASS_CANCELED);
} }
@ -1017,9 +1017,9 @@ keyinfo_status_cb (void *opaque, const char *line)
char **serialno = opaque; char **serialno = opaque;
const char *s, *s2; const char *s, *s2;
if (!strncmp (line, "KEYINFO ", 8) && !*serialno) if ((s = has_leading_keyword (line, "KEYINFO")) && !*serialno)
{ {
s = strchr (line+8, ' '); s = strchr (s, ' ');
if (s && s[1] == 'T' && s[2] == ' ' && s[3]) if (s && s[1] == 'T' && s[2] == ' ' && s[3])
{ {
s += 3; s += 3;
@ -1172,7 +1172,7 @@ inq_import_key_parms (void *opaque, const char *line)
struct import_key_parm_s *parm = opaque; struct import_key_parm_s *parm = opaque;
gpg_error_t err; gpg_error_t err;
if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7])) if (has_leading_keyword (line, "KEYDATA"))
{ {
assuan_begin_confidential (parm->ctx); assuan_begin_confidential (parm->ctx);
err = assuan_send_data (parm->ctx, parm->key, parm->keylen); err = assuan_send_data (parm->ctx, parm->key, parm->keylen);

View File

@ -282,47 +282,40 @@ static gpg_error_t
inq_certificate (void *opaque, const char *line) inq_certificate (void *opaque, const char *line)
{ {
struct inq_certificate_parm_s *parm = opaque; struct inq_certificate_parm_s *parm = opaque;
const char *s;
int rc; int rc;
size_t n;
const unsigned char *der; const unsigned char *der;
size_t derlen; size_t derlen;
int issuer_mode = 0; int issuer_mode = 0;
ksba_sexp_t ski = NULL; ksba_sexp_t ski = NULL;
if (!strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8])) if ((s = has_leading_keyword (line, "SENDCERT")))
{ {
line += 8; line = s;
} }
else if (!strncmp (line, "SENDCERT_SKI", 12) && (line[12]==' ' || !line[12])) else if ((s = has_leading_keyword (line, "SENDCERT_SKI")))
{ {
size_t n;
/* Send a certificate where a sourceKeyIdentifier is included. */ /* Send a certificate where a sourceKeyIdentifier is included. */
line += 12; line = s;
while (*line == ' ')
line++;
ski = make_simple_sexp_from_hexstr (line, &n); ski = make_simple_sexp_from_hexstr (line, &n);
line += n; line += n;
while (*line == ' ') while (*line == ' ')
line++; line++;
} }
else if (!strncmp (line, "SENDISSUERCERT", 14) else if ((s = has_leading_keyword (line, "SENDISSUERCERT")))
&& (line[14] == ' ' || !line[14]))
{ {
line += 14; line = s;
issuer_mode = 1; issuer_mode = 1;
} }
else if (!strncmp (line, "ISTRUSTED", 9) && (line[9]==' ' || !line[9])) else if ((s = has_leading_keyword (line, "ISTRUSTED")))
{ {
/* The server is asking us whether the certificate is a trusted /* The server is asking us whether the certificate is a trusted
root certificate. */ root certificate. */
const char *s;
size_t n;
char fpr[41]; char fpr[41];
struct rootca_flags_s rootca_flags; struct rootca_flags_s rootca_flags;
line += 9; line = s;
while (*line == ' ')
line++;
for (s=line,n=0; hexdigitp (s); s++, n++) for (s=line,n=0; hexdigitp (s); s++, n++)
; ;
@ -410,22 +403,21 @@ static gpg_error_t
isvalid_status_cb (void *opaque, const char *line) isvalid_status_cb (void *opaque, const char *line)
{ {
struct isvalid_status_parm_s *parm = opaque; struct isvalid_status_parm_s *parm = opaque;
const char *s;
if (!strncmp (line, "PROGRESS", 8) && (line[8]==' ' || !line[8])) if ((s = has_leading_keyword (line, "PROGRESS")))
{ {
if (parm->ctrl) if (parm->ctrl)
{ {
for (line += 8; *line == ' '; line++) line = s;
;
if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line)) if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line))
return gpg_error (GPG_ERR_ASS_CANCELED); return gpg_error (GPG_ERR_ASS_CANCELED);
} }
} }
else if (!strncmp (line, "ONLY_VALID_IF_CERT_VALID", 24) else if ((s = has_leading_keyword (line, "ONLY_VALID_IF_CERT_VALID")))
&& (line[24]==' ' || !line[24]))
{ {
parm->seen++; parm->seen++;
if (!line[24] || !unhexify_fpr (line+25, parm->fpr)) if (!*s || !unhexify_fpr (s, parm->fpr))
parm->seen++; /* Bumb it to indicate an error. */ parm->seen++; /* Bumb it to indicate an error. */
} }
return 0; return 0;
@ -693,23 +685,22 @@ static gpg_error_t
lookup_status_cb (void *opaque, const char *line) lookup_status_cb (void *opaque, const char *line)
{ {
struct lookup_parm_s *parm = opaque; struct lookup_parm_s *parm = opaque;
const char *s;
if (!strncmp (line, "PROGRESS", 8) && (line[8]==' ' || !line[8])) if ((s = has_leading_keyword (line, "PROGRESS")))
{ {
if (parm->ctrl) if (parm->ctrl)
{ {
for (line += 8; *line == ' '; line++) line = s;
;
if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line)) if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line))
return gpg_error (GPG_ERR_ASS_CANCELED); return gpg_error (GPG_ERR_ASS_CANCELED);
} }
} }
else if (!strncmp (line, "TRUNCATED", 9) && (line[9]==' ' || !line[9])) else if ((s = has_leading_keyword (line, "TRUNCATED")))
{ {
if (parm->ctrl) if (parm->ctrl)
{ {
for (line +=9; *line == ' '; line++) line = s;
;
gpgsm_status (parm->ctrl, STATUS_TRUNCATED, line); gpgsm_status (parm->ctrl, STATUS_TRUNCATED, line);
} }
} }
@ -878,16 +869,17 @@ static gpg_error_t
run_command_inq_cb (void *opaque, const char *line) run_command_inq_cb (void *opaque, const char *line)
{ {
struct run_command_parm_s *parm = opaque; struct run_command_parm_s *parm = opaque;
const char *s;
int rc = 0; int rc = 0;
if ( !strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]) ) if ((s = has_leading_keyword (line, "SENDCERT")))
{ /* send the given certificate */ { /* send the given certificate */
int err; int err;
ksba_cert_t cert; ksba_cert_t cert;
const unsigned char *der; const unsigned char *der;
size_t derlen; size_t derlen;
line += 8; line = s;
if (!*line) if (!*line)
return gpg_error (GPG_ERR_ASS_PARAMETER); return gpg_error (GPG_ERR_ASS_PARAMETER);
@ -907,9 +899,9 @@ run_command_inq_cb (void *opaque, const char *line)
ksba_cert_release (cert); ksba_cert_release (cert);
} }
} }
else if ( !strncmp (line, "PRINTINFO", 9) && (line[9] == ' ' || !line[9]) ) else if ((s = has_leading_keyword (line, "PRINTINFO")))
{ /* Simply show the message given in the argument. */ { /* Simply show the message given in the argument. */
line += 9; line = s;
log_info ("dirmngr: %s\n", line); log_info ("dirmngr: %s\n", line);
} }
else else
@ -925,17 +917,17 @@ static gpg_error_t
run_command_status_cb (void *opaque, const char *line) run_command_status_cb (void *opaque, const char *line)
{ {
ctrl_t ctrl = opaque; ctrl_t ctrl = opaque;
const char *s;
if (opt.verbose) if (opt.verbose)
{ {
log_info ("dirmngr status: %s\n", line); log_info ("dirmngr status: %s\n", line);
} }
if (!strncmp (line, "PROGRESS", 8) && (line[8]==' ' || !line[8])) if ((s = has_leading_keyword (line, "PROGRESS")))
{ {
if (ctrl) if (ctrl)
{ {
for (line += 8; *line == ' '; line++) line = s;
;
if (gpgsm_status (ctrl, STATUS_PROGRESS, line)) if (gpgsm_status (ctrl, STATUS_PROGRESS, line))
return gpg_error (GPG_ERR_ASS_CANCELED); return gpg_error (GPG_ERR_ASS_CANCELED);
} }

View File

@ -3382,7 +3382,6 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
int in_rule = 0; int in_rule = 0;
int got_match = 0; int got_match = 0;
int runtime[GC_BACKEND_NR]; int runtime[GC_BACKEND_NR];
int used_components[GC_COMPONENT_NR];
int backend_id, component_id; int backend_id, component_id;
char *fname; char *fname;
@ -3393,8 +3392,6 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++) for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++)
runtime[backend_id] = 0; runtime[backend_id] = 0;
for (component_id = 0; component_id < GC_COMPONENT_NR; component_id++)
used_components[component_id] = 0;
config = fopen (fname, "r"); config = fopen (fname, "r");
if (!config) if (!config)
@ -3621,9 +3618,6 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
if (defaults) if (defaults)
{ {
assert (component_id >= 0 && component_id < GC_COMPONENT_NR);
used_components[component_id] = 1;
/* Here we explicitly allow to update the value again. */ /* Here we explicitly allow to update the value again. */
if (newflags) if (newflags)
{ {