mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-21 14:47:03 +01:00
Add TLS hash mode
This commit is contained in:
parent
ae390ea0a2
commit
5134fc27b3
@ -1,5 +1,12 @@
|
|||||||
2006-10-05 Werner Koch <wk@g10code.com>
|
2006-10-05 Werner Koch <wk@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.
|
* divert-scd.c (encode_md_for_card): Check that the algo is valid.
|
||||||
|
|
||||||
2006-10-04 Werner Koch <wk@g10code.com>
|
2006-10-04 Werner Koch <wk@g10code.com>
|
||||||
|
@ -36,8 +36,15 @@
|
|||||||
#include "../common/errors.h"
|
#include "../common/errors.h"
|
||||||
#include "membuf.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 */
|
/* A large struct name "opt" to keep global flags */
|
||||||
struct
|
struct
|
||||||
|
@ -136,6 +136,21 @@ has_option (const char *line, const char *name)
|
|||||||
return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
|
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
|
/* Skip over options. It is assumed that leading spaces have been
|
||||||
removed (this is the case for lines passed to a handler from
|
removed (this is the case for lines passed to a handler from
|
||||||
assuan). Bkanls after the options are also removed. */
|
assuan). Bkanls after the options are also removed. */
|
||||||
@ -455,7 +470,7 @@ cmd_setkeydesc (assuan_context_t ctx, char *line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* SETHASH <algonumber> <hexstring>
|
/* SETHASH --hash=<name>|<algonumber> <hexstring>
|
||||||
|
|
||||||
The client can use this command to tell the server about the data
|
The client can use this command to tell the server about the data
|
||||||
(which usually is a hash) to be signed. */
|
(which usually is a hash) to be signed. */
|
||||||
@ -470,12 +485,37 @@ cmd_sethash (assuan_context_t ctx, char *line)
|
|||||||
char *endp;
|
char *endp;
|
||||||
int algo;
|
int algo;
|
||||||
|
|
||||||
/* Parse the algo number and check it. */
|
/* Parse the alternative hash options which may be used instead of
|
||||||
algo = (int)strtoul (line, &endp, 10);
|
the algo number. */
|
||||||
for (line = endp; *line == ' ' || *line == '\t'; line++)
|
if (has_option_name (line, "--hash"))
|
||||||
;
|
{
|
||||||
if (!algo || gcry_md_test_algo (algo))
|
if (has_option (line, "--hash=sha1"))
|
||||||
return set_error (GPG_ERR_UNSUPPORTED_ALGORITHM, NULL);
|
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;
|
ctrl->digest.algo = algo;
|
||||||
|
|
||||||
/* Parse the hash value. */
|
/* Parse the hash value. */
|
||||||
@ -483,8 +523,11 @@ cmd_sethash (assuan_context_t ctx, char *line)
|
|||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
n /= 2;
|
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");
|
return set_error (GPG_ERR_ASS_PARAMETER, "unsupported length of hash");
|
||||||
|
|
||||||
if (n > MAX_DIGEST_LEN)
|
if (n > MAX_DIGEST_LEN)
|
||||||
return set_error (GPG_ERR_ASS_PARAMETER, "hash value to long");
|
return set_error (GPG_ERR_ASS_PARAMETER, "hash value to long");
|
||||||
|
|
||||||
|
@ -318,26 +318,36 @@ divert_pksign (ctrl_t ctrl,
|
|||||||
int rc;
|
int rc;
|
||||||
char *kid;
|
char *kid;
|
||||||
size_t siglen;
|
size_t siglen;
|
||||||
unsigned char *sigval;
|
unsigned char *sigval = NULL;
|
||||||
unsigned char *data;
|
|
||||||
size_t ndata;
|
|
||||||
|
|
||||||
rc = ask_for_card (ctrl, shadow_info, &kid);
|
rc = ask_for_card (ctrl, shadow_info, &kid);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
rc = encode_md_for_card (digest, digestlen, algo,
|
if (algo == GCRY_MD_USER_TLS_MD5SHA1)
|
||||||
&data, &ndata);
|
{
|
||||||
if (rc)
|
rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl,
|
||||||
return rc;
|
digest, digestlen, &sigval, &siglen);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned char *data;
|
||||||
|
size_t ndata;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl,
|
|
||||||
data, ndata, &sigval, &siglen);
|
|
||||||
if (!rc)
|
if (!rc)
|
||||||
*r_sig = sigval;
|
*r_sig = sigval;
|
||||||
xfree (data);
|
|
||||||
xfree (kid);
|
xfree (kid);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash,
|
|||||||
gcry_sexp_t hash;
|
gcry_sexp_t hash;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (! raw_value)
|
if (!raw_value)
|
||||||
{
|
{
|
||||||
const char *s;
|
const char *s;
|
||||||
char tmp[16+1];
|
char tmp[16+1];
|
||||||
@ -55,7 +55,7 @@ do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash,
|
|||||||
|
|
||||||
rc = gcry_sexp_build (&hash, NULL,
|
rc = gcry_sexp_build (&hash, NULL,
|
||||||
"(data (flags pkcs1) (hash %s %b))",
|
"(data (flags pkcs1) (hash %s %b))",
|
||||||
tmp, mdlen, md);
|
tmp, (int)mdlen, md);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -77,6 +77,55 @@ do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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
|
/* SIGN whatever information we have accumulated in CTRL and return
|
||||||
the signature S-Expression. */
|
the signature S-Expression. */
|
||||||
int
|
int
|
||||||
@ -133,12 +182,18 @@ agent_pksign_do (ctrl_t ctrl, const char *desc_text,
|
|||||||
|
|
||||||
gcry_sexp_t s_hash = NULL;
|
gcry_sexp_t s_hash = NULL;
|
||||||
|
|
||||||
/* put the hash into a sexp */
|
/* Put the hash into a sexp */
|
||||||
rc = do_encode_md (ctrl->digest.value,
|
if (ctrl->digest.algo == GCRY_MD_USER_TLS_MD5SHA1)
|
||||||
ctrl->digest.valuelen,
|
rc = do_encode_raw_pkcs1 (ctrl->digest.value,
|
||||||
ctrl->digest.algo,
|
ctrl->digest.valuelen,
|
||||||
&s_hash,
|
gcry_pk_get_nbits (s_skey),
|
||||||
ctrl->digest.raw_value);
|
&s_hash);
|
||||||
|
else
|
||||||
|
rc = do_encode_md (ctrl->digest.value,
|
||||||
|
ctrl->digest.valuelen,
|
||||||
|
ctrl->digest.algo,
|
||||||
|
&s_hash,
|
||||||
|
ctrl->digest.raw_value);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user