summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2013-03-20 10:00:12 +0100
committerWerner Koch <wk@gnupg.org>2013-03-20 10:00:12 +0100
commiteaa6dc3a8b4f31525650cd4785d6bafab86d68b7 (patch)
tree6552e846c825e2dae78d5ceefebee0e2acaeb27f
parentAdd code to allow for late memory cleanup. (diff)
parentgpg: Print indicator for unknown key capability. (diff)
downloadgnupg2-eaa6dc3a8b4f31525650cd4785d6bafab86d68b7.tar.xz
gnupg2-eaa6dc3a8b4f31525650cd4785d6bafab86d68b7.zip
Merge branch 'master' into key-storage-work
--
-rw-r--r--.gitignore4
-rw-r--r--agent/agent.h3
-rw-r--r--agent/call-pinentry.c9
-rw-r--r--agent/call-scd.c53
-rw-r--r--agent/command-ssh.c2
-rw-r--r--agent/command.c1
-rw-r--r--agent/divert-scd.c8
-rw-r--r--agent/findkey.c2
-rw-r--r--agent/pksign.c92
-rw-r--r--common/util.h10
-rw-r--r--configure.ac2
-rw-r--r--doc/DETAILS1
-rw-r--r--doc/gpg.texi4
-rw-r--r--g10/call-agent.c22
-rw-r--r--g10/call-dirmngr.c4
-rw-r--r--g10/card-util.c6
-rw-r--r--g10/getkey.c8
-rw-r--r--g10/keygen.c3
-rw-r--r--g10/keylist.c3
-rw-r--r--g13/g13.c18
-rw-r--r--include/cipher.h7
-rw-r--r--scd/app-openpgp.c379
-rw-r--r--scd/ccid-driver.c2
-rw-r--r--sm/call-agent.c28
-rw-r--r--sm/call-dirmngr.c64
-rw-r--r--tools/gpgconf-comp.c6
26 files changed, 482 insertions, 259 deletions
diff --git a/.gitignore b/.gitignore
index d3a576aa4..6502072e7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -154,7 +154,5 @@ tools/mk-tdata
tools/symcryptrun
tools/watchgnupg
tools/gpgtar
-
-
+private-keys-v1.d/
x.parm
-private-keys-v1.d/ \ No newline at end of file
diff --git a/agent/agent.h b/agent/agent.h
index 030b29520..2fd0b8b8a 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -405,7 +405,8 @@ void agent_reload_trustlist (void);
/*-- divert-scd.c --*/
int divert_pksign (ctrl_t ctrl,
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,
const unsigned char *cipher,
const unsigned char *shadow_info,
diff --git a/agent/call-pinentry.c b/agent/call-pinentry.c
index c6b6b5282..78e1c1106 100644
--- a/agent/call-pinentry.c
+++ b/agent/call-pinentry.c
@@ -596,18 +596,15 @@ static gpg_error_t
inq_quality (void *opaque, const char *line)
{
assuan_context_t ctx = opaque;
+ const char *s;
char *pin;
int rc;
int percent;
char numbuf[20];
- if (!strncmp (line, "QUALITY", 7) && (line[7] == ' ' || !line[7]))
+ if ((s = has_leading_keyword (line, "QUALITY")))
{
- line += 7;
- while (*line == ' ')
- line++;
-
- pin = unescape_passphrase_string (line);
+ pin = unescape_passphrase_string (s);
if (!pin)
rc = gpg_error_from_syserror ();
else
diff --git a/agent/call-scd.c b/agent/call-scd.c
index cbe4d1c34..a334b15a1 100644
--- a/agent/call-scd.c
+++ b/agent/call-scd.c
@@ -701,17 +701,15 @@ static gpg_error_t
inq_needpin (void *opaque, const char *line)
{
struct inq_needpin_s *parm = opaque;
+ const char *s;
char *pin;
size_t pinlen;
int rc;
parm->any_inq_seen = 1;
- if (!strncmp (line, "NEEDPIN", 7) && (line[7] == ' ' || !line[7]))
+ if ((s = has_leading_keyword (line, "NEEDPIN")))
{
- line += 7;
- while (*line == ' ')
- line++;
-
+ line = s;
pinlen = 90;
pin = gcry_malloc_secure (pinlen);
if (!pin)
@@ -722,17 +720,11 @@ inq_needpin (void *opaque, const char *line)
rc = assuan_send_data (parm->ctx, pin, pinlen);
xfree (pin);
}
- else if (!strncmp (line, "POPUPPINPADPROMPT", 17)
- && (line[17] == ' ' || !line[17]))
+ else if ((s = has_leading_keyword (line, "POPUPPINPADPROMPT")))
{
- line += 17;
- while (*line == ' ')
- line++;
-
- rc = parm->getpin_cb (parm->getpin_cb_arg, line, NULL, 1);
+ rc = parm->getpin_cb (parm->getpin_cb_arg, s, NULL, 1);
}
- else if (!strncmp (line, "DISMISSPINPADPROMPT", 19)
- && (line[19] == ' ' || !line[19]))
+ else if ((s = has_leading_keyword (line, "DISMISSPINPADPROMPT")))
{
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];
membuf_t data;
struct inq_needpin_s inqparm;
- size_t len;
- unsigned char *sigbuf;
- size_t sigbuflen;
- int prepend_nul;
*r_buf = NULL;
rc = start_scd (ctrl);
@@ -876,32 +864,13 @@ agent_card_pksign (ctrl_t ctrl,
if (rc)
{
+ size_t len;
+
xfree (get_membuf (&data, &len));
return unlock_scd (ctrl, rc);
}
- sigbuf = get_membuf (&data, &sigbuflen);
-
- /* Create an S-expression from it which is formatted like this:
- "(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));
+
+ *r_buf = get_membuf (&data, r_buflen);
return unlock_scd (ctrl, 0);
}
@@ -1069,7 +1038,7 @@ inq_writekey_parms (void *opaque, const char *line)
{
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);
else
return inq_needpin (opaque, line);
diff --git a/agent/command-ssh.c b/agent/command-ssh.c
index c0b608a4a..94538b3d8 100644
--- a/agent/command-ssh.c
+++ b/agent/command-ssh.c
@@ -1247,6 +1247,8 @@ ssh_signature_encoder_ecdsa (ssh_key_type_spec_t *spec,
gpg_error_t err;
int i;
+ (void)spec;
+
innerlen = 0;
for (i = 0; i < DIM(data); i++)
{
diff --git a/agent/command.c b/agent/command.c
index 2844398f6..823b233bf 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -2197,6 +2197,7 @@ cmd_keytocard (assuan_context_t ctx, char *line)
gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, keydata, keydatalen);
gcry_sexp_release (s_skey);
+ keydatalen--; /* Decrement for last '\0'. */
/* Add timestamp "created-at" in the private key */
timestamp = isotime2epoch (timestamp_str);
snprintf (keydata+keydatalen-1, 30, "(10:created-at10:%010lu))", timestamp);
diff --git a/agent/divert-scd.c b/agent/divert-scd.c
index 5fb037ee5..f0d847389 100644
--- a/agent/divert-scd.c
+++ b/agent/divert-scd.c
@@ -335,7 +335,8 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
int
divert_pksign (ctrl_t ctrl,
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;
char *kid;
@@ -369,7 +370,10 @@ divert_pksign (ctrl_t ctrl,
}
if (!rc)
- *r_sig = sigval;
+ {
+ *r_sig = sigval;
+ *r_siglen = siglen;
+ }
xfree (kid);
diff --git a/agent/findkey.c b/agent/findkey.c
index b17870ef7..ebdcc038e 100644
--- a/agent/findkey.c
+++ b/agent/findkey.c
@@ -828,7 +828,7 @@ agent_public_key_from_file (ctrl_t ctrl,
int i, idx;
gcry_sexp_t s_skey;
char algoname[6];
- char elems[6];
+ char elems[7];
gcry_sexp_t uri_sexp, comment_sexp;
const char *uri, *comment;
size_t uri_length, comment_length;
diff --git a/agent/pksign.c b/agent/pksign.c
index dc44b881d..85187305c 100644
--- a/agent/pksign.c
+++ b/agent/pksign.c
@@ -278,24 +278,104 @@ agent_pksign_do (ctrl_t ctrl, const char *cache_nonce,
if (!s_skey)
{
/* Divert operation to the smartcard */
-
+ gcry_sexp_t s_pkey, l;
+ const char *name;
+ size_t len;
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,
ctrl->digest.value,
ctrl->digest.valuelen,
ctrl->digest.algo,
- shadow_info, &buf);
+ shadow_info, &buf, &len);
if (rc)
{
log_error ("smartcard signing failed: %s\n", gpg_strerror (rc));
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);
if (rc)
{
diff --git a/common/util.h b/common/util.h
index c8a008fd7..73ba84e41 100644
--- a/common/util.h
+++ b/common/util.h
@@ -34,16 +34,6 @@
#include <gcrypt.h> /* We need this for the memory function protos. */
#include <errno.h> /* We need errno. */
#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. */
diff --git a/configure.ac b/configure.ac
index cf5ab3fa6..353546a09 100644
--- a/configure.ac
+++ b/configure.ac
@@ -43,7 +43,7 @@ m4_define([mym4_full_version],[mym4_version[]mym4_betastring])
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_VERSION=1.5.0
diff --git a/doc/DETAILS b/doc/DETAILS
index a52979f65..d5c5cea75 100644
--- a/doc/DETAILS
+++ b/doc/DETAILS
@@ -161,6 +161,7 @@ described here.
- s :: Sign
- c :: Certify
- a :: Authentication
+ - ? :: Unknown capability
A key may have any combination of them in any order. In addition
to these letters, the primary key has uppercase versions of the
diff --git a/doc/gpg.texi b/doc/gpg.texi
index cf647e19b..0462c9e45 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -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
correctly. If you prefix @code{name} with an exclamation mark (!), the
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
(certifications). @option{--set-notation} sets both.
@@ -2440,7 +2440,7 @@ meaningful when using the OpenPGP smartcard.
@opindex sig-policy-url
@opindex cert-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
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
diff --git a/g10/call-agent.c b/g10/call-agent.c
index 4828f9a3f..cb965e9ad 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -607,6 +607,10 @@ agent_keytocard (const char *hexgrip, int keyno, int force,
{
int rc;
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",
force?"--force ": "", hexgrip, serialno, keyno, timestamp);
@@ -616,8 +620,8 @@ agent_keytocard (const char *hexgrip, int keyno, int force,
if (rc)
return rc;
- rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb,
- NULL, NULL, NULL);
+ rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, &parm,
+ NULL, NULL);
if (rc)
return rc;
@@ -721,7 +725,7 @@ inq_writecert_parms (void *opaque, const char *line)
int rc;
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,
parm->certdata, parm->certdatalen);
@@ -774,7 +778,7 @@ inq_writekey_parms (void *opaque, const char *line)
int rc;
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);
}
@@ -1467,9 +1471,9 @@ keyinfo_status_cb (void *opaque, const char *line)
char **serialno = opaque;
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])
{
s += 3;
@@ -1571,7 +1575,7 @@ inq_genkey_parms (void *opaque, const char *line)
struct genkey_parm_s *parm = opaque;
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,
parm->keyparms, strlen (parm->keyparms));
@@ -1798,7 +1802,7 @@ inq_ciphertext_cb (void *opaque, const char *line)
struct cipher_parm_s *parm = opaque;
int rc;
- if (!strncmp (line, "CIPHERTEXT", 10) && (line[10]==' '||!line[10]))
+ if (has_leading_keyword (line, "CIPHERTEXT"))
{
assuan_begin_confidential (parm->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;
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);
}
diff --git a/g10/call-dirmngr.c b/g10/call-dirmngr.c
index 09ade4eb9..75f25f8a4 100644
--- a/g10/call-dirmngr.c
+++ b/g10/call-dirmngr.c
@@ -515,12 +515,12 @@ ks_put_inq_cb (void *opaque, const char *line)
struct ks_put_parm_s *parm = opaque;
gpg_error_t err = 0;
- if (!strncmp (line, "KEYBLOCK", 8) && (line[8] == ' ' || !line[8]))
+ if (has_leading_keyword (line, "KEYBLOCK"))
{
if (parm->data)
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;
estream_t fp;
diff --git a/g10/card-util.c b/g10/card-util.c
index 75208cc86..add8eed09 100644
--- a/g10/card-util.c
+++ b/g10/card-util.c
@@ -550,7 +550,9 @@ card_status (estream_t fp, char *serialno, size_t serialnobuflen)
tty_fprintf (fp, " %u%c",
info.key_attr[i].nbits,
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, "Max. PIN lengths .: %d %d %d\n",
@@ -1560,7 +1562,7 @@ card_store_subkey (KBNODE node, int use)
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 ("\n");
diff --git a/g10/getkey.c b/g10/getkey.c
index 60429b6a1..4453a92d5 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -1291,13 +1291,19 @@ parse_key_usage (PKT_signature * sig)
if (flags)
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
capability that we do not handle. This serves to distinguish
between a zero key usage which we handle as the default
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;
}
diff --git a/g10/keygen.c b/g10/keygen.c
index fc985eef3..2017662e7 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -216,9 +216,6 @@ do_add_key_flags (PKT_signature *sig, unsigned int use)
if (use & PUBKEY_USAGE_AUTH)
buf[0] |= 0x20;
- if (!buf[0])
- return;
-
build_sig_subpkt (sig, SIGSUBPKT_KEY_FLAGS, buf, 1);
}
diff --git a/g10/keylist.c b/g10/keylist.c
index 87f3a4bb0..d45aed672 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -627,6 +627,9 @@ print_capabilities (PKT_public_key *pk, KBNODE keyblock)
if ((use & PUBKEY_USAGE_AUTH))
es_putc ('a', es_stdout);
+ if ((use & PUBKEY_USAGE_UNKNOWN))
+ es_putc ('?', es_stdout);
+
if (keyblock)
{
/* Figure out the usable capabilities. */
diff --git a/g13/g13.c b/g13/g13.c
index 82ed9d895..fca9e7a19 100644
--- a/g13/g13.c
+++ b/g13/g13.c
@@ -323,7 +323,7 @@ main ( int argc, char **argv)
int orig_argc;
char **orig_argv;
gpg_error_t err = 0;
- const char *fname;
+ /* const char *fname; */
int may_coredump;
FILE *configfp = NULL;
char *configname = NULL;
@@ -334,10 +334,10 @@ main ( int argc, char **argv)
char *logfile = NULL;
int greeting = 0;
int nogreeting = 0;
- int debug_wait = 0;
+ /* int debug_wait = 0; */
int use_random_seed = 1;
- int nodetach = 0;
- int nokeysetup = 0;
+ /* int nodetach = 0; */
+ /* int nokeysetup = 0; */
enum cmd_and_opt_values cmd = 0;
struct server_control_s ctrl;
strlist_t recipients = NULL;
@@ -473,13 +473,13 @@ main ( int argc, char **argv)
case aGPGConfTest:
set_cmd (&cmd, pargs.r_opt);
nogreeting = 1;
- nokeysetup = 1;
+ /* nokeysetup = 1; */
break;
case aServer:
case aMount:
case aUmount:
- nokeysetup = 1;
+ /* nokeysetup = 1; */
case aCreate:
set_cmd (&cmd, pargs.r_opt);
break;
@@ -504,13 +504,13 @@ main ( int argc, char **argv)
case oLogFile: logfile = pargs.r.ret_str; 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 oDebugAll: debug_value = ~0; break;
case oDebugNone: debug_value = 0; 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:
may_coredump = enable_core_dumps ();
break;
@@ -653,7 +653,7 @@ main ( int argc, char **argv)
}
/* 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
and stops if any of the given keys was not found. */
diff --git a/include/cipher.h b/include/cipher.h
index 191e197bc..557ab70e1 100644
--- a/include/cipher.h
+++ b/include/cipher.h
@@ -54,9 +54,14 @@
#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_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_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_SHA1 /* 2 */ GCRY_MD_SHA1
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 23b28c3f5..673570d3f 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -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. */
typedef enum
{
@@ -128,6 +138,15 @@ typedef enum
rsa_key_format_t;
+/* Elliptic Curves. */
+enum
+ {
+ CURVE_NIST_P256,
+ CURVE_NIST_P384,
+ CURVE_NIST_P521
+ };
+
+
/* One cache item for DOs. */
struct cache_s {
struct cache_s *next;
@@ -199,15 +218,27 @@ struct app_local_s {
int fixedlen_admin;
} pinpad;
- struct
- {
- unsigned int n_bits; /* Size of the modulus in bits. The rest
- of this strucuire is only valid if
- this is not 0. */
- unsigned int e_bits; /* Size of the public exponent in bits. */
- rsa_key_format_t format;
- } keyattr[3];
-
+ struct
+ {
+ key_type_t key_type;
+ union {
+ struct {
+ unsigned int n_bits; /* Size of the modulus in bits. The rest
+ of this strucuire is only valid if
+ 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];
};
@@ -845,18 +876,59 @@ 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
send_key_attr (ctrl_t ctrl, app_t app, const char *keyword, int number)
{
char buffer[200];
+ int n_bits;
+ const char *curve_oid;
assert (number >=0 && number < DIM(app->app_local->keyattr));
- /* We only support RSA thus the algo identifier is fixed to 1. */
- snprintf (buffer, sizeof buffer, "%d 1 %u %u %d",
- number+1,
- app->app_local->keyattr[number].n_bits,
- app->app_local->keyattr[number].e_bits,
- app->app_local->keyattr[number].format);
+ if (app->app_local->keyattr[number].key_type == KEY_TYPE_RSA)
+ snprintf (buffer, sizeof buffer, "%d 1 %u %u %d",
+ number+1,
+ app->app_local->keyattr[number].rsa.n_bits,
+ app->app_local->keyattr[number].rsa.e_bits,
+ 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);
}
@@ -1154,6 +1226,18 @@ retrieve_key_material (FILE *fp, const char *hexkeyid,
#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
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
@@ -1171,11 +1255,14 @@ get_public_key (app_t app, int keyno)
gpg_error_t err = 0;
unsigned char *buffer;
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 *ebuf = NULL;
char *keybuf = NULL;
- char *keybuf_p;
+ gcry_sexp_t s_pkey;
+ size_t len;
if (keyno < 1 || keyno > 3)
return gpg_error (GPG_ERR_INV_ID);
@@ -1227,51 +1314,34 @@ get_public_key (app_t app, int keyno)
goto leave;
}
- m = find_tlv (keydata, keydatalen, 0x0081, &mlen);
- if (!m)
+ if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_RSA)
{
- err = gpg_error (GPG_ERR_CARD);
- log_error (_("response does not contain the RSA modulus\n"));
- 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;
- }
+ m = find_tlv (keydata, keydatalen, 0x0081, &mlen);
+ if (!m)
+ {
+ err = gpg_error (GPG_ERR_CARD);
+ log_error (_("response does not contain the RSA modulus\n"));
+ goto leave;
+ }
- /* Prepend numbers with a 0 if needed. */
- if (mlen && (*m & 0x80))
- {
- mbuf = xtrymalloc ( mlen + 1);
- if (!mbuf)
+ e = find_tlv (keydata, keydatalen, 0x0082, &elen);
+ if (!e)
{
- err = gpg_error_from_syserror ();
+ err = gpg_error (GPG_ERR_CARD);
+ log_error (_("response does not contain the RSA public exponent\n"));
goto leave;
}
- *mbuf = 0;
- memcpy (mbuf+1, m, mlen);
- mlen++;
- m = mbuf;
}
- if (elen && (*e & 0x80))
+ else
{
- ebuf = xtrymalloc ( elen + 1);
- if (!ebuf)
+ m = find_tlv (keydata, keydatalen, 0x0086, &mlen);
+ if (!m)
{
- err = gpg_error_from_syserror ();
+ err = gpg_error (GPG_ERR_CARD);
+ log_error (_("response does not contain the EC public point\n"));
goto leave;
}
- *ebuf = 0;
- memcpy (ebuf+1, e, elen);
- elen++;
- e = ebuf;
}
-
}
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
- mechanism. */
- keybuf = xtrymalloc (50 + 2*35 + mlen + elen + 1);
- if (!keybuf)
+
+ mbuf = xtrymalloc ( mlen + 1);
+ if (!mbuf)
{
err = gpg_error_from_syserror ();
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);
+
+ ebuf = xtrymalloc ( elen + 1);
+ if (!ebuf)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ /* Prepend numbers with a 0 if needed. */
+ if (elen && (*e & 0x80))
+ {
+ *ebuf = 0;
+ memcpy (ebuf+1, e, elen);
+ elen++;
+ }
+ else
+ memcpy (ebuf, e, elen);
- sprintf (keybuf, "(10:public-key(3:rsa(1:n%u:", (unsigned int) mlen);
- keybuf_p = keybuf + strlen (keybuf);
- memcpy (keybuf_p, m, mlen);
- keybuf_p += mlen;
- sprintf (keybuf_p, ")(1:e%u:", (unsigned int)elen);
- keybuf_p += strlen (keybuf_p);
- memcpy (keybuf_p, e, elen);
- keybuf_p += elen;
- strcpy (keybuf_p, ")))");
- keybuf_p += strlen (keybuf_p);
+ 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].keylen = (keybuf_p - keybuf);
+ app->app_local->pk[keyno].keylen = len - 1; /* Decrement for trailing '\0' */
leave:
/* 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;
*resultlen = 0;
- switch (app->app_local->keyattr[keyno].format)
+ switch (app->app_local->keyattr[keyno].rsa.format)
{
case RSA_STD:
case RSA_STD_N:
@@ -2409,7 +2538,7 @@ build_privkey_template (app_t app, int keyno,
}
/* 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);
/* 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);
datalen += rsa_q_len;
- if (app->app_local->keyattr[keyno].format == RSA_STD_N
- || app->app_local->keyattr[keyno].format == RSA_CRT_N)
+ if (app->app_local->keyattr[keyno].rsa.format == RSA_STD_N
+ || app->app_local->keyattr[keyno].rsa.format == RSA_CRT_N)
{
tp += add_tlv (tp, 0x97, 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);
tp += rsa_q_len;
- if (app->app_local->keyattr[keyno].format == RSA_STD_N
- || app->app_local->keyattr[keyno].format == RSA_CRT_N)
+ if (app->app_local->keyattr[keyno].rsa.format == RSA_STD_N
+ || app->app_local->keyattr[keyno].rsa.format == RSA_CRT_N)
{
memcpy (tp, rsa_n, rsa_n_len);
tp += rsa_n_len;
@@ -2764,7 +2893,7 @@ do_writekey (app_t app, ctrl_t ctrl,
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;
if (opt.verbose)
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. */
err = change_keyattr (app, keyno, nbits, pincb, pincb_arg);
if (!err)
- maxbits = app->app_local->keyattr[keyno].n_bits;
+ maxbits = app->app_local->keyattr[keyno].rsa.n_bits;
}
if (nbits != maxbits)
{
@@ -2785,7 +2914,7 @@ do_writekey (app_t app, ctrl_t ctrl,
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)
maxbits = 32; /* Our code for v1 does only support 32 bits. */
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;
}
- 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;
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
already lead to a 527 byte long status line and thus a 4096 bit
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)
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); \
}
- X(SHA1, sha1, 1)
- else X(RMD160, rmd160, 1)
- 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)
+ if (use_auth
+ || app->app_local->keyattr[use_auth? 2: 0].key_type == KEY_TYPE_RSA)
+ {
+ X(SHA1, sha1, 1)
+ else X(RMD160, rmd160, 1)
+ 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
- return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
+ {
+ datalen = indatalen;
+ memcpy (data, indata, indatalen);
+ }
#undef X
/* 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. */
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. */
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.
KEYNO must be in the range 0..2. */
static void
@@ -3765,7 +3927,8 @@ parse_algorithm_attribute (app_t app, int keyno)
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);
if (!relptr)
@@ -3784,27 +3947,41 @@ parse_algorithm_attribute (app_t app, int keyno)
log_info ("Key-Attr-%s ..: ", desc[keyno]);
if (*buffer == 1 && (buflen == 5 || buflen == 6))
{
- app->app_local->keyattr[keyno].n_bits = (buffer[1]<<8 | buffer[2]);
- app->app_local->keyattr[keyno].e_bits = (buffer[3]<<8 | buffer[4]);
- app->app_local->keyattr[keyno].format = 0;
+ app->app_local->keyattr[keyno].rsa.n_bits = (buffer[1]<<8 | buffer[2]);
+ app->app_local->keyattr[keyno].rsa.e_bits = (buffer[3]<<8 | buffer[4]);
+ app->app_local->keyattr[keyno].rsa.format = 0;
if (buflen < 6)
- app->app_local->keyattr[keyno].format = RSA_STD;
+ app->app_local->keyattr[keyno].rsa.format = RSA_STD;
else
- app->app_local->keyattr[keyno].format = (buffer[5] == 0? RSA_STD :
- buffer[5] == 1? RSA_STD_N :
- buffer[5] == 2? RSA_CRT :
- buffer[5] == 3? RSA_CRT_N :
- RSA_UNKNOWN_FMT);
+ app->app_local->keyattr[keyno].rsa.format = (buffer[5] == 0? RSA_STD :
+ buffer[5] == 1? RSA_STD_N :
+ buffer[5] == 2? RSA_CRT :
+ buffer[5] == 3? RSA_CRT_N :
+ RSA_UNKNOWN_FMT);
if (opt.verbose)
log_printf
("RSA, n=%u, e=%u, fmt=%s\n",
- app->app_local->keyattr[keyno].n_bits,
- app->app_local->keyattr[keyno].e_bits,
- app->app_local->keyattr[keyno].format == RSA_STD? "std" :
- app->app_local->keyattr[keyno].format == RSA_STD_N?"std+n":
- app->app_local->keyattr[keyno].format == RSA_CRT? "crt" :
- app->app_local->keyattr[keyno].format == RSA_CRT_N?"crt+n":"?");
+ app->app_local->keyattr[keyno].rsa.n_bits,
+ app->app_local->keyattr[keyno].rsa.e_bits,
+ app->app_local->keyattr[keyno].rsa.format == RSA_STD? "std" :
+ app->app_local->keyattr[keyno].rsa.format == RSA_STD_N?"std+n":
+ app->app_local->keyattr[keyno].rsa.format == RSA_CRT? "crt" :
+ 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)
log_printhex ("", buffer, buflen);
diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c
index 2d1ef8d46..da5fac954 100644
--- a/scd/ccid-driver.c
+++ b/scd/ccid-driver.c
@@ -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
extended APDU T=1 block the maximum length 65544; however
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. */
msg[0] = PC_to_RDR_XfrBlock;
diff --git a/sm/call-agent.c b/sm/call-agent.c
index acf6c04ad..f99caade4 100644
--- a/sm/call-agent.c
+++ b/sm/call-agent.c
@@ -138,7 +138,7 @@ default_inq_cb (void *opaque, const char *line)
gpg_error_t err;
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);
if (err)
@@ -315,7 +315,7 @@ inq_ciphertext_cb (void *opaque, const char *line)
struct cipher_parm_s *parm = opaque;
int rc;
- if (!strncmp (line, "CIPHERTEXT", 10) && (line[10]==' '||!line[10]))
+ if (has_leading_keyword (line, "CIPHERTEXT"))
{
assuan_begin_confidential (parm->ctx);
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;
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);
}
@@ -693,14 +693,14 @@ static gpg_error_t
istrusted_status_cb (void *opaque, const char *line)
{
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++)
- ;
- if (!strncmp (line, "relax", 5) && (line[5] == ' ' || !line[5]))
+ line = s;
+ if (has_leading_keyword (line, "relax"))
flags->relax = 1;
- else if (!strncmp (line, "cm", 2) && (line[2] == ' ' || !line[2]))
+ else if (has_leading_keyword (line, "cm"))
flags->chain_model = 1;
}
return 0;
@@ -824,14 +824,14 @@ static gpg_error_t
learn_status_cb (void *opaque, const char *line)
{
struct learn_parm_s *parm = opaque;
+ const char *s;
/* 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)
{
- for (line += 8; *line == ' '; line++)
- ;
if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line))
return gpg_error (GPG_ERR_ASS_CANCELED);
}
@@ -1017,9 +1017,9 @@ keyinfo_status_cb (void *opaque, const char *line)
char **serialno = opaque;
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])
{
s += 3;
@@ -1172,7 +1172,7 @@ inq_import_key_parms (void *opaque, const char *line)
struct import_key_parm_s *parm = opaque;
gpg_error_t err;
- if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
+ if (has_leading_keyword (line, "KEYDATA"))
{
assuan_begin_confidential (parm->ctx);
err = assuan_send_data (parm->ctx, parm->key, parm->keylen);
diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c
index b7417a368..99a14c0e7 100644
--- a/sm/call-dirmngr.c
+++ b/sm/call-dirmngr.c
@@ -282,47 +282,40 @@ static gpg_error_t
inq_certificate (void *opaque, const char *line)
{
struct inq_certificate_parm_s *parm = opaque;
+ const char *s;
int rc;
+ size_t n;
const unsigned char *der;
size_t derlen;
int issuer_mode = 0;
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. */
- line += 12;
- while (*line == ' ')
- line++;
+ line = s;
ski = make_simple_sexp_from_hexstr (line, &n);
line += n;
while (*line == ' ')
line++;
}
- else if (!strncmp (line, "SENDISSUERCERT", 14)
- && (line[14] == ' ' || !line[14]))
+ else if ((s = has_leading_keyword (line, "SENDISSUERCERT")))
{
- line += 14;
+ line = s;
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
root certificate. */
- const char *s;
- size_t n;
char fpr[41];
struct rootca_flags_s rootca_flags;
- line += 9;
- while (*line == ' ')
- line++;
+ line = s;
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)
{
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)
{
- for (line += 8; *line == ' '; line++)
- ;
+ line = s;
if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line))
return gpg_error (GPG_ERR_ASS_CANCELED);
}
}
- else if (!strncmp (line, "ONLY_VALID_IF_CERT_VALID", 24)
- && (line[24]==' ' || !line[24]))
+ else if ((s = has_leading_keyword (line, "ONLY_VALID_IF_CERT_VALID")))
{
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. */
}
return 0;
@@ -693,23 +685,22 @@ static gpg_error_t
lookup_status_cb (void *opaque, const char *line)
{
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)
{
- for (line += 8; *line == ' '; line++)
- ;
+ line = s;
if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line))
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)
{
- for (line +=9; *line == ' '; line++)
- ;
+ line = s;
gpgsm_status (parm->ctrl, STATUS_TRUNCATED, line);
}
}
@@ -878,16 +869,17 @@ static gpg_error_t
run_command_inq_cb (void *opaque, const char *line)
{
struct run_command_parm_s *parm = opaque;
+ const char *s;
int rc = 0;
- if ( !strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]) )
+ if ((s = has_leading_keyword (line, "SENDCERT")))
{ /* send the given certificate */
int err;
ksba_cert_t cert;
const unsigned char *der;
size_t derlen;
- line += 8;
+ line = s;
if (!*line)
return gpg_error (GPG_ERR_ASS_PARAMETER);
@@ -907,9 +899,9 @@ run_command_inq_cb (void *opaque, const char *line)
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. */
- line += 9;
+ line = s;
log_info ("dirmngr: %s\n", line);
}
else
@@ -925,17 +917,17 @@ static gpg_error_t
run_command_status_cb (void *opaque, const char *line)
{
ctrl_t ctrl = opaque;
+ const char *s;
if (opt.verbose)
{
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)
{
- for (line += 8; *line == ' '; line++)
- ;
+ line = s;
if (gpgsm_status (ctrl, STATUS_PROGRESS, line))
return gpg_error (GPG_ERR_ASS_CANCELED);
}
diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c
index 9dbddeee9..0b3c9c0e7 100644
--- a/tools/gpgconf-comp.c
+++ b/tools/gpgconf-comp.c
@@ -3382,7 +3382,6 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
int in_rule = 0;
int got_match = 0;
int runtime[GC_BACKEND_NR];
- int used_components[GC_COMPONENT_NR];
int backend_id, component_id;
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++)
runtime[backend_id] = 0;
- for (component_id = 0; component_id < GC_COMPONENT_NR; component_id++)
- used_components[component_id] = 0;
config = fopen (fname, "r");
if (!config)
@@ -3621,9 +3618,6 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int 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. */
if (newflags)
{