1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

Finished ECC integration.

Wrote the ChangeLog 2011-01-13 entry for Andrey's orginal work modulo
the cleanups I did in the last week.  Adjusted my own ChangeLog
entries to be consistent with that entry.

Nuked quite some trailing spaces; again sorry for that, I will better
take care of not saving them in the future.  "git diff -b" is useful
to read the actual changes ;-).

The ECC-INTEGRATION-2-1 branch can be closed now.
This commit is contained in:
Werner Koch 2011-02-03 16:31:42 +01:00
parent 20f429f735
commit 0b5bcb40cf
11 changed files with 336 additions and 292 deletions

View File

@ -11,6 +11,9 @@ Authors
Ales Nyakhaychyk <nyakhaychyk@i1fn.linux.by> Translations [be] Ales Nyakhaychyk <nyakhaychyk@i1fn.linux.by> Translations [be]
Andrey Jivsov <openpgp@brainhub.org> Assigns past and future changes for ECC.
(g10/ecdh.c. other changes to support ECC)
Birger Langkjer <birger.langkjer@image.dk> Translations [da] Birger Langkjer <birger.langkjer@image.dk> Translations [da]
Maxim Britov <maxim.britov@gmail.com> Translations [ru] Maxim Britov <maxim.britov@gmail.com> Translations [ru]
@ -174,4 +177,3 @@ name gpg2keys_*.
This file is distributed in the hope that it will be useful, but This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

18
NEWS
View File

@ -20,6 +20,8 @@ Noteworthy changes in version 2.1.0beta2 (unreleased)
* Dirmngr has taken over the function of the keyserver helpers. Thus * Dirmngr has taken over the function of the keyserver helpers. Thus
we now have a specified direct interface to keyservers via Dirmngr. we now have a specified direct interface to keyservers via Dirmngr.
* ECC support for GPG as described by draft-jivsov-openpgp-ecc-06.txt.
Noteworthy changes in version 2.1.0beta1 (2010-10-26) Noteworthy changes in version 2.1.0beta1 (2010-10-26)
----------------------------------------------------- -----------------------------------------------------
@ -183,7 +185,7 @@ Noteworthy changes in version 2.0.10 (2009-01-12)
the installation directory to %CSIDL_COMMON_APPDATA%/GNU/etc/gnupg. the installation directory to %CSIDL_COMMON_APPDATA%/GNU/etc/gnupg.
* [w32] The gnupg2.nls directory is not anymore used. The standard * [w32] The gnupg2.nls directory is not anymore used. The standard
locale directory is now used. locale directory is now used.
* [w32] Fixed a race condition between gpg and gpgsm in the use of * [w32] Fixed a race condition between gpg and gpgsm in the use of
temporary file names. temporary file names.
@ -235,7 +237,7 @@ Noteworthy changes in version 2.0.8 (2007-12-20)
* The envvars XAUTHORITY and PINENTRY_USER_DATA are now passed to the * The envvars XAUTHORITY and PINENTRY_USER_DATA are now passed to the
Pinentry. Pinentry.
* Fixed the auto creation of the key stub for smartcards. * Fixed the auto creation of the key stub for smartcards.
* Fixed a rare bug in decryption using the OpenPGP card. * Fixed a rare bug in decryption using the OpenPGP card.
@ -277,7 +279,7 @@ Noteworthy changes in version 2.0.6 (2007-08-16)
* GPGSM does now grok --default-key. * GPGSM does now grok --default-key.
* GPGCONF is now aware of --default-key and --encrypt-to. * GPGCONF is now aware of --default-key and --encrypt-to.
* GPGSM does again correctly print the serial number as well the the * GPGSM does again correctly print the serial number as well the the
various keyids. This was broken since 2.0.4. various keyids. This was broken since 2.0.4.
@ -286,7 +288,7 @@ Noteworthy changes in version 2.0.6 (2007-08-16)
* Improved Windows support. * Improved Windows support.
Noteworthy changes in version 2.0.5 (2007-07-05) Noteworthy changes in version 2.0.5 (2007-07-05)
------------------------------------------------ ------------------------------------------------
@ -326,7 +328,7 @@ Noteworthy changes in version 2.0.3 (2007-03-08)
such messages by default which makes those programs safe again. such messages by default which makes those programs safe again.
--allow-multiple-messages returns to the old behavior. [CVE-2007-1263]. --allow-multiple-messages returns to the old behavior. [CVE-2007-1263].
* New --verify-option show-primary-uid-only. * New --verify-option show-primary-uid-only.
* gpgconf may now reads a global configuration file to select which * gpgconf may now reads a global configuration file to select which
options are changeable by a frontend. The new applygnupgdefaults options are changeable by a frontend. The new applygnupgdefaults
@ -490,7 +492,7 @@ Noteworthy changes in version 1.9.21 (2006-06-20)
* Support for the CardMan 4040 PCMCIA reader (Linux 2.6.15 required). * Support for the CardMan 4040 PCMCIA reader (Linux 2.6.15 required).
* Scdaemon does not anymore reset cards at the end of a connection. * Scdaemon does not anymore reset cards at the end of a connection.
* Kludge to allow use of Bundesnetzagentur issued X.509 certificates. * Kludge to allow use of Bundesnetzagentur issued X.509 certificates.
@ -510,7 +512,7 @@ Noteworthy changes in version 1.9.20 (2005-12-20)
* Basic support for qualified signatures. * Basic support for qualified signatures.
* New debug tool gpgparsemail. * New debug tool gpgparsemail.
Noteworthy changes in version 1.9.19 (2005-09-12) Noteworthy changes in version 1.9.19 (2005-09-12)
@ -794,7 +796,7 @@ Noteworthy changes in version 1.9.0 (2003-08-05)
Copyright 2002, 2003, 2004, 2005, 2006, 2007, Copyright 2002, 2003, 2004, 2005, 2006, 2007,
2008, 2009 Free Software Foundation, Inc. 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without unlimited permission to copy and/or distribute it, with or without

View File

@ -1,3 +1,19 @@
2011-02-03 Werner Koch <wk@g10code.com>
* protect.c (protect_info): Support ECC algos.
* pksign.c (do_encode_dsa): Map public key algo number. Extend
DSA size check for ECDSA.
* gpg-agent.c: Include cipher.h.
(map_pk_openpgp_to_gcry): New.
* findkey.c (key_parms_from_sexp): Support ECDH.
* cvt-openpgp.c (get_keygrip): Support ECC algorithms.
(convert_secret_key): Ditto.
(do_unprotect): Ditto.
2011-02-02 Werner Koch <wk@g10code.com> 2011-02-02 Werner Koch <wk@g10code.com>
* cvt-openpgp.c (convert_secret_key): Remove algo mapping. * cvt-openpgp.c (convert_secret_key): Remove algo mapping.

View File

@ -1,6 +1,6 @@
/* protect.c - Un/Protect a secret key /* protect.c - Un/Protect a secret key
* Copyright (C) 1998, 1999, 2000, 2001, 2002, * Copyright (C) 1998, 1999, 2000, 2001, 2002,
* 2003, 2007, 2009 Free Software Foundation, Inc. * 2003, 2007, 2009, 2011 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -85,14 +85,14 @@ calibrate_get_time (struct calibrate_time_s *data)
#ifdef HAVE_W32_SYSTEM #ifdef HAVE_W32_SYSTEM
# ifdef HAVE_W32CE_SYSTEM # ifdef HAVE_W32CE_SYSTEM
GetThreadTimes (GetCurrentThread (), GetThreadTimes (GetCurrentThread (),
# else # else
GetProcessTimes (GetCurrentProcess (), GetProcessTimes (GetCurrentProcess (),
# endif # endif
&data->creation_time, &data->exit_time, &data->creation_time, &data->exit_time,
&data->kernel_time, &data->user_time); &data->kernel_time, &data->user_time);
#else #else
struct tms tmp; struct tms tmp;
times (&tmp); times (&tmp);
data->ticks = tmp.tms_utime; data->ticks = tmp.tms_utime;
#endif #endif
@ -103,12 +103,12 @@ static unsigned long
calibrate_elapsed_time (struct calibrate_time_s *starttime) calibrate_elapsed_time (struct calibrate_time_s *starttime)
{ {
struct calibrate_time_s stoptime; struct calibrate_time_s stoptime;
calibrate_get_time (&stoptime); calibrate_get_time (&stoptime);
#ifdef HAVE_W32_SYSTEM #ifdef HAVE_W32_SYSTEM
{ {
unsigned long long t1, t2; unsigned long long t1, t2;
t1 = (((unsigned long long)starttime->kernel_time.dwHighDateTime << 32) t1 = (((unsigned long long)starttime->kernel_time.dwHighDateTime << 32)
+ starttime->kernel_time.dwLowDateTime); + starttime->kernel_time.dwLowDateTime);
t1 += (((unsigned long long)starttime->user_time.dwHighDateTime << 32) t1 += (((unsigned long long)starttime->user_time.dwHighDateTime << 32)
@ -145,7 +145,7 @@ calibrate_s2k_count_one (unsigned long count)
/* Measure the time we need to do the hash operations and deduce an /* Measure the time we need to do the hash operations and deduce an
S2K count which requires about 100ms of time. */ S2K count which requires about 100ms of time. */
static unsigned long static unsigned long
calibrate_s2k_count (void) calibrate_s2k_count (void)
{ {
@ -197,7 +197,7 @@ get_standard_s2k_count (void)
/* Calculate the MIC for a private key or shared secret S-expression. /* Calculate the MIC for a private key or shared secret S-expression.
SHA1HASH should point to a 20 byte buffer. This function is SHA1HASH should point to a 20 byte buffer. This function is
suitable for all algorithms. */ suitable for all algorithms. */
static int static int
calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash) calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash)
{ {
const unsigned char *hash_begin, *hash_end; const unsigned char *hash_begin, *hash_end;
@ -211,13 +211,13 @@ calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash)
s++; s++;
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
if (smatch (&s, n, "private-key")) if (smatch (&s, n, "private-key"))
is_shared_secret = 0; is_shared_secret = 0;
else if (smatch (&s, n, "shared-secret")) else if (smatch (&s, n, "shared-secret"))
is_shared_secret = 1; is_shared_secret = 1;
else else
return gpg_error (GPG_ERR_UNKNOWN_SEXP); return gpg_error (GPG_ERR_UNKNOWN_SEXP);
if (*s != '(') if (*s != '(')
return gpg_error (GPG_ERR_UNKNOWN_SEXP); return gpg_error (GPG_ERR_UNKNOWN_SEXP);
hash_begin = s; hash_begin = s;
@ -226,7 +226,7 @@ calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash)
s++; s++;
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
s += n; /* Skip the algorithm name. */ s += n; /* Skip the algorithm name. */
} }
@ -235,18 +235,18 @@ calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash)
s++; s++;
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
s += n; s += n;
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
s += n; s += n;
if ( *s != ')' ) if ( *s != ')' )
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
s++; s++;
} }
if (*s != ')') if (*s != ')')
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
s++; s++;
hash_end = s; hash_end = s;
@ -269,7 +269,7 @@ calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash)
(d #046129F..[some bytes not shown]..81#) (d #046129F..[some bytes not shown]..81#)
(p #00e861b..[some bytes not shown]..f1#) (p #00e861b..[some bytes not shown]..f1#)
(q #00f7a7c..[some bytes not shown]..61#) (q #00f7a7c..[some bytes not shown]..61#)
(u #304559a..[some bytes not shown]..9b#) (u #304559a..[some bytes not shown]..9b#)
the returned block is the S-Expression: the returned block is the S-Expression:
@ -277,7 +277,7 @@ calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash)
*/ */
static int static int
do_encryption (const unsigned char *protbegin, size_t protlen, do_encryption (const unsigned char *protbegin, size_t protlen,
const char *passphrase, const unsigned char *sha1hash, const char *passphrase, const unsigned char *sha1hash,
unsigned char **result, size_t *resultlen) unsigned char **result, size_t *resultlen)
{ {
@ -330,14 +330,14 @@ do_encryption (const unsigned char *protbegin, size_t protlen,
{ {
unsigned char *key; unsigned char *key;
size_t keylen = PROT_CIPHER_KEYLEN; size_t keylen = PROT_CIPHER_KEYLEN;
key = gcry_malloc_secure (keylen); key = gcry_malloc_secure (keylen);
if (!key) if (!key)
rc = out_of_core (); rc = out_of_core ();
else else
{ {
rc = hash_passphrase (passphrase, GCRY_MD_SHA1, rc = hash_passphrase (passphrase, GCRY_MD_SHA1,
3, iv+2*blklen, 3, iv+2*blklen,
get_standard_s2k_count (), key, keylen); get_standard_s2k_count (), key, keylen);
if (!rc) if (!rc)
rc = gcry_cipher_setkey (hd, key, keylen); rc = gcry_cipher_setkey (hd, key, keylen);
@ -357,7 +357,7 @@ do_encryption (const unsigned char *protbegin, size_t protlen,
p += 20; p += 20;
*p++ = ')'; *p++ = ')';
*p++ = ')'; *p++ = ')';
memcpy (p, iv+blklen, blklen); memcpy (p, iv+blklen, blklen);
p += blklen; p += blklen;
assert ( p - outbuf == outlen); assert ( p - outbuf == outlen);
rc = gcry_cipher_encrypt (hd, outbuf, enclen, NULL, 0); rc = gcry_cipher_encrypt (hd, outbuf, enclen, NULL, 0);
@ -375,7 +375,7 @@ do_encryption (const unsigned char *protbegin, size_t protlen,
(protected openpgp-s2k3-sha1-aes-cbc (protected openpgp-s2k3-sha1-aes-cbc
((sha1 salt no_of_iterations) 16byte_iv) ((sha1 salt no_of_iterations) 16byte_iv)
encrypted_octet_string) encrypted_octet_string)
in canoncical format of course. We use asprintf and %n modifier in canoncical format of course. We use asprintf and %n modifier
and dummy values as placeholders. */ and dummy values as placeholders. */
{ {
@ -385,7 +385,7 @@ do_encryption (const unsigned char *protbegin, size_t protlen,
p = xtryasprintf p = xtryasprintf
("(9:protected%d:%s((4:sha18:%n_8bytes_%u:%s)%d:%n%*s)%d:%n%*s)", ("(9:protected%d:%s((4:sha18:%n_8bytes_%u:%s)%d:%n%*s)%d:%n%*s)",
(int)strlen (modestr), modestr, (int)strlen (modestr), modestr,
&saltpos, &saltpos,
(unsigned int)strlen (countbuf), countbuf, (unsigned int)strlen (countbuf), countbuf,
blklen, &ivpos, blklen, "", blklen, &ivpos, blklen, "",
enclen, &encpos, enclen, ""); enclen, &encpos, enclen, "");
@ -411,7 +411,7 @@ do_encryption (const unsigned char *protbegin, size_t protlen,
/* Protect the key encoded in canonical format in PLAINKEY. We assume /* Protect the key encoded in canonical format in PLAINKEY. We assume
a valid S-Exp here. */ a valid S-Exp here. */
int int
agent_protect (const unsigned char *plainkey, const char *passphrase, agent_protect (const unsigned char *plainkey, const char *passphrase,
unsigned char **result, size_t *resultlen) unsigned char **result, size_t *resultlen)
{ {
@ -442,9 +442,9 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
s++; s++;
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
if (!smatch (&s, n, "private-key")) if (!smatch (&s, n, "private-key"))
return gpg_error (GPG_ERR_UNKNOWN_SEXP); return gpg_error (GPG_ERR_UNKNOWN_SEXP);
if (*s != '(') if (*s != '(')
return gpg_error (GPG_ERR_UNKNOWN_SEXP); return gpg_error (GPG_ERR_UNKNOWN_SEXP);
depth++; depth++;
@ -452,13 +452,13 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
s++; s++;
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
for (infidx=0; protect_info[infidx].algo for (infidx=0; protect_info[infidx].algo
&& !smatch (&s, n, protect_info[infidx].algo); infidx++) && !smatch (&s, n, protect_info[infidx].algo); infidx++)
; ;
if (!protect_info[infidx].algo) if (!protect_info[infidx].algo)
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
prot_begin = prot_end = NULL; prot_begin = prot_end = NULL;
for (i=0; (c=protect_info[infidx].parmlist[i]); i++) for (i=0; (c=protect_info[infidx].parmlist[i]); i++)
@ -471,23 +471,23 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
s++; s++;
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
if (n != 1 || c != *s) if (n != 1 || c != *s)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
s += n; s += n;
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
s +=n; /* skip value */ s +=n; /* skip value */
if (*s != ')') if (*s != ')')
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
depth--; depth--;
if (i == protect_info[infidx].prot_to) if (i == protect_info[infidx].prot_to)
prot_end = s; prot_end = s;
s++; s++;
} }
if (*s != ')' || !prot_begin || !prot_end ) if (*s != ')' || !prot_begin || !prot_end )
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
depth--; depth--;
hash_end = s; hash_end = s;
s++; s++;
@ -499,10 +499,10 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
assert (!depth); assert (!depth);
real_end = s-1; real_end = s-1;
/* Hash the stuff. Because the timestamp_exp won't get protected, /* Hash the stuff. Because the timestamp_exp won't get protected,
we can't simply hash a continuous buffer but need to use several we can't simply hash a continuous buffer but need to use several
md_writes. */ md_writes. */
rc = gcry_md_open (&md, GCRY_MD_SHA1, 0 ); rc = gcry_md_open (&md, GCRY_MD_SHA1, 0 );
if (rc) if (rc)
return rc; return rc;
@ -555,8 +555,8 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
/* Do the actual decryption and check the return list for consistency. */ /* Do the actual decryption and check the return list for consistency. */
static int static int
do_decryption (const unsigned char *protected, size_t protectedlen, do_decryption (const unsigned char *protected, size_t protectedlen,
const char *passphrase, const char *passphrase,
const unsigned char *s2ksalt, unsigned long s2kcount, const unsigned char *s2ksalt, unsigned long s2kcount,
const unsigned char *iv, size_t ivlen, const unsigned char *iv, size_t ivlen,
unsigned char **result) unsigned char **result)
@ -585,7 +585,7 @@ do_decryption (const unsigned char *protected, size_t protectedlen,
{ {
unsigned char *key; unsigned char *key;
size_t keylen = PROT_CIPHER_KEYLEN; size_t keylen = PROT_CIPHER_KEYLEN;
key = gcry_malloc_secure (keylen); key = gcry_malloc_secure (keylen);
if (!key) if (!key)
rc = out_of_core (); rc = out_of_core ();
@ -633,7 +633,7 @@ do_decryption (const unsigned char *protected, size_t protectedlen,
calculation but then be removed. */ calculation but then be removed. */
static int static int
merge_lists (const unsigned char *protectedkey, merge_lists (const unsigned char *protectedkey,
size_t replacepos, size_t replacepos,
const unsigned char *cleartext, const unsigned char *cleartext,
unsigned char *sha1hash, unsigned char *sha1hash,
unsigned char **result, size_t *resultlen, unsigned char **result, size_t *resultlen,
@ -644,7 +644,7 @@ merge_lists (const unsigned char *protectedkey,
const unsigned char *s; const unsigned char *s;
const unsigned char *startpos, *endpos; const unsigned char *startpos, *endpos;
int i, rc; int i, rc;
*result = NULL; *result = NULL;
*resultlen = 0; *resultlen = 0;
*cutoff = 0; *cutoff = 0;
@ -707,7 +707,7 @@ merge_lists (const unsigned char *protectedkey,
goto invalid_sexp; goto invalid_sexp;
n = snext (&s); n = snext (&s);
if (!smatch (&s, n, "sha1")) if (!smatch (&s, n, "sha1"))
goto invalid_sexp; goto invalid_sexp;
n = snext (&s); n = snext (&s);
if (n != 20) if (n != 20)
goto invalid_sexp; goto invalid_sexp;
@ -720,7 +720,7 @@ merge_lists (const unsigned char *protectedkey,
/* append the parameter list */ /* append the parameter list */
memcpy (p, startpos, endpos - startpos); memcpy (p, startpos, endpos - startpos);
p += endpos - startpos; p += endpos - startpos;
/* Skip over the protected list element in the original list. */ /* Skip over the protected list element in the original list. */
s = protectedkey + replacepos; s = protectedkey + replacepos;
assert (*s == '('); assert (*s == '(');
@ -758,7 +758,7 @@ merge_lists (const unsigned char *protectedkey,
*cutoff = p - newlist; *cutoff = p - newlist;
memcpy (p, startpos, endpos - startpos); memcpy (p, startpos, endpos - startpos);
p += endpos - startpos; p += endpos - startpos;
/* ready */ /* ready */
*result = newlist; *result = newlist;
@ -781,14 +781,14 @@ merge_lists (const unsigned char *protectedkey,
/* Unprotect the key encoded in canonical format. We assume a valid /* Unprotect the key encoded in canonical format. We assume a valid
S-Exp here. If a protected-at item is available, its value will S-Exp here. If a protected-at item is available, its value will
be stored at protocted_at unless this is NULL. */ be stored at protocted_at unless this is NULL. */
int int
agent_unprotect (const unsigned char *protectedkey, const char *passphrase, agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
gnupg_isotime_t protected_at, gnupg_isotime_t protected_at,
unsigned char **result, size_t *resultlen) unsigned char **result, size_t *resultlen)
{ {
int rc; int rc;
const unsigned char *s; const unsigned char *s;
const unsigned char *protect_list; const unsigned char *protect_list;
size_t n; size_t n;
int infidx, i; int infidx, i;
unsigned char sha1hash[20], sha1hash2[20]; unsigned char sha1hash[20], sha1hash2[20];
@ -810,21 +810,21 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
s++; s++;
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
if (!smatch (&s, n, "protected-private-key")) if (!smatch (&s, n, "protected-private-key"))
return gpg_error (GPG_ERR_UNKNOWN_SEXP); return gpg_error (GPG_ERR_UNKNOWN_SEXP);
if (*s != '(') if (*s != '(')
return gpg_error (GPG_ERR_UNKNOWN_SEXP); return gpg_error (GPG_ERR_UNKNOWN_SEXP);
s++; s++;
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
for (infidx=0; protect_info[infidx].algo for (infidx=0; protect_info[infidx].algo
&& !smatch (&s, n, protect_info[infidx].algo); infidx++) && !smatch (&s, n, protect_info[infidx].algo); infidx++)
; ;
if (!protect_info[infidx].algo) if (!protect_info[infidx].algo)
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
/* See wether we have a protected-at timestamp. */ /* See wether we have a protected-at timestamp. */
@ -859,7 +859,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
/* Now find the list with the protected information. Here is an /* Now find the list with the protected information. Here is an
example for such a list: example for such a list:
(protected openpgp-s2k3-sha1-aes-cbc (protected openpgp-s2k3-sha1-aes-cbc
((sha1 <salt> <count>) <Initialization_Vector>) ((sha1 <salt> <count>) <Initialization_Vector>)
<encrypted_data>) <encrypted_data>)
*/ */
@ -872,7 +872,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
s++; s++;
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
if (smatch (&s, n, "protected")) if (smatch (&s, n, "protected"))
break; break;
s += n; s += n;
@ -884,7 +884,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
/* found */ /* found */
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
if (!smatch (&s, n, "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc")) if (!smatch (&s, n, "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc"))
return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION); return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION);
if (*s != '(' || s[1] != '(') if (*s != '(' || s[1] != '(')
@ -892,7 +892,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
s += 2; s += 2;
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
if (!smatch (&s, n, "sha1")) if (!smatch (&s, n, "sha1"))
return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION); return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION);
n = snext (&s); n = snext (&s);
@ -908,7 +908,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
is nothing we should worry about */ is nothing we should worry about */
if (s[n] != ')' ) if (s[n] != ')' )
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
/* Old versions of gpg-agent used the funny floating point number in /* Old versions of gpg-agent used the funny floating point number in
a byte encoding as specified by OpenPGP. However this is not a byte encoding as specified by OpenPGP. However this is not
needed and thus we now store it as a plain unsigned integer. We needed and thus we now store it as a plain unsigned integer. We
@ -938,8 +938,8 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
s++; s++;
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
cleartext = NULL; /* Avoid cc warning. */ cleartext = NULL; /* Avoid cc warning. */
rc = do_decryption (s, n, rc = do_decryption (s, n,
passphrase, s2ksalt, s2kcount, passphrase, s2ksalt, s2kcount,
@ -1014,7 +1014,7 @@ agent_private_key_type (const unsigned char *privatekey)
store this key in the caller provided buffer KEY. The caller must store this key in the caller provided buffer KEY. The caller must
provide an HASHALGO, a valid S2KMODE (see rfc-2440) and depending on provide an HASHALGO, a valid S2KMODE (see rfc-2440) and depending on
that mode an S2KSALT of 8 random bytes and an S2KCOUNT. that mode an S2KSALT of 8 random bytes and an S2KCOUNT.
Returns an error code on failure. */ Returns an error code on failure. */
static int static int
hash_passphrase (const char *passphrase, int hashalgo, hash_passphrase (const char *passphrase, int hashalgo,
@ -1034,7 +1034,7 @@ hash_passphrase (const char *passphrase, int hashalgo,
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_VALUE);
if ((s2kmode == 1 ||s2kmode == 3) && !s2ksalt) if ((s2kmode == 1 ||s2kmode == 3) && !s2ksalt)
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_VALUE);
rc = gcry_md_open (&md, hashalgo, GCRY_MD_FLAG_SECURE); rc = gcry_md_open (&md, hashalgo, GCRY_MD_FLAG_SECURE);
if (rc) if (rc)
return rc; return rc;
@ -1068,7 +1068,7 @@ hash_passphrase (const char *passphrase, int hashalgo,
} }
if (count < 8) if (count < 8)
gcry_md_write (md, s2ksalt, count); gcry_md_write (md, s2ksalt, count);
else else
{ {
gcry_md_write (md, s2ksalt, 8); gcry_md_write (md, s2ksalt, 8);
count -= 8; count -= 8;
@ -1077,7 +1077,7 @@ hash_passphrase (const char *passphrase, int hashalgo,
} }
else else
gcry_md_write (md, passphrase, pwlen); gcry_md_write (md, passphrase, pwlen);
gcry_md_final (md); gcry_md_final (md);
i = gcry_md_get_algo_dlen (hashalgo); i = gcry_md_get_algo_dlen (hashalgo);
if (i > keylen - used) if (i > keylen - used)
@ -1097,7 +1097,7 @@ s2k_hash_passphrase (const char *passphrase, int hashalgo,
unsigned int s2kcount, unsigned int s2kcount,
unsigned char *key, size_t keylen) unsigned char *key, size_t keylen)
{ {
return hash_passphrase (passphrase, hashalgo, s2kmode, s2ksalt, return hash_passphrase (passphrase, hashalgo, s2kmode, s2ksalt,
(16ul + (s2kcount & 15)) << ((s2kcount >> 4) + 6), (16ul + (s2kcount & 15)) << ((s2kcount >> 4) + 6),
key, keylen); key, keylen);
} }
@ -1140,7 +1140,7 @@ make_shadow_info (const char *serialno, const char *idstring)
S-expression is returned in an allocated buffer RESULT will point S-expression is returned in an allocated buffer RESULT will point
to. The input parameters are expected to be valid canonicalized to. The input parameters are expected to be valid canonicalized
S-expressions */ S-expressions */
int int
agent_shadow_key (const unsigned char *pubkey, agent_shadow_key (const unsigned char *pubkey,
const unsigned char *shadow_info, const unsigned char *shadow_info,
unsigned char **result) unsigned char **result)
@ -1162,16 +1162,16 @@ agent_shadow_key (const unsigned char *pubkey,
s++; s++;
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
if (!smatch (&s, n, "public-key")) if (!smatch (&s, n, "public-key"))
return gpg_error (GPG_ERR_UNKNOWN_SEXP); return gpg_error (GPG_ERR_UNKNOWN_SEXP);
if (*s != '(') if (*s != '(')
return gpg_error (GPG_ERR_UNKNOWN_SEXP); return gpg_error (GPG_ERR_UNKNOWN_SEXP);
depth++; depth++;
s++; s++;
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
s += n; /* skip over the algorithm name */ s += n; /* skip over the algorithm name */
while (*s != ')') while (*s != ')')
@ -1181,15 +1181,15 @@ agent_shadow_key (const unsigned char *pubkey,
depth++; depth++;
s++; s++;
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
s += n; s += n;
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
s +=n; /* skip value */ s +=n; /* skip value */
if (*s != ')') if (*s != ')')
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
depth--; depth--;
s++; s++;
} }
@ -1221,7 +1221,7 @@ agent_shadow_key (const unsigned char *pubkey,
/* Parse a canonical encoded shadowed key and return a pointer to the /* Parse a canonical encoded shadowed key and return a pointer to the
inner list with the shadow_info */ inner list with the shadow_info */
int int
agent_get_shadow_info (const unsigned char *shadowkey, agent_get_shadow_info (const unsigned char *shadowkey,
unsigned char const **shadow_info) unsigned char const **shadow_info)
{ {
@ -1236,16 +1236,16 @@ agent_get_shadow_info (const unsigned char *shadowkey,
s++; s++;
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
if (!smatch (&s, n, "shadowed-private-key")) if (!smatch (&s, n, "shadowed-private-key"))
return gpg_error (GPG_ERR_UNKNOWN_SEXP); return gpg_error (GPG_ERR_UNKNOWN_SEXP);
if (*s != '(') if (*s != '(')
return gpg_error (GPG_ERR_UNKNOWN_SEXP); return gpg_error (GPG_ERR_UNKNOWN_SEXP);
depth++; depth++;
s++; s++;
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
s += n; /* skip over the algorithm name */ s += n; /* skip over the algorithm name */
for (;;) for (;;)
@ -1257,24 +1257,24 @@ agent_get_shadow_info (const unsigned char *shadowkey,
depth++; depth++;
s++; s++;
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
if (smatch (&s, n, "shadowed")) if (smatch (&s, n, "shadowed"))
break; break;
s += n; s += n;
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
s +=n; /* skip value */ s +=n; /* skip value */
if (*s != ')') if (*s != ')')
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
depth--; depth--;
s++; s++;
} }
/* Found the shadowed list, S points to the protocol */ /* Found the shadowed list, S points to the protocol */
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
if (smatch (&s, n, "t1-v1")) if (smatch (&s, n, "t1-v1"))
{ {
if (*s != '(') if (*s != '(')
@ -1294,7 +1294,7 @@ agent_get_shadow_info (const unsigned char *shadowkey,
parameters addresses. If the serial number or the ID string is not parameters addresses. If the serial number or the ID string is not
required, NULL may be passed for them. */ required, NULL may be passed for them. */
gpg_error_t gpg_error_t
parse_shadow_info (const unsigned char *shadow_info, parse_shadow_info (const unsigned char *shadow_info,
char **r_hexsn, char **r_idstr) char **r_hexsn, char **r_idstr)
{ {
const unsigned char *s; const unsigned char *s;
@ -1331,7 +1331,7 @@ parse_shadow_info (const unsigned char *shadow_info,
} }
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
} }
if (r_idstr) if (r_idstr)
{ {
*r_idstr = xtrymalloc (n+1); *r_idstr = xtrymalloc (n+1);
@ -1350,4 +1350,3 @@ parse_shadow_info (const unsigned char *shadow_info,
return 0; return 0;
} }

View File

@ -3,8 +3,6 @@
* openpgp-oid.c: New. * openpgp-oid.c: New.
* t-openpgp-oid.c: New. * t-openpgp-oid.c: New.
* convert.c (mpi2hex): Remove.
2011-01-20 Werner Koch <wk@g10code.com> 2011-01-20 Werner Koch <wk@g10code.com>
Fix bug#1313. Fix bug#1313.

View File

@ -23,7 +23,6 @@
#include <ctype.h> #include <ctype.h>
#include "util.h" #include "util.h"
#include "gcrypt.h" /* FIXME: really needed? */
#define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A')) #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
@ -107,14 +106,14 @@ do_bin2hex (const void *buffer, size_t length, char *stringbuf, int with_colon)
{ {
const unsigned char *s; const unsigned char *s;
char *p; char *p;
if (!stringbuf) if (!stringbuf)
{ {
/* Not really correct for with_colon but we don't care about the /* Not really correct for with_colon but we don't care about the
one wasted byte. */ one wasted byte. */
size_t n = with_colon? 3:2; size_t n = with_colon? 3:2;
size_t nbytes = n * length + 1; size_t nbytes = n * length + 1;
if (length && (nbytes-1) / n != length) if (length && (nbytes-1) / n != length)
{ {
gpg_err_set_errno (ENOMEM); gpg_err_set_errno (ENOMEM);
return NULL; return NULL;
@ -123,7 +122,7 @@ do_bin2hex (const void *buffer, size_t length, char *stringbuf, int with_colon)
if (!stringbuf) if (!stringbuf)
return NULL; return NULL;
} }
for (s = buffer, p = stringbuf; length; length--, s++) for (s = buffer, p = stringbuf; length; length--, s++)
{ {
if (with_colon && s != buffer) if (with_colon && s != buffer)
@ -172,7 +171,7 @@ bin2hexcolon (const void *buffer, size_t length, char *stringbuf)
buffer, the function returns NULL and won't change the existing buffer, the function returns NULL and won't change the existing
conent of buffer. In-place conversion is possible as long as conent of buffer. In-place conversion is possible as long as
BUFFER points to HEXSTRING. BUFFER points to HEXSTRING.
If BUFFER is NULL and bufsize is 0 the function scans HEXSTRING but If BUFFER is NULL and bufsize is 0 the function scans HEXSTRING but
does not store anything. This may be used to find the end of does not store anything. This may be used to find the end of
hexstring. hexstring.
@ -205,7 +204,7 @@ hex2str (const char *hexstring, char *buffer, size_t bufsize, size_t *buflen)
{ {
if (count > bufsize) if (count > bufsize)
return NULL; /* Too long. */ return NULL; /* Too long. */
for (s=hexstring, idx=0; hexdigitp (s) && hexdigitp (s+1); s += 2) for (s=hexstring, idx=0; hexdigitp (s) && hexdigitp (s+1); s += 2)
((unsigned char*)buffer)[idx++] = xtoi_2 (s); ((unsigned char*)buffer)[idx++] = xtoi_2 (s);
if (need_nul) if (need_nul)

View File

@ -1,3 +1,8 @@
2011-02-03 Werner Koch <wk@g10code.com>
Finished ECC integration.
Wrote change description for 2011-01-13.
2011-02-02 Werner Koch <wk@g10code.com> 2011-02-02 Werner Koch <wk@g10code.com>
* encrypt.c (write_pubkey_enc_from_list): Don't compute the * encrypt.c (write_pubkey_enc_from_list): Don't compute the
@ -12,36 +17,31 @@
2011-02-01 Werner Koch <wk@g10code.com> 2011-02-01 Werner Koch <wk@g10code.com>
* import.c (transfer_secret_keys): Implement ECC case.
* gpg.c (main): Call setup_libgcrypt_logging. * gpg.c (main): Call setup_libgcrypt_logging.
* import.c (transfer_secret_keys): Implement ECC case.
(one_mpi_from_pkey): New.
* export.c (transfer_format_to_openpgp): Ditto.
* keygen.c (gpg_curve_to_oid): New. * keygen.c (gpg_curve_to_oid): New.
(ecckey_from_sexp): Factor curve name mapping out to new function. (ecckey_from_sexp): Factor curve name mapping out to new function.
2011-01-31 Werner Koch <wk@g10code.com> 2011-01-31 Werner Koch <wk@g10code.com>
* misc.c (make_flagged_int, openpgp_oid_from_str)
(openpgp_oid_to_str): Move to ../common/openpgp-oids.c.
* ecdh.c (pk_ecdh_encrypt_with_shared_point): Return an opaque MPI. * ecdh.c (pk_ecdh_encrypt_with_shared_point): Return an opaque MPI.
* build-packet.c (mpi_write): Rename to gpg_mpi_write and make global. * build-packet.c (mpi_write): Rename to gpg_mpi_write and make global.
(write_size_body_mpi): Remove.
2011-01-30 Werner Koch <wk@g10code.com> 2011-01-30 Werner Koch <wk@g10code.com>
* keyid.c (keygrip_from_pk): Adjust ECC cases. * keyid.c (keygrip_from_pk): Adjust ECC cases.
* pkglue.c (pk_verify): Ditto. * pkglue.c (pk_verify): Ditto.
* parse-packet.c (read_size_body): Rewrite. * parse-packet.c (parse_key): Simply ECC case.
(parse_key): Simply ECC case.
(parse_pubkeyenc): Ditto. (parse_pubkeyenc): Ditto.
* misc.c (pubkey_get_npkey): Special case ECC. * misc.c (pubkey_get_npkey): Special case ECC.
(pubkey_get_nskey): Ditto. (pubkey_get_nskey): Ditto.
(mpi_print): Support printfing of opaque values. (mpi_print): Support printing of opaque values.
(openpgp_oid_to_str): New. (openpgp_oid_to_str): New.
(pubkey_nbits): For ECC pass curve parameter. (pubkey_nbits): For ECC pass curve parameter.
@ -61,19 +61,6 @@
(get_parameter_algo): Map algo number. (get_parameter_algo): Map algo number.
(ecckey_from_sexp): New. (ecckey_from_sexp): New.
* misc.c (map_pk_gcry_to_openpgp): New. * misc.c (map_pk_gcry_to_openpgp): New.
(openpgp_oid_from_str): New. Based on libksba code.
2011-01-26 Werner Koch <wk@g10code.com>
* misc.c (ecdsa_qbits_from_Q): Use unsigned int.
* misc.c (iobuf_read_size_body): Move and rename to ..
* parse-packet.c (read_size_body): .. here. Make static.
* misc.c (iobuf_write_size_body_mpi): Move and rename to ..
* build-packet.c (write_size_body_mpi): .. here.
(iobuf_name_oid_write, ecdh_kek_params_write, ecdh_esk_write):
Remove macros. Replace users by direct calls to
write_size_body_mpi.
2011-01-25 Werner Koch <wk@g10code.com> 2011-01-25 Werner Koch <wk@g10code.com>
@ -84,28 +71,17 @@
(pk_ecdh_encrypt): Remove. (pk_ecdh_encrypt): Remove.
(pk_ecdh_encrypt_with_shared_point): Make public. (pk_ecdh_encrypt_with_shared_point): Make public.
* pubkey-enc.c (get_it): Fix assertion. * pubkey-enc.c (get_it): Fix assertion. Use GPG_ERR_WRONG_SECKEY
Use GPG_ERR_WRONG_SECKEY instead of log_fatal. Add safety checks instead of log_fatal. Add safety checks for NFRAME.
for NFRAME.
* main.h (KEYGEN_FLAG_NO_PROTECTION, KEYGEN_FLAG_TRANSIENT_KEY): * keygen.c (pk_ecc_keypair_gen): Make static.
Move back to ..
* keygen.c: .. here.
(pk_ecc_keypair_gen): Make static.
(common_key_gen): Fold back into ..
(common_gen): .. this.
(delme__pk_ecc_build_sexp): Remove unused function.
(pk_ecc_keypair_gen): Fold it into ..
(gen_ecc): .. this.
(ask_keysize): Use proper rounding for ECC. (ask_keysize): Use proper rounding for ECC.
(pk_ecc_build_key_params): Remove NBITSSTR. (pk_ecc_build_key_params): Remove NBITSSTR.
* verify-stubs.c: Remove.
2011-01-20 Werner Koch <wk@g10code.com> 2011-01-20 Werner Koch <wk@g10code.com>
* keyserver.c: Rewrite most stuff for use with dirmngr. Get rid * keyserver.c: Rewrite most stuff for use with dirmngr. Get rid
of all spawn code. Work work pending. of all spawn code. More work pending.
* export.c (export_pubkeys_buffer): New. * export.c (export_pubkeys_buffer): New.
@ -116,6 +92,57 @@
* gpg.c: Include call-dirmngr.h. * gpg.c: Include call-dirmngr.h.
(gpg_deinit_default_ctrl): Call gpg_dirmngr_deinit_session_data. (gpg_deinit_default_ctrl): Call gpg_dirmngr_deinit_session_data.
2011-01-13 Andrey Jivsov <openpgp@brainhub.org> (wk)
Integrated ECC support. Below are the changes finally merged into
the git master after some cleanup by wk until 2011-02-03.
* ecdh.c: New.
* sign.c (mpi_from_sexp): Remove.
(match_dsa_hash): Uses SHA-512 for ECDSA with 521 bits.
(hash_for): Support ECDSA.
(make_keysig_packet): Ditto.
* seskey.c (encode_session_key): Add arg OPENPGP_PK_ALGO. Support
ECDH.
(encode_md_value): Map pkalgo. Extend size checks to ECDSA.
* pubkey-enc.c (get_it): Support ECDH.
* pkglue.c (mpi_from_sexp): Make global.
(pk_verify, pk_encrypt, pk_check_secret_key): Support ECC.
* parse-packet.c (read_size_body): New.
(parse_pubkeyenc): Support ECC.
(parse_key): Ditto.
* misc.c (map_pk_openpgp_to_gcry, map_pk_gcry_to_openpgp): New.
(openpgp_pk_test_algo, openpgp_pk_test_algo2): Map algo numbers.
(openpgp_pk_algo_usage): Support ECDH and ECDSA.
(openpgp_pk_algo_name): Simplify.
(ecdsa_qbits_from_Q): New.
* mainproc.c (proc_pubkey_enc): Support ECC.
* keyid.c (pubkey_letter): Add 'E' and 'e'.
(keygrip_from_pk): Supporf ECC.
* keygen.c: Include pkglue.h.
(ask_algo): Add option 9 for ECDSA and ECDH.
(ask_keysize): Support ECDSA and ECDH.
(do_create): Ditto.
(gen_ecc): New.
(pk_ecc_build_key_params): New.
* getkey.c (cache_public_key): Support ECC.
* encrypt.c (write_pubkey_enc_from_list): Pass PK to PK_ENCRYPT
and the pkalgo to encode_session_key.
* build-packet.c (do_key, do_pubkey_enc): Support ECC.
(write_size_body_mpi): New.
2011-01-06 Werner Koch <wk@g10code.com> 2011-01-06 Werner Koch <wk@g10code.com>
* gpg.c (main): Use keyserver_spec_t. * gpg.c (main): Use keyserver_spec_t.

View File

@ -55,7 +55,7 @@
#define KEYGEN_FLAG_TRANSIENT_KEY 2 #define KEYGEN_FLAG_TRANSIENT_KEY 2
/* Maximum number of supported algorithm preferences. */ /* Maximum number of supported algorithm preferences. */
#define MAX_PREFS 30 #define MAX_PREFS 30
enum para_name { enum para_name {
pKEYTYPE, pKEYTYPE,
@ -148,7 +148,7 @@ print_status_key_created (int letter, PKT_public_key *pk, const char *handle)
byte array[MAX_FINGERPRINT_LEN], *s; byte array[MAX_FINGERPRINT_LEN], *s;
char *buf, *p; char *buf, *p;
size_t i, n; size_t i, n;
if (!handle) if (!handle)
handle = ""; handle = "";
@ -216,7 +216,7 @@ do_add_key_flags (PKT_signature *sig, unsigned int use)
if (use & PUBKEY_USAGE_AUTH) if (use & PUBKEY_USAGE_AUTH)
buf[0] |= 0x20; buf[0] |= 0x20;
if (!buf[0]) if (!buf[0])
return; return;
build_sig_subpkt (sig, SIGSUBPKT_KEY_FLAGS, buf, 1); build_sig_subpkt (sig, SIGSUBPKT_KEY_FLAGS, buf, 1);
@ -229,14 +229,14 @@ keygen_add_key_expire (PKT_signature *sig, void *opaque)
PKT_public_key *pk = opaque; PKT_public_key *pk = opaque;
byte buf[8]; byte buf[8];
u32 u; u32 u;
if (pk->expiredate) if (pk->expiredate)
{ {
if (pk->expiredate > pk->timestamp) if (pk->expiredate > pk->timestamp)
u = pk->expiredate - pk->timestamp; u = pk->expiredate - pk->timestamp;
else else
u = 1; u = 1;
buf[0] = (u >> 24) & 0xff; buf[0] = (u >> 24) & 0xff;
buf[1] = (u >> 16) & 0xff; buf[1] = (u >> 16) & 0xff;
buf[2] = (u >> 8) & 0xff; buf[2] = (u >> 8) & 0xff;
@ -258,7 +258,7 @@ static int
keygen_add_key_flags_and_expire (PKT_signature *sig, void *opaque) keygen_add_key_flags_and_expire (PKT_signature *sig, void *opaque)
{ {
struct opaque_data_usage_and_pk *oduap = opaque; struct opaque_data_usage_and_pk *oduap = opaque;
do_add_key_flags (sig, oduap->usage); do_add_key_flags (sig, oduap->usage);
return keygen_add_key_expire (sig, oduap->pk); return keygen_add_key_expire (sig, oduap->pk);
} }
@ -325,7 +325,7 @@ keygen_set_std_prefs (const char *string,int personal)
gpg -r pgpkey -r gpgkey ---gives--> AES256 gpg -r pgpkey -r gpgkey ---gives--> AES256
gpg -r gpgkey -r pgpkey ---gives--> AES gpg -r gpgkey -r pgpkey ---gives--> AES
Note that by using --personal-cipher-preferences it is Note that by using --personal-cipher-preferences it is
possible to prefer AES128. possible to prefer AES128.
*/ */
@ -392,7 +392,7 @@ keygen_set_std_prefs (const char *string,int personal)
strcat(dummy_string,"Z1 "); strcat(dummy_string,"Z1 ");
any_compress = 1; any_compress = 1;
} }
/* In case we have no compress algo at all, declare that /* In case we have no compress algo at all, declare that
we prefer no compresssion. */ we prefer no compresssion. */
if (!any_compress) if (!any_compress)
@ -676,18 +676,18 @@ int
keygen_upd_std_prefs (PKT_signature *sig, void *opaque) keygen_upd_std_prefs (PKT_signature *sig, void *opaque)
{ {
(void)opaque; (void)opaque;
if (!prefs_initialized) if (!prefs_initialized)
keygen_set_std_prefs (NULL, 0); keygen_set_std_prefs (NULL, 0);
if (nsym_prefs) if (nsym_prefs)
build_sig_subpkt (sig, SIGSUBPKT_PREF_SYM, sym_prefs, nsym_prefs); build_sig_subpkt (sig, SIGSUBPKT_PREF_SYM, sym_prefs, nsym_prefs);
else else
{ {
delete_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_SYM); delete_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_SYM);
delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PREF_SYM); delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PREF_SYM);
} }
if (nhash_prefs) if (nhash_prefs)
build_sig_subpkt (sig, SIGSUBPKT_PREF_HASH, hash_prefs, nhash_prefs); build_sig_subpkt (sig, SIGSUBPKT_PREF_HASH, hash_prefs, nhash_prefs);
else else
@ -703,7 +703,7 @@ keygen_upd_std_prefs (PKT_signature *sig, void *opaque)
delete_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_COMPR); delete_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_COMPR);
delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PREF_COMPR); delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PREF_COMPR);
} }
/* Make sure that the MDC feature flag is set if needed. */ /* Make sure that the MDC feature flag is set if needed. */
add_feature_mdc (sig,mdc_available); add_feature_mdc (sig,mdc_available);
add_keyserver_modify (sig,ks_modify); add_keyserver_modify (sig,ks_modify);
@ -721,12 +721,12 @@ int
keygen_add_std_prefs (PKT_signature *sig, void *opaque) keygen_add_std_prefs (PKT_signature *sig, void *opaque)
{ {
PKT_public_key *pk = opaque; PKT_public_key *pk = opaque;
do_add_key_flags (sig, pk->pubkey_usage); do_add_key_flags (sig, pk->pubkey_usage);
keygen_add_key_expire (sig, opaque ); keygen_add_key_expire (sig, opaque );
keygen_upd_std_prefs (sig, opaque); keygen_upd_std_prefs (sig, opaque);
keygen_add_keyserver_url (sig,NULL); keygen_add_keyserver_url (sig,NULL);
return 0; return 0;
} }
@ -840,7 +840,7 @@ make_backsig (PKT_signature *sig, PKT_public_key *pk,
/* Get it into a binary packed form. */ /* Get it into a binary packed form. */
IOBUF backsig_out = iobuf_temp(); IOBUF backsig_out = iobuf_temp();
PACKET backsig_pkt; PACKET backsig_pkt;
init_packet (&backsig_pkt); init_packet (&backsig_pkt);
backsig_pkt.pkttype = PKT_SIGNATURE; backsig_pkt.pkttype = PKT_SIGNATURE;
backsig_pkt.pkt.signature = backsig; backsig_pkt.pkt.signature = backsig;
@ -852,15 +852,15 @@ make_backsig (PKT_signature *sig, PKT_public_key *pk,
{ {
size_t pktlen = 0; size_t pktlen = 0;
byte *buf = iobuf_get_temp_buffer (backsig_out); byte *buf = iobuf_get_temp_buffer (backsig_out);
/* Remove the packet header. */ /* Remove the packet header. */
if(buf[0]&0x40) if(buf[0]&0x40)
{ {
if (buf[1] < 192) if (buf[1] < 192)
{ {
pktlen = buf[1]; pktlen = buf[1];
buf += 2; buf += 2;
} }
else if(buf[1] < 224) else if(buf[1] < 224)
{ {
pktlen = (buf[1]-192)*256; pktlen = (buf[1]-192)*256;
@ -881,34 +881,34 @@ make_backsig (PKT_signature *sig, PKT_public_key *pk,
else else
{ {
int mark = 1; int mark = 1;
switch (buf[0]&3) switch (buf[0]&3)
{ {
case 3: case 3:
BUG (); BUG ();
break; break;
case 2: case 2:
pktlen = buf[mark++] << 24; pktlen = buf[mark++] << 24;
pktlen |= buf[mark++] << 16; pktlen |= buf[mark++] << 16;
case 1: case 1:
pktlen |= buf[mark++] << 8; pktlen |= buf[mark++] << 8;
case 0: case 0:
pktlen |= buf[mark++]; pktlen |= buf[mark++];
} }
buf += mark; buf += mark;
} }
/* Now make the binary blob into a subpacket. */ /* Now make the binary blob into a subpacket. */
build_sig_subpkt (sig, SIGSUBPKT_SIGNATURE, buf, pktlen); build_sig_subpkt (sig, SIGSUBPKT_SIGNATURE, buf, pktlen);
iobuf_close (backsig_out); iobuf_close (backsig_out);
} }
} }
return err; return err;
} }
@ -949,7 +949,7 @@ write_direct_sig (KBNODE root, PKT_public_key *psk,
log_error ("make_keysig_packet failed: %s\n", g10_errstr (err) ); log_error ("make_keysig_packet failed: %s\n", g10_errstr (err) );
return err; return err;
} }
pkt = xmalloc_clear (sizeof *pkt); pkt = xmalloc_clear (sizeof *pkt);
pkt->pkttype = PKT_SIGNATURE; pkt->pkttype = PKT_SIGNATURE;
pkt->pkt.signature = sig; pkt->pkt.signature = sig;
@ -990,7 +990,7 @@ write_selfsigs (KBNODE root, PKT_public_key *psk,
/* The usage has not yet been set - do it now. */ /* The usage has not yet been set - do it now. */
pk->pubkey_usage = use; pk->pubkey_usage = use;
/* We have to cache the key, so that the verification of the /* We have to cache the key, so that the verification of the
signature creation is able to retrieve the public key. */ signature creation is able to retrieve the public key. */
cache_public_key (pk); cache_public_key (pk);
@ -999,7 +999,7 @@ write_selfsigs (KBNODE root, PKT_public_key *psk,
err = make_keysig_packet (&sig, pk, uid, NULL, psk, 0x13, err = make_keysig_packet (&sig, pk, uid, NULL, psk, 0x13,
0, 0, timestamp, 0, 0, 0, timestamp, 0,
keygen_add_std_prefs, pk, cache_nonce); keygen_add_std_prefs, pk, cache_nonce);
if (err) if (err)
{ {
log_error ("make_keysig_packet failed: %s\n", g10_errstr (err)); log_error ("make_keysig_packet failed: %s\n", g10_errstr (err));
return err; return err;
@ -1041,10 +1041,10 @@ write_keybinding (KBNODE root, PKT_public_key *pri_psk, PKT_public_key *sub_psk,
/* We have to cache the key, so that the verification of the /* We have to cache the key, so that the verification of the
* signature creation is able to retrieve the public key. */ * signature creation is able to retrieve the public key. */
cache_public_key (pri_pk); cache_public_key (pri_pk);
/* Find the last subkey. */ /* Find the last subkey. */
sub_pk = NULL; sub_pk = NULL;
for (node = root; node; node = node->next ) for (node = root; node; node = node->next )
{ {
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
sub_pk = node->pkt->pkt.public_key; sub_pk = node->pkt->pkt.public_key;
@ -1055,11 +1055,11 @@ write_keybinding (KBNODE root, PKT_public_key *pri_psk, PKT_public_key *sub_psk,
/* Make the signature. */ /* Make the signature. */
oduap.usage = use; oduap.usage = use;
oduap.pk = sub_pk; oduap.pk = sub_pk;
err = make_keysig_packet (&sig, pri_pk, NULL, sub_pk, pri_psk, 0x18, err = make_keysig_packet (&sig, pri_pk, NULL, sub_pk, pri_psk, 0x18,
0, 0, timestamp, 0, 0, 0, timestamp, 0,
keygen_add_key_flags_and_expire, &oduap, keygen_add_key_flags_and_expire, &oduap,
cache_nonce); cache_nonce);
if (err) if (err)
{ {
log_error ("make_keysig_packet failed: %s\n", g10_errstr (err)); log_error ("make_keysig_packet failed: %s\n", g10_errstr (err));
return err; return err;
@ -1072,7 +1072,7 @@ write_keybinding (KBNODE root, PKT_public_key *pri_psk, PKT_public_key *sub_psk,
if (err) if (err)
return err; return err;
} }
pkt = xmalloc_clear ( sizeof *pkt ); pkt = xmalloc_clear ( sizeof *pkt );
pkt->pkttype = PKT_SIGNATURE; pkt->pkttype = PKT_SIGNATURE;
pkt->pkt.signature = sig; pkt->pkt.signature = sig;
@ -1203,7 +1203,7 @@ ecckey_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp, int algo)
/* Extract key parameters from SEXP and store them in ARRAY. ELEMS is /* Extract key parameters from SEXP and store them in ARRAY. ELEMS is
a string where each character denotes a parameter name. TOPNAME is a string where each character denotes a parameter name. TOPNAME is
the name of the top element above the elements. */ the name of the top element above the elements. */
static int static int
key_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp, key_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp,
const char *topname, const char *elems) const char *topname, const char *elems)
@ -1232,7 +1232,7 @@ key_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp,
} }
array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
gcry_sexp_release (l2); gcry_sexp_release (l2);
if (!array[idx]) if (!array[idx])
{ {
rc = gpg_error (GPG_ERR_INV_OBJ); /* required parameter invalid */ rc = gpg_error (GPG_ERR_INV_OBJ); /* required parameter invalid */
goto leave; goto leave;
@ -1272,7 +1272,7 @@ common_gen (const char *keyparms, int algo, const char *algoelem,
log_error ("agent_genkey failed: %s\n", gpg_strerror (err) ); log_error ("agent_genkey failed: %s\n", gpg_strerror (err) );
return err; return err;
} }
pk = xtrycalloc (1, sizeof *pk); pk = xtrycalloc (1, sizeof *pk);
if (!pk) if (!pk)
{ {
@ -1283,7 +1283,7 @@ common_gen (const char *keyparms, int algo, const char *algoelem,
pk->timestamp = timestamp; pk->timestamp = timestamp;
pk->version = 4; pk->version = 4;
if (expireval) if (expireval)
pk->expiredate = pk->timestamp + expireval; pk->expiredate = pk->timestamp + expireval;
pk->pubkey_algo = algo; pk->pubkey_algo = algo;
@ -1291,14 +1291,15 @@ common_gen (const char *keyparms, int algo, const char *algoelem,
err = ecckey_from_sexp (pk->pkey, s_key, algo); err = ecckey_from_sexp (pk->pkey, s_key, algo);
else else
err = key_from_sexp (pk->pkey, s_key, "public-key", algoelem); err = key_from_sexp (pk->pkey, s_key, "public-key", algoelem);
if (err) if (err)
{ {
log_error ("key_from_sexp failed: %s\n", gpg_strerror (err) ); log_error ("key_from_sexp failed: %s\n", gpg_strerror (err) );
gcry_sexp_release (s_key); gcry_sexp_release (s_key);
free_public_key (pk); free_public_key (pk);
return err; return err;
} }
gcry_sexp_release (s_key);
pkt = xtrycalloc (1, sizeof *pkt); pkt = xtrycalloc (1, sizeof *pkt);
if (!pkt) if (!pkt)
{ {
@ -1326,7 +1327,7 @@ gen_elg (int algo, unsigned int nbits, KBNODE pub_root,
int err; int err;
char *keyparms; char *keyparms;
char nbitsstr[35]; char nbitsstr[35];
assert (is_ELGAMAL (algo)); assert (is_ELGAMAL (algo));
if (nbits < 512) if (nbits < 512)
@ -1355,7 +1356,7 @@ gen_elg (int algo, unsigned int nbits, KBNODE pub_root,
err = gpg_error_from_syserror (); err = gpg_error_from_syserror ();
else else
{ {
err = common_gen (keyparms, algo, "pgy", err = common_gen (keyparms, algo, "pgy",
pub_root, timestamp, expireval, is_subkey, pub_root, timestamp, expireval, is_subkey,
keygen_flags, cache_nonce_addr); keygen_flags, cache_nonce_addr);
xfree (keyparms); xfree (keyparms);
@ -1369,7 +1370,7 @@ gen_elg (int algo, unsigned int nbits, KBNODE pub_root,
* Generate an DSA key * Generate an DSA key
*/ */
static gpg_error_t static gpg_error_t
gen_dsa (unsigned int nbits, KBNODE pub_root, gen_dsa (unsigned int nbits, KBNODE pub_root,
u32 timestamp, u32 expireval, int is_subkey, u32 timestamp, u32 expireval, int is_subkey,
int keygen_flags, char **cache_nonce_addr) int keygen_flags, char **cache_nonce_addr)
{ {
@ -1379,7 +1380,7 @@ gen_dsa (unsigned int nbits, KBNODE pub_root,
char nbitsstr[35]; char nbitsstr[35];
char qbitsstr[35]; char qbitsstr[35];
if ( nbits < 512) if ( nbits < 512)
{ {
nbits = 1024; nbits = 1024;
log_info(_("keysize invalid; using %u bits\n"), nbits ); log_info(_("keysize invalid; using %u bits\n"), nbits );
@ -1406,26 +1407,26 @@ gen_dsa (unsigned int nbits, KBNODE pub_root,
/* /*
Figure out a q size based on the key size. FIPS 180-3 says: Figure out a q size based on the key size. FIPS 180-3 says:
L = 1024, N = 160 L = 1024, N = 160
L = 2048, N = 224 L = 2048, N = 224
L = 2048, N = 256 L = 2048, N = 256
L = 3072, N = 256 L = 3072, N = 256
2048/256 is an odd pair since there is also a 2048/224 and 2048/256 is an odd pair since there is also a 2048/224 and
3072/256. Matching sizes is not a very exact science. 3072/256. Matching sizes is not a very exact science.
We'll do 256 qbits for nbits over 2047, 224 for nbits over 1024 We'll do 256 qbits for nbits over 2047, 224 for nbits over 1024
but less than 2048, and 160 for 1024 (DSA1). but less than 2048, and 160 for 1024 (DSA1).
*/ */
if (nbits > 2047) if (nbits > 2047)
qbits = 256; qbits = 256;
else if ( nbits > 1024) else if ( nbits > 1024)
qbits = 224; qbits = 224;
else else
qbits = 160; qbits = 160;
if (qbits != 160 ) if (qbits != 160 )
log_info (_("WARNING: some OpenPGP programs can't" log_info (_("WARNING: some OpenPGP programs can't"
" handle a DSA key with this digest size\n")); " handle a DSA key with this digest size\n"));
@ -1442,7 +1443,7 @@ gen_dsa (unsigned int nbits, KBNODE pub_root,
err = gpg_error_from_syserror (); err = gpg_error_from_syserror ();
else else
{ {
err = common_gen (keyparms, PUBKEY_ALGO_DSA, "pqgy", err = common_gen (keyparms, PUBKEY_ALGO_DSA, "pqgy",
pub_root, timestamp, expireval, is_subkey, pub_root, timestamp, expireval, is_subkey,
keygen_flags, cache_nonce_addr); keygen_flags, cache_nonce_addr);
xfree (keyparms); xfree (keyparms);
@ -1473,10 +1474,10 @@ gen_ecc (int algo, unsigned int nbits, kbnode_t pub_root,
curve = "NIST P-256"; curve = "NIST P-256";
else if (nbits <= 384) else if (nbits <= 384)
curve = "NIST P-384"; curve = "NIST P-384";
else else
curve = "NIST P-521"; curve = "NIST P-521";
keyparms = xtryasprintf ("(genkey(%s(curve %zu:%s)%s))", keyparms = xtryasprintf ("(genkey(%s(curve %zu:%s)%s))",
algo == PUBKEY_ALGO_ECDSA ? "ecdsa" : "ecdh", algo == PUBKEY_ALGO_ECDSA ? "ecdsa" : "ecdh",
strlen (curve), curve, strlen (curve), curve,
((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY) ((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
@ -1496,7 +1497,7 @@ gen_ecc (int algo, unsigned int nbits, kbnode_t pub_root,
} }
/* /*
* Generate an RSA key. * Generate an RSA key.
*/ */
static int static int
@ -1513,12 +1514,12 @@ gen_rsa (int algo, unsigned int nbits, KBNODE pub_root,
if (!nbits) if (!nbits)
nbits = DEFAULT_STD_KEYSIZE; nbits = DEFAULT_STD_KEYSIZE;
if (nbits < 1024) if (nbits < 1024)
{ {
nbits = 1024; nbits = 1024;
log_info (_("keysize invalid; using %u bits\n"), nbits ); log_info (_("keysize invalid; using %u bits\n"), nbits );
} }
if ((nbits % 32)) if ((nbits % 32))
{ {
nbits = ((nbits + 31) / 32) * 32; nbits = ((nbits + 31) / 32) * 32;
@ -1526,7 +1527,7 @@ gen_rsa (int algo, unsigned int nbits, KBNODE pub_root,
} }
snprintf (nbitsstr, sizeof nbitsstr, "%u", nbits); snprintf (nbitsstr, sizeof nbitsstr, "%u", nbits);
keyparms = xtryasprintf ("(genkey(rsa(nbits %zu:%s)%s))", keyparms = xtryasprintf ("(genkey(rsa(nbits %zu:%s)%s))",
strlen (nbitsstr), nbitsstr, strlen (nbitsstr), nbitsstr,
((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY) ((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
&& (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))? && (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
@ -1535,7 +1536,7 @@ gen_rsa (int algo, unsigned int nbits, KBNODE pub_root,
err = gpg_error_from_syserror (); err = gpg_error_from_syserror ();
else else
{ {
err = common_gen (keyparms, algo, "ne", err = common_gen (keyparms, algo, "ne",
pub_root, timestamp, expireval, is_subkey, pub_root, timestamp, expireval, is_subkey,
keygen_flags, cache_nonce_addr); keygen_flags, cache_nonce_addr);
xfree (keyparms); xfree (keyparms);
@ -1704,7 +1705,7 @@ ask_algo (int addmode, int *r_subkey_algo, unsigned int *r_usage)
if (!r_subkey_algo) if (!r_subkey_algo)
r_subkey_algo = &dummy_algo; r_subkey_algo = &dummy_algo;
tty_printf (_("Please select what kind of key you want:\n")); tty_printf (_("Please select what kind of key you want:\n"));
if (!addmode) if (!addmode)
@ -1725,7 +1726,7 @@ ask_algo (int addmode, int *r_subkey_algo, unsigned int *r_usage)
tty_printf (_(" (%d) DSA (set your own capabilities)\n"), 7 ); tty_printf (_(" (%d) DSA (set your own capabilities)\n"), 7 );
tty_printf (_(" (%d) RSA (set your own capabilities)\n"), 8 ); tty_printf (_(" (%d) RSA (set your own capabilities)\n"), 8 );
} }
tty_printf (_(" (%d) ECDSA and ECDH\n"), 9 ); tty_printf (_(" (%d) ECDSA and ECDH\n"), 9 );
for(;;) for(;;)
@ -1793,7 +1794,7 @@ ask_algo (int addmode, int *r_subkey_algo, unsigned int *r_usage)
else else
tty_printf (_("Invalid selection.\n")); tty_printf (_("Invalid selection.\n"));
} }
return algo; return algo;
} }
@ -1863,7 +1864,7 @@ ask_keysize (int algo, unsigned int primary_keysize)
nbits = *answer? atoi (answer): def; nbits = *answer? atoi (answer): def;
xfree(prompt); xfree(prompt);
xfree(answer); xfree(answer);
if(nbits<min || nbits>max) if(nbits<min || nbits>max)
tty_printf(_("%s keysizes must be in the range %u-%u\n"), tty_printf(_("%s keysizes must be in the range %u-%u\n"),
openpgp_pk_algo_name (algo), min, max); openpgp_pk_algo_name (algo), min, max);
@ -1923,7 +1924,7 @@ parse_expire_string( const char *string )
u32 abs_date = 0; u32 abs_date = 0;
u32 curtime = make_timestamp (); u32 curtime = make_timestamp ();
time_t tt; time_t tt;
if (!*string) if (!*string)
seconds = 0; seconds = 0;
else if (!strncmp (string, "seconds=", 8)) else if (!strncmp (string, "seconds=", 8))
@ -1937,7 +1938,7 @@ parse_expire_string( const char *string )
seconds = atoi (string) * 86400L * mult; seconds = atoi (string) * 86400L * mult;
else else
seconds = (u32)(-1); seconds = (u32)(-1);
return seconds; return seconds;
} }
@ -1947,7 +1948,7 @@ static u32
parse_creation_string (const char *string) parse_creation_string (const char *string)
{ {
u32 seconds; u32 seconds;
if (!*string) if (!*string)
seconds = 0; seconds = 0;
else if ( !strncmp (string, "seconds=", 8) ) else if ( !strncmp (string, "seconds=", 8) )
@ -2242,7 +2243,7 @@ ask_user_id (int mode, KBNODE keyblock)
lower and uppercase. Below you will find the matching lower and uppercase. Below you will find the matching
string which should be translated accordingly and the string which should be translated accordingly and the
letter changed to match the one in the answer string. letter changed to match the one in the answer string.
n = Change name n = Change name
c = Change comment c = Change comment
e = Change email e = Change email
@ -2403,7 +2404,7 @@ PKT_user_id *
generate_user_id (KBNODE keyblock) generate_user_id (KBNODE keyblock)
{ {
char *p; char *p;
p = ask_user_id (1, keyblock); p = ask_user_id (1, keyblock);
if (!p) if (!p)
return NULL; /* Canceled. */ return NULL; /* Canceled. */
@ -2415,7 +2416,7 @@ static void
release_parameter_list (struct para_data_s *r) release_parameter_list (struct para_data_s *r)
{ {
struct para_data_s *r2; struct para_data_s *r2;
for (; r ; r = r2) for (; r ; r = r2)
{ {
r2 = r->next; r2 = r->next;
@ -2423,7 +2424,7 @@ release_parameter_list (struct para_data_s *r)
xfree (r->u.dek); xfree (r->u.dek);
else if (r->key == pPASSPHRASE_S2K ) else if (r->key == pPASSPHRASE_S2K )
xfree (r->u.s2k); xfree (r->u.s2k);
xfree (r); xfree (r);
} }
} }
@ -2446,7 +2447,7 @@ get_parameter_value( struct para_data_s *para, enum para_name key )
} }
static int static int
get_parameter_algo( struct para_data_s *para, enum para_name key, get_parameter_algo( struct para_data_s *para, enum para_name key,
int *r_default) int *r_default)
{ {
int i; int i;
@ -2479,7 +2480,7 @@ get_parameter_algo( struct para_data_s *para, enum para_name key,
return i; return i;
} }
/* /*
* Parse the usage parameter and set the keyflags. Returns -1 on * Parse the usage parameter and set the keyflags. Returns -1 on
* error, 0 for no usage given or 1 for usage available. * error, 0 for no usage given or 1 for usage available.
*/ */
@ -2493,7 +2494,7 @@ parse_parameter_usage (const char *fname,
if( !r ) if( !r )
return 0; /* none (this is an optional parameter)*/ return 0; /* none (this is an optional parameter)*/
use = 0; use = 0;
pn = r->u.value; pn = r->u.value;
while ( (p = strsep (&pn, " \t,")) ) { while ( (p = strsep (&pn, " \t,")) ) {
@ -2581,7 +2582,7 @@ get_parameter_u32( struct para_data_s *para, enum para_name key )
return r->u.expire; return r->u.expire;
if( r->key == pKEYUSAGE || r->key == pSUBKEYUSAGE ) if( r->key == pKEYUSAGE || r->key == pSUBKEYUSAGE )
return r->u.usage; return r->u.usage;
return (unsigned int)strtoul( r->u.value, NULL, 10 ); return (unsigned int)strtoul( r->u.value, NULL, 10 );
} }
@ -2775,7 +2776,7 @@ proc_parameter_file( struct para_data_s *para, const char *fname,
para = r; para = r;
} }
if (canceled) if (canceled)
{ {
log_error ("%s:%d: key generation canceled\n", fname, r->lnr ); log_error ("%s:%d: key generation canceled\n", fname, r->lnr );
return -1; return -1;
@ -2791,7 +2792,7 @@ proc_parameter_file( struct para_data_s *para, const char *fname,
* but because we do this always, why not here. */ * but because we do this always, why not here. */
STRING2KEY *s2k; STRING2KEY *s2k;
DEK *dek; DEK *dek;
s2k = xmalloc_secure ( sizeof *s2k ); s2k = xmalloc_secure ( sizeof *s2k );
s2k->mode = opt.s2k_mode; s2k->mode = opt.s2k_mode;
s2k->hash_algo = S2K_DIGEST_ALGO; s2k->hash_algo = S2K_DIGEST_ALGO;
@ -2801,7 +2802,7 @@ proc_parameter_file( struct para_data_s *para, const char *fname,
set_next_passphrase (NULL ); set_next_passphrase (NULL );
assert (dek); assert (dek);
memset (r->u.value, 0, strlen(r->u.value)); memset (r->u.value, 0, strlen(r->u.value));
r = xmalloc_clear (sizeof *r); r = xmalloc_clear (sizeof *r);
r->key = pPASSPHRASE_S2K; r->key = pPASSPHRASE_S2K;
r->u.s2k = s2k; r->u.s2k = s2k;
@ -2958,7 +2959,7 @@ read_parameter_file( const char *fname )
else if( !ascii_strcasecmp( keyword, "%commit" ) ) { else if( !ascii_strcasecmp( keyword, "%commit" ) ) {
outctrl.lnr = lnr; outctrl.lnr = lnr;
if (proc_parameter_file( para, fname, &outctrl, 0 )) if (proc_parameter_file( para, fname, &outctrl, 0 ))
print_status_key_not_created print_status_key_not_created
(get_parameter_value (para, pHANDLE)); (get_parameter_value (para, pHANDLE));
release_parameter_list( para ); release_parameter_list( para );
para = NULL; para = NULL;
@ -3052,7 +3053,7 @@ read_parameter_file( const char *fname )
/* Must invalidate that ugly cache to actually close it. */ /* Must invalidate that ugly cache to actually close it. */
if (outctrl.pub.fname) if (outctrl.pub.fname)
iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE,
0, (char*)outctrl.pub.fname); 0, (char*)outctrl.pub.fname);
xfree( outctrl.pub.fname ); xfree( outctrl.pub.fname );
@ -3073,7 +3074,7 @@ read_parameter_file( const char *fname )
* imported to the card and a backup file created by gpg-agent. * imported to the card and a backup file created by gpg-agent.
*/ */
void void
generate_keypair (const char *fname, const char *card_serialno, generate_keypair (const char *fname, const char *card_serialno,
int card_backup_key) int card_backup_key)
{ {
unsigned int nbits; unsigned int nbits;
@ -3085,16 +3086,16 @@ generate_keypair (const char *fname, const char *card_serialno,
struct para_data_s *para = NULL; struct para_data_s *para = NULL;
struct para_data_s *r; struct para_data_s *r;
struct output_control_s outctrl; struct output_control_s outctrl;
memset( &outctrl, 0, sizeof( outctrl ) ); memset( &outctrl, 0, sizeof( outctrl ) );
if (opt.batch && card_serialno) if (opt.batch && card_serialno)
{ {
/* We don't yet support unattended key generation. */ /* We don't yet support unattended key generation. */
log_error (_("can't do this in batch mode\n")); log_error (_("can't do this in batch mode\n"));
return; return;
} }
if (opt.batch) if (opt.batch)
{ {
read_parameter_file( fname ); read_parameter_file( fname );
@ -3109,9 +3110,9 @@ generate_keypair (const char *fname, const char *card_serialno,
strcpy( r->u.value, card_serialno); strcpy( r->u.value, card_serialno);
r->next = para; r->next = para;
para = r; para = r;
algo = PUBKEY_ALGO_RSA; algo = PUBKEY_ALGO_RSA;
r = xcalloc (1, sizeof *r + 20 ); r = xcalloc (1, sizeof *r + 20 );
r->key = pKEYTYPE; r->key = pKEYTYPE;
sprintf( r->u.value, "%d", algo ); sprintf( r->u.value, "%d", algo );
@ -3122,7 +3123,7 @@ generate_keypair (const char *fname, const char *card_serialno,
strcpy (r->u.value, "sign"); strcpy (r->u.value, "sign");
r->next = para; r->next = para;
para = r; para = r;
r = xcalloc (1, sizeof *r + 20 ); r = xcalloc (1, sizeof *r + 20 );
r->key = pSUBKEYTYPE; r->key = pSUBKEYTYPE;
sprintf( r->u.value, "%d", algo ); sprintf( r->u.value, "%d", algo );
@ -3133,7 +3134,7 @@ generate_keypair (const char *fname, const char *card_serialno,
strcpy (r->u.value, "encrypt"); strcpy (r->u.value, "encrypt");
r->next = para; r->next = para;
para = r; para = r;
r = xcalloc (1, sizeof *r + 20 ); r = xcalloc (1, sizeof *r + 20 );
r->key = pAUTHKEYTYPE; r->key = pAUTHKEYTYPE;
sprintf( r->u.value, "%d", algo ); sprintf( r->u.value, "%d", algo );
@ -3152,11 +3153,11 @@ generate_keypair (const char *fname, const char *card_serialno,
} }
else else
{ {
int subkey_algo; int subkey_algo;
algo = ask_algo (0, &subkey_algo, &use); algo = ask_algo (0, &subkey_algo, &use);
if (subkey_algo) if (subkey_algo)
{ {
/* Create primary and subkey at once. */ /* Create primary and subkey at once. */
both = 1; both = 1;
r = xmalloc_clear( sizeof *r + 20 ); r = xmalloc_clear( sizeof *r + 20 );
@ -3175,7 +3176,7 @@ generate_keypair (const char *fname, const char *card_serialno,
strcpy( r->u.value, "sign" ); strcpy( r->u.value, "sign" );
r->next = para; r->next = para;
para = r; para = r;
r = xmalloc_clear( sizeof *r + 20 ); r = xmalloc_clear( sizeof *r + 20 );
r->key = pSUBKEYTYPE; r->key = pSUBKEYTYPE;
sprintf( r->u.value, "%d", subkey_algo); sprintf( r->u.value, "%d", subkey_algo);
@ -3187,14 +3188,14 @@ generate_keypair (const char *fname, const char *card_serialno,
r->next = para; r->next = para;
para = r; para = r;
} }
else else
{ {
r = xmalloc_clear( sizeof *r + 20 ); r = xmalloc_clear( sizeof *r + 20 );
r->key = pKEYTYPE; r->key = pKEYTYPE;
sprintf( r->u.value, "%d", algo ); sprintf( r->u.value, "%d", algo );
r->next = para; r->next = para;
para = r; para = r;
if (use) if (use)
{ {
r = xmalloc_clear( sizeof *r + 25 ); r = xmalloc_clear( sizeof *r + 25 );
@ -3216,7 +3217,7 @@ generate_keypair (const char *fname, const char *card_serialno,
r->next = para; r->next = para;
para = r; para = r;
} }
expire = ask_expire_interval(0,NULL); expire = ask_expire_interval(0,NULL);
r = xmalloc_clear( sizeof *r + 20 ); r = xmalloc_clear( sizeof *r + 20 );
r->key = pKEYEXPIRE; r->key = pKEYEXPIRE;
@ -3230,7 +3231,7 @@ generate_keypair (const char *fname, const char *card_serialno,
para = r; para = r;
uid = ask_user_id (0, NULL); uid = ask_user_id (0, NULL);
if( !uid ) if( !uid )
{ {
log_error(_("Key generation canceled.\n")); log_error(_("Key generation canceled.\n"));
release_parameter_list( para ); release_parameter_list( para );
@ -3241,7 +3242,7 @@ generate_keypair (const char *fname, const char *card_serialno,
strcpy( r->u.value, uid ); strcpy( r->u.value, uid );
r->next = para; r->next = para;
para = r; para = r;
proc_parameter_file( para, "[internal]", &outctrl, !!card_serialno); proc_parameter_file( para, "[internal]", &outctrl, !!card_serialno);
release_parameter_list( para ); release_parameter_list( para );
} }
@ -3276,7 +3277,7 @@ generate_raw_key (int algo, unsigned int nbits, u32 created_at,
log_info (_("keysize invalid; using %u bits\n"), nbits ); log_info (_("keysize invalid; using %u bits\n"), nbits );
} }
if ((nbits % 32)) if ((nbits % 32))
{ {
nbits = ((nbits + 31) / 32) * 32; nbits = ((nbits + 31) / 32) * 32;
log_info(_("keysize rounded up to %u bits\n"), nbits ); log_info(_("keysize rounded up to %u bits\n"), nbits );
@ -3314,16 +3315,16 @@ generate_raw_key (int algo, unsigned int nbits, u32 created_at,
} }
rc = key_from_sexp (sk->skey, s_key, "private-key", "nedpqu"); rc = key_from_sexp (sk->skey, s_key, "private-key", "nedpqu");
gcry_sexp_release (s_key); gcry_sexp_release (s_key);
if (rc) if (rc)
{ {
log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc) ); log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc) );
goto leave; goto leave;
} }
for (i=npkey; i < nskey; i++) for (i=npkey; i < nskey; i++)
sk->csum += checksum_mpi (sk->skey[i]); sk->csum += checksum_mpi (sk->skey[i]);
if (r_sk_unprotected) if (r_sk_unprotected)
*r_sk_unprotected = copy_secret_key (NULL, sk); *r_sk_unprotected = copy_secret_key (NULL, sk);
rc = genhelp_protect (dek, s2k, sk); rc = genhelp_protect (dek, s2k, sk);
@ -3377,10 +3378,10 @@ do_generate_keypair (struct para_data_s *para,
log_info("dry-run mode - key generation skipped\n"); log_info("dry-run mode - key generation skipped\n");
return; return;
} }
if ( outctrl->use_files ) if ( outctrl->use_files )
{ {
if ( outctrl->pub.newfname ) if ( outctrl->pub.newfname )
{ {
iobuf_close(outctrl->pub.stream); iobuf_close(outctrl->pub.stream);
outctrl->pub.stream = NULL; outctrl->pub.stream = NULL;
@ -3390,8 +3391,8 @@ do_generate_keypair (struct para_data_s *para,
xfree( outctrl->pub.fname ); xfree( outctrl->pub.fname );
outctrl->pub.fname = outctrl->pub.newfname; outctrl->pub.fname = outctrl->pub.newfname;
outctrl->pub.newfname = NULL; outctrl->pub.newfname = NULL;
if (is_secured_filename (outctrl->pub.fname) ) if (is_secured_filename (outctrl->pub.fname) )
{ {
outctrl->pub.stream = NULL; outctrl->pub.stream = NULL;
gpg_err_set_errno (EPERM); gpg_err_set_errno (EPERM);
@ -3420,7 +3421,7 @@ do_generate_keypair (struct para_data_s *para,
structure we create is known in advance we simply generate a structure we create is known in advance we simply generate a
linked list. The first packet is a dummy packet which we flag as linked list. The first packet is a dummy packet which we flag as
deleted. The very first packet must always be a KEY packet. */ deleted. The very first packet must always be a KEY packet. */
start_tree (&pub_root); start_tree (&pub_root);
timestamp = get_parameter_u32 (para, pKEYCREATIONDATE); timestamp = get_parameter_u32 (para, pKEYCREATIONDATE);
@ -3441,7 +3442,7 @@ do_generate_keypair (struct para_data_s *para,
get_parameter_uint( para, pKEYLENGTH ), get_parameter_uint( para, pKEYLENGTH ),
pub_root, pub_root,
timestamp, timestamp,
get_parameter_u32( para, pKEYEXPIRE ), 0, get_parameter_u32( para, pKEYEXPIRE ), 0,
outctrl->keygen_flags, &cache_nonce); outctrl->keygen_flags, &cache_nonce);
else else
err = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root, err = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root,
@ -3490,7 +3491,7 @@ do_generate_keypair (struct para_data_s *para,
{ {
err = do_create (get_parameter_algo (para, pSUBKEYTYPE, NULL), err = do_create (get_parameter_algo (para, pSUBKEYTYPE, NULL),
get_parameter_uint (para, pSUBKEYLENGTH), get_parameter_uint (para, pSUBKEYLENGTH),
pub_root, pub_root,
timestamp, timestamp,
get_parameter_u32 (para, pSUBKEYEXPIRE), 1, get_parameter_u32 (para, pSUBKEYEXPIRE), 1,
outctrl->keygen_flags, &cache_nonce); outctrl->keygen_flags, &cache_nonce);
@ -3498,7 +3499,7 @@ do_generate_keypair (struct para_data_s *para,
if (!err) if (!err)
{ {
kbnode_t node; kbnode_t node;
for (node = pub_root; node; node = node->next) for (node = pub_root; node; node = node->next)
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
sub_psk = node->pkt->pkt.public_key; sub_psk = node->pkt->pkt.public_key;
@ -3542,26 +3543,26 @@ do_generate_keypair (struct para_data_s *para,
KEYDB_HANDLE pub_hd = keydb_new (); KEYDB_HANDLE pub_hd = keydb_new ();
err = keydb_locate_writable (pub_hd, NULL); err = keydb_locate_writable (pub_hd, NULL);
if (err) if (err)
log_error (_("no writable public keyring found: %s\n"), log_error (_("no writable public keyring found: %s\n"),
g10_errstr (err)); g10_errstr (err));
if (!err && opt.verbose) if (!err && opt.verbose)
{ {
log_info (_("writing public key to `%s'\n"), log_info (_("writing public key to `%s'\n"),
keydb_get_resource_name (pub_hd)); keydb_get_resource_name (pub_hd));
} }
if (!err) if (!err)
{ {
err = keydb_insert_keyblock (pub_hd, pub_root); err = keydb_insert_keyblock (pub_hd, pub_root);
if (err) if (err)
log_error (_("error writing public keyring `%s': %s\n"), log_error (_("error writing public keyring `%s': %s\n"),
keydb_get_resource_name (pub_hd), g10_errstr(err)); keydb_get_resource_name (pub_hd), g10_errstr(err));
} }
keydb_release (pub_hd); keydb_release (pub_hd);
if (!err) if (!err)
{ {
int no_enc_rsa; int no_enc_rsa;
@ -3581,14 +3582,14 @@ do_generate_keypair (struct para_data_s *para,
update_ownertrust (pk, ((get_ownertrust (pk) & ~TRUST_MASK) update_ownertrust (pk, ((get_ownertrust (pk) & ~TRUST_MASK)
| TRUST_ULTIMATE )); | TRUST_ULTIMATE ));
if (!opt.batch) if (!opt.batch)
{ {
tty_printf (_("public and secret key created and signed.\n") ); tty_printf (_("public and secret key created and signed.\n") );
tty_printf ("\n"); tty_printf ("\n");
list_keyblock (pub_root, 0, 1, NULL); list_keyblock (pub_root, 0, 1, NULL);
} }
if (!opt.batch if (!opt.batch
&& (get_parameter_algo (para, pKEYTYPE, NULL) == PUBKEY_ALGO_DSA && (get_parameter_algo (para, pKEYTYPE, NULL) == PUBKEY_ALGO_DSA
|| no_enc_rsa ) || no_enc_rsa )
@ -3613,12 +3614,12 @@ do_generate_keypair (struct para_data_s *para,
} }
else else
{ {
PKT_public_key *pk = find_kbnode (pub_root, PKT_public_key *pk = find_kbnode (pub_root,
PKT_PUBLIC_KEY)->pkt->pkt.public_key; PKT_PUBLIC_KEY)->pkt->pkt.public_key;
print_status_key_created (did_sub? 'B':'P', pk, print_status_key_created (did_sub? 'B':'P', pk,
get_parameter_value (para, pHANDLE)); get_parameter_value (para, pHANDLE));
} }
release_kbnode (pub_root); release_kbnode (pub_root);
xfree (cache_nonce); xfree (cache_nonce);
} }
@ -3643,7 +3644,7 @@ generate_subkeypair (KBNODE keyblock)
/* Break out the primary key. */ /* Break out the primary key. */
node = find_kbnode (keyblock, PKT_PUBLIC_KEY); node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
if (!node) if (!node)
{ {
log_error ("Oops; primary key missing in keyblock!\n"); log_error ("Oops; primary key missing in keyblock!\n");
err = gpg_error (GPG_ERR_BUG); err = gpg_error (GPG_ERR_BUG);
@ -3667,7 +3668,7 @@ generate_subkeypair (KBNODE keyblock)
} }
} }
if (pri_psk->version < 4) if (pri_psk->version < 4)
{ {
log_info (_("NOTE: creating subkeys for v3 keys " log_info (_("NOTE: creating subkeys for v3 keys "
"is not OpenPGP compliant\n")); "is not OpenPGP compliant\n"));
@ -3695,7 +3696,7 @@ generate_subkeypair (KBNODE keyblock)
{ {
err = gpg_error (GPG_ERR_CANCELED); err = gpg_error (GPG_ERR_CANCELED);
goto leave; goto leave;
} }
err = do_create (algo, nbits, keyblock, cur_time, expire, 1, 0, NULL); err = do_create (algo, nbits, keyblock, cur_time, expire, 1, 0, NULL);
if (err) if (err)
@ -3803,7 +3804,7 @@ generate_card_subkeypair (kbnode_t pub_keyblock,
if (!err) if (!err)
{ {
PKT_public_key *sub_pk = NULL; PKT_public_key *sub_pk = NULL;
for (node = pub_keyblock; node; node = node->next) for (node = pub_keyblock; node; node = node->next)
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
sub_pk = node->pkt->pkt.public_key; sub_pk = node->pkt->pkt.public_key;
@ -3848,7 +3849,7 @@ write_keyblock( IOBUF out, KBNODE node )
/* Note that timestamp is an in/out arg. */ /* Note that timestamp is an in/out arg. */
static gpg_error_t static gpg_error_t
gen_card_key (int algo, int keyno, int is_primary, kbnode_t pub_root, gen_card_key (int algo, int keyno, int is_primary, kbnode_t pub_root,
u32 *timestamp, u32 expireval) u32 *timestamp, u32 expireval)
{ {
#ifdef ENABLE_CARD_SUPPORT #ifdef ENABLE_CARD_SUPPORT
@ -3869,11 +3870,11 @@ gen_card_key (int algo, int keyno, int is_primary, kbnode_t pub_root,
xfree (pk); xfree (pk);
return gpg_error_from_syserror (); return gpg_error_from_syserror ();
} }
/* Note: SCD knows the serialnumber, thus there is no point in passing it. */ /* Note: SCD knows the serialnumber, thus there is no point in passing it. */
err = agent_scd_genkey (&info, keyno, 1, NULL, *timestamp); err = agent_scd_genkey (&info, keyno, 1, NULL, *timestamp);
/* The code below is not used because we force creation of /* The code below is not used because we force creation of
* the a card key (3rd arg). * the a card key (3rd arg).
* if (gpg_err_code (rc) == GPG_ERR_EEXIST) * if (gpg_err_code (rc) == GPG_ERR_EEXIST)
* { * {
* tty_printf ("\n"); * tty_printf ("\n");
@ -3898,7 +3899,7 @@ gen_card_key (int algo, int keyno, int is_primary, kbnode_t pub_root,
xfree (pk); xfree (pk);
return err; return err;
} }
if (*timestamp != info.created_at) if (*timestamp != info.created_at)
log_info ("NOTE: the key does not use the suggested creation date\n"); log_info ("NOTE: the key does not use the suggested creation date\n");
*timestamp = info.created_at; *timestamp = info.created_at;
@ -3909,7 +3910,7 @@ gen_card_key (int algo, int keyno, int is_primary, kbnode_t pub_root,
pk->expiredate = pk->timestamp + expireval; pk->expiredate = pk->timestamp + expireval;
pk->pubkey_algo = algo; pk->pubkey_algo = algo;
pk->pkey[0] = info.n; pk->pkey[0] = info.n;
pk->pkey[1] = info.e; pk->pkey[1] = info.e;
pkt->pkttype = is_primary ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; pkt->pkttype = is_primary ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY;
pkt->pkt.public_key = pk; pkt->pkt.public_key = pk;
@ -3937,11 +3938,11 @@ gen_card_key_with_backup (int algo, int keyno, int is_primary,
size_t n; size_t n;
int i; int i;
unsigned int nbits; unsigned int nbits;
/* Get the size of the key directly from the card. */ /* Get the size of the key directly from the card. */
{ {
struct agent_card_info_s info; struct agent_card_info_s info;
memset (&info, 0, sizeof info); memset (&info, 0, sizeof info);
if (!agent_scd_getattr ("KEY-ATTR", &info) if (!agent_scd_getattr ("KEY-ATTR", &info)
&& info.key_attr[1].algo) && info.key_attr[1].algo)
@ -4007,7 +4008,7 @@ gen_card_key_with_backup (int algo, int keyno, int is_primary,
else else
fp = iobuf_create (fname); fp = iobuf_create (fname);
umask (oldmask); umask (oldmask);
if (!fp) if (!fp)
{ {
rc = gpg_error_from_syserror (); rc = gpg_error_from_syserror ();
log_error (_("can't create backup file `%s': %s\n"), log_error (_("can't create backup file `%s': %s\n"),
@ -4033,7 +4034,7 @@ gen_card_key_with_backup (int algo, int keyno, int is_primary,
{ {
unsigned char array[MAX_FINGERPRINT_LEN]; unsigned char array[MAX_FINGERPRINT_LEN];
char *fprbuf, *p; char *fprbuf, *p;
iobuf_close (fp); iobuf_close (fp);
iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)fname); iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)fname);
log_info (_("NOTE: backup of card key saved to `%s'\n"), fname); log_info (_("NOTE: backup of card key saved to `%s'\n"), fname);
@ -4150,7 +4151,7 @@ save_unprotected_key_to_card (PKT_public_key *sk, int keyno)
p = stpcpy (stpcpy (stpcpy (p, numbuf), numbuf2), "))"); p = stpcpy (stpcpy (stpcpy (p, numbuf), numbuf2), "))");
/* Fixme: Unfortunately we don't have the serialnumber available - /* Fixme: Unfortunately we don't have the serialnumber available -
thus we can't pass it down to the agent. */ thus we can't pass it down to the agent. */
rc = agent_scd_writekey (keyno, NULL, sexp, p - sexp); rc = agent_scd_writekey (keyno, NULL, sexp, p - sexp);
leave: leave:

View File

@ -184,8 +184,6 @@ pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
{ {
gcry_mpi_t k; gcry_mpi_t k;
char *curve; char *curve;
byte fp[MAX_FINGERPRINT_LEN];
size_t fpn;
rc = pk_ecdh_generate_ephemeral_key (pkey, &k); rc = pk_ecdh_generate_ephemeral_key (pkey, &k);
if (rc) if (rc)

View File

@ -160,7 +160,7 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
if (!enc->data[0] || !enc->data[1]) if (!enc->data[0] || !enc->data[1])
err = gpg_error (GPG_ERR_BAD_MPI); err = gpg_error (GPG_ERR_BAD_MPI);
else else
err = gcry_sexp_build (&s_data, NULL, "(enc-val(elg(a%m)(b%m)))", err = gcry_sexp_build (&s_data, NULL, "(enc-val(elg(a%m)(b%m)))",
enc->data[0], enc->data[1]); enc->data[0], enc->data[1]);
} }
else if (pkalgo == GCRY_PK_RSA || pkalgo == GCRY_PK_RSA_E) else if (pkalgo == GCRY_PK_RSA || pkalgo == GCRY_PK_RSA_E)
@ -185,9 +185,11 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
if (err) if (err)
goto leave; goto leave;
/* fixme: only needed for ECDH. Don't compute always. */ if (sk->pubkey_algo == PUBKEY_ALGO_ECDH)
fingerprint_from_pk (sk, fp, &fpn); {
assert (fpn == 20); fingerprint_from_pk (sk, fp, &fpn);
assert (fpn == 20);
}
/* Decrypt. */ /* Decrypt. */
desc = gpg_format_keydesc (sk, 0, 1); desc = gpg_format_keydesc (sk, 0, 1);

View File

@ -49,10 +49,10 @@ make_session_key( DEK *dek )
0 : GCRY_CIPHER_ENABLE_SYNC))) ) 0 : GCRY_CIPHER_ENABLE_SYNC))) )
BUG(); BUG();
gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM ); gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM );
for (i=0; i < 16; i++ ) for (i=0; i < 16; i++ )
{ {
rc = gcry_cipher_setkey (chd, dek->key, dek->keylen); rc = gcry_cipher_setkey (chd, dek->key, dek->keylen);
if (!rc) if (!rc)
{ {
gcry_cipher_close (chd); gcry_cipher_close (chd);
return; return;
@ -82,7 +82,7 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
int i,n; int i,n;
u16 csum; u16 csum;
gcry_mpi_t a; gcry_mpi_t a;
if (DBG_CIPHER) if (DBG_CIPHER)
log_debug ("encode_session_key: encoding %d byte DEK", dek->keylen); log_debug ("encode_session_key: encoding %d byte DEK", dek->keylen);
@ -102,10 +102,10 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
*/ */
nframe = (( 1 + dek->keylen + 2 /* The value so far is always odd. */ nframe = (( 1 + dek->keylen + 2 /* The value so far is always odd. */
+ 7 ) & (~7)); + 7 ) & (~7));
/* alg+key+csum fit and the size is congruent to 8. */ /* alg+key+csum fit and the size is congruent to 8. */
assert (!(nframe%8) && nframe > 1 + dek->keylen + 2 ); assert (!(nframe%8) && nframe > 1 + dek->keylen + 2 );
frame = xmalloc_secure (nframe); frame = xmalloc_secure (nframe);
n = 0; n = 0;
frame[n++] = dek->algo; frame[n++] = dek->algo;
@ -122,13 +122,13 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
"[%d] %02x %02x %02x ... %02x %02x %02x\n", "[%d] %02x %02x %02x ... %02x %02x %02x\n",
nframe, frame[0], frame[1], frame[2], nframe, frame[0], frame[1], frame[2],
frame[nframe-3], frame[nframe-2], frame[nframe-1]); frame[nframe-3], frame[nframe-2], frame[nframe-1]);
if (gcry_mpi_scan (&a, GCRYMPI_FMT_USG, frame, nframe, &nframe)) if (gcry_mpi_scan (&a, GCRYMPI_FMT_USG, frame, nframe, &nframe))
BUG(); BUG();
xfree(frame); xfree(frame);
return a; return a;
} }
/* The current limitation is that we can only use a session key /* The current limitation is that we can only use a session key
* whose length is a multiple of BITS_PER_MPI_LIMB * whose length is a multiple of BITS_PER_MPI_LIMB
* I think we can live with that. * I think we can live with that.
@ -136,7 +136,7 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
if (dek->keylen + 7 > nframe || !nframe) if (dek->keylen + 7 > nframe || !nframe)
log_bug ("can't encode a %d bit key in a %d bits frame\n", log_bug ("can't encode a %d bit key in a %d bits frame\n",
dek->keylen*8, nbits ); dek->keylen*8, nbits );
/* We encode the session key in this way: /* We encode the session key in this way:
* *
* 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes) * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes)
@ -163,7 +163,7 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
{ {
int j, k; int j, k;
byte *pp; byte *pp;
/* Count the zero bytes. */ /* Count the zero bytes. */
for (j=k=0; j < i; j++ ) for (j=k=0; j < i; j++ )
if (!p[j]) if (!p[j])
@ -273,9 +273,9 @@ encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo)
i.e. 04 <x> <y> */ i.e. 04 <x> <y> */
if (pkalgo == GCRY_PK_ECDSA) if (pkalgo == GCRY_PK_ECDSA)
qbytes = ecdsa_qbits_from_Q (qbytes); qbytes = ecdsa_qbits_from_Q (qbytes);
/* Make sure it is a multiple of 8 bits. */ /* Make sure it is a multiple of 8 bits. */
if (qbytes%8) if (qbytes%8)
{ {
log_error(_("DSA requires the hash length to be a" log_error(_("DSA requires the hash length to be a"
@ -295,11 +295,11 @@ encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo)
gcry_pk_algo_name (pkalgo), keystr_from_pk (pk), qbytes); gcry_pk_algo_name (pkalgo), keystr_from_pk (pk), qbytes);
return NULL; return NULL;
} }
qbytes /= 8; qbytes /= 8;
/* Check if we're too short. Too long is safe as we'll /* Check if we're too short. Too long is safe as we'll
automatically left-truncate. automatically left-truncate.
FIXME: Check against FIPS. FIXME: Check against FIPS.
This checks would require the use of SHA512 with ECDSA 512. I This checks would require the use of SHA512 with ECDSA 512. I
@ -308,7 +308,7 @@ encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo)
adjust it later for general case. (Note that the check will adjust it later for general case. (Note that the check will
never pass for ECDSA 521 anyway as the only hash that never pass for ECDSA 521 anyway as the only hash that
intended to match it is SHA 512, but 512 < 521). */ intended to match it is SHA 512, but 512 < 521). */
if (gcry_md_get_algo_dlen (hash_algo) if (gcry_md_get_algo_dlen (hash_algo)
< ((pkalgo == GCRY_PK_ECDSA && qbytes > (521)/8) ? 512/8 : qbytes)) < ((pkalgo == GCRY_PK_ECDSA && qbytes > (521)/8) ? 512/8 : qbytes))
{ {
log_error (_("%s key %s requires a %zu bit or larger hash " log_error (_("%s key %s requires a %zu bit or larger hash "