[svn] GnuPG - r4292 - trunk/agent
svn author wk
cvs at cvs.gnupg.org
Fri Oct 6 12:58:19 CEST 2006
Author: wk
Date: 2006-10-06 12:58:18 +0200 (Fri, 06 Oct 2006)
New Revision: 4292
Modified:
trunk/agent/ChangeLog
trunk/agent/agent.h
trunk/agent/command.c
trunk/agent/divert-scd.c
trunk/agent/pksign.c
Log:
Add TLS hash mode
Modified: trunk/agent/ChangeLog
===================================================================
--- trunk/agent/ChangeLog 2006-10-06 05:57:52 UTC (rev 4291)
+++ trunk/agent/ChangeLog 2006-10-06 10:58:18 UTC (rev 4292)
@@ -1,5 +1,12 @@
2006-10-05 Werner Koch <wk at g10code.com>
+ * command.c (has_option_name): New.
+ (cmd_sethash): New --hash option.
+ * pksign.c (do_encode_raw_pkcs1): New.
+ (agent_pksign_do): Use it here for the TLS algo.
+ * agent.h (GCRY_MD_USER_TLS_MD5SHA1): New.
+ * divert-scd.c (pksign): Add case for tls-md5sha1.
+
* divert-scd.c (encode_md_for_card): Check that the algo is valid.
2006-10-04 Werner Koch <wk at g10code.com>
Modified: trunk/agent/agent.h
===================================================================
--- trunk/agent/agent.h 2006-10-06 05:57:52 UTC (rev 4291)
+++ trunk/agent/agent.h 2006-10-06 10:58:18 UTC (rev 4292)
@@ -36,8 +36,15 @@
#include "../common/errors.h"
#include "membuf.h"
+/* To convey some special hash algorithms we use algorithm numbers
+ reserved for application use. */
+#ifndef GCRY_MD_USER
+#define GCRY_MD_USER 1024
+#endif
+#define GCRY_MD_USER_TLS_MD5SHA1 (GCRY_MD_USER+1)
-#define MAX_DIGEST_LEN 24
+/* Maximum length of a digest. */
+#define MAX_DIGEST_LEN 36
/* A large struct name "opt" to keep global flags */
struct
Modified: trunk/agent/command.c
===================================================================
--- trunk/agent/command.c 2006-10-06 05:57:52 UTC (rev 4291)
+++ trunk/agent/command.c 2006-10-06 10:58:18 UTC (rev 4292)
@@ -136,6 +136,21 @@
return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
}
+/* Same as has_option but does only test for the name of the option
+ and ignores an argument, i.e. with NAME being "--hash" it would
+ return true for "--hash" as well as for "--hash=foo". */
+static int
+has_option_name (const char *line, const char *name)
+{
+ const char *s;
+ int n = strlen (name);
+
+ s = strstr (line, name);
+ return (s && (s == line || spacep (s-1))
+ && (!s[n] || spacep (s+n) || s[n] == '='));
+}
+
+
/* Skip over options. It is assumed that leading spaces have been
removed (this is the case for lines passed to a handler from
assuan). Bkanls after the options are also removed. */
@@ -455,7 +470,7 @@
}
-/* SETHASH <algonumber> <hexstring>
+/* SETHASH --hash=<name>|<algonumber> <hexstring>
The client can use this command to tell the server about the data
(which usually is a hash) to be signed. */
@@ -470,12 +485,37 @@
char *endp;
int algo;
- /* Parse the algo number and check it. */
- algo = (int)strtoul (line, &endp, 10);
- for (line = endp; *line == ' ' || *line == '\t'; line++)
- ;
- if (!algo || gcry_md_test_algo (algo))
- return set_error (GPG_ERR_UNSUPPORTED_ALGORITHM, NULL);
+ /* Parse the alternative hash options which may be used instead of
+ the algo number. */
+ if (has_option_name (line, "--hash"))
+ {
+ if (has_option (line, "--hash=sha1"))
+ algo = GCRY_MD_SHA1;
+ else if (has_option (line, "--hash=sha256"))
+ algo = GCRY_MD_SHA256;
+ else if (has_option (line, "--hash=rmd160"))
+ algo = GCRY_MD_RMD160;
+ else if (has_option (line, "--hash=md5"))
+ algo = GCRY_MD_MD5;
+ else if (has_option (line, "--hash=tls-md5sha1"))
+ algo = GCRY_MD_USER_TLS_MD5SHA1;
+ else
+ return set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
+ }
+ else
+ algo = 0;
+
+ line = skip_options (line);
+
+ if (!algo)
+ {
+ /* No hash option has been given: require an algo number instead */
+ algo = (int)strtoul (line, &endp, 10);
+ for (line = endp; *line == ' ' || *line == '\t'; line++)
+ ;
+ if (!algo || gcry_md_test_algo (algo))
+ return set_error (GPG_ERR_UNSUPPORTED_ALGORITHM, NULL);
+ }
ctrl->digest.algo = algo;
/* Parse the hash value. */
@@ -483,8 +523,11 @@
if (rc)
return rc;
n /= 2;
- if (n != 16 && n != 20 && n != 24 && n != 32)
+ if (algo == GCRY_MD_USER_TLS_MD5SHA1 && n == 36)
+ ;
+ else if (n != 16 && n != 20 && n != 24 && n != 32)
return set_error (GPG_ERR_ASS_PARAMETER, "unsupported length of hash");
+
if (n > MAX_DIGEST_LEN)
return set_error (GPG_ERR_ASS_PARAMETER, "hash value to long");
Modified: trunk/agent/divert-scd.c
===================================================================
--- trunk/agent/divert-scd.c 2006-10-06 05:57:52 UTC (rev 4291)
+++ trunk/agent/divert-scd.c 2006-10-06 10:58:18 UTC (rev 4292)
@@ -318,26 +318,36 @@
int rc;
char *kid;
size_t siglen;
- unsigned char *sigval;
- unsigned char *data;
- size_t ndata;
+ unsigned char *sigval = NULL;
rc = ask_for_card (ctrl, shadow_info, &kid);
if (rc)
return rc;
- rc = encode_md_for_card (digest, digestlen, algo,
- &data, &ndata);
- if (rc)
- return rc;
+ if (algo == GCRY_MD_USER_TLS_MD5SHA1)
+ {
+ rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl,
+ digest, digestlen, &sigval, &siglen);
+ }
+ else
+ {
+ unsigned char *data;
+ size_t ndata;
- rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl,
- data, ndata, &sigval, &siglen);
+ rc = encode_md_for_card (digest, digestlen, algo, &data, &ndata);
+ if (!rc)
+ {
+ rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl,
+ data, ndata, &sigval, &siglen);
+ xfree (data);
+ }
+ }
+
if (!rc)
*r_sig = sigval;
- xfree (data);
+
xfree (kid);
-
+
return rc;
}
Modified: trunk/agent/pksign.c
===================================================================
--- trunk/agent/pksign.c 2006-10-06 05:57:52 UTC (rev 4291)
+++ trunk/agent/pksign.c 2006-10-06 10:58:18 UTC (rev 4292)
@@ -39,7 +39,7 @@
gcry_sexp_t hash;
int rc;
- if (! raw_value)
+ if (!raw_value)
{
const char *s;
char tmp[16+1];
@@ -55,7 +55,7 @@
rc = gcry_sexp_build (&hash, NULL,
"(data (flags pkcs1) (hash %s %b))",
- tmp, mdlen, md);
+ tmp, (int)mdlen, md);
}
else
{
@@ -77,6 +77,55 @@
}
+/* Special version of do_encode_md to take care of pckcs#1 padding.
+ For TLS-MD5SHA1 we need to do the padding ourself as Libgrypt does
+ not know about this special scheme. Fixme: We should have a
+ pkcs1-only-padding flag for Libgcrypt. */
+static int
+do_encode_raw_pkcs1 (const byte *md, size_t mdlen, unsigned int nbits,
+ gcry_sexp_t *r_hash)
+{
+ int rc;
+ gcry_sexp_t hash;
+ unsigned char *frame;
+ size_t i, n, nframe;
+
+ nframe = (nbits+7) / 8;
+ if ( !mdlen || mdlen + 8 + 4 > nframe )
+ {
+ /* Can't encode this hash into a frame of size NFRAME. */
+ return gpg_error (GPG_ERR_TOO_SHORT);
+ }
+
+ frame = xtrymalloc (nframe);
+ if (!frame)
+ return gpg_error_from_syserror ();
+
+ /* Assemble the pkcs#1 block type 1. */
+ n = 0;
+ frame[n++] = 0;
+ frame[n++] = 1; /* Block type. */
+ i = nframe - mdlen - 3 ;
+ assert (i >= 8); /* At least 8 bytes of padding. */
+ memset (frame+n, 0xff, i );
+ n += i;
+ frame[n++] = 0;
+ memcpy (frame+n, md, mdlen );
+ n += mdlen;
+ assert (n == nframe);
+
+ /* Create the S-expression. */
+ rc = gcry_sexp_build (&hash, NULL,
+ "(data (flags raw) (value %b))",
+ (int)nframe, frame);
+ xfree (frame);
+
+ *r_hash = hash;
+ return rc;
+}
+
+
+
/* SIGN whatever information we have accumulated in CTRL and return
the signature S-Expression. */
int
@@ -133,12 +182,18 @@
gcry_sexp_t s_hash = NULL;
- /* put the hash into a sexp */
- rc = do_encode_md (ctrl->digest.value,
- ctrl->digest.valuelen,
- ctrl->digest.algo,
- &s_hash,
- ctrl->digest.raw_value);
+ /* Put the hash into a sexp */
+ if (ctrl->digest.algo == GCRY_MD_USER_TLS_MD5SHA1)
+ rc = do_encode_raw_pkcs1 (ctrl->digest.value,
+ ctrl->digest.valuelen,
+ gcry_pk_get_nbits (s_skey),
+ &s_hash);
+ else
+ rc = do_encode_md (ctrl->digest.value,
+ ctrl->digest.valuelen,
+ ctrl->digest.algo,
+ &s_hash,
+ ctrl->digest.raw_value);
if (rc)
goto leave;
More information about the Gnupg-commits
mailing list