1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

More changes on the way to remove secring.gpg.

This commit is contained in:
Werner Koch 2010-04-21 16:26:17 +00:00
parent 00f8eafbef
commit a1412b05de
31 changed files with 843 additions and 936 deletions

View file

@ -1,3 +1,13 @@
2010-04-19 Werner Koch <wk@g10code.com>
* pksign.c (get_dsa_qbits, do_encode_dsa): New.
(agent_pksign_do): Detect DSA keys and use do_encode_dsa.
* findkey.c (agent_public_key_from_file): Factor some code out to ..
(key_parms_from_sexp): New.
(agent_is_dsa_key): New.
* command.c (cmd_sethash): Clear digeest.RAW_VALUE.
2010-04-14 Werner Koch <wk@g10code.com>
* Makefile.am (libexec_PROGRAMS) [W32CE]: Do not build

View file

@ -232,6 +232,7 @@ gpg_error_t agent_key_from_file (ctrl_t ctrl,
gpg_error_t agent_public_key_from_file (ctrl_t ctrl,
const unsigned char *grip,
gcry_sexp_t *result);
int agent_is_dsa_key (gcry_sexp_t s_key);
int agent_key_available (const unsigned char *grip);
gpg_error_t agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
int *r_keytype,

View file

@ -589,7 +589,7 @@ cmd_setkeydesc (assuan_context_t ctx, char *line)
static const char hlp_sethash[] =
"SETHASH --hash=<name>|<algonumber> <hexstring>\n"
"SETHASH (--hash=<name>)|(<algonumber>) <hexstring>\n"
"\n"
"The client can use this command to tell the server about the data\n"
"(which usually is a hash) to be signed.";
@ -642,6 +642,7 @@ cmd_sethash (assuan_context_t ctx, char *line)
return set_error (GPG_ERR_UNSUPPORTED_ALGORITHM, NULL);
}
ctrl->digest.algo = algo;
ctrl->digest.raw_value = 0;
/* Parse the hash value. */
n = 0;
@ -848,7 +849,7 @@ static const char hlp_keyinfo[] =
"\n"
"TYPE is describes the type of the key:\n"
" 'D' - Regular key stored on disk,\n"
" 'T' - Key is stored on a smartcard (token).\n"
" 'T' - Key is stored on a smartcard (token),\n"
" '-' - Unknown type.\n"
"\n"
"SERIALNO is an ASCII string with the serial number of the\n"

View file

@ -1,6 +1,6 @@
/* findkey.c - Locate the secret key
* Copyright (C) 2001, 2002, 2003, 2004, 2005,
* 2007 Free Software Foundation, Inc.
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007,
* 2010 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -626,50 +626,32 @@ agent_key_from_file (ctrl_t ctrl, const char *desc_text,
}
/* Return the public key for the keygrip GRIP. The result is stored
at RESULT. This function extracts the public key from the private
key database. On failure an error code is returned and NULL stored
at RESULT. */
gpg_error_t
agent_public_key_from_file (ctrl_t ctrl,
const unsigned char *grip,
gcry_sexp_t *result)
/* Return the string name from the S-expression S_KEY as well as a
string describing the names of the parameters. ALGONAMESIZE and
ELEMSSIZE give the allocated size of the provided buffers. The
buffers may be NULL if not required. If R_LIST is not NULL the top
level list will be stored tehre; the caller needs to release it in
this case. */
static gpg_error_t
key_parms_from_sexp (gcry_sexp_t s_key, gcry_sexp_t *r_list,
char *r_algoname, size_t algonamesize,
char *r_elems, size_t elemssize)
{
int i, idx, rc;
gcry_sexp_t s_skey;
const char *algoname;
gcry_sexp_t uri_sexp, comment_sexp;
const char *uri, *comment;
size_t uri_length, comment_length;
char *format, *p;
void *args[4+2+2+1]; /* Size is max. # of elements + 2 for uri + 2
for comment + end-of-list. */
int argidx;
gcry_sexp_t list, l2;
const char *name;
const char *s;
const char *name, *algoname, *elems;
size_t n;
const char *elems;
gcry_mpi_t *array;
(void)ctrl;
if (r_list)
*r_list = NULL;
*result = NULL;
rc = read_key_file (grip, &s_skey);
if (rc)
return rc;
list = gcry_sexp_find_token (s_skey, "shadowed-private-key", 0 );
list = gcry_sexp_find_token (s_key, "shadowed-private-key", 0 );
if (!list)
list = gcry_sexp_find_token (s_skey, "protected-private-key", 0 );
list = gcry_sexp_find_token (s_key, "protected-private-key", 0 );
if (!list)
list = gcry_sexp_find_token (s_skey, "private-key", 0 );
list = gcry_sexp_find_token (s_key, "private-key", 0 );
if (!list)
{
log_error ("invalid private key format\n");
gcry_sexp_release (s_skey);
return gpg_error (GPG_ERR_BAD_SECKEY);
}
@ -696,19 +678,99 @@ agent_public_key_from_file (ctrl_t ctrl,
{
log_error ("unknown private key algorithm\n");
gcry_sexp_release (list);
gcry_sexp_release (s_skey);
return gpg_error (GPG_ERR_BAD_SECKEY);
}
if (r_algoname)
{
if (strlen (algoname) >= algonamesize)
return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
strcpy (r_algoname, algoname);
}
if (r_elems)
{
if (strlen (elems) >= elemssize)
return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
strcpy (r_elems, elems);
}
if (r_list)
*r_list = list;
else
gcry_sexp_release (list);
return 0;
}
/* Return true if S_KEY is a DSA style key. */
int
agent_is_dsa_key (gcry_sexp_t s_key)
{
char algoname[6];
if (!s_key)
return 0;
if (key_parms_from_sexp (s_key, NULL, algoname, sizeof algoname, NULL, 0))
return 0; /* Error - assume it is not an DSA key. */
return (!strcmp (algoname, "dsa") || !strcmp (algoname, "ecdsa"));
}
/* Return the public key for the keygrip GRIP. The result is stored
at RESULT. This function extracts the public key from the private
key database. On failure an error code is returned and NULL stored
at RESULT. */
gpg_error_t
agent_public_key_from_file (ctrl_t ctrl,
const unsigned char *grip,
gcry_sexp_t *result)
{
gpg_error_t err;
int i, idx;
gcry_sexp_t s_skey;
char algoname[6];
char elems[6];
gcry_sexp_t uri_sexp, comment_sexp;
const char *uri, *comment;
size_t uri_length, comment_length;
char *format, *p;
void *args[4+2+2+1]; /* Size is max. # of elements + 2 for uri + 2
for comment + end-of-list. */
int argidx;
gcry_sexp_t list, l2;
const char *s;
gcry_mpi_t *array;
(void)ctrl;
*result = NULL;
err = read_key_file (grip, &s_skey);
if (err)
return err;
err = key_parms_from_sexp (s_skey, &list,
algoname, sizeof algoname,
elems, sizeof elems);
if (err)
{
gcry_sexp_release (s_skey);
return err;
}
/* Allocate an array for the parameters and copy them out of the
secret key. FIXME: We should have a generic copy function. */
array = xtrycalloc (strlen(elems) + 1, sizeof *array);
if (!array)
{
rc = gpg_error_from_syserror ();
err = gpg_error_from_syserror ();
gcry_sexp_release (list);
gcry_sexp_release (s_skey);
return rc;
return err;
}
for (idx=0, s=elems; *s; s++, idx++ )
@ -757,8 +819,8 @@ agent_public_key_from_file (ctrl_t ctrl,
/* FIXME: The following thing is pretty ugly code; we should
investigate how to make it cleaner. Probably code to handle
canonical S-expressions in a memory buffer is better suioted for
investigate how to make it cleaner. Probably code to handle
canonical S-expressions in a memory buffer is better suited for
such a task. After all that is what we do in protect.c. Neeed
to find common patterns and write a straightformward API to use
them. */
@ -767,13 +829,13 @@ agent_public_key_from_file (ctrl_t ctrl,
format = xtrymalloc (15+7*strlen (elems)+10+15+1+1);
if (!format)
{
rc = gpg_error_from_syserror ();
err = gpg_error_from_syserror ();
for (i=0; array[i]; i++)
gcry_mpi_release (array[i]);
xfree (array);
gcry_sexp_release (uri_sexp);
gcry_sexp_release (comment_sexp);
return rc;
return err;
}
argidx = 0;
@ -806,7 +868,7 @@ agent_public_key_from_file (ctrl_t ctrl,
assert (argidx < DIM (args));
args[argidx] = NULL;
rc = gcry_sexp_build_array (&list, NULL, format, args);
err = gcry_sexp_build_array (&list, NULL, format, args);
xfree (format);
for (i=0; array[i]; i++)
gcry_mpi_release (array[i]);
@ -814,9 +876,9 @@ agent_public_key_from_file (ctrl_t ctrl,
gcry_sexp_release (uri_sexp);
gcry_sexp_release (comment_sexp);
if (!rc)
if (!err)
*result = list;
return rc;
return err;
}

View file

@ -1,5 +1,5 @@
/* pksign.c - public key signing (well, actually using a secret key)
* Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
* Copyright (C) 2001, 2002, 2003, 2004, 2010 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -28,6 +28,7 @@
#include <sys/stat.h>
#include "agent.h"
#include "i18n.h"
static int
@ -75,6 +76,104 @@ do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash,
}
/* Return the number of bits of the Q parameter from the DSA key
KEY. */
static unsigned int
get_dsa_qbits (gcry_sexp_t key)
{
gcry_sexp_t l1, l2;
gcry_mpi_t q;
unsigned int nbits;
l1 = gcry_sexp_find_token (key, "private-key", 0);
if (!l1)
l1 = gcry_sexp_find_token (key, "protected-private-key", 0);
if (!l1)
l1 = gcry_sexp_find_token (key, "shadowed-private-key", 0);
if (!l1)
l1 = gcry_sexp_find_token (key, "public-key", 0);
if (!l1)
return 0; /* Does not contain a key object. */
l2 = gcry_sexp_cadr (l1);
gcry_sexp_release (l1);
l1 = gcry_sexp_find_token (l2, "q", 1);
gcry_sexp_release (l2);
if (!l1)
return 0; /* Invalid object. */
q = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
gcry_sexp_release (l1);
if (!q)
return 0; /* Missing value. */
nbits = gcry_mpi_get_nbits (q);
gcry_mpi_release (q);
return nbits;
}
/* Encode a message digest for use with an DSA algorithm. */
static gpg_error_t
do_encode_dsa (const byte * md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey,
gcry_sexp_t *r_hash)
{
gpg_error_t err;
gcry_sexp_t hash;
unsigned int qbits;
*r_hash = NULL;
if (dsaalgo == GCRY_PK_ECDSA)
qbits = gcry_pk_get_nbits (pkey);
else if (dsaalgo == GCRY_PK_DSA)
qbits = get_dsa_qbits (pkey);
else
return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO);
if ((qbits%8))
{
log_error (_("DSA requires the hash length to be a"
" multiple of 8 bits\n"));
return gpg_error (GPG_ERR_INV_LENGTH);
}
/* Don't allow any Q smaller than 160 bits. We don't want someone
to issue signatures from a key with a 16-bit Q or something like
that, which would look correct but allow trivial forgeries. Yes,
I know this rules out using MD5 with DSA. ;) */
if (qbits < 160)
{
log_error (_("%s key uses an unsafe (%u bit) hash\n"),
gcry_pk_algo_name (dsaalgo), qbits);
return gpg_error (GPG_ERR_INV_LENGTH);
}
/* Check if we're too short. Too long is safe as we'll
automatically left-truncate. */
if (mdlen < qbits/8)
{
log_error (_("a %zu bit hash is not valid for a %u bit %s key\n"),
mdlen*8,
gcry_pk_get_nbits (pkey),
gcry_pk_algo_name (dsaalgo));
/* FIXME: we need to check the requirements for ECDSA. */
if (mdlen < 20 || dsaalgo == GCRY_PK_DSA)
return gpg_error (GPG_ERR_INV_LENGTH);
}
/* Truncate. */
if (mdlen > qbits/8)
mdlen = qbits/8;
/* Create the S-expression. */
err = gcry_sexp_build (&hash, NULL,
"(data (flags raw) (value %b))",
(int)mdlen, md);
if (!err)
*r_hash = hash;
return err;
}
/* Special version of do_encode_md to take care of pkcs#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
@ -180,8 +279,8 @@ agent_pksign_do (ctrl_t ctrl, const char *desc_text,
else
{
/* No smartcard, but a private key */
gcry_sexp_t s_hash = NULL;
int dsaalgo;
/* Put the hash into a sexp */
if (ctrl->digest.algo == MD_USER_TLS_MD5SHA1)
@ -189,6 +288,11 @@ agent_pksign_do (ctrl_t ctrl, const char *desc_text,
ctrl->digest.valuelen,
gcry_pk_get_nbits (s_skey),
&s_hash);
else if ( (dsaalgo = agent_is_dsa_key (s_skey)) )
rc = do_encode_dsa (ctrl->digest.value,
ctrl->digest.valuelen,
dsaalgo, s_skey,
&s_hash);
else
rc = do_encode_md (ctrl->digest.value,
ctrl->digest.valuelen,