summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS4
-rw-r--r--agent/command.c2
-rw-r--r--configure.ac4
-rw-r--r--scd/ChangeLog4
-rw-r--r--scd/app-openpgp.c22
-rw-r--r--sm/ChangeLog7
-rw-r--r--sm/call-agent.c88
-rw-r--r--sm/certreqgen.c74
-rw-r--r--sm/gpgsm.h5
-rw-r--r--tools/ChangeLog4
-rwxr-xr-xtools/gpgsm-gencert.sh36
11 files changed, 211 insertions, 39 deletions
diff --git a/NEWS b/NEWS
index e1798d6a0..aaca93680 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,7 @@
+Noteworthy changes in version 1.9.93
+-------------------------------------------------
+
+
Noteworthy changes in version 1.9.92 (2006-10-11)
-------------------------------------------------
diff --git a/agent/command.c b/agent/command.c
index a2634f7d5..cebbf9a2f 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -236,7 +236,7 @@ parse_hexstring (assuan_context_t ctx, const char *string, size_t *len)
}
/* Parse the keygrip in STRING into the provided buffer BUF. BUF must
- provide space for 20 bytes. BUF is not changed if the fucntions
+ provide space for 20 bytes. BUF is not changed if the function
returns an error. */
static int
parse_keygrip (assuan_context_t ctx, const char *string, unsigned char *buf)
diff --git a/configure.ac b/configure.ac
index 7c2bf75c1..f93ab7260 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,8 +26,8 @@ min_automake_version="1.9.3"
# Remember to change the version number immediately *after* a release.
# Set my_issvn to "yes" for non-released code. Remember to run an
# "svn up" and "autogen.sh" right before creating a distribution.
-m4_define([my_version], [1.9.92])
-m4_define([my_issvn], [no])
+m4_define([my_version], [1.9.93])
+m4_define([my_issvn], [yes])
m4_define([svn_revision], m4_esyscmd([echo -n $((svn info 2>/dev/null \
diff --git a/scd/ChangeLog b/scd/ChangeLog
index 9f6a0f5c5..41a89b8b7 100644
--- a/scd/ChangeLog
+++ b/scd/ChangeLog
@@ -1,3 +1,7 @@
+2006-10-11 Werner Koch <wk@g10code.com>
+
+ * app-openpgp.c (do_sign): Redirect to do_auth for OpenPGP.3.
+
2006-10-06 Werner Koch <wk@g10code.com>
* Makefile.am (AM_CFLAGS): Use PTH version of libassuan.
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 4de465ee1..466f37c57 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -142,6 +142,11 @@ struct app_local_s {
static unsigned long convert_sig_counter_value (const unsigned char *value,
size_t valuelen);
static unsigned long get_sig_counter (app_t app);
+static gpg_error_t do_auth (app_t app, const char *keyidstr,
+ gpg_error_t (*pincb)(void*, const char *, char **),
+ void *pincb_arg,
+ const void *indata, size_t indatalen,
+ unsigned char **outdata, size_t *outdatalen);
@@ -2088,7 +2093,11 @@ check_against_given_fingerprint (app_t app, const char *fpr, int keyno)
Note that this function may return the error code
GPG_ERR_WRONG_CARD to indicate that the card currently present does
not match the one required for the requested action (e.g. the
- serial number does not match). */
+ serial number does not match).
+
+ As a special feature a KEYIDSTR of "OPENPGP.3" redirects the
+ operation to the auth command.
+*/
static gpg_error_t
do_sign (app_t app, const char *keyidstr, int hashalgo,
gpg_error_t (*pincb)(void*, const char *, char **),
@@ -2109,6 +2118,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
int n;
const char *fpr = NULL;
unsigned long sigcount;
+ int use_auth = 0;
if (!keyidstr || !*keyidstr)
return gpg_error (GPG_ERR_INV_VALUE);
@@ -2136,6 +2146,8 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
/* Check whether an OpenPGP card of any version has been requested. */
if (!strcmp (keyidstr, "OPENPGP.1"))
;
+ else if (!strcmp (keyidstr, "OPENPGP.3"))
+ use_auth = 1;
else if (strlen (keyidstr) < 32 || strncmp (keyidstr, "D27600012401", 12))
return gpg_error (GPG_ERR_INV_ID);
else
@@ -2178,6 +2190,14 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
memcpy (data+15, indata, indatalen);
+ if (use_auth)
+ {
+ /* This is a hack to redirect to the internal authenticate command. */
+ return do_auth (app, "OPENPGP.3", pincb, pincb_arg,
+ data, 35,
+ outdata, outdatalen);
+ }
+
sigcount = get_sig_counter (app);
log_info (_("signatures created so far: %lu\n"), sigcount);
diff --git a/sm/ChangeLog b/sm/ChangeLog
index 74c5c4302..8bf306e54 100644
--- a/sm/ChangeLog
+++ b/sm/ChangeLog
@@ -1,3 +1,10 @@
+2006-10-11 Werner Koch <wk@g10code.com>
+
+ * certreqgen.c (proc_parameters, create_request): Allow for
+ creation directly from a card.
+ * call-agent.c (gpgsm_agent_readkey): New arg FROMCARD.
+ (gpgsm_scd_pksign): New.
+
2006-10-06 Werner Koch <wk@g10code.com>
* Makefile.am (AM_CFLAGS): Use PTH version of libassuan.
diff --git a/sm/call-agent.c b/sm/call-agent.c
index 35ad1b83b..47f53041d 100644
--- a/sm/call-agent.c
+++ b/sm/call-agent.c
@@ -271,6 +271,84 @@ gpgsm_agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc,
}
+/* Call the scdaemon to do a sign operation using the key identified by
+ the hex string KEYID. */
+int
+gpgsm_scd_pksign (ctrl_t ctrl, const char *keyid, const char *desc,
+ unsigned char *digest, size_t digestlen, int digestalgo,
+ unsigned char **r_buf, size_t *r_buflen )
+{
+ int rc, i;
+ char *p, line[ASSUAN_LINELENGTH];
+ membuf_t data;
+ size_t len;
+ const char *hashopt;
+ unsigned char *sigbuf;
+ size_t sigbuflen;
+
+ *r_buf = NULL;
+
+ switch(digestalgo)
+ {
+ case GCRY_MD_SHA1: hashopt = "--hash=sha1"; break;
+ case GCRY_MD_RMD160:hashopt = "--hash=rmd160"; break;
+ case GCRY_MD_MD5: hashopt = "--hash=md5"; break;
+ case GCRY_MD_SHA256:hashopt = "--hash=sha256"; break;
+ default:
+ return gpg_error (GPG_ERR_DIGEST_ALGO);
+ }
+
+ rc = start_agent (ctrl);
+ if (rc)
+ return rc;
+
+ if (digestlen*2 + 50 > DIM(line))
+ return gpg_error (GPG_ERR_GENERAL);
+
+ p = stpcpy (line, "SCD SETDATA " );
+ for (i=0; i < digestlen ; i++, p += 2 )
+ sprintf (p, "%02X", digest[i]);
+ rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
+ if (rc)
+ return rc;
+
+ init_membuf (&data, 1024);
+
+ snprintf (line, DIM(line)-1, "SCD PKSIGN %s %s", hashopt, keyid);
+ line[DIM(line)-1] = 0;
+ rc = assuan_transact (agent_ctx, line,
+ membuf_data_cb, &data, NULL, NULL, NULL, NULL);
+ if (rc)
+ {
+ xfree (get_membuf (&data, &len));
+ return 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)))" Fixme: If a card ever
+ creates non-RSA keys we need to change things. */
+ *r_buflen = 21 + 11 + sigbuflen + 4;
+ p = xtrymalloc (*r_buflen);
+ *r_buf = (unsigned char*)p;
+ if (!p)
+ {
+ xfree (sigbuf);
+ return 0;
+ }
+ p = stpcpy (p, "(7:sig-val(3:rsa(1:s" );
+ sprintf (p, "%u:", (unsigned int)sigbuflen);
+ p += strlen (p);
+ memcpy (p, sigbuf, sigbuflen);
+ p += sigbuflen;
+ strcpy (p, ")))");
+ xfree (sigbuf);
+
+ assert (gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL));
+ return 0;
+}
+
+
/* Handle a CIPHERTEXT inquiry. Note, we only send the data,
@@ -449,9 +527,12 @@ gpgsm_agent_genkey (ctrl_t ctrl,
}
-/* Call the agent to read the public key part for a given keygrip. */
+/* Call the agent to read the public key part for a given keygrip. If
+ FROMCARD is true, the key is directly read from the current
+ smartcard. In this case HEXKEYGRIP should be the keyID
+ (e.g. OPENPGP.3). */
int
-gpgsm_agent_readkey (ctrl_t ctrl, const char *hexkeygrip,
+gpgsm_agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
ksba_sexp_t *r_pubkey)
{
int rc;
@@ -469,7 +550,8 @@ gpgsm_agent_readkey (ctrl_t ctrl, const char *hexkeygrip,
if (rc)
return rc;
- snprintf (line, DIM(line)-1, "READKEY %s", hexkeygrip);
+ snprintf (line, DIM(line)-1, "%sREADKEY %s",
+ fromcard? "SCD ":"", hexkeygrip);
line[DIM(line)-1] = 0;
init_membuf (&data, 1024);
diff --git a/sm/certreqgen.c b/sm/certreqgen.c
index e1006753e..f0221d3fd 100644
--- a/sm/certreqgen.c
+++ b/sm/certreqgen.c
@@ -148,6 +148,7 @@ static int proc_parameters (ctrl_t ctrl,
struct reqgen_ctrl_s *outctrl);
static int create_request (ctrl_t ctrl,
struct para_data_s *para,
+ const char *carddirect,
ksba_const_sexp_t public,
struct reqgen_ctrl_s *outctrl);
@@ -452,15 +453,24 @@ proc_parameters (ctrl_t ctrl,
ksba_sexp_t public;
int seq;
size_t erroff, errlen;
+ char *cardkeyid = NULL;
/* Check that we have all required parameters; */
assert (get_parameter (para, pKEYTYPE, 0));
- /* We can only use RSA for now. There is a with pkcs-10 on how to
- use ElGamal because it is expected that a PK algorithm can always
- be used for signing. */
+ /* We can only use RSA for now. There is a problem with pkcs-10 on
+ how to use ElGamal because it is expected that a PK algorithm can
+ always be used for signing. Another problem is that on-card
+ generated encryption keys may not be used for signing. */
i = get_parameter_algo (para, pKEYTYPE);
- if (i < 1 || i != GCRY_PK_RSA )
+ if (!i && (s = get_parameter_value (para, pKEYTYPE, 0)) && *s)
+ {
+ /* Hack to allow creation of certificates directly from a smart
+ card. For example: "Key-Type: card:OPENPGP.3". */
+ if (!strncmp (s, "card:", 5) && s[5])
+ cardkeyid = xtrystrdup (s+5);
+ }
+ if ( (i < 1 || i != GCRY_PK_RSA) && !cardkeyid )
{
r = get_parameter (para, pKEYTYPE, 0);
log_error (_("line %d: invalid algorithm\n"), r->lnr);
@@ -472,18 +482,22 @@ proc_parameters (ctrl_t ctrl,
nbits = 1024;
else
nbits = get_parameter_uint (para, pKEYLENGTH);
- if (nbits < 1024 || nbits > 4096)
+ if ((nbits < 1024 || nbits > 4096) && !cardkeyid)
{
/* The BSI specs dated 2002-11-25 don't allow lengths below 1024. */
r = get_parameter (para, pKEYLENGTH, 0);
log_error (_("line %d: invalid key length %u (valid are %d to %d)\n"),
r->lnr, nbits, 1024, 4096);
+ xfree (cardkeyid);
return gpg_error (GPG_ERR_INV_PARAMETER);
}
/* Check the usage. */
if (parse_parameter_usage (para, pKEYUSAGE))
- return gpg_error (GPG_ERR_INV_PARAMETER);
+ {
+ xfree (cardkeyid);
+ return gpg_error (GPG_ERR_INV_PARAMETER);
+ }
/* Check that there is a subject name and that this DN fits our
requirements. */
@@ -491,6 +505,7 @@ proc_parameters (ctrl_t ctrl,
{
r = get_parameter (para, pNAMEDN, 0);
log_error (_("line %d: no subject name given\n"), r->lnr);
+ xfree (cardkeyid);
return gpg_error (GPG_ERR_INV_PARAMETER);
}
err = ksba_dn_teststr (s, 0, &erroff, &errlen);
@@ -504,6 +519,7 @@ proc_parameters (ctrl_t ctrl,
log_error (_("line %d: invalid subject name `%s' at pos %d\n"),
r->lnr, s, erroff);
+ xfree (cardkeyid);
return gpg_error (GPG_ERR_INV_PARAMETER);
}
@@ -518,19 +534,32 @@ proc_parameters (ctrl_t ctrl,
{
r = get_parameter (para, pNAMEEMAIL, seq);
log_error (_("line %d: not a valid email address\n"), r->lnr);
+ xfree (cardkeyid);
return gpg_error (GPG_ERR_INV_PARAMETER);
}
}
- s = get_parameter_value (para, pKEYGRIP, 0);
- if (s) /* Use existing key. */
+ if (cardkeyid) /* Take the key from the current smart card. */
{
- rc = gpgsm_agent_readkey (ctrl, s, &public);
+ rc = gpgsm_agent_readkey (ctrl, 1, cardkeyid, &public);
+ if (rc)
+ {
+ r = get_parameter (para, pKEYTYPE, 0);
+ log_error (_("line %d: error reading key `%s' from card: %s\n"),
+ r->lnr, cardkeyid, gpg_strerror (rc));
+ xfree (cardkeyid);
+ return rc;
+ }
+ }
+ else if ((s=get_parameter_value (para, pKEYGRIP, 0))) /* Use existing key.*/
+ {
+ rc = gpgsm_agent_readkey (ctrl, 0, s, &public);
if (rc)
{
r = get_parameter (para, pKEYTYPE, 0);
log_error (_("line %d: error getting key by keygrip `%s': %s\n"),
r->lnr, s, gpg_strerror (rc));
+ xfree (cardkeyid);
return rc;
}
}
@@ -546,12 +575,14 @@ proc_parameters (ctrl_t ctrl,
r = get_parameter (para, pKEYTYPE, 0);
log_error (_("line %d: key generation failed: %s\n"),
r->lnr, gpg_strerror (rc));
+ xfree (cardkeyid);
return rc;
}
}
- rc = create_request (ctrl, para, public, outctrl);
+ rc = create_request (ctrl, para, cardkeyid, public, outctrl);
xfree (public);
+ xfree (cardkeyid);
return rc;
}
@@ -560,8 +591,10 @@ proc_parameters (ctrl_t ctrl,
/* Parameters are checked, the key pair has been created. Now
generate the request and write it out */
static int
-create_request (ctrl_t ctrl,
- struct para_data_s *para, ksba_const_sexp_t public,
+create_request (ctrl_t ctrl,
+ struct para_data_s *para,
+ const char *carddirect,
+ ksba_const_sexp_t public,
struct reqgen_ctrl_s *outctrl)
{
ksba_certreq_t cr;
@@ -758,11 +791,18 @@ create_request (ctrl_t ctrl,
for (n=0; n < 20; n++)
sprintf (hexgrip+n*2, "%02X", grip[n]);
- rc = gpgsm_agent_pksign (ctrl, hexgrip, NULL,
- gcry_md_read(md, GCRY_MD_SHA1),
- gcry_md_get_algo_dlen (GCRY_MD_SHA1),
- GCRY_MD_SHA1,
- &sigval, &siglen);
+ if (carddirect)
+ rc = gpgsm_scd_pksign (ctrl, carddirect, NULL,
+ gcry_md_read(md, GCRY_MD_SHA1),
+ gcry_md_get_algo_dlen (GCRY_MD_SHA1),
+ GCRY_MD_SHA1,
+ &sigval, &siglen);
+ else
+ rc = gpgsm_agent_pksign (ctrl, hexgrip, NULL,
+ gcry_md_read(md, GCRY_MD_SHA1),
+ gcry_md_get_algo_dlen (GCRY_MD_SHA1),
+ GCRY_MD_SHA1,
+ &sigval, &siglen);
if (rc)
{
log_error ("signing failed: %s\n", gpg_strerror (rc));
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
index 541783dd7..d92bf5923 100644
--- a/sm/gpgsm.h
+++ b/sm/gpgsm.h
@@ -322,12 +322,15 @@ int gpgsm_agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc,
size_t digestlen,
int digestalgo,
unsigned char **r_buf, size_t *r_buflen);
+int gpgsm_scd_pksign (ctrl_t ctrl, const char *keyid, const char *desc,
+ unsigned char *digest, size_t digestlen, int digestalgo,
+ unsigned char **r_buf, size_t *r_buflen);
int gpgsm_agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
ksba_const_sexp_t ciphertext,
char **r_buf, size_t *r_buflen);
int gpgsm_agent_genkey (ctrl_t ctrl,
ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey);
-int gpgsm_agent_readkey (ctrl_t ctrl, const char *hexkeygrip,
+int gpgsm_agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
ksba_sexp_t *r_pubkey);
int gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert,
struct rootca_flags_s *rootca_flags);
diff --git a/tools/ChangeLog b/tools/ChangeLog
index de22a2ec6..5ed381049 100644
--- a/tools/ChangeLog
+++ b/tools/ChangeLog
@@ -1,3 +1,7 @@
+2006-10-11 Werner Koch <wk@g10code.com>
+
+ * gpgsm-gencert.sh: Allow generation of card keys.
+
2006-10-08 Werner Koch <wk@g10code.com>
* Makefile.am (gpgkey2ssh_LDADD): Add LIBINTL. Suggested by
diff --git a/tools/gpgsm-gencert.sh b/tools/gpgsm-gencert.sh
index 3949f2361..19e961f03 100755
--- a/tools/gpgsm-gencert.sh
+++ b/tools/gpgsm-gencert.sh
@@ -84,19 +84,27 @@ query_user_menu()
echo "You selected: $ANSWER" >&2
}
-query_user_menu "Key type" "RSA" "existing key"
-if [ "$ANSWER" = "existing key" ]; then
- # User requested to use an existing key; need to set some dummy defaults
- KEY_TYPE=RSA
- KEY_LENGTH=1024
- query_user "Keygrip "
- KEY_GRIP=$ANSWER
-else
- KEY_TYPE=$ANSWER
- query_user_menu "Key length" "1024" "2048"
- KEY_LENGTH=$ANSWER
- KEY_GRIP=
-fi
+query_user_menu "Key type" "RSA" "existing key" "OPENPGP.1" "OPENPGP.3"
+case "$ANSWER" in
+ RSA)
+ KEY_TYPE=$ANSWER
+ query_user_menu "Key length" "1024" "2048"
+ KEY_LENGTH=$ANSWER
+ KEY_GRIP=
+ ;;
+ existing*)
+ # User requested to use an existing key; need to set some dummy defaults
+ KEY_TYPE=RSA
+ KEY_LENGTH=1024
+ query_user "Keygrip "
+ KEY_GRIP=$ANSWER
+ ;;
+ *)
+ KEY_TYPE="card:$ANSWER"
+ KEY_LENGTH=
+ KEY_GRIP=
+ ;;
+esac
query_user_menu "Key usage" "sign, encrypt" "sign" "encrypt"
@@ -162,7 +170,7 @@ query_user_menu "Really create such a CSR?" "yes" "no"
echo -e "$ASSUAN_COMMANDS" | \
- gpgsm --no-log-file --debug-level none --debug-none \
+ gpgsm --no-log-file --debug-level none --debug-none \
--server 4< "$file_parameter" 5>"$outfile" >/dev/null
cat "$outfile"