mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-21 10:09:57 +01:00
Merge branch 'master' into key-storage-work
--
This commit is contained in:
commit
eaa6dc3a8b
4
.gitignore
vendored
4
.gitignore
vendored
@ -154,7 +154,5 @@ tools/mk-tdata
|
||||
tools/symcryptrun
|
||||
tools/watchgnupg
|
||||
tools/gpgtar
|
||||
|
||||
|
||||
private-keys-v1.d/
|
||||
x.parm
|
||||
private-keys-v1.d/
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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++)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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. */
|
||||
|
18
g13/g13.c
18
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. */
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
};
|
||||
|
||||
|
||||
@ -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
|
||||
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;
|
||||
}
|
||||
|
||||
/* Prepend numbers with a 0 if needed. */
|
||||
if (mlen && (*m & 0x80))
|
||||
{
|
||||
mbuf = xtrymalloc ( mlen + 1);
|
||||
if (!mbuf)
|
||||
m = find_tlv (keydata, keydatalen, 0x0081, &mlen);
|
||||
if (!m)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
err = gpg_error (GPG_ERR_CARD);
|
||||
log_error (_("response does not contain the RSA modulus\n"));
|
||||
goto leave;
|
||||
}
|
||||
*mbuf = 0;
|
||||
memcpy (mbuf+1, m, mlen);
|
||||
mlen++;
|
||||
m = mbuf;
|
||||
}
|
||||
if (elen && (*e & 0x80))
|
||||
{
|
||||
ebuf = xtrymalloc ( elen + 1);
|
||||
if (!ebuf)
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
*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);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user