mirror of
git://git.gnupg.org/gnupg.git
synced 2025-04-17 15:44:34 +02:00
Fixed card key generation of gpg2.
Reveal less information about timings while generating a key.
This commit is contained in:
parent
fa84b8cd82
commit
4631bc8ddf
@ -1,3 +1,7 @@
|
|||||||
|
2007-07-05 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* configure.ac: Require libassuan 1.0.2.
|
||||||
|
|
||||||
2007-07-05 Marcus Brinkmann <marcus@g10code.de>
|
2007-07-05 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* configure.ac: Invoke AM_LANGINFO_CODESET.
|
* configure.ac: Invoke AM_LANGINFO_CODESET.
|
||||||
|
3
NEWS
3
NEWS
@ -11,6 +11,9 @@ Noteworthy changes in version 2.0.5
|
|||||||
* The command --gen-key may now be used instead of the
|
* The command --gen-key may now be used instead of the
|
||||||
gpgsm-gencert.sh script.
|
gpgsm-gencert.sh script.
|
||||||
|
|
||||||
|
* Changed key generation to reveal less information about the
|
||||||
|
machine. Bug fixes for gpg2's card key generation.
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 2.0.4 (2007-05-09)
|
Noteworthy changes in version 2.0.4 (2007-05-09)
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2007-07-05 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* call-scd.c (struct inq_needpin_s): New.
|
||||||
|
(inq_needpin): Pass unknown inquiries up.
|
||||||
|
|
||||||
2007-07-04 Werner Koch <wk@g10code.com>
|
2007-07-04 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* gpg-agent.c (TIMERTICK_INTERVAL): New.
|
* gpg-agent.c (TIMERTICK_INTERVAL): New.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* call-scd.c - fork of the scdaemon to do SC operations
|
/* call-scd.c - fork of the scdaemon to do SC operations
|
||||||
* Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
|
* Copyright (C) 2001, 2002, 2005, 2007 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -79,6 +79,8 @@ struct inq_needpin_s
|
|||||||
assuan_context_t ctx;
|
assuan_context_t ctx;
|
||||||
int (*getpin_cb)(void *, const char *, char*, size_t);
|
int (*getpin_cb)(void *, const char *, char*, size_t);
|
||||||
void *getpin_cb_arg;
|
void *getpin_cb_arg;
|
||||||
|
assuan_context_t passthru; /* If not NULL, pass unknown inquiries
|
||||||
|
up to the caller. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -731,6 +733,36 @@ inq_needpin (void *opaque, const char *line)
|
|||||||
{
|
{
|
||||||
rc = parm->getpin_cb (parm->getpin_cb_arg, "", NULL, 0);
|
rc = parm->getpin_cb (parm->getpin_cb_arg, "", NULL, 0);
|
||||||
}
|
}
|
||||||
|
else if (parm->passthru)
|
||||||
|
{
|
||||||
|
unsigned char *value;
|
||||||
|
size_t valuelen;
|
||||||
|
int rest;
|
||||||
|
int needrest = !strncmp (line, "KEYDATA", 8);
|
||||||
|
|
||||||
|
/* Pass the inquiry up to our caller. We limit the maximum
|
||||||
|
amount to an arbitrary value. As we know that the KEYDATA
|
||||||
|
enquiry is pretty sensitive we disable logging then */
|
||||||
|
if ((rest = (needrest
|
||||||
|
&& !assuan_get_flag (parm->passthru, ASSUAN_CONFIDENTIAL))))
|
||||||
|
assuan_begin_confidential (parm->passthru);
|
||||||
|
rc = assuan_inquire (parm->passthru, line, &value, &valuelen, 8096);
|
||||||
|
if (rest)
|
||||||
|
assuan_end_confidential (parm->passthru);
|
||||||
|
if (!rc)
|
||||||
|
{
|
||||||
|
if ((rest = (needrest
|
||||||
|
&& !assuan_get_flag (parm->ctx, ASSUAN_CONFIDENTIAL))))
|
||||||
|
assuan_begin_confidential (parm->ctx);
|
||||||
|
rc = assuan_send_data (parm->ctx, value, valuelen);
|
||||||
|
if (rest)
|
||||||
|
assuan_end_confidential (parm->ctx);
|
||||||
|
xfree (value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
log_error ("error forwarding inquiry `%s': %s\n",
|
||||||
|
line, gpg_strerror (rc));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log_error ("unsupported inquiry `%s'\n", line);
|
log_error ("unsupported inquiry `%s'\n", line);
|
||||||
@ -780,6 +812,7 @@ agent_card_pksign (ctrl_t ctrl,
|
|||||||
inqparm.ctx = ctrl->scd_local->ctx;
|
inqparm.ctx = ctrl->scd_local->ctx;
|
||||||
inqparm.getpin_cb = getpin_cb;
|
inqparm.getpin_cb = getpin_cb;
|
||||||
inqparm.getpin_cb_arg = getpin_cb_arg;
|
inqparm.getpin_cb_arg = getpin_cb_arg;
|
||||||
|
inqparm.passthru = 0;
|
||||||
snprintf (line, DIM(line)-1,
|
snprintf (line, DIM(line)-1,
|
||||||
ctrl->use_auth_call? "PKAUTH %s":"PKSIGN %s", keyid);
|
ctrl->use_auth_call? "PKAUTH %s":"PKSIGN %s", keyid);
|
||||||
line[DIM(line)-1] = 0;
|
line[DIM(line)-1] = 0;
|
||||||
@ -850,6 +883,7 @@ agent_card_pkdecrypt (ctrl_t ctrl,
|
|||||||
inqparm.ctx = ctrl->scd_local->ctx;
|
inqparm.ctx = ctrl->scd_local->ctx;
|
||||||
inqparm.getpin_cb = getpin_cb;
|
inqparm.getpin_cb = getpin_cb;
|
||||||
inqparm.getpin_cb_arg = getpin_cb_arg;
|
inqparm.getpin_cb_arg = getpin_cb_arg;
|
||||||
|
inqparm.passthru = 0;
|
||||||
snprintf (line, DIM(line)-1, "PKDECRYPT %s", keyid);
|
snprintf (line, DIM(line)-1, "PKDECRYPT %s", keyid);
|
||||||
line[DIM(line)-1] = 0;
|
line[DIM(line)-1] = 0;
|
||||||
rc = assuan_transact (ctrl->scd_local->ctx, line,
|
rc = assuan_transact (ctrl->scd_local->ctx, line,
|
||||||
@ -1065,8 +1099,8 @@ pass_data_thru (void *opaque, const void *buffer, size_t length)
|
|||||||
|
|
||||||
/* Send the line CMDLINE with command for the SCDdaemon to it and send
|
/* Send the line CMDLINE with command for the SCDdaemon to it and send
|
||||||
all status messages back. This command is used as a general quoting
|
all status messages back. This command is used as a general quoting
|
||||||
mechanism to pass everything verbatim to SCDAEMOPN. The PIN
|
mechanism to pass everything verbatim to SCDAEMON. The PIN
|
||||||
inquirey is handled inside gpg-agent. */
|
inquiry is handled inside gpg-agent. */
|
||||||
int
|
int
|
||||||
agent_card_scd (ctrl_t ctrl, const char *cmdline,
|
agent_card_scd (ctrl_t ctrl, const char *cmdline,
|
||||||
int (*getpin_cb)(void *, const char *, char*, size_t),
|
int (*getpin_cb)(void *, const char *, char*, size_t),
|
||||||
@ -1082,6 +1116,7 @@ agent_card_scd (ctrl_t ctrl, const char *cmdline,
|
|||||||
inqparm.ctx = ctrl->scd_local->ctx;
|
inqparm.ctx = ctrl->scd_local->ctx;
|
||||||
inqparm.getpin_cb = getpin_cb;
|
inqparm.getpin_cb = getpin_cb;
|
||||||
inqparm.getpin_cb_arg = getpin_cb_arg;
|
inqparm.getpin_cb_arg = getpin_cb_arg;
|
||||||
|
inqparm.passthru = assuan_context;
|
||||||
rc = assuan_transact (ctrl->scd_local->ctx, cmdline,
|
rc = assuan_transact (ctrl->scd_local->ctx, cmdline,
|
||||||
pass_data_thru, assuan_context,
|
pass_data_thru, assuan_context,
|
||||||
inq_needpin, &inqparm,
|
inq_needpin, &inqparm,
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2007-07-05 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* t-gettime.c: New.
|
||||||
|
* gettime.c (isotime2epoch, epoch2isotime): New.
|
||||||
|
|
||||||
2007-07-04 Werner Koch <wk@g10code.com>
|
2007-07-04 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* estream.c (es_init_do): Do not throw an error if pth as already
|
* estream.c (es_init_do): Do not throw an error if pth as already
|
||||||
|
@ -81,13 +81,15 @@ libgpgrl_a_SOURCES = \
|
|||||||
#
|
#
|
||||||
# Module tests
|
# Module tests
|
||||||
#
|
#
|
||||||
module_tests = t-convert
|
module_tests = t-convert t-gettime
|
||||||
|
|
||||||
t_common_ldadd = ../jnlib/libjnlib.a $(libcommon) ../gl/libgnu.a \
|
t_common_ldadd = $(libcommon) ../jnlib/libjnlib.a ../gl/libgnu.a \
|
||||||
$(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV)
|
$(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV)
|
||||||
|
|
||||||
t_convert_DEPENDENCIES = convert.c libcommon.a
|
t_convert_DEPENDENCIES = convert.c libcommon.a
|
||||||
t_convert_LDADD = $(t_common_ldadd)
|
t_convert_LDADD = $(t_common_ldadd)
|
||||||
|
t_gettime_DEPENDENCIES = gettime.c libcommon.a
|
||||||
|
t_gettime_LDADD = $(t_common_ldadd)
|
||||||
|
|
||||||
|
|
||||||
$(PROGRAMS): ../jnlib/libjnlib.a $(libcommon) ../gl/libgnu.a
|
$(PROGRAMS): ../jnlib/libjnlib.a $(libcommon) ../gl/libgnu.a
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* gettime.c - Wrapper for time functions
|
/* gettime.c - Wrapper for time functions
|
||||||
* Copyright (C) 1998, 2002 Free Software Foundation, Inc.
|
* Copyright (C) 1998, 2002, 2007 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -20,6 +20,7 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <ctype.h>
|
||||||
#ifdef HAVE_LANGINFO_H
|
#ifdef HAVE_LANGINFO_H
|
||||||
#include <langinfo.h>
|
#include <langinfo.h>
|
||||||
#endif
|
#endif
|
||||||
@ -64,7 +65,7 @@ gnupg_get_isotime (gnupg_isotime_t timebuf)
|
|||||||
#else
|
#else
|
||||||
tp = gmtime (&atime);
|
tp = gmtime (&atime);
|
||||||
#endif
|
#endif
|
||||||
sprintf (timebuf,"%04d%02d%02dT%02d%02d%02d",
|
snprintf (timebuf, 16, "%04d%02d%02dT%02d%02d%02d",
|
||||||
1900 + tp->tm_year, tp->tm_mon+1, tp->tm_mday,
|
1900 + tp->tm_year, tp->tm_mon+1, tp->tm_mday,
|
||||||
tp->tm_hour, tp->tm_min, tp->tm_sec);
|
tp->tm_hour, tp->tm_min, tp->tm_sec);
|
||||||
}
|
}
|
||||||
@ -164,6 +165,78 @@ scan_isodatestr( const char *string )
|
|||||||
return stamp;
|
return stamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Scan am ISO timestamp and return a epoch based timestamp. The only
|
||||||
|
supported format is "yyyymmddThhmmss" delimited by white space, nul, a
|
||||||
|
colon or a comma. Returns (time_t)(-1) for an invalid string. */
|
||||||
|
time_t
|
||||||
|
isotime2epoch (const char *string)
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
int year, month, day, hour, minu, sec;
|
||||||
|
struct tm tmbuf;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!*string)
|
||||||
|
return (time_t)(-1);
|
||||||
|
for (s=string, i=0; i < 8; i++, s++)
|
||||||
|
if (!digitp (s))
|
||||||
|
return (time_t)(-1);
|
||||||
|
if (*s != 'T')
|
||||||
|
return (time_t)(-1);
|
||||||
|
for (s++, i=9; i < 15; i++, s++)
|
||||||
|
if (!digitp (s))
|
||||||
|
return (time_t)(-1);
|
||||||
|
if ( !(!*s || (isascii (*s) && isspace(*s)) || *s == ':' || *s == ','))
|
||||||
|
return (time_t)(-1); /* Wrong delimiter. */
|
||||||
|
|
||||||
|
year = atoi_4 (string);
|
||||||
|
month = atoi_2 (string + 4);
|
||||||
|
day = atoi_2 (string + 6);
|
||||||
|
hour = atoi_2 (string + 9);
|
||||||
|
minu = atoi_2 (string + 11);
|
||||||
|
sec = atoi_2 (string + 13);
|
||||||
|
|
||||||
|
/* Basic checks. */
|
||||||
|
if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31
|
||||||
|
|| hour > 23 || minu > 59 || sec > 61 )
|
||||||
|
return (time_t)(-1);
|
||||||
|
|
||||||
|
memset (&tmbuf, 0, sizeof tmbuf);
|
||||||
|
tmbuf.tm_sec = sec;
|
||||||
|
tmbuf.tm_min = minu;
|
||||||
|
tmbuf.tm_hour = hour;
|
||||||
|
tmbuf.tm_mday = day;
|
||||||
|
tmbuf.tm_mon = month-1;
|
||||||
|
tmbuf.tm_year = year - 1900;
|
||||||
|
tmbuf.tm_isdst = -1;
|
||||||
|
return timegm (&tmbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Convert an Epoch time to an iso time stamp. */
|
||||||
|
void
|
||||||
|
epoch2isotime (gnupg_isotime_t timebuf, time_t atime)
|
||||||
|
{
|
||||||
|
if (atime < 0)
|
||||||
|
*timebuf = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct tm *tp;
|
||||||
|
#ifdef HAVE_GMTIME_R
|
||||||
|
struct tm tmbuf;
|
||||||
|
|
||||||
|
tp = gmtime_r (&atime, &tmbuf);
|
||||||
|
#else
|
||||||
|
tp = gmtime (&atime);
|
||||||
|
#endif
|
||||||
|
snprintf (timebuf, 16, "%04d%02d%02dT%02d%02d%02d",
|
||||||
|
1900 + tp->tm_year, tp->tm_mon+1, tp->tm_mday,
|
||||||
|
tp->tm_hour, tp->tm_min, tp->tm_sec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
u32
|
u32
|
||||||
add_days_to_timestamp( u32 stamp, u16 days )
|
add_days_to_timestamp( u32 stamp, u16 days )
|
||||||
|
98
common/t-gettime.c
Normal file
98
common/t-gettime.c
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/* t-gettime.c - Module test for gettime.c
|
||||||
|
* Copyright (C) 2007 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (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
|
||||||
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#define pass() do { ; } while(0)
|
||||||
|
#define fail(a) do { fprintf (stderr, "%s:%d: test %d failed\n",\
|
||||||
|
__FILE__,__LINE__, (a)); \
|
||||||
|
errcount++; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
static int verbose;
|
||||||
|
static int errcount;
|
||||||
|
#define INVALID ((time_t)(-1))
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_isotime2epoch (void)
|
||||||
|
{
|
||||||
|
struct { const char *string; time_t expected; } array [] = {
|
||||||
|
{ "19700101T000001", 1 },
|
||||||
|
{ "19700101T235959", 86399 },
|
||||||
|
{ "19980815T143712", 903191832 },
|
||||||
|
{ "19700101T000000", 0 },
|
||||||
|
{ "19691231T235959", INVALID },
|
||||||
|
{ "19000101T000000", INVALID },
|
||||||
|
{ "", INVALID },
|
||||||
|
{ "19000101T00000", INVALID },
|
||||||
|
{ "20010101t123456", INVALID },
|
||||||
|
{ "20010101T123456", 978352496 },
|
||||||
|
{ "20070629T160000", 1183132800 },
|
||||||
|
{ "20070629T160000:", 1183132800 },
|
||||||
|
{ "20070629T160000,", 1183132800 },
|
||||||
|
{ "20070629T160000 ", 1183132800 },
|
||||||
|
{ "20070629T160000\n", 1183132800 },
|
||||||
|
{ "20070629T160000.", INVALID },
|
||||||
|
{ NULL, 0 }
|
||||||
|
};
|
||||||
|
int idx;
|
||||||
|
u32 val;
|
||||||
|
gnupg_isotime_t tbuf;
|
||||||
|
|
||||||
|
for (idx=0; array[idx].string; idx++)
|
||||||
|
{
|
||||||
|
val = isotime2epoch (array[idx].string);
|
||||||
|
if (val != array[idx].expected )
|
||||||
|
{
|
||||||
|
fail (idx);
|
||||||
|
if (verbose)
|
||||||
|
fprintf (stderr, "string `%s' exp: %ld got: %ld\n",
|
||||||
|
array[idx].string, (long)array[idx].expected,
|
||||||
|
(long)val);
|
||||||
|
}
|
||||||
|
if (array[idx].expected != INVALID)
|
||||||
|
{
|
||||||
|
epoch2isotime (tbuf, val);
|
||||||
|
if (strlen (tbuf) != 15)
|
||||||
|
fail (idx);
|
||||||
|
if (strncmp (array[idx].string, tbuf, 15))
|
||||||
|
fail (idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc > 1 && !strcmp (argv[1], "--verbose"))
|
||||||
|
verbose = 1;
|
||||||
|
|
||||||
|
test_isotime2epoch ();
|
||||||
|
|
||||||
|
return !!errcount;
|
||||||
|
}
|
||||||
|
|
@ -103,6 +103,8 @@ void gnupg_set_time (time_t newtime, int freeze);
|
|||||||
int gnupg_faked_time_p (void);
|
int gnupg_faked_time_p (void);
|
||||||
u32 make_timestamp (void);
|
u32 make_timestamp (void);
|
||||||
u32 scan_isodatestr (const char *string);
|
u32 scan_isodatestr (const char *string);
|
||||||
|
time_t isotime2epoch (const char *string);
|
||||||
|
void epoch2isotime (gnupg_isotime_t timebuf, time_t atime);
|
||||||
u32 add_days_to_timestamp (u32 stamp, u16 days);
|
u32 add_days_to_timestamp (u32 stamp, u16 days);
|
||||||
const char *strtimevalue (u32 stamp);
|
const char *strtimevalue (u32 stamp);
|
||||||
const char *strtimestamp (u32 stamp); /* GMT */
|
const char *strtimestamp (u32 stamp); /* GMT */
|
||||||
|
@ -43,7 +43,7 @@ NEED_LIBGCRYPT_API=1
|
|||||||
NEED_LIBGCRYPT_VERSION=1.2.2
|
NEED_LIBGCRYPT_VERSION=1.2.2
|
||||||
|
|
||||||
NEED_LIBASSUAN_API=1
|
NEED_LIBASSUAN_API=1
|
||||||
NEED_LIBASSUAN_VERSION=0.9.3
|
NEED_LIBASSUAN_VERSION=1.0.2
|
||||||
|
|
||||||
NEED_KSBA_API=1
|
NEED_KSBA_API=1
|
||||||
NEED_KSBA_VERSION=1.0.2
|
NEED_KSBA_VERSION=1.0.2
|
||||||
|
@ -819,6 +819,13 @@ The format of this file is as follows:
|
|||||||
may either be entered in ISO date format (2000-08-15) or as
|
may either be entered in ISO date format (2000-08-15) or as
|
||||||
number of days, weeks, month or years. Without a letter days
|
number of days, weeks, month or years. Without a letter days
|
||||||
are assumed.
|
are assumed.
|
||||||
|
Creation-Date: <iso-date>
|
||||||
|
Set the creation date of the key as stored in the key
|
||||||
|
information and which is also part of the fingerprint
|
||||||
|
calculation. Either a date like "1986-04-26" or a full
|
||||||
|
timestamp like "19860426T042640" may be used. The time is
|
||||||
|
considered to be UTC. If it is not given the current time
|
||||||
|
is used.
|
||||||
Preferences: <string>
|
Preferences: <string>
|
||||||
Set the cipher, hash, and compression preference values for
|
Set the cipher, hash, and compression preference values for
|
||||||
this key. This expects the same type of string as "setpref"
|
this key. This expects the same type of string as "setpref"
|
||||||
|
@ -176,10 +176,10 @@ or other purposes and don't have a corresponding certificate.
|
|||||||
|
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* gpg 1.4 vs. 1.9:: Relationship between the two branches.
|
* GnuPG-1 and GnuPG-2:: Relationship between the two branches.
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
@node gpg 1.4 vs. 1.9
|
@node GnuPG-1 and GnuPG-2
|
||||||
@subsection Relationship between the two branches.
|
@subsection Relationship between the two branches.
|
||||||
|
|
||||||
Here is a little picture showing how the components work together:
|
Here is a little picture showing how the components work together:
|
||||||
|
@ -1,3 +1,27 @@
|
|||||||
|
2007-07-05 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* card-util.c (card_generate_subkey, card_store_subkey): Enable
|
||||||
|
the code also for GnuPG-2.
|
||||||
|
|
||||||
|
* keygen.c (make_backsig): Add arg TIMESTAMP.
|
||||||
|
(write_keybinding): Add arg TIMESTAMP, pass it to make_backsig.
|
||||||
|
(write_direct_sig, write_selfsigs): Add arg TIMESTAMP.
|
||||||
|
(gen_elg, gen_dsa, gen_rsa): Add arg TIMESTAMP.
|
||||||
|
(do_create): Ditto.
|
||||||
|
(do_generate_keypair): Use the same timestamp for key creation
|
||||||
|
time and all key signatures. Return an error if write_direct_sig
|
||||||
|
for the secret key fails.
|
||||||
|
(generate_subkeypair): Ditto.
|
||||||
|
(gen_card_key): New arg TIMESTAMP.
|
||||||
|
(generate_card_subkeypair): Pass current time to gen_card_key.
|
||||||
|
(gen_card_key_with_backup): New arg TIMESTAMP.
|
||||||
|
(read_parameter_file): Add option Creation-Date.
|
||||||
|
(parse_creation_string): New.
|
||||||
|
(do_generate_keypair): Use the Creation-Date if available.
|
||||||
|
(save_unprotected_key_to_card): Use P for P and not D.
|
||||||
|
* call-agent.c (agent_scd_genkey): Add arg CREATETIME.
|
||||||
|
* keyedit.c (menu_backsign): Use the same timestamp for all backsigs.
|
||||||
|
|
||||||
2007-06-26 Werner Koch <wk@g10code.com>
|
2007-06-26 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* openfile.c (try_make_homedir): Support W32; use standard_homedir.
|
* openfile.c (try_make_homedir): Support W32; use standard_homedir.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* call-agent.c - divert operations to the agent
|
/* call-agent.c - divert operations to the agent
|
||||||
* Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
|
* Copyright (C) 2001, 2002, 2003, 2006, 2007 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -498,21 +498,32 @@ scd_genkey_cb (void *opaque, const char *line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Send a GENKEY command to the SCdaemon. SERIALNO is not used in
|
/* Send a GENKEY command to the SCdaemon. SERIALNO is not used in
|
||||||
this implementation. */
|
this implementation. If CREATEDATE has been given, it will be
|
||||||
|
passed to SCDAEMON so that the key can be created with this
|
||||||
|
timestamp; note the user needs to use the returned timestamp as old
|
||||||
|
versions of scddaemon don't support this option. */
|
||||||
int
|
int
|
||||||
agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
|
agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
|
||||||
const char *serialno)
|
const char *serialno, u32 createtime)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
char line[ASSUAN_LINELENGTH];
|
char line[ASSUAN_LINELENGTH];
|
||||||
|
gnupg_isotime_t tbuf;
|
||||||
|
|
||||||
rc = start_agent ();
|
rc = start_agent ();
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
if (createtime)
|
||||||
|
epoch2isotime (tbuf, createtime);
|
||||||
|
else
|
||||||
|
*tbuf = 0;
|
||||||
|
|
||||||
memset (info, 0, sizeof *info);
|
memset (info, 0, sizeof *info);
|
||||||
snprintf (line, DIM(line)-1, "SCD GENKEY %s%d",
|
snprintf (line, DIM(line)-1, "SCD GENKEY %s%s %s %d",
|
||||||
force? "--force ":"", keyno);
|
*tbuf? "--timestamp=":"", tbuf,
|
||||||
|
force? "--force":"",
|
||||||
|
keyno);
|
||||||
line[DIM(line)-1] = 0;
|
line[DIM(line)-1] = 0;
|
||||||
|
|
||||||
memset (info, 0, sizeof *info);
|
memset (info, 0, sizeof *info);
|
||||||
|
@ -82,7 +82,7 @@ int agent_scd_writekey (int keyno, const char *serialno,
|
|||||||
|
|
||||||
/* Send a GENKEY command to the SCdaemon. */
|
/* Send a GENKEY command to the SCdaemon. */
|
||||||
int agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
|
int agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
|
||||||
const char *serialno);
|
const char *serialno, u32 createtime);
|
||||||
|
|
||||||
/* Send a PKSIGN command to the SCdaemon. */
|
/* Send a PKSIGN command to the SCdaemon. */
|
||||||
int agent_scd_pksign (const char *keyid, int hashalgo,
|
int agent_scd_pksign (const char *keyid, int hashalgo,
|
||||||
|
@ -999,7 +999,7 @@ restore_forced_chv1 (int *forced_chv1)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GNUPG_MAJOR_VERSION == 1
|
|
||||||
/* Helper for the key generation/edit functions. */
|
/* Helper for the key generation/edit functions. */
|
||||||
static void
|
static void
|
||||||
show_card_key_info (struct agent_card_info_s *info)
|
show_card_key_info (struct agent_card_info_s *info)
|
||||||
@ -1012,9 +1012,8 @@ show_card_key_info (struct agent_card_info_s *info)
|
|||||||
print_sha1_fpr (NULL, info->fpr3valid? info->fpr3:NULL);
|
print_sha1_fpr (NULL, info->fpr3valid? info->fpr3:NULL);
|
||||||
tty_printf ("\n");
|
tty_printf ("\n");
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if GNUPG_MAJOR_VERSION == 1
|
|
||||||
/* Helper for the key generation/edit functions. */
|
/* Helper for the key generation/edit functions. */
|
||||||
static int
|
static int
|
||||||
replace_existing_key_p (struct agent_card_info_s *info, int keyno)
|
replace_existing_key_p (struct agent_card_info_s *info, int keyno)
|
||||||
@ -1034,7 +1033,6 @@ replace_existing_key_p (struct agent_card_info_s *info, int keyno)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1104,7 +1102,6 @@ generate_card_keys (const char *serialno)
|
|||||||
int
|
int
|
||||||
card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock)
|
card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock)
|
||||||
{
|
{
|
||||||
#if GNUPG_MAJOR_VERSION == 1
|
|
||||||
struct agent_card_info_s info;
|
struct agent_card_info_s info;
|
||||||
int okay = 0;
|
int okay = 0;
|
||||||
int forced_chv1 = 0;
|
int forced_chv1 = 0;
|
||||||
@ -1151,9 +1148,6 @@ card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock)
|
|||||||
agent_release_card_info (&info);
|
agent_release_card_info (&info);
|
||||||
restore_forced_chv1 (&forced_chv1);
|
restore_forced_chv1 (&forced_chv1);
|
||||||
return okay;
|
return okay;
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1164,7 +1158,6 @@ card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock)
|
|||||||
int
|
int
|
||||||
card_store_subkey (KBNODE node, int use)
|
card_store_subkey (KBNODE node, int use)
|
||||||
{
|
{
|
||||||
#if GNUPG_MAJOR_VERSION == 1
|
|
||||||
struct agent_card_info_s info;
|
struct agent_card_info_s info;
|
||||||
int okay = 0;
|
int okay = 0;
|
||||||
int rc;
|
int rc;
|
||||||
@ -1266,7 +1259,7 @@ card_store_subkey (KBNODE node, int use)
|
|||||||
n = pubkey_get_nskey (sk->pubkey_algo);
|
n = pubkey_get_nskey (sk->pubkey_algo);
|
||||||
for (i=pubkey_get_npkey (sk->pubkey_algo); i < n; i++)
|
for (i=pubkey_get_npkey (sk->pubkey_algo); i < n; i++)
|
||||||
{
|
{
|
||||||
mpi_free (sk->skey[i]);
|
gcry_mpi_release (sk->skey[i]);
|
||||||
sk->skey[i] = NULL;
|
sk->skey[i] = NULL;
|
||||||
}
|
}
|
||||||
i = pubkey_get_npkey (sk->pubkey_algo);
|
i = pubkey_get_npkey (sk->pubkey_algo);
|
||||||
@ -1285,9 +1278,6 @@ card_store_subkey (KBNODE node, int use)
|
|||||||
free_secret_key (copied_sk);
|
free_secret_key (copied_sk);
|
||||||
agent_release_card_info (&info);
|
agent_release_card_info (&info);
|
||||||
return okay;
|
return okay;
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3652,6 +3652,7 @@ menu_backsign(KBNODE pub_keyblock,KBNODE sec_keyblock)
|
|||||||
PKT_public_key *main_pk;
|
PKT_public_key *main_pk;
|
||||||
PKT_secret_key *main_sk,*sub_sk=NULL;
|
PKT_secret_key *main_sk,*sub_sk=NULL;
|
||||||
KBNODE node;
|
KBNODE node;
|
||||||
|
u32 timestamp;
|
||||||
|
|
||||||
assert(pub_keyblock->pkt->pkttype==PKT_PUBLIC_KEY);
|
assert(pub_keyblock->pkt->pkttype==PKT_PUBLIC_KEY);
|
||||||
assert(sec_keyblock->pkt->pkttype==PKT_SECRET_KEY);
|
assert(sec_keyblock->pkt->pkttype==PKT_SECRET_KEY);
|
||||||
@ -3661,6 +3662,10 @@ menu_backsign(KBNODE pub_keyblock,KBNODE sec_keyblock)
|
|||||||
main_sk=copy_secret_key(NULL,sec_keyblock->pkt->pkt.secret_key);
|
main_sk=copy_secret_key(NULL,sec_keyblock->pkt->pkt.secret_key);
|
||||||
keyid_from_pk(main_pk,NULL);
|
keyid_from_pk(main_pk,NULL);
|
||||||
|
|
||||||
|
/* We use the same timestamp for all backsigs so that we don't
|
||||||
|
reveal information about the used machine. */
|
||||||
|
timestamp = make_timestamp ();
|
||||||
|
|
||||||
for(node=pub_keyblock;node;node=node->next)
|
for(node=pub_keyblock;node;node=node->next)
|
||||||
{
|
{
|
||||||
PKT_public_key *sub_pk=NULL;
|
PKT_public_key *sub_pk=NULL;
|
||||||
@ -3748,7 +3753,8 @@ menu_backsign(KBNODE pub_keyblock,KBNODE sec_keyblock)
|
|||||||
set_next_passphrase(passphrase);
|
set_next_passphrase(passphrase);
|
||||||
xfree(passphrase);
|
xfree(passphrase);
|
||||||
|
|
||||||
rc=make_backsig(sig_pk->pkt->pkt.signature,main_pk,sub_pk,sub_sk);
|
rc = make_backsig (sig_pk->pkt->pkt.signature, main_pk, sub_pk, sub_sk,
|
||||||
|
timestamp);
|
||||||
if(rc==0)
|
if(rc==0)
|
||||||
{
|
{
|
||||||
PKT_signature *newsig;
|
PKT_signature *newsig;
|
||||||
|
407
g10/keygen.c
407
g10/keygen.c
@ -1,6 +1,6 @@
|
|||||||
/* keygen.c - generate a key pair
|
/* keygen.c - generate a key pair
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
|
||||||
* 2006 Free Software Foundation, Inc.
|
* 2006, 2007 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -60,6 +60,8 @@ enum para_name {
|
|||||||
pPREFERENCES,
|
pPREFERENCES,
|
||||||
pREVOKER,
|
pREVOKER,
|
||||||
pUSERID,
|
pUSERID,
|
||||||
|
pCREATIONDATE,
|
||||||
|
pKEYCREATIONDATE, /* Same in seconds since epoch. */
|
||||||
pEXPIREDATE,
|
pEXPIREDATE,
|
||||||
pKEYEXPIRE, /* in n seconds */
|
pKEYEXPIRE, /* in n seconds */
|
||||||
pSUBKEYEXPIRE, /* in n seconds */
|
pSUBKEYEXPIRE, /* in n seconds */
|
||||||
@ -80,6 +82,7 @@ struct para_data_s {
|
|||||||
DEK *dek;
|
DEK *dek;
|
||||||
STRING2KEY *s2k;
|
STRING2KEY *s2k;
|
||||||
u32 expire;
|
u32 expire;
|
||||||
|
u32 creation;
|
||||||
unsigned int usage;
|
unsigned int usage;
|
||||||
struct revocation_key revkey;
|
struct revocation_key revkey;
|
||||||
char value[1];
|
char value[1];
|
||||||
@ -126,9 +129,11 @@ static int write_keyblock( IOBUF out, KBNODE node );
|
|||||||
static int gen_card_key (int algo, int keyno, int is_primary,
|
static int gen_card_key (int algo, int keyno, int is_primary,
|
||||||
KBNODE pub_root, KBNODE sec_root,
|
KBNODE pub_root, KBNODE sec_root,
|
||||||
PKT_secret_key **ret_sk,
|
PKT_secret_key **ret_sk,
|
||||||
|
u32 *timestamp,
|
||||||
u32 expireval, struct para_data_s *para);
|
u32 expireval, struct para_data_s *para);
|
||||||
static int gen_card_key_with_backup (int algo, int keyno, int is_primary,
|
static int gen_card_key_with_backup (int algo, int keyno, int is_primary,
|
||||||
KBNODE pub_root, KBNODE sec_root,
|
KBNODE pub_root, KBNODE sec_root,
|
||||||
|
u32 timestamp,
|
||||||
u32 expireval, struct para_data_s *para,
|
u32 expireval, struct para_data_s *para,
|
||||||
const char *backup_dir);
|
const char *backup_dir);
|
||||||
|
|
||||||
@ -769,21 +774,27 @@ keygen_add_revkey(PKT_signature *sig, void *opaque)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Create a back-signature. If TIMESTAMP is not NULL, use it for the
|
||||||
|
signature creation time. */
|
||||||
int
|
int
|
||||||
make_backsig (PKT_signature *sig,PKT_public_key *pk,
|
make_backsig (PKT_signature *sig,PKT_public_key *pk,
|
||||||
PKT_public_key *sub_pk,PKT_secret_key *sub_sk)
|
PKT_public_key *sub_pk,PKT_secret_key *sub_sk,
|
||||||
|
u32 timestamp)
|
||||||
{
|
{
|
||||||
PKT_signature *backsig;
|
PKT_signature *backsig;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
cache_public_key(sub_pk);
|
cache_public_key(sub_pk);
|
||||||
|
|
||||||
rc=make_keysig_packet(&backsig,pk,NULL,sub_pk,sub_sk,0x19,0,0,0,0,NULL,NULL);
|
rc = make_keysig_packet (&backsig, pk, NULL, sub_pk, sub_sk, 0x19,
|
||||||
|
0, 0, timestamp, 0, NULL, NULL);
|
||||||
if(rc)
|
if(rc)
|
||||||
log_error("make_keysig_packet failed for backsig: %s\n",g10_errstr(rc));
|
log_error("make_keysig_packet failed for backsig: %s\n",g10_errstr(rc));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* get it into a binary packed form. */
|
/* Get it into a binary packed form. */
|
||||||
IOBUF backsig_out=iobuf_temp();
|
IOBUF backsig_out=iobuf_temp();
|
||||||
PACKET backsig_pkt;
|
PACKET backsig_pkt;
|
||||||
|
|
||||||
@ -848,7 +859,7 @@ make_backsig(PKT_signature *sig,PKT_public_key *pk,
|
|||||||
buf+=mark;
|
buf+=mark;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now make the binary blob into a subpacket */
|
/* Now make the binary blob into a subpacket. */
|
||||||
build_sig_subpkt(sig,SIGSUBPKT_SIGNATURE,buf,pktlen);
|
build_sig_subpkt(sig,SIGSUBPKT_SIGNATURE,buf,pktlen);
|
||||||
|
|
||||||
iobuf_close(backsig_out);
|
iobuf_close(backsig_out);
|
||||||
@ -861,7 +872,7 @@ make_backsig(PKT_signature *sig,PKT_public_key *pk,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
write_direct_sig (KBNODE root, KBNODE pub_root, PKT_secret_key *sk,
|
write_direct_sig (KBNODE root, KBNODE pub_root, PKT_secret_key *sk,
|
||||||
struct revocation_key *revkey )
|
struct revocation_key *revkey, u32 timestamp)
|
||||||
{
|
{
|
||||||
PACKET *pkt;
|
PACKET *pkt;
|
||||||
PKT_signature *sig;
|
PKT_signature *sig;
|
||||||
@ -872,20 +883,22 @@ write_direct_sig( KBNODE root, KBNODE pub_root, PKT_secret_key *sk,
|
|||||||
if( opt.verbose )
|
if( opt.verbose )
|
||||||
log_info(_("writing direct signature\n"));
|
log_info(_("writing direct signature\n"));
|
||||||
|
|
||||||
/* get the pk packet from the pub_tree */
|
/* Get the pk packet from the pub_tree. */
|
||||||
node = find_kbnode( pub_root, PKT_PUBLIC_KEY );
|
node = find_kbnode( pub_root, PKT_PUBLIC_KEY );
|
||||||
if( !node )
|
if( !node )
|
||||||
BUG();
|
BUG();
|
||||||
pk = node->pkt->pkt.public_key;
|
pk = node->pkt->pkt.public_key;
|
||||||
|
|
||||||
/* we have to cache the key, so that the verification of the signature
|
/* We have to cache the key, so that the verification of the
|
||||||
* creation is able to retrieve the public key */
|
signature creation is able to retrieve the public key. */
|
||||||
cache_public_key (pk);
|
cache_public_key (pk);
|
||||||
|
|
||||||
/* and make the signature */
|
/* Make the signature. */
|
||||||
rc = make_keysig_packet(&sig,pk,NULL,NULL,sk,0x1F,0,0,0,0,
|
rc = make_keysig_packet (&sig,pk,NULL,NULL,sk,0x1F,
|
||||||
|
0, 0, timestamp, 0,
|
||||||
keygen_add_revkey, revkey);
|
keygen_add_revkey, revkey);
|
||||||
if( rc ) {
|
if( rc )
|
||||||
|
{
|
||||||
log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) );
|
log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) );
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -897,9 +910,10 @@ write_direct_sig( KBNODE root, KBNODE pub_root, PKT_secret_key *sk,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
write_selfsigs( KBNODE sec_root, KBNODE pub_root, PKT_secret_key *sk,
|
write_selfsigs( KBNODE sec_root, KBNODE pub_root, PKT_secret_key *sk,
|
||||||
unsigned int use )
|
unsigned int use, u32 timestamp )
|
||||||
{
|
{
|
||||||
PACKET *pkt;
|
PACKET *pkt;
|
||||||
PKT_signature *sig;
|
PKT_signature *sig;
|
||||||
@ -911,25 +925,29 @@ write_selfsigs( KBNODE sec_root, KBNODE pub_root, PKT_secret_key *sk,
|
|||||||
if( opt.verbose )
|
if( opt.verbose )
|
||||||
log_info(_("writing self signature\n"));
|
log_info(_("writing self signature\n"));
|
||||||
|
|
||||||
/* get the uid packet from the list */
|
/* Get the uid packet from the list. */
|
||||||
node = find_kbnode( pub_root, PKT_USER_ID );
|
node = find_kbnode( pub_root, PKT_USER_ID );
|
||||||
if( !node )
|
if( !node )
|
||||||
BUG(); /* no user id packet in tree */
|
BUG(); /* No user id packet in tree. */
|
||||||
uid = node->pkt->pkt.user_id;
|
uid = node->pkt->pkt.user_id;
|
||||||
/* get the pk packet from the pub_tree */
|
|
||||||
|
/* Get the pk packet from the pub_tree. */
|
||||||
node = find_kbnode( pub_root, PKT_PUBLIC_KEY );
|
node = find_kbnode( pub_root, PKT_PUBLIC_KEY );
|
||||||
if( !node )
|
if( !node )
|
||||||
BUG();
|
BUG();
|
||||||
pk = node->pkt->pkt.public_key;
|
pk = node->pkt->pkt.public_key;
|
||||||
pk->pubkey_usage = use;
|
pk->pubkey_usage = use;
|
||||||
/* we have to cache the key, so that the verification of the signature
|
|
||||||
* creation is able to retrieve the 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 (pk);
|
cache_public_key (pk);
|
||||||
|
|
||||||
/* and make the signature */
|
/* Make the signature. */
|
||||||
rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0, 0, 0, 0,
|
rc = make_keysig_packet (&sig, pk, uid, NULL, sk, 0x13,
|
||||||
|
0, 0, timestamp, 0,
|
||||||
keygen_add_std_prefs, pk);
|
keygen_add_std_prefs, pk);
|
||||||
if( rc ) {
|
if( rc )
|
||||||
|
{
|
||||||
log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) );
|
log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) );
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -946,10 +964,13 @@ write_selfsigs( KBNODE sec_root, KBNODE pub_root, PKT_secret_key *sk,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Write the key binding signature. If TIMESTAMP is not NULL use the
|
||||||
|
signature creation times. */
|
||||||
static int
|
static int
|
||||||
write_keybinding (KBNODE root, KBNODE pub_root,
|
write_keybinding (KBNODE root, KBNODE pub_root,
|
||||||
PKT_secret_key *pri_sk, PKT_secret_key *sub_sk,
|
PKT_secret_key *pri_sk, PKT_secret_key *sub_sk,
|
||||||
unsigned int use )
|
unsigned int use, u32 timestamp)
|
||||||
{
|
{
|
||||||
PACKET *pkt;
|
PACKET *pkt;
|
||||||
PKT_signature *sig;
|
PKT_signature *sig;
|
||||||
@ -961,38 +982,42 @@ write_keybinding( KBNODE root, KBNODE pub_root,
|
|||||||
if ( opt.verbose )
|
if ( opt.verbose )
|
||||||
log_info(_("writing key binding signature\n"));
|
log_info(_("writing key binding signature\n"));
|
||||||
|
|
||||||
/* get the pk packet from the pub_tree */
|
/* Get the pk packet from the pub_tree. */
|
||||||
node = find_kbnode ( pub_root, PKT_PUBLIC_KEY );
|
node = find_kbnode ( pub_root, PKT_PUBLIC_KEY );
|
||||||
if ( !node )
|
if ( !node )
|
||||||
BUG();
|
BUG();
|
||||||
pri_pk = node->pkt->pkt.public_key;
|
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 */
|
/* 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);
|
cache_public_key (pri_pk);
|
||||||
|
|
||||||
/* find the last subkey */
|
/* Find the last subkey. */
|
||||||
sub_pk = NULL;
|
sub_pk = NULL;
|
||||||
for(node=pub_root; node; node = node->next ) {
|
for (node=pub_root; node; node = node->next )
|
||||||
|
{
|
||||||
if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
|
if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
|
||||||
sub_pk = node->pkt->pkt.public_key;
|
sub_pk = node->pkt->pkt.public_key;
|
||||||
}
|
}
|
||||||
if (!sub_pk)
|
if (!sub_pk)
|
||||||
BUG();
|
BUG();
|
||||||
|
|
||||||
/* and make the signature */
|
/* Make the signature. */
|
||||||
oduap.usage = use;
|
oduap.usage = use;
|
||||||
oduap.pk = sub_pk;
|
oduap.pk = sub_pk;
|
||||||
rc=make_keysig_packet(&sig, pri_pk, NULL, sub_pk, pri_sk, 0x18, 0, 0, 0, 0,
|
rc = make_keysig_packet (&sig, pri_pk, NULL, sub_pk, pri_sk, 0x18,
|
||||||
|
0, 0, timestamp, 0,
|
||||||
keygen_add_key_flags_and_expire, &oduap );
|
keygen_add_key_flags_and_expire, &oduap );
|
||||||
if( rc ) {
|
if (rc)
|
||||||
|
{
|
||||||
log_error ("make_keysig_packet failed: %s\n", g10_errstr(rc) );
|
log_error ("make_keysig_packet failed: %s\n", g10_errstr(rc) );
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make a backsig */
|
/* Make a backsig. */
|
||||||
if (use&PUBKEY_USAGE_SIG)
|
if (use&PUBKEY_USAGE_SIG)
|
||||||
{
|
{
|
||||||
rc=make_backsig(sig,pri_pk,sub_pk,sub_sk);
|
rc = make_backsig (sig, pri_pk, sub_pk, sub_sk, timestamp);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -1103,11 +1128,13 @@ genhelp_factors (gcry_sexp_t misc_key_info, KBNODE sec_root)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Generate an Elgamal encryption key pair. TIMESTAMP is the creatuion
|
||||||
|
time to be put into the key structure. */
|
||||||
static int
|
static int
|
||||||
gen_elg (int algo, unsigned int nbits,
|
gen_elg (int algo, unsigned int nbits,
|
||||||
KBNODE pub_root, KBNODE sec_root, DEK *dek,
|
KBNODE pub_root, KBNODE sec_root, DEK *dek,
|
||||||
STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval,
|
STRING2KEY *s2k, PKT_secret_key **ret_sk,
|
||||||
int is_subkey)
|
u32 timestamp, u32 expireval, int is_subkey)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
PACKET *pkt;
|
PACKET *pkt;
|
||||||
@ -1118,12 +1145,14 @@ gen_elg(int algo, unsigned int nbits,
|
|||||||
|
|
||||||
assert( is_ELGAMAL(algo) );
|
assert( is_ELGAMAL(algo) );
|
||||||
|
|
||||||
if( nbits < 512 ) {
|
if (nbits < 512)
|
||||||
|
{
|
||||||
nbits = 1024;
|
nbits = 1024;
|
||||||
log_info (_("keysize invalid; using %u bits\n"), nbits );
|
log_info (_("keysize invalid; using %u bits\n"), nbits );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (nbits % 32) ) {
|
if ((nbits % 32))
|
||||||
|
{
|
||||||
nbits = ((nbits + 31) / 32) * 32;
|
nbits = ((nbits + 31) / 32) * 32;
|
||||||
log_info (_("keysize rounded up to %u bits\n"), nbits );
|
log_info (_("keysize rounded up to %u bits\n"), nbits );
|
||||||
}
|
}
|
||||||
@ -1147,19 +1176,13 @@ gen_elg(int algo, unsigned int nbits,
|
|||||||
|
|
||||||
sk = xmalloc_clear( sizeof *sk );
|
sk = xmalloc_clear( sizeof *sk );
|
||||||
pk = xmalloc_clear( sizeof *pk );
|
pk = xmalloc_clear( sizeof *pk );
|
||||||
sk->timestamp = pk->timestamp = make_timestamp();
|
sk->timestamp = pk->timestamp = timestamp;
|
||||||
sk->version = pk->version = 4;
|
sk->version = pk->version = 4;
|
||||||
if( expireval ) {
|
if (expireval)
|
||||||
|
{
|
||||||
sk->expiredate = pk->expiredate = sk->timestamp + expireval;
|
sk->expiredate = pk->expiredate = sk->timestamp + expireval;
|
||||||
}
|
}
|
||||||
sk->pubkey_algo = pk->pubkey_algo = algo;
|
sk->pubkey_algo = pk->pubkey_algo = algo;
|
||||||
/* pk->pkey[0] = mpi_copy( skey[0] ); */
|
|
||||||
/* pk->pkey[1] = mpi_copy( skey[1] ); */
|
|
||||||
/* pk->pkey[2] = mpi_copy( skey[2] ); */
|
|
||||||
/* sk->skey[0] = skey[0]; */
|
|
||||||
/* sk->skey[1] = skey[1]; */
|
|
||||||
/* sk->skey[2] = skey[2]; */
|
|
||||||
/* sk->skey[3] = skey[3]; */
|
|
||||||
|
|
||||||
rc = key_from_sexp (pk->pkey, s_key, "public-key", "pgy");
|
rc = key_from_sexp (pk->pkey, s_key, "public-key", "pgy");
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -1186,7 +1209,7 @@ gen_elg(int algo, unsigned int nbits,
|
|||||||
sk->protect.algo = 0;
|
sk->protect.algo = 0;
|
||||||
|
|
||||||
sk->csum = checksum_mpi (sk->skey[3]);
|
sk->csum = checksum_mpi (sk->skey[3]);
|
||||||
if( ret_sk ) /* return an unprotected version of the sk */
|
if (ret_sk) /* Return an unprotected version of the sk. */
|
||||||
*ret_sk = copy_secret_key ( NULL, sk );
|
*ret_sk = copy_secret_key ( NULL, sk );
|
||||||
|
|
||||||
rc = genhelp_protect (dek, s2k, sk);
|
rc = genhelp_protect (dek, s2k, sk);
|
||||||
@ -1203,8 +1226,9 @@ gen_elg(int algo, unsigned int nbits,
|
|||||||
pkt->pkt.public_key = pk;
|
pkt->pkt.public_key = pk;
|
||||||
add_kbnode (pub_root, new_kbnode( pkt ));
|
add_kbnode (pub_root, new_kbnode( pkt ));
|
||||||
|
|
||||||
/* Don't know whether it makes sense to have the factors, so for now
|
/* Don't know whether it makes sense to have access to the factors,
|
||||||
* we store them in the secret keyring (but they are not secret). */
|
so for now we store them in the secret keyring (but they are not
|
||||||
|
secret). */
|
||||||
pkt = xmalloc_clear (sizeof *pkt);
|
pkt = xmalloc_clear (sizeof *pkt);
|
||||||
pkt->pkttype = is_subkey ? PKT_SECRET_SUBKEY : PKT_SECRET_KEY;
|
pkt->pkttype = is_subkey ? PKT_SECRET_SUBKEY : PKT_SECRET_KEY;
|
||||||
pkt->pkt.secret_key = sk;
|
pkt->pkt.secret_key = sk;
|
||||||
@ -1221,7 +1245,8 @@ gen_elg(int algo, unsigned int nbits,
|
|||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
gen_dsa (unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
|
gen_dsa (unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
|
||||||
STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval, int is_subkey)
|
STRING2KEY *s2k, PKT_secret_key **ret_sk,
|
||||||
|
u32 timestamp, u32 expireval, int is_subkey)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
PACKET *pkt;
|
PACKET *pkt;
|
||||||
@ -1290,7 +1315,7 @@ gen_dsa (unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
|
|||||||
|
|
||||||
sk = xmalloc_clear( sizeof *sk );
|
sk = xmalloc_clear( sizeof *sk );
|
||||||
pk = xmalloc_clear( sizeof *pk );
|
pk = xmalloc_clear( sizeof *pk );
|
||||||
sk->timestamp = pk->timestamp = make_timestamp();
|
sk->timestamp = pk->timestamp = timestamp;
|
||||||
sk->version = pk->version = 4;
|
sk->version = pk->version = 4;
|
||||||
if (expireval)
|
if (expireval)
|
||||||
sk->expiredate = pk->expiredate = sk->timestamp + expireval;
|
sk->expiredate = pk->expiredate = sk->timestamp + expireval;
|
||||||
@ -1360,7 +1385,8 @@ gen_dsa (unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
|
|||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
gen_rsa (int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
|
gen_rsa (int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
|
||||||
STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval, int is_subkey)
|
STRING2KEY *s2k, PKT_secret_key **ret_sk,
|
||||||
|
u32 timestamp, u32 expireval, int is_subkey)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
PACKET *pkt;
|
PACKET *pkt;
|
||||||
@ -1370,12 +1396,14 @@ gen_rsa(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
|
|||||||
|
|
||||||
assert (is_RSA(algo));
|
assert (is_RSA(algo));
|
||||||
|
|
||||||
if( nbits < 1024 ) {
|
if (nbits < 1024)
|
||||||
|
{
|
||||||
nbits = 1024;
|
nbits = 1024;
|
||||||
log_info (_("keysize invalid; using %u bits\n"), nbits );
|
log_info (_("keysize invalid; using %u bits\n"), nbits );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (nbits % 32) ) {
|
if ((nbits % 32))
|
||||||
|
{
|
||||||
nbits = ((nbits + 31) / 32) * 32;
|
nbits = ((nbits + 31) / 32) * 32;
|
||||||
log_info (_("keysize rounded up to %u bits\n"), nbits );
|
log_info (_("keysize rounded up to %u bits\n"), nbits );
|
||||||
}
|
}
|
||||||
@ -1396,9 +1424,10 @@ gen_rsa(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
|
|||||||
|
|
||||||
sk = xmalloc_clear( sizeof *sk );
|
sk = xmalloc_clear( sizeof *sk );
|
||||||
pk = xmalloc_clear( sizeof *pk );
|
pk = xmalloc_clear( sizeof *pk );
|
||||||
sk->timestamp = pk->timestamp = make_timestamp();
|
sk->timestamp = pk->timestamp = timestamp;
|
||||||
sk->version = pk->version = 4;
|
sk->version = pk->version = 4;
|
||||||
if( expireval ) {
|
if (expireval)
|
||||||
|
{
|
||||||
sk->expiredate = pk->expiredate = sk->timestamp + expireval;
|
sk->expiredate = pk->expiredate = sk->timestamp + expireval;
|
||||||
}
|
}
|
||||||
sk->pubkey_algo = pk->pubkey_algo = algo;
|
sk->pubkey_algo = pk->pubkey_algo = algo;
|
||||||
@ -1762,6 +1791,26 @@ parse_expire_string( const char *string )
|
|||||||
return seconds;
|
return seconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* object == 0 for a key, and 1 for a sig */
|
/* object == 0 for a key, and 1 for a sig */
|
||||||
u32
|
u32
|
||||||
ask_expire_interval(int object,const char *def_expire)
|
ask_expire_interval(int object,const char *def_expire)
|
||||||
@ -2084,10 +2133,12 @@ do_ask_passphrase ( STRING2KEY **ret_s2k, int *r_canceled )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Basic key generation. Here we divert to the actual generation
|
||||||
|
routines based on the requested algorithm. */
|
||||||
static int
|
static int
|
||||||
do_create (int algo, unsigned int nbits, KBNODE pub_root, KBNODE sec_root,
|
do_create (int algo, unsigned int nbits, KBNODE pub_root, KBNODE sec_root,
|
||||||
DEK *dek, STRING2KEY *s2k, PKT_secret_key **sk, u32 expiredate,
|
DEK *dek, STRING2KEY *s2k, PKT_secret_key **sk,
|
||||||
int is_subkey )
|
u32 timestamp, u32 expiredate, int is_subkey )
|
||||||
{
|
{
|
||||||
int rc=0;
|
int rc=0;
|
||||||
|
|
||||||
@ -2099,14 +2150,14 @@ do_create( int algo, unsigned int nbits, KBNODE pub_root, KBNODE sec_root,
|
|||||||
"generator a better chance to gain enough entropy.\n") );
|
"generator a better chance to gain enough entropy.\n") );
|
||||||
|
|
||||||
if( algo == PUBKEY_ALGO_ELGAMAL_E )
|
if( algo == PUBKEY_ALGO_ELGAMAL_E )
|
||||||
rc = gen_elg(algo, nbits, pub_root, sec_root, dek, s2k, sk, expiredate,
|
rc = gen_elg(algo, nbits, pub_root, sec_root, dek, s2k, sk,
|
||||||
is_subkey);
|
timestamp, expiredate, is_subkey);
|
||||||
else if( algo == PUBKEY_ALGO_DSA )
|
else if( algo == PUBKEY_ALGO_DSA )
|
||||||
rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, sk, expiredate,
|
rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, sk,
|
||||||
is_subkey);
|
timestamp, expiredate, is_subkey);
|
||||||
else if( algo == PUBKEY_ALGO_RSA )
|
else if( algo == PUBKEY_ALGO_RSA )
|
||||||
rc = gen_rsa(algo, nbits, pub_root, sec_root, dek, s2k, sk, expiredate,
|
rc = gen_rsa(algo, nbits, pub_root, sec_root, dek, s2k, sk,
|
||||||
is_subkey);
|
timestamp, expiredate, is_subkey);
|
||||||
else
|
else
|
||||||
BUG();
|
BUG();
|
||||||
|
|
||||||
@ -2283,6 +2334,8 @@ get_parameter_u32( struct para_data_s *para, enum para_name key )
|
|||||||
|
|
||||||
if( !r )
|
if( !r )
|
||||||
return 0;
|
return 0;
|
||||||
|
if( r->key == pKEYCREATIONDATE )
|
||||||
|
return r->u.creation;
|
||||||
if( r->key == pKEYEXPIRE || r->key == pSUBKEYEXPIRE )
|
if( r->key == pKEYEXPIRE || r->key == pSUBKEYEXPIRE )
|
||||||
return r->u.expire;
|
return r->u.expire;
|
||||||
if( r->key == pKEYUSAGE || r->key == pSUBKEYUSAGE )
|
if( r->key == pKEYUSAGE || r->key == pSUBKEYUSAGE )
|
||||||
@ -2472,7 +2525,23 @@ proc_parameter_file( struct para_data_s *para, const char *fname,
|
|||||||
para = r;
|
para = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make KEYEXPIRE from Expire-Date */
|
/* 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. */
|
||||||
r = get_parameter( para, pEXPIREDATE );
|
r = get_parameter( para, pEXPIREDATE );
|
||||||
if( r && *r->u.value )
|
if( r && *r->u.value )
|
||||||
{
|
{
|
||||||
@ -2525,6 +2594,7 @@ read_parameter_file( const char *fname )
|
|||||||
{ "Name-Email", pNAMEEMAIL },
|
{ "Name-Email", pNAMEEMAIL },
|
||||||
{ "Name-Comment", pNAMECOMMENT },
|
{ "Name-Comment", pNAMECOMMENT },
|
||||||
{ "Expire-Date", pEXPIREDATE },
|
{ "Expire-Date", pEXPIREDATE },
|
||||||
|
{ "Creation-Date", pCREATIONDATE },
|
||||||
{ "Passphrase", pPASSPHRASE },
|
{ "Passphrase", pPASSPHRASE },
|
||||||
{ "Preferences", pPREFERENCES },
|
{ "Preferences", pPREFERENCES },
|
||||||
{ "Revoker", pREVOKER },
|
{ "Revoker", pREVOKER },
|
||||||
@ -3027,6 +3097,7 @@ start_tree(KBNODE *tree)
|
|||||||
delete_kbnode(*tree);
|
delete_kbnode(*tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
do_generate_keypair (struct para_data_s *para,
|
do_generate_keypair (struct para_data_s *para,
|
||||||
struct output_control_s *outctrl, int card)
|
struct output_control_s *outctrl, int card)
|
||||||
@ -3038,6 +3109,7 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
struct revocation_key *revkey;
|
struct revocation_key *revkey;
|
||||||
int rc;
|
int rc;
|
||||||
int did_sub = 0;
|
int did_sub = 0;
|
||||||
|
u32 timestamp;
|
||||||
|
|
||||||
if( outctrl->dryrun )
|
if( outctrl->dryrun )
|
||||||
{
|
{
|
||||||
@ -3045,8 +3117,10 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( outctrl->use_files ) {
|
if ( outctrl->use_files )
|
||||||
if( outctrl->pub.newfname ) {
|
{
|
||||||
|
if ( outctrl->pub.newfname )
|
||||||
|
{
|
||||||
iobuf_close(outctrl->pub.stream);
|
iobuf_close(outctrl->pub.stream);
|
||||||
outctrl->pub.stream = NULL;
|
outctrl->pub.stream = NULL;
|
||||||
if (outctrl->pub.fname)
|
if (outctrl->pub.fname)
|
||||||
@ -3055,23 +3129,27 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
outctrl->pub.fname = outctrl->pub.newfname;
|
outctrl->pub.fname = outctrl->pub.newfname;
|
||||||
outctrl->pub.newfname = NULL;
|
outctrl->pub.newfname = NULL;
|
||||||
|
|
||||||
if (is_secured_filename (outctrl->pub.fname) ) {
|
if (is_secured_filename (outctrl->pub.fname) )
|
||||||
|
{
|
||||||
outctrl->pub.stream = NULL;
|
outctrl->pub.stream = NULL;
|
||||||
errno = EPERM;
|
errno = EPERM;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
outctrl->pub.stream = iobuf_create( outctrl->pub.fname );
|
outctrl->pub.stream = iobuf_create( outctrl->pub.fname );
|
||||||
if( !outctrl->pub.stream ) {
|
if (!outctrl->pub.stream)
|
||||||
|
{
|
||||||
log_error(_("can't create `%s': %s\n"), outctrl->pub.newfname,
|
log_error(_("can't create `%s': %s\n"), outctrl->pub.newfname,
|
||||||
strerror(errno) );
|
strerror(errno) );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if( opt.armor ) {
|
if (opt.armor)
|
||||||
|
{
|
||||||
outctrl->pub.afx->what = 1;
|
outctrl->pub.afx->what = 1;
|
||||||
push_armor_filter (outctrl->pub.afx, outctrl->pub.stream);
|
push_armor_filter (outctrl->pub.afx, outctrl->pub.stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( outctrl->sec.newfname ) {
|
if (outctrl->sec.newfname)
|
||||||
|
{
|
||||||
mode_t oldmask;
|
mode_t oldmask;
|
||||||
|
|
||||||
iobuf_close(outctrl->sec.stream);
|
iobuf_close(outctrl->sec.stream);
|
||||||
@ -3083,26 +3161,30 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
outctrl->sec.newfname = NULL;
|
outctrl->sec.newfname = NULL;
|
||||||
|
|
||||||
oldmask = umask (077);
|
oldmask = umask (077);
|
||||||
if (is_secured_filename (outctrl->sec.fname) ) {
|
if (is_secured_filename (outctrl->sec.fname) )
|
||||||
|
{
|
||||||
outctrl->sec.stream = NULL;
|
outctrl->sec.stream = NULL;
|
||||||
errno = EPERM;
|
errno = EPERM;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
outctrl->sec.stream = iobuf_create( outctrl->sec.fname );
|
outctrl->sec.stream = iobuf_create( outctrl->sec.fname );
|
||||||
umask (oldmask);
|
umask (oldmask);
|
||||||
if( !outctrl->sec.stream ) {
|
if (!outctrl->sec.stream)
|
||||||
|
{
|
||||||
log_error(_("can't create `%s': %s\n"), outctrl->sec.newfname,
|
log_error(_("can't create `%s': %s\n"), outctrl->sec.newfname,
|
||||||
strerror(errno) );
|
strerror(errno) );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if( opt.armor ) {
|
if (opt.armor)
|
||||||
|
{
|
||||||
outctrl->sec.afx->what = 5;
|
outctrl->sec.afx->what = 5;
|
||||||
push_armor_filter (outctrl->sec.afx, outctrl->sec.stream);
|
push_armor_filter (outctrl->sec.afx, outctrl->sec.stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert( outctrl->pub.stream );
|
assert( outctrl->pub.stream );
|
||||||
assert( outctrl->sec.stream );
|
assert( outctrl->sec.stream );
|
||||||
if( opt.verbose ) {
|
if (opt.verbose)
|
||||||
|
{
|
||||||
log_info (_("writing public key to `%s'\n"), outctrl->pub.fname );
|
log_info (_("writing public key to `%s'\n"), outctrl->pub.fname );
|
||||||
if (card)
|
if (card)
|
||||||
log_info (_("writing secret key stub to `%s'\n"),
|
log_info (_("writing secret key stub to `%s'\n"),
|
||||||
@ -3113,15 +3195,18 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* we create the packets as a tree of kbnodes. Because the
|
/* We create the packets as a tree of kbnodes. Because the
|
||||||
* structure we create is known in advance we simply generate a
|
structure we create is known in advance we simply generate a
|
||||||
* linked list. The first packet is a dummy packet which we flag
|
linked list. The first packet is a dummy packet which we flag as
|
||||||
* as deleted. The very first packet must always be a KEY packet.
|
deleted. The very first packet must always be a KEY packet. */
|
||||||
*/
|
|
||||||
|
|
||||||
start_tree (&pub_root);
|
start_tree (&pub_root);
|
||||||
start_tree (&sec_root);
|
start_tree (&sec_root);
|
||||||
|
|
||||||
|
timestamp = get_parameter_u32 (para, pKEYCREATIONDATE);
|
||||||
|
if (!timestamp)
|
||||||
|
timestamp = make_timestamp ();
|
||||||
|
|
||||||
if (!card)
|
if (!card)
|
||||||
{
|
{
|
||||||
rc = do_create (get_parameter_algo( para, pKEYTYPE ),
|
rc = do_create (get_parameter_algo( para, pKEYTYPE ),
|
||||||
@ -3130,11 +3215,15 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
get_parameter_dek( para, pPASSPHRASE_DEK ),
|
get_parameter_dek( para, pPASSPHRASE_DEK ),
|
||||||
get_parameter_s2k( para, pPASSPHRASE_S2K ),
|
get_parameter_s2k( para, pPASSPHRASE_S2K ),
|
||||||
&pri_sk,
|
&pri_sk,
|
||||||
|
timestamp,
|
||||||
get_parameter_u32( para, pKEYEXPIRE ), 0 );
|
get_parameter_u32( para, pKEYEXPIRE ), 0 );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* Note, that depending on the backend, the card key generation
|
||||||
|
may update TIMESTAMP. */
|
||||||
rc = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root, sec_root, NULL,
|
rc = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root, sec_root, NULL,
|
||||||
|
×tamp,
|
||||||
get_parameter_u32 (para, pKEYEXPIRE), para);
|
get_parameter_u32 (para, pKEYEXPIRE), para);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
@ -3145,20 +3234,18 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
|
|
||||||
if(!rc && (revkey=get_parameter_revkey(para,pREVOKER)))
|
if(!rc && (revkey=get_parameter_revkey(para,pREVOKER)))
|
||||||
{
|
{
|
||||||
rc=write_direct_sig(pub_root,pub_root,pri_sk,revkey);
|
rc = write_direct_sig (pub_root, pub_root, pri_sk, revkey, timestamp);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
write_direct_sig(sec_root,pub_root,pri_sk,revkey);
|
rc = write_direct_sig (sec_root, pub_root, pri_sk, revkey, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !rc && (s=get_parameter_value(para, pUSERID)) )
|
if( !rc && (s=get_parameter_value(para, pUSERID)) )
|
||||||
{
|
{
|
||||||
write_uid (pub_root, s );
|
write_uid (pub_root, s );
|
||||||
if( !rc )
|
|
||||||
write_uid (sec_root, s );
|
write_uid (sec_root, s );
|
||||||
|
|
||||||
if( !rc )
|
|
||||||
rc = write_selfsigs (sec_root, pub_root, pri_sk,
|
rc = write_selfsigs (sec_root, pub_root, pri_sk,
|
||||||
get_parameter_uint (para, pKEYUSAGE));
|
get_parameter_uint (para, pKEYUSAGE), timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write the auth key to the card before the encryption key. This
|
/* Write the auth key to the card before the encryption key. This
|
||||||
@ -3170,13 +3257,18 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
|
|
||||||
if (!rc && card && get_parameter (para, pAUTHKEYTYPE))
|
if (!rc && card && get_parameter (para, pAUTHKEYTYPE))
|
||||||
{
|
{
|
||||||
|
/* Note, that depending on the backend, the card key generation
|
||||||
|
may update TIMESTAMP. */
|
||||||
rc = gen_card_key (PUBKEY_ALGO_RSA, 3, 0, pub_root, sec_root, NULL,
|
rc = gen_card_key (PUBKEY_ALGO_RSA, 3, 0, pub_root, sec_root, NULL,
|
||||||
|
×tamp,
|
||||||
get_parameter_u32 (para, pKEYEXPIRE), para);
|
get_parameter_u32 (para, pKEYEXPIRE), para);
|
||||||
|
|
||||||
if (!rc)
|
if (!rc)
|
||||||
rc = write_keybinding (pub_root, pub_root, pri_sk, sub_sk, PUBKEY_USAGE_AUTH);
|
rc = write_keybinding (pub_root, pub_root, pri_sk, sub_sk,
|
||||||
|
PUBKEY_USAGE_AUTH, timestamp);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
rc = write_keybinding (sec_root, pub_root, pri_sk, sub_sk, PUBKEY_USAGE_AUTH);
|
rc = write_keybinding (sec_root, pub_root, pri_sk, sub_sk,
|
||||||
|
PUBKEY_USAGE_AUTH, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !rc && get_parameter( para, pSUBKEYTYPE ) )
|
if( !rc && get_parameter( para, pSUBKEYTYPE ) )
|
||||||
@ -3189,6 +3281,7 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
get_parameter_dek( para, pPASSPHRASE_DEK ),
|
get_parameter_dek( para, pPASSPHRASE_DEK ),
|
||||||
get_parameter_s2k( para, pPASSPHRASE_S2K ),
|
get_parameter_s2k( para, pPASSPHRASE_S2K ),
|
||||||
&sub_sk,
|
&sub_sk,
|
||||||
|
timestamp,
|
||||||
get_parameter_u32( para, pSUBKEYEXPIRE ), 1 );
|
get_parameter_u32( para, pSUBKEYEXPIRE ), 1 );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -3196,58 +3289,69 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
if ((s = get_parameter_value (para, pBACKUPENCDIR)))
|
if ((s = get_parameter_value (para, pBACKUPENCDIR)))
|
||||||
{
|
{
|
||||||
/* A backup of the encryption key has been requested.
|
/* A backup of the encryption key has been requested.
|
||||||
Generate the key i software and import it then to
|
Generate the key in software and import it then to
|
||||||
the card. Write a backup file. */
|
the card. Write a backup file. */
|
||||||
rc = gen_card_key_with_backup (PUBKEY_ALGO_RSA, 2, 0,
|
rc = gen_card_key_with_backup (PUBKEY_ALGO_RSA, 2, 0,
|
||||||
pub_root, sec_root,
|
pub_root, sec_root,
|
||||||
|
timestamp,
|
||||||
get_parameter_u32 (para,
|
get_parameter_u32 (para,
|
||||||
pKEYEXPIRE),
|
pKEYEXPIRE),
|
||||||
para, s);
|
para, s);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
/* Note, that depending on the backend, the card key
|
||||||
|
generation may update TIMESTAMP. */
|
||||||
rc = gen_card_key (PUBKEY_ALGO_RSA, 2, 0, pub_root, sec_root,
|
rc = gen_card_key (PUBKEY_ALGO_RSA, 2, 0, pub_root, sec_root,
|
||||||
NULL,
|
NULL,
|
||||||
|
×tamp,
|
||||||
get_parameter_u32 (para, pKEYEXPIRE), para);
|
get_parameter_u32 (para, pKEYEXPIRE), para);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( !rc )
|
if( !rc )
|
||||||
rc = write_keybinding(pub_root, pub_root, pri_sk, sub_sk,
|
rc = write_keybinding(pub_root, pub_root, pri_sk, sub_sk,
|
||||||
get_parameter_uint (para, pSUBKEYUSAGE));
|
get_parameter_uint (para, pSUBKEYUSAGE),
|
||||||
|
timestamp);
|
||||||
if( !rc )
|
if( !rc )
|
||||||
rc = write_keybinding(sec_root, pub_root, pri_sk, sub_sk,
|
rc = write_keybinding(sec_root, pub_root, pri_sk, sub_sk,
|
||||||
get_parameter_uint (para, pSUBKEYUSAGE));
|
get_parameter_uint (para, pSUBKEYUSAGE),
|
||||||
|
timestamp);
|
||||||
did_sub = 1;
|
did_sub = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !rc && outctrl->use_files ) { /* direct write to specified files */
|
if (!rc && outctrl->use_files) /* Direct write to specified files. */
|
||||||
|
{
|
||||||
rc = write_keyblock( outctrl->pub.stream, pub_root );
|
rc = write_keyblock( outctrl->pub.stream, pub_root );
|
||||||
if (rc)
|
if (rc)
|
||||||
log_error ("can't write public key: %s\n", g10_errstr(rc) );
|
log_error ("can't write public key: %s\n", g10_errstr(rc) );
|
||||||
if( !rc ) {
|
if (!rc)
|
||||||
|
{
|
||||||
rc = write_keyblock( outctrl->sec.stream, sec_root );
|
rc = write_keyblock( outctrl->sec.stream, sec_root );
|
||||||
if(rc)
|
if(rc)
|
||||||
log_error ("can't write secret key: %s\n", g10_errstr(rc) );
|
log_error ("can't write secret key: %s\n", g10_errstr(rc) );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if( !rc ) { /* write to the standard keyrings */
|
else if (!rc) /* Write to the standard keyrings. */
|
||||||
|
{
|
||||||
KEYDB_HANDLE pub_hd = keydb_new (0);
|
KEYDB_HANDLE pub_hd = keydb_new (0);
|
||||||
KEYDB_HANDLE sec_hd = keydb_new (1);
|
KEYDB_HANDLE sec_hd = keydb_new (1);
|
||||||
|
|
||||||
/* FIXME: we may have to create the keyring first */
|
|
||||||
rc = keydb_locate_writable (pub_hd, NULL);
|
rc = keydb_locate_writable (pub_hd, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
log_error (_("no writable public keyring found: %s\n"),
|
log_error (_("no writable public keyring found: %s\n"),
|
||||||
g10_errstr (rc));
|
g10_errstr (rc));
|
||||||
|
|
||||||
if (!rc) {
|
if (!rc)
|
||||||
|
{
|
||||||
rc = keydb_locate_writable (sec_hd, NULL);
|
rc = keydb_locate_writable (sec_hd, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
log_error (_("no writable secret keyring found: %s\n"),
|
log_error (_("no writable secret keyring found: %s\n"),
|
||||||
g10_errstr (rc));
|
g10_errstr (rc));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rc && opt.verbose) {
|
if (!rc && opt.verbose)
|
||||||
|
{
|
||||||
log_info (_("writing public key to `%s'\n"),
|
log_info (_("writing public key to `%s'\n"),
|
||||||
keydb_get_resource_name (pub_hd));
|
keydb_get_resource_name (pub_hd));
|
||||||
if (card)
|
if (card)
|
||||||
@ -3258,14 +3362,16 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
keydb_get_resource_name (sec_hd));
|
keydb_get_resource_name (sec_hd));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rc) {
|
if (!rc)
|
||||||
|
{
|
||||||
rc = keydb_insert_keyblock (pub_hd, pub_root);
|
rc = keydb_insert_keyblock (pub_hd, pub_root);
|
||||||
if (rc)
|
if (rc)
|
||||||
log_error (_("error writing public keyring `%s': %s\n"),
|
log_error (_("error writing public keyring `%s': %s\n"),
|
||||||
keydb_get_resource_name (pub_hd), g10_errstr(rc));
|
keydb_get_resource_name (pub_hd), g10_errstr(rc));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rc) {
|
if (!rc)
|
||||||
|
{
|
||||||
rc = keydb_insert_keyblock (sec_hd, sec_root);
|
rc = keydb_insert_keyblock (sec_hd, sec_root);
|
||||||
if (rc)
|
if (rc)
|
||||||
log_error (_("error writing secret keyring `%s': %s\n"),
|
log_error (_("error writing secret keyring `%s': %s\n"),
|
||||||
@ -3275,22 +3381,26 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
keydb_release (pub_hd);
|
keydb_release (pub_hd);
|
||||||
keydb_release (sec_hd);
|
keydb_release (sec_hd);
|
||||||
|
|
||||||
if (!rc) {
|
if (!rc)
|
||||||
int no_enc_rsa =
|
{
|
||||||
get_parameter_algo(para, pKEYTYPE) == PUBKEY_ALGO_RSA
|
int no_enc_rsa;
|
||||||
|
PKT_public_key *pk;
|
||||||
|
|
||||||
|
no_enc_rsa = (get_parameter_algo (para, pKEYTYPE) == PUBKEY_ALGO_RSA
|
||||||
&& get_parameter_uint (para, pKEYUSAGE)
|
&& get_parameter_uint (para, pKEYUSAGE)
|
||||||
&& !(get_parameter_uint( para,pKEYUSAGE) & PUBKEY_USAGE_ENC);
|
&& !((get_parameter_uint (para, pKEYUSAGE)
|
||||||
PKT_public_key *pk = find_kbnode (pub_root,
|
& PUBKEY_USAGE_ENC)) );
|
||||||
PKT_PUBLIC_KEY)->pkt->pkt.public_key;
|
|
||||||
|
pk = find_kbnode (pub_root, PKT_PUBLIC_KEY)->pkt->pkt.public_key;
|
||||||
|
|
||||||
keyid_from_pk(pk,pk->main_keyid);
|
keyid_from_pk(pk,pk->main_keyid);
|
||||||
register_trusted_keyid(pk->main_keyid);
|
register_trusted_keyid(pk->main_keyid);
|
||||||
|
|
||||||
update_ownertrust (pk,
|
update_ownertrust (pk, ((get_ownertrust (pk) & ~TRUST_MASK)
|
||||||
((get_ownertrust (pk) & ~TRUST_MASK)
|
|
||||||
| TRUST_ULTIMATE ));
|
| TRUST_ULTIMATE ));
|
||||||
|
|
||||||
if (!opt.batch) {
|
if (!opt.batch)
|
||||||
|
{
|
||||||
tty_printf (_("public and secret key created and signed.\n") );
|
tty_printf (_("public and secret key created and signed.\n") );
|
||||||
tty_printf ("\n");
|
tty_printf ("\n");
|
||||||
list_keyblock(pub_root,0,1,NULL);
|
list_keyblock(pub_root,0,1,NULL);
|
||||||
@ -3310,14 +3420,16 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( rc ) {
|
if (rc)
|
||||||
|
{
|
||||||
if (opt.batch)
|
if (opt.batch)
|
||||||
log_error ("key generation failed: %s\n", g10_errstr(rc) );
|
log_error ("key generation failed: %s\n", g10_errstr(rc) );
|
||||||
else
|
else
|
||||||
tty_printf (_("Key generation failed: %s\n"), g10_errstr(rc) );
|
tty_printf (_("Key generation failed: %s\n"), g10_errstr(rc) );
|
||||||
print_status_key_not_created ( get_parameter_value (para, pHANDLE) );
|
print_status_key_not_created ( get_parameter_value (para, pHANDLE) );
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
PKT_public_key *pk = find_kbnode (pub_root,
|
PKT_public_key *pk = find_kbnode (pub_root,
|
||||||
PKT_PUBLIC_KEY)->pkt->pkt.public_key;
|
PKT_PUBLIC_KEY)->pkt->pkt.public_key;
|
||||||
print_status_key_created (did_sub? 'B':'P', pk,
|
print_status_key_created (did_sub? 'B':'P', pk,
|
||||||
@ -3326,17 +3438,15 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
release_kbnode( pub_root );
|
release_kbnode( pub_root );
|
||||||
release_kbnode( sec_root );
|
release_kbnode( sec_root );
|
||||||
|
|
||||||
if( pri_sk && !card) /* the unprotected secret key unless we have a */
|
if (pri_sk && !card) /* The unprotected secret key unless we */
|
||||||
free_secret_key(pri_sk); /* shallow copy in card mode. */
|
free_secret_key (pri_sk); /* have a shallow copy in card mode. */
|
||||||
if (sub_sk)
|
if (sub_sk)
|
||||||
free_secret_key(sub_sk);
|
free_secret_key(sub_sk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************
|
/* Add a new subkey to an existing key. Returns true if a new key has
|
||||||
* add a new subkey to an existing key.
|
been generated and put into the keyblocks. */
|
||||||
* Returns true if a new key has been generated and put into the keyblocks.
|
|
||||||
*/
|
|
||||||
int
|
int
|
||||||
generate_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock)
|
generate_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock)
|
||||||
{
|
{
|
||||||
@ -3354,36 +3464,42 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
|
|||||||
int ask_pass = 0;
|
int ask_pass = 0;
|
||||||
int canceled;
|
int canceled;
|
||||||
|
|
||||||
/* break out the primary secret key */
|
/* Break out the primary secret key. */
|
||||||
node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
|
node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
|
||||||
if( !node ) {
|
if( !node )
|
||||||
|
{
|
||||||
log_error ("Oops; secret key not found anymore!\n");
|
log_error ("Oops; secret key not found anymore!\n");
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make a copy of the sk to keep the protected one in the keyblock */
|
/* Make a copy of the sk to keep the protected one in the keyblock. */
|
||||||
pri_sk = copy_secret_key (NULL, node->pkt->pkt.secret_key);
|
pri_sk = copy_secret_key (NULL, node->pkt->pkt.secret_key);
|
||||||
|
|
||||||
cur_time = make_timestamp();
|
cur_time = make_timestamp();
|
||||||
if( pri_sk->timestamp > cur_time ) {
|
|
||||||
|
if (pri_sk->timestamp > cur_time)
|
||||||
|
{
|
||||||
ulong d = pri_sk->timestamp - cur_time;
|
ulong d = pri_sk->timestamp - cur_time;
|
||||||
log_info ( d==1 ? _("key has been created %lu second "
|
log_info ( d==1 ? _("key has been created %lu second "
|
||||||
"in future (time warp or clock problem)\n")
|
"in future (time warp or clock problem)\n")
|
||||||
: _("key has been created %lu seconds "
|
: _("key has been created %lu seconds "
|
||||||
"in future (time warp or clock problem)\n"), d );
|
"in future (time warp or clock problem)\n"), d );
|
||||||
if( !opt.ignore_time_conflict ) {
|
if (!opt.ignore_time_conflict)
|
||||||
|
{
|
||||||
rc = G10ERR_TIME_CONFLICT;
|
rc = G10ERR_TIME_CONFLICT;
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pri_sk->version < 4) {
|
if (pri_sk->version < 4)
|
||||||
|
{
|
||||||
log_info (_("NOTE: creating subkeys for v3 keys "
|
log_info (_("NOTE: creating subkeys for v3 keys "
|
||||||
"is not OpenPGP compliant\n"));
|
"is not OpenPGP compliant\n"));
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pri_sk->is_protected && pri_sk->protect.s2k.mode == 1001) {
|
if (pri_sk->is_protected && pri_sk->protect.s2k.mode == 1001)
|
||||||
|
{
|
||||||
tty_printf (_("Secret parts of primary key are not available.\n"));
|
tty_printf (_("Secret parts of primary key are not available.\n"));
|
||||||
rc = G10ERR_NO_SECKEY;
|
rc = G10ERR_NO_SECKEY;
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -3391,7 +3507,8 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
|
|||||||
|
|
||||||
|
|
||||||
/* Unprotect to get the passphrase. */
|
/* Unprotect to get the passphrase. */
|
||||||
switch( is_secret_key_protected( pri_sk ) ) {
|
switch (is_secret_key_protected (pri_sk) )
|
||||||
|
{
|
||||||
case -1:
|
case -1:
|
||||||
rc = G10ERR_PUBKEY_ALGO;
|
rc = G10ERR_PUBKEY_ALGO;
|
||||||
break;
|
break;
|
||||||
@ -3423,7 +3540,8 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
|
|||||||
canceled = 0;
|
canceled = 0;
|
||||||
if (ask_pass)
|
if (ask_pass)
|
||||||
dek = do_ask_passphrase (&s2k, &canceled);
|
dek = do_ask_passphrase (&s2k, &canceled);
|
||||||
else if (passphrase) {
|
else if (passphrase)
|
||||||
|
{
|
||||||
s2k = xmalloc_secure ( sizeof *s2k );
|
s2k = xmalloc_secure ( sizeof *s2k );
|
||||||
s2k->mode = opt.s2k_mode;
|
s2k->mode = opt.s2k_mode;
|
||||||
s2k->hash_algo = S2K_DIGEST_ALGO;
|
s2k->hash_algo = S2K_DIGEST_ALGO;
|
||||||
@ -3437,12 +3555,15 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
|
|||||||
|
|
||||||
if (!rc)
|
if (!rc)
|
||||||
rc = do_create (algo, nbits, pub_keyblock, sec_keyblock,
|
rc = do_create (algo, nbits, pub_keyblock, sec_keyblock,
|
||||||
dek, s2k, &sub_sk, expire, 1 );
|
dek, s2k, &sub_sk, cur_time, expire, 1 );
|
||||||
if (!rc)
|
if (!rc)
|
||||||
rc = write_keybinding(pub_keyblock, pub_keyblock, pri_sk, sub_sk, use);
|
rc = write_keybinding (pub_keyblock, pub_keyblock, pri_sk, sub_sk,
|
||||||
|
use, cur_time);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
rc = write_keybinding(sec_keyblock, pub_keyblock, pri_sk, sub_sk, use);
|
rc = write_keybinding (sec_keyblock, pub_keyblock, pri_sk, sub_sk,
|
||||||
if( !rc ) {
|
use, cur_time);
|
||||||
|
if (!rc)
|
||||||
|
{
|
||||||
okay = 1;
|
okay = 1;
|
||||||
write_status_text (STATUS_KEY_CREATED, "S");
|
write_status_text (STATUS_KEY_CREATED, "S");
|
||||||
}
|
}
|
||||||
@ -3453,7 +3574,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
|
|||||||
xfree (passphrase);
|
xfree (passphrase);
|
||||||
xfree (dek);
|
xfree (dek);
|
||||||
xfree (s2k);
|
xfree (s2k);
|
||||||
/* release the copy of the (now unprotected) secret keys */
|
/* Release the copy of the (now unprotected) secret keys. */
|
||||||
if (pri_sk)
|
if (pri_sk)
|
||||||
free_secret_key (pri_sk);
|
free_secret_key (pri_sk);
|
||||||
if (sub_sk)
|
if (sub_sk)
|
||||||
@ -3551,12 +3672,17 @@ generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock,
|
|||||||
|
|
||||||
if (passphrase)
|
if (passphrase)
|
||||||
set_next_passphrase (passphrase);
|
set_next_passphrase (passphrase);
|
||||||
|
|
||||||
|
/* Note, that depending on the backend, the card key generation may
|
||||||
|
update CUR_TIME. */
|
||||||
rc = gen_card_key (algo, keyno, 0, pub_keyblock, sec_keyblock,
|
rc = gen_card_key (algo, keyno, 0, pub_keyblock, sec_keyblock,
|
||||||
&sub_sk, expire, para);
|
&sub_sk, &cur_time, expire, para);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
rc = write_keybinding (pub_keyblock, pub_keyblock, pri_sk, sub_sk, use);
|
rc = write_keybinding (pub_keyblock, pub_keyblock, pri_sk, sub_sk,
|
||||||
|
use, cur_time);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
rc = write_keybinding (sec_keyblock, pub_keyblock, pri_sk, sub_sk, use);
|
rc = write_keybinding (sec_keyblock, pub_keyblock, pri_sk, sub_sk,
|
||||||
|
use, cur_time);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
okay = 1;
|
okay = 1;
|
||||||
@ -3577,7 +3703,7 @@ generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock,
|
|||||||
#endif /* !ENABLE_CARD_SUPPORT */
|
#endif /* !ENABLE_CARD_SUPPORT */
|
||||||
|
|
||||||
|
|
||||||
/****************
|
/*
|
||||||
* Write a keyblock to an output stream
|
* Write a keyblock to an output stream
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
@ -3601,10 +3727,11 @@ write_keyblock( IOBUF out, KBNODE node )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Note that timestamp is an in/out arg. */
|
||||||
static int
|
static int
|
||||||
gen_card_key (int algo, int keyno, int is_primary,
|
gen_card_key (int algo, int keyno, int is_primary,
|
||||||
KBNODE pub_root, KBNODE sec_root, PKT_secret_key **ret_sk,
|
KBNODE pub_root, KBNODE sec_root, PKT_secret_key **ret_sk,
|
||||||
u32 expireval, struct para_data_s *para)
|
u32 *timestamp, u32 expireval, struct para_data_s *para)
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_CARD_SUPPORT
|
#ifdef ENABLE_CARD_SUPPORT
|
||||||
int rc;
|
int rc;
|
||||||
@ -3617,7 +3744,7 @@ gen_card_key (int algo, int keyno, int is_primary,
|
|||||||
assert (algo == PUBKEY_ALGO_RSA);
|
assert (algo == PUBKEY_ALGO_RSA);
|
||||||
|
|
||||||
/* Fixme: We don't have the serialnumber available, thus passing NULL. */
|
/* Fixme: We don't have the serialnumber available, thus passing NULL. */
|
||||||
rc = agent_scd_genkey (&info, keyno, 1, NULL);
|
rc = agent_scd_genkey (&info, keyno, 1, NULL, *timestamp);
|
||||||
/* if (gpg_err_code (rc) == GPG_ERR_EEXIST) */
|
/* if (gpg_err_code (rc) == GPG_ERR_EEXIST) */
|
||||||
/* { */
|
/* { */
|
||||||
/* tty_printf ("\n"); */
|
/* tty_printf ("\n"); */
|
||||||
@ -3641,6 +3768,9 @@ gen_card_key (int algo, int keyno, int is_primary,
|
|||||||
return gpg_error (GPG_ERR_GENERAL);
|
return gpg_error (GPG_ERR_GENERAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (*timestamp != info.created_at)
|
||||||
|
log_info ("Note that the key does not use the suggested creation date\n");
|
||||||
|
*timestamp = info.created_at;
|
||||||
|
|
||||||
pk = xcalloc (1, sizeof *pk );
|
pk = xcalloc (1, sizeof *pk );
|
||||||
sk = xcalloc (1, sizeof *sk );
|
sk = xcalloc (1, sizeof *sk );
|
||||||
@ -3688,6 +3818,7 @@ gen_card_key (int algo, int keyno, int is_primary,
|
|||||||
static int
|
static int
|
||||||
gen_card_key_with_backup (int algo, int keyno, int is_primary,
|
gen_card_key_with_backup (int algo, int keyno, int is_primary,
|
||||||
KBNODE pub_root, KBNODE sec_root,
|
KBNODE pub_root, KBNODE sec_root,
|
||||||
|
u32 timestamp,
|
||||||
u32 expireval, struct para_data_s *para,
|
u32 expireval, struct para_data_s *para,
|
||||||
const char *backup_dir)
|
const char *backup_dir)
|
||||||
{
|
{
|
||||||
@ -3700,7 +3831,7 @@ gen_card_key_with_backup (int algo, int keyno, int is_primary,
|
|||||||
size_t n;
|
size_t n;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
rc = generate_raw_key (algo, 1024, make_timestamp (),
|
rc = generate_raw_key (algo, 1024, timestamp,
|
||||||
&sk_unprotected, &sk_protected);
|
&sk_unprotected, &sk_protected);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
@ -3857,8 +3988,8 @@ save_unprotected_key_to_card (PKT_secret_key *sk, int keyno)
|
|||||||
/* Copy the parameters into straight buffers. */
|
/* Copy the parameters into straight buffers. */
|
||||||
gcry_mpi_aprint (GCRYMPI_FMT_USG, &rsa_n, &rsa_n_len, sk->skey[0]);
|
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]);
|
gcry_mpi_aprint (GCRYMPI_FMT_USG, &rsa_e, &rsa_e_len, sk->skey[1]);
|
||||||
gcry_mpi_aprint (GCRYMPI_FMT_USG, &rsa_p, &rsa_p_len, sk->skey[2]);
|
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[3]);
|
gcry_mpi_aprint (GCRYMPI_FMT_USG, &rsa_q, &rsa_q_len, sk->skey[4]);
|
||||||
if (!rsa_n || !rsa_e || !rsa_p || !rsa_q)
|
if (!rsa_n || !rsa_e || !rsa_p || !rsa_q)
|
||||||
{
|
{
|
||||||
rc = G10ERR_INV_ARG;
|
rc = G10ERR_INV_ARG;
|
||||||
|
@ -198,7 +198,8 @@ int keygen_add_keyserver_url(PKT_signature *sig, void *opaque);
|
|||||||
int keygen_add_notations(PKT_signature *sig,void *opaque);
|
int keygen_add_notations(PKT_signature *sig,void *opaque);
|
||||||
int keygen_add_revkey(PKT_signature *sig, void *opaque);
|
int keygen_add_revkey(PKT_signature *sig, void *opaque);
|
||||||
int make_backsig(PKT_signature *sig,PKT_public_key *pk,
|
int make_backsig(PKT_signature *sig,PKT_public_key *pk,
|
||||||
PKT_public_key *sub_pk,PKT_secret_key *sub_sk);
|
PKT_public_key *sub_pk,PKT_secret_key *sub_sk,
|
||||||
|
u32 timestamp);
|
||||||
int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock );
|
int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock );
|
||||||
#ifdef ENABLE_CARD_SUPPORT
|
#ifdef ENABLE_CARD_SUPPORT
|
||||||
int generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock,
|
int generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock,
|
||||||
|
368
po/pt_BR.po
368
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
368
po/zh_CN.po
368
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
368
po/zh_TW.po
368
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,14 @@
|
|||||||
|
2007-07-05 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* command.c (has_option_name, skip_options): New.
|
||||||
|
(cmd_genkey): Add option --timestamp.
|
||||||
|
(cmd_writekey): Enter confidential mode while inquiring the key data.
|
||||||
|
|
||||||
|
* app.c (app_genkey): Add arg CREATETIME.
|
||||||
|
* app-common.h (app_ctx_s): Likewise
|
||||||
|
* app-openpgp.c (do_genkey): Ditto. Use it.
|
||||||
|
|
||||||
|
|
||||||
2007-07-04 Werner Koch <wk@g10code.com>
|
2007-07-04 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* command.c (cmd_getinfo): New subcommand "version".
|
* command.c (cmd_getinfo): New subcommand "version".
|
||||||
|
@ -97,6 +97,7 @@ struct app_ctx_s {
|
|||||||
const unsigned char *pk, size_t pklen);
|
const unsigned char *pk, size_t pklen);
|
||||||
gpg_error_t (*genkey) (app_t app, ctrl_t ctrl,
|
gpg_error_t (*genkey) (app_t app, ctrl_t ctrl,
|
||||||
const char *keynostr, unsigned int flags,
|
const char *keynostr, unsigned int flags,
|
||||||
|
time_t createtime,
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
void *pincb_arg);
|
void *pincb_arg);
|
||||||
gpg_error_t (*change_pin) (app_t app, ctrl_t ctrl,
|
gpg_error_t (*change_pin) (app_t app, ctrl_t ctrl,
|
||||||
@ -167,6 +168,7 @@ gpg_error_t app_writekey (app_t app, ctrl_t ctrl,
|
|||||||
const unsigned char *keydata, size_t keydatalen);
|
const unsigned char *keydata, size_t keydatalen);
|
||||||
gpg_error_t app_genkey (app_t app, ctrl_t ctrl,
|
gpg_error_t app_genkey (app_t app, ctrl_t ctrl,
|
||||||
const char *keynostr, unsigned int flags,
|
const char *keynostr, unsigned int flags,
|
||||||
|
time_t createtime,
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
void *pincb_arg);
|
void *pincb_arg);
|
||||||
gpg_error_t app_get_challenge (app_t app, size_t nbytes,
|
gpg_error_t app_get_challenge (app_t app, size_t nbytes,
|
||||||
|
@ -1981,6 +1981,7 @@ do_writekey (app_t app, ctrl_t ctrl,
|
|||||||
/* Handle the GENKEY command. */
|
/* Handle the GENKEY command. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
|
do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
|
||||||
|
time_t createtime,
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
void *pincb_arg)
|
void *pincb_arg)
|
||||||
{
|
{
|
||||||
@ -2014,7 +2015,7 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
|
|||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
/* Prepare for key generation by verifying the ADmin PIN. */
|
/* Prepare for key generation by verifying the Admin PIN. */
|
||||||
rc = verify_chv3 (app, pincb, pincb_arg);
|
rc = verify_chv3 (app, pincb, pincb_arg);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -2067,7 +2068,7 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
|
|||||||
/* log_printhex ("RSA e:", e, elen); */
|
/* log_printhex ("RSA e:", e, elen); */
|
||||||
send_key_data (ctrl, "e", e, elen);
|
send_key_data (ctrl, "e", e, elen);
|
||||||
|
|
||||||
created_at = gnupg_get_time ();
|
created_at = createtime? createtime : gnupg_get_time ();
|
||||||
sprintf (numbuf, "%lu", (unsigned long)created_at);
|
sprintf (numbuf, "%lu", (unsigned long)created_at);
|
||||||
send_status_info (ctrl, "KEY-CREATED-AT",
|
send_status_info (ctrl, "KEY-CREATED-AT",
|
||||||
numbuf, (size_t)strlen(numbuf), NULL, 0);
|
numbuf, (size_t)strlen(numbuf), NULL, 0);
|
||||||
|
@ -766,6 +766,7 @@ app_writekey (app_t app, ctrl_t ctrl,
|
|||||||
/* Perform a SETATTR operation. */
|
/* Perform a SETATTR operation. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
app_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
|
app_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
|
||||||
|
time_t createtime,
|
||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
void *pincb_arg)
|
void *pincb_arg)
|
||||||
{
|
{
|
||||||
@ -780,7 +781,8 @@ app_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
|
|||||||
err = lock_reader (app->slot);
|
err = lock_reader (app->slot);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
err = app->fnc.genkey (app, ctrl, keynostr, flags, pincb, pincb_arg);
|
err = app->fnc.genkey (app, ctrl, keynostr, flags,
|
||||||
|
createtime, pincb, pincb_arg);
|
||||||
unlock_reader (app->slot);
|
unlock_reader (app->slot);
|
||||||
if (opt.verbose)
|
if (opt.verbose)
|
||||||
log_info ("operation genkey result: %s\n", gpg_strerror (err));
|
log_info ("operation genkey result: %s\n", gpg_strerror (err));
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/* command.c - SCdaemon command handler
|
/* command.c - SCdaemon command handler
|
||||||
* Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
* Copyright (C) 2001, 2002, 2003, 2004, 2005,
|
||||||
|
* 2007 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -178,6 +179,41 @@ has_option (const char *line, const char *name)
|
|||||||
return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
|
return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Same as has_option but does only test for the name of the option
|
||||||
|
and ignores an argument, i.e. with NAME being "--hash" it would
|
||||||
|
return a pointer for "--hash" as well as for "--hash=foo". If
|
||||||
|
thhere is no such option NULL is returned. The pointer returned
|
||||||
|
points right behind the option name, this may be an equal sign, Nul
|
||||||
|
or a space. */
|
||||||
|
static const char *
|
||||||
|
has_option_name (const char *line, const char *name)
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
int n = strlen (name);
|
||||||
|
|
||||||
|
s = strstr (line, name);
|
||||||
|
return (s && (s == line || spacep (s-1))
|
||||||
|
&& (!s[n] || spacep (s+n) || s[n] == '=')) ? (s+n) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Skip over options. It is assumed that leading spaces have been
|
||||||
|
removed (this is the case for lines passed to a handler from
|
||||||
|
assuan). Blanks after the options are also removed. */
|
||||||
|
static char *
|
||||||
|
skip_options (char *line)
|
||||||
|
{
|
||||||
|
while ( *line == '-' && line[1] == '-' )
|
||||||
|
{
|
||||||
|
while (*line && !spacep (line))
|
||||||
|
line++;
|
||||||
|
while (spacep (line))
|
||||||
|
line++;
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Convert the STRING into a newly allocated buffer while translating
|
/* Convert the STRING into a newly allocated buffer while translating
|
||||||
the hex numbers. Stops at the first invalid character. Blanks and
|
the hex numbers. Stops at the first invalid character. Blanks and
|
||||||
@ -1099,7 +1135,9 @@ cmd_writekey (assuan_context_t ctx, char *line)
|
|||||||
return out_of_core ();
|
return out_of_core ();
|
||||||
|
|
||||||
/* Now get the actual keydata. */
|
/* Now get the actual keydata. */
|
||||||
|
assuan_begin_confidential (ctx);
|
||||||
rc = assuan_inquire (ctx, "KEYDATA", &keydata, &keydatalen, MAXLEN_KEYDATA);
|
rc = assuan_inquire (ctx, "KEYDATA", &keydata, &keydatalen, MAXLEN_KEYDATA);
|
||||||
|
assuan_end_confidential (ctx);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
xfree (keyid);
|
xfree (keyid);
|
||||||
@ -1118,7 +1156,7 @@ cmd_writekey (assuan_context_t ctx, char *line)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* GENKEY [--force] <no>
|
/* GENKEY [--force] [--timestamp=<isodate>] <no>
|
||||||
|
|
||||||
Generate a key on-card identified by NO, which is application
|
Generate a key on-card identified by NO, which is application
|
||||||
specific. Return values are application specific. For OpenPGP
|
specific. Return values are application specific. For OpenPGP
|
||||||
@ -1128,11 +1166,14 @@ cmd_writekey (assuan_context_t ctx, char *line)
|
|||||||
S KEY-CREATED-AT <seconds_since_epoch>
|
S KEY-CREATED-AT <seconds_since_epoch>
|
||||||
S KEY-DATA [p|n] <hexdata>
|
S KEY-DATA [p|n] <hexdata>
|
||||||
|
|
||||||
|
|
||||||
--force is required to overwrite an already existing key. The
|
--force is required to overwrite an already existing key. The
|
||||||
KEY-CREATED-AT is required for further processing because it is
|
KEY-CREATED-AT is required for further processing because it is
|
||||||
part of the hashed key material for the fingerprint.
|
part of the hashed key material for the fingerprint.
|
||||||
|
|
||||||
|
If --timestamp is given an OpenPGP key will be created using this
|
||||||
|
value. The value needs to be in ISO Format; e.g.
|
||||||
|
"--timestamp=20030316T120000" and after 1970-01-01 00:00:00.
|
||||||
|
|
||||||
The public part of the key can also later be retrieved using the
|
The public part of the key can also later be retrieved using the
|
||||||
READKEY command.
|
READKEY command.
|
||||||
|
|
||||||
@ -1143,19 +1184,28 @@ cmd_genkey (assuan_context_t ctx, char *line)
|
|||||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||||
int rc;
|
int rc;
|
||||||
char *keyno;
|
char *keyno;
|
||||||
int force = has_option (line, "--force");
|
int force;
|
||||||
|
const char *s;
|
||||||
|
time_t timestamp;
|
||||||
|
|
||||||
if ( IS_LOCKED (ctrl) )
|
if ( IS_LOCKED (ctrl) )
|
||||||
return gpg_error (GPG_ERR_LOCKED);
|
return gpg_error (GPG_ERR_LOCKED);
|
||||||
|
|
||||||
/* Skip over options. */
|
force = has_option (line, "--force");
|
||||||
while ( *line == '-' && line[1] == '-' )
|
|
||||||
|
if ((s=has_option_name (line, "--timestamp")))
|
||||||
{
|
{
|
||||||
while (*line && !spacep (line))
|
if (*s != '=')
|
||||||
line++;
|
return set_error (GPG_ERR_ASS_PARAMETER, "missing value for option");
|
||||||
while (spacep (line))
|
timestamp = isotime2epoch (s+1);
|
||||||
line++;
|
if (timestamp < 1)
|
||||||
|
return set_error (GPG_ERR_ASS_PARAMETER, "invalid time value");
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
timestamp = 0;
|
||||||
|
|
||||||
|
|
||||||
|
line = skip_options (line);
|
||||||
if (!*line)
|
if (!*line)
|
||||||
return set_error (GPG_ERR_ASS_PARAMETER, "no key number given");
|
return set_error (GPG_ERR_ASS_PARAMETER, "no key number given");
|
||||||
keyno = line;
|
keyno = line;
|
||||||
@ -1172,7 +1222,8 @@ cmd_genkey (assuan_context_t ctx, char *line)
|
|||||||
keyno = xtrystrdup (keyno);
|
keyno = xtrystrdup (keyno);
|
||||||
if (!keyno)
|
if (!keyno)
|
||||||
return out_of_core ();
|
return out_of_core ();
|
||||||
rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0, pin_cb, ctx);
|
rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0,
|
||||||
|
timestamp, pin_cb, ctx);
|
||||||
xfree (keyno);
|
xfree (keyno);
|
||||||
|
|
||||||
TEST_CARD_REMOVAL (ctrl, rc);
|
TEST_CARD_REMOVAL (ctrl, rc);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user