2003-06-05 09:14:21 +02:00
|
|
|
/* keygen.c - generate a key pair
|
2011-01-25 16:54:18 +01:00
|
|
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
|
|
|
* 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
|
2014-07-23 15:12:43 +02:00
|
|
|
* Copyright (C) 2014 Werner Koch
|
2003-06-05 09:14:21 +02:00
|
|
|
*
|
|
|
|
* This file is part of GnuPG.
|
|
|
|
*
|
|
|
|
* GnuPG is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
2007-07-04 21:49:40 +02:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
2003-06-05 09:14:21 +02:00
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* GnuPG is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2007-07-04 21:49:40 +02:00
|
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
2003-06-05 09:14:21 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <assert.h>
|
2006-04-19 13:26:11 +02:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
2003-06-18 21:56:13 +02:00
|
|
|
|
|
|
|
#include "gpg.h"
|
2003-06-05 09:14:21 +02:00
|
|
|
#include "util.h"
|
|
|
|
#include "main.h"
|
|
|
|
#include "packet.h"
|
|
|
|
#include "ttyio.h"
|
|
|
|
#include "options.h"
|
|
|
|
#include "keydb.h"
|
|
|
|
#include "trustdb.h"
|
|
|
|
#include "status.h"
|
|
|
|
#include "i18n.h"
|
2006-06-27 16:30:59 +02:00
|
|
|
#include "keyserver-internal.h"
|
2003-06-27 22:53:09 +02:00
|
|
|
#include "call-agent.h"
|
2011-01-06 02:33:17 +01:00
|
|
|
#include "pkglue.h"
|
2003-06-27 22:53:09 +02:00
|
|
|
|
2009-12-04 20:47:54 +01:00
|
|
|
/* The default algorithms. If you change them remember to change them
|
|
|
|
also in gpg.c:gpgconf_list. You should also check that the value
|
|
|
|
is inside the bounds enforced by ask_keysize and gen_xxx. */
|
2014-09-27 15:14:13 +02:00
|
|
|
#define DEFAULT_STD_ALGO PUBKEY_ALGO_RSA
|
|
|
|
#define DEFAULT_STD_KEYSIZE 2048
|
|
|
|
#define DEFAULT_STD_CURVE NULL
|
|
|
|
#define DEFAULT_STD_SUBALGO PUBKEY_ALGO_RSA
|
|
|
|
#define DEFAULT_STD_SUBKEYSIZE 2048
|
|
|
|
#define DEFAULT_STD_SUBCURVE NULL
|
2009-12-04 20:47:54 +01:00
|
|
|
|
2011-01-25 16:54:18 +01:00
|
|
|
/* Flag bits used during key generation. */
|
|
|
|
#define KEYGEN_FLAG_NO_PROTECTION 1
|
|
|
|
#define KEYGEN_FLAG_TRANSIENT_KEY 2
|
|
|
|
|
|
|
|
/* Maximum number of supported algorithm preferences. */
|
2011-02-03 16:31:42 +01:00
|
|
|
#define MAX_PREFS 30
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
enum para_name {
|
|
|
|
pKEYTYPE,
|
|
|
|
pKEYLENGTH,
|
2013-11-15 08:59:45 +01:00
|
|
|
pKEYCURVE,
|
2003-06-05 09:14:21 +02:00
|
|
|
pKEYUSAGE,
|
|
|
|
pSUBKEYTYPE,
|
|
|
|
pSUBKEYLENGTH,
|
2013-11-15 08:59:45 +01:00
|
|
|
pSUBKEYCURVE,
|
2003-06-05 09:14:21 +02:00
|
|
|
pSUBKEYUSAGE,
|
2003-07-23 09:11:06 +02:00
|
|
|
pAUTHKEYTYPE,
|
2003-06-05 09:14:21 +02:00
|
|
|
pNAMEREAL,
|
|
|
|
pNAMEEMAIL,
|
|
|
|
pNAMECOMMENT,
|
|
|
|
pPREFERENCES,
|
|
|
|
pREVOKER,
|
|
|
|
pUSERID,
|
2007-07-05 18:58:19 +02:00
|
|
|
pCREATIONDATE,
|
|
|
|
pKEYCREATIONDATE, /* Same in seconds since epoch. */
|
2003-06-05 09:14:21 +02:00
|
|
|
pEXPIREDATE,
|
|
|
|
pKEYEXPIRE, /* in n seconds */
|
|
|
|
pSUBKEYEXPIRE, /* in n seconds */
|
|
|
|
pPASSPHRASE,
|
2006-04-19 13:26:11 +02:00
|
|
|
pSERIALNO,
|
2010-11-17 14:21:24 +01:00
|
|
|
pCARDBACKUPKEY,
|
2006-06-27 16:30:59 +02:00
|
|
|
pHANDLE,
|
|
|
|
pKEYSERVER
|
2003-06-05 09:14:21 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct para_data_s {
|
|
|
|
struct para_data_s *next;
|
|
|
|
int lnr;
|
|
|
|
enum para_name key;
|
|
|
|
union {
|
|
|
|
u32 expire;
|
2007-07-05 18:58:19 +02:00
|
|
|
u32 creation;
|
2003-06-05 09:14:21 +02:00
|
|
|
unsigned int usage;
|
|
|
|
struct revocation_key revkey;
|
|
|
|
char value[1];
|
|
|
|
} u;
|
|
|
|
};
|
|
|
|
|
2010-11-17 14:21:24 +01:00
|
|
|
struct output_control_s
|
|
|
|
{
|
|
|
|
int lnr;
|
|
|
|
int dryrun;
|
|
|
|
unsigned int keygen_flags;
|
|
|
|
int use_files;
|
|
|
|
struct {
|
|
|
|
char *fname;
|
|
|
|
char *newfname;
|
|
|
|
IOBUF stream;
|
|
|
|
armor_filter_context_t *afx;
|
|
|
|
} pub;
|
2003-06-05 09:14:21 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct opaque_data_usage_and_pk {
|
|
|
|
unsigned int usage;
|
|
|
|
PKT_public_key *pk;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static int prefs_initialized = 0;
|
|
|
|
static byte sym_prefs[MAX_PREFS];
|
|
|
|
static int nsym_prefs;
|
|
|
|
static byte hash_prefs[MAX_PREFS];
|
|
|
|
static int nhash_prefs;
|
|
|
|
static byte zip_prefs[MAX_PREFS];
|
|
|
|
static int nzip_prefs;
|
|
|
|
static int mdc_available,ks_modify;
|
|
|
|
|
|
|
|
static void do_generate_keypair( struct para_data_s *para,
|
2006-04-19 13:26:11 +02:00
|
|
|
struct output_control_s *outctrl, int card );
|
2010-04-20 19:57:50 +02:00
|
|
|
static int write_keyblock (iobuf_t out, kbnode_t node);
|
2010-11-17 14:21:24 +01:00
|
|
|
static gpg_error_t gen_card_key (int algo, int keyno, int is_primary,
|
|
|
|
kbnode_t pub_root,
|
|
|
|
u32 *timestamp, u32 expireval);
|
2006-04-19 13:26:11 +02:00
|
|
|
static int gen_card_key_with_backup (int algo, int keyno, int is_primary,
|
2010-04-20 19:57:50 +02:00
|
|
|
kbnode_t pub_root, u32 timestamp,
|
2010-11-17 14:21:24 +01:00
|
|
|
u32 expireval, struct para_data_s *para);
|
2006-04-19 13:26:11 +02:00
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
print_status_key_created (int letter, PKT_public_key *pk, const char *handle)
|
|
|
|
{
|
|
|
|
byte array[MAX_FINGERPRINT_LEN], *s;
|
|
|
|
char *buf, *p;
|
|
|
|
size_t i, n;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
if (!handle)
|
|
|
|
handle = "";
|
|
|
|
|
|
|
|
buf = xmalloc (MAX_FINGERPRINT_LEN*2+31 + strlen (handle) + 1);
|
|
|
|
|
|
|
|
p = buf;
|
|
|
|
if (letter || pk)
|
|
|
|
{
|
|
|
|
*p++ = letter;
|
|
|
|
*p++ = ' ';
|
|
|
|
fingerprint_from_pk (pk, array, &n);
|
|
|
|
s = array;
|
|
|
|
for (i=0; i < n ; i++, s++, p += 2)
|
|
|
|
sprintf (p, "%02X", *s);
|
|
|
|
}
|
|
|
|
if (*handle)
|
|
|
|
{
|
|
|
|
*p++ = ' ';
|
|
|
|
for (i=0; handle[i] && i < 100; i++)
|
|
|
|
*p++ = isspace ((unsigned int)handle[i])? '_':handle[i];
|
|
|
|
}
|
|
|
|
*p = 0;
|
|
|
|
write_status_text ((letter || pk)?STATUS_KEY_CREATED:STATUS_KEY_NOT_CREATED,
|
|
|
|
buf);
|
|
|
|
xfree (buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
print_status_key_not_created (const char *handle)
|
|
|
|
{
|
|
|
|
print_status_key_created (0, NULL, handle);
|
|
|
|
}
|
2003-06-27 22:53:09 +02:00
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
write_uid( KBNODE root, const char *s )
|
|
|
|
{
|
2006-04-19 13:26:11 +02:00
|
|
|
PACKET *pkt = xmalloc_clear(sizeof *pkt );
|
2003-06-05 09:14:21 +02:00
|
|
|
size_t n = strlen(s);
|
|
|
|
|
|
|
|
pkt->pkttype = PKT_USER_ID;
|
2006-04-19 13:26:11 +02:00
|
|
|
pkt->pkt.user_id = xmalloc_clear( sizeof *pkt->pkt.user_id + n - 1 );
|
2003-06-05 09:14:21 +02:00
|
|
|
pkt->pkt.user_id->len = n;
|
|
|
|
pkt->pkt.user_id->ref = 1;
|
|
|
|
strcpy(pkt->pkt.user_id->name, s);
|
|
|
|
add_kbnode( root, new_kbnode( pkt ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
do_add_key_flags (PKT_signature *sig, unsigned int use)
|
|
|
|
{
|
|
|
|
byte buf[1];
|
|
|
|
|
|
|
|
buf[0] = 0;
|
2006-04-19 13:26:11 +02:00
|
|
|
|
|
|
|
/* The spec says that all primary keys MUST be able to certify. */
|
|
|
|
if(sig->sig_class!=0x18)
|
|
|
|
buf[0] |= 0x01;
|
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
if (use & PUBKEY_USAGE_SIG)
|
2006-04-19 13:26:11 +02:00
|
|
|
buf[0] |= 0x02;
|
2003-06-05 09:14:21 +02:00
|
|
|
if (use & PUBKEY_USAGE_ENC)
|
|
|
|
buf[0] |= 0x04 | 0x08;
|
2003-09-05 09:40:18 +02:00
|
|
|
if (use & PUBKEY_USAGE_AUTH)
|
|
|
|
buf[0] |= 0x20;
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
build_sig_subpkt (sig, SIGSUBPKT_KEY_FLAGS, buf, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2010-04-20 19:57:50 +02:00
|
|
|
keygen_add_key_expire (PKT_signature *sig, void *opaque)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
PKT_public_key *pk = opaque;
|
|
|
|
byte buf[8];
|
|
|
|
u32 u;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
if (pk->expiredate)
|
|
|
|
{
|
|
|
|
if (pk->expiredate > pk->timestamp)
|
|
|
|
u = pk->expiredate - pk->timestamp;
|
|
|
|
else
|
|
|
|
u = 1;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
buf[0] = (u >> 24) & 0xff;
|
|
|
|
buf[1] = (u >> 16) & 0xff;
|
|
|
|
buf[2] = (u >> 8) & 0xff;
|
|
|
|
buf[3] = u & 0xff;
|
|
|
|
build_sig_subpkt (sig, SIGSUBPKT_KEY_EXPIRE, buf, 4);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Make sure we don't leave a key expiration subpacket lying
|
|
|
|
around */
|
|
|
|
delete_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
return 0;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
static int
|
|
|
|
keygen_add_key_flags_and_expire (PKT_signature *sig, void *opaque)
|
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
struct opaque_data_usage_and_pk *oduap = opaque;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
do_add_key_flags (sig, oduap->usage);
|
|
|
|
return keygen_add_key_expire (sig, oduap->pk);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
static int
|
|
|
|
set_one_pref (int val, int type, const char *item, byte *buf, int *nbuf)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i=0; i < *nbuf; i++ )
|
|
|
|
if (buf[i] == val)
|
|
|
|
{
|
2012-06-05 19:29:22 +02:00
|
|
|
log_info (_("preference '%s' duplicated\n"), item);
|
2003-06-05 09:14:21 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*nbuf >= MAX_PREFS)
|
|
|
|
{
|
|
|
|
if(type==1)
|
|
|
|
log_info(_("too many cipher preferences\n"));
|
|
|
|
else if(type==2)
|
|
|
|
log_info(_("too many digest preferences\n"));
|
|
|
|
else if(type==3)
|
|
|
|
log_info(_("too many compression preferences\n"));
|
|
|
|
else
|
|
|
|
BUG();
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
buf[(*nbuf)++] = val;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse the supplied string and use it to set the standard
|
|
|
|
* preferences. The string may be in a form like the one printed by
|
|
|
|
* "pref" (something like: "S10 S3 H3 H2 Z2 Z1") or the actual
|
|
|
|
* cipher/hash/compress names. Use NULL to set the default
|
|
|
|
* preferences. Returns: 0 = okay
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
keygen_set_std_prefs (const char *string,int personal)
|
|
|
|
{
|
|
|
|
byte sym[MAX_PREFS], hash[MAX_PREFS], zip[MAX_PREFS];
|
|
|
|
int nsym=0, nhash=0, nzip=0, val, rc=0;
|
|
|
|
int mdc=1, modify=0; /* mdc defaults on, modify defaults off. */
|
2009-07-09 10:52:31 +02:00
|
|
|
char dummy_string[20*4+1]; /* Enough for 20 items. */
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
if (!string || !ascii_strcasecmp (string, "default"))
|
|
|
|
{
|
|
|
|
if (opt.def_preference_list)
|
|
|
|
string=opt.def_preference_list;
|
|
|
|
else
|
|
|
|
{
|
2010-04-26 13:53:14 +02:00
|
|
|
int any_compress = 0;
|
2006-04-19 13:26:11 +02:00
|
|
|
dummy_string[0]='\0';
|
|
|
|
|
|
|
|
/* The rationale why we use the order AES256,192,128 is
|
|
|
|
for compatibility reasons with PGP. If gpg would
|
|
|
|
define AES128 first, we would get the somewhat
|
|
|
|
confusing situation:
|
|
|
|
|
|
|
|
gpg -r pgpkey -r gpgkey ---gives--> AES256
|
|
|
|
gpg -r gpgkey -r pgpkey ---gives--> AES
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
Note that by using --personal-cipher-preferences it is
|
|
|
|
possible to prefer AES128.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Make sure we do not add more than 15 items here, as we
|
|
|
|
could overflow the size of dummy_string. We currently
|
|
|
|
have at most 12. */
|
2006-04-19 15:24:36 +02:00
|
|
|
if ( !openpgp_cipher_test_algo (CIPHER_ALGO_AES256) )
|
2006-04-19 13:26:11 +02:00
|
|
|
strcat(dummy_string,"S9 ");
|
2006-04-19 15:24:36 +02:00
|
|
|
if ( !openpgp_cipher_test_algo (CIPHER_ALGO_AES192) )
|
2006-04-19 13:26:11 +02:00
|
|
|
strcat(dummy_string,"S8 ");
|
2006-04-19 15:24:36 +02:00
|
|
|
if ( !openpgp_cipher_test_algo (CIPHER_ALGO_AES) )
|
2006-04-19 13:26:11 +02:00
|
|
|
strcat(dummy_string,"S7 ");
|
|
|
|
strcat(dummy_string,"S2 "); /* 3DES */
|
|
|
|
|
2009-07-09 10:52:31 +02:00
|
|
|
/* The default hash algo order is:
|
2014-08-26 23:20:07 +02:00
|
|
|
SHA-256, SHA-384, SHA-512, SHA-224, SHA-1.
|
|
|
|
*/
|
2009-07-09 10:52:31 +02:00
|
|
|
if (!openpgp_md_test_algo (DIGEST_ALGO_SHA256))
|
|
|
|
strcat (dummy_string, "H8 ");
|
|
|
|
|
|
|
|
if (!openpgp_md_test_algo (DIGEST_ALGO_SHA384))
|
|
|
|
strcat (dummy_string, "H9 ");
|
|
|
|
|
|
|
|
if (!openpgp_md_test_algo (DIGEST_ALGO_SHA512))
|
|
|
|
strcat (dummy_string, "H10 ");
|
|
|
|
|
|
|
|
if (!openpgp_md_test_algo (DIGEST_ALGO_SHA224))
|
|
|
|
strcat (dummy_string, "H11 ");
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2014-08-26 23:20:07 +02:00
|
|
|
strcat (dummy_string, "H2 "); /* SHA-1 */
|
|
|
|
|
2010-04-14 16:39:16 +02:00
|
|
|
if(!check_compress_algo(COMPRESS_ALGO_ZLIB))
|
2010-04-26 13:53:14 +02:00
|
|
|
{
|
|
|
|
strcat(dummy_string,"Z2 ");
|
|
|
|
any_compress = 1;
|
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
|
|
|
|
if(!check_compress_algo(COMPRESS_ALGO_BZIP2))
|
2010-04-26 13:53:14 +02:00
|
|
|
{
|
|
|
|
strcat(dummy_string,"Z3 ");
|
|
|
|
any_compress = 1;
|
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2010-04-14 16:39:16 +02:00
|
|
|
if(!check_compress_algo(COMPRESS_ALGO_ZIP))
|
2010-04-26 13:53:14 +02:00
|
|
|
{
|
|
|
|
strcat(dummy_string,"Z1 ");
|
|
|
|
any_compress = 1;
|
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2010-04-26 13:53:14 +02:00
|
|
|
/* In case we have no compress algo at all, declare that
|
|
|
|
we prefer no compresssion. */
|
|
|
|
if (!any_compress)
|
|
|
|
strcat(dummy_string,"Z0 ");
|
|
|
|
|
|
|
|
/* Remove the trailing space. */
|
|
|
|
if (*dummy_string && dummy_string[strlen (dummy_string)-1] == ' ')
|
|
|
|
dummy_string[strlen (dummy_string)-1] = 0;
|
2006-04-19 13:26:11 +02:00
|
|
|
|
|
|
|
string=dummy_string;
|
|
|
|
}
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
else if (!ascii_strcasecmp (string, "none"))
|
|
|
|
string = "";
|
|
|
|
|
|
|
|
if(strlen(string))
|
|
|
|
{
|
|
|
|
char *tok,*prefstring;
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
prefstring=xstrdup(string); /* need a writable string! */
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
while((tok=strsep(&prefstring," ,")))
|
|
|
|
{
|
2006-05-24 13:12:28 +02:00
|
|
|
if((val=string_to_cipher_algo (tok)))
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
|
|
|
if(set_one_pref(val,1,tok,sym,&nsym))
|
|
|
|
rc=-1;
|
|
|
|
}
|
2006-05-24 13:12:28 +02:00
|
|
|
else if((val=string_to_digest_algo (tok)))
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
|
|
|
if(set_one_pref(val,2,tok,hash,&nhash))
|
|
|
|
rc=-1;
|
|
|
|
}
|
|
|
|
else if((val=string_to_compress_algo(tok))>-1)
|
|
|
|
{
|
|
|
|
if(set_one_pref(val,3,tok,zip,&nzip))
|
|
|
|
rc=-1;
|
|
|
|
}
|
|
|
|
else if (ascii_strcasecmp(tok,"mdc")==0)
|
|
|
|
mdc=1;
|
|
|
|
else if (ascii_strcasecmp(tok,"no-mdc")==0)
|
|
|
|
mdc=0;
|
|
|
|
else if (ascii_strcasecmp(tok,"ks-modify")==0)
|
|
|
|
modify=1;
|
|
|
|
else if (ascii_strcasecmp(tok,"no-ks-modify")==0)
|
|
|
|
modify=0;
|
|
|
|
else
|
|
|
|
{
|
2012-06-05 19:29:22 +02:00
|
|
|
log_info (_("invalid item '%s' in preference string\n"),tok);
|
2003-06-05 09:14:21 +02:00
|
|
|
rc=-1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
xfree(prefstring);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if(!rc)
|
|
|
|
{
|
|
|
|
if(personal)
|
|
|
|
{
|
|
|
|
if(personal==PREFTYPE_SYM)
|
|
|
|
{
|
2006-04-19 13:26:11 +02:00
|
|
|
xfree(opt.personal_cipher_prefs);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
if(nsym==0)
|
|
|
|
opt.personal_cipher_prefs=NULL;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
opt.personal_cipher_prefs=
|
2006-04-19 13:26:11 +02:00
|
|
|
xmalloc(sizeof(prefitem_t *)*(nsym+1));
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
for (i=0; i<nsym; i++)
|
|
|
|
{
|
|
|
|
opt.personal_cipher_prefs[i].type = PREFTYPE_SYM;
|
|
|
|
opt.personal_cipher_prefs[i].value = sym[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
opt.personal_cipher_prefs[i].type = PREFTYPE_NONE;
|
|
|
|
opt.personal_cipher_prefs[i].value = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(personal==PREFTYPE_HASH)
|
|
|
|
{
|
2006-04-19 13:26:11 +02:00
|
|
|
xfree(opt.personal_digest_prefs);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
if(nhash==0)
|
|
|
|
opt.personal_digest_prefs=NULL;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
opt.personal_digest_prefs=
|
2006-04-19 13:26:11 +02:00
|
|
|
xmalloc(sizeof(prefitem_t *)*(nhash+1));
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
for (i=0; i<nhash; i++)
|
|
|
|
{
|
|
|
|
opt.personal_digest_prefs[i].type = PREFTYPE_HASH;
|
|
|
|
opt.personal_digest_prefs[i].value = hash[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
opt.personal_digest_prefs[i].type = PREFTYPE_NONE;
|
|
|
|
opt.personal_digest_prefs[i].value = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(personal==PREFTYPE_ZIP)
|
|
|
|
{
|
2006-04-19 13:26:11 +02:00
|
|
|
xfree(opt.personal_compress_prefs);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
if(nzip==0)
|
|
|
|
opt.personal_compress_prefs=NULL;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
opt.personal_compress_prefs=
|
2006-04-19 13:26:11 +02:00
|
|
|
xmalloc(sizeof(prefitem_t *)*(nzip+1));
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
for (i=0; i<nzip; i++)
|
|
|
|
{
|
|
|
|
opt.personal_compress_prefs[i].type = PREFTYPE_ZIP;
|
|
|
|
opt.personal_compress_prefs[i].value = zip[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
opt.personal_compress_prefs[i].type = PREFTYPE_NONE;
|
|
|
|
opt.personal_compress_prefs[i].value = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy (sym_prefs, sym, (nsym_prefs=nsym));
|
|
|
|
memcpy (hash_prefs, hash, (nhash_prefs=nhash));
|
|
|
|
memcpy (zip_prefs, zip, (nzip_prefs=nzip));
|
|
|
|
mdc_available = mdc;
|
|
|
|
ks_modify = modify;
|
|
|
|
prefs_initialized = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return a fake user ID containing the preferences. Caller must
|
|
|
|
free. */
|
2009-07-09 10:52:31 +02:00
|
|
|
PKT_user_id *
|
|
|
|
keygen_get_std_prefs(void)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
|
|
|
int i,j=0;
|
2006-04-19 13:26:11 +02:00
|
|
|
PKT_user_id *uid=xmalloc_clear(sizeof(PKT_user_id));
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
if(!prefs_initialized)
|
|
|
|
keygen_set_std_prefs(NULL,0);
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
uid->ref=1;
|
|
|
|
|
|
|
|
uid->prefs=xmalloc((sizeof(prefitem_t *)*
|
2003-06-05 09:14:21 +02:00
|
|
|
(nsym_prefs+nhash_prefs+nzip_prefs+1)));
|
|
|
|
|
|
|
|
for(i=0;i<nsym_prefs;i++,j++)
|
|
|
|
{
|
|
|
|
uid->prefs[j].type=PREFTYPE_SYM;
|
|
|
|
uid->prefs[j].value=sym_prefs[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i=0;i<nhash_prefs;i++,j++)
|
|
|
|
{
|
|
|
|
uid->prefs[j].type=PREFTYPE_HASH;
|
|
|
|
uid->prefs[j].value=hash_prefs[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i=0;i<nzip_prefs;i++,j++)
|
|
|
|
{
|
|
|
|
uid->prefs[j].type=PREFTYPE_ZIP;
|
|
|
|
uid->prefs[j].value=zip_prefs[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
uid->prefs[j].type=PREFTYPE_NONE;
|
|
|
|
uid->prefs[j].value=0;
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
uid->flags.mdc=mdc_available;
|
|
|
|
uid->flags.ks_modify=ks_modify;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
return uid;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
add_feature_mdc (PKT_signature *sig,int enabled)
|
|
|
|
{
|
|
|
|
const byte *s;
|
|
|
|
size_t n;
|
|
|
|
int i;
|
|
|
|
char *buf;
|
|
|
|
|
|
|
|
s = parse_sig_subpkt (sig->hashed, SIGSUBPKT_FEATURES, &n );
|
|
|
|
/* Already set or cleared */
|
|
|
|
if (s && n &&
|
|
|
|
((enabled && (s[0] & 0x01)) || (!enabled && !(s[0] & 0x01))))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!s || !n) { /* create a new one */
|
|
|
|
n = 1;
|
2006-04-19 13:26:11 +02:00
|
|
|
buf = xmalloc_clear (n);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
else {
|
2003-06-18 21:56:13 +02:00
|
|
|
buf = xmalloc (n);
|
2003-06-05 09:14:21 +02:00
|
|
|
memcpy (buf, s, n);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(enabled)
|
|
|
|
buf[0] |= 0x01; /* MDC feature */
|
|
|
|
else
|
|
|
|
buf[0] &= ~0x01;
|
|
|
|
|
|
|
|
/* Are there any bits set? */
|
|
|
|
for(i=0;i<n;i++)
|
|
|
|
if(buf[i]!=0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if(i==n)
|
|
|
|
delete_sig_subpkt (sig->hashed, SIGSUBPKT_FEATURES);
|
|
|
|
else
|
|
|
|
build_sig_subpkt (sig, SIGSUBPKT_FEATURES, buf, n);
|
|
|
|
|
2003-06-18 21:56:13 +02:00
|
|
|
xfree (buf);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
add_keyserver_modify (PKT_signature *sig,int enabled)
|
|
|
|
{
|
|
|
|
const byte *s;
|
|
|
|
size_t n;
|
|
|
|
int i;
|
|
|
|
char *buf;
|
|
|
|
|
|
|
|
/* The keyserver modify flag is a negative flag (i.e. no-modify) */
|
|
|
|
enabled=!enabled;
|
|
|
|
|
|
|
|
s = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KS_FLAGS, &n );
|
|
|
|
/* Already set or cleared */
|
|
|
|
if (s && n &&
|
|
|
|
((enabled && (s[0] & 0x80)) || (!enabled && !(s[0] & 0x80))))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!s || !n) { /* create a new one */
|
|
|
|
n = 1;
|
2006-04-19 13:26:11 +02:00
|
|
|
buf = xmalloc_clear (n);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
else {
|
2003-06-18 21:56:13 +02:00
|
|
|
buf = xmalloc (n);
|
2003-06-05 09:14:21 +02:00
|
|
|
memcpy (buf, s, n);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(enabled)
|
|
|
|
buf[0] |= 0x80; /* no-modify flag */
|
|
|
|
else
|
|
|
|
buf[0] &= ~0x80;
|
|
|
|
|
|
|
|
/* Are there any bits set? */
|
|
|
|
for(i=0;i<n;i++)
|
|
|
|
if(buf[i]!=0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if(i==n)
|
|
|
|
delete_sig_subpkt (sig->hashed, SIGSUBPKT_KS_FLAGS);
|
|
|
|
else
|
|
|
|
build_sig_subpkt (sig, SIGSUBPKT_KS_FLAGS, buf, n);
|
|
|
|
|
2003-06-18 21:56:13 +02:00
|
|
|
xfree (buf);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2008-10-20 15:53:23 +02:00
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
int
|
2008-10-20 15:53:23 +02:00
|
|
|
keygen_upd_std_prefs (PKT_signature *sig, void *opaque)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2008-10-20 15:53:23 +02:00
|
|
|
(void)opaque;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2008-10-20 15:53:23 +02:00
|
|
|
if (!prefs_initialized)
|
|
|
|
keygen_set_std_prefs (NULL, 0);
|
2011-02-03 16:31:42 +01:00
|
|
|
|
|
|
|
if (nsym_prefs)
|
2008-10-20 15:53:23 +02:00
|
|
|
build_sig_subpkt (sig, SIGSUBPKT_PREF_SYM, sym_prefs, nsym_prefs);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
delete_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_SYM);
|
|
|
|
delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PREF_SYM);
|
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2008-10-20 15:53:23 +02:00
|
|
|
if (nhash_prefs)
|
|
|
|
build_sig_subpkt (sig, SIGSUBPKT_PREF_HASH, hash_prefs, nhash_prefs);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
delete_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_HASH);
|
|
|
|
delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PREF_HASH);
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2008-10-20 15:53:23 +02:00
|
|
|
if (nzip_prefs)
|
|
|
|
build_sig_subpkt (sig, SIGSUBPKT_PREF_COMPR, zip_prefs, nzip_prefs);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
delete_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_COMPR);
|
|
|
|
delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PREF_COMPR);
|
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2008-10-20 15:53:23 +02:00
|
|
|
/* Make sure that the MDC feature flag is set if needed. */
|
|
|
|
add_feature_mdc (sig,mdc_available);
|
|
|
|
add_keyserver_modify (sig,ks_modify);
|
|
|
|
keygen_add_keyserver_url(sig,NULL);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2008-10-20 15:53:23 +02:00
|
|
|
return 0;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************
|
|
|
|
* Add preference to the self signature packet.
|
|
|
|
* This is only called for packets with version > 3.
|
|
|
|
*/
|
|
|
|
int
|
2010-04-20 19:57:50 +02:00
|
|
|
keygen_add_std_prefs (PKT_signature *sig, void *opaque)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
PKT_public_key *pk = opaque;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
do_add_key_flags (sig, pk->pubkey_usage);
|
|
|
|
keygen_add_key_expire (sig, opaque );
|
|
|
|
keygen_upd_std_prefs (sig, opaque);
|
|
|
|
keygen_add_keyserver_url (sig,NULL);
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
return 0;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2003-09-23 19:48:33 +02:00
|
|
|
int
|
|
|
|
keygen_add_keyserver_url(PKT_signature *sig, void *opaque)
|
|
|
|
{
|
|
|
|
const char *url=opaque;
|
|
|
|
|
2006-06-27 16:30:59 +02:00
|
|
|
if(!url)
|
|
|
|
url=opt.def_keyserver_url;
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
if(url)
|
|
|
|
build_sig_subpkt(sig,SIGSUBPKT_PREF_KS,url,strlen(url));
|
|
|
|
else
|
|
|
|
delete_sig_subpkt (sig->hashed,SIGSUBPKT_PREF_KS);
|
2003-09-23 19:48:33 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
int
|
|
|
|
keygen_add_notations(PKT_signature *sig,void *opaque)
|
|
|
|
{
|
|
|
|
struct notation *notation;
|
|
|
|
|
|
|
|
/* We always start clean */
|
|
|
|
delete_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION);
|
|
|
|
delete_sig_subpkt(sig->unhashed,SIGSUBPKT_NOTATION);
|
|
|
|
sig->flags.notation=0;
|
|
|
|
|
|
|
|
for(notation=opaque;notation;notation=notation->next)
|
|
|
|
if(!notation->flags.ignore)
|
|
|
|
{
|
|
|
|
unsigned char *buf;
|
|
|
|
unsigned int n1,n2;
|
|
|
|
|
|
|
|
n1=strlen(notation->name);
|
|
|
|
if(notation->altvalue)
|
|
|
|
n2=strlen(notation->altvalue);
|
|
|
|
else if(notation->bdat)
|
|
|
|
n2=notation->blen;
|
|
|
|
else
|
|
|
|
n2=strlen(notation->value);
|
|
|
|
|
|
|
|
buf = xmalloc( 8 + n1 + n2 );
|
|
|
|
|
|
|
|
/* human readable or not */
|
|
|
|
buf[0] = notation->bdat?0:0x80;
|
|
|
|
buf[1] = buf[2] = buf[3] = 0;
|
|
|
|
buf[4] = n1 >> 8;
|
|
|
|
buf[5] = n1;
|
|
|
|
buf[6] = n2 >> 8;
|
|
|
|
buf[7] = n2;
|
|
|
|
memcpy(buf+8, notation->name, n1 );
|
|
|
|
if(notation->altvalue)
|
|
|
|
memcpy(buf+8+n1, notation->altvalue, n2 );
|
|
|
|
else if(notation->bdat)
|
|
|
|
memcpy(buf+8+n1, notation->bdat, n2 );
|
|
|
|
else
|
|
|
|
memcpy(buf+8+n1, notation->value, n2 );
|
|
|
|
build_sig_subpkt( sig, SIGSUBPKT_NOTATION |
|
|
|
|
(notation->flags.critical?SIGSUBPKT_FLAG_CRITICAL:0),
|
|
|
|
buf, 8+n1+n2 );
|
|
|
|
xfree(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2003-09-23 19:48:33 +02:00
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
int
|
2010-04-20 19:57:50 +02:00
|
|
|
keygen_add_revkey (PKT_signature *sig, void *opaque)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
struct revocation_key *revkey = opaque;
|
2003-06-05 09:14:21 +02:00
|
|
|
byte buf[2+MAX_FINGERPRINT_LEN];
|
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
buf[0] = revkey->class;
|
|
|
|
buf[1] = revkey->algid;
|
|
|
|
memcpy (&buf[2], revkey->fpr, MAX_FINGERPRINT_LEN);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
build_sig_subpkt (sig, SIGSUBPKT_REV_KEY, buf, 2+MAX_FINGERPRINT_LEN);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
/* All sigs with revocation keys set are nonrevocable. */
|
|
|
|
sig->flags.revocable = 0;
|
2003-06-05 09:14:21 +02:00
|
|
|
buf[0] = 0;
|
2010-04-20 19:57:50 +02:00
|
|
|
build_sig_subpkt (sig, SIGSUBPKT_REVOCABLE, buf, 1);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
parse_revkeys (sig);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
|
|
|
|
|
|
|
|
/* Create a back-signature. If TIMESTAMP is not NULL, use it for the
|
|
|
|
signature creation time. */
|
2010-04-20 19:57:50 +02:00
|
|
|
gpg_error_t
|
|
|
|
make_backsig (PKT_signature *sig, PKT_public_key *pk,
|
|
|
|
PKT_public_key *sub_pk, PKT_public_key *sub_psk,
|
2010-09-01 14:49:05 +02:00
|
|
|
u32 timestamp, const char *cache_nonce)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
gpg_error_t err;
|
2006-04-19 13:26:11 +02:00
|
|
|
PKT_signature *backsig;
|
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
cache_public_key (sub_pk);
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
err = make_keysig_packet (&backsig, pk, NULL, sub_pk, sub_psk, 0x19,
|
2014-10-12 20:07:12 +02:00
|
|
|
0, timestamp, 0, NULL, NULL, cache_nonce);
|
2010-04-20 19:57:50 +02:00
|
|
|
if (err)
|
|
|
|
log_error ("make_keysig_packet failed for backsig: %s\n", g10_errstr(err));
|
2006-04-19 13:26:11 +02:00
|
|
|
else
|
|
|
|
{
|
2007-07-05 18:58:19 +02:00
|
|
|
/* Get it into a binary packed form. */
|
2010-04-20 19:57:50 +02:00
|
|
|
IOBUF backsig_out = iobuf_temp();
|
2006-04-19 13:26:11 +02:00
|
|
|
PACKET backsig_pkt;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
init_packet (&backsig_pkt);
|
|
|
|
backsig_pkt.pkttype = PKT_SIGNATURE;
|
|
|
|
backsig_pkt.pkt.signature = backsig;
|
|
|
|
err = build_packet (backsig_out, &backsig_pkt);
|
|
|
|
free_packet (&backsig_pkt);
|
|
|
|
if (err)
|
|
|
|
log_error ("build_packet failed for backsig: %s\n", g10_errstr(err));
|
2006-04-19 13:26:11 +02:00
|
|
|
else
|
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
size_t pktlen = 0;
|
|
|
|
byte *buf = iobuf_get_temp_buffer (backsig_out);
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
/* Remove the packet header. */
|
2006-04-19 13:26:11 +02:00
|
|
|
if(buf[0]&0x40)
|
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
if (buf[1] < 192)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
pktlen = buf[1];
|
2011-02-03 16:31:42 +01:00
|
|
|
buf += 2;
|
|
|
|
}
|
2010-04-20 19:57:50 +02:00
|
|
|
else if(buf[1] < 224)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
pktlen = (buf[1]-192)*256;
|
|
|
|
pktlen += buf[2]+192;
|
|
|
|
buf += 3;
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
2010-04-20 19:57:50 +02:00
|
|
|
else if (buf[1] == 255)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
pktlen = buf[2] << 24;
|
|
|
|
pktlen |= buf[3] << 16;
|
|
|
|
pktlen |= buf[4] << 8;
|
|
|
|
pktlen |= buf[5];
|
|
|
|
buf += 6;
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
|
|
|
else
|
2010-04-20 19:57:50 +02:00
|
|
|
BUG ();
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
int mark = 1;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
switch (buf[0]&3)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
|
|
|
case 3:
|
2010-04-20 19:57:50 +02:00
|
|
|
BUG ();
|
2006-04-19 13:26:11 +02:00
|
|
|
break;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
case 2:
|
2010-04-20 19:57:50 +02:00
|
|
|
pktlen = buf[mark++] << 24;
|
|
|
|
pktlen |= buf[mark++] << 16;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
case 1:
|
2010-04-20 19:57:50 +02:00
|
|
|
pktlen |= buf[mark++] << 8;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
case 0:
|
2010-04-20 19:57:50 +02:00
|
|
|
pktlen |= buf[mark++];
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
buf += mark;
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
/* Now make the binary blob into a subpacket. */
|
2010-04-20 19:57:50 +02:00
|
|
|
build_sig_subpkt (sig, SIGSUBPKT_SIGNATURE, buf, pktlen);
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
iobuf_close (backsig_out);
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
return err;
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
/* Write a direct key signature to the first key in ROOT using the key
|
|
|
|
PSK. REVKEY is describes the direct key signature and TIMESTAMP is
|
|
|
|
the timestamp to set on the signature. */
|
|
|
|
static gpg_error_t
|
|
|
|
write_direct_sig (KBNODE root, PKT_public_key *psk,
|
2010-09-01 14:49:05 +02:00
|
|
|
struct revocation_key *revkey, u32 timestamp,
|
|
|
|
const char *cache_nonce)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
gpg_error_t err;
|
2007-07-05 18:58:19 +02:00
|
|
|
PACKET *pkt;
|
|
|
|
PKT_signature *sig;
|
|
|
|
KBNODE node;
|
|
|
|
PKT_public_key *pk;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
if (opt.verbose)
|
|
|
|
log_info (_("writing direct signature\n"));
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
/* Get the pk packet from the pub_tree. */
|
2010-04-20 19:57:50 +02:00
|
|
|
node = find_kbnode (root, PKT_PUBLIC_KEY);
|
|
|
|
if (!node)
|
|
|
|
BUG ();
|
2007-07-05 18:58:19 +02:00
|
|
|
pk = node->pkt->pkt.public_key;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
/* We have to cache the key, so that the verification of the
|
|
|
|
signature creation is able to retrieve the public key. */
|
|
|
|
cache_public_key (pk);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
/* Make the signature. */
|
2010-04-20 19:57:50 +02:00
|
|
|
err = make_keysig_packet (&sig, pk, NULL,NULL, psk, 0x1F,
|
2014-10-12 20:07:12 +02:00
|
|
|
0, timestamp, 0,
|
2010-09-01 14:49:05 +02:00
|
|
|
keygen_add_revkey, revkey, cache_nonce);
|
2010-04-20 19:57:50 +02:00
|
|
|
if (err)
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
log_error ("make_keysig_packet failed: %s\n", g10_errstr (err) );
|
|
|
|
return err;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
pkt = xmalloc_clear (sizeof *pkt);
|
2007-07-05 18:58:19 +02:00
|
|
|
pkt->pkttype = PKT_SIGNATURE;
|
|
|
|
pkt->pkt.signature = sig;
|
2010-04-20 19:57:50 +02:00
|
|
|
add_kbnode (root, new_kbnode (pkt));
|
|
|
|
return err;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
|
|
|
|
/* Write a self-signature to the first user id in ROOT using the key
|
|
|
|
PSK. USE and TIMESTAMP give the extra data we need for the
|
|
|
|
signature. */
|
|
|
|
static gpg_error_t
|
|
|
|
write_selfsigs (KBNODE root, PKT_public_key *psk,
|
2010-09-01 14:49:05 +02:00
|
|
|
unsigned int use, u32 timestamp, const char *cache_nonce)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
gpg_error_t err;
|
2007-07-05 18:58:19 +02:00
|
|
|
PACKET *pkt;
|
|
|
|
PKT_signature *sig;
|
|
|
|
PKT_user_id *uid;
|
|
|
|
KBNODE node;
|
|
|
|
PKT_public_key *pk;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
if (opt.verbose)
|
|
|
|
log_info (_("writing self signature\n"));
|
2007-07-05 18:58:19 +02:00
|
|
|
|
|
|
|
/* Get the uid packet from the list. */
|
2010-04-20 19:57:50 +02:00
|
|
|
node = find_kbnode (root, PKT_USER_ID);
|
|
|
|
if (!node)
|
2007-07-05 18:58:19 +02:00
|
|
|
BUG(); /* No user id packet in tree. */
|
|
|
|
uid = node->pkt->pkt.user_id;
|
|
|
|
|
|
|
|
/* Get the pk packet from the pub_tree. */
|
2010-04-20 19:57:50 +02:00
|
|
|
node = find_kbnode (root, PKT_PUBLIC_KEY);
|
|
|
|
if (!node)
|
2007-07-05 18:58:19 +02:00
|
|
|
BUG();
|
|
|
|
pk = node->pkt->pkt.public_key;
|
2010-04-20 19:57:50 +02:00
|
|
|
|
|
|
|
/* The usage has not yet been set - do it now. */
|
2007-07-05 18:58:19 +02:00
|
|
|
pk->pubkey_usage = use;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
/* We have to cache the key, so that the verification of the
|
|
|
|
signature creation is able to retrieve the public key. */
|
|
|
|
cache_public_key (pk);
|
|
|
|
|
|
|
|
/* Make the signature. */
|
2010-04-20 19:57:50 +02:00
|
|
|
err = make_keysig_packet (&sig, pk, uid, NULL, psk, 0x13,
|
2014-10-12 20:07:12 +02:00
|
|
|
0, timestamp, 0,
|
2010-09-01 14:49:05 +02:00
|
|
|
keygen_add_std_prefs, pk, cache_nonce);
|
2011-02-03 16:31:42 +01:00
|
|
|
if (err)
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
log_error ("make_keysig_packet failed: %s\n", g10_errstr (err));
|
|
|
|
return err;
|
2007-07-05 18:58:19 +02:00
|
|
|
}
|
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
pkt = xmalloc_clear (sizeof *pkt);
|
2007-07-05 18:58:19 +02:00
|
|
|
pkt->pkttype = PKT_SIGNATURE;
|
|
|
|
pkt->pkt.signature = sig;
|
2010-04-20 19:57:50 +02:00
|
|
|
add_kbnode (root, new_kbnode (pkt));
|
2007-07-05 18:58:19 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
return err;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
|
|
|
|
/* Write the key binding signature. If TIMESTAMP is not NULL use the
|
2010-04-20 19:57:50 +02:00
|
|
|
signature creation time. PRI_PSK is the key use for signing.
|
|
|
|
SUB_PSK is a key used to create a back-signature; that one is only
|
|
|
|
used if USE has the PUBKEY_USAGE_SIG capability. */
|
2003-06-05 09:14:21 +02:00
|
|
|
static int
|
2010-04-20 19:57:50 +02:00
|
|
|
write_keybinding (KBNODE root, PKT_public_key *pri_psk, PKT_public_key *sub_psk,
|
2010-09-01 14:49:05 +02:00
|
|
|
unsigned int use, u32 timestamp, const char *cache_nonce)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
gpg_error_t err;
|
2007-07-05 18:58:19 +02:00
|
|
|
PACKET *pkt;
|
|
|
|
PKT_signature *sig;
|
|
|
|
KBNODE node;
|
|
|
|
PKT_public_key *pri_pk, *sub_pk;
|
|
|
|
struct opaque_data_usage_and_pk oduap;
|
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
if (opt.verbose)
|
2007-07-05 18:58:19 +02:00
|
|
|
log_info(_("writing key binding signature\n"));
|
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
/* Get the primary pk packet from the tree. */
|
|
|
|
node = find_kbnode (root, PKT_PUBLIC_KEY);
|
|
|
|
if (!node)
|
2007-07-05 18:58:19 +02:00
|
|
|
BUG();
|
|
|
|
pri_pk = node->pkt->pkt.public_key;
|
|
|
|
|
|
|
|
/* We have to cache the key, so that the verification of the
|
|
|
|
* signature creation is able to retrieve the public key. */
|
|
|
|
cache_public_key (pri_pk);
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
/* Find the last subkey. */
|
|
|
|
sub_pk = NULL;
|
2011-02-03 16:31:42 +01:00
|
|
|
for (node = root; node; node = node->next )
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
|
2007-07-05 18:58:19 +02:00
|
|
|
sub_pk = node->pkt->pkt.public_key;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2007-07-05 18:58:19 +02:00
|
|
|
if (!sub_pk)
|
|
|
|
BUG();
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
/* Make the signature. */
|
|
|
|
oduap.usage = use;
|
|
|
|
oduap.pk = sub_pk;
|
2011-02-03 16:31:42 +01:00
|
|
|
err = make_keysig_packet (&sig, pri_pk, NULL, sub_pk, pri_psk, 0x18,
|
2014-10-12 20:07:12 +02:00
|
|
|
0, timestamp, 0,
|
2010-09-01 14:49:05 +02:00
|
|
|
keygen_add_key_flags_and_expire, &oduap,
|
|
|
|
cache_nonce);
|
2011-02-03 16:31:42 +01:00
|
|
|
if (err)
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2014-10-12 20:07:12 +02:00
|
|
|
log_error ("make_keysig_packeto failed: %s\n", g10_errstr (err));
|
2010-04-20 19:57:50 +02:00
|
|
|
return err;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
/* Make a backsig. */
|
2010-04-20 19:57:50 +02:00
|
|
|
if (use & PUBKEY_USAGE_SIG)
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2010-09-01 14:49:05 +02:00
|
|
|
err = make_backsig (sig, pri_pk, sub_pk, sub_psk, timestamp, cache_nonce);
|
2010-04-20 19:57:50 +02:00
|
|
|
if (err)
|
|
|
|
return err;
|
2007-07-05 18:58:19 +02:00
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
pkt = xmalloc_clear ( sizeof *pkt );
|
|
|
|
pkt->pkttype = PKT_SIGNATURE;
|
|
|
|
pkt->pkt.signature = sig;
|
|
|
|
add_kbnode (root, new_kbnode (pkt) );
|
2010-04-20 19:57:50 +02:00
|
|
|
return err;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-31 09:27:06 +01:00
|
|
|
static gpg_error_t
|
|
|
|
ecckey_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp, int algo)
|
|
|
|
{
|
|
|
|
gpg_error_t err;
|
|
|
|
gcry_sexp_t list, l2;
|
|
|
|
char *curve;
|
|
|
|
int i;
|
|
|
|
const char *oidstr;
|
|
|
|
unsigned int nbits;
|
|
|
|
|
|
|
|
array[0] = NULL;
|
|
|
|
array[1] = NULL;
|
|
|
|
array[2] = NULL;
|
|
|
|
|
|
|
|
list = gcry_sexp_find_token (sexp, "public-key", 0);
|
|
|
|
if (!list)
|
|
|
|
return gpg_error (GPG_ERR_INV_OBJ);
|
|
|
|
l2 = gcry_sexp_cadr (list);
|
|
|
|
gcry_sexp_release (list);
|
|
|
|
list = l2;
|
|
|
|
if (!list)
|
|
|
|
return gpg_error (GPG_ERR_NO_OBJ);
|
|
|
|
|
|
|
|
l2 = gcry_sexp_find_token (list, "curve", 0);
|
|
|
|
if (!l2)
|
|
|
|
{
|
|
|
|
err = gpg_error (GPG_ERR_NO_OBJ);
|
|
|
|
goto leave;
|
|
|
|
}
|
|
|
|
curve = gcry_sexp_nth_string (l2, 1);
|
|
|
|
if (!curve)
|
|
|
|
{
|
|
|
|
err = gpg_error (GPG_ERR_NO_OBJ);
|
|
|
|
goto leave;
|
|
|
|
}
|
|
|
|
gcry_sexp_release (l2);
|
2013-11-15 08:59:45 +01:00
|
|
|
oidstr = openpgp_curve_to_oid (curve, &nbits);
|
2011-02-02 15:48:54 +01:00
|
|
|
if (!oidstr)
|
2011-01-31 09:27:06 +01:00
|
|
|
{
|
2011-02-02 15:48:54 +01:00
|
|
|
/* That can't happen because we used one of the curves
|
|
|
|
gpg_curve_to_oid knows about. */
|
2011-01-31 09:27:06 +01:00
|
|
|
err = gpg_error (GPG_ERR_INV_OBJ);
|
|
|
|
goto leave;
|
|
|
|
}
|
|
|
|
err = openpgp_oid_from_str (oidstr, &array[0]);
|
|
|
|
if (err)
|
|
|
|
goto leave;
|
|
|
|
|
|
|
|
l2 = gcry_sexp_find_token (list, "q", 0);
|
|
|
|
if (!l2)
|
|
|
|
{
|
|
|
|
err = gpg_error (GPG_ERR_NO_OBJ);
|
|
|
|
goto leave;
|
|
|
|
}
|
|
|
|
array[1] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
|
|
|
|
gcry_sexp_release (l2);
|
|
|
|
if (!array[1])
|
|
|
|
{
|
|
|
|
err = gpg_error (GPG_ERR_INV_OBJ);
|
|
|
|
goto leave;
|
|
|
|
}
|
|
|
|
gcry_sexp_release (list);
|
|
|
|
|
|
|
|
if (algo == PUBKEY_ALGO_ECDH)
|
|
|
|
{
|
|
|
|
array[2] = pk_ecdh_default_params (nbits);
|
|
|
|
if (!array[2])
|
|
|
|
{
|
|
|
|
err = gpg_error_from_syserror ();
|
|
|
|
goto leave;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
leave:
|
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
for (i=0; i < 3; i++)
|
|
|
|
{
|
|
|
|
gcry_mpi_release (array[i]);
|
|
|
|
array[i] = NULL;
|
|
|
|
}
|
|
|
|
}
|
2013-11-15 08:59:45 +01:00
|
|
|
return err;
|
2011-01-31 09:27:06 +01:00
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2011-01-31 09:27:06 +01:00
|
|
|
|
|
|
|
/* Extract key parameters from SEXP and store them in ARRAY. ELEMS is
|
|
|
|
a string where each character denotes a parameter name. TOPNAME is
|
2011-02-03 16:31:42 +01:00
|
|
|
the name of the top element above the elements. */
|
2003-06-05 09:14:21 +02:00
|
|
|
static int
|
2003-07-29 10:53:19 +02:00
|
|
|
key_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp,
|
|
|
|
const char *topname, const char *elems)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2003-07-29 10:53:19 +02:00
|
|
|
gcry_sexp_t list, l2;
|
|
|
|
const char *s;
|
|
|
|
int i, idx;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
list = gcry_sexp_find_token (sexp, topname, 0);
|
|
|
|
if (!list)
|
|
|
|
return gpg_error (GPG_ERR_INV_OBJ);
|
|
|
|
l2 = gcry_sexp_cadr (list);
|
|
|
|
gcry_sexp_release (list);
|
|
|
|
list = l2;
|
|
|
|
if (!list)
|
|
|
|
return gpg_error (GPG_ERR_NO_OBJ);
|
|
|
|
|
|
|
|
for (idx=0,s=elems; *s; s++, idx++)
|
|
|
|
{
|
|
|
|
l2 = gcry_sexp_find_token (list, s, 1);
|
|
|
|
if (!l2)
|
|
|
|
{
|
|
|
|
rc = gpg_error (GPG_ERR_NO_OBJ); /* required parameter not found */
|
|
|
|
goto leave;
|
|
|
|
}
|
|
|
|
array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
|
|
|
|
gcry_sexp_release (l2);
|
2011-02-03 16:31:42 +01:00
|
|
|
if (!array[idx])
|
2003-07-29 10:53:19 +02:00
|
|
|
{
|
|
|
|
rc = gpg_error (GPG_ERR_INV_OBJ); /* required parameter invalid */
|
|
|
|
goto leave;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
gcry_sexp_release (list);
|
|
|
|
|
|
|
|
leave:
|
|
|
|
if (rc)
|
|
|
|
{
|
|
|
|
for (i=0; i<idx; i++)
|
|
|
|
{
|
2010-10-01 22:33:53 +02:00
|
|
|
gcry_mpi_release (array[i]);
|
2003-07-29 10:53:19 +02:00
|
|
|
array[i] = NULL;
|
|
|
|
}
|
|
|
|
gcry_sexp_release (list);
|
|
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
|
2011-11-06 17:01:31 +01:00
|
|
|
/* Create a keyblock using the given KEYGRIP. ALGO is the OpenPGP
|
|
|
|
algorithm of that keygrip. */
|
|
|
|
static int
|
|
|
|
do_create_from_keygrip (ctrl_t ctrl, int algo, const char *hexkeygrip,
|
|
|
|
kbnode_t pub_root, u32 timestamp, u32 expireval,
|
|
|
|
int is_subkey)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
PACKET *pkt;
|
|
|
|
PKT_public_key *pk;
|
|
|
|
gcry_sexp_t s_key;
|
|
|
|
const char *algoelem;
|
|
|
|
|
|
|
|
if (hexkeygrip[0] == '&')
|
|
|
|
hexkeygrip++;
|
|
|
|
|
|
|
|
switch (algo)
|
|
|
|
{
|
|
|
|
case PUBKEY_ALGO_RSA: algoelem = "ne"; break;
|
|
|
|
case PUBKEY_ALGO_DSA: algoelem = "pqgy"; break;
|
|
|
|
case PUBKEY_ALGO_ELGAMAL_E: algoelem = "pgy"; break;
|
|
|
|
case PUBKEY_ALGO_ECDH:
|
|
|
|
case PUBKEY_ALGO_ECDSA: algoelem = ""; break;
|
gpg: Use only OpenPGP public key algo ids and add the EdDSA algo id.
* common/sexputil.c (get_pk_algo_from_canon_sexp): Change to return a
string.
* g10/keygen.c (check_keygrip): Adjust for change.
* sm/certreqgen-ui.c (check_keygrip): Likewise.
* agent/pksign.c (do_encode_dsa): Remove bogus map_pk_openpgp_to_gcry.
* g10/misc.c (map_pk_openpgp_to_gcry): Remove.
(openpgp_pk_test_algo): Change to a wrapper for openpgp_pk_test_algo2.
(openpgp_pk_test_algo2): Rewrite.
(openpgp_pk_algo_usage, pubkey_nbits): Add support for EdDSA.
(openpgp_pk_algo_name): Rewrite to remove need for gcry calls.
(pubkey_get_npkey, pubkey_get_nskey): Ditto.
(pubkey_get_nsig, pubkey_get_nenc): Ditto.
* g10/keygen.c(do_create_from_keygrip): Support EdDSA.
(common_gen, gen_ecc, ask_keysize, generate_keypair): Ditto.
* g10/build-packet.c (do_key): Ditto.
* g10/export.c (transfer_format_to_openpgp): Ditto.
* g10/getkey.c (cache_public_key): Ditto.
* g10/import.c (transfer_secret_keys): Ditto.
* g10/keylist.c (list_keyblock_print, list_keyblock_colon): Ditto.
* g10/mainproc.c (proc_pubkey_enc): Ditto.
* g10/parse-packet.c (parse_key): Ditto,
* g10/sign.c (hash_for, sign_file, make_keysig_packet): Ditto.
* g10/keyserver.c (print_keyrec): Use openpgp_pk_algo_name.
* g10/pkglue.c (pk_verify, pk_encrypt, pk_check_secret_key): Use only
OpenPGP algo ids and support EdDSA.
* g10/pubkey-enc.c (get_it): Use only OpenPGP algo ids.
* g10/seskey.c (encode_md_value): Ditto.
--
This patch separates Libgcrypt and OpenPGP public key algorithms ids
and in most cases completely removes the Libgcrypt ones. This is
useful because for Libgcrypt we specify the algorithm in the
S-expressions and the public key ids are not anymore needed.
This patch also adds some support for PUBKEY_ALGO_EDDSA which will
eventually be used instead of merging EdDSA with ECDSA. As of now an
experimental algorithm id is used but the plan is to write an I-D so
that we can get a new id from the IETF. Note that EdDSA (Ed25519)
does not yet work and that more changes are required.
The ECC support is still broken right now. Needs to be fixed.
Signed-off-by: Werner Koch <wk@gnupg.org>
2014-01-30 18:48:37 +01:00
|
|
|
case PUBKEY_ALGO_EDDSA: algoelem = ""; break;
|
2011-11-06 17:01:31 +01:00
|
|
|
default: return gpg_error (GPG_ERR_INTERNAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Ask the agent for the public key matching HEXKEYGRIP. */
|
|
|
|
{
|
|
|
|
unsigned char *public;
|
|
|
|
|
|
|
|
err = agent_readkey (ctrl, 0, hexkeygrip, &public);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
err = gcry_sexp_sscan (&s_key, NULL,
|
|
|
|
public, gcry_sexp_canon_len (public, 0, NULL, NULL));
|
|
|
|
xfree (public);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Build a public key packet. */
|
|
|
|
pk = xtrycalloc (1, sizeof *pk);
|
|
|
|
if (!pk)
|
|
|
|
{
|
|
|
|
err = gpg_error_from_syserror ();
|
|
|
|
gcry_sexp_release (s_key);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
pk->timestamp = timestamp;
|
|
|
|
pk->version = 4;
|
|
|
|
if (expireval)
|
|
|
|
pk->expiredate = pk->timestamp + expireval;
|
|
|
|
pk->pubkey_algo = algo;
|
|
|
|
|
gpg: Use only OpenPGP public key algo ids and add the EdDSA algo id.
* common/sexputil.c (get_pk_algo_from_canon_sexp): Change to return a
string.
* g10/keygen.c (check_keygrip): Adjust for change.
* sm/certreqgen-ui.c (check_keygrip): Likewise.
* agent/pksign.c (do_encode_dsa): Remove bogus map_pk_openpgp_to_gcry.
* g10/misc.c (map_pk_openpgp_to_gcry): Remove.
(openpgp_pk_test_algo): Change to a wrapper for openpgp_pk_test_algo2.
(openpgp_pk_test_algo2): Rewrite.
(openpgp_pk_algo_usage, pubkey_nbits): Add support for EdDSA.
(openpgp_pk_algo_name): Rewrite to remove need for gcry calls.
(pubkey_get_npkey, pubkey_get_nskey): Ditto.
(pubkey_get_nsig, pubkey_get_nenc): Ditto.
* g10/keygen.c(do_create_from_keygrip): Support EdDSA.
(common_gen, gen_ecc, ask_keysize, generate_keypair): Ditto.
* g10/build-packet.c (do_key): Ditto.
* g10/export.c (transfer_format_to_openpgp): Ditto.
* g10/getkey.c (cache_public_key): Ditto.
* g10/import.c (transfer_secret_keys): Ditto.
* g10/keylist.c (list_keyblock_print, list_keyblock_colon): Ditto.
* g10/mainproc.c (proc_pubkey_enc): Ditto.
* g10/parse-packet.c (parse_key): Ditto,
* g10/sign.c (hash_for, sign_file, make_keysig_packet): Ditto.
* g10/keyserver.c (print_keyrec): Use openpgp_pk_algo_name.
* g10/pkglue.c (pk_verify, pk_encrypt, pk_check_secret_key): Use only
OpenPGP algo ids and support EdDSA.
* g10/pubkey-enc.c (get_it): Use only OpenPGP algo ids.
* g10/seskey.c (encode_md_value): Ditto.
--
This patch separates Libgcrypt and OpenPGP public key algorithms ids
and in most cases completely removes the Libgcrypt ones. This is
useful because for Libgcrypt we specify the algorithm in the
S-expressions and the public key ids are not anymore needed.
This patch also adds some support for PUBKEY_ALGO_EDDSA which will
eventually be used instead of merging EdDSA with ECDSA. As of now an
experimental algorithm id is used but the plan is to write an I-D so
that we can get a new id from the IETF. Note that EdDSA (Ed25519)
does not yet work and that more changes are required.
The ECC support is still broken right now. Needs to be fixed.
Signed-off-by: Werner Koch <wk@gnupg.org>
2014-01-30 18:48:37 +01:00
|
|
|
if (algo == PUBKEY_ALGO_ECDSA
|
|
|
|
|| algo == PUBKEY_ALGO_EDDSA
|
|
|
|
|| algo == PUBKEY_ALGO_ECDH )
|
2011-11-06 17:01:31 +01:00
|
|
|
err = ecckey_from_sexp (pk->pkey, s_key, algo);
|
|
|
|
else
|
|
|
|
err = key_from_sexp (pk->pkey, s_key, "public-key", algoelem);
|
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
log_error ("key_from_sexp failed: %s\n", gpg_strerror (err) );
|
|
|
|
gcry_sexp_release (s_key);
|
|
|
|
free_public_key (pk);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
gcry_sexp_release (s_key);
|
|
|
|
|
|
|
|
pkt = xtrycalloc (1, sizeof *pkt);
|
|
|
|
if (!pkt)
|
|
|
|
{
|
|
|
|
err = gpg_error_from_syserror ();
|
|
|
|
free_public_key (pk);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY;
|
|
|
|
pkt->pkt.public_key = pk;
|
|
|
|
add_kbnode (pub_root, new_kbnode (pkt));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-25 16:54:18 +01:00
|
|
|
/* Common code for the key generation fucntion gen_xxx. */
|
2003-07-29 10:53:19 +02:00
|
|
|
static int
|
2011-01-25 16:54:18 +01:00
|
|
|
common_gen (const char *keyparms, int algo, const char *algoelem,
|
|
|
|
kbnode_t pub_root, u32 timestamp, u32 expireval, int is_subkey,
|
|
|
|
int keygen_flags, char **cache_nonce_addr)
|
2003-07-29 10:53:19 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
int err;
|
2011-01-25 16:54:18 +01:00
|
|
|
PACKET *pkt;
|
2010-04-20 19:57:50 +02:00
|
|
|
PKT_public_key *pk;
|
|
|
|
gcry_sexp_t s_key;
|
2011-01-06 02:33:17 +01:00
|
|
|
|
2010-10-14 18:34:31 +02:00
|
|
|
err = agent_genkey (NULL, cache_nonce_addr, keyparms,
|
|
|
|
!!(keygen_flags & KEYGEN_FLAG_NO_PROTECTION), &s_key);
|
2010-04-20 19:57:50 +02:00
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
log_error ("agent_genkey failed: %s\n", gpg_strerror (err) );
|
|
|
|
return err;
|
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
pk = xtrycalloc (1, sizeof *pk);
|
|
|
|
if (!pk)
|
2003-07-29 10:53:19 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
err = gpg_error_from_syserror ();
|
|
|
|
gcry_sexp_release (s_key);
|
|
|
|
return err;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2011-01-25 16:54:18 +01:00
|
|
|
pk->timestamp = timestamp;
|
2010-04-20 19:57:50 +02:00
|
|
|
pk->version = 4;
|
2011-02-03 16:31:42 +01:00
|
|
|
if (expireval)
|
2011-01-25 16:54:18 +01:00
|
|
|
pk->expiredate = pk->timestamp + expireval;
|
2010-04-20 19:57:50 +02:00
|
|
|
pk->pubkey_algo = algo;
|
2003-07-29 10:53:19 +02:00
|
|
|
|
gpg: Use only OpenPGP public key algo ids and add the EdDSA algo id.
* common/sexputil.c (get_pk_algo_from_canon_sexp): Change to return a
string.
* g10/keygen.c (check_keygrip): Adjust for change.
* sm/certreqgen-ui.c (check_keygrip): Likewise.
* agent/pksign.c (do_encode_dsa): Remove bogus map_pk_openpgp_to_gcry.
* g10/misc.c (map_pk_openpgp_to_gcry): Remove.
(openpgp_pk_test_algo): Change to a wrapper for openpgp_pk_test_algo2.
(openpgp_pk_test_algo2): Rewrite.
(openpgp_pk_algo_usage, pubkey_nbits): Add support for EdDSA.
(openpgp_pk_algo_name): Rewrite to remove need for gcry calls.
(pubkey_get_npkey, pubkey_get_nskey): Ditto.
(pubkey_get_nsig, pubkey_get_nenc): Ditto.
* g10/keygen.c(do_create_from_keygrip): Support EdDSA.
(common_gen, gen_ecc, ask_keysize, generate_keypair): Ditto.
* g10/build-packet.c (do_key): Ditto.
* g10/export.c (transfer_format_to_openpgp): Ditto.
* g10/getkey.c (cache_public_key): Ditto.
* g10/import.c (transfer_secret_keys): Ditto.
* g10/keylist.c (list_keyblock_print, list_keyblock_colon): Ditto.
* g10/mainproc.c (proc_pubkey_enc): Ditto.
* g10/parse-packet.c (parse_key): Ditto,
* g10/sign.c (hash_for, sign_file, make_keysig_packet): Ditto.
* g10/keyserver.c (print_keyrec): Use openpgp_pk_algo_name.
* g10/pkglue.c (pk_verify, pk_encrypt, pk_check_secret_key): Use only
OpenPGP algo ids and support EdDSA.
* g10/pubkey-enc.c (get_it): Use only OpenPGP algo ids.
* g10/seskey.c (encode_md_value): Ditto.
--
This patch separates Libgcrypt and OpenPGP public key algorithms ids
and in most cases completely removes the Libgcrypt ones. This is
useful because for Libgcrypt we specify the algorithm in the
S-expressions and the public key ids are not anymore needed.
This patch also adds some support for PUBKEY_ALGO_EDDSA which will
eventually be used instead of merging EdDSA with ECDSA. As of now an
experimental algorithm id is used but the plan is to write an I-D so
that we can get a new id from the IETF. Note that EdDSA (Ed25519)
does not yet work and that more changes are required.
The ECC support is still broken right now. Needs to be fixed.
Signed-off-by: Werner Koch <wk@gnupg.org>
2014-01-30 18:48:37 +01:00
|
|
|
if (algo == PUBKEY_ALGO_ECDSA
|
|
|
|
|| algo == PUBKEY_ALGO_EDDSA
|
|
|
|
|| algo == PUBKEY_ALGO_ECDH )
|
2011-01-31 09:27:06 +01:00
|
|
|
err = ecckey_from_sexp (pk->pkey, s_key, algo);
|
|
|
|
else
|
|
|
|
err = key_from_sexp (pk->pkey, s_key, "public-key", algoelem);
|
2011-02-03 16:31:42 +01:00
|
|
|
if (err)
|
2010-04-20 19:57:50 +02:00
|
|
|
{
|
|
|
|
log_error ("key_from_sexp failed: %s\n", gpg_strerror (err) );
|
|
|
|
gcry_sexp_release (s_key);
|
|
|
|
free_public_key (pk);
|
|
|
|
return err;
|
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
gcry_sexp_release (s_key);
|
|
|
|
|
2011-01-25 16:54:18 +01:00
|
|
|
pkt = xtrycalloc (1, sizeof *pkt);
|
|
|
|
if (!pkt)
|
|
|
|
{
|
|
|
|
err = gpg_error_from_syserror ();
|
|
|
|
free_public_key (pk);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY;
|
|
|
|
pkt->pkt.public_key = pk;
|
|
|
|
add_kbnode (pub_root, new_kbnode (pkt));
|
2010-04-20 19:57:50 +02:00
|
|
|
|
|
|
|
return 0;
|
2003-07-29 10:53:19 +02:00
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2003-07-29 10:53:19 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
/*
|
|
|
|
* Generate an Elgamal key.
|
|
|
|
*/
|
2003-07-29 10:53:19 +02:00
|
|
|
static int
|
2010-04-20 19:57:50 +02:00
|
|
|
gen_elg (int algo, unsigned int nbits, KBNODE pub_root,
|
2010-10-14 18:34:31 +02:00
|
|
|
u32 timestamp, u32 expireval, int is_subkey,
|
|
|
|
int keygen_flags, char **cache_nonce_addr)
|
2003-07-29 10:53:19 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
int err;
|
|
|
|
char *keyparms;
|
|
|
|
char nbitsstr[35];
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
assert (is_ELGAMAL (algo));
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2014-06-25 20:25:28 +02:00
|
|
|
if (nbits < 1024)
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2013-08-30 10:27:21 +02:00
|
|
|
nbits = 2048;
|
2007-07-05 18:58:19 +02:00
|
|
|
log_info (_("keysize invalid; using %u bits\n"), nbits );
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2014-06-25 20:25:28 +02:00
|
|
|
else if (nbits > 4096)
|
|
|
|
{
|
|
|
|
nbits = 4096;
|
|
|
|
log_info (_("keysize invalid; using %u bits\n"), nbits );
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
if ((nbits % 32))
|
|
|
|
{
|
|
|
|
nbits = ((nbits + 31) / 32) * 32;
|
|
|
|
log_info (_("keysize rounded up to %u bits\n"), nbits );
|
2003-07-29 10:53:19 +02:00
|
|
|
}
|
|
|
|
|
2010-10-14 18:34:31 +02:00
|
|
|
/* Note that we use transient-key only if no-protection has also
|
|
|
|
been enabled. */
|
2010-04-20 19:57:50 +02:00
|
|
|
snprintf (nbitsstr, sizeof nbitsstr, "%u", nbits);
|
2010-10-14 18:34:31 +02:00
|
|
|
keyparms = xtryasprintf ("(genkey(%s(nbits %zu:%s)%s))",
|
2010-04-20 19:57:50 +02:00
|
|
|
algo == GCRY_PK_ELG_E ? "openpgp-elg" :
|
|
|
|
algo == GCRY_PK_ELG ? "elg" : "x-oops" ,
|
2010-10-14 18:34:31 +02:00
|
|
|
strlen (nbitsstr), nbitsstr,
|
|
|
|
((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
|
|
|
|
&& (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
|
|
|
|
"(transient-key)" : "" );
|
2010-04-20 19:57:50 +02:00
|
|
|
if (!keyparms)
|
|
|
|
err = gpg_error_from_syserror ();
|
|
|
|
else
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2011-02-03 16:31:42 +01:00
|
|
|
err = common_gen (keyparms, algo, "pgy",
|
2010-09-01 11:48:35 +02:00
|
|
|
pub_root, timestamp, expireval, is_subkey,
|
2010-10-14 18:34:31 +02:00
|
|
|
keygen_flags, cache_nonce_addr);
|
2010-04-20 19:57:50 +02:00
|
|
|
xfree (keyparms);
|
2007-07-05 18:58:19 +02:00
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
return err;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
/*
|
|
|
|
* Generate an DSA key
|
2003-06-05 09:14:21 +02:00
|
|
|
*/
|
2010-04-20 19:57:50 +02:00
|
|
|
static gpg_error_t
|
2011-02-03 16:31:42 +01:00
|
|
|
gen_dsa (unsigned int nbits, KBNODE pub_root,
|
2010-10-14 18:34:31 +02:00
|
|
|
u32 timestamp, u32 expireval, int is_subkey,
|
|
|
|
int keygen_flags, char **cache_nonce_addr)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
int err;
|
2007-07-05 18:58:19 +02:00
|
|
|
unsigned int qbits;
|
2010-04-20 19:57:50 +02:00
|
|
|
char *keyparms;
|
|
|
|
char nbitsstr[35];
|
|
|
|
char qbitsstr[35];
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2014-06-25 20:25:28 +02:00
|
|
|
if (nbits < 768)
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2013-08-30 10:27:21 +02:00
|
|
|
nbits = 2048;
|
2007-07-05 18:58:19 +02:00
|
|
|
log_info(_("keysize invalid; using %u bits\n"), nbits );
|
|
|
|
}
|
|
|
|
else if ( nbits > 3072 )
|
|
|
|
{
|
|
|
|
nbits = 3072;
|
|
|
|
log_info(_("keysize invalid; using %u bits\n"), nbits );
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
if( (nbits % 64) )
|
|
|
|
{
|
|
|
|
nbits = ((nbits + 63) / 64) * 64;
|
|
|
|
log_info(_("keysize rounded up to %u bits\n"), nbits );
|
|
|
|
}
|
2006-06-27 16:30:59 +02:00
|
|
|
|
2009-07-09 10:52:31 +02:00
|
|
|
/* To comply with FIPS rules we round up to the next value unless in
|
|
|
|
expert mode. */
|
|
|
|
if (!opt.expert && nbits > 1024 && (nbits % 1024))
|
|
|
|
{
|
|
|
|
nbits = ((nbits + 1023) / 1024) * 1024;
|
|
|
|
log_info(_("keysize rounded up to %u bits\n"), nbits );
|
|
|
|
}
|
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
/*
|
|
|
|
Figure out a q size based on the key size. FIPS 180-3 says:
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
L = 1024, N = 160
|
|
|
|
L = 2048, N = 224
|
|
|
|
L = 2048, N = 256
|
|
|
|
L = 3072, N = 256
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
2048/256 is an odd pair since there is also a 2048/224 and
|
|
|
|
3072/256. Matching sizes is not a very exact science.
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2009-07-09 10:52:31 +02:00
|
|
|
We'll do 256 qbits for nbits over 2047, 224 for nbits over 1024
|
2007-07-05 18:58:19 +02:00
|
|
|
but less than 2048, and 160 for 1024 (DSA1).
|
|
|
|
*/
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2009-07-09 10:52:31 +02:00
|
|
|
if (nbits > 2047)
|
2007-07-05 18:58:19 +02:00
|
|
|
qbits = 256;
|
|
|
|
else if ( nbits > 1024)
|
|
|
|
qbits = 224;
|
|
|
|
else
|
|
|
|
qbits = 160;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
if (qbits != 160 )
|
|
|
|
log_info (_("WARNING: some OpenPGP programs can't"
|
|
|
|
" handle a DSA key with this digest size\n"));
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
snprintf (nbitsstr, sizeof nbitsstr, "%u", nbits);
|
|
|
|
snprintf (qbitsstr, sizeof qbitsstr, "%u", qbits);
|
2010-10-14 18:34:31 +02:00
|
|
|
keyparms = xtryasprintf ("(genkey(dsa(nbits %zu:%s)(qbits %zu:%s)%s))",
|
2010-04-20 19:57:50 +02:00
|
|
|
strlen (nbitsstr), nbitsstr,
|
2010-10-14 18:34:31 +02:00
|
|
|
strlen (qbitsstr), qbitsstr,
|
|
|
|
((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
|
|
|
|
&& (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
|
|
|
|
"(transient-key)" : "" );
|
2010-04-20 19:57:50 +02:00
|
|
|
if (!keyparms)
|
|
|
|
err = gpg_error_from_syserror ();
|
|
|
|
else
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2011-02-03 16:31:42 +01:00
|
|
|
err = common_gen (keyparms, PUBKEY_ALGO_DSA, "pqgy",
|
2010-09-01 11:48:35 +02:00
|
|
|
pub_root, timestamp, expireval, is_subkey,
|
2010-10-14 18:34:31 +02:00
|
|
|
keygen_flags, cache_nonce_addr);
|
2010-04-20 19:57:50 +02:00
|
|
|
xfree (keyparms);
|
2007-07-05 18:58:19 +02:00
|
|
|
}
|
2003-07-29 10:53:19 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
return err;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2011-01-06 02:33:17 +01:00
|
|
|
|
|
|
|
|
2011-01-25 16:54:18 +01:00
|
|
|
/*
|
|
|
|
* Generate an ECC key
|
|
|
|
*/
|
|
|
|
static gpg_error_t
|
2013-11-15 08:59:45 +01:00
|
|
|
gen_ecc (int algo, const char *curve, kbnode_t pub_root,
|
2011-01-25 16:54:18 +01:00
|
|
|
u32 timestamp, u32 expireval, int is_subkey,
|
|
|
|
int keygen_flags, char **cache_nonce_addr)
|
|
|
|
{
|
2011-01-31 09:27:06 +01:00
|
|
|
gpg_error_t err;
|
2011-01-06 02:33:17 +01:00
|
|
|
char *keyparms;
|
|
|
|
|
gpg: Use only OpenPGP public key algo ids and add the EdDSA algo id.
* common/sexputil.c (get_pk_algo_from_canon_sexp): Change to return a
string.
* g10/keygen.c (check_keygrip): Adjust for change.
* sm/certreqgen-ui.c (check_keygrip): Likewise.
* agent/pksign.c (do_encode_dsa): Remove bogus map_pk_openpgp_to_gcry.
* g10/misc.c (map_pk_openpgp_to_gcry): Remove.
(openpgp_pk_test_algo): Change to a wrapper for openpgp_pk_test_algo2.
(openpgp_pk_test_algo2): Rewrite.
(openpgp_pk_algo_usage, pubkey_nbits): Add support for EdDSA.
(openpgp_pk_algo_name): Rewrite to remove need for gcry calls.
(pubkey_get_npkey, pubkey_get_nskey): Ditto.
(pubkey_get_nsig, pubkey_get_nenc): Ditto.
* g10/keygen.c(do_create_from_keygrip): Support EdDSA.
(common_gen, gen_ecc, ask_keysize, generate_keypair): Ditto.
* g10/build-packet.c (do_key): Ditto.
* g10/export.c (transfer_format_to_openpgp): Ditto.
* g10/getkey.c (cache_public_key): Ditto.
* g10/import.c (transfer_secret_keys): Ditto.
* g10/keylist.c (list_keyblock_print, list_keyblock_colon): Ditto.
* g10/mainproc.c (proc_pubkey_enc): Ditto.
* g10/parse-packet.c (parse_key): Ditto,
* g10/sign.c (hash_for, sign_file, make_keysig_packet): Ditto.
* g10/keyserver.c (print_keyrec): Use openpgp_pk_algo_name.
* g10/pkglue.c (pk_verify, pk_encrypt, pk_check_secret_key): Use only
OpenPGP algo ids and support EdDSA.
* g10/pubkey-enc.c (get_it): Use only OpenPGP algo ids.
* g10/seskey.c (encode_md_value): Ditto.
--
This patch separates Libgcrypt and OpenPGP public key algorithms ids
and in most cases completely removes the Libgcrypt ones. This is
useful because for Libgcrypt we specify the algorithm in the
S-expressions and the public key ids are not anymore needed.
This patch also adds some support for PUBKEY_ALGO_EDDSA which will
eventually be used instead of merging EdDSA with ECDSA. As of now an
experimental algorithm id is used but the plan is to write an I-D so
that we can get a new id from the IETF. Note that EdDSA (Ed25519)
does not yet work and that more changes are required.
The ECC support is still broken right now. Needs to be fixed.
Signed-off-by: Werner Koch <wk@gnupg.org>
2014-01-30 18:48:37 +01:00
|
|
|
assert (algo == PUBKEY_ALGO_ECDSA
|
|
|
|
|| algo == PUBKEY_ALGO_EDDSA
|
|
|
|
|| algo == PUBKEY_ALGO_ECDH);
|
2011-01-06 02:33:17 +01:00
|
|
|
|
2013-11-15 08:59:45 +01:00
|
|
|
if (!curve || !*curve)
|
|
|
|
return gpg_error (GPG_ERR_UNKNOWN_CURVE);
|
2011-01-31 09:27:06 +01:00
|
|
|
|
2014-07-24 16:16:53 +02:00
|
|
|
/* Note that we use the "comp" flag with EdDSA to request the use of
|
|
|
|
a 0x40 compression prefix octet. */
|
|
|
|
if (algo == PUBKEY_ALGO_EDDSA)
|
|
|
|
keyparms = xtryasprintf
|
|
|
|
("(genkey(ecc(curve %zu:%s)(flags eddsa comp%s)))",
|
|
|
|
strlen (curve), curve,
|
|
|
|
(((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
|
|
|
|
&& (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
|
|
|
|
" transient-key" : ""));
|
|
|
|
else
|
|
|
|
keyparms = xtryasprintf
|
|
|
|
("(genkey(ecc(curve %zu:%s)(flags nocomp%s)))",
|
|
|
|
strlen (curve), curve,
|
|
|
|
(((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
|
|
|
|
&& (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
|
|
|
|
" transient-key" : ""));
|
|
|
|
|
2011-01-25 16:54:18 +01:00
|
|
|
if (!keyparms)
|
2011-01-31 09:27:06 +01:00
|
|
|
err = gpg_error_from_syserror ();
|
2011-01-06 02:33:17 +01:00
|
|
|
else
|
|
|
|
{
|
2011-01-31 09:27:06 +01:00
|
|
|
err = common_gen (keyparms, algo, "",
|
2011-01-25 16:54:18 +01:00
|
|
|
pub_root, timestamp, expireval, is_subkey,
|
|
|
|
keygen_flags, cache_nonce_addr);
|
2011-01-06 02:33:17 +01:00
|
|
|
xfree (keyparms);
|
|
|
|
}
|
|
|
|
|
2011-01-31 09:27:06 +01:00
|
|
|
return err;
|
2011-01-06 02:33:17 +01:00
|
|
|
}
|
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2011-02-03 16:31:42 +01:00
|
|
|
/*
|
2003-06-05 09:14:21 +02:00
|
|
|
* Generate an RSA key.
|
|
|
|
*/
|
|
|
|
static int
|
2010-04-20 19:57:50 +02:00
|
|
|
gen_rsa (int algo, unsigned int nbits, KBNODE pub_root,
|
2010-10-14 18:34:31 +02:00
|
|
|
u32 timestamp, u32 expireval, int is_subkey,
|
|
|
|
int keygen_flags, char **cache_nonce_addr)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
int err;
|
|
|
|
char *keyparms;
|
|
|
|
char nbitsstr[35];
|
2014-10-09 22:54:15 +02:00
|
|
|
const unsigned maxsize = (opt.flags.large_rsa ? 8192 : 4096);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
assert (is_RSA(algo));
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2009-12-04 20:47:54 +01:00
|
|
|
if (!nbits)
|
|
|
|
nbits = DEFAULT_STD_KEYSIZE;
|
|
|
|
|
2011-02-03 16:31:42 +01:00
|
|
|
if (nbits < 1024)
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2013-08-30 10:27:21 +02:00
|
|
|
nbits = 2048;
|
2007-07-05 18:58:19 +02:00
|
|
|
log_info (_("keysize invalid; using %u bits\n"), nbits );
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2014-10-09 22:54:15 +02:00
|
|
|
else if (nbits > maxsize)
|
2014-06-25 20:25:28 +02:00
|
|
|
{
|
2014-10-09 22:54:15 +02:00
|
|
|
nbits = maxsize;
|
2014-06-25 20:25:28 +02:00
|
|
|
log_info (_("keysize invalid; using %u bits\n"), nbits );
|
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
if ((nbits % 32))
|
|
|
|
{
|
|
|
|
nbits = ((nbits + 31) / 32) * 32;
|
|
|
|
log_info (_("keysize rounded up to %u bits\n"), nbits );
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
snprintf (nbitsstr, sizeof nbitsstr, "%u", nbits);
|
2011-02-03 16:31:42 +01:00
|
|
|
keyparms = xtryasprintf ("(genkey(rsa(nbits %zu:%s)%s))",
|
2010-10-14 18:34:31 +02:00
|
|
|
strlen (nbitsstr), nbitsstr,
|
|
|
|
((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
|
|
|
|
&& (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
|
|
|
|
"(transient-key)" : "" );
|
2010-04-20 19:57:50 +02:00
|
|
|
if (!keyparms)
|
|
|
|
err = gpg_error_from_syserror ();
|
|
|
|
else
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2011-02-03 16:31:42 +01:00
|
|
|
err = common_gen (keyparms, algo, "ne",
|
2010-09-01 11:48:35 +02:00
|
|
|
pub_root, timestamp, expireval, is_subkey,
|
2010-10-14 18:34:31 +02:00
|
|
|
keygen_flags, cache_nonce_addr);
|
2010-04-20 19:57:50 +02:00
|
|
|
xfree (keyparms);
|
2007-07-05 18:58:19 +02:00
|
|
|
}
|
2003-07-29 10:53:19 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
return err;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************
|
|
|
|
* check valid days:
|
|
|
|
* return 0 on error or the multiplier
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
check_valid_days( const char *s )
|
|
|
|
{
|
2003-09-23 19:48:33 +02:00
|
|
|
if( !digitp(s) )
|
2003-06-05 09:14:21 +02:00
|
|
|
return 0;
|
|
|
|
for( s++; *s; s++)
|
2003-09-23 19:48:33 +02:00
|
|
|
if( !digitp(s) )
|
2003-06-05 09:14:21 +02:00
|
|
|
break;
|
|
|
|
if( !*s )
|
|
|
|
return 1;
|
|
|
|
if( s[1] )
|
|
|
|
return 0; /* e.g. "2323wc" */
|
|
|
|
if( *s == 'd' || *s == 'D' )
|
|
|
|
return 1;
|
|
|
|
if( *s == 'w' || *s == 'W' )
|
|
|
|
return 7;
|
|
|
|
if( *s == 'm' || *s == 'M' )
|
|
|
|
return 30;
|
|
|
|
if( *s == 'y' || *s == 'Y' )
|
|
|
|
return 365;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
static void
|
|
|
|
print_key_flags(int flags)
|
|
|
|
{
|
|
|
|
if(flags&PUBKEY_USAGE_SIG)
|
|
|
|
tty_printf("%s ",_("Sign"));
|
|
|
|
|
|
|
|
if(flags&PUBKEY_USAGE_CERT)
|
|
|
|
tty_printf("%s ",_("Certify"));
|
|
|
|
|
|
|
|
if(flags&PUBKEY_USAGE_ENC)
|
|
|
|
tty_printf("%s ",_("Encrypt"));
|
|
|
|
|
|
|
|
if(flags&PUBKEY_USAGE_AUTH)
|
|
|
|
tty_printf("%s ",_("Authenticate"));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Returns the key flags */
|
|
|
|
static unsigned int
|
|
|
|
ask_key_flags(int algo,int subkey)
|
|
|
|
{
|
2007-12-04 12:23:31 +01:00
|
|
|
/* TRANSLATORS: Please use only plain ASCII characters for the
|
|
|
|
translation. If this is not possible use single digits. The
|
|
|
|
string needs to 8 bytes long. Here is a description of the
|
|
|
|
functions:
|
|
|
|
|
|
|
|
s = Toggle signing capability
|
|
|
|
e = Toggle encryption capability
|
|
|
|
a = Toggle authentication capability
|
|
|
|
q = Finish
|
|
|
|
*/
|
2006-04-19 13:26:11 +02:00
|
|
|
const char *togglers=_("SsEeAaQq");
|
|
|
|
char *answer=NULL;
|
2014-09-26 14:43:48 +02:00
|
|
|
const char *s;
|
2006-04-19 13:26:11 +02:00
|
|
|
unsigned int current=0;
|
|
|
|
unsigned int possible=openpgp_pk_algo_usage(algo);
|
|
|
|
|
2009-05-20 11:08:48 +02:00
|
|
|
if ( strlen(togglers) != 8 )
|
2007-12-04 12:23:31 +01:00
|
|
|
{
|
|
|
|
tty_printf ("NOTE: Bad translation at %s:%d. "
|
|
|
|
"Please report.\n", __FILE__, __LINE__);
|
|
|
|
togglers = "11223300";
|
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
|
|
|
|
/* Only primary keys may certify. */
|
|
|
|
if(subkey)
|
|
|
|
possible&=~PUBKEY_USAGE_CERT;
|
|
|
|
|
|
|
|
/* Preload the current set with the possible set, minus
|
|
|
|
authentication, since nobody really uses auth yet. */
|
|
|
|
current=possible&~PUBKEY_USAGE_AUTH;
|
|
|
|
|
|
|
|
for(;;)
|
|
|
|
{
|
|
|
|
tty_printf("\n");
|
|
|
|
tty_printf(_("Possible actions for a %s key: "),
|
2011-02-03 17:40:43 +01:00
|
|
|
openpgp_pk_algo_name (algo));
|
2006-04-19 13:26:11 +02:00
|
|
|
print_key_flags(possible);
|
|
|
|
tty_printf("\n");
|
|
|
|
tty_printf(_("Current allowed actions: "));
|
|
|
|
print_key_flags(current);
|
|
|
|
tty_printf("\n\n");
|
|
|
|
|
|
|
|
if(possible&PUBKEY_USAGE_SIG)
|
|
|
|
tty_printf(_(" (%c) Toggle the sign capability\n"),
|
|
|
|
togglers[0]);
|
|
|
|
if(possible&PUBKEY_USAGE_ENC)
|
|
|
|
tty_printf(_(" (%c) Toggle the encrypt capability\n"),
|
|
|
|
togglers[2]);
|
|
|
|
if(possible&PUBKEY_USAGE_AUTH)
|
|
|
|
tty_printf(_(" (%c) Toggle the authenticate capability\n"),
|
|
|
|
togglers[4]);
|
|
|
|
|
|
|
|
tty_printf(_(" (%c) Finished\n"),togglers[6]);
|
|
|
|
tty_printf("\n");
|
|
|
|
|
|
|
|
xfree(answer);
|
|
|
|
answer = cpr_get("keygen.flags",_("Your selection? "));
|
|
|
|
cpr_kill_prompt();
|
|
|
|
|
2014-09-26 14:43:48 +02:00
|
|
|
if (*answer == '=')
|
|
|
|
{
|
|
|
|
/* Hack to allow direct entry of the capabilities. */
|
|
|
|
current = 0;
|
|
|
|
for (s=answer+1; *s; s++)
|
|
|
|
{
|
|
|
|
if ((*s == 's' || *s == 'S') && (possible&PUBKEY_USAGE_SIG))
|
|
|
|
current |= PUBKEY_USAGE_SIG;
|
|
|
|
else if ((*s == 'e' || *s == 'E') && (possible&PUBKEY_USAGE_ENC))
|
|
|
|
current |= PUBKEY_USAGE_ENC;
|
|
|
|
else if ((*s == 'a' || *s == 'A') && (possible&PUBKEY_USAGE_AUTH))
|
|
|
|
current |= PUBKEY_USAGE_AUTH;
|
2014-10-03 15:05:47 +02:00
|
|
|
else if (!subkey && *s == 'c')
|
|
|
|
{
|
|
|
|
/* Accept 'c' for the primary key because USAGE_CERT
|
|
|
|
will will be set anyway. This is for folks who
|
|
|
|
want to experiment with a cert-only primary key. */
|
|
|
|
current |= PUBKEY_USAGE_CERT;
|
|
|
|
}
|
2014-09-26 14:43:48 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (strlen(answer)>1)
|
2006-04-19 13:26:11 +02:00
|
|
|
tty_printf(_("Invalid selection.\n"));
|
|
|
|
else if(*answer=='\0' || *answer==togglers[6] || *answer==togglers[7])
|
|
|
|
break;
|
|
|
|
else if((*answer==togglers[0] || *answer==togglers[1])
|
|
|
|
&& possible&PUBKEY_USAGE_SIG)
|
|
|
|
{
|
|
|
|
if(current&PUBKEY_USAGE_SIG)
|
|
|
|
current&=~PUBKEY_USAGE_SIG;
|
|
|
|
else
|
|
|
|
current|=PUBKEY_USAGE_SIG;
|
|
|
|
}
|
|
|
|
else if((*answer==togglers[2] || *answer==togglers[3])
|
|
|
|
&& possible&PUBKEY_USAGE_ENC)
|
|
|
|
{
|
|
|
|
if(current&PUBKEY_USAGE_ENC)
|
|
|
|
current&=~PUBKEY_USAGE_ENC;
|
|
|
|
else
|
|
|
|
current|=PUBKEY_USAGE_ENC;
|
|
|
|
}
|
|
|
|
else if((*answer==togglers[4] || *answer==togglers[5])
|
|
|
|
&& possible&PUBKEY_USAGE_AUTH)
|
|
|
|
{
|
|
|
|
if(current&PUBKEY_USAGE_AUTH)
|
|
|
|
current&=~PUBKEY_USAGE_AUTH;
|
|
|
|
else
|
|
|
|
current|=PUBKEY_USAGE_AUTH;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
tty_printf(_("Invalid selection.\n"));
|
|
|
|
}
|
|
|
|
|
|
|
|
xfree(answer);
|
|
|
|
|
|
|
|
return current;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-06 17:01:31 +01:00
|
|
|
/* Check whether we have a key for the key with HEXGRIP. Returns 0 if
|
|
|
|
there is no such key or the OpenPGP algo number for the key. */
|
|
|
|
static int
|
|
|
|
check_keygrip (ctrl_t ctrl, const char *hexgrip)
|
|
|
|
{
|
|
|
|
gpg_error_t err;
|
|
|
|
unsigned char *public;
|
|
|
|
size_t publiclen;
|
gpg: Use only OpenPGP public key algo ids and add the EdDSA algo id.
* common/sexputil.c (get_pk_algo_from_canon_sexp): Change to return a
string.
* g10/keygen.c (check_keygrip): Adjust for change.
* sm/certreqgen-ui.c (check_keygrip): Likewise.
* agent/pksign.c (do_encode_dsa): Remove bogus map_pk_openpgp_to_gcry.
* g10/misc.c (map_pk_openpgp_to_gcry): Remove.
(openpgp_pk_test_algo): Change to a wrapper for openpgp_pk_test_algo2.
(openpgp_pk_test_algo2): Rewrite.
(openpgp_pk_algo_usage, pubkey_nbits): Add support for EdDSA.
(openpgp_pk_algo_name): Rewrite to remove need for gcry calls.
(pubkey_get_npkey, pubkey_get_nskey): Ditto.
(pubkey_get_nsig, pubkey_get_nenc): Ditto.
* g10/keygen.c(do_create_from_keygrip): Support EdDSA.
(common_gen, gen_ecc, ask_keysize, generate_keypair): Ditto.
* g10/build-packet.c (do_key): Ditto.
* g10/export.c (transfer_format_to_openpgp): Ditto.
* g10/getkey.c (cache_public_key): Ditto.
* g10/import.c (transfer_secret_keys): Ditto.
* g10/keylist.c (list_keyblock_print, list_keyblock_colon): Ditto.
* g10/mainproc.c (proc_pubkey_enc): Ditto.
* g10/parse-packet.c (parse_key): Ditto,
* g10/sign.c (hash_for, sign_file, make_keysig_packet): Ditto.
* g10/keyserver.c (print_keyrec): Use openpgp_pk_algo_name.
* g10/pkglue.c (pk_verify, pk_encrypt, pk_check_secret_key): Use only
OpenPGP algo ids and support EdDSA.
* g10/pubkey-enc.c (get_it): Use only OpenPGP algo ids.
* g10/seskey.c (encode_md_value): Ditto.
--
This patch separates Libgcrypt and OpenPGP public key algorithms ids
and in most cases completely removes the Libgcrypt ones. This is
useful because for Libgcrypt we specify the algorithm in the
S-expressions and the public key ids are not anymore needed.
This patch also adds some support for PUBKEY_ALGO_EDDSA which will
eventually be used instead of merging EdDSA with ECDSA. As of now an
experimental algorithm id is used but the plan is to write an I-D so
that we can get a new id from the IETF. Note that EdDSA (Ed25519)
does not yet work and that more changes are required.
The ECC support is still broken right now. Needs to be fixed.
Signed-off-by: Werner Koch <wk@gnupg.org>
2014-01-30 18:48:37 +01:00
|
|
|
const char *algostr;
|
2011-11-06 17:01:31 +01:00
|
|
|
|
|
|
|
if (hexgrip[0] == '&')
|
|
|
|
hexgrip++;
|
|
|
|
|
|
|
|
err = agent_readkey (ctrl, 0, hexgrip, &public);
|
|
|
|
if (err)
|
|
|
|
return 0;
|
|
|
|
publiclen = gcry_sexp_canon_len (public, 0, NULL, NULL);
|
|
|
|
|
gpg: Use only OpenPGP public key algo ids and add the EdDSA algo id.
* common/sexputil.c (get_pk_algo_from_canon_sexp): Change to return a
string.
* g10/keygen.c (check_keygrip): Adjust for change.
* sm/certreqgen-ui.c (check_keygrip): Likewise.
* agent/pksign.c (do_encode_dsa): Remove bogus map_pk_openpgp_to_gcry.
* g10/misc.c (map_pk_openpgp_to_gcry): Remove.
(openpgp_pk_test_algo): Change to a wrapper for openpgp_pk_test_algo2.
(openpgp_pk_test_algo2): Rewrite.
(openpgp_pk_algo_usage, pubkey_nbits): Add support for EdDSA.
(openpgp_pk_algo_name): Rewrite to remove need for gcry calls.
(pubkey_get_npkey, pubkey_get_nskey): Ditto.
(pubkey_get_nsig, pubkey_get_nenc): Ditto.
* g10/keygen.c(do_create_from_keygrip): Support EdDSA.
(common_gen, gen_ecc, ask_keysize, generate_keypair): Ditto.
* g10/build-packet.c (do_key): Ditto.
* g10/export.c (transfer_format_to_openpgp): Ditto.
* g10/getkey.c (cache_public_key): Ditto.
* g10/import.c (transfer_secret_keys): Ditto.
* g10/keylist.c (list_keyblock_print, list_keyblock_colon): Ditto.
* g10/mainproc.c (proc_pubkey_enc): Ditto.
* g10/parse-packet.c (parse_key): Ditto,
* g10/sign.c (hash_for, sign_file, make_keysig_packet): Ditto.
* g10/keyserver.c (print_keyrec): Use openpgp_pk_algo_name.
* g10/pkglue.c (pk_verify, pk_encrypt, pk_check_secret_key): Use only
OpenPGP algo ids and support EdDSA.
* g10/pubkey-enc.c (get_it): Use only OpenPGP algo ids.
* g10/seskey.c (encode_md_value): Ditto.
--
This patch separates Libgcrypt and OpenPGP public key algorithms ids
and in most cases completely removes the Libgcrypt ones. This is
useful because for Libgcrypt we specify the algorithm in the
S-expressions and the public key ids are not anymore needed.
This patch also adds some support for PUBKEY_ALGO_EDDSA which will
eventually be used instead of merging EdDSA with ECDSA. As of now an
experimental algorithm id is used but the plan is to write an I-D so
that we can get a new id from the IETF. Note that EdDSA (Ed25519)
does not yet work and that more changes are required.
The ECC support is still broken right now. Needs to be fixed.
Signed-off-by: Werner Koch <wk@gnupg.org>
2014-01-30 18:48:37 +01:00
|
|
|
get_pk_algo_from_canon_sexp (public, publiclen, &algostr);
|
2011-11-06 17:01:31 +01:00
|
|
|
xfree (public);
|
|
|
|
|
gpg: Use only OpenPGP public key algo ids and add the EdDSA algo id.
* common/sexputil.c (get_pk_algo_from_canon_sexp): Change to return a
string.
* g10/keygen.c (check_keygrip): Adjust for change.
* sm/certreqgen-ui.c (check_keygrip): Likewise.
* agent/pksign.c (do_encode_dsa): Remove bogus map_pk_openpgp_to_gcry.
* g10/misc.c (map_pk_openpgp_to_gcry): Remove.
(openpgp_pk_test_algo): Change to a wrapper for openpgp_pk_test_algo2.
(openpgp_pk_test_algo2): Rewrite.
(openpgp_pk_algo_usage, pubkey_nbits): Add support for EdDSA.
(openpgp_pk_algo_name): Rewrite to remove need for gcry calls.
(pubkey_get_npkey, pubkey_get_nskey): Ditto.
(pubkey_get_nsig, pubkey_get_nenc): Ditto.
* g10/keygen.c(do_create_from_keygrip): Support EdDSA.
(common_gen, gen_ecc, ask_keysize, generate_keypair): Ditto.
* g10/build-packet.c (do_key): Ditto.
* g10/export.c (transfer_format_to_openpgp): Ditto.
* g10/getkey.c (cache_public_key): Ditto.
* g10/import.c (transfer_secret_keys): Ditto.
* g10/keylist.c (list_keyblock_print, list_keyblock_colon): Ditto.
* g10/mainproc.c (proc_pubkey_enc): Ditto.
* g10/parse-packet.c (parse_key): Ditto,
* g10/sign.c (hash_for, sign_file, make_keysig_packet): Ditto.
* g10/keyserver.c (print_keyrec): Use openpgp_pk_algo_name.
* g10/pkglue.c (pk_verify, pk_encrypt, pk_check_secret_key): Use only
OpenPGP algo ids and support EdDSA.
* g10/pubkey-enc.c (get_it): Use only OpenPGP algo ids.
* g10/seskey.c (encode_md_value): Ditto.
--
This patch separates Libgcrypt and OpenPGP public key algorithms ids
and in most cases completely removes the Libgcrypt ones. This is
useful because for Libgcrypt we specify the algorithm in the
S-expressions and the public key ids are not anymore needed.
This patch also adds some support for PUBKEY_ALGO_EDDSA which will
eventually be used instead of merging EdDSA with ECDSA. As of now an
experimental algorithm id is used but the plan is to write an I-D so
that we can get a new id from the IETF. Note that EdDSA (Ed25519)
does not yet work and that more changes are required.
The ECC support is still broken right now. Needs to be fixed.
Signed-off-by: Werner Koch <wk@gnupg.org>
2014-01-30 18:48:37 +01:00
|
|
|
/* FIXME: Mapping of ECC algorithms is probably not correct. */
|
|
|
|
if (!algostr)
|
|
|
|
return 0;
|
|
|
|
else if (!strcmp (algostr, "rsa"))
|
|
|
|
return PUBKEY_ALGO_RSA;
|
|
|
|
else if (!strcmp (algostr, "dsa"))
|
|
|
|
return PUBKEY_ALGO_DSA;
|
|
|
|
else if (!strcmp (algostr, "elg"))
|
|
|
|
return PUBKEY_ALGO_ELGAMAL_E;
|
|
|
|
else if (!strcmp (algostr, "ecc"))
|
|
|
|
return PUBKEY_ALGO_ECDH;
|
|
|
|
else if (!strcmp (algostr, "ecdsa"))
|
|
|
|
return PUBKEY_ALGO_ECDSA;
|
|
|
|
else if (!strcmp (algostr, "eddsa"))
|
|
|
|
return PUBKEY_ALGO_EDDSA;
|
|
|
|
else
|
|
|
|
return 0;
|
2011-11-06 17:01:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-05-17 15:08:18 +02:00
|
|
|
/* Ask for an algorithm. The function returns the algorithm id to
|
|
|
|
* create. If ADDMODE is false the function won't show an option to
|
|
|
|
* create the primary and subkey combined and won't set R_USAGE
|
|
|
|
* either. If a combined algorithm has been selected, the subkey
|
2011-11-06 17:01:31 +01:00
|
|
|
* algorithm is stored at R_SUBKEY_ALGO. If R_KEYGRIP is given, the
|
|
|
|
* user has the choice to enter the keygrip of an existing key. That
|
|
|
|
* keygrip is then stored at this address. The caller needs to free
|
|
|
|
* it. */
|
2003-06-05 09:14:21 +02:00
|
|
|
static int
|
2011-11-06 17:01:31 +01:00
|
|
|
ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
|
|
|
|
char **r_keygrip)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2011-11-06 17:01:31 +01:00
|
|
|
char *keygrip = NULL;
|
2009-05-17 15:08:18 +02:00
|
|
|
char *answer;
|
|
|
|
int algo;
|
|
|
|
int dummy_algo;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2009-05-17 15:08:18 +02:00
|
|
|
if (!r_subkey_algo)
|
|
|
|
r_subkey_algo = &dummy_algo;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2009-05-17 15:08:18 +02:00
|
|
|
tty_printf (_("Please select what kind of key you want:\n"));
|
|
|
|
|
2014-02-07 13:45:11 +01:00
|
|
|
#if GPG_USE_RSA
|
2009-05-17 15:08:18 +02:00
|
|
|
if (!addmode)
|
|
|
|
tty_printf (_(" (%d) RSA and RSA (default)\n"), 1 );
|
2014-02-07 13:45:11 +01:00
|
|
|
#endif
|
|
|
|
|
2009-05-17 15:08:18 +02:00
|
|
|
if (!addmode)
|
|
|
|
tty_printf (_(" (%d) DSA and Elgamal\n"), 2 );
|
|
|
|
|
|
|
|
tty_printf (_(" (%d) DSA (sign only)\n"), 3 );
|
2014-02-07 13:45:11 +01:00
|
|
|
#if GPG_USE_RSA
|
2009-05-17 15:08:18 +02:00
|
|
|
tty_printf (_(" (%d) RSA (sign only)\n"), 4 );
|
2014-02-07 13:45:11 +01:00
|
|
|
#endif
|
2009-05-17 15:08:18 +02:00
|
|
|
|
|
|
|
if (addmode)
|
|
|
|
{
|
|
|
|
tty_printf (_(" (%d) Elgamal (encrypt only)\n"), 5 );
|
2014-02-07 13:45:11 +01:00
|
|
|
#if GPG_USE_RSA
|
2009-05-17 15:08:18 +02:00
|
|
|
tty_printf (_(" (%d) RSA (encrypt only)\n"), 6 );
|
2014-02-07 13:45:11 +01:00
|
|
|
#endif
|
2009-05-17 15:08:18 +02:00
|
|
|
}
|
|
|
|
if (opt.expert)
|
|
|
|
{
|
|
|
|
tty_printf (_(" (%d) DSA (set your own capabilities)\n"), 7 );
|
2014-02-07 13:45:11 +01:00
|
|
|
#if GPG_USE_RSA
|
2009-05-17 15:08:18 +02:00
|
|
|
tty_printf (_(" (%d) RSA (set your own capabilities)\n"), 8 );
|
2014-02-07 13:45:11 +01:00
|
|
|
#endif
|
2009-05-17 15:08:18 +02:00
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2014-02-07 13:45:11 +01:00
|
|
|
#if GPG_USE_ECDSA || GPG_USE_ECDH || GPG_USE_EDDSA
|
2011-02-03 17:40:43 +01:00
|
|
|
if (opt.expert && !addmode)
|
2014-09-18 16:00:34 +02:00
|
|
|
tty_printf (_(" (%d) ECC and ECC\n"), 9 );
|
2011-02-03 17:40:43 +01:00
|
|
|
if (opt.expert)
|
gpg: Use only OpenPGP public key algo ids and add the EdDSA algo id.
* common/sexputil.c (get_pk_algo_from_canon_sexp): Change to return a
string.
* g10/keygen.c (check_keygrip): Adjust for change.
* sm/certreqgen-ui.c (check_keygrip): Likewise.
* agent/pksign.c (do_encode_dsa): Remove bogus map_pk_openpgp_to_gcry.
* g10/misc.c (map_pk_openpgp_to_gcry): Remove.
(openpgp_pk_test_algo): Change to a wrapper for openpgp_pk_test_algo2.
(openpgp_pk_test_algo2): Rewrite.
(openpgp_pk_algo_usage, pubkey_nbits): Add support for EdDSA.
(openpgp_pk_algo_name): Rewrite to remove need for gcry calls.
(pubkey_get_npkey, pubkey_get_nskey): Ditto.
(pubkey_get_nsig, pubkey_get_nenc): Ditto.
* g10/keygen.c(do_create_from_keygrip): Support EdDSA.
(common_gen, gen_ecc, ask_keysize, generate_keypair): Ditto.
* g10/build-packet.c (do_key): Ditto.
* g10/export.c (transfer_format_to_openpgp): Ditto.
* g10/getkey.c (cache_public_key): Ditto.
* g10/import.c (transfer_secret_keys): Ditto.
* g10/keylist.c (list_keyblock_print, list_keyblock_colon): Ditto.
* g10/mainproc.c (proc_pubkey_enc): Ditto.
* g10/parse-packet.c (parse_key): Ditto,
* g10/sign.c (hash_for, sign_file, make_keysig_packet): Ditto.
* g10/keyserver.c (print_keyrec): Use openpgp_pk_algo_name.
* g10/pkglue.c (pk_verify, pk_encrypt, pk_check_secret_key): Use only
OpenPGP algo ids and support EdDSA.
* g10/pubkey-enc.c (get_it): Use only OpenPGP algo ids.
* g10/seskey.c (encode_md_value): Ditto.
--
This patch separates Libgcrypt and OpenPGP public key algorithms ids
and in most cases completely removes the Libgcrypt ones. This is
useful because for Libgcrypt we specify the algorithm in the
S-expressions and the public key ids are not anymore needed.
This patch also adds some support for PUBKEY_ALGO_EDDSA which will
eventually be used instead of merging EdDSA with ECDSA. As of now an
experimental algorithm id is used but the plan is to write an I-D so
that we can get a new id from the IETF. Note that EdDSA (Ed25519)
does not yet work and that more changes are required.
The ECC support is still broken right now. Needs to be fixed.
Signed-off-by: Werner Koch <wk@gnupg.org>
2014-01-30 18:48:37 +01:00
|
|
|
tty_printf (_(" (%d) ECC (sign only)\n"), 10 );
|
2011-02-03 17:40:43 +01:00
|
|
|
if (opt.expert)
|
gpg: Use only OpenPGP public key algo ids and add the EdDSA algo id.
* common/sexputil.c (get_pk_algo_from_canon_sexp): Change to return a
string.
* g10/keygen.c (check_keygrip): Adjust for change.
* sm/certreqgen-ui.c (check_keygrip): Likewise.
* agent/pksign.c (do_encode_dsa): Remove bogus map_pk_openpgp_to_gcry.
* g10/misc.c (map_pk_openpgp_to_gcry): Remove.
(openpgp_pk_test_algo): Change to a wrapper for openpgp_pk_test_algo2.
(openpgp_pk_test_algo2): Rewrite.
(openpgp_pk_algo_usage, pubkey_nbits): Add support for EdDSA.
(openpgp_pk_algo_name): Rewrite to remove need for gcry calls.
(pubkey_get_npkey, pubkey_get_nskey): Ditto.
(pubkey_get_nsig, pubkey_get_nenc): Ditto.
* g10/keygen.c(do_create_from_keygrip): Support EdDSA.
(common_gen, gen_ecc, ask_keysize, generate_keypair): Ditto.
* g10/build-packet.c (do_key): Ditto.
* g10/export.c (transfer_format_to_openpgp): Ditto.
* g10/getkey.c (cache_public_key): Ditto.
* g10/import.c (transfer_secret_keys): Ditto.
* g10/keylist.c (list_keyblock_print, list_keyblock_colon): Ditto.
* g10/mainproc.c (proc_pubkey_enc): Ditto.
* g10/parse-packet.c (parse_key): Ditto,
* g10/sign.c (hash_for, sign_file, make_keysig_packet): Ditto.
* g10/keyserver.c (print_keyrec): Use openpgp_pk_algo_name.
* g10/pkglue.c (pk_verify, pk_encrypt, pk_check_secret_key): Use only
OpenPGP algo ids and support EdDSA.
* g10/pubkey-enc.c (get_it): Use only OpenPGP algo ids.
* g10/seskey.c (encode_md_value): Ditto.
--
This patch separates Libgcrypt and OpenPGP public key algorithms ids
and in most cases completely removes the Libgcrypt ones. This is
useful because for Libgcrypt we specify the algorithm in the
S-expressions and the public key ids are not anymore needed.
This patch also adds some support for PUBKEY_ALGO_EDDSA which will
eventually be used instead of merging EdDSA with ECDSA. As of now an
experimental algorithm id is used but the plan is to write an I-D so
that we can get a new id from the IETF. Note that EdDSA (Ed25519)
does not yet work and that more changes are required.
The ECC support is still broken right now. Needs to be fixed.
Signed-off-by: Werner Koch <wk@gnupg.org>
2014-01-30 18:48:37 +01:00
|
|
|
tty_printf (_(" (%d) ECC (set your own capabilities)\n"), 11 );
|
2011-02-03 17:40:43 +01:00
|
|
|
if (opt.expert && addmode)
|
gpg: Use only OpenPGP public key algo ids and add the EdDSA algo id.
* common/sexputil.c (get_pk_algo_from_canon_sexp): Change to return a
string.
* g10/keygen.c (check_keygrip): Adjust for change.
* sm/certreqgen-ui.c (check_keygrip): Likewise.
* agent/pksign.c (do_encode_dsa): Remove bogus map_pk_openpgp_to_gcry.
* g10/misc.c (map_pk_openpgp_to_gcry): Remove.
(openpgp_pk_test_algo): Change to a wrapper for openpgp_pk_test_algo2.
(openpgp_pk_test_algo2): Rewrite.
(openpgp_pk_algo_usage, pubkey_nbits): Add support for EdDSA.
(openpgp_pk_algo_name): Rewrite to remove need for gcry calls.
(pubkey_get_npkey, pubkey_get_nskey): Ditto.
(pubkey_get_nsig, pubkey_get_nenc): Ditto.
* g10/keygen.c(do_create_from_keygrip): Support EdDSA.
(common_gen, gen_ecc, ask_keysize, generate_keypair): Ditto.
* g10/build-packet.c (do_key): Ditto.
* g10/export.c (transfer_format_to_openpgp): Ditto.
* g10/getkey.c (cache_public_key): Ditto.
* g10/import.c (transfer_secret_keys): Ditto.
* g10/keylist.c (list_keyblock_print, list_keyblock_colon): Ditto.
* g10/mainproc.c (proc_pubkey_enc): Ditto.
* g10/parse-packet.c (parse_key): Ditto,
* g10/sign.c (hash_for, sign_file, make_keysig_packet): Ditto.
* g10/keyserver.c (print_keyrec): Use openpgp_pk_algo_name.
* g10/pkglue.c (pk_verify, pk_encrypt, pk_check_secret_key): Use only
OpenPGP algo ids and support EdDSA.
* g10/pubkey-enc.c (get_it): Use only OpenPGP algo ids.
* g10/seskey.c (encode_md_value): Ditto.
--
This patch separates Libgcrypt and OpenPGP public key algorithms ids
and in most cases completely removes the Libgcrypt ones. This is
useful because for Libgcrypt we specify the algorithm in the
S-expressions and the public key ids are not anymore needed.
This patch also adds some support for PUBKEY_ALGO_EDDSA which will
eventually be used instead of merging EdDSA with ECDSA. As of now an
experimental algorithm id is used but the plan is to write an I-D so
that we can get a new id from the IETF. Note that EdDSA (Ed25519)
does not yet work and that more changes are required.
The ECC support is still broken right now. Needs to be fixed.
Signed-off-by: Werner Koch <wk@gnupg.org>
2014-01-30 18:48:37 +01:00
|
|
|
tty_printf (_(" (%d) ECC (encrypt only)\n"), 12 );
|
2014-02-07 13:45:11 +01:00
|
|
|
#endif
|
2011-01-25 16:54:18 +01:00
|
|
|
|
2011-11-06 17:01:31 +01:00
|
|
|
if (opt.expert && r_keygrip)
|
|
|
|
tty_printf (_(" (%d) Existing key\n"), 13 );
|
|
|
|
|
2011-02-03 17:40:43 +01:00
|
|
|
for (;;)
|
2009-05-17 15:08:18 +02:00
|
|
|
{
|
|
|
|
*r_usage = 0;
|
|
|
|
*r_subkey_algo = 0;
|
|
|
|
answer = cpr_get ("keygen.algo", _("Your selection? "));
|
|
|
|
cpr_kill_prompt ();
|
|
|
|
algo = *answer? atoi (answer) : 1;
|
|
|
|
xfree(answer);
|
2011-11-06 17:01:31 +01:00
|
|
|
answer = NULL;
|
2009-05-17 15:08:18 +02:00
|
|
|
if (algo == 1 && !addmode)
|
|
|
|
{
|
|
|
|
algo = PUBKEY_ALGO_RSA;
|
|
|
|
*r_subkey_algo = PUBKEY_ALGO_RSA;
|
|
|
|
break;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2009-05-17 15:08:18 +02:00
|
|
|
else if (algo == 2 && !addmode)
|
|
|
|
{
|
|
|
|
algo = PUBKEY_ALGO_DSA;
|
|
|
|
*r_subkey_algo = PUBKEY_ALGO_ELGAMAL_E;
|
|
|
|
break;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2009-05-17 15:08:18 +02:00
|
|
|
else if (algo == 3)
|
|
|
|
{
|
|
|
|
algo = PUBKEY_ALGO_DSA;
|
|
|
|
*r_usage = PUBKEY_USAGE_SIG;
|
|
|
|
break;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2009-05-17 15:08:18 +02:00
|
|
|
else if (algo == 4)
|
|
|
|
{
|
|
|
|
algo = PUBKEY_ALGO_RSA;
|
|
|
|
*r_usage = PUBKEY_USAGE_SIG;
|
|
|
|
break;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2009-05-17 15:08:18 +02:00
|
|
|
else if (algo == 5 && addmode)
|
|
|
|
{
|
|
|
|
algo = PUBKEY_ALGO_ELGAMAL_E;
|
|
|
|
*r_usage = PUBKEY_USAGE_ENC;
|
|
|
|
break;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2009-05-17 15:08:18 +02:00
|
|
|
else if (algo == 6 && addmode)
|
|
|
|
{
|
|
|
|
algo = PUBKEY_ALGO_RSA;
|
|
|
|
*r_usage = PUBKEY_USAGE_ENC;
|
|
|
|
break;
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
2009-05-17 15:08:18 +02:00
|
|
|
else if (algo == 7 && opt.expert)
|
|
|
|
{
|
|
|
|
algo = PUBKEY_ALGO_DSA;
|
|
|
|
*r_usage = ask_key_flags (algo, addmode);
|
|
|
|
break;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2009-05-17 15:08:18 +02:00
|
|
|
else if (algo == 8 && opt.expert)
|
|
|
|
{
|
|
|
|
algo = PUBKEY_ALGO_RSA;
|
|
|
|
*r_usage = ask_key_flags (algo, addmode);
|
|
|
|
break;
|
|
|
|
}
|
2011-02-03 17:40:43 +01:00
|
|
|
else if (algo == 9 && opt.expert && !addmode)
|
2011-01-06 02:33:17 +01:00
|
|
|
{
|
|
|
|
algo = PUBKEY_ALGO_ECDSA;
|
|
|
|
*r_subkey_algo = PUBKEY_ALGO_ECDH;
|
|
|
|
break;
|
|
|
|
}
|
2011-02-03 17:40:43 +01:00
|
|
|
else if (algo == 10 && opt.expert)
|
|
|
|
{
|
|
|
|
algo = PUBKEY_ALGO_ECDSA;
|
|
|
|
*r_usage = PUBKEY_USAGE_SIG;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (algo == 11 && opt.expert)
|
|
|
|
{
|
|
|
|
algo = PUBKEY_ALGO_ECDSA;
|
|
|
|
*r_usage = ask_key_flags (algo, addmode);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (algo == 12 && opt.expert && addmode)
|
|
|
|
{
|
|
|
|
algo = PUBKEY_ALGO_ECDH;
|
|
|
|
*r_usage = PUBKEY_USAGE_ENC;
|
|
|
|
break;
|
|
|
|
}
|
2011-11-06 17:01:31 +01:00
|
|
|
else if (algo == 13 && opt.expert && r_keygrip)
|
|
|
|
{
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
xfree (answer);
|
|
|
|
answer = tty_get (_("Enter the keygrip: "));
|
|
|
|
tty_kill_prompt ();
|
|
|
|
trim_spaces (answer);
|
|
|
|
if (!*answer)
|
|
|
|
{
|
|
|
|
xfree (answer);
|
|
|
|
answer = NULL;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strlen (answer) != 40 &&
|
|
|
|
!(answer[0] == '&' && strlen (answer+1) == 40))
|
|
|
|
tty_printf
|
|
|
|
(_("Not a valid keygrip (expecting 40 hex digits)\n"));
|
|
|
|
else if (!(algo = check_keygrip (ctrl, answer)) )
|
|
|
|
tty_printf (_("No key with this keygrip\n"));
|
|
|
|
else
|
|
|
|
break; /* Okay. */
|
|
|
|
}
|
|
|
|
xfree (keygrip);
|
|
|
|
keygrip = answer;
|
|
|
|
answer = NULL;
|
|
|
|
*r_usage = ask_key_flags (algo, addmode);
|
|
|
|
break;
|
|
|
|
}
|
2009-05-17 15:08:18 +02:00
|
|
|
else
|
|
|
|
tty_printf (_("Invalid selection.\n"));
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2011-11-06 17:01:31 +01:00
|
|
|
if (r_keygrip)
|
|
|
|
*r_keygrip = keygrip;
|
2009-05-17 15:08:18 +02:00
|
|
|
return algo;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-07-23 17:18:58 +02:00
|
|
|
/* Ask for the key size. ALGO is the algorithm. If PRIMARY_KEYSIZE
|
2009-05-17 15:08:18 +02:00
|
|
|
is not 0, the function asks for the size of the encryption
|
|
|
|
subkey. */
|
2003-06-05 09:14:21 +02:00
|
|
|
static unsigned
|
2009-05-17 15:08:18 +02:00
|
|
|
ask_keysize (int algo, unsigned int primary_keysize)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2009-12-04 20:47:54 +01:00
|
|
|
unsigned int nbits, min, def = DEFAULT_STD_KEYSIZE, max=4096;
|
2009-05-17 15:08:18 +02:00
|
|
|
int for_subkey = !!primary_keysize;
|
|
|
|
int autocomp = 0;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
if(opt.expert)
|
|
|
|
min=512;
|
|
|
|
else
|
|
|
|
min=1024;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2009-05-17 15:08:18 +02:00
|
|
|
if (primary_keysize && !opt.expert)
|
|
|
|
{
|
|
|
|
/* Deduce the subkey size from the primary key size. */
|
|
|
|
if (algo == PUBKEY_ALGO_DSA && primary_keysize > 3072)
|
|
|
|
nbits = 3072; /* For performance reasons we don't support more
|
|
|
|
than 3072 bit DSA. However we won't see this
|
|
|
|
case anyway because DSA can't be used as an
|
|
|
|
encryption subkey ;-). */
|
|
|
|
else
|
|
|
|
nbits = primary_keysize;
|
|
|
|
autocomp = 1;
|
|
|
|
goto leave;
|
|
|
|
}
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
switch(algo)
|
|
|
|
{
|
|
|
|
case PUBKEY_ALGO_DSA:
|
2009-05-20 11:57:10 +02:00
|
|
|
def=2048;
|
|
|
|
max=3072;
|
2006-04-19 13:26:11 +02:00
|
|
|
break;
|
|
|
|
|
2011-01-06 02:33:17 +01:00
|
|
|
case PUBKEY_ALGO_ECDSA:
|
|
|
|
case PUBKEY_ALGO_ECDH:
|
|
|
|
min=256;
|
|
|
|
def=256;
|
|
|
|
max=521;
|
|
|
|
break;
|
|
|
|
|
gpg: Use only OpenPGP public key algo ids and add the EdDSA algo id.
* common/sexputil.c (get_pk_algo_from_canon_sexp): Change to return a
string.
* g10/keygen.c (check_keygrip): Adjust for change.
* sm/certreqgen-ui.c (check_keygrip): Likewise.
* agent/pksign.c (do_encode_dsa): Remove bogus map_pk_openpgp_to_gcry.
* g10/misc.c (map_pk_openpgp_to_gcry): Remove.
(openpgp_pk_test_algo): Change to a wrapper for openpgp_pk_test_algo2.
(openpgp_pk_test_algo2): Rewrite.
(openpgp_pk_algo_usage, pubkey_nbits): Add support for EdDSA.
(openpgp_pk_algo_name): Rewrite to remove need for gcry calls.
(pubkey_get_npkey, pubkey_get_nskey): Ditto.
(pubkey_get_nsig, pubkey_get_nenc): Ditto.
* g10/keygen.c(do_create_from_keygrip): Support EdDSA.
(common_gen, gen_ecc, ask_keysize, generate_keypair): Ditto.
* g10/build-packet.c (do_key): Ditto.
* g10/export.c (transfer_format_to_openpgp): Ditto.
* g10/getkey.c (cache_public_key): Ditto.
* g10/import.c (transfer_secret_keys): Ditto.
* g10/keylist.c (list_keyblock_print, list_keyblock_colon): Ditto.
* g10/mainproc.c (proc_pubkey_enc): Ditto.
* g10/parse-packet.c (parse_key): Ditto,
* g10/sign.c (hash_for, sign_file, make_keysig_packet): Ditto.
* g10/keyserver.c (print_keyrec): Use openpgp_pk_algo_name.
* g10/pkglue.c (pk_verify, pk_encrypt, pk_check_secret_key): Use only
OpenPGP algo ids and support EdDSA.
* g10/pubkey-enc.c (get_it): Use only OpenPGP algo ids.
* g10/seskey.c (encode_md_value): Ditto.
--
This patch separates Libgcrypt and OpenPGP public key algorithms ids
and in most cases completely removes the Libgcrypt ones. This is
useful because for Libgcrypt we specify the algorithm in the
S-expressions and the public key ids are not anymore needed.
This patch also adds some support for PUBKEY_ALGO_EDDSA which will
eventually be used instead of merging EdDSA with ECDSA. As of now an
experimental algorithm id is used but the plan is to write an I-D so
that we can get a new id from the IETF. Note that EdDSA (Ed25519)
does not yet work and that more changes are required.
The ECC support is still broken right now. Needs to be fixed.
Signed-off-by: Werner Koch <wk@gnupg.org>
2014-01-30 18:48:37 +01:00
|
|
|
case PUBKEY_ALGO_EDDSA:
|
|
|
|
min=255;
|
|
|
|
def=255;
|
|
|
|
max=441;
|
|
|
|
break;
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
case PUBKEY_ALGO_RSA:
|
|
|
|
min=1024;
|
|
|
|
break;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
|
|
|
|
tty_printf(_("%s keys may be between %u and %u bits long.\n"),
|
2011-01-06 02:33:17 +01:00
|
|
|
openpgp_pk_algo_name (algo), min, max);
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2011-01-25 16:54:18 +01:00
|
|
|
for (;;)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2009-05-17 15:08:18 +02:00
|
|
|
char *prompt, *answer;
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2009-05-17 15:08:18 +02:00
|
|
|
if (for_subkey)
|
|
|
|
prompt = xasprintf (_("What keysize do you want "
|
|
|
|
"for the subkey? (%u) "), def);
|
|
|
|
else
|
|
|
|
prompt = xasprintf (_("What keysize do you want? (%u) "), def);
|
|
|
|
answer = cpr_get ("keygen.size", prompt);
|
|
|
|
cpr_kill_prompt ();
|
|
|
|
nbits = *answer? atoi (answer): def;
|
2006-04-19 13:26:11 +02:00
|
|
|
xfree(prompt);
|
|
|
|
xfree(answer);
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
if(nbits<min || nbits>max)
|
|
|
|
tty_printf(_("%s keysizes must be in the range %u-%u\n"),
|
2011-01-06 02:33:17 +01:00
|
|
|
openpgp_pk_algo_name (algo), min, max);
|
2006-04-19 13:26:11 +02:00
|
|
|
else
|
|
|
|
break;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2011-01-25 16:54:18 +01:00
|
|
|
tty_printf (_("Requested keysize is %u bits\n"), nbits);
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2009-05-17 15:08:18 +02:00
|
|
|
leave:
|
2011-01-25 16:54:18 +01:00
|
|
|
if (algo == PUBKEY_ALGO_DSA && (nbits % 64))
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2011-01-25 16:54:18 +01:00
|
|
|
nbits = ((nbits + 63) / 64) * 64;
|
|
|
|
if (!autocomp)
|
|
|
|
tty_printf (_("rounded up to %u bits\n"), nbits);
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
gpg: Use only OpenPGP public key algo ids and add the EdDSA algo id.
* common/sexputil.c (get_pk_algo_from_canon_sexp): Change to return a
string.
* g10/keygen.c (check_keygrip): Adjust for change.
* sm/certreqgen-ui.c (check_keygrip): Likewise.
* agent/pksign.c (do_encode_dsa): Remove bogus map_pk_openpgp_to_gcry.
* g10/misc.c (map_pk_openpgp_to_gcry): Remove.
(openpgp_pk_test_algo): Change to a wrapper for openpgp_pk_test_algo2.
(openpgp_pk_test_algo2): Rewrite.
(openpgp_pk_algo_usage, pubkey_nbits): Add support for EdDSA.
(openpgp_pk_algo_name): Rewrite to remove need for gcry calls.
(pubkey_get_npkey, pubkey_get_nskey): Ditto.
(pubkey_get_nsig, pubkey_get_nenc): Ditto.
* g10/keygen.c(do_create_from_keygrip): Support EdDSA.
(common_gen, gen_ecc, ask_keysize, generate_keypair): Ditto.
* g10/build-packet.c (do_key): Ditto.
* g10/export.c (transfer_format_to_openpgp): Ditto.
* g10/getkey.c (cache_public_key): Ditto.
* g10/import.c (transfer_secret_keys): Ditto.
* g10/keylist.c (list_keyblock_print, list_keyblock_colon): Ditto.
* g10/mainproc.c (proc_pubkey_enc): Ditto.
* g10/parse-packet.c (parse_key): Ditto,
* g10/sign.c (hash_for, sign_file, make_keysig_packet): Ditto.
* g10/keyserver.c (print_keyrec): Use openpgp_pk_algo_name.
* g10/pkglue.c (pk_verify, pk_encrypt, pk_check_secret_key): Use only
OpenPGP algo ids and support EdDSA.
* g10/pubkey-enc.c (get_it): Use only OpenPGP algo ids.
* g10/seskey.c (encode_md_value): Ditto.
--
This patch separates Libgcrypt and OpenPGP public key algorithms ids
and in most cases completely removes the Libgcrypt ones. This is
useful because for Libgcrypt we specify the algorithm in the
S-expressions and the public key ids are not anymore needed.
This patch also adds some support for PUBKEY_ALGO_EDDSA which will
eventually be used instead of merging EdDSA with ECDSA. As of now an
experimental algorithm id is used but the plan is to write an I-D so
that we can get a new id from the IETF. Note that EdDSA (Ed25519)
does not yet work and that more changes are required.
The ECC support is still broken right now. Needs to be fixed.
Signed-off-by: Werner Koch <wk@gnupg.org>
2014-01-30 18:48:37 +01:00
|
|
|
else if (algo == PUBKEY_ALGO_EDDSA)
|
|
|
|
{
|
|
|
|
if (nbits != 255 && nbits != 441)
|
|
|
|
{
|
|
|
|
if (nbits < 256)
|
|
|
|
nbits = 255;
|
|
|
|
else
|
|
|
|
nbits = 441;
|
|
|
|
if (!autocomp)
|
|
|
|
tty_printf (_("rounded to %u bits\n"), nbits);
|
|
|
|
}
|
|
|
|
}
|
2011-01-25 16:54:18 +01:00
|
|
|
else if (algo == PUBKEY_ALGO_ECDH || algo == PUBKEY_ALGO_ECDSA)
|
|
|
|
{
|
|
|
|
if (nbits != 256 && nbits != 384 && nbits != 521)
|
|
|
|
{
|
|
|
|
if (nbits < 256)
|
|
|
|
nbits = 256;
|
|
|
|
else if (nbits < 384)
|
|
|
|
nbits = 384;
|
|
|
|
else
|
|
|
|
nbits = 521;
|
|
|
|
if (!autocomp)
|
|
|
|
tty_printf (_("rounded to %u bits\n"), nbits);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((nbits % 32))
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
|
|
|
nbits = ((nbits + 31) / 32) * 32;
|
2009-05-17 15:08:18 +02:00
|
|
|
if (!autocomp)
|
2011-01-25 16:54:18 +01:00
|
|
|
tty_printf (_("rounded up to %u bits\n"), nbits );
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
|
|
|
|
return nbits;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-07 13:16:32 +02:00
|
|
|
/* Ask for the curve. ALGO is the selected algorithm which this
|
|
|
|
function may adjust. Returns a malloced string with the name of
|
2014-06-05 12:03:27 +02:00
|
|
|
the curve. BOTH tells that gpg creates a primary and subkey. */
|
2013-11-15 08:59:45 +01:00
|
|
|
static char *
|
2014-06-05 12:03:27 +02:00
|
|
|
ask_curve (int *algo, int both)
|
2013-11-15 08:59:45 +01:00
|
|
|
{
|
|
|
|
struct {
|
|
|
|
const char *name;
|
|
|
|
int available;
|
|
|
|
int expert_only;
|
2014-05-07 13:16:32 +02:00
|
|
|
int fix_curve;
|
2013-11-15 08:59:45 +01:00
|
|
|
const char *pretty_name;
|
|
|
|
} curves[] = {
|
2014-02-07 13:45:11 +01:00
|
|
|
#if GPG_USE_EDDSA
|
2014-05-07 13:16:32 +02:00
|
|
|
{ "Curve25519", 0, 0, 1, "Curve 25519" },
|
2014-02-07 13:45:11 +01:00
|
|
|
#endif
|
|
|
|
#if GPG_USE_ECDSA || GPG_USE_ECDH
|
2014-05-07 13:16:32 +02:00
|
|
|
{ "NIST P-256", 0, 1, 0, },
|
|
|
|
{ "NIST P-384", 0, 0, 0, },
|
|
|
|
{ "NIST P-521", 0, 1, 0, },
|
|
|
|
{ "brainpoolP256r1", 0, 1, 0, "Brainpool P-256" },
|
|
|
|
{ "brainpoolP384r1", 0, 1, 0, "Brainpool P-384" },
|
|
|
|
{ "brainpoolP512r1", 0, 1, 0, "Brainpool P-512" },
|
|
|
|
{ "secp256k1", 0, 1, 0 },
|
2014-02-07 13:45:11 +01:00
|
|
|
#endif
|
2013-11-15 08:59:45 +01:00
|
|
|
};
|
|
|
|
int idx;
|
|
|
|
char *answer;
|
|
|
|
char *result = NULL;
|
|
|
|
gcry_sexp_t keyparms;
|
|
|
|
|
|
|
|
tty_printf (_("Please select which elliptic curve you want:\n"));
|
|
|
|
|
2014-06-05 12:03:27 +02:00
|
|
|
again:
|
2013-11-15 08:59:45 +01:00
|
|
|
keyparms = NULL;
|
|
|
|
for (idx=0; idx < DIM(curves); idx++)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
curves[idx].available = 0;
|
|
|
|
if (!opt.expert && curves[idx].expert_only)
|
|
|
|
continue;
|
|
|
|
|
2014-05-07 13:16:32 +02:00
|
|
|
/* FIXME: The strcmp below is a temporary hack during
|
|
|
|
development. It shall be removed as soon as we have proper
|
|
|
|
Curve25519 support in Libgcrypt. */
|
2013-11-15 08:59:45 +01:00
|
|
|
gcry_sexp_release (keyparms);
|
|
|
|
rc = gcry_sexp_build (&keyparms, NULL,
|
2014-05-07 13:16:32 +02:00
|
|
|
"(public-key(ecc(curve %s)))",
|
|
|
|
(!strcmp (curves[idx].name, "Curve25519")
|
|
|
|
? "Ed25519" : curves[idx].name));
|
2013-11-15 08:59:45 +01:00
|
|
|
if (rc)
|
|
|
|
continue;
|
|
|
|
if (!gcry_pk_get_curve (keyparms, 0, NULL))
|
|
|
|
continue;
|
2014-06-05 12:03:27 +02:00
|
|
|
if (both && curves[idx].fix_curve)
|
|
|
|
{
|
|
|
|
/* Both Curve 25519 keys are to be created. Check that
|
|
|
|
Libgcrypt also supports the real Curve25519. */
|
|
|
|
gcry_sexp_release (keyparms);
|
|
|
|
rc = gcry_sexp_build (&keyparms, NULL,
|
|
|
|
"(public-key(ecc(curve %s)))",
|
|
|
|
curves[idx].name);
|
|
|
|
if (rc)
|
|
|
|
continue;
|
|
|
|
if (!gcry_pk_get_curve (keyparms, 0, NULL))
|
|
|
|
continue;
|
|
|
|
}
|
2013-11-15 08:59:45 +01:00
|
|
|
|
|
|
|
curves[idx].available = 1;
|
2013-11-18 14:09:47 +01:00
|
|
|
tty_printf (" (%d) %s\n", idx + 1,
|
2013-11-15 08:59:45 +01:00
|
|
|
curves[idx].pretty_name?
|
|
|
|
curves[idx].pretty_name:curves[idx].name);
|
|
|
|
}
|
|
|
|
gcry_sexp_release (keyparms);
|
|
|
|
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
answer = cpr_get ("keygen.curve", _("Your selection? "));
|
|
|
|
cpr_kill_prompt ();
|
|
|
|
idx = *answer? atoi (answer) : 1;
|
|
|
|
if (*answer && !idx)
|
|
|
|
{
|
|
|
|
/* See whether the user entered the name of the curve. */
|
|
|
|
for (idx=0; idx < DIM(curves); idx++)
|
|
|
|
{
|
|
|
|
if (!opt.expert && curves[idx].expert_only)
|
|
|
|
continue;
|
|
|
|
if (!stricmp (curves[idx].name, answer)
|
|
|
|
|| (curves[idx].pretty_name
|
|
|
|
&& !stricmp (curves[idx].pretty_name, answer)))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (idx == DIM(curves))
|
|
|
|
idx = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
idx--;
|
|
|
|
xfree(answer);
|
|
|
|
answer = NULL;
|
|
|
|
if (idx < 0 || idx >= DIM (curves) || !curves[idx].available)
|
|
|
|
tty_printf (_("Invalid selection.\n"));
|
|
|
|
else
|
|
|
|
{
|
2014-05-07 13:16:32 +02:00
|
|
|
if (curves[idx].fix_curve)
|
2014-06-05 12:03:27 +02:00
|
|
|
{
|
2014-09-12 11:31:49 +02:00
|
|
|
log_info ("WARNING: Curve25519 is not yet part of the"
|
|
|
|
" OpenPGP standard.\n");
|
2014-06-05 12:03:27 +02:00
|
|
|
|
|
|
|
if (!cpr_get_answer_is_yes("experimental_curve.override",
|
|
|
|
"Use this curve anyway? (y/N) ") )
|
|
|
|
goto again;
|
|
|
|
}
|
2014-05-07 13:16:32 +02:00
|
|
|
|
|
|
|
/* If the user selected a signing algorithm and Curve25519
|
|
|
|
we need to update the algo and and the curve name. */
|
|
|
|
if ((*algo == PUBKEY_ALGO_ECDSA || *algo == PUBKEY_ALGO_EDDSA)
|
|
|
|
&& curves[idx].fix_curve)
|
|
|
|
{
|
|
|
|
*algo = PUBKEY_ALGO_EDDSA;
|
|
|
|
result = xstrdup ("Ed25519");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
result = xstrdup (curves[idx].name);
|
2013-11-15 08:59:45 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!result)
|
|
|
|
result = xstrdup (curves[0].name);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
/****************
|
2006-04-19 13:26:11 +02:00
|
|
|
* Parse an expire string and return its value in seconds.
|
|
|
|
* Returns (u32)-1 on error.
|
|
|
|
* This isn't perfect since scan_isodatestr returns unix time, and
|
|
|
|
* OpenPGP actually allows a 32-bit time *plus* a 32-bit offset.
|
|
|
|
* Because of this, we only permit setting expirations up to 2106, but
|
|
|
|
* OpenPGP could theoretically allow up to 2242. I think we'll all
|
|
|
|
* just cope for the next few years until we get a 64-bit time_t or
|
|
|
|
* similar.
|
2003-06-05 09:14:21 +02:00
|
|
|
*/
|
2006-04-19 13:26:11 +02:00
|
|
|
u32
|
2003-06-05 09:14:21 +02:00
|
|
|
parse_expire_string( const char *string )
|
|
|
|
{
|
2008-08-11 10:08:08 +02:00
|
|
|
int mult;
|
|
|
|
u32 seconds;
|
|
|
|
u32 abs_date = 0;
|
|
|
|
u32 curtime = make_timestamp ();
|
2009-05-13 13:42:34 +02:00
|
|
|
time_t tt;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2008-08-11 10:08:08 +02:00
|
|
|
if (!*string)
|
|
|
|
seconds = 0;
|
|
|
|
else if (!strncmp (string, "seconds=", 8))
|
|
|
|
seconds = atoi (string+8);
|
2009-05-13 13:42:34 +02:00
|
|
|
else if ((abs_date = scan_isodatestr(string))
|
|
|
|
&& (abs_date+86400/2) > curtime)
|
|
|
|
seconds = (abs_date+86400/2) - curtime;
|
|
|
|
else if ((tt = isotime2epoch (string)) != (time_t)(-1))
|
|
|
|
seconds = (u32)tt - curtime;
|
2008-08-11 10:08:08 +02:00
|
|
|
else if ((mult = check_valid_days (string)))
|
|
|
|
seconds = atoi (string) * 86400L * mult;
|
|
|
|
else
|
|
|
|
seconds = (u32)(-1);
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2008-08-11 10:08:08 +02:00
|
|
|
return seconds;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
/* Parsean Creation-Date string which is either "1986-04-26" or
|
|
|
|
"19860426T042640". Returns 0 on error. */
|
|
|
|
static u32
|
|
|
|
parse_creation_string (const char *string)
|
|
|
|
{
|
|
|
|
u32 seconds;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
if (!*string)
|
|
|
|
seconds = 0;
|
|
|
|
else if ( !strncmp (string, "seconds=", 8) )
|
|
|
|
seconds = atoi (string+8);
|
|
|
|
else if ( !(seconds = scan_isodatestr (string)))
|
|
|
|
{
|
|
|
|
time_t tmp = isotime2epoch (string);
|
|
|
|
seconds = (tmp == (time_t)(-1))? 0 : tmp;
|
|
|
|
}
|
|
|
|
return seconds;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
/* object == 0 for a key, and 1 for a sig */
|
|
|
|
u32
|
2006-04-19 13:26:11 +02:00
|
|
|
ask_expire_interval(int object,const char *def_expire)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2006-04-19 13:26:11 +02:00
|
|
|
u32 interval;
|
2003-06-05 09:14:21 +02:00
|
|
|
char *answer;
|
|
|
|
|
|
|
|
switch(object)
|
|
|
|
{
|
|
|
|
case 0:
|
2006-04-19 13:26:11 +02:00
|
|
|
if(def_expire)
|
|
|
|
BUG();
|
2003-06-05 09:14:21 +02:00
|
|
|
tty_printf(_("Please specify how long the key should be valid.\n"
|
|
|
|
" 0 = key does not expire\n"
|
|
|
|
" <n> = key expires in n days\n"
|
|
|
|
" <n>w = key expires in n weeks\n"
|
|
|
|
" <n>m = key expires in n months\n"
|
|
|
|
" <n>y = key expires in n years\n"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
2006-04-19 13:26:11 +02:00
|
|
|
if(!def_expire)
|
|
|
|
BUG();
|
2003-06-05 09:14:21 +02:00
|
|
|
tty_printf(_("Please specify how long the signature should be valid.\n"
|
|
|
|
" 0 = signature does not expire\n"
|
|
|
|
" <n> = signature expires in n days\n"
|
|
|
|
" <n>w = signature expires in n weeks\n"
|
|
|
|
" <n>m = signature expires in n months\n"
|
|
|
|
" <n>y = signature expires in n years\n"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
BUG();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Note: The elgamal subkey for DSA has no expiration date because
|
|
|
|
* it must be signed with the DSA key and this one has the expiration
|
|
|
|
* date */
|
|
|
|
|
|
|
|
answer = NULL;
|
2006-04-19 13:26:11 +02:00
|
|
|
for(;;)
|
|
|
|
{
|
2014-05-14 08:49:37 +02:00
|
|
|
u32 curtime;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
xfree(answer);
|
2003-06-05 09:14:21 +02:00
|
|
|
if(object==0)
|
|
|
|
answer = cpr_get("keygen.valid",_("Key is valid for? (0) "));
|
|
|
|
else
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
|
|
|
char *prompt;
|
|
|
|
|
|
|
|
#define PROMPTSTRING _("Signature is valid for? (%s) ")
|
|
|
|
/* This will actually end up larger than necessary because
|
|
|
|
of the 2 bytes for '%s' */
|
|
|
|
prompt=xmalloc(strlen(PROMPTSTRING)+strlen(def_expire)+1);
|
|
|
|
sprintf(prompt,PROMPTSTRING,def_expire);
|
|
|
|
#undef PROMPTSTRING
|
|
|
|
|
|
|
|
answer = cpr_get("siggen.valid",prompt);
|
|
|
|
xfree(prompt);
|
|
|
|
|
|
|
|
if(*answer=='\0')
|
|
|
|
answer=xstrdup(def_expire);
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
cpr_kill_prompt();
|
|
|
|
trim_spaces(answer);
|
2014-05-14 08:49:37 +02:00
|
|
|
curtime = make_timestamp ();
|
2006-04-19 13:26:11 +02:00
|
|
|
interval = parse_expire_string( answer );
|
|
|
|
if( interval == (u32)-1 )
|
|
|
|
{
|
2003-06-05 09:14:21 +02:00
|
|
|
tty_printf(_("invalid value\n"));
|
|
|
|
continue;
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
if( !interval )
|
|
|
|
{
|
|
|
|
tty_printf((object==0)
|
|
|
|
? _("Key does not expire at all\n")
|
|
|
|
: _("Signature does not expire at all\n"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tty_printf(object==0
|
|
|
|
? _("Key expires at %s\n")
|
|
|
|
: _("Signature expires at %s\n"),
|
|
|
|
asctimestamp((ulong)(curtime + interval) ) );
|
2010-10-27 13:26:53 +02:00
|
|
|
#if SIZEOF_TIME_T <= 4 && !defined (HAVE_UNSIGNED_TIME_T)
|
2006-11-21 12:00:14 +01:00
|
|
|
if ( (time_t)((ulong)(curtime+interval)) < 0 )
|
|
|
|
tty_printf (_("Your system can't display dates beyond 2038.\n"
|
|
|
|
"However, it will be correctly handled up to"
|
|
|
|
" 2106.\n"));
|
2008-08-11 10:08:08 +02:00
|
|
|
else
|
2006-11-21 12:00:14 +01:00
|
|
|
#endif /*SIZEOF_TIME_T*/
|
2008-08-11 10:08:08 +02:00
|
|
|
if ( (time_t)((unsigned long)(curtime+interval)) < curtime )
|
|
|
|
{
|
|
|
|
tty_printf (_("invalid value\n"));
|
|
|
|
continue;
|
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
if( cpr_enabled() || cpr_get_answer_is_yes("keygen.valid.okay",
|
2006-04-19 13:26:11 +02:00
|
|
|
_("Is this correct? (y/N) ")) )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
xfree(answer);
|
2003-06-05 09:14:21 +02:00
|
|
|
return interval;
|
|
|
|
}
|
|
|
|
|
|
|
|
u32
|
|
|
|
ask_expiredate()
|
|
|
|
{
|
2006-04-19 13:26:11 +02:00
|
|
|
u32 x = ask_expire_interval(0,NULL);
|
2003-06-05 09:14:21 +02:00
|
|
|
return x? make_timestamp() + x : 0;
|
|
|
|
}
|
|
|
|
|
2003-06-18 21:56:13 +02:00
|
|
|
|
2009-09-03 22:51:55 +02:00
|
|
|
|
|
|
|
static PKT_user_id *
|
|
|
|
uid_from_string (const char *string)
|
|
|
|
{
|
|
|
|
size_t n;
|
|
|
|
PKT_user_id *uid;
|
|
|
|
|
|
|
|
n = strlen (string);
|
|
|
|
uid = xmalloc_clear (sizeof *uid + n);
|
|
|
|
uid->len = n;
|
|
|
|
strcpy (uid->name, string);
|
|
|
|
uid->ref = 1;
|
|
|
|
return uid;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Ask for a user ID. With a MODE of 1 an extra help prompt is
|
|
|
|
printed for use during a new key creation. If KEYBLOCK is not NULL
|
|
|
|
the function prevents the creation of an already existing user
|
2014-09-27 15:14:13 +02:00
|
|
|
ID. IF FULL is not set some prompts are not shown. */
|
2003-06-05 09:14:21 +02:00
|
|
|
static char *
|
2014-09-27 15:14:13 +02:00
|
|
|
ask_user_id (int mode, int full, KBNODE keyblock)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
|
|
|
char *answer;
|
|
|
|
char *aname, *acomment, *amail, *uid;
|
|
|
|
|
2008-06-01 21:44:05 +02:00
|
|
|
if ( !mode )
|
|
|
|
{
|
2009-01-08 16:48:51 +01:00
|
|
|
/* TRANSLATORS: This is the new string telling the user what
|
|
|
|
gpg is now going to do (i.e. ask for the parts of the user
|
2013-11-18 14:09:47 +01:00
|
|
|
ID). Note that if you do not translate this string, a
|
2014-09-27 15:14:13 +02:00
|
|
|
different string will be used, which might still have
|
2013-11-18 14:09:47 +01:00
|
|
|
a correct translation. */
|
2008-06-01 21:44:05 +02:00
|
|
|
const char *s1 =
|
|
|
|
N_("\n"
|
|
|
|
"GnuPG needs to construct a user ID to identify your key.\n"
|
|
|
|
"\n");
|
|
|
|
const char *s2 = _(s1);
|
|
|
|
|
|
|
|
if (!strcmp (s1, s2))
|
|
|
|
{
|
|
|
|
/* There is no translation for the string thus we to use
|
|
|
|
the old info text. gettext has no way to tell whether
|
|
|
|
a translation is actually available, thus we need to
|
|
|
|
to compare again. */
|
2009-01-08 16:48:51 +01:00
|
|
|
/* TRANSLATORS: This string is in general not anymore used
|
|
|
|
but you should keep your existing translation. In case
|
|
|
|
the new string is not translated this old string will
|
|
|
|
be used. */
|
2008-06-01 21:44:05 +02:00
|
|
|
const char *s3 = N_("\n"
|
2006-04-19 13:26:11 +02:00
|
|
|
"You need a user ID to identify your key; "
|
|
|
|
"the software constructs the user ID\n"
|
|
|
|
"from the Real Name, Comment and Email Address in this form:\n"
|
2008-06-01 21:44:05 +02:00
|
|
|
" \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n\n");
|
|
|
|
const char *s4 = _(s3);
|
|
|
|
if (strcmp (s3, s4))
|
|
|
|
s2 = s3; /* A translation exists - use it. */
|
|
|
|
}
|
|
|
|
tty_printf ("%s", s2) ;
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
uid = aname = acomment = amail = NULL;
|
|
|
|
for(;;) {
|
|
|
|
char *p;
|
|
|
|
int fail=0;
|
|
|
|
|
|
|
|
if( !aname ) {
|
|
|
|
for(;;) {
|
2006-04-19 13:26:11 +02:00
|
|
|
xfree(aname);
|
2003-06-05 09:14:21 +02:00
|
|
|
aname = cpr_get("keygen.name",_("Real name: "));
|
|
|
|
trim_spaces(aname);
|
|
|
|
cpr_kill_prompt();
|
|
|
|
|
|
|
|
if( opt.allow_freeform_uid )
|
|
|
|
break;
|
|
|
|
|
|
|
|
if( strpbrk( aname, "<>" ) )
|
|
|
|
tty_printf(_("Invalid character in name\n"));
|
2003-09-23 19:48:33 +02:00
|
|
|
else if( digitp(aname) )
|
2003-06-05 09:14:21 +02:00
|
|
|
tty_printf(_("Name may not start with a digit\n"));
|
|
|
|
else if( strlen(aname) < 5 )
|
|
|
|
tty_printf(_("Name must be at least 5 characters long\n"));
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( !amail ) {
|
|
|
|
for(;;) {
|
2006-04-19 13:26:11 +02:00
|
|
|
xfree(amail);
|
2003-06-05 09:14:21 +02:00
|
|
|
amail = cpr_get("keygen.email",_("Email address: "));
|
|
|
|
trim_spaces(amail);
|
|
|
|
cpr_kill_prompt();
|
2003-09-23 19:48:33 +02:00
|
|
|
if( !*amail || opt.allow_freeform_uid )
|
2003-06-05 09:14:21 +02:00
|
|
|
break; /* no email address is okay */
|
2006-04-19 13:26:11 +02:00
|
|
|
else if ( !is_valid_mailbox (amail) )
|
|
|
|
tty_printf(_("Not a valid email address\n"));
|
2003-06-05 09:14:21 +02:00
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2014-09-27 15:14:13 +02:00
|
|
|
if (!acomment) {
|
|
|
|
if (full) {
|
2003-06-05 09:14:21 +02:00
|
|
|
for(;;) {
|
2006-04-19 13:26:11 +02:00
|
|
|
xfree(acomment);
|
2003-06-05 09:14:21 +02:00
|
|
|
acomment = cpr_get("keygen.comment",_("Comment: "));
|
|
|
|
trim_spaces(acomment);
|
|
|
|
cpr_kill_prompt();
|
|
|
|
if( !*acomment )
|
|
|
|
break; /* no comment is okay */
|
|
|
|
else if( strpbrk( acomment, "()" ) )
|
|
|
|
tty_printf(_("Invalid character in comment\n"));
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
2014-09-27 15:14:13 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
xfree (acomment);
|
|
|
|
acomment = xstrdup ("");
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
xfree(uid);
|
|
|
|
uid = p = xmalloc(strlen(aname)+strlen(amail)+strlen(acomment)+12+10);
|
2003-06-05 09:14:21 +02:00
|
|
|
p = stpcpy(p, aname );
|
|
|
|
if( *acomment )
|
|
|
|
p = stpcpy(stpcpy(stpcpy(p," ("), acomment),")");
|
|
|
|
if( *amail )
|
|
|
|
p = stpcpy(stpcpy(stpcpy(p," <"), amail),">");
|
|
|
|
|
2006-08-21 22:20:23 +02:00
|
|
|
/* Append a warning if the RNG is switched into fake mode. */
|
|
|
|
if ( random_is_faked () )
|
|
|
|
strcpy(p, " (insecure!)" );
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
/* print a note in case that UTF8 mapping has to be done */
|
|
|
|
for(p=uid; *p; p++ ) {
|
|
|
|
if( *p & 0x80 ) {
|
2012-06-05 19:29:22 +02:00
|
|
|
tty_printf(_("You are using the '%s' character set.\n"),
|
2003-06-05 09:14:21 +02:00
|
|
|
get_native_charset() );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tty_printf(_("You selected this USER-ID:\n \"%s\"\n\n"), uid);
|
2009-09-03 22:51:55 +02:00
|
|
|
|
2003-09-23 19:48:33 +02:00
|
|
|
if( !*amail && !opt.allow_freeform_uid
|
2006-04-19 13:26:11 +02:00
|
|
|
&& (strchr( aname, '@' ) || strchr( acomment, '@'))) {
|
2003-06-05 09:14:21 +02:00
|
|
|
fail = 1;
|
2009-09-03 22:51:55 +02:00
|
|
|
tty_printf(_("Please don't put the email address "
|
|
|
|
"into the real name or the comment\n") );
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2009-09-03 22:51:55 +02:00
|
|
|
if (!fail && keyblock)
|
|
|
|
{
|
|
|
|
PKT_user_id *uidpkt = uid_from_string (uid);
|
|
|
|
KBNODE node;
|
|
|
|
|
|
|
|
for (node=keyblock; node && !fail; node=node->next)
|
|
|
|
if (!is_deleted_kbnode (node)
|
|
|
|
&& node->pkt->pkttype == PKT_USER_ID
|
|
|
|
&& !cmp_user_ids (uidpkt, node->pkt->pkt.user_id))
|
|
|
|
fail = 1;
|
|
|
|
if (fail)
|
|
|
|
tty_printf (_("Such a user ID already exists on this key!\n"));
|
|
|
|
free_user_id (uidpkt);
|
|
|
|
}
|
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
for(;;) {
|
2006-04-19 13:26:11 +02:00
|
|
|
/* TRANSLATORS: These are the allowed answers in
|
|
|
|
lower and uppercase. Below you will find the matching
|
|
|
|
string which should be translated accordingly and the
|
|
|
|
letter changed to match the one in the answer string.
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
n = Change name
|
|
|
|
c = Change comment
|
|
|
|
e = Change email
|
|
|
|
o = Okay (ready, continue)
|
|
|
|
q = Quit
|
|
|
|
*/
|
2003-06-05 09:14:21 +02:00
|
|
|
const char *ansstr = _("NnCcEeOoQq");
|
|
|
|
|
|
|
|
if( strlen(ansstr) != 10 )
|
|
|
|
BUG();
|
|
|
|
if( cpr_enabled() ) {
|
2010-02-17 11:23:42 +01:00
|
|
|
answer = xstrdup (ansstr + (fail?8:6));
|
2003-06-05 09:14:21 +02:00
|
|
|
answer[1] = 0;
|
|
|
|
}
|
2014-09-27 15:14:13 +02:00
|
|
|
else if (full) {
|
2003-06-05 09:14:21 +02:00
|
|
|
answer = cpr_get("keygen.userid.cmd", fail?
|
|
|
|
_("Change (N)ame, (C)omment, (E)mail or (Q)uit? ") :
|
|
|
|
_("Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? "));
|
|
|
|
cpr_kill_prompt();
|
2014-09-27 15:14:13 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
answer = cpr_get("keygen.userid.cmd", fail?
|
|
|
|
_("Change (N)ame, (E)mail, or (Q)uit? ") :
|
|
|
|
_("Change (N)ame, (E)mail, or (O)kay/(Q)uit? "));
|
|
|
|
cpr_kill_prompt();
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
if( strlen(answer) > 1 )
|
|
|
|
;
|
|
|
|
else if( *answer == ansstr[0] || *answer == ansstr[1] ) {
|
2006-04-19 13:26:11 +02:00
|
|
|
xfree(aname); aname = NULL;
|
2003-06-05 09:14:21 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if( *answer == ansstr[2] || *answer == ansstr[3] ) {
|
2006-04-19 13:26:11 +02:00
|
|
|
xfree(acomment); acomment = NULL;
|
2003-06-05 09:14:21 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if( *answer == ansstr[4] || *answer == ansstr[5] ) {
|
2006-04-19 13:26:11 +02:00
|
|
|
xfree(amail); amail = NULL;
|
2003-06-05 09:14:21 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if( *answer == ansstr[6] || *answer == ansstr[7] ) {
|
|
|
|
if( fail ) {
|
|
|
|
tty_printf(_("Please correct the error first\n"));
|
|
|
|
}
|
|
|
|
else {
|
2006-04-19 13:26:11 +02:00
|
|
|
xfree(aname); aname = NULL;
|
|
|
|
xfree(acomment); acomment = NULL;
|
|
|
|
xfree(amail); amail = NULL;
|
2003-06-05 09:14:21 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( *answer == ansstr[8] || *answer == ansstr[9] ) {
|
2006-04-19 13:26:11 +02:00
|
|
|
xfree(aname); aname = NULL;
|
|
|
|
xfree(acomment); acomment = NULL;
|
|
|
|
xfree(amail); amail = NULL;
|
|
|
|
xfree(uid); uid = NULL;
|
2003-06-05 09:14:21 +02:00
|
|
|
break;
|
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
xfree(answer);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
xfree(answer);
|
2003-06-05 09:14:21 +02:00
|
|
|
if( !amail && !acomment && !amail )
|
2006-04-19 13:26:11 +02:00
|
|
|
break;
|
|
|
|
xfree(uid); uid = NULL;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
if( uid ) {
|
|
|
|
char *p = native_to_utf8( uid );
|
2006-04-19 13:26:11 +02:00
|
|
|
xfree( uid );
|
2003-06-05 09:14:21 +02:00
|
|
|
uid = p;
|
|
|
|
}
|
|
|
|
return uid;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-05-15 21:26:46 +02:00
|
|
|
/* MODE 0 - standard
|
|
|
|
1 - Ask for passphrase of the card backup key. */
|
2014-11-02 15:43:52 +01:00
|
|
|
#if 0
|
2003-06-05 09:14:21 +02:00
|
|
|
static DEK *
|
2009-05-15 21:26:46 +02:00
|
|
|
do_ask_passphrase (STRING2KEY **ret_s2k, int mode, int *r_canceled)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
|
|
|
DEK *dek = NULL;
|
|
|
|
STRING2KEY *s2k;
|
|
|
|
const char *errtext = NULL;
|
2009-05-15 21:26:46 +02:00
|
|
|
const char *custdesc = NULL;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
tty_printf(_("You need a Passphrase to protect your secret key.\n\n") );
|
|
|
|
|
2009-05-15 21:26:46 +02:00
|
|
|
if (mode == 1)
|
|
|
|
custdesc = _("Please enter a passphrase to protect the off-card "
|
|
|
|
"backup of the new encryption key.");
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
s2k = xmalloc_secure( sizeof *s2k );
|
2003-06-05 09:14:21 +02:00
|
|
|
for(;;) {
|
|
|
|
s2k->mode = opt.s2k_mode;
|
2006-04-19 13:26:11 +02:00
|
|
|
s2k->hash_algo = S2K_DIGEST_ALGO;
|
2009-05-15 21:26:46 +02:00
|
|
|
dek = passphrase_to_dek_ext (NULL, 0, opt.s2k_cipher_algo, s2k, 2,
|
|
|
|
errtext, custdesc, NULL, r_canceled);
|
2006-12-06 11:16:50 +01:00
|
|
|
if (!dek && *r_canceled) {
|
|
|
|
xfree(dek); dek = NULL;
|
|
|
|
xfree(s2k); s2k = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if( !dek ) {
|
2003-06-05 09:14:21 +02:00
|
|
|
errtext = N_("passphrase not correctly repeated; try again");
|
|
|
|
tty_printf(_("%s.\n"), _(errtext));
|
|
|
|
}
|
|
|
|
else if( !dek->keylen ) {
|
2006-04-19 13:26:11 +02:00
|
|
|
xfree(dek); dek = NULL;
|
|
|
|
xfree(s2k); s2k = NULL;
|
2003-06-05 09:14:21 +02:00
|
|
|
tty_printf(_(
|
|
|
|
"You don't want a passphrase - this is probably a *bad* idea!\n"
|
|
|
|
"I will do it anyway. You can change your passphrase at any time,\n"
|
|
|
|
"using this program with the option \"--edit-key\".\n\n"));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break; /* okay */
|
|
|
|
}
|
|
|
|
*ret_s2k = s2k;
|
|
|
|
return dek;
|
|
|
|
}
|
2014-11-02 15:43:52 +01:00
|
|
|
#endif /* 0 */
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
/* Basic key generation. Here we divert to the actual generation
|
|
|
|
routines based on the requested algorithm. */
|
2003-06-05 09:14:21 +02:00
|
|
|
static int
|
2013-11-15 08:59:45 +01:00
|
|
|
do_create (int algo, unsigned int nbits, const char *curve, KBNODE pub_root,
|
2010-09-01 11:48:35 +02:00
|
|
|
u32 timestamp, u32 expiredate, int is_subkey,
|
2010-10-14 18:34:31 +02:00
|
|
|
int keygen_flags, char **cache_nonce_addr)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
gpg_error_t err;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
/* Fixme: The entropy collecting message should be moved to a
|
|
|
|
libgcrypt progress handler. */
|
|
|
|
if (!opt.batch)
|
|
|
|
tty_printf (_(
|
2003-06-05 09:14:21 +02:00
|
|
|
"We need to generate a lot of random bytes. It is a good idea to perform\n"
|
|
|
|
"some other action (type on the keyboard, move the mouse, utilize the\n"
|
|
|
|
"disks) during the prime generation; this gives the random number\n"
|
|
|
|
"generator a better chance to gain enough entropy.\n") );
|
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
if (algo == PUBKEY_ALGO_ELGAMAL_E)
|
2010-09-01 11:48:35 +02:00
|
|
|
err = gen_elg (algo, nbits, pub_root, timestamp, expiredate, is_subkey,
|
2010-10-14 18:34:31 +02:00
|
|
|
keygen_flags, cache_nonce_addr);
|
2010-04-20 19:57:50 +02:00
|
|
|
else if (algo == PUBKEY_ALGO_DSA)
|
2010-09-01 11:48:35 +02:00
|
|
|
err = gen_dsa (nbits, pub_root, timestamp, expiredate, is_subkey,
|
2010-10-14 18:34:31 +02:00
|
|
|
keygen_flags, cache_nonce_addr);
|
gpg: Use only OpenPGP public key algo ids and add the EdDSA algo id.
* common/sexputil.c (get_pk_algo_from_canon_sexp): Change to return a
string.
* g10/keygen.c (check_keygrip): Adjust for change.
* sm/certreqgen-ui.c (check_keygrip): Likewise.
* agent/pksign.c (do_encode_dsa): Remove bogus map_pk_openpgp_to_gcry.
* g10/misc.c (map_pk_openpgp_to_gcry): Remove.
(openpgp_pk_test_algo): Change to a wrapper for openpgp_pk_test_algo2.
(openpgp_pk_test_algo2): Rewrite.
(openpgp_pk_algo_usage, pubkey_nbits): Add support for EdDSA.
(openpgp_pk_algo_name): Rewrite to remove need for gcry calls.
(pubkey_get_npkey, pubkey_get_nskey): Ditto.
(pubkey_get_nsig, pubkey_get_nenc): Ditto.
* g10/keygen.c(do_create_from_keygrip): Support EdDSA.
(common_gen, gen_ecc, ask_keysize, generate_keypair): Ditto.
* g10/build-packet.c (do_key): Ditto.
* g10/export.c (transfer_format_to_openpgp): Ditto.
* g10/getkey.c (cache_public_key): Ditto.
* g10/import.c (transfer_secret_keys): Ditto.
* g10/keylist.c (list_keyblock_print, list_keyblock_colon): Ditto.
* g10/mainproc.c (proc_pubkey_enc): Ditto.
* g10/parse-packet.c (parse_key): Ditto,
* g10/sign.c (hash_for, sign_file, make_keysig_packet): Ditto.
* g10/keyserver.c (print_keyrec): Use openpgp_pk_algo_name.
* g10/pkglue.c (pk_verify, pk_encrypt, pk_check_secret_key): Use only
OpenPGP algo ids and support EdDSA.
* g10/pubkey-enc.c (get_it): Use only OpenPGP algo ids.
* g10/seskey.c (encode_md_value): Ditto.
--
This patch separates Libgcrypt and OpenPGP public key algorithms ids
and in most cases completely removes the Libgcrypt ones. This is
useful because for Libgcrypt we specify the algorithm in the
S-expressions and the public key ids are not anymore needed.
This patch also adds some support for PUBKEY_ALGO_EDDSA which will
eventually be used instead of merging EdDSA with ECDSA. As of now an
experimental algorithm id is used but the plan is to write an I-D so
that we can get a new id from the IETF. Note that EdDSA (Ed25519)
does not yet work and that more changes are required.
The ECC support is still broken right now. Needs to be fixed.
Signed-off-by: Werner Koch <wk@gnupg.org>
2014-01-30 18:48:37 +01:00
|
|
|
else if (algo == PUBKEY_ALGO_ECDSA
|
|
|
|
|| algo == PUBKEY_ALGO_EDDSA
|
|
|
|
|| algo == PUBKEY_ALGO_ECDH)
|
2013-11-15 08:59:45 +01:00
|
|
|
err = gen_ecc (algo, curve, pub_root, timestamp, expiredate, is_subkey,
|
2011-01-06 02:33:17 +01:00
|
|
|
keygen_flags, cache_nonce_addr);
|
2010-04-20 19:57:50 +02:00
|
|
|
else if (algo == PUBKEY_ALGO_RSA)
|
2010-09-01 11:48:35 +02:00
|
|
|
err = gen_rsa (algo, nbits, pub_root, timestamp, expiredate, is_subkey,
|
2010-10-14 18:34:31 +02:00
|
|
|
keygen_flags, cache_nonce_addr);
|
2006-04-19 13:26:11 +02:00
|
|
|
else
|
|
|
|
BUG();
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
return err;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-09-03 22:51:55 +02:00
|
|
|
/* Generate a new user id packet or return NULL if canceled. If
|
|
|
|
KEYBLOCK is not NULL the function prevents the creation of an
|
|
|
|
already existing user ID. */
|
2003-06-05 09:14:21 +02:00
|
|
|
PKT_user_id *
|
2009-09-03 22:51:55 +02:00
|
|
|
generate_user_id (KBNODE keyblock)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2009-09-03 22:51:55 +02:00
|
|
|
char *p;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2014-09-27 15:14:13 +02:00
|
|
|
p = ask_user_id (1, 1, keyblock);
|
2009-09-03 22:51:55 +02:00
|
|
|
if (!p)
|
|
|
|
return NULL; /* Canceled. */
|
|
|
|
return uid_from_string (p);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-02-21 20:35:10 +01:00
|
|
|
/* Append R to the linked list PARA. */
|
|
|
|
static void
|
|
|
|
append_to_parameter (struct para_data_s *para, struct para_data_s *r)
|
|
|
|
{
|
|
|
|
assert (para);
|
|
|
|
while (para->next)
|
|
|
|
para = para->next;
|
|
|
|
para->next = r;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Release the parameter list R. */
|
2003-06-05 09:14:21 +02:00
|
|
|
static void
|
2010-11-17 14:21:24 +01:00
|
|
|
release_parameter_list (struct para_data_s *r)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-11-17 14:21:24 +01:00
|
|
|
struct para_data_s *r2;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2010-11-17 14:21:24 +01:00
|
|
|
for (; r ; r = r2)
|
|
|
|
{
|
|
|
|
r2 = r->next;
|
|
|
|
xfree (r);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct para_data_s *
|
|
|
|
get_parameter( struct para_data_s *para, enum para_name key )
|
|
|
|
{
|
|
|
|
struct para_data_s *r;
|
|
|
|
|
|
|
|
for( r = para; r && r->key != key; r = r->next )
|
|
|
|
;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
get_parameter_value( struct para_data_s *para, enum para_name key )
|
|
|
|
{
|
|
|
|
struct para_data_s *r = get_parameter( para, key );
|
|
|
|
return (r && *r->u.value)? r->u.value : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2011-02-03 16:31:42 +01:00
|
|
|
get_parameter_algo( struct para_data_s *para, enum para_name key,
|
2009-12-04 20:47:54 +01:00
|
|
|
int *r_default)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2009-12-04 20:47:54 +01:00
|
|
|
int i;
|
|
|
|
struct para_data_s *r = get_parameter( para, key );
|
|
|
|
|
|
|
|
if (r_default)
|
|
|
|
*r_default = 0;
|
|
|
|
|
|
|
|
if (!r)
|
|
|
|
return -1;
|
|
|
|
|
2014-11-24 11:56:49 +01:00
|
|
|
/* Note that we need to handle the ECC algorithms specified as
|
|
|
|
strings directly because Libgcrypt folds them all to ECC. */
|
2009-12-04 20:47:54 +01:00
|
|
|
if (!ascii_strcasecmp (r->u.value, "default"))
|
|
|
|
{
|
|
|
|
/* Note: If you change this default algo, remember to change it
|
|
|
|
also in gpg.c:gpgconf_list. */
|
|
|
|
i = DEFAULT_STD_ALGO;
|
|
|
|
if (r_default)
|
|
|
|
*r_default = 1;
|
|
|
|
}
|
|
|
|
else if (digitp (r->u.value))
|
|
|
|
i = atoi( r->u.value );
|
|
|
|
else if (!strcmp (r->u.value, "ELG-E")
|
|
|
|
|| !strcmp (r->u.value, "ELG"))
|
2014-09-27 15:14:13 +02:00
|
|
|
i = PUBKEY_ALGO_ELGAMAL_E;
|
2014-11-24 11:56:49 +01:00
|
|
|
else if (!ascii_strcasecmp (r->u.value, "EdDSA"))
|
|
|
|
i = PUBKEY_ALGO_EDDSA;
|
|
|
|
else if (!ascii_strcasecmp (r->u.value, "ECDSA"))
|
|
|
|
i = PUBKEY_ALGO_ECDSA;
|
|
|
|
else if (!ascii_strcasecmp (r->u.value, "ECDH"))
|
|
|
|
i = PUBKEY_ALGO_ECDH;
|
2009-12-04 20:47:54 +01:00
|
|
|
else
|
2011-01-31 09:27:06 +01:00
|
|
|
i = map_pk_gcry_to_openpgp (gcry_pk_map_name (r->u.value));
|
2009-12-04 20:47:54 +01:00
|
|
|
|
|
|
|
if (i == PUBKEY_ALGO_RSA_E || i == PUBKEY_ALGO_RSA_S)
|
|
|
|
i = 0; /* we don't want to allow generation of these algorithms */
|
|
|
|
return i;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2011-02-03 16:31:42 +01:00
|
|
|
/*
|
2008-12-09 11:46:29 +01:00
|
|
|
* Parse the usage parameter and set the keyflags. Returns -1 on
|
|
|
|
* error, 0 for no usage given or 1 for usage available.
|
2003-06-05 09:14:21 +02:00
|
|
|
*/
|
|
|
|
static int
|
|
|
|
parse_parameter_usage (const char *fname,
|
|
|
|
struct para_data_s *para, enum para_name key)
|
|
|
|
{
|
|
|
|
struct para_data_s *r = get_parameter( para, key );
|
|
|
|
char *p, *pn;
|
|
|
|
unsigned int use;
|
|
|
|
|
|
|
|
if( !r )
|
|
|
|
return 0; /* none (this is an optional parameter)*/
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2003-06-05 09:14:21 +02:00
|
|
|
use = 0;
|
|
|
|
pn = r->u.value;
|
|
|
|
while ( (p = strsep (&pn, " \t,")) ) {
|
|
|
|
if ( !*p)
|
|
|
|
;
|
|
|
|
else if ( !ascii_strcasecmp (p, "sign") )
|
|
|
|
use |= PUBKEY_USAGE_SIG;
|
|
|
|
else if ( !ascii_strcasecmp (p, "encrypt") )
|
|
|
|
use |= PUBKEY_USAGE_ENC;
|
2003-09-05 09:40:18 +02:00
|
|
|
else if ( !ascii_strcasecmp (p, "auth") )
|
|
|
|
use |= PUBKEY_USAGE_AUTH;
|
2003-06-05 09:14:21 +02:00
|
|
|
else {
|
|
|
|
log_error("%s:%d: invalid usage list\n", fname, r->lnr );
|
|
|
|
return -1; /* error */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r->u.usage = use;
|
2006-04-19 13:26:11 +02:00
|
|
|
return 1;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
parse_revocation_key (const char *fname,
|
|
|
|
struct para_data_s *para, enum para_name key)
|
|
|
|
{
|
|
|
|
struct para_data_s *r = get_parameter( para, key );
|
|
|
|
struct revocation_key revkey;
|
|
|
|
char *pn;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if( !r )
|
|
|
|
return 0; /* none (this is an optional parameter) */
|
|
|
|
|
|
|
|
pn = r->u.value;
|
|
|
|
|
|
|
|
revkey.class=0x80;
|
|
|
|
revkey.algid=atoi(pn);
|
|
|
|
if(!revkey.algid)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
/* Skip to the fpr */
|
|
|
|
while(*pn && *pn!=':')
|
|
|
|
pn++;
|
|
|
|
|
|
|
|
if(*pn!=':')
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
pn++;
|
|
|
|
|
|
|
|
for(i=0;i<MAX_FINGERPRINT_LEN && *pn;i++,pn+=2)
|
|
|
|
{
|
|
|
|
int c=hextobyte(pn);
|
|
|
|
if(c==-1)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
revkey.fpr[i]=c;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* skip to the tag */
|
|
|
|
while(*pn && *pn!='s' && *pn!='S')
|
|
|
|
pn++;
|
|
|
|
|
|
|
|
if(ascii_strcasecmp(pn,"sensitive")==0)
|
|
|
|
revkey.class|=0x40;
|
|
|
|
|
|
|
|
memcpy(&r->u.revkey,&revkey,sizeof(struct revocation_key));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
log_error("%s:%d: invalid revocation key\n", fname, r->lnr );
|
|
|
|
return -1; /* error */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static u32
|
|
|
|
get_parameter_u32( struct para_data_s *para, enum para_name key )
|
|
|
|
{
|
2007-07-05 18:58:19 +02:00
|
|
|
struct para_data_s *r = get_parameter( para, key );
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
if( !r )
|
|
|
|
return 0;
|
|
|
|
if( r->key == pKEYCREATIONDATE )
|
|
|
|
return r->u.creation;
|
|
|
|
if( r->key == pKEYEXPIRE || r->key == pSUBKEYEXPIRE )
|
|
|
|
return r->u.expire;
|
|
|
|
if( r->key == pKEYUSAGE || r->key == pSUBKEYUSAGE )
|
|
|
|
return r->u.usage;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
return (unsigned int)strtoul( r->u.value, NULL, 10 );
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int
|
|
|
|
get_parameter_uint( struct para_data_s *para, enum para_name key )
|
|
|
|
{
|
|
|
|
return get_parameter_u32( para, key );
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct revocation_key *
|
|
|
|
get_parameter_revkey( struct para_data_s *para, enum para_name key )
|
|
|
|
{
|
|
|
|
struct para_data_s *r = get_parameter( para, key );
|
|
|
|
return r? &r->u.revkey : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
proc_parameter_file( struct para_data_s *para, const char *fname,
|
2003-06-27 22:53:09 +02:00
|
|
|
struct output_control_s *outctrl, int card )
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2006-04-19 13:26:11 +02:00
|
|
|
struct para_data_s *r;
|
|
|
|
const char *s1, *s2, *s3;
|
|
|
|
size_t n;
|
|
|
|
char *p;
|
2009-12-04 20:47:54 +01:00
|
|
|
int is_default = 0;
|
|
|
|
int have_user_id = 0;
|
|
|
|
int err, algo;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
/* Check that we have all required parameters. */
|
|
|
|
r = get_parameter( para, pKEYTYPE );
|
|
|
|
if(r)
|
|
|
|
{
|
2009-12-04 20:47:54 +01:00
|
|
|
algo = get_parameter_algo (para, pKEYTYPE, &is_default);
|
2006-04-28 16:31:29 +02:00
|
|
|
if (openpgp_pk_test_algo2 (algo, PUBKEY_USAGE_SIG))
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2008-12-09 11:46:29 +01:00
|
|
|
log_error ("%s:%d: invalid algorithm\n", fname, r->lnr );
|
2006-04-19 13:26:11 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-12-09 11:46:29 +01:00
|
|
|
log_error ("%s: no Key-Type specified\n",fname);
|
2006-04-19 13:26:11 +02:00
|
|
|
return -1;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2008-12-09 11:46:29 +01:00
|
|
|
err = parse_parameter_usage (fname, para, pKEYUSAGE);
|
|
|
|
if (!err)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2009-12-04 20:47:54 +01:00
|
|
|
/* Default to algo capabilities if key-usage is not provided and
|
|
|
|
no default algorithm has been requested. */
|
2008-12-09 11:46:29 +01:00
|
|
|
r = xmalloc_clear(sizeof(*r));
|
|
|
|
r->key = pKEYUSAGE;
|
2009-12-04 20:47:54 +01:00
|
|
|
r->u.usage = (is_default
|
|
|
|
? (PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG)
|
|
|
|
: openpgp_pk_algo_usage(algo));
|
2013-02-21 20:35:10 +01:00
|
|
|
append_to_parameter (para, r);
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
2008-12-09 11:46:29 +01:00
|
|
|
else if (err == -1)
|
2006-04-19 13:26:11 +02:00
|
|
|
return -1;
|
2008-12-09 11:46:29 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
r = get_parameter (para, pKEYUSAGE);
|
|
|
|
if (r && (r->u.usage & ~openpgp_pk_algo_usage (algo)))
|
|
|
|
{
|
|
|
|
log_error ("%s:%d: specified Key-Usage not allowed for algo %d\n",
|
|
|
|
fname, r->lnr, algo);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2009-12-04 20:47:54 +01:00
|
|
|
is_default = 0;
|
2006-04-19 13:26:11 +02:00
|
|
|
r = get_parameter( para, pSUBKEYTYPE );
|
|
|
|
if(r)
|
|
|
|
{
|
2009-12-04 20:47:54 +01:00
|
|
|
algo = get_parameter_algo (para, pSUBKEYTYPE, &is_default);
|
2006-04-19 15:24:36 +02:00
|
|
|
if (openpgp_pk_test_algo (algo))
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2008-12-09 11:46:29 +01:00
|
|
|
log_error ("%s:%d: invalid algorithm\n", fname, r->lnr );
|
2006-04-19 13:26:11 +02:00
|
|
|
return -1;
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2008-12-09 11:46:29 +01:00
|
|
|
err = parse_parameter_usage (fname, para, pSUBKEYUSAGE);
|
|
|
|
if (!err)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
|
|
|
/* Default to algo capabilities if subkey-usage is not
|
|
|
|
provided */
|
2008-12-09 11:46:29 +01:00
|
|
|
r = xmalloc_clear (sizeof(*r));
|
|
|
|
r->key = pSUBKEYUSAGE;
|
2009-12-04 20:47:54 +01:00
|
|
|
r->u.usage = (is_default
|
|
|
|
? PUBKEY_USAGE_ENC
|
|
|
|
: openpgp_pk_algo_usage (algo));
|
2013-02-21 20:35:10 +01:00
|
|
|
append_to_parameter (para, r);
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
2008-12-09 11:46:29 +01:00
|
|
|
else if (err == -1)
|
2003-06-05 09:14:21 +02:00
|
|
|
return -1;
|
2008-12-09 11:46:29 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
r = get_parameter (para, pSUBKEYUSAGE);
|
|
|
|
if (r && (r->u.usage & ~openpgp_pk_algo_usage (algo)))
|
|
|
|
{
|
|
|
|
log_error ("%s:%d: specified Subkey-Usage not allowed"
|
|
|
|
" for algo %d\n", fname, r->lnr, algo);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2008-12-09 11:46:29 +01:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
if( get_parameter_value( para, pUSERID ) )
|
|
|
|
have_user_id=1;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* create the formatted user ID */
|
|
|
|
s1 = get_parameter_value( para, pNAMEREAL );
|
|
|
|
s2 = get_parameter_value( para, pNAMECOMMENT );
|
|
|
|
s3 = get_parameter_value( para, pNAMEEMAIL );
|
|
|
|
if( s1 || s2 || s3 )
|
|
|
|
{
|
|
|
|
n = (s1?strlen(s1):0) + (s2?strlen(s2):0) + (s3?strlen(s3):0);
|
|
|
|
r = xmalloc_clear( sizeof *r + n + 20 );
|
|
|
|
r->key = pUSERID;
|
|
|
|
p = r->u.value;
|
|
|
|
if( s1 )
|
|
|
|
p = stpcpy(p, s1 );
|
|
|
|
if( s2 )
|
|
|
|
p = stpcpy(stpcpy(stpcpy(p," ("), s2 ),")");
|
|
|
|
if( s3 )
|
|
|
|
p = stpcpy(stpcpy(stpcpy(p," <"), s3 ),">");
|
2013-02-21 20:35:10 +01:00
|
|
|
append_to_parameter (para, r);
|
2006-04-19 13:26:11 +02:00
|
|
|
have_user_id=1;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
if(!have_user_id)
|
|
|
|
{
|
|
|
|
log_error("%s: no User-ID specified\n",fname);
|
2003-06-05 09:14:21 +02:00
|
|
|
return -1;
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
/* Set preferences, if any. */
|
|
|
|
keygen_set_std_prefs(get_parameter_value( para, pPREFERENCES ), 0);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2006-06-27 16:30:59 +02:00
|
|
|
/* Set keyserver, if any. */
|
|
|
|
s1=get_parameter_value( para, pKEYSERVER );
|
|
|
|
if(s1)
|
|
|
|
{
|
|
|
|
struct keyserver_spec *spec;
|
|
|
|
|
|
|
|
spec=parse_keyserver_uri(s1,1,NULL,0);
|
|
|
|
if(spec)
|
|
|
|
{
|
|
|
|
free_keyserver_spec(spec);
|
|
|
|
opt.def_keyserver_url=s1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
log_error("%s:%d: invalid keyserver url\n", fname, r->lnr );
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
/* Set revoker, if any. */
|
|
|
|
if (parse_revocation_key (fname, para, pREVOKER))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
/* Make KEYCREATIONDATE from Creation-Date. */
|
|
|
|
r = get_parameter (para, pCREATIONDATE);
|
|
|
|
if (r && *r->u.value)
|
|
|
|
{
|
|
|
|
u32 seconds;
|
|
|
|
|
|
|
|
seconds = parse_creation_string (r->u.value);
|
|
|
|
if (!seconds)
|
|
|
|
{
|
|
|
|
log_error ("%s:%d: invalid creation date\n", fname, r->lnr );
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
r->u.creation = seconds;
|
|
|
|
r->key = pKEYCREATIONDATE; /* Change that entry. */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Make KEYEXPIRE from Expire-Date. */
|
2006-04-19 13:26:11 +02:00
|
|
|
r = get_parameter( para, pEXPIREDATE );
|
|
|
|
if( r && *r->u.value )
|
|
|
|
{
|
|
|
|
u32 seconds;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
seconds = parse_expire_string( r->u.value );
|
|
|
|
if( seconds == (u32)-1 )
|
|
|
|
{
|
|
|
|
log_error("%s:%d: invalid expire date\n", fname, r->lnr );
|
|
|
|
return -1;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
r->u.expire = seconds;
|
|
|
|
r->key = pKEYEXPIRE; /* change hat entry */
|
|
|
|
/* also set it for the subkey */
|
|
|
|
r = xmalloc_clear( sizeof *r + 20 );
|
|
|
|
r->key = pSUBKEYEXPIRE;
|
|
|
|
r->u.expire = seconds;
|
2013-02-21 20:35:10 +01:00
|
|
|
append_to_parameter (para, r);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
do_generate_keypair( para, outctrl, card );
|
|
|
|
return 0;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************
|
|
|
|
* Kludge to allow non interactive key generation controlled
|
2006-04-19 13:26:11 +02:00
|
|
|
* by a parameter file.
|
2003-06-05 09:14:21 +02:00
|
|
|
* Note, that string parameters are expected to be in UTF-8
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
read_parameter_file( const char *fname )
|
|
|
|
{
|
|
|
|
static struct { const char *name;
|
|
|
|
enum para_name key;
|
|
|
|
} keywords[] = {
|
|
|
|
{ "Key-Type", pKEYTYPE},
|
|
|
|
{ "Key-Length", pKEYLENGTH },
|
2013-11-15 08:59:45 +01:00
|
|
|
{ "Key-Curve", pKEYCURVE },
|
2003-06-05 09:14:21 +02:00
|
|
|
{ "Key-Usage", pKEYUSAGE },
|
|
|
|
{ "Subkey-Type", pSUBKEYTYPE },
|
|
|
|
{ "Subkey-Length", pSUBKEYLENGTH },
|
2013-11-15 08:59:45 +01:00
|
|
|
{ "Subkey-Curve", pSUBKEYCURVE },
|
2003-06-05 09:14:21 +02:00
|
|
|
{ "Subkey-Usage", pSUBKEYUSAGE },
|
|
|
|
{ "Name-Real", pNAMEREAL },
|
|
|
|
{ "Name-Email", pNAMEEMAIL },
|
|
|
|
{ "Name-Comment", pNAMECOMMENT },
|
|
|
|
{ "Expire-Date", pEXPIREDATE },
|
2007-07-05 18:58:19 +02:00
|
|
|
{ "Creation-Date", pCREATIONDATE },
|
2003-06-05 09:14:21 +02:00
|
|
|
{ "Passphrase", pPASSPHRASE },
|
|
|
|
{ "Preferences", pPREFERENCES },
|
|
|
|
{ "Revoker", pREVOKER },
|
2006-04-19 13:26:11 +02:00
|
|
|
{ "Handle", pHANDLE },
|
2006-06-27 16:30:59 +02:00
|
|
|
{ "Keyserver", pKEYSERVER },
|
2003-06-05 09:14:21 +02:00
|
|
|
{ NULL, 0 }
|
|
|
|
};
|
2006-04-19 13:26:11 +02:00
|
|
|
IOBUF fp;
|
|
|
|
byte *line;
|
|
|
|
unsigned int maxlen, nline;
|
|
|
|
char *p;
|
2003-06-05 09:14:21 +02:00
|
|
|
int lnr;
|
|
|
|
const char *err = NULL;
|
|
|
|
struct para_data_s *para, *r;
|
|
|
|
int i;
|
|
|
|
struct output_control_s outctrl;
|
|
|
|
|
|
|
|
memset( &outctrl, 0, sizeof( outctrl ) );
|
2006-12-06 11:16:50 +01:00
|
|
|
outctrl.pub.afx = new_armor_context ();
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
if( !fname || !*fname)
|
|
|
|
fname = "-";
|
|
|
|
|
|
|
|
fp = iobuf_open (fname);
|
|
|
|
if (fp && is_secured_file (iobuf_get_fd (fp)))
|
|
|
|
{
|
|
|
|
iobuf_close (fp);
|
|
|
|
fp = NULL;
|
2010-04-01 15:24:55 +02:00
|
|
|
gpg_err_set_errno (EPERM);
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
|
|
|
if (!fp) {
|
2012-06-05 19:29:22 +02:00
|
|
|
log_error (_("can't open '%s': %s\n"), fname, strerror(errno) );
|
2006-04-19 13:26:11 +02:00
|
|
|
return;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2010-03-08 18:05:37 +01:00
|
|
|
iobuf_ioctl (fp, IOBUF_IOCTL_NO_CACHE, 1, NULL);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
lnr = 0;
|
|
|
|
err = NULL;
|
|
|
|
para = NULL;
|
2006-04-19 13:26:11 +02:00
|
|
|
maxlen = 1024;
|
|
|
|
line = NULL;
|
|
|
|
while ( iobuf_read_line (fp, &line, &nline, &maxlen) ) {
|
2003-06-05 09:14:21 +02:00
|
|
|
char *keyword, *value;
|
|
|
|
|
|
|
|
lnr++;
|
2006-04-19 13:26:11 +02:00
|
|
|
if( !maxlen ) {
|
2003-06-05 09:14:21 +02:00
|
|
|
err = "line too long";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
for( p = line; isspace(*(byte*)p); p++ )
|
|
|
|
;
|
|
|
|
if( !*p || *p == '#' )
|
|
|
|
continue;
|
|
|
|
keyword = p;
|
|
|
|
if( *keyword == '%' ) {
|
|
|
|
for( ; !isspace(*(byte*)p); p++ )
|
|
|
|
;
|
|
|
|
if( *p )
|
|
|
|
*p++ = 0;
|
|
|
|
for( ; isspace(*(byte*)p); p++ )
|
|
|
|
;
|
|
|
|
value = p;
|
|
|
|
trim_trailing_ws( value, strlen(value) );
|
|
|
|
if( !ascii_strcasecmp( keyword, "%echo" ) )
|
|
|
|
log_info("%s\n", value );
|
|
|
|
else if( !ascii_strcasecmp( keyword, "%dry-run" ) )
|
|
|
|
outctrl.dryrun = 1;
|
2008-06-16 17:48:33 +02:00
|
|
|
else if( !ascii_strcasecmp( keyword, "%ask-passphrase" ) )
|
2014-11-02 15:43:52 +01:00
|
|
|
; /* Dummy for backward compatibility. */
|
2008-06-16 17:48:33 +02:00
|
|
|
else if( !ascii_strcasecmp( keyword, "%no-ask-passphrase" ) )
|
2014-11-02 15:43:52 +01:00
|
|
|
; /* Dummy for backward compatibility. */
|
2010-10-14 18:34:31 +02:00
|
|
|
else if( !ascii_strcasecmp( keyword, "%no-protection" ) )
|
|
|
|
outctrl.keygen_flags |= KEYGEN_FLAG_NO_PROTECTION;
|
|
|
|
else if( !ascii_strcasecmp( keyword, "%transient-key" ) )
|
|
|
|
outctrl.keygen_flags |= KEYGEN_FLAG_TRANSIENT_KEY;
|
2003-06-05 09:14:21 +02:00
|
|
|
else if( !ascii_strcasecmp( keyword, "%commit" ) ) {
|
|
|
|
outctrl.lnr = lnr;
|
2006-04-19 13:26:11 +02:00
|
|
|
if (proc_parameter_file( para, fname, &outctrl, 0 ))
|
2011-02-03 16:31:42 +01:00
|
|
|
print_status_key_not_created
|
2006-04-19 13:26:11 +02:00
|
|
|
(get_parameter_value (para, pHANDLE));
|
2003-06-05 09:14:21 +02:00
|
|
|
release_parameter_list( para );
|
|
|
|
para = NULL;
|
|
|
|
}
|
|
|
|
else if( !ascii_strcasecmp( keyword, "%pubring" ) ) {
|
|
|
|
if( outctrl.pub.fname && !strcmp( outctrl.pub.fname, value ) )
|
|
|
|
; /* still the same file - ignore it */
|
|
|
|
else {
|
2006-04-19 13:26:11 +02:00
|
|
|
xfree( outctrl.pub.newfname );
|
|
|
|
outctrl.pub.newfname = xstrdup( value );
|
2003-06-05 09:14:21 +02:00
|
|
|
outctrl.use_files = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( !ascii_strcasecmp( keyword, "%secring" ) ) {
|
2010-11-17 14:21:24 +01:00
|
|
|
/* Ignore this command. */
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
else
|
2012-06-05 19:29:22 +02:00
|
|
|
log_info("skipping control '%s' (%s)\n", keyword, value );
|
2003-06-05 09:14:21 +02:00
|
|
|
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if( !(p = strchr( p, ':' )) || p == keyword ) {
|
|
|
|
err = "missing colon";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if( *p )
|
|
|
|
*p++ = 0;
|
|
|
|
for( ; isspace(*(byte*)p); p++ )
|
|
|
|
;
|
|
|
|
if( !*p ) {
|
|
|
|
err = "missing argument";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
value = p;
|
|
|
|
trim_trailing_ws( value, strlen(value) );
|
|
|
|
|
|
|
|
for(i=0; keywords[i].name; i++ ) {
|
|
|
|
if( !ascii_strcasecmp( keywords[i].name, keyword ) )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if( !keywords[i].name ) {
|
|
|
|
err = "unknown keyword";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if( keywords[i].key != pKEYTYPE && !para ) {
|
|
|
|
err = "parameter block does not start with \"Key-Type\"";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( keywords[i].key == pKEYTYPE && para ) {
|
|
|
|
outctrl.lnr = lnr;
|
2006-04-19 13:26:11 +02:00
|
|
|
if (proc_parameter_file( para, fname, &outctrl, 0 ))
|
|
|
|
print_status_key_not_created
|
|
|
|
(get_parameter_value (para, pHANDLE));
|
2003-06-05 09:14:21 +02:00
|
|
|
release_parameter_list( para );
|
|
|
|
para = NULL;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for( r = para; r; r = r->next ) {
|
|
|
|
if( r->key == keywords[i].key )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if( r ) {
|
|
|
|
err = "duplicate keyword";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
r = xmalloc_clear( sizeof *r + strlen( value ) );
|
2003-06-05 09:14:21 +02:00
|
|
|
r->lnr = lnr;
|
|
|
|
r->key = keywords[i].key;
|
|
|
|
strcpy( r->u.value, value );
|
|
|
|
r->next = para;
|
|
|
|
para = r;
|
|
|
|
}
|
|
|
|
if( err )
|
|
|
|
log_error("%s:%d: %s\n", fname, lnr, err );
|
2006-04-19 13:26:11 +02:00
|
|
|
else if( iobuf_error (fp) ) {
|
|
|
|
log_error("%s:%d: read error\n", fname, lnr);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
else if( para ) {
|
|
|
|
outctrl.lnr = lnr;
|
2006-04-19 13:26:11 +02:00
|
|
|
if (proc_parameter_file( para, fname, &outctrl, 0 ))
|
|
|
|
print_status_key_not_created (get_parameter_value (para, pHANDLE));
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if( outctrl.use_files ) { /* close open streams */
|
|
|
|
iobuf_close( outctrl.pub.stream );
|
2006-04-19 13:26:11 +02:00
|
|
|
|
|
|
|
/* Must invalidate that ugly cache to actually close it. */
|
|
|
|
if (outctrl.pub.fname)
|
2011-02-03 16:31:42 +01:00
|
|
|
iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE,
|
2010-03-08 18:05:37 +01:00
|
|
|
0, (char*)outctrl.pub.fname);
|
2006-04-19 13:26:11 +02:00
|
|
|
|
|
|
|
xfree( outctrl.pub.fname );
|
|
|
|
xfree( outctrl.pub.newfname );
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
release_parameter_list( para );
|
2006-04-19 13:26:11 +02:00
|
|
|
iobuf_close (fp);
|
2006-12-06 11:16:50 +01:00
|
|
|
release_armor_context (outctrl.pub.afx);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-23 15:12:43 +02:00
|
|
|
/* Helper for quick_generate_keypair. */
|
|
|
|
static struct para_data_s *
|
|
|
|
quickgen_set_para (struct para_data_s *para, int for_subkey,
|
|
|
|
int algo, int nbits, const char *curve)
|
|
|
|
{
|
|
|
|
struct para_data_s *r;
|
|
|
|
|
|
|
|
r = xmalloc_clear (sizeof *r + 20);
|
|
|
|
r->key = for_subkey? pSUBKEYUSAGE : pKEYUSAGE;
|
|
|
|
strcpy (r->u.value, for_subkey ? "encrypt" : "sign");
|
|
|
|
r->next = para;
|
|
|
|
para = r;
|
|
|
|
r = xmalloc_clear (sizeof *r + 20);
|
|
|
|
r->key = for_subkey? pSUBKEYTYPE : pKEYTYPE;
|
|
|
|
sprintf (r->u.value, "%d", algo);
|
|
|
|
r->next = para;
|
|
|
|
para = r;
|
|
|
|
|
|
|
|
if (curve)
|
|
|
|
{
|
|
|
|
r = xmalloc_clear (sizeof *r + strlen (curve));
|
|
|
|
r->key = for_subkey? pSUBKEYCURVE : pKEYCURVE;
|
|
|
|
strcpy (r->u.value, curve);
|
|
|
|
r->next = para;
|
|
|
|
para = r;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
r = xmalloc_clear (sizeof *r + 20);
|
|
|
|
r->key = for_subkey? pSUBKEYLENGTH : pKEYLENGTH;
|
|
|
|
sprintf (r->u.value, "%u", nbits);
|
|
|
|
r->next = para;
|
|
|
|
para = r;
|
|
|
|
}
|
|
|
|
|
|
|
|
return para;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2014-07-24 16:16:53 +02:00
|
|
|
* Unattended generation of a standard key.
|
2014-07-23 15:12:43 +02:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
quick_generate_keypair (const char *uid)
|
|
|
|
{
|
|
|
|
gpg_error_t err;
|
|
|
|
struct para_data_s *para = NULL;
|
|
|
|
struct para_data_s *r;
|
|
|
|
struct output_control_s outctrl;
|
|
|
|
int use_tty;
|
|
|
|
|
|
|
|
memset (&outctrl, 0, sizeof outctrl);
|
|
|
|
|
|
|
|
use_tty = (!opt.batch && !opt.answer_yes
|
|
|
|
&& !cpr_enabled ()
|
|
|
|
&& gnupg_isatty (fileno (stdin))
|
|
|
|
&& gnupg_isatty (fileno (stdout))
|
|
|
|
&& gnupg_isatty (fileno (stderr)));
|
|
|
|
|
|
|
|
r = xmalloc_clear (sizeof *r + strlen (uid));
|
|
|
|
r->key = pUSERID;
|
|
|
|
strcpy (r->u.value, uid);
|
|
|
|
r->next = para;
|
|
|
|
para = r;
|
|
|
|
|
|
|
|
uid = trim_spaces (r->u.value);
|
|
|
|
if (!*uid || (!opt.allow_freeform_uid && !is_valid_user_id (uid)))
|
|
|
|
{
|
|
|
|
log_error (_("Key generation failed: %s\n"),
|
|
|
|
gpg_strerror (GPG_ERR_INV_USER_ID));
|
|
|
|
goto leave;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If gpg is directly used on the console ask whether a key with the
|
|
|
|
given user id shall really be created. */
|
|
|
|
if (use_tty)
|
|
|
|
{
|
|
|
|
tty_printf (_("About to create a key for:\n \"%s\"\n\n"), uid);
|
|
|
|
if (!cpr_get_answer_is_yes_def ("quick_keygen.okay",
|
|
|
|
_("Continue? (Y/n) "), 1))
|
|
|
|
goto leave;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check whether such a user ID already exists. */
|
|
|
|
{
|
|
|
|
KEYDB_HANDLE kdbhd;
|
|
|
|
KEYDB_SEARCH_DESC desc;
|
|
|
|
|
|
|
|
memset (&desc, 0, sizeof desc);
|
|
|
|
desc.mode = KEYDB_SEARCH_MODE_EXACT;
|
|
|
|
desc.u.name = uid;
|
|
|
|
|
|
|
|
kdbhd = keydb_new ();
|
|
|
|
err = keydb_search (kdbhd, &desc, 1, NULL);
|
|
|
|
keydb_release (kdbhd);
|
|
|
|
if (gpg_err_code (err) != GPG_ERR_NOT_FOUND)
|
|
|
|
{
|
|
|
|
log_info (_("A key for \"%s\" already exists\n"), uid);
|
|
|
|
if (opt.answer_yes)
|
|
|
|
;
|
|
|
|
else if (!use_tty
|
|
|
|
|| !cpr_get_answer_is_yes_def ("quick_keygen.force",
|
|
|
|
_("Create anyway? (y/N) "), 0))
|
|
|
|
{
|
|
|
|
log_inc_errorcount (); /* we used log_info */
|
|
|
|
goto leave;
|
|
|
|
}
|
|
|
|
log_info (_("creating anyway\n"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-27 15:14:13 +02:00
|
|
|
para = quickgen_set_para (para, 0,
|
|
|
|
DEFAULT_STD_ALGO, DEFAULT_STD_KEYSIZE,
|
|
|
|
DEFAULT_STD_CURVE);
|
|
|
|
para = quickgen_set_para (para, 1,
|
|
|
|
DEFAULT_STD_SUBALGO, DEFAULT_STD_SUBKEYSIZE,
|
|
|
|
DEFAULT_STD_SUBCURVE);
|
2014-07-23 15:12:43 +02:00
|
|
|
|
|
|
|
proc_parameter_file (para, "[internal]", &outctrl, 0);
|
|
|
|
leave:
|
|
|
|
release_parameter_list (para);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
/*
|
2003-10-08 12:46:58 +02:00
|
|
|
* Generate a keypair (fname is only used in batch mode) If
|
2006-05-23 18:19:43 +02:00
|
|
|
* CARD_SERIALNO is not NULL the function will create the keys on an
|
2010-11-17 14:21:24 +01:00
|
|
|
* OpenPGP Card. If CARD_BACKUP_KEY has been set and CARD_SERIALNO is
|
|
|
|
* NOT NULL, the encryption key for the card is generated on the host,
|
2014-09-27 15:14:13 +02:00
|
|
|
* imported to the card and a backup file created by gpg-agent. If
|
|
|
|
* FULL is not set only the basic prompts are used (except for batch
|
|
|
|
* mode).
|
2003-06-05 09:14:21 +02:00
|
|
|
*/
|
|
|
|
void
|
2014-09-27 15:14:13 +02:00
|
|
|
generate_keypair (ctrl_t ctrl, int full, const char *fname,
|
|
|
|
const char *card_serialno, int card_backup_key)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2003-06-27 22:53:09 +02:00
|
|
|
unsigned int nbits;
|
|
|
|
char *uid = NULL;
|
|
|
|
int algo;
|
|
|
|
unsigned int use;
|
|
|
|
int both = 0;
|
|
|
|
u32 expire;
|
|
|
|
struct para_data_s *para = NULL;
|
|
|
|
struct para_data_s *r;
|
|
|
|
struct output_control_s outctrl;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2014-02-10 23:12:28 +01:00
|
|
|
#ifndef ENABLE_CARD_SUPPORT
|
|
|
|
(void)card_backup_key;
|
|
|
|
#endif
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
memset( &outctrl, 0, sizeof( outctrl ) );
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2003-10-08 12:46:58 +02:00
|
|
|
if (opt.batch && card_serialno)
|
2003-06-27 22:53:09 +02:00
|
|
|
{
|
2003-10-08 12:46:58 +02:00
|
|
|
/* We don't yet support unattended key generation. */
|
2006-04-19 13:26:11 +02:00
|
|
|
log_error (_("can't do this in batch mode\n"));
|
2003-06-27 22:53:09 +02:00
|
|
|
return;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2003-10-08 12:46:58 +02:00
|
|
|
if (opt.batch)
|
2003-06-27 22:53:09 +02:00
|
|
|
{
|
2003-10-08 12:46:58 +02:00
|
|
|
read_parameter_file( fname );
|
|
|
|
return;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2003-10-08 12:46:58 +02:00
|
|
|
if (card_serialno)
|
2003-07-01 10:34:45 +02:00
|
|
|
{
|
2006-04-19 13:26:11 +02:00
|
|
|
#ifdef ENABLE_CARD_SUPPORT
|
2003-10-08 12:46:58 +02:00
|
|
|
r = xcalloc (1, sizeof *r + strlen (card_serialno) );
|
2003-07-01 10:34:45 +02:00
|
|
|
r->key = pSERIALNO;
|
2003-10-08 12:46:58 +02:00
|
|
|
strcpy( r->u.value, card_serialno);
|
2003-07-01 10:34:45 +02:00
|
|
|
r->next = para;
|
|
|
|
para = r;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2003-06-27 22:53:09 +02:00
|
|
|
algo = PUBKEY_ALGO_RSA;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2003-06-27 22:53:09 +02:00
|
|
|
r = xcalloc (1, sizeof *r + 20 );
|
|
|
|
r->key = pKEYTYPE;
|
2003-07-03 20:08:16 +02:00
|
|
|
sprintf( r->u.value, "%d", algo );
|
2003-06-27 22:53:09 +02:00
|
|
|
r->next = para;
|
|
|
|
para = r;
|
|
|
|
r = xcalloc (1, sizeof *r + 20 );
|
2003-07-03 20:08:16 +02:00
|
|
|
r->key = pKEYUSAGE;
|
|
|
|
strcpy (r->u.value, "sign");
|
2003-06-27 22:53:09 +02:00
|
|
|
r->next = para;
|
|
|
|
para = r;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2003-06-27 22:53:09 +02:00
|
|
|
r = xcalloc (1, sizeof *r + 20 );
|
|
|
|
r->key = pSUBKEYTYPE;
|
|
|
|
sprintf( r->u.value, "%d", algo );
|
|
|
|
r->next = para;
|
|
|
|
para = r;
|
|
|
|
r = xcalloc (1, sizeof *r + 20 );
|
2003-07-03 20:08:16 +02:00
|
|
|
r->key = pSUBKEYUSAGE;
|
|
|
|
strcpy (r->u.value, "encrypt");
|
2003-06-27 22:53:09 +02:00
|
|
|
r->next = para;
|
|
|
|
para = r;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2003-07-23 09:11:06 +02:00
|
|
|
r = xcalloc (1, sizeof *r + 20 );
|
|
|
|
r->key = pAUTHKEYTYPE;
|
|
|
|
sprintf( r->u.value, "%d", algo );
|
|
|
|
r->next = para;
|
|
|
|
para = r;
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2010-11-17 14:21:24 +01:00
|
|
|
if (card_backup_key)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2010-11-17 14:21:24 +01:00
|
|
|
r = xcalloc (1, sizeof *r + 1);
|
|
|
|
r->key = pCARDBACKUPKEY;
|
|
|
|
strcpy (r->u.value, "1");
|
2006-04-19 13:26:11 +02:00
|
|
|
r->next = para;
|
|
|
|
para = r;
|
|
|
|
}
|
|
|
|
#endif /*ENABLE_CARD_SUPPORT*/
|
2003-07-03 20:08:16 +02:00
|
|
|
}
|
2014-09-27 15:14:13 +02:00
|
|
|
else if (full) /* Full featured key generation. */
|
2003-07-03 20:08:16 +02:00
|
|
|
{
|
2011-02-03 16:31:42 +01:00
|
|
|
int subkey_algo;
|
2013-11-15 08:59:45 +01:00
|
|
|
char *curve = NULL;
|
2009-05-17 15:08:18 +02:00
|
|
|
|
2011-11-06 17:01:31 +01:00
|
|
|
/* Fixme: To support creating a primary key by keygrip we better
|
|
|
|
also define the keyword for the parameter file. Note that
|
|
|
|
the subkey case will never be asserted if a keygrip has been
|
|
|
|
given. */
|
|
|
|
algo = ask_algo (ctrl, 0, &subkey_algo, &use, NULL);
|
2009-05-17 15:08:18 +02:00
|
|
|
if (subkey_algo)
|
2011-02-03 16:31:42 +01:00
|
|
|
{
|
2009-05-17 15:08:18 +02:00
|
|
|
/* Create primary and subkey at once. */
|
2003-07-03 20:08:16 +02:00
|
|
|
both = 1;
|
gpg: Use only OpenPGP public key algo ids and add the EdDSA algo id.
* common/sexputil.c (get_pk_algo_from_canon_sexp): Change to return a
string.
* g10/keygen.c (check_keygrip): Adjust for change.
* sm/certreqgen-ui.c (check_keygrip): Likewise.
* agent/pksign.c (do_encode_dsa): Remove bogus map_pk_openpgp_to_gcry.
* g10/misc.c (map_pk_openpgp_to_gcry): Remove.
(openpgp_pk_test_algo): Change to a wrapper for openpgp_pk_test_algo2.
(openpgp_pk_test_algo2): Rewrite.
(openpgp_pk_algo_usage, pubkey_nbits): Add support for EdDSA.
(openpgp_pk_algo_name): Rewrite to remove need for gcry calls.
(pubkey_get_npkey, pubkey_get_nskey): Ditto.
(pubkey_get_nsig, pubkey_get_nenc): Ditto.
* g10/keygen.c(do_create_from_keygrip): Support EdDSA.
(common_gen, gen_ecc, ask_keysize, generate_keypair): Ditto.
* g10/build-packet.c (do_key): Ditto.
* g10/export.c (transfer_format_to_openpgp): Ditto.
* g10/getkey.c (cache_public_key): Ditto.
* g10/import.c (transfer_secret_keys): Ditto.
* g10/keylist.c (list_keyblock_print, list_keyblock_colon): Ditto.
* g10/mainproc.c (proc_pubkey_enc): Ditto.
* g10/parse-packet.c (parse_key): Ditto,
* g10/sign.c (hash_for, sign_file, make_keysig_packet): Ditto.
* g10/keyserver.c (print_keyrec): Use openpgp_pk_algo_name.
* g10/pkglue.c (pk_verify, pk_encrypt, pk_check_secret_key): Use only
OpenPGP algo ids and support EdDSA.
* g10/pubkey-enc.c (get_it): Use only OpenPGP algo ids.
* g10/seskey.c (encode_md_value): Ditto.
--
This patch separates Libgcrypt and OpenPGP public key algorithms ids
and in most cases completely removes the Libgcrypt ones. This is
useful because for Libgcrypt we specify the algorithm in the
S-expressions and the public key ids are not anymore needed.
This patch also adds some support for PUBKEY_ALGO_EDDSA which will
eventually be used instead of merging EdDSA with ECDSA. As of now an
experimental algorithm id is used but the plan is to write an I-D so
that we can get a new id from the IETF. Note that EdDSA (Ed25519)
does not yet work and that more changes are required.
The ECC support is still broken right now. Needs to be fixed.
Signed-off-by: Werner Koch <wk@gnupg.org>
2014-01-30 18:48:37 +01:00
|
|
|
if (algo == PUBKEY_ALGO_ECDSA
|
|
|
|
|| algo == PUBKEY_ALGO_EDDSA
|
|
|
|
|| algo == PUBKEY_ALGO_ECDH)
|
2013-11-15 08:59:45 +01:00
|
|
|
{
|
2014-06-05 12:03:27 +02:00
|
|
|
curve = ask_curve (&algo, both);
|
2014-05-07 13:16:32 +02:00
|
|
|
r = xmalloc_clear( sizeof *r + 20 );
|
|
|
|
r->key = pKEYTYPE;
|
|
|
|
sprintf( r->u.value, "%d", algo);
|
|
|
|
r->next = para;
|
|
|
|
para = r;
|
gpg: Use only OpenPGP public key algo ids and add the EdDSA algo id.
* common/sexputil.c (get_pk_algo_from_canon_sexp): Change to return a
string.
* g10/keygen.c (check_keygrip): Adjust for change.
* sm/certreqgen-ui.c (check_keygrip): Likewise.
* agent/pksign.c (do_encode_dsa): Remove bogus map_pk_openpgp_to_gcry.
* g10/misc.c (map_pk_openpgp_to_gcry): Remove.
(openpgp_pk_test_algo): Change to a wrapper for openpgp_pk_test_algo2.
(openpgp_pk_test_algo2): Rewrite.
(openpgp_pk_algo_usage, pubkey_nbits): Add support for EdDSA.
(openpgp_pk_algo_name): Rewrite to remove need for gcry calls.
(pubkey_get_npkey, pubkey_get_nskey): Ditto.
(pubkey_get_nsig, pubkey_get_nenc): Ditto.
* g10/keygen.c(do_create_from_keygrip): Support EdDSA.
(common_gen, gen_ecc, ask_keysize, generate_keypair): Ditto.
* g10/build-packet.c (do_key): Ditto.
* g10/export.c (transfer_format_to_openpgp): Ditto.
* g10/getkey.c (cache_public_key): Ditto.
* g10/import.c (transfer_secret_keys): Ditto.
* g10/keylist.c (list_keyblock_print, list_keyblock_colon): Ditto.
* g10/mainproc.c (proc_pubkey_enc): Ditto.
* g10/parse-packet.c (parse_key): Ditto,
* g10/sign.c (hash_for, sign_file, make_keysig_packet): Ditto.
* g10/keyserver.c (print_keyrec): Use openpgp_pk_algo_name.
* g10/pkglue.c (pk_verify, pk_encrypt, pk_check_secret_key): Use only
OpenPGP algo ids and support EdDSA.
* g10/pubkey-enc.c (get_it): Use only OpenPGP algo ids.
* g10/seskey.c (encode_md_value): Ditto.
--
This patch separates Libgcrypt and OpenPGP public key algorithms ids
and in most cases completely removes the Libgcrypt ones. This is
useful because for Libgcrypt we specify the algorithm in the
S-expressions and the public key ids are not anymore needed.
This patch also adds some support for PUBKEY_ALGO_EDDSA which will
eventually be used instead of merging EdDSA with ECDSA. As of now an
experimental algorithm id is used but the plan is to write an I-D so
that we can get a new id from the IETF. Note that EdDSA (Ed25519)
does not yet work and that more changes are required.
The ECC support is still broken right now. Needs to be fixed.
Signed-off-by: Werner Koch <wk@gnupg.org>
2014-01-30 18:48:37 +01:00
|
|
|
nbits = 0;
|
2013-11-15 08:59:45 +01:00
|
|
|
r = xmalloc_clear (sizeof *r + strlen (curve));
|
|
|
|
r->key = pKEYCURVE;
|
|
|
|
strcpy (r->u.value, curve);
|
|
|
|
r->next = para;
|
|
|
|
para = r;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-05-07 13:16:32 +02:00
|
|
|
r = xmalloc_clear( sizeof *r + 20 );
|
|
|
|
r->key = pKEYTYPE;
|
|
|
|
sprintf( r->u.value, "%d", algo);
|
|
|
|
r->next = para;
|
|
|
|
para = r;
|
2013-11-15 08:59:45 +01:00
|
|
|
nbits = ask_keysize (algo, 0);
|
|
|
|
r = xmalloc_clear( sizeof *r + 20 );
|
|
|
|
r->key = pKEYLENGTH;
|
|
|
|
sprintf( r->u.value, "%u", nbits);
|
|
|
|
r->next = para;
|
|
|
|
para = r;
|
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
r = xmalloc_clear( sizeof *r + 20 );
|
2003-09-23 19:48:33 +02:00
|
|
|
r->key = pKEYUSAGE;
|
|
|
|
strcpy( r->u.value, "sign" );
|
|
|
|
r->next = para;
|
|
|
|
para = r;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
r = xmalloc_clear( sizeof *r + 20 );
|
2003-07-03 20:08:16 +02:00
|
|
|
r->key = pSUBKEYTYPE;
|
2009-05-17 15:08:18 +02:00
|
|
|
sprintf( r->u.value, "%d", subkey_algo);
|
2003-07-03 20:08:16 +02:00
|
|
|
r->next = para;
|
|
|
|
para = r;
|
2006-04-19 13:26:11 +02:00
|
|
|
r = xmalloc_clear( sizeof *r + 20 );
|
2003-09-23 19:48:33 +02:00
|
|
|
r->key = pSUBKEYUSAGE;
|
|
|
|
strcpy( r->u.value, "encrypt" );
|
|
|
|
r->next = para;
|
|
|
|
para = r;
|
2014-05-07 13:16:32 +02:00
|
|
|
|
|
|
|
if (algo == PUBKEY_ALGO_ECDSA
|
|
|
|
|| algo == PUBKEY_ALGO_EDDSA
|
|
|
|
|| algo == PUBKEY_ALGO_ECDH)
|
|
|
|
{
|
|
|
|
if (algo == PUBKEY_ALGO_EDDSA
|
|
|
|
&& subkey_algo == PUBKEY_ALGO_ECDH)
|
|
|
|
{
|
|
|
|
/* Need to switch to a different curve for the
|
|
|
|
encryption key. */
|
|
|
|
xfree (curve);
|
|
|
|
curve = xstrdup ("Curve25519");
|
|
|
|
}
|
|
|
|
r = xmalloc_clear (sizeof *r + strlen (curve));
|
|
|
|
r->key = pSUBKEYCURVE;
|
|
|
|
strcpy (r->u.value, curve);
|
|
|
|
r->next = para;
|
|
|
|
para = r;
|
|
|
|
}
|
2003-07-03 20:08:16 +02:00
|
|
|
}
|
2014-05-07 13:16:32 +02:00
|
|
|
else /* Create only a single key. */
|
2003-06-27 22:53:09 +02:00
|
|
|
{
|
2014-05-07 13:16:32 +02:00
|
|
|
/* For ECC we need to ask for the curve before storing the
|
2014-06-05 12:03:27 +02:00
|
|
|
algo because ask_curve may change the algo. */
|
2014-05-07 13:16:32 +02:00
|
|
|
if (algo == PUBKEY_ALGO_ECDSA
|
|
|
|
|| algo == PUBKEY_ALGO_EDDSA
|
|
|
|
|| algo == PUBKEY_ALGO_ECDH)
|
|
|
|
{
|
2014-06-05 12:03:27 +02:00
|
|
|
curve = ask_curve (&algo, 0);
|
2014-05-07 13:16:32 +02:00
|
|
|
nbits = 0;
|
|
|
|
r = xmalloc_clear (sizeof *r + strlen (curve));
|
|
|
|
r->key = pKEYCURVE;
|
|
|
|
strcpy (r->u.value, curve);
|
|
|
|
r->next = para;
|
|
|
|
para = r;
|
|
|
|
}
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
r = xmalloc_clear( sizeof *r + 20 );
|
2003-07-03 20:08:16 +02:00
|
|
|
r->key = pKEYTYPE;
|
|
|
|
sprintf( r->u.value, "%d", algo );
|
2003-06-27 22:53:09 +02:00
|
|
|
r->next = para;
|
|
|
|
para = r;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2003-07-03 20:08:16 +02:00
|
|
|
if (use)
|
|
|
|
{
|
2006-04-19 13:26:11 +02:00
|
|
|
r = xmalloc_clear( sizeof *r + 25 );
|
2003-07-03 20:08:16 +02:00
|
|
|
r->key = pKEYUSAGE;
|
2006-04-19 13:26:11 +02:00
|
|
|
sprintf( r->u.value, "%s%s%s",
|
2003-07-03 20:08:16 +02:00
|
|
|
(use & PUBKEY_USAGE_SIG)? "sign ":"",
|
2006-04-19 13:26:11 +02:00
|
|
|
(use & PUBKEY_USAGE_ENC)? "encrypt ":"",
|
|
|
|
(use & PUBKEY_USAGE_AUTH)? "auth":"" );
|
2003-07-03 20:08:16 +02:00
|
|
|
r->next = para;
|
|
|
|
para = r;
|
|
|
|
}
|
2009-05-17 15:08:18 +02:00
|
|
|
nbits = 0;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2006-06-27 16:30:59 +02:00
|
|
|
|
gpg: Use only OpenPGP public key algo ids and add the EdDSA algo id.
* common/sexputil.c (get_pk_algo_from_canon_sexp): Change to return a
string.
* g10/keygen.c (check_keygrip): Adjust for change.
* sm/certreqgen-ui.c (check_keygrip): Likewise.
* agent/pksign.c (do_encode_dsa): Remove bogus map_pk_openpgp_to_gcry.
* g10/misc.c (map_pk_openpgp_to_gcry): Remove.
(openpgp_pk_test_algo): Change to a wrapper for openpgp_pk_test_algo2.
(openpgp_pk_test_algo2): Rewrite.
(openpgp_pk_algo_usage, pubkey_nbits): Add support for EdDSA.
(openpgp_pk_algo_name): Rewrite to remove need for gcry calls.
(pubkey_get_npkey, pubkey_get_nskey): Ditto.
(pubkey_get_nsig, pubkey_get_nenc): Ditto.
* g10/keygen.c(do_create_from_keygrip): Support EdDSA.
(common_gen, gen_ecc, ask_keysize, generate_keypair): Ditto.
* g10/build-packet.c (do_key): Ditto.
* g10/export.c (transfer_format_to_openpgp): Ditto.
* g10/getkey.c (cache_public_key): Ditto.
* g10/import.c (transfer_secret_keys): Ditto.
* g10/keylist.c (list_keyblock_print, list_keyblock_colon): Ditto.
* g10/mainproc.c (proc_pubkey_enc): Ditto.
* g10/parse-packet.c (parse_key): Ditto,
* g10/sign.c (hash_for, sign_file, make_keysig_packet): Ditto.
* g10/keyserver.c (print_keyrec): Use openpgp_pk_algo_name.
* g10/pkglue.c (pk_verify, pk_encrypt, pk_check_secret_key): Use only
OpenPGP algo ids and support EdDSA.
* g10/pubkey-enc.c (get_it): Use only OpenPGP algo ids.
* g10/seskey.c (encode_md_value): Ditto.
--
This patch separates Libgcrypt and OpenPGP public key algorithms ids
and in most cases completely removes the Libgcrypt ones. This is
useful because for Libgcrypt we specify the algorithm in the
S-expressions and the public key ids are not anymore needed.
This patch also adds some support for PUBKEY_ALGO_EDDSA which will
eventually be used instead of merging EdDSA with ECDSA. As of now an
experimental algorithm id is used but the plan is to write an I-D so
that we can get a new id from the IETF. Note that EdDSA (Ed25519)
does not yet work and that more changes are required.
The ECC support is still broken right now. Needs to be fixed.
Signed-off-by: Werner Koch <wk@gnupg.org>
2014-01-30 18:48:37 +01:00
|
|
|
if (algo == PUBKEY_ALGO_ECDSA
|
|
|
|
|| algo == PUBKEY_ALGO_EDDSA
|
|
|
|
|| algo == PUBKEY_ALGO_ECDH)
|
2013-11-15 08:59:45 +01:00
|
|
|
{
|
2014-05-07 13:16:32 +02:00
|
|
|
/* The curve has already been set. */
|
2013-11-15 08:59:45 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nbits = ask_keysize (both? subkey_algo : algo, nbits);
|
|
|
|
r = xmalloc_clear( sizeof *r + 20 );
|
|
|
|
r->key = both? pSUBKEYLENGTH : pKEYLENGTH;
|
|
|
|
sprintf( r->u.value, "%u", nbits);
|
|
|
|
r->next = para;
|
|
|
|
para = r;
|
|
|
|
}
|
|
|
|
|
|
|
|
xfree (curve);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2014-09-27 15:14:13 +02:00
|
|
|
else /* Default key generation. */
|
|
|
|
{
|
|
|
|
tty_printf ( _("Note: Use \"%s %s\""
|
|
|
|
" for a full featured key generation dialog.\n"),
|
2014-11-04 10:52:46 +01:00
|
|
|
NAME_OF_INSTALLED_GPG, "--full-gen-key" );
|
2014-09-27 15:14:13 +02:00
|
|
|
para = quickgen_set_para (para, 0,
|
|
|
|
DEFAULT_STD_ALGO, DEFAULT_STD_KEYSIZE,
|
|
|
|
DEFAULT_STD_CURVE);
|
|
|
|
para = quickgen_set_para (para, 1,
|
|
|
|
DEFAULT_STD_SUBALGO, DEFAULT_STD_SUBKEYSIZE,
|
|
|
|
DEFAULT_STD_SUBCURVE);
|
|
|
|
}
|
|
|
|
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2014-09-27 15:14:13 +02:00
|
|
|
expire = full? ask_expire_interval (0, NULL) : 0;
|
|
|
|
r = xcalloc (1, sizeof *r + 20);
|
2003-06-27 22:53:09 +02:00
|
|
|
r->key = pKEYEXPIRE;
|
|
|
|
r->u.expire = expire;
|
|
|
|
r->next = para;
|
|
|
|
para = r;
|
2014-09-27 15:14:13 +02:00
|
|
|
r = xcalloc (1, sizeof *r + 20);
|
2003-06-27 22:53:09 +02:00
|
|
|
r->key = pSUBKEYEXPIRE;
|
|
|
|
r->u.expire = expire;
|
|
|
|
r->next = para;
|
|
|
|
para = r;
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2014-09-27 15:14:13 +02:00
|
|
|
uid = ask_user_id (0, full, NULL);
|
|
|
|
if (!uid)
|
2003-06-27 22:53:09 +02:00
|
|
|
{
|
|
|
|
log_error(_("Key generation canceled.\n"));
|
|
|
|
release_parameter_list( para );
|
|
|
|
return;
|
|
|
|
}
|
2014-09-27 15:14:13 +02:00
|
|
|
r = xcalloc (1, sizeof *r + strlen (uid));
|
2003-06-27 22:53:09 +02:00
|
|
|
r->key = pUSERID;
|
2014-09-27 15:14:13 +02:00
|
|
|
strcpy (r->u.value, uid);
|
2003-06-27 22:53:09 +02:00
|
|
|
r->next = para;
|
|
|
|
para = r;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2014-09-27 15:14:13 +02:00
|
|
|
proc_parameter_file (para, "[internal]", &outctrl, !!card_serialno);
|
|
|
|
release_parameter_list (para);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-17 14:21:24 +01:00
|
|
|
#if 0 /* not required */
|
2006-04-19 13:26:11 +02:00
|
|
|
/* Generate a raw key and return it as a secret key packet. The
|
|
|
|
function will ask for the passphrase and return a protected as well
|
|
|
|
as an unprotected copy of a new secret key packet. 0 is returned
|
|
|
|
on success and the caller must then free the returned values. */
|
|
|
|
static int
|
|
|
|
generate_raw_key (int algo, unsigned int nbits, u32 created_at,
|
|
|
|
PKT_secret_key **r_sk_unprotected,
|
|
|
|
PKT_secret_key **r_sk_protected)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2006-04-19 13:26:11 +02:00
|
|
|
int rc;
|
|
|
|
DEK *dek = NULL;
|
|
|
|
STRING2KEY *s2k = NULL;
|
|
|
|
PKT_secret_key *sk = NULL;
|
|
|
|
int i;
|
|
|
|
size_t nskey, npkey;
|
2006-08-16 12:47:53 +02:00
|
|
|
gcry_sexp_t s_parms, s_key;
|
2006-12-06 11:16:50 +01:00
|
|
|
int canceled;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
npkey = pubkey_get_npkey (algo);
|
|
|
|
nskey = pubkey_get_nskey (algo);
|
|
|
|
assert (nskey <= PUBKEY_MAX_NSKEY && npkey < nskey);
|
2003-06-27 22:53:09 +02:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
if (nbits < 512)
|
|
|
|
{
|
|
|
|
nbits = 512;
|
|
|
|
log_info (_("keysize invalid; using %u bits\n"), nbits );
|
|
|
|
}
|
2003-06-27 22:53:09 +02:00
|
|
|
|
2011-02-03 16:31:42 +01:00
|
|
|
if ((nbits % 32))
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
|
|
|
nbits = ((nbits + 31) / 32) * 32;
|
|
|
|
log_info(_("keysize rounded up to %u bits\n"), nbits );
|
|
|
|
}
|
|
|
|
|
2009-05-15 21:26:46 +02:00
|
|
|
dek = do_ask_passphrase (&s2k, 1, &canceled);
|
2006-12-06 11:16:50 +01:00
|
|
|
if (canceled)
|
|
|
|
{
|
|
|
|
rc = gpg_error (GPG_ERR_CANCELED);
|
|
|
|
goto leave;
|
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
|
|
|
|
sk = xmalloc_clear (sizeof *sk);
|
|
|
|
sk->timestamp = created_at;
|
|
|
|
sk->version = 4;
|
|
|
|
sk->pubkey_algo = algo;
|
2003-06-27 22:53:09 +02:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
if ( !is_RSA (algo) )
|
2003-06-27 22:53:09 +02:00
|
|
|
{
|
2006-04-19 13:26:11 +02:00
|
|
|
log_error ("only RSA is supported for offline generated keys\n");
|
|
|
|
rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
|
|
|
goto leave;
|
|
|
|
}
|
|
|
|
rc = gcry_sexp_build (&s_parms, NULL,
|
|
|
|
"(genkey(rsa(nbits %d)))",
|
|
|
|
(int)nbits);
|
|
|
|
if (rc)
|
|
|
|
log_bug ("gcry_sexp_build failed: %s\n", gpg_strerror (rc));
|
|
|
|
rc = gcry_pk_genkey (&s_key, s_parms);
|
|
|
|
gcry_sexp_release (s_parms);
|
|
|
|
if (rc)
|
|
|
|
{
|
|
|
|
log_error ("gcry_pk_genkey failed: %s\n", gpg_strerror (rc) );
|
|
|
|
goto leave;
|
|
|
|
}
|
|
|
|
rc = key_from_sexp (sk->skey, s_key, "private-key", "nedpqu");
|
|
|
|
gcry_sexp_release (s_key);
|
2011-02-03 16:31:42 +01:00
|
|
|
if (rc)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
|
|
|
log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc) );
|
|
|
|
goto leave;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
for (i=npkey; i < nskey; i++)
|
|
|
|
sk->csum += checksum_mpi (sk->skey[i]);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2011-02-03 16:31:42 +01:00
|
|
|
if (r_sk_unprotected)
|
2006-04-19 13:26:11 +02:00
|
|
|
*r_sk_unprotected = copy_secret_key (NULL, sk);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
rc = genhelp_protect (dek, s2k, sk);
|
|
|
|
if (rc)
|
|
|
|
goto leave;
|
|
|
|
|
|
|
|
if (r_sk_protected)
|
2003-06-27 22:53:09 +02:00
|
|
|
{
|
2006-04-19 13:26:11 +02:00
|
|
|
*r_sk_protected = sk;
|
|
|
|
sk = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
leave:
|
|
|
|
if (sk)
|
|
|
|
free_secret_key (sk);
|
|
|
|
xfree (dek);
|
|
|
|
xfree (s2k);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
#endif /* ENABLE_CARD_SUPPORT */
|
|
|
|
|
|
|
|
/* Create and delete a dummy packet to start off a list of kbnodes. */
|
|
|
|
static void
|
|
|
|
start_tree(KBNODE *tree)
|
|
|
|
{
|
|
|
|
PACKET *pkt;
|
|
|
|
|
|
|
|
pkt=xmalloc_clear(sizeof(*pkt));
|
|
|
|
pkt->pkttype=PKT_NONE;
|
|
|
|
*tree=new_kbnode(pkt);
|
|
|
|
delete_kbnode(*tree);
|
|
|
|
}
|
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
static void
|
2007-07-05 18:58:19 +02:00
|
|
|
do_generate_keypair (struct para_data_s *para,
|
|
|
|
struct output_control_s *outctrl, int card)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
gpg_error_t err;
|
2007-07-05 18:58:19 +02:00
|
|
|
KBNODE pub_root = NULL;
|
|
|
|
const char *s;
|
2010-04-20 19:57:50 +02:00
|
|
|
PKT_public_key *pri_psk = NULL;
|
|
|
|
PKT_public_key *sub_psk = NULL;
|
2007-07-05 18:58:19 +02:00
|
|
|
struct revocation_key *revkey;
|
|
|
|
int did_sub = 0;
|
|
|
|
u32 timestamp;
|
2010-09-01 11:48:35 +02:00
|
|
|
char *cache_nonce = NULL;
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
if (outctrl->dryrun)
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
|
|
|
log_info("dry-run mode - key generation skipped\n");
|
|
|
|
return;
|
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
|
|
|
|
if ( outctrl->use_files )
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2011-02-03 16:31:42 +01:00
|
|
|
if ( outctrl->pub.newfname )
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
|
|
|
iobuf_close(outctrl->pub.stream);
|
|
|
|
outctrl->pub.stream = NULL;
|
|
|
|
if (outctrl->pub.fname)
|
2010-03-08 18:05:37 +01:00
|
|
|
iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE,
|
|
|
|
0, (char*)outctrl->pub.fname);
|
2007-07-05 18:58:19 +02:00
|
|
|
xfree( outctrl->pub.fname );
|
|
|
|
outctrl->pub.fname = outctrl->pub.newfname;
|
|
|
|
outctrl->pub.newfname = NULL;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
|
|
|
if (is_secured_filename (outctrl->pub.fname) )
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
|
|
|
outctrl->pub.stream = NULL;
|
2010-04-01 15:24:55 +02:00
|
|
|
gpg_err_set_errno (EPERM);
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
2007-07-05 18:58:19 +02:00
|
|
|
else
|
2014-06-25 20:25:28 +02:00
|
|
|
outctrl->pub.stream = iobuf_create (outctrl->pub.fname, 0);
|
2007-07-05 18:58:19 +02:00
|
|
|
if (!outctrl->pub.stream)
|
|
|
|
{
|
2012-06-05 19:29:22 +02:00
|
|
|
log_error(_("can't create '%s': %s\n"), outctrl->pub.newfname,
|
2007-07-05 18:58:19 +02:00
|
|
|
strerror(errno) );
|
|
|
|
return;
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
2007-07-05 18:58:19 +02:00
|
|
|
if (opt.armor)
|
|
|
|
{
|
|
|
|
outctrl->pub.afx->what = 1;
|
|
|
|
push_armor_filter (outctrl->pub.afx, outctrl->pub.stream);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert( outctrl->pub.stream );
|
|
|
|
if (opt.verbose)
|
2012-06-05 19:29:22 +02:00
|
|
|
log_info (_("writing public key to '%s'\n"), outctrl->pub.fname );
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
/* We create the packets as a tree of kbnodes. Because the
|
|
|
|
structure we create is known in advance we simply generate a
|
|
|
|
linked list. The first packet is a dummy packet which we flag as
|
|
|
|
deleted. The very first packet must always be a KEY packet. */
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
start_tree (&pub_root);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
timestamp = get_parameter_u32 (para, pKEYCREATIONDATE);
|
|
|
|
if (!timestamp)
|
|
|
|
timestamp = make_timestamp ();
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2009-07-20 13:02:20 +02:00
|
|
|
/* Note that, depending on the backend (i.e. the used scdaemon
|
|
|
|
version), the card key generation may update TIMESTAMP for each
|
|
|
|
key. Thus we need to pass TIMESTAMP to all signing function to
|
|
|
|
make sure that the binding signature is done using the timestamp
|
|
|
|
of the corresponding (sub)key and not that of the primary key.
|
|
|
|
An alternative implementation could tell the signing function the
|
|
|
|
node of the subkey but that is more work than just to pass the
|
|
|
|
current timestamp. */
|
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
if (!card)
|
2010-04-20 19:57:50 +02:00
|
|
|
err = do_create (get_parameter_algo( para, pKEYTYPE, NULL ),
|
|
|
|
get_parameter_uint( para, pKEYLENGTH ),
|
2013-11-15 08:59:45 +01:00
|
|
|
get_parameter_value (para, pKEYCURVE),
|
2010-04-20 19:57:50 +02:00
|
|
|
pub_root,
|
|
|
|
timestamp,
|
2011-02-03 16:31:42 +01:00
|
|
|
get_parameter_u32( para, pKEYEXPIRE ), 0,
|
2010-10-14 18:34:31 +02:00
|
|
|
outctrl->keygen_flags, &cache_nonce);
|
2007-07-05 18:58:19 +02:00
|
|
|
else
|
2010-04-20 19:57:50 +02:00
|
|
|
err = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root,
|
|
|
|
×tamp,
|
2010-11-17 14:21:24 +01:00
|
|
|
get_parameter_u32 (para, pKEYEXPIRE));
|
2003-06-27 22:53:09 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
/* Get the pointer to the generated public key packet. */
|
|
|
|
if (!err)
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
pri_psk = pub_root->next->pkt->pkt.public_key;
|
|
|
|
assert (pri_psk);
|
2007-07-05 18:58:19 +02:00
|
|
|
}
|
2003-07-03 20:08:16 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
if (!err && (revkey = get_parameter_revkey (para, pREVOKER)))
|
2010-09-01 14:49:05 +02:00
|
|
|
err = write_direct_sig (pub_root, pri_psk, revkey, timestamp, cache_nonce);
|
2010-04-20 19:57:50 +02:00
|
|
|
|
|
|
|
if (!err && (s = get_parameter_value (para, pUSERID)))
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
|
|
|
write_uid (pub_root, s );
|
2010-04-20 19:57:50 +02:00
|
|
|
err = write_selfsigs (pub_root, pri_psk,
|
2010-09-01 14:49:05 +02:00
|
|
|
get_parameter_uint (para, pKEYUSAGE), timestamp,
|
|
|
|
cache_nonce);
|
2007-07-05 18:58:19 +02:00
|
|
|
}
|
2003-07-23 09:11:06 +02:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
/* Write the auth key to the card before the encryption key. This
|
|
|
|
is a partial workaround for a PGP bug (as of this writing, all
|
|
|
|
versions including 8.1), that causes it to try and encrypt to
|
|
|
|
the most recent subkey regardless of whether that subkey is
|
|
|
|
actually an encryption type. In this case, the auth key is an
|
|
|
|
RSA key so it succeeds. */
|
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
if (!err && card && get_parameter (para, pAUTHKEYTYPE))
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
err = gen_card_key (PUBKEY_ALGO_RSA, 3, 0, pub_root,
|
|
|
|
×tamp,
|
2010-11-17 14:21:24 +01:00
|
|
|
get_parameter_u32 (para, pKEYEXPIRE));
|
2010-04-20 19:57:50 +02:00
|
|
|
if (!err)
|
|
|
|
err = write_keybinding (pub_root, pri_psk, NULL,
|
2010-09-01 14:49:05 +02:00
|
|
|
PUBKEY_USAGE_AUTH, timestamp, cache_nonce);
|
2007-07-05 18:58:19 +02:00
|
|
|
}
|
2003-07-23 09:11:06 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
if (!err && get_parameter (para, pSUBKEYTYPE))
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
sub_psk = NULL;
|
2007-07-05 18:58:19 +02:00
|
|
|
if (!card)
|
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
err = do_create (get_parameter_algo (para, pSUBKEYTYPE, NULL),
|
|
|
|
get_parameter_uint (para, pSUBKEYLENGTH),
|
2013-11-15 08:59:45 +01:00
|
|
|
get_parameter_value (para, pSUBKEYCURVE),
|
2011-02-03 16:31:42 +01:00
|
|
|
pub_root,
|
2010-04-20 19:57:50 +02:00
|
|
|
timestamp,
|
2010-09-01 11:48:35 +02:00
|
|
|
get_parameter_u32 (para, pSUBKEYEXPIRE), 1,
|
2010-10-14 18:34:31 +02:00
|
|
|
outctrl->keygen_flags, &cache_nonce);
|
2010-04-20 19:57:50 +02:00
|
|
|
/* Get the pointer to the generated public subkey packet. */
|
|
|
|
if (!err)
|
|
|
|
{
|
|
|
|
kbnode_t node;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
for (node = pub_root; node; node = node->next)
|
|
|
|
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
|
|
|
|
sub_psk = node->pkt->pkt.public_key;
|
|
|
|
assert (sub_psk);
|
|
|
|
}
|
2007-07-05 18:58:19 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-11-17 14:21:24 +01:00
|
|
|
if ((s = get_parameter_value (para, pCARDBACKUPKEY)))
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
|
|
|
/* A backup of the encryption key has been requested.
|
|
|
|
Generate the key in software and import it then to
|
|
|
|
the card. Write a backup file. */
|
2010-11-17 14:21:24 +01:00
|
|
|
err = gen_card_key_with_backup
|
|
|
|
(PUBKEY_ALGO_RSA, 2, 0, pub_root, timestamp,
|
|
|
|
get_parameter_u32 (para, pKEYEXPIRE), para);
|
2007-07-05 18:58:19 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
err = gen_card_key (PUBKEY_ALGO_RSA, 2, 0, pub_root,
|
|
|
|
×tamp,
|
2010-11-17 14:21:24 +01:00
|
|
|
get_parameter_u32 (para, pKEYEXPIRE));
|
2007-07-05 18:58:19 +02:00
|
|
|
}
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
if (!err)
|
|
|
|
err = write_keybinding (pub_root, pri_psk, sub_psk,
|
|
|
|
get_parameter_uint (para, pSUBKEYUSAGE),
|
2010-09-01 14:49:05 +02:00
|
|
|
timestamp, cache_nonce);
|
2007-07-05 18:58:19 +02:00
|
|
|
did_sub = 1;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
if (!err && outctrl->use_files) /* Direct write to specified files. */
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
err = write_keyblock (outctrl->pub.stream, pub_root);
|
|
|
|
if (err)
|
|
|
|
log_error ("can't write public key: %s\n", g10_errstr (err));
|
2007-07-05 18:58:19 +02:00
|
|
|
}
|
2010-04-20 19:57:50 +02:00
|
|
|
else if (!err) /* Write to the standard keyrings. */
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2010-04-21 18:26:17 +02:00
|
|
|
KEYDB_HANDLE pub_hd = keydb_new ();
|
2007-07-05 18:58:19 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
err = keydb_locate_writable (pub_hd, NULL);
|
2011-02-03 16:31:42 +01:00
|
|
|
if (err)
|
2007-07-05 18:58:19 +02:00
|
|
|
log_error (_("no writable public keyring found: %s\n"),
|
2010-04-20 19:57:50 +02:00
|
|
|
g10_errstr (err));
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
if (!err && opt.verbose)
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2012-06-05 19:29:22 +02:00
|
|
|
log_info (_("writing public key to '%s'\n"),
|
2007-07-05 18:58:19 +02:00
|
|
|
keydb_get_resource_name (pub_hd));
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
|
|
|
|
if (!err)
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
err = keydb_insert_keyblock (pub_hd, pub_root);
|
|
|
|
if (err)
|
2012-06-05 19:29:22 +02:00
|
|
|
log_error (_("error writing public keyring '%s': %s\n"),
|
2010-04-20 19:57:50 +02:00
|
|
|
keydb_get_resource_name (pub_hd), g10_errstr(err));
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
keydb_release (pub_hd);
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
if (!err)
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
|
|
|
int no_enc_rsa;
|
|
|
|
PKT_public_key *pk;
|
|
|
|
|
2009-12-04 20:47:54 +01:00
|
|
|
no_enc_rsa = ((get_parameter_algo (para, pKEYTYPE, NULL)
|
|
|
|
== PUBKEY_ALGO_RSA)
|
2007-07-05 18:58:19 +02:00
|
|
|
&& get_parameter_uint (para, pKEYUSAGE)
|
|
|
|
&& !((get_parameter_uint (para, pKEYUSAGE)
|
|
|
|
& PUBKEY_USAGE_ENC)) );
|
2003-06-27 22:53:09 +02:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
pk = find_kbnode (pub_root, PKT_PUBLIC_KEY)->pkt->pkt.public_key;
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
keyid_from_pk (pk, pk->main_keyid);
|
|
|
|
register_trusted_keyid (pk->main_keyid);
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
update_ownertrust (pk, ((get_ownertrust (pk) & ~TRUST_MASK)
|
|
|
|
| TRUST_ULTIMATE ));
|
2003-09-02 21:06:34 +02:00
|
|
|
|
2014-09-17 15:12:08 +02:00
|
|
|
gen_standard_revoke (pk, cache_nonce);
|
2014-06-25 20:25:28 +02:00
|
|
|
|
2011-02-03 16:31:42 +01:00
|
|
|
if (!opt.batch)
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
|
|
|
tty_printf (_("public and secret key created and signed.\n") );
|
|
|
|
tty_printf ("\n");
|
2014-06-03 21:35:59 +02:00
|
|
|
list_keyblock (pub_root, 0, 1, 1, NULL);
|
2003-09-02 21:06:34 +02:00
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
|
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
if (!opt.batch
|
2009-12-04 20:47:54 +01:00
|
|
|
&& (get_parameter_algo (para, pKEYTYPE, NULL) == PUBKEY_ALGO_DSA
|
2007-07-05 18:58:19 +02:00
|
|
|
|| no_enc_rsa )
|
|
|
|
&& !get_parameter (para, pSUBKEYTYPE) )
|
|
|
|
{
|
|
|
|
tty_printf(_("Note that this key cannot be used for "
|
|
|
|
"encryption. You may want to use\n"
|
|
|
|
"the command \"--edit-key\" to generate a "
|
|
|
|
"subkey for this purpose.\n") );
|
|
|
|
}
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
if (err)
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
|
|
|
if (opt.batch)
|
2010-04-20 19:57:50 +02:00
|
|
|
log_error ("key generation failed: %s\n", g10_errstr(err) );
|
2007-07-05 18:58:19 +02:00
|
|
|
else
|
2010-04-20 19:57:50 +02:00
|
|
|
tty_printf (_("Key generation failed: %s\n"), g10_errstr(err) );
|
|
|
|
write_status_error (card? "card_key_generate":"key_generate", err);
|
2007-07-05 18:58:19 +02:00
|
|
|
print_status_key_not_created ( get_parameter_value (para, pHANDLE) );
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2007-07-05 18:58:19 +02:00
|
|
|
else
|
|
|
|
{
|
2011-02-03 16:31:42 +01:00
|
|
|
PKT_public_key *pk = find_kbnode (pub_root,
|
2007-07-05 18:58:19 +02:00
|
|
|
PKT_PUBLIC_KEY)->pkt->pkt.public_key;
|
|
|
|
print_status_key_created (did_sub? 'B':'P', pk,
|
|
|
|
get_parameter_value (para, pHANDLE));
|
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
release_kbnode (pub_root);
|
2010-09-01 11:48:35 +02:00
|
|
|
xfree (cache_nonce);
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
/* Add a new subkey to an existing key. Returns 0 if a new key has
|
2007-07-05 18:58:19 +02:00
|
|
|
been generated and put into the keyblocks. */
|
2010-04-20 19:57:50 +02:00
|
|
|
gpg_error_t
|
2011-11-06 17:01:31 +01:00
|
|
|
generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock)
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
gpg_error_t err = 0;
|
|
|
|
kbnode_t node;
|
|
|
|
PKT_public_key *pri_psk = NULL;
|
|
|
|
PKT_public_key *sub_psk = NULL;
|
2007-07-05 18:58:19 +02:00
|
|
|
int algo;
|
|
|
|
unsigned int use;
|
|
|
|
u32 expire;
|
2013-11-15 08:59:45 +01:00
|
|
|
unsigned int nbits = 0;
|
|
|
|
char *curve = NULL;
|
2007-07-05 18:58:19 +02:00
|
|
|
u32 cur_time;
|
2010-10-13 17:57:08 +02:00
|
|
|
char *hexgrip = NULL;
|
|
|
|
char *serialno = NULL;
|
2007-07-05 18:58:19 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
/* Break out the primary key. */
|
|
|
|
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
|
2011-02-03 16:31:42 +01:00
|
|
|
if (!node)
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
log_error ("Oops; primary key missing in keyblock!\n");
|
|
|
|
err = gpg_error (GPG_ERR_BUG);
|
2007-07-05 18:58:19 +02:00
|
|
|
goto leave;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2010-04-20 19:57:50 +02:00
|
|
|
pri_psk = node->pkt->pkt.public_key;
|
2007-07-05 18:58:19 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
cur_time = make_timestamp ();
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2010-04-20 19:57:50 +02:00
|
|
|
if (pri_psk->timestamp > cur_time)
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
ulong d = pri_psk->timestamp - cur_time;
|
2007-07-05 18:58:19 +02:00
|
|
|
log_info ( d==1 ? _("key has been created %lu second "
|
|
|
|
"in future (time warp or clock problem)\n")
|
|
|
|
: _("key has been created %lu seconds "
|
|
|
|
"in future (time warp or clock problem)\n"), d );
|
|
|
|
if (!opt.ignore_time_conflict)
|
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
err = gpg_error (GPG_ERR_TIME_CONFLICT);
|
2007-07-05 18:58:19 +02:00
|
|
|
goto leave;
|
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2011-02-03 16:31:42 +01:00
|
|
|
if (pri_psk->version < 4)
|
2007-07-05 18:58:19 +02:00
|
|
|
{
|
2014-10-10 15:29:42 +02:00
|
|
|
log_info (_("Note: creating subkeys for v3 keys "
|
2007-07-05 18:58:19 +02:00
|
|
|
"is not OpenPGP compliant\n"));
|
2010-04-20 19:57:50 +02:00
|
|
|
err = gpg_error (GPG_ERR_CONFLICT);
|
2007-07-05 18:58:19 +02:00
|
|
|
goto leave;
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
|
|
|
|
2010-10-13 17:57:08 +02:00
|
|
|
err = hexkeygrip_from_pk (pri_psk, &hexgrip);
|
|
|
|
if (err)
|
|
|
|
goto leave;
|
|
|
|
if (agent_get_keyinfo (NULL, hexgrip, &serialno))
|
|
|
|
{
|
|
|
|
tty_printf (_("Secret parts of primary key are not available.\n"));
|
|
|
|
goto leave;
|
|
|
|
}
|
|
|
|
if (serialno)
|
|
|
|
tty_printf (_("Secret parts of primary key are stored on-card.\n"));
|
2003-06-05 09:14:21 +02:00
|
|
|
|
2011-11-06 17:01:31 +01:00
|
|
|
xfree (hexgrip);
|
|
|
|
hexgrip = NULL;
|
|
|
|
algo = ask_algo (ctrl, 1, NULL, &use, &hexgrip);
|
2007-07-05 18:58:19 +02:00
|
|
|
assert (algo);
|
2013-11-15 08:59:45 +01:00
|
|
|
|
|
|
|
if (hexgrip)
|
|
|
|
nbits = 0;
|
gpg: Use only OpenPGP public key algo ids and add the EdDSA algo id.
* common/sexputil.c (get_pk_algo_from_canon_sexp): Change to return a
string.
* g10/keygen.c (check_keygrip): Adjust for change.
* sm/certreqgen-ui.c (check_keygrip): Likewise.
* agent/pksign.c (do_encode_dsa): Remove bogus map_pk_openpgp_to_gcry.
* g10/misc.c (map_pk_openpgp_to_gcry): Remove.
(openpgp_pk_test_algo): Change to a wrapper for openpgp_pk_test_algo2.
(openpgp_pk_test_algo2): Rewrite.
(openpgp_pk_algo_usage, pubkey_nbits): Add support for EdDSA.
(openpgp_pk_algo_name): Rewrite to remove need for gcry calls.
(pubkey_get_npkey, pubkey_get_nskey): Ditto.
(pubkey_get_nsig, pubkey_get_nenc): Ditto.
* g10/keygen.c(do_create_from_keygrip): Support EdDSA.
(common_gen, gen_ecc, ask_keysize, generate_keypair): Ditto.
* g10/build-packet.c (do_key): Ditto.
* g10/export.c (transfer_format_to_openpgp): Ditto.
* g10/getkey.c (cache_public_key): Ditto.
* g10/import.c (transfer_secret_keys): Ditto.
* g10/keylist.c (list_keyblock_print, list_keyblock_colon): Ditto.
* g10/mainproc.c (proc_pubkey_enc): Ditto.
* g10/parse-packet.c (parse_key): Ditto,
* g10/sign.c (hash_for, sign_file, make_keysig_packet): Ditto.
* g10/keyserver.c (print_keyrec): Use openpgp_pk_algo_name.
* g10/pkglue.c (pk_verify, pk_encrypt, pk_check_secret_key): Use only
OpenPGP algo ids and support EdDSA.
* g10/pubkey-enc.c (get_it): Use only OpenPGP algo ids.
* g10/seskey.c (encode_md_value): Ditto.
--
This patch separates Libgcrypt and OpenPGP public key algorithms ids
and in most cases completely removes the Libgcrypt ones. This is
useful because for Libgcrypt we specify the algorithm in the
S-expressions and the public key ids are not anymore needed.
This patch also adds some support for PUBKEY_ALGO_EDDSA which will
eventually be used instead of merging EdDSA with ECDSA. As of now an
experimental algorithm id is used but the plan is to write an I-D so
that we can get a new id from the IETF. Note that EdDSA (Ed25519)
does not yet work and that more changes are required.
The ECC support is still broken right now. Needs to be fixed.
Signed-off-by: Werner Koch <wk@gnupg.org>
2014-01-30 18:48:37 +01:00
|
|
|
else if (algo == PUBKEY_ALGO_ECDSA
|
|
|
|
|| algo == PUBKEY_ALGO_EDDSA
|
|
|
|
|| algo == PUBKEY_ALGO_ECDH)
|
2014-06-05 12:03:27 +02:00
|
|
|
curve = ask_curve (&algo, 0);
|
2013-11-15 08:59:45 +01:00
|
|
|
else
|
|
|
|
nbits = ask_keysize (algo, 0);
|
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
expire = ask_expire_interval (0, NULL);
|
|
|
|
if (!cpr_enabled() && !cpr_get_answer_is_yes("keygen.sub.okay",
|
|
|
|
_("Really create? (y/N) ")))
|
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
err = gpg_error (GPG_ERR_CANCELED);
|
|
|
|
goto leave;
|
2011-02-03 16:31:42 +01:00
|
|
|
}
|
2010-04-20 19:57:50 +02:00
|
|
|
|
2011-11-06 17:01:31 +01:00
|
|
|
if (hexgrip)
|
|
|
|
err = do_create_from_keygrip (ctrl, algo, hexgrip,
|
|
|
|
keyblock, cur_time, expire, 1);
|
|
|
|
else
|
2013-11-15 08:59:45 +01:00
|
|
|
err = do_create (algo, nbits, curve,
|
|
|
|
keyblock, cur_time, expire, 1, 0, NULL);
|
2010-04-20 19:57:50 +02:00
|
|
|
if (err)
|
|
|
|
goto leave;
|
|
|
|
|
|
|
|
/* Get the pointer to the generated public subkey packet. */
|
|
|
|
for (node = keyblock; node; node = node->next)
|
|
|
|
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
|
|
|
|
sub_psk = node->pkt->pkt.public_key;
|
|
|
|
|
|
|
|
/* Write the binding signature. */
|
2010-09-01 14:49:05 +02:00
|
|
|
err = write_keybinding (keyblock, pri_psk, sub_psk, use, cur_time, NULL);
|
2010-04-20 19:57:50 +02:00
|
|
|
if (err)
|
|
|
|
goto leave;
|
|
|
|
|
|
|
|
write_status_text (STATUS_KEY_CREATED, "S");
|
2007-07-05 18:58:19 +02:00
|
|
|
|
|
|
|
leave:
|
2013-11-15 08:59:45 +01:00
|
|
|
xfree (curve);
|
2010-10-13 17:57:08 +02:00
|
|
|
xfree (hexgrip);
|
|
|
|
xfree (serialno);
|
2010-04-20 19:57:50 +02:00
|
|
|
if (err)
|
|
|
|
log_error (_("Key generation failed: %s\n"), g10_errstr (err) );
|
|
|
|
return err;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
|
|
|
|
#ifdef ENABLE_CARD_SUPPORT
|
|
|
|
/* Generate a subkey on a card. */
|
2010-11-17 14:21:24 +01:00
|
|
|
gpg_error_t
|
|
|
|
generate_card_subkeypair (kbnode_t pub_keyblock,
|
2006-04-19 13:26:11 +02:00
|
|
|
int keyno, const char *serialno)
|
|
|
|
{
|
2010-04-20 19:57:50 +02:00
|
|
|
gpg_error_t err = 0;
|
|
|
|
kbnode_t node;
|
2010-11-17 14:21:24 +01:00
|
|
|
PKT_public_key *pri_pk = NULL;
|
2006-04-19 13:26:11 +02:00
|
|
|
int algo;
|
|
|
|
unsigned int use;
|
|
|
|
u32 expire;
|
|
|
|
u32 cur_time;
|
|
|
|
struct para_data_s *para = NULL;
|
|
|
|
|
|
|
|
assert (keyno >= 1 && keyno <= 3);
|
|
|
|
|
2010-11-17 14:21:24 +01:00
|
|
|
para = xtrycalloc (1, sizeof *para + strlen (serialno) );
|
|
|
|
if (!para)
|
|
|
|
{
|
|
|
|
err = gpg_error_from_syserror ();
|
|
|
|
goto leave;
|
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
para->key = pSERIALNO;
|
|
|
|
strcpy (para->u.value, serialno);
|
|
|
|
|
|
|
|
/* Break out the primary secret key */
|
2010-11-17 14:21:24 +01:00
|
|
|
node = find_kbnode (pub_keyblock, PKT_PUBLIC_KEY);
|
2007-07-05 18:58:19 +02:00
|
|
|
if (!node)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2010-11-17 14:21:24 +01:00
|
|
|
log_error ("Oops; publkic key lost!\n");
|
|
|
|
err = gpg_error (GPG_ERR_INTERNAL);
|
2006-04-19 13:26:11 +02:00
|
|
|
goto leave;
|
|
|
|
}
|
2010-11-17 14:21:24 +01:00
|
|
|
pri_pk = node->pkt->pkt.public_key;
|
2006-04-19 13:26:11 +02:00
|
|
|
|
|
|
|
cur_time = make_timestamp();
|
2010-11-17 14:21:24 +01:00
|
|
|
if (pri_pk->timestamp > cur_time)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2010-11-17 14:21:24 +01:00
|
|
|
ulong d = pri_pk->timestamp - cur_time;
|
2006-04-19 13:26:11 +02:00
|
|
|
log_info (d==1 ? _("key has been created %lu second "
|
|
|
|
"in future (time warp or clock problem)\n")
|
|
|
|
: _("key has been created %lu seconds "
|
|
|
|
"in future (time warp or clock problem)\n"), d );
|
|
|
|
if (!opt.ignore_time_conflict)
|
|
|
|
{
|
2010-11-17 14:21:24 +01:00
|
|
|
err = gpg_error (GPG_ERR_TIME_CONFLICT);
|
2006-04-19 13:26:11 +02:00
|
|
|
goto leave;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-17 14:21:24 +01:00
|
|
|
if (pri_pk->version < 4)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2014-10-10 15:29:42 +02:00
|
|
|
log_info (_("Note: creating subkeys for v3 keys "
|
2006-04-19 13:26:11 +02:00
|
|
|
"is not OpenPGP compliant\n"));
|
2010-11-17 14:21:24 +01:00
|
|
|
err = gpg_error (GPG_ERR_NOT_SUPPORTED);
|
2006-04-19 13:26:11 +02:00
|
|
|
goto leave;
|
|
|
|
}
|
|
|
|
|
|
|
|
algo = PUBKEY_ALGO_RSA;
|
2010-11-17 14:21:24 +01:00
|
|
|
expire = ask_expire_interval (0, NULL);
|
2006-04-19 13:26:11 +02:00
|
|
|
if (keyno == 1)
|
|
|
|
use = PUBKEY_USAGE_SIG;
|
|
|
|
else if (keyno == 2)
|
|
|
|
use = PUBKEY_USAGE_ENC;
|
|
|
|
else
|
|
|
|
use = PUBKEY_USAGE_AUTH;
|
|
|
|
if (!cpr_enabled() && !cpr_get_answer_is_yes("keygen.cardsub.okay",
|
|
|
|
_("Really create? (y/N) ")))
|
2010-11-17 14:21:24 +01:00
|
|
|
{
|
|
|
|
err = gpg_error (GPG_ERR_CANCELED);
|
|
|
|
goto leave;
|
|
|
|
}
|
2007-07-05 18:58:19 +02:00
|
|
|
|
|
|
|
/* Note, that depending on the backend, the card key generation may
|
|
|
|
update CUR_TIME. */
|
2010-11-17 14:21:24 +01:00
|
|
|
err = gen_card_key (algo, keyno, 0, pub_keyblock, &cur_time, expire);
|
|
|
|
/* Get the pointer to the generated public subkey packet. */
|
2010-04-20 19:57:50 +02:00
|
|
|
if (!err)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2010-11-17 14:21:24 +01:00
|
|
|
PKT_public_key *sub_pk = NULL;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2010-11-17 14:21:24 +01:00
|
|
|
for (node = pub_keyblock; node; node = node->next)
|
|
|
|
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
|
|
|
|
sub_pk = node->pkt->pkt.public_key;
|
|
|
|
assert (sub_pk);
|
|
|
|
err = write_keybinding (pub_keyblock, pri_pk, sub_pk,
|
|
|
|
use, cur_time, NULL);
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
leave:
|
2010-04-20 19:57:50 +02:00
|
|
|
if (err)
|
|
|
|
log_error (_("Key generation failed: %s\n"), g10_errstr(err) );
|
2010-11-17 14:21:24 +01:00
|
|
|
else
|
|
|
|
write_status_text (STATUS_KEY_CREATED, "S");
|
2006-04-19 13:26:11 +02:00
|
|
|
release_parameter_list (para);
|
2010-11-17 14:21:24 +01:00
|
|
|
return err;
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
|
|
|
#endif /* !ENABLE_CARD_SUPPORT */
|
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
/*
|
2003-06-05 09:14:21 +02:00
|
|
|
* Write a keyblock to an output stream
|
|
|
|
*/
|
|
|
|
static int
|
2006-04-19 13:26:11 +02:00
|
|
|
write_keyblock( IOBUF out, KBNODE node )
|
2003-06-05 09:14:21 +02:00
|
|
|
{
|
2006-04-19 13:26:11 +02:00
|
|
|
for( ; node ; node = node->next )
|
|
|
|
{
|
|
|
|
if(!is_deleted_kbnode(node))
|
|
|
|
{
|
|
|
|
int rc = build_packet( out, node->pkt );
|
|
|
|
if( rc )
|
|
|
|
{
|
|
|
|
log_error("build_packet(%d) failed: %s\n",
|
|
|
|
node->pkt->pkttype, g10_errstr(rc) );
|
2006-04-19 15:24:36 +02:00
|
|
|
return rc;
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
|
|
|
|
return 0;
|
2003-06-05 09:14:21 +02:00
|
|
|
}
|
2003-06-27 22:53:09 +02:00
|
|
|
|
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
/* Note that timestamp is an in/out arg. */
|
2010-11-17 14:21:24 +01:00
|
|
|
static gpg_error_t
|
2011-02-03 16:31:42 +01:00
|
|
|
gen_card_key (int algo, int keyno, int is_primary, kbnode_t pub_root,
|
2010-11-17 14:21:24 +01:00
|
|
|
u32 *timestamp, u32 expireval)
|
2003-06-27 22:53:09 +02:00
|
|
|
{
|
2006-04-19 13:26:11 +02:00
|
|
|
#ifdef ENABLE_CARD_SUPPORT
|
2010-11-17 14:21:24 +01:00
|
|
|
gpg_error_t err;
|
2003-06-27 22:53:09 +02:00
|
|
|
struct agent_card_genkey_s info;
|
|
|
|
PACKET *pkt;
|
|
|
|
PKT_public_key *pk;
|
|
|
|
|
2010-11-17 14:21:24 +01:00
|
|
|
if (algo != PUBKEY_ALGO_RSA)
|
|
|
|
return gpg_error (GPG_ERR_PUBKEY_ALGO);
|
2003-06-27 22:53:09 +02:00
|
|
|
|
2010-11-17 14:21:24 +01:00
|
|
|
pk = xtrycalloc (1, sizeof *pk );
|
|
|
|
if (!pk)
|
|
|
|
return gpg_error_from_syserror ();
|
|
|
|
pkt = xtrycalloc (1, sizeof *pkt);
|
|
|
|
if (!pkt)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2010-11-17 14:21:24 +01:00
|
|
|
xfree (pk);
|
|
|
|
return gpg_error_from_syserror ();
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2010-11-17 14:21:24 +01:00
|
|
|
/* Note: SCD knows the serialnumber, thus there is no point in passing it. */
|
|
|
|
err = agent_scd_genkey (&info, keyno, 1, NULL, *timestamp);
|
2011-02-03 16:31:42 +01:00
|
|
|
/* The code below is not used because we force creation of
|
|
|
|
* the a card key (3rd arg).
|
2010-11-17 14:21:24 +01:00
|
|
|
* if (gpg_err_code (rc) == GPG_ERR_EEXIST)
|
|
|
|
* {
|
|
|
|
* tty_printf ("\n");
|
|
|
|
* log_error ("WARNING: key does already exists!\n");
|
|
|
|
* tty_printf ("\n");
|
|
|
|
* if ( cpr_get_answer_is_yes( "keygen.card.replace_key",
|
|
|
|
* _("Replace existing key? ")))
|
|
|
|
* rc = agent_scd_genkey (&info, keyno, 1);
|
|
|
|
* }
|
|
|
|
*/
|
|
|
|
if (!err && (!info.n || !info.e))
|
2003-06-27 22:53:09 +02:00
|
|
|
{
|
|
|
|
log_error ("communication error with SCD\n");
|
2006-08-16 12:47:53 +02:00
|
|
|
gcry_mpi_release (info.n);
|
|
|
|
gcry_mpi_release (info.e);
|
2010-11-17 14:21:24 +01:00
|
|
|
err = gpg_error (GPG_ERR_GENERAL);
|
|
|
|
}
|
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
log_error ("key generation failed: %s\n", gpg_strerror (err));
|
|
|
|
xfree (pkt);
|
|
|
|
xfree (pk);
|
|
|
|
return err;
|
2003-06-27 22:53:09 +02:00
|
|
|
}
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2014-10-19 14:09:04 +02:00
|
|
|
/* Send the learn command so that the agent creates a shadow key for
|
|
|
|
card key. We need to do that now so that we are able to create
|
|
|
|
the self-signatures. */
|
|
|
|
err = agent_learn ();
|
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
/* Oops: Card removed during generation. */
|
|
|
|
log_error (_("OpenPGP card not available: %s\n"), gpg_strerror (err));
|
|
|
|
xfree (pkt);
|
|
|
|
xfree (pk);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
if (*timestamp != info.created_at)
|
2010-11-17 14:21:24 +01:00
|
|
|
log_info ("NOTE: the key does not use the suggested creation date\n");
|
2007-07-05 18:58:19 +02:00
|
|
|
*timestamp = info.created_at;
|
2003-06-27 22:53:09 +02:00
|
|
|
|
2010-11-17 14:21:24 +01:00
|
|
|
pk->timestamp = info.created_at;
|
|
|
|
pk->version = 4;
|
2003-06-27 22:53:09 +02:00
|
|
|
if (expireval)
|
2010-11-17 14:21:24 +01:00
|
|
|
pk->expiredate = pk->timestamp + expireval;
|
|
|
|
pk->pubkey_algo = algo;
|
2003-06-27 22:53:09 +02:00
|
|
|
pk->pkey[0] = info.n;
|
2011-02-03 16:31:42 +01:00
|
|
|
pk->pkey[1] = info.e;
|
2006-06-27 16:30:59 +02:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
pkt->pkttype = is_primary ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY;
|
2003-06-27 22:53:09 +02:00
|
|
|
pkt->pkt.public_key = pk;
|
2010-11-17 14:21:24 +01:00
|
|
|
add_kbnode (pub_root, new_kbnode (pkt));
|
2003-06-27 22:53:09 +02:00
|
|
|
|
|
|
|
return 0;
|
2006-04-19 13:26:11 +02:00
|
|
|
#else
|
2014-02-10 23:12:28 +01:00
|
|
|
(void)algo;
|
|
|
|
(void)keyno;
|
|
|
|
(void)is_primary;
|
|
|
|
(void)pub_root;
|
|
|
|
(void)timestamp;
|
|
|
|
(void)expireval;
|
2010-04-20 19:57:50 +02:00
|
|
|
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
2006-04-19 13:26:11 +02:00
|
|
|
#endif /*!ENABLE_CARD_SUPPORT*/
|
2003-06-27 22:53:09 +02:00
|
|
|
}
|
|
|
|
|
2003-07-16 15:45:15 +02:00
|
|
|
|
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
static int
|
|
|
|
gen_card_key_with_backup (int algo, int keyno, int is_primary,
|
2010-04-20 19:57:50 +02:00
|
|
|
KBNODE pub_root, u32 timestamp,
|
2010-11-17 14:21:24 +01:00
|
|
|
u32 expireval, struct para_data_s *para)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2014-02-10 23:12:28 +01:00
|
|
|
#if ENABLE_CARD_SUPPORT && 0
|
|
|
|
/* FIXME: Move this to gpg-agent. */
|
2006-04-19 13:26:11 +02:00
|
|
|
int rc;
|
|
|
|
const char *s;
|
|
|
|
PACKET *pkt;
|
2006-08-16 12:47:53 +02:00
|
|
|
PKT_secret_key *sk, *sk_unprotected = NULL, *sk_protected = NULL;
|
2006-04-19 13:26:11 +02:00
|
|
|
PKT_public_key *pk;
|
|
|
|
size_t n;
|
|
|
|
int i;
|
2009-05-15 21:26:46 +02:00
|
|
|
unsigned int nbits;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2009-05-15 21:26:46 +02:00
|
|
|
/* Get the size of the key directly from the card. */
|
|
|
|
{
|
|
|
|
struct agent_card_info_s info;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2009-05-15 21:26:46 +02:00
|
|
|
memset (&info, 0, sizeof info);
|
|
|
|
if (!agent_scd_getattr ("KEY-ATTR", &info)
|
|
|
|
&& info.key_attr[1].algo)
|
|
|
|
nbits = info.key_attr[1].nbits;
|
|
|
|
else
|
|
|
|
nbits = 1024; /* All pre-v2.0 cards. */
|
|
|
|
agent_release_card_info (&info);
|
|
|
|
}
|
2006-04-19 13:26:11 +02:00
|
|
|
|
2009-05-15 21:26:46 +02:00
|
|
|
/* Create a key of this size in memory. */
|
|
|
|
rc = generate_raw_key (algo, nbits, timestamp,
|
2006-04-19 13:26:11 +02:00
|
|
|
&sk_unprotected, &sk_protected);
|
|
|
|
if (rc)
|
|
|
|
return rc;
|
|
|
|
|
2009-05-15 21:26:46 +02:00
|
|
|
/* Store the key to the card. */
|
2006-04-19 13:26:11 +02:00
|
|
|
rc = save_unprotected_key_to_card (sk_unprotected, keyno);
|
|
|
|
if (rc)
|
|
|
|
{
|
|
|
|
log_error (_("storing key onto card failed: %s\n"), g10_errstr (rc));
|
|
|
|
free_secret_key (sk_unprotected);
|
|
|
|
free_secret_key (sk_protected);
|
2010-01-08 20:18:49 +01:00
|
|
|
write_status_errcode ("save_key_to_card", rc);
|
2006-04-19 13:26:11 +02:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get rid of the secret key parameters and store the serial numer. */
|
|
|
|
sk = sk_unprotected;
|
|
|
|
n = pubkey_get_nskey (sk->pubkey_algo);
|
|
|
|
for (i=pubkey_get_npkey (sk->pubkey_algo); i < n; i++)
|
|
|
|
{
|
2006-08-16 12:47:53 +02:00
|
|
|
gcry_mpi_release (sk->skey[i]);
|
2006-04-19 13:26:11 +02:00
|
|
|
sk->skey[i] = NULL;
|
|
|
|
}
|
|
|
|
i = pubkey_get_npkey (sk->pubkey_algo);
|
2006-06-30 11:42:08 +02:00
|
|
|
sk->skey[i] = gcry_mpi_set_opaque (NULL, xstrdup ("dummydata"), 10*8);
|
2006-04-19 13:26:11 +02:00
|
|
|
sk->is_protected = 1;
|
|
|
|
sk->protect.s2k.mode = 1002;
|
|
|
|
s = get_parameter_value (para, pSERIALNO);
|
|
|
|
assert (s);
|
|
|
|
for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1];
|
|
|
|
sk->protect.ivlen++, s += 2)
|
|
|
|
sk->protect.iv[sk->protect.ivlen] = xtoi_2 (s);
|
|
|
|
|
|
|
|
/* Now write the *protected* secret key to the file. */
|
|
|
|
{
|
|
|
|
char name_buffer[50];
|
|
|
|
char *fname;
|
|
|
|
IOBUF fp;
|
|
|
|
mode_t oldmask;
|
|
|
|
|
|
|
|
keyid_from_sk (sk, NULL);
|
2009-05-17 15:08:18 +02:00
|
|
|
snprintf (name_buffer, sizeof name_buffer, "sk_%08lX%08lX.gpg",
|
|
|
|
(ulong)sk->keyid[0], (ulong)sk->keyid[1]);
|
2006-04-19 13:26:11 +02:00
|
|
|
|
|
|
|
fname = make_filename (backup_dir, name_buffer, NULL);
|
2014-06-25 20:25:28 +02:00
|
|
|
/* Note that the umask call is not anymore needed because
|
|
|
|
iobuf_create now takes care of it. However, it does not harm
|
|
|
|
and thus we keep it. */
|
2006-04-19 13:26:11 +02:00
|
|
|
oldmask = umask (077);
|
|
|
|
if (is_secured_filename (fname))
|
|
|
|
{
|
|
|
|
fp = NULL;
|
2010-04-01 15:24:55 +02:00
|
|
|
gpg_err_set_errno (EPERM);
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
|
|
|
else
|
2014-06-25 20:25:28 +02:00
|
|
|
fp = iobuf_create (fname, 1);
|
2006-04-19 13:26:11 +02:00
|
|
|
umask (oldmask);
|
2011-02-03 16:31:42 +01:00
|
|
|
if (!fp)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
2006-09-14 18:50:33 +02:00
|
|
|
rc = gpg_error_from_syserror ();
|
2012-06-05 19:29:22 +02:00
|
|
|
log_error (_("can't create backup file '%s': %s\n"),
|
2006-04-19 13:26:11 +02:00
|
|
|
fname, strerror(errno) );
|
|
|
|
xfree (fname);
|
|
|
|
free_secret_key (sk_unprotected);
|
|
|
|
free_secret_key (sk_protected);
|
2006-08-16 12:47:53 +02:00
|
|
|
return rc;
|
2006-04-19 13:26:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pkt = xcalloc (1, sizeof *pkt);
|
|
|
|
pkt->pkttype = PKT_SECRET_KEY;
|
|
|
|
pkt->pkt.secret_key = sk_protected;
|
|
|
|
sk_protected = NULL;
|
|
|
|
|
|
|
|
rc = build_packet (fp, pkt);
|
|
|
|
if (rc)
|
|
|
|
{
|
|
|
|
log_error("build packet failed: %s\n", g10_errstr(rc) );
|
|
|
|
iobuf_cancel (fp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-08-16 12:47:53 +02:00
|
|
|
unsigned char array[MAX_FINGERPRINT_LEN];
|
2006-04-19 13:26:11 +02:00
|
|
|
char *fprbuf, *p;
|
2011-02-03 16:31:42 +01:00
|
|
|
|
2006-04-19 13:26:11 +02:00
|
|
|
iobuf_close (fp);
|
2010-03-08 18:05:37 +01:00
|
|
|
iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)fname);
|
2014-10-10 15:29:42 +02:00
|
|
|
log_info (_("Note: backup of card key saved to '%s'\n"), fname);
|
2006-04-19 13:26:11 +02:00
|
|
|
|
|
|
|
fingerprint_from_sk (sk, array, &n);
|
|
|
|
p = fprbuf = xmalloc (MAX_FINGERPRINT_LEN*2 + 1 + 1);
|
|
|
|
for (i=0; i < n ; i++, p += 2)
|
|
|
|
sprintf (p, "%02X", array[i]);
|
|
|
|
*p++ = ' ';
|
|
|
|
*p = 0;
|
|
|
|
|
|
|
|
write_status_text_and_buffer (STATUS_BACKUP_KEY_CREATED,
|
|
|
|
fprbuf,
|
|
|
|
fname, strlen (fname),
|
|
|
|
0);
|
|
|
|
xfree (fprbuf);
|
|
|
|
}
|
|
|
|
free_packet (pkt);
|
|
|
|
xfree (pkt);
|
|
|
|
xfree (fname);
|
|
|
|
if (rc)
|
|
|
|
{
|
|
|
|
free_secret_key (sk_unprotected);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create the public key from the secret key. */
|
|
|
|
pk = xcalloc (1, sizeof *pk );
|
|
|
|
pk->timestamp = sk->timestamp;
|
|
|
|
pk->version = sk->version;
|
|
|
|
if (expireval)
|
|
|
|
pk->expiredate = sk->expiredate = sk->timestamp + expireval;
|
|
|
|
pk->pubkey_algo = sk->pubkey_algo;
|
|
|
|
n = pubkey_get_npkey (sk->pubkey_algo);
|
|
|
|
for (i=0; i < n; i++)
|
|
|
|
pk->pkey[i] = mpi_copy (sk->skey[i]);
|
|
|
|
|
|
|
|
/* Build packets and add them to the node lists. */
|
|
|
|
pkt = xcalloc (1,sizeof *pkt);
|
|
|
|
pkt->pkttype = is_primary ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY;
|
|
|
|
pkt->pkt.public_key = pk;
|
|
|
|
add_kbnode(pub_root, new_kbnode( pkt ));
|
|
|
|
|
|
|
|
pkt = xcalloc (1,sizeof *pkt);
|
|
|
|
pkt->pkttype = is_primary ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY;
|
|
|
|
pkt->pkt.secret_key = sk;
|
|
|
|
add_kbnode(sec_root, new_kbnode( pkt ));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
#else
|
2014-02-10 23:12:28 +01:00
|
|
|
# if __GCC__ && ENABLE_CARD_SUPPORT
|
|
|
|
# warning Card support still missing
|
|
|
|
# endif
|
|
|
|
(void)algo;
|
|
|
|
(void)keyno;
|
|
|
|
(void)is_primary;
|
|
|
|
(void)pub_root;
|
|
|
|
(void)timestamp;
|
|
|
|
(void)expireval;
|
|
|
|
(void)para;
|
2010-04-20 19:57:50 +02:00
|
|
|
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
2006-04-19 13:26:11 +02:00
|
|
|
#endif /*!ENABLE_CARD_SUPPORT*/
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-17 14:21:24 +01:00
|
|
|
#if 0
|
2006-04-19 13:26:11 +02:00
|
|
|
int
|
2010-11-17 14:21:24 +01:00
|
|
|
save_unprotected_key_to_card (PKT_public_key *sk, int keyno)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
unsigned char *rsa_n = NULL;
|
|
|
|
unsigned char *rsa_e = NULL;
|
|
|
|
unsigned char *rsa_p = NULL;
|
|
|
|
unsigned char *rsa_q = NULL;
|
2006-11-21 12:00:14 +01:00
|
|
|
size_t rsa_n_len, rsa_e_len, rsa_p_len, rsa_q_len;
|
2006-04-19 13:26:11 +02:00
|
|
|
unsigned char *sexp = NULL;
|
|
|
|
unsigned char *p;
|
|
|
|
char numbuf[55], numbuf2[50];
|
|
|
|
|
|
|
|
assert (is_RSA (sk->pubkey_algo));
|
|
|
|
assert (!sk->is_protected);
|
|
|
|
|
|
|
|
/* Copy the parameters into straight buffers. */
|
2006-08-16 12:47:53 +02:00
|
|
|
gcry_mpi_aprint (GCRYMPI_FMT_USG, &rsa_n, &rsa_n_len, sk->skey[0]);
|
|
|
|
gcry_mpi_aprint (GCRYMPI_FMT_USG, &rsa_e, &rsa_e_len, sk->skey[1]);
|
2007-07-05 18:58:19 +02:00
|
|
|
gcry_mpi_aprint (GCRYMPI_FMT_USG, &rsa_p, &rsa_p_len, sk->skey[3]);
|
|
|
|
gcry_mpi_aprint (GCRYMPI_FMT_USG, &rsa_q, &rsa_q_len, sk->skey[4]);
|
|
|
|
if (!rsa_n || !rsa_e || !rsa_p || !rsa_q)
|
2006-04-19 13:26:11 +02:00
|
|
|
{
|
|
|
|
rc = G10ERR_INV_ARG;
|
|
|
|
goto leave;
|
|
|
|
}
|
|
|
|
|
2007-07-05 18:58:19 +02:00
|
|
|
/* Put the key into an S-expression. */
|
2006-04-19 13:26:11 +02:00
|
|
|
sexp = p = xmalloc_secure (30
|
|
|
|
+ rsa_n_len + rsa_e_len + rsa_p_len + rsa_q_len
|
|
|
|
+ 4*sizeof (numbuf) + 25 + sizeof(numbuf) + 20);
|
|
|
|
|
|
|
|
p = stpcpy (p,"(11:private-key(3:rsa(1:n");
|
2006-11-21 12:00:14 +01:00
|
|
|
sprintf (numbuf, "%u:", (unsigned int)rsa_n_len);
|
2006-04-19 13:26:11 +02:00
|
|
|
p = stpcpy (p, numbuf);
|
|
|
|
memcpy (p, rsa_n, rsa_n_len);
|
|
|
|
p += rsa_n_len;
|
|
|
|
|
2006-11-21 12:00:14 +01:00
|
|
|
sprintf (numbuf, ")(1:e%u:", (unsigned int)rsa_e_len);
|
2006-04-19 13:26:11 +02:00
|
|
|
p = stpcpy (p, numbuf);
|
|
|
|
memcpy (p, rsa_e, rsa_e_len);
|
|
|
|
p += rsa_e_len;
|
|
|
|
|
2006-11-21 12:00:14 +01:00
|
|
|
sprintf (numbuf, ")(1:p%u:", (unsigned int)rsa_p_len);
|
2006-04-19 13:26:11 +02:00
|
|
|
p = stpcpy (p, numbuf);
|
|
|
|
memcpy (p, rsa_p, rsa_p_len);
|
|
|
|
p += rsa_p_len;
|
|
|
|
|
2006-11-21 12:00:14 +01:00
|
|
|
sprintf (numbuf, ")(1:q%u:", (unsigned int)rsa_q_len);
|
2006-04-19 13:26:11 +02:00
|
|
|
p = stpcpy (p, numbuf);
|
|
|
|
memcpy (p, rsa_q, rsa_q_len);
|
|
|
|
p += rsa_q_len;
|
|
|
|
|
|
|
|
p = stpcpy (p,"))(10:created-at");
|
|
|
|
sprintf (numbuf2, "%lu", (unsigned long)sk->timestamp);
|
|
|
|
sprintf (numbuf, "%lu:", (unsigned long)strlen (numbuf2));
|
|
|
|
p = stpcpy (stpcpy (stpcpy (p, numbuf), numbuf2), "))");
|
|
|
|
|
|
|
|
/* Fixme: Unfortunately we don't have the serialnumber available -
|
2011-02-03 16:31:42 +01:00
|
|
|
thus we can't pass it down to the agent. */
|
2006-04-19 13:26:11 +02:00
|
|
|
rc = agent_scd_writekey (keyno, NULL, sexp, p - sexp);
|
|
|
|
|
|
|
|
leave:
|
|
|
|
xfree (sexp);
|
|
|
|
xfree (rsa_n);
|
|
|
|
xfree (rsa_e);
|
|
|
|
xfree (rsa_p);
|
|
|
|
xfree (rsa_q);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
#endif /*ENABLE_CARD_SUPPORT*/
|