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 /* We need this for the memory function protos. */ #include /* We need errno. */ #include /* 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]; }; @@ -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); 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) {