mirror of
git://git.gnupg.org/gnupg.git
synced 2025-04-17 15:44:34 +02:00
Key generation and signing using the OpenPGP card does rudimentary work.
This commit is contained in:
parent
b7bd5e8088
commit
5c46f134e2
2
NEWS
2
NEWS
@ -1,6 +1,8 @@
|
|||||||
Noteworthy changes in version 1.9.0 (unreleased)
|
Noteworthy changes in version 1.9.0 (unreleased)
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
|
* gpg does now also use libgcrypt, libgpg-error is required.
|
||||||
|
|
||||||
* New gpgsm commands --call-dirmngr and --call-protect-tool.
|
* New gpgsm commands --call-dirmngr and --call-protect-tool.
|
||||||
|
|
||||||
* Changing a passphrase is now possible using "gpgsm --passwd"
|
* Changing a passphrase is now possible using "gpgsm --passwd"
|
||||||
|
@ -1,3 +1,25 @@
|
|||||||
|
2003-06-27 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
|
* seckey-cert.c (check_secret_key): Bypass the unprotection for
|
||||||
|
mode 1002.
|
||||||
|
* sign.c (do_sign): Handle card case (i.e. mode 1002).
|
||||||
|
|
||||||
|
2003-06-26 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
|
* build-packet.c (do_secret_key): Implement special protection
|
||||||
|
mode 1002.
|
||||||
|
* parse-packet.c (parse_key): Likewise.
|
||||||
|
|
||||||
|
* keygen.c (smartcard_gen_key): New.
|
||||||
|
* call-agent.c (agent_scd_setattr): New.
|
||||||
|
|
||||||
|
2003-06-24 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
|
* Makefile.am: Removed signal.c
|
||||||
|
|
||||||
|
* g10.c (emergency_cleanup): New.
|
||||||
|
(main): Use gnupg_init_signals and register malloc for assuan.
|
||||||
|
|
||||||
2003-06-23 Werner Koch <wk@gnupg.org>
|
2003-06-23 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
* keyid.c (do_fingerprint_md): Made it work again.
|
* keyid.c (do_fingerprint_md): Made it work again.
|
||||||
|
@ -63,8 +63,7 @@ common_source = \
|
|||||||
plaintext.c \
|
plaintext.c \
|
||||||
sig-check.c \
|
sig-check.c \
|
||||||
keylist.c \
|
keylist.c \
|
||||||
pkglue.c pkglue.h \
|
pkglue.c pkglue.h
|
||||||
signal.c
|
|
||||||
|
|
||||||
gpg_SOURCES = g10.c \
|
gpg_SOURCES = g10.c \
|
||||||
$(common_source) \
|
$(common_source) \
|
||||||
|
@ -415,8 +415,9 @@ do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk )
|
|||||||
if( sk->protect.s2k.mode == 3 )
|
if( sk->protect.s2k.mode == 3 )
|
||||||
iobuf_put(a, sk->protect.s2k.count );
|
iobuf_put(a, sk->protect.s2k.count );
|
||||||
|
|
||||||
/* For out special mode 1001 we do not need an IV */
|
/* For out special modes 1001 and 1002 we do not need an IV */
|
||||||
if( sk->protect.s2k.mode != 1001 )
|
if( sk->protect.s2k.mode != 1001
|
||||||
|
&& sk->protect.s2k.mode != 1002 )
|
||||||
iobuf_write(a, sk->protect.iv, sk->protect.ivlen );
|
iobuf_write(a, sk->protect.iv, sk->protect.ivlen );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -425,6 +426,11 @@ do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk )
|
|||||||
|
|
||||||
if( sk->protect.s2k.mode == 1001 )
|
if( sk->protect.s2k.mode == 1001 )
|
||||||
; /* GnuPG extension - don't write a secret key at all */
|
; /* GnuPG extension - don't write a secret key at all */
|
||||||
|
else if( sk->protect.s2k.mode == 1002 )
|
||||||
|
{ /* GnuPG extension - divert to OpenPGP smartcard. */
|
||||||
|
iobuf_put(a, 0 ); /* length of the serial number or 0 for unknown. */
|
||||||
|
/* fixme: write the serial number. */
|
||||||
|
}
|
||||||
else if( sk->is_protected && sk->version >= 4 ) {
|
else if( sk->is_protected && sk->version >= 4 ) {
|
||||||
/* The secret key is protected - write it out as it is */
|
/* The secret key is protected - write it out as it is */
|
||||||
byte *p;
|
byte *p;
|
||||||
|
311
g10/call-agent.c
311
g10/call-agent.c
@ -47,7 +47,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static ASSUAN_CONTEXT agent_ctx = NULL;
|
static ASSUAN_CONTEXT agent_ctx = NULL;
|
||||||
static int force_pipe_server = 0;
|
static int force_pipe_server = 1; /* FIXME: set this back to 0. */
|
||||||
|
|
||||||
struct cipher_parm_s {
|
struct cipher_parm_s {
|
||||||
ASSUAN_CONTEXT ctx;
|
ASSUAN_CONTEXT ctx;
|
||||||
@ -61,11 +61,6 @@ struct genkey_parm_s {
|
|||||||
size_t sexplen;
|
size_t sexplen;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct learn_parm_s {
|
|
||||||
int error;
|
|
||||||
ASSUAN_CONTEXT ctx;
|
|
||||||
struct membuf *data;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* Try to connect to the agent via socket or fork it off and work by
|
/* Try to connect to the agent via socket or fork it off and work by
|
||||||
@ -292,14 +287,57 @@ start_agent (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static AssuanError
|
/* Return a new malloced string by unescaping the string S. Escaping
|
||||||
membuf_data_cb (void *opaque, const void *buffer, size_t length)
|
is percent escaping and '+'/space mapping. A binary nul will
|
||||||
|
silently be replaced by a 0xFF. Function returns NULL to indicate
|
||||||
|
an out of memory status. */
|
||||||
|
static char *
|
||||||
|
unescape_status_string (const unsigned char *s)
|
||||||
{
|
{
|
||||||
membuf_t *data = opaque;
|
char *buffer, *d;
|
||||||
|
|
||||||
if (buffer)
|
buffer = d = xtrymalloc (strlen (s)+1);
|
||||||
put_membuf (data, buffer, length);
|
if (!buffer)
|
||||||
return 0;
|
return NULL;
|
||||||
|
while (*s)
|
||||||
|
{
|
||||||
|
if (*s == '%' && s[1] && s[2])
|
||||||
|
{
|
||||||
|
s++;
|
||||||
|
*d = xtoi_2 (s);
|
||||||
|
if (!*d)
|
||||||
|
*d = '\xff';
|
||||||
|
d++;
|
||||||
|
s += 2;
|
||||||
|
}
|
||||||
|
else if (*s == '+')
|
||||||
|
{
|
||||||
|
*d++ = ' ';
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*d++ = *s++;
|
||||||
|
}
|
||||||
|
*d = 0;
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Take a 20 byte hexencoded string and put it into the the provided
|
||||||
|
20 byte buffer FPR in binary format. */
|
||||||
|
static int
|
||||||
|
unhexify_fpr (const char *hexstr, unsigned char *fpr)
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
for (s=hexstr, n=0; hexdigitp (s); s++, n++)
|
||||||
|
;
|
||||||
|
if (*s || (n != 40))
|
||||||
|
return 0; /* no fingerprint (invalid or wrong length). */
|
||||||
|
n /= 2;
|
||||||
|
for (s=hexstr, n=0; *s; s += 2, n++)
|
||||||
|
fpr[n] = xtoi_2 (s);
|
||||||
|
return 1; /* okay */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -391,10 +429,161 @@ agent_havekey (const char *hexkeygrip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Ask the agent to change the passphrase of the key identified by
|
static AssuanError
|
||||||
HEXKEYGRIP. */
|
learn_status_cb (void *opaque, const char *line)
|
||||||
|
{
|
||||||
|
struct agent_card_info_s *parm = opaque;
|
||||||
|
const char *keyword = line;
|
||||||
|
int keywordlen;
|
||||||
|
|
||||||
|
log_debug ("got status line `%s'\n", line);
|
||||||
|
for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
|
||||||
|
;
|
||||||
|
while (spacep (line))
|
||||||
|
line++;
|
||||||
|
|
||||||
|
if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
|
||||||
|
{
|
||||||
|
parm->disp_name = unescape_status_string (line);
|
||||||
|
}
|
||||||
|
else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY_URL", keywordlen))
|
||||||
|
{
|
||||||
|
parm->pubkey_url = unescape_status_string (line);
|
||||||
|
}
|
||||||
|
else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
|
||||||
|
{
|
||||||
|
int no = atoi (line);
|
||||||
|
while (!spacep (line))
|
||||||
|
line++;
|
||||||
|
while (spacep (line))
|
||||||
|
line++;
|
||||||
|
if (no == 1)
|
||||||
|
parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
|
||||||
|
else if (no == 2)
|
||||||
|
parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
|
||||||
|
else if (no == 3)
|
||||||
|
parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call the agent to learn about a smartcard */
|
||||||
int
|
int
|
||||||
agent_passwd (const char *hexkeygrip)
|
agent_learn (struct agent_card_info_s *info)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = start_agent ();
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
memset (info, 0, sizeof *info);
|
||||||
|
rc = assuan_transact (agent_ctx, "LEARN --send",
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
learn_status_cb, info);
|
||||||
|
|
||||||
|
return map_assuan_err (rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Send an setattr command to the SCdaemon. */
|
||||||
|
int
|
||||||
|
agent_scd_setattr (const char *name,
|
||||||
|
const unsigned char *value, size_t valuelen)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
char line[ASSUAN_LINELENGTH];
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (!*name || !valuelen)
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
|
/* We assume that NAME does not need escaping. */
|
||||||
|
if (12 + strlen (name) > DIM(line)-1)
|
||||||
|
return gpg_error (GPG_ERR_TOO_LARGE);
|
||||||
|
|
||||||
|
p = stpcpy (stpcpy (line, "SCD SETATTR "), name);
|
||||||
|
*p++ = ' ';
|
||||||
|
for (; valuelen; value++, valuelen--)
|
||||||
|
{
|
||||||
|
if (p >= line + DIM(line)-5 )
|
||||||
|
return gpg_error (GPG_ERR_TOO_LARGE);
|
||||||
|
if (*value < ' ' || *value == '+' || *value == '%')
|
||||||
|
{
|
||||||
|
sprintf (p, "%%%02X", *value);
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
else if (*value == ' ')
|
||||||
|
*p++ = '+';
|
||||||
|
else
|
||||||
|
*p++ = *value;
|
||||||
|
}
|
||||||
|
*p = 0;
|
||||||
|
|
||||||
|
rc = start_agent ();
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
return map_assuan_err (rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Status callback for the SCD GENKEY command. */
|
||||||
|
static AssuanError
|
||||||
|
scd_genkey_cb (void *opaque, const char *line)
|
||||||
|
{
|
||||||
|
struct agent_card_genkey_s *parm = opaque;
|
||||||
|
const char *keyword = line;
|
||||||
|
int keywordlen;
|
||||||
|
gpg_error_t rc;
|
||||||
|
|
||||||
|
log_debug ("got status line `%s'\n", line);
|
||||||
|
for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
|
||||||
|
;
|
||||||
|
while (spacep (line))
|
||||||
|
line++;
|
||||||
|
|
||||||
|
if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
|
||||||
|
{
|
||||||
|
parm->fprvalid = unhexify_fpr (line, parm->fpr);
|
||||||
|
}
|
||||||
|
if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
|
||||||
|
{
|
||||||
|
gcry_mpi_t a;
|
||||||
|
const char *name = line;
|
||||||
|
|
||||||
|
while (!spacep (line))
|
||||||
|
line++;
|
||||||
|
while (spacep (line))
|
||||||
|
line++;
|
||||||
|
|
||||||
|
rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0);
|
||||||
|
if (rc)
|
||||||
|
log_error ("error parsing received key data: %s\n", gpg_strerror (rc));
|
||||||
|
else if (*name == 'n' && spacep (name+1))
|
||||||
|
parm->n = a;
|
||||||
|
else if (*name == 'e' && spacep (name+1))
|
||||||
|
parm->e = a;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_info ("unknown parameter name in received key data\n");
|
||||||
|
gcry_mpi_release (a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
|
||||||
|
{
|
||||||
|
parm->created_at = (u32)strtoul (line, NULL, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send a GENKEY command to the SCdaemon. */
|
||||||
|
int
|
||||||
|
agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
char line[ASSUAN_LINELENGTH];
|
char line[ASSUAN_LINELENGTH];
|
||||||
@ -403,13 +592,95 @@ agent_passwd (const char *hexkeygrip)
|
|||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (!hexkeygrip || strlen (hexkeygrip) != 40)
|
memset (info, 0, sizeof *info);
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
snprintf (line, DIM(line)-1, "SCD GENKEY %s%d",
|
||||||
|
force? "--force ":"", keyno);
|
||||||
snprintf (line, DIM(line)-1, "PASSWD %s", hexkeygrip);
|
|
||||||
line[DIM(line)-1] = 0;
|
line[DIM(line)-1] = 0;
|
||||||
|
|
||||||
rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
memset (info, 0, sizeof *info);
|
||||||
|
rc = assuan_transact (agent_ctx, line,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
scd_genkey_cb, info);
|
||||||
|
|
||||||
return map_assuan_err (rc);
|
return map_assuan_err (rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static AssuanError
|
||||||
|
membuf_data_cb (void *opaque, const void *buffer, size_t length)
|
||||||
|
{
|
||||||
|
membuf_t *data = opaque;
|
||||||
|
|
||||||
|
if (buffer)
|
||||||
|
put_membuf (data, buffer, length);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send a sign command to the scdaemon via gpg-agent's pass thru
|
||||||
|
mechanism. */
|
||||||
|
int
|
||||||
|
agent_scd_pksign (const char *keyid, int hashalgo,
|
||||||
|
const unsigned char *indata, size_t indatalen,
|
||||||
|
char **r_buf, size_t *r_buflen)
|
||||||
|
{
|
||||||
|
int rc, i;
|
||||||
|
char *p, line[ASSUAN_LINELENGTH];
|
||||||
|
membuf_t data;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
/* Note, hashalgo is not yet used but hardwired to SHA1 in SCdaemon. */
|
||||||
|
|
||||||
|
*r_buf = NULL;
|
||||||
|
*r_buflen = 0;
|
||||||
|
|
||||||
|
rc = start_agent ();
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (indatalen*2 + 50 > DIM(line))
|
||||||
|
return gpg_error (GPG_ERR_GENERAL);
|
||||||
|
|
||||||
|
sprintf (line, "SCD SETDATA ");
|
||||||
|
p = line + strlen (line);
|
||||||
|
for (i=0; i < indatalen ; i++, p += 2 )
|
||||||
|
sprintf (p, "%02X", indata[i]);
|
||||||
|
rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
init_membuf (&data, 1024);
|
||||||
|
snprintf (line, DIM(line)-1, "SCD PKSIGN %s", keyid);
|
||||||
|
line[DIM(line)-1] = 0;
|
||||||
|
rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data,
|
||||||
|
NULL, NULL, NULL, NULL);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
xfree (get_membuf (&data, &len));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
*r_buf = get_membuf (&data, r_buflen);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,10 +20,46 @@
|
|||||||
#ifndef GNUPG_G10_CALL_AGENT_H
|
#ifndef GNUPG_G10_CALL_AGENT_H
|
||||||
#define GNUPG_G10_CALL_AGENT_H
|
#define GNUPG_G10_CALL_AGENT_H
|
||||||
|
|
||||||
|
|
||||||
|
struct agent_card_info_s {
|
||||||
|
int error; /* private. */
|
||||||
|
char *disp_name; /* malloced. */
|
||||||
|
char *pubkey_url; /* malloced. */
|
||||||
|
char fpr1valid;
|
||||||
|
char fpr2valid;
|
||||||
|
char fpr3valid;
|
||||||
|
char fpr1[20];
|
||||||
|
char fpr2[20];
|
||||||
|
char fpr3[20];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct agent_card_genkey_s {
|
||||||
|
char fprvalid;
|
||||||
|
char fpr[20];
|
||||||
|
u32 created_at;
|
||||||
|
gcry_mpi_t n;
|
||||||
|
gcry_mpi_t e;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Return card info. */
|
||||||
|
int agent_learn (struct agent_card_info_s *info);
|
||||||
|
|
||||||
/* Check whether the secret key for the key identified by HEXKEYGRIP
|
/* Check whether the secret key for the key identified by HEXKEYGRIP
|
||||||
is available. Return 0 for yes or an error code. */
|
is available. Return 0 for yes or an error code. */
|
||||||
int agent_havekey (const char *hexkeygrip);
|
int agent_havekey (const char *hexkeygrip);
|
||||||
|
|
||||||
|
/* Send a SETATTR command to the SCdaemon. */
|
||||||
|
int agent_scd_setattr (const char *name,
|
||||||
|
const unsigned char *value, size_t valuelen);
|
||||||
|
|
||||||
|
/* Send a GENKEY command to the SCdaemon. */
|
||||||
|
int agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force);
|
||||||
|
|
||||||
|
/* Send a PKSIGN command to the SCdaemon. */
|
||||||
|
int agent_scd_pksign (const char *keyid, int hashalgo,
|
||||||
|
const unsigned char *indata, size_t indatalen,
|
||||||
|
char **r_buf, size_t *r_buflen);
|
||||||
|
|
||||||
/* Ask the agent to let the user change the passphrase of the secret
|
/* Ask the agent to let the user change the passphrase of the secret
|
||||||
key identified by HEXKEYGRIP. */
|
key identified by HEXKEYGRIP. */
|
||||||
int agent_passwd (const char *hexkeygrip);
|
int agent_passwd (const char *hexkeygrip);
|
||||||
@ -31,4 +67,7 @@ int agent_passwd (const char *hexkeygrip);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*GNUPG_G10_CALL_AGENT_H*/
|
#endif /*GNUPG_G10_CALL_AGENT_H*/
|
||||||
|
|
||||||
|
11
g10/g10.c
11
g10/g10.c
@ -639,6 +639,7 @@ static void set_cmd( enum cmd_and_opt_values *ret_cmd,
|
|||||||
static void print_mds( const char *fname, int algo );
|
static void print_mds( const char *fname, int algo );
|
||||||
static void add_notation_data( const char *string, int which );
|
static void add_notation_data( const char *string, int which );
|
||||||
static void add_policy_url( const char *string, int which );
|
static void add_policy_url( const char *string, int which );
|
||||||
|
static void emergency_cleanup (void);
|
||||||
|
|
||||||
#ifdef __riscos__
|
#ifdef __riscos__
|
||||||
RISCOS_GLOBAL_STATICS("GnuPG Heap")
|
RISCOS_GLOBAL_STATICS("GnuPG Heap")
|
||||||
@ -1191,7 +1192,7 @@ main( int argc, char **argv )
|
|||||||
gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
|
gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
|
||||||
|
|
||||||
may_coredump = disable_core_dumps();
|
may_coredump = disable_core_dumps();
|
||||||
init_signals (); /* why not gnupg_init_signals. */
|
gnupg_init_signals (0, emergency_cleanup);
|
||||||
create_dotlock (NULL); /* register locking cleanup */
|
create_dotlock (NULL); /* register locking cleanup */
|
||||||
i18n_init();
|
i18n_init();
|
||||||
|
|
||||||
@ -1304,6 +1305,7 @@ main( int argc, char **argv )
|
|||||||
/* Okay, we are now working under our real uid */
|
/* Okay, we are now working under our real uid */
|
||||||
|
|
||||||
/* malloc hooks go here ... */
|
/* malloc hooks go here ... */
|
||||||
|
assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
|
||||||
|
|
||||||
set_native_charset (NULL); /* Try to auto set the character set */
|
set_native_charset (NULL); /* Try to auto set the character set */
|
||||||
|
|
||||||
@ -2894,6 +2896,13 @@ main( int argc, char **argv )
|
|||||||
return 8; /*NEVER REACHED*/
|
return 8; /*NEVER REACHED*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Note: This function is used by signal handlers!. */
|
||||||
|
static void
|
||||||
|
emergency_cleanup (void)
|
||||||
|
{
|
||||||
|
gcry_control (GCRYCTL_TERM_SECMEM );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
g10_exit( int rc )
|
g10_exit( int rc )
|
||||||
|
@ -147,7 +147,7 @@ main( int argc, char **argv )
|
|||||||
|
|
||||||
set_strusage (my_strusage);
|
set_strusage (my_strusage);
|
||||||
log_set_prefix ("gpgv", 1);
|
log_set_prefix ("gpgv", 1);
|
||||||
init_signals();
|
gnupg_init_signals(0, NULL);
|
||||||
i18n_init();
|
i18n_init();
|
||||||
opt.command_fd = -1; /* no command fd */
|
opt.command_fd = -1; /* no command fd */
|
||||||
opt.pgp2_workarounds = 1;
|
opt.pgp2_workarounds = 1;
|
||||||
|
@ -921,6 +921,10 @@ change_passphrase( KBNODE keyblock )
|
|||||||
tty_printf(_("Secret parts of primary key are not available.\n"));
|
tty_printf(_("Secret parts of primary key are not available.\n"));
|
||||||
no_primary_secrets = 1;
|
no_primary_secrets = 1;
|
||||||
}
|
}
|
||||||
|
else if( sk->protect.s2k.mode == 1002 ) {
|
||||||
|
tty_printf(_("Secret key is actually stored on a card.\n"));
|
||||||
|
no_primary_secrets = 1;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
tty_printf(_("Key is protected.\n"));
|
tty_printf(_("Key is protected.\n"));
|
||||||
rc = check_secret_key( sk, 0 );
|
rc = check_secret_key( sk, 0 );
|
||||||
|
448
g10/keygen.c
448
g10/keygen.c
@ -38,6 +38,8 @@
|
|||||||
#include "trustdb.h"
|
#include "trustdb.h"
|
||||||
#include "status.h"
|
#include "status.h"
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
#include "call-agent.h"
|
||||||
|
|
||||||
|
|
||||||
#define MAX_PREFS 30
|
#define MAX_PREFS 30
|
||||||
|
|
||||||
@ -111,8 +113,11 @@ static int nzip_prefs;
|
|||||||
static int mdc_available,ks_modify;
|
static int mdc_available,ks_modify;
|
||||||
|
|
||||||
static void do_generate_keypair( struct para_data_s *para,
|
static void do_generate_keypair( struct para_data_s *para,
|
||||||
struct output_control_s *outctrl );
|
struct output_control_s *outctrl, int card);
|
||||||
static int write_keyblock( iobuf_t out, KBNODE node );
|
static int write_keyblock( iobuf_t out, KBNODE node );
|
||||||
|
static int check_smartcard (void);
|
||||||
|
static int gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root, u32 expireval);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1752,7 +1757,7 @@ get_parameter_revkey( struct para_data_s *para, enum para_name key )
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
proc_parameter_file( struct para_data_s *para, const char *fname,
|
proc_parameter_file( struct para_data_s *para, const char *fname,
|
||||||
struct output_control_s *outctrl )
|
struct output_control_s *outctrl, int card )
|
||||||
{
|
{
|
||||||
struct para_data_s *r;
|
struct para_data_s *r;
|
||||||
const char *s1, *s2, *s3;
|
const char *s1, *s2, *s3;
|
||||||
@ -1814,8 +1819,8 @@ proc_parameter_file( struct para_data_s *para, const char *fname,
|
|||||||
r = get_parameter( para, pPASSPHRASE );
|
r = get_parameter( para, pPASSPHRASE );
|
||||||
if( r && *r->u.value ) {
|
if( r && *r->u.value ) {
|
||||||
/* we have a plain text passphrase - create a DEK from it.
|
/* we have a plain text passphrase - create a DEK from it.
|
||||||
* It is a little bit ridiculous to keep it ih secure memory
|
* It is a little bit ridiculous to keep it in secure memory
|
||||||
* but becuase we do this alwasy, why not here */
|
* but because we do this always, why not here. */
|
||||||
STRING2KEY *s2k;
|
STRING2KEY *s2k;
|
||||||
DEK *dek;
|
DEK *dek;
|
||||||
|
|
||||||
@ -1864,7 +1869,7 @@ proc_parameter_file( struct para_data_s *para, const char *fname,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
do_generate_keypair( para, outctrl );
|
do_generate_keypair( para, outctrl, card);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1948,7 +1953,7 @@ read_parameter_file( const char *fname )
|
|||||||
outctrl.dryrun = 1;
|
outctrl.dryrun = 1;
|
||||||
else if( !ascii_strcasecmp( keyword, "%commit" ) ) {
|
else if( !ascii_strcasecmp( keyword, "%commit" ) ) {
|
||||||
outctrl.lnr = lnr;
|
outctrl.lnr = lnr;
|
||||||
proc_parameter_file( para, fname, &outctrl );
|
proc_parameter_file( para, fname, &outctrl, 0 );
|
||||||
release_parameter_list( para );
|
release_parameter_list( para );
|
||||||
para = NULL;
|
para = NULL;
|
||||||
}
|
}
|
||||||
@ -2008,7 +2013,7 @@ read_parameter_file( const char *fname )
|
|||||||
|
|
||||||
if( keywords[i].key == pKEYTYPE && para ) {
|
if( keywords[i].key == pKEYTYPE && para ) {
|
||||||
outctrl.lnr = lnr;
|
outctrl.lnr = lnr;
|
||||||
proc_parameter_file( para, fname, &outctrl );
|
proc_parameter_file( para, fname, &outctrl, 0 );
|
||||||
release_parameter_list( para );
|
release_parameter_list( para );
|
||||||
para = NULL;
|
para = NULL;
|
||||||
}
|
}
|
||||||
@ -2036,7 +2041,7 @@ read_parameter_file( const char *fname )
|
|||||||
}
|
}
|
||||||
else if( para ) {
|
else if( para ) {
|
||||||
outctrl.lnr = lnr;
|
outctrl.lnr = lnr;
|
||||||
proc_parameter_file( para, fname, &outctrl );
|
proc_parameter_file( para, fname, &outctrl, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( outctrl.use_files ) { /* close open streams */
|
if( outctrl.use_files ) { /* close open streams */
|
||||||
@ -2068,6 +2073,7 @@ generate_keypair( const char *fname )
|
|||||||
int algo;
|
int algo;
|
||||||
unsigned int use;
|
unsigned int use;
|
||||||
int both = 0;
|
int both = 0;
|
||||||
|
int card = 0;
|
||||||
u32 expire;
|
u32 expire;
|
||||||
struct para_data_s *para = NULL;
|
struct para_data_s *para = NULL;
|
||||||
struct para_data_s *r;
|
struct para_data_s *r;
|
||||||
@ -2075,13 +2081,32 @@ generate_keypair( const char *fname )
|
|||||||
|
|
||||||
memset (&outctrl, 0, sizeof (outctrl));
|
memset (&outctrl, 0, sizeof (outctrl));
|
||||||
|
|
||||||
if( opt.batch ) {
|
if (opt.batch)
|
||||||
|
{
|
||||||
read_parameter_file( fname );
|
read_parameter_file( fname );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
card = check_smartcard ();
|
||||||
|
if (card < 0)
|
||||||
|
return;
|
||||||
|
if (card > 1)
|
||||||
|
log_error (_("can't generate subkey here\n"));
|
||||||
|
}
|
||||||
|
while (card > 1);
|
||||||
|
|
||||||
|
if (card)
|
||||||
|
{
|
||||||
|
algo = PUBKEY_ALGO_RSA;
|
||||||
|
use = PUBKEY_USAGE_SIG;
|
||||||
|
}
|
||||||
|
else
|
||||||
algo = ask_algo (0, &use);
|
algo = ask_algo (0, &use);
|
||||||
if( !algo ) { /* default: DSA with ElG subkey of the specified size */
|
|
||||||
|
if (!algo)
|
||||||
|
{ /* default: DSA with ElG subkey of the specified size */
|
||||||
both = 1;
|
both = 1;
|
||||||
r = xcalloc (1, sizeof *r + 20 );
|
r = xcalloc (1, sizeof *r + 20 );
|
||||||
r->key = pKEYTYPE;
|
r->key = pKEYTYPE;
|
||||||
@ -2102,14 +2127,16 @@ generate_keypair( const char *fname )
|
|||||||
r->next = para;
|
r->next = para;
|
||||||
para = r;
|
para = r;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
r = xcalloc (1, sizeof *r + 20 );
|
r = xcalloc (1, sizeof *r + 20 );
|
||||||
r->key = pKEYTYPE;
|
r->key = pKEYTYPE;
|
||||||
sprintf( r->u.value, "%d", algo );
|
sprintf( r->u.value, "%d", algo );
|
||||||
r->next = para;
|
r->next = para;
|
||||||
para = r;
|
para = r;
|
||||||
|
|
||||||
if (use) {
|
if (use)
|
||||||
|
{
|
||||||
r = xcalloc (1, sizeof *r + 20 );
|
r = xcalloc (1, sizeof *r + 20 );
|
||||||
r->key = pKEYUSAGE;
|
r->key = pKEYUSAGE;
|
||||||
sprintf( r->u.value, "%s%s",
|
sprintf( r->u.value, "%s%s",
|
||||||
@ -2118,15 +2145,17 @@ generate_keypair( const char *fname )
|
|||||||
r->next = para;
|
r->next = para;
|
||||||
para = r;
|
para = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!card)
|
||||||
|
{
|
||||||
nbits = ask_keysize( algo );
|
nbits = ask_keysize( algo );
|
||||||
r = xcalloc (1, sizeof *r + 20 );
|
r = xcalloc (1, sizeof *r + 20 );
|
||||||
r->key = both? pSUBKEYLENGTH : pKEYLENGTH;
|
r->key = both? pSUBKEYLENGTH : pKEYLENGTH;
|
||||||
sprintf( r->u.value, "%u", nbits);
|
sprintf( r->u.value, "%u", nbits);
|
||||||
r->next = para;
|
r->next = para;
|
||||||
para = r;
|
para = r;
|
||||||
|
}
|
||||||
|
|
||||||
expire = ask_expire_interval(0);
|
expire = ask_expire_interval(0);
|
||||||
r = xcalloc (1, sizeof *r + 20 );
|
r = xcalloc (1, sizeof *r + 20 );
|
||||||
@ -2141,7 +2170,8 @@ generate_keypair( const char *fname )
|
|||||||
para = r;
|
para = r;
|
||||||
|
|
||||||
uid = ask_user_id(0);
|
uid = ask_user_id(0);
|
||||||
if( !uid ) {
|
if (!uid)
|
||||||
|
{
|
||||||
log_error(_("Key generation canceled.\n"));
|
log_error(_("Key generation canceled.\n"));
|
||||||
release_parameter_list( para );
|
release_parameter_list( para );
|
||||||
return;
|
return;
|
||||||
@ -2152,8 +2182,9 @@ generate_keypair( const char *fname )
|
|||||||
r->next = para;
|
r->next = para;
|
||||||
para = r;
|
para = r;
|
||||||
|
|
||||||
dek = ask_passphrase( &s2k );
|
dek = card? NULL : ask_passphrase( &s2k );
|
||||||
if( dek ) {
|
if (dek)
|
||||||
|
{
|
||||||
r = xcalloc (1, sizeof *r );
|
r = xcalloc (1, sizeof *r );
|
||||||
r->key = pPASSPHRASE_DEK;
|
r->key = pPASSPHRASE_DEK;
|
||||||
r->u.dek = dek;
|
r->u.dek = dek;
|
||||||
@ -2166,7 +2197,7 @@ generate_keypair( const char *fname )
|
|||||||
para = r;
|
para = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
proc_parameter_file( para, "[internal]", &outctrl );
|
proc_parameter_file (para, "[internal]", &outctrl, card);
|
||||||
release_parameter_list (para);
|
release_parameter_list (para);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2189,9 +2220,11 @@ print_status_key_created (int letter, PKT_public_key *pk)
|
|||||||
write_status_text (STATUS_KEY_CREATED, buf);
|
write_status_text (STATUS_KEY_CREATED, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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 )
|
struct output_control_s *outctrl, int card)
|
||||||
{
|
{
|
||||||
KBNODE pub_root = NULL;
|
KBNODE pub_root = NULL;
|
||||||
KBNODE sec_root = NULL;
|
KBNODE sec_root = NULL;
|
||||||
@ -2201,14 +2234,17 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
int rc;
|
int rc;
|
||||||
int did_sub = 0;
|
int did_sub = 0;
|
||||||
|
|
||||||
if( outctrl->dryrun ) {
|
if (outctrl->dryrun)
|
||||||
|
{
|
||||||
log_info ("dry-run mode - key generation skipped\n");
|
log_info ("dry-run mode - key generation skipped\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if( outctrl->use_files ) {
|
if (outctrl->use_files)
|
||||||
if( outctrl->pub.newfname ) {
|
{
|
||||||
|
if (outctrl->pub.newfname)
|
||||||
|
{
|
||||||
iobuf_close (outctrl->pub.stream);
|
iobuf_close (outctrl->pub.stream);
|
||||||
outctrl->pub.stream = NULL;
|
outctrl->pub.stream = NULL;
|
||||||
xfree (outctrl->pub.fname);
|
xfree (outctrl->pub.fname);
|
||||||
@ -2216,18 +2252,21 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
outctrl->pub.newfname = NULL;
|
outctrl->pub.newfname = NULL;
|
||||||
|
|
||||||
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;
|
||||||
iobuf_push_filter (outctrl->pub.stream, armor_filter,
|
iobuf_push_filter (outctrl->pub.stream, armor_filter,
|
||||||
&outctrl->pub.afx);
|
&outctrl->pub.afx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( outctrl->sec.newfname ) {
|
if (outctrl->sec.newfname)
|
||||||
|
{
|
||||||
iobuf_close (outctrl->sec.stream);
|
iobuf_close (outctrl->sec.stream);
|
||||||
outctrl->sec.stream = NULL;
|
outctrl->sec.stream = NULL;
|
||||||
xfree (outctrl->sec.fname);
|
xfree (outctrl->sec.fname);
|
||||||
@ -2235,12 +2274,14 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
outctrl->sec.newfname = NULL;
|
outctrl->sec.newfname = NULL;
|
||||||
|
|
||||||
outctrl->sec.stream = iobuf_create (outctrl->sec.fname);
|
outctrl->sec.stream = iobuf_create (outctrl->sec.fname);
|
||||||
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;
|
||||||
iobuf_push_filter (outctrl->sec.stream, armor_filter,
|
iobuf_push_filter (outctrl->sec.stream, armor_filter,
|
||||||
&outctrl->sec.afx);
|
&outctrl->sec.afx);
|
||||||
@ -2248,28 +2289,47 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
}
|
}
|
||||||
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)
|
||||||
|
log_info (_("writing secret key stub to `%s'\n"),
|
||||||
|
outctrl->sec.fname);
|
||||||
|
else
|
||||||
log_info (_("writing secret key to `%s'\n"), outctrl->sec.fname);
|
log_info (_("writing secret key to `%s'\n"), outctrl->sec.fname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* we create the packets as a tree of kbnodes. Because the structure
|
/* We create the packets as a tree of kbnodes. Because the structure
|
||||||
* we create is known in advance we simply generate a linked list
|
* we create is known in advance we simply generate a linked list.
|
||||||
* The first packet is a dummy comment packet which we flag
|
* The first packet is a dummy comment packet which we flag
|
||||||
* as deleted. The very first packet must always be a KEY packet.
|
* as deleted. The very first packet must always be a KEY packet.
|
||||||
*/
|
*/
|
||||||
pub_root = make_comment_node("#"); delete_kbnode(pub_root);
|
pub_root = make_comment_node ("#");
|
||||||
sec_root = make_comment_node("#"); delete_kbnode(sec_root);
|
delete_kbnode (pub_root);
|
||||||
|
sec_root = make_comment_node ("#");
|
||||||
|
delete_kbnode (sec_root);
|
||||||
|
if (!card)
|
||||||
|
{
|
||||||
rc = do_create (get_parameter_algo (para, pKEYTYPE),
|
rc = do_create (get_parameter_algo (para, pKEYTYPE),
|
||||||
get_parameter_uint (para, pKEYLENGTH),
|
get_parameter_uint (para, pKEYLENGTH),
|
||||||
pub_root, sec_root,
|
pub_root, sec_root,
|
||||||
get_parameter_dek (para, pPASSPHRASE_DEK),
|
get_parameter_dek (para, pPASSPHRASE_DEK),
|
||||||
get_parameter_s2k (para, pPASSPHRASE_S2K),
|
get_parameter_s2k (para, pPASSPHRASE_S2K),
|
||||||
&sk,
|
&sk, get_parameter_u32 (para, pKEYEXPIRE));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = gen_card_key (PUBKEY_ALGO_RSA, 1, pub_root, sec_root,
|
||||||
get_parameter_u32 (para, pKEYEXPIRE));
|
get_parameter_u32 (para, pKEYEXPIRE));
|
||||||
|
if (!rc)
|
||||||
|
{
|
||||||
|
sk = sec_root->next->pkt->pkt.secret_key;
|
||||||
|
assert (sk);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (!rc && (revkey = get_parameter_revkey (para, pREVOKER)))
|
if (!rc && (revkey = get_parameter_revkey (para, pREVOKER)))
|
||||||
{
|
{
|
||||||
@ -2278,7 +2338,8 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
write_direct_sig (sec_root, pub_root, sk, revkey);
|
write_direct_sig (sec_root, pub_root, sk, revkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
if (!rc)
|
||||||
write_uid (sec_root, s);
|
write_uid (sec_root, s);
|
||||||
@ -2290,14 +2351,14 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
get_parameter_uint (para, pKEYUSAGE));
|
get_parameter_uint (para, pKEYUSAGE));
|
||||||
}
|
}
|
||||||
|
|
||||||
if( get_parameter( para, pSUBKEYTYPE ) ) {
|
if (get_parameter (para, pSUBKEYTYPE))
|
||||||
|
{
|
||||||
rc = do_create (get_parameter_algo (para, pSUBKEYTYPE),
|
rc = do_create (get_parameter_algo (para, pSUBKEYTYPE),
|
||||||
get_parameter_uint (para, pSUBKEYLENGTH),
|
get_parameter_uint (para, pSUBKEYLENGTH),
|
||||||
pub_root, sec_root,
|
pub_root, sec_root,
|
||||||
get_parameter_dek (para, pPASSPHRASE_DEK),
|
get_parameter_dek (para, pPASSPHRASE_DEK),
|
||||||
get_parameter_s2k (para, pPASSPHRASE_S2K),
|
get_parameter_s2k (para, pPASSPHRASE_S2K),
|
||||||
NULL,
|
NULL, get_parameter_u32 (para, pSUBKEYEXPIRE));
|
||||||
get_parameter_u32( para, pSUBKEYEXPIRE ) );
|
|
||||||
if (!rc)
|
if (!rc)
|
||||||
rc = write_keybinding (pub_root, pub_root, sk,
|
rc = write_keybinding (pub_root, pub_root, sk,
|
||||||
get_parameter_uint (para, pSUBKEYUSAGE));
|
get_parameter_uint (para, pSUBKEYUSAGE));
|
||||||
@ -2308,18 +2369,21 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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", gpg_strerror (rc));
|
log_error ("can't write public key: %s\n", gpg_strerror (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", gpg_strerror (rc));
|
log_error ("can't write secret key: %s\n", gpg_strerror (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);
|
||||||
|
|
||||||
@ -2329,28 +2393,36 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
log_error (_("no writable public keyring found: %s\n"),
|
log_error (_("no writable public keyring found: %s\n"),
|
||||||
gpg_strerror (rc));
|
gpg_strerror (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"),
|
||||||
gpg_strerror (rc));
|
gpg_strerror (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)
|
||||||
|
log_info (_("writing secret key stub to `%s'\n"),
|
||||||
|
keydb_get_resource_name (sec_hd));
|
||||||
|
else
|
||||||
log_info (_("writing secret key to `%s'\n"),
|
log_info (_("writing secret key to `%s'\n"),
|
||||||
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), gpg_strerror (rc));
|
keydb_get_resource_name (pub_hd), gpg_strerror (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"),
|
||||||
@ -2360,19 +2432,22 @@ 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 =
|
int no_enc_rsa =
|
||||||
get_parameter_algo (para, pKEYTYPE) == PUBKEY_ALGO_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) & PUBKEY_USAGE_ENC);
|
||||||
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;
|
||||||
|
|
||||||
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 (_("key marked as ultimately trusted.\n"));
|
tty_printf (_("key marked as ultimately trusted.\n"));
|
||||||
tty_printf ("\n");
|
tty_printf ("\n");
|
||||||
@ -2382,8 +2457,7 @@ do_generate_keypair( struct para_data_s *para,
|
|||||||
|
|
||||||
if (!opt.batch
|
if (!opt.batch
|
||||||
&& (get_parameter_algo (para, pKEYTYPE) == PUBKEY_ALGO_DSA
|
&& (get_parameter_algo (para, pKEYTYPE) == PUBKEY_ALGO_DSA
|
||||||
|| no_enc_rsa )
|
|| no_enc_rsa) && !get_parameter (para, pSUBKEYTYPE))
|
||||||
&& !get_parameter( para, pSUBKEYTYPE ) )
|
|
||||||
{
|
{
|
||||||
tty_printf (_("Note that this key cannot be used for "
|
tty_printf (_("Note that this key cannot be used for "
|
||||||
"encryption. You may want to use\n"
|
"encryption. You may want to use\n"
|
||||||
@ -2393,21 +2467,24 @@ 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", gpg_strerror (rc));
|
log_error ("key generation failed: %s\n", gpg_strerror (rc));
|
||||||
else
|
else
|
||||||
tty_printf (_("Key generation failed: %s\n"), gpg_strerror (rc));
|
tty_printf (_("Key generation failed: %s\n"), gpg_strerror (rc));
|
||||||
}
|
}
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
release_kbnode (pub_root);
|
release_kbnode (pub_root);
|
||||||
release_kbnode (sec_root);
|
release_kbnode (sec_root);
|
||||||
if( sk ) /* the unprotected secret key */
|
if (sk && !card) /* The unprotected secret key unless we have */
|
||||||
free_secret_key(sk);
|
free_secret_key (sk); /* shallow copy in card mode. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2534,3 +2611,268 @@ write_keyblock( iobuf_t out, KBNODE node )
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
show_sha1_fpr (const unsigned char *fpr)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (fpr)
|
||||||
|
{
|
||||||
|
for (i=0; i < 20 ; i+=2, fpr += 2 )
|
||||||
|
{
|
||||||
|
if (i == 10 )
|
||||||
|
tty_printf (" ");
|
||||||
|
tty_printf (" %02X%02X", *fpr, fpr[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tty_printf ("[none]");
|
||||||
|
tty_printf ("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
show_smartcard (struct agent_card_info_s *info)
|
||||||
|
{
|
||||||
|
/* FIXME: Sanitize what we show. */
|
||||||
|
tty_printf ("Name of cardholder: %s\n",
|
||||||
|
info->disp_name && *info->disp_name? info->disp_name
|
||||||
|
: "[not set]");
|
||||||
|
tty_printf ("URL of public key : %s\n",
|
||||||
|
info->pubkey_url && *info->pubkey_url? info->pubkey_url
|
||||||
|
: "[not set]");
|
||||||
|
tty_printf ("Signature key ....: ");
|
||||||
|
show_sha1_fpr (info->fpr1valid? info->fpr1:NULL);
|
||||||
|
tty_printf ("Encryption key....: ");
|
||||||
|
show_sha1_fpr (info->fpr2valid? info->fpr2:NULL);
|
||||||
|
tty_printf ("Authentication key: ");
|
||||||
|
show_sha1_fpr (info->fpr3valid? info->fpr3:NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
smartcard_get_one_name (const char *prompt1, const char *prompt2)
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
name = cpr_get (prompt1, prompt2);
|
||||||
|
if (!name)
|
||||||
|
return NULL;
|
||||||
|
trim_spaces (name);
|
||||||
|
cpr_kill_prompt ();
|
||||||
|
for (i=0; name[i] && name[i] >= ' ' && name[i] <= 126; i++)
|
||||||
|
;
|
||||||
|
|
||||||
|
/* The name must be in Latin-1 and not UTF-8 - lacking the code
|
||||||
|
to ensure this we restrict it to ASCII. */
|
||||||
|
if (name[i])
|
||||||
|
tty_printf (_("Error: Only plain ASCII is currently allowed.\n"));
|
||||||
|
else if (strchr (name, '<'))
|
||||||
|
tty_printf (_("Error: The \"<\" character may not be used.\n"));
|
||||||
|
else if (strstr (name, " "))
|
||||||
|
tty_printf (_("Error: Double spaces are not allowed.\n"));
|
||||||
|
else
|
||||||
|
return name;
|
||||||
|
xfree (name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
smartcard_change_name (const char *current_name)
|
||||||
|
{
|
||||||
|
char *surname = NULL, *givenname = NULL;
|
||||||
|
char *isoname, *p;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
surname = smartcard_get_one_name ("keygen.smartcard.surname",
|
||||||
|
_("Cardholder's surname: "));
|
||||||
|
givenname = smartcard_get_one_name ("keygen.smartcard.givenname",
|
||||||
|
_("Cardholder's given name: "));
|
||||||
|
if (!surname || !givenname || (!*surname && !*givenname))
|
||||||
|
{
|
||||||
|
xfree (surname);
|
||||||
|
xfree (givenname);
|
||||||
|
return -1; /*canceled*/
|
||||||
|
}
|
||||||
|
|
||||||
|
isoname = xmalloc ( strlen (surname) + 2 + strlen (givenname) + 1);
|
||||||
|
strcpy (stpcpy (stpcpy (isoname, surname), "<<"), givenname);
|
||||||
|
xfree (surname);
|
||||||
|
xfree (givenname);
|
||||||
|
for (p=isoname; *p; p++)
|
||||||
|
if (*p == ' ')
|
||||||
|
*p = '<';
|
||||||
|
|
||||||
|
log_debug ("setting Name to `%s'\n", isoname);
|
||||||
|
rc = agent_scd_setattr ("DISP-NAME", isoname, strlen (isoname) );
|
||||||
|
if (rc)
|
||||||
|
log_error ("error setting Name: %s\n", gpg_strerror (rc));
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Check whether a smartcatrd is available and alow to select it as
|
||||||
|
the target for key generation.
|
||||||
|
|
||||||
|
Return values: -1 = Quit generation
|
||||||
|
0 = No smartcard
|
||||||
|
1 = Generate primary key
|
||||||
|
2 = generate subkey
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
check_smartcard (void)
|
||||||
|
{
|
||||||
|
struct agent_card_info_s info;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = agent_learn (&info);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
tty_printf (_("OpenPGP card not available: %s\n"),
|
||||||
|
gpg_strerror (rc));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tty_printf (_("OpenPGP card with serial number %s detected\n"), "xxx");
|
||||||
|
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
char *answer;
|
||||||
|
int reread = 0;
|
||||||
|
|
||||||
|
tty_printf ("\n");
|
||||||
|
show_smartcard (&info);
|
||||||
|
|
||||||
|
tty_printf ("\n"
|
||||||
|
"N - change cardholder name\n"
|
||||||
|
"U - change public key URL\n"
|
||||||
|
"1 - generate signature key\n"
|
||||||
|
"2 - generate encryption key\n"
|
||||||
|
"3 - generate authentication key\n"
|
||||||
|
"Q - quit\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
answer = cpr_get("keygen.smartcard.menu",_("Your selection? "));
|
||||||
|
cpr_kill_prompt();
|
||||||
|
if (strlen (answer) != 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rc = 0;
|
||||||
|
if ( *answer == 'N' || *answer == 'n')
|
||||||
|
{
|
||||||
|
if (!smartcard_change_name (info.disp_name))
|
||||||
|
reread = 1;
|
||||||
|
}
|
||||||
|
else if ( *answer == 'U' || *answer == 'u')
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else if ( *answer == '1' || *answer == '2')
|
||||||
|
{
|
||||||
|
rc = *answer - '0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if ( *answer == '3' )
|
||||||
|
{
|
||||||
|
tty_printf (_("Generation of authentication key"
|
||||||
|
" not yet implemented\n"));
|
||||||
|
}
|
||||||
|
else if ( *answer == 'q' || *answer == 'Q')
|
||||||
|
{
|
||||||
|
rc = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reread)
|
||||||
|
{
|
||||||
|
xfree (info.disp_name); info.disp_name = NULL;
|
||||||
|
xfree (info.pubkey_url); info.pubkey_url = NULL;
|
||||||
|
rc = agent_learn (&info);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
tty_printf (_("OpenPGP card not anymore available: %s\n"),
|
||||||
|
gpg_strerror (rc));
|
||||||
|
g10_exit (1);
|
||||||
|
}
|
||||||
|
reread = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xfree (info.disp_name);
|
||||||
|
xfree (info.pubkey_url);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root,
|
||||||
|
u32 expireval)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
struct agent_card_genkey_s info;
|
||||||
|
PACKET *pkt;
|
||||||
|
PKT_secret_key *sk;
|
||||||
|
PKT_public_key *pk;
|
||||||
|
|
||||||
|
assert (algo == PUBKEY_ALGO_RSA);
|
||||||
|
|
||||||
|
rc = agent_scd_genkey (&info, keyno, 0);
|
||||||
|
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 (rc)
|
||||||
|
{
|
||||||
|
log_error ("key generation failed: %s\n", gpg_strerror (rc));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
if ( !info.n || !info.e )
|
||||||
|
{
|
||||||
|
log_error ("communication error with SCD\n");
|
||||||
|
gcry_mpi_release (info.n);
|
||||||
|
gcry_mpi_release (info.e);
|
||||||
|
return gpg_error (GPG_ERR_GENERAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pk = xcalloc (1, sizeof *pk );
|
||||||
|
sk = xcalloc (1, sizeof *sk );
|
||||||
|
sk->timestamp = pk->timestamp = make_timestamp();
|
||||||
|
sk->version = pk->version = 4;
|
||||||
|
if (expireval)
|
||||||
|
sk->expiredate = pk->expiredate = pk->timestamp + expireval;
|
||||||
|
sk->pubkey_algo = pk->pubkey_algo = algo;
|
||||||
|
pk->pkey[0] = info.n;
|
||||||
|
pk->pkey[1] = info.e;
|
||||||
|
sk->skey[0] = mpi_copy (pk->pkey[0]);
|
||||||
|
sk->skey[1] = mpi_copy (pk->pkey[1]);
|
||||||
|
sk->skey[2] = mpi_set_opaque (NULL, xstrdup ("dummydata"), 10);
|
||||||
|
sk->is_protected = 1;
|
||||||
|
sk->protect.s2k.mode = 1002;
|
||||||
|
|
||||||
|
pkt = xcalloc (1,sizeof *pkt);
|
||||||
|
pkt->pkttype = keyno == 1 ? 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 = keyno == 1 ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY;
|
||||||
|
pkt->pkt.secret_key = sk;
|
||||||
|
add_kbnode(sec_root, new_kbnode( pkt ));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1634,6 +1634,8 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
|
|||||||
break;
|
break;
|
||||||
case 1001: if( list_mode ) printf( "\tgnu-dummy S2K" );
|
case 1001: if( list_mode ) printf( "\tgnu-dummy S2K" );
|
||||||
break;
|
break;
|
||||||
|
case 1002: if (list_mode) printf("\tgnu-divert-to-card S2K");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if( list_mode )
|
if( list_mode )
|
||||||
printf( "\tunknown %sS2K %d\n",
|
printf( "\tunknown %sS2K %d\n",
|
||||||
@ -1669,6 +1671,31 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
|
|||||||
printf("\tprotect count: %lu\n",
|
printf("\tprotect count: %lu\n",
|
||||||
(ulong)sk->protect.s2k.count);
|
(ulong)sk->protect.s2k.count);
|
||||||
}
|
}
|
||||||
|
else if( sk->protect.s2k.mode == 1002 ) {
|
||||||
|
size_t snlen;
|
||||||
|
/* Read the serial number. */
|
||||||
|
if (pktlen < 1) {
|
||||||
|
rc = GPG_ERR_INV_PACKET;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
snlen = iobuf_get (inp);
|
||||||
|
pktlen--;
|
||||||
|
if (pktlen < snlen || snlen == -1) {
|
||||||
|
rc = GPG_ERR_INV_PACKET;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( list_mode ) {
|
||||||
|
printf("\tserial-number: ");
|
||||||
|
for (;snlen; snlen--)
|
||||||
|
printf ("%02X", (unsigned int)iobuf_get_noeof (inp));
|
||||||
|
putchar ('\n');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (;snlen; snlen--)
|
||||||
|
iobuf_get_noeof (inp);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Note that a sk->protect.algo > 110 is illegal, but I'm
|
/* Note that a sk->protect.algo > 110 is illegal, but I'm
|
||||||
not erroring on it here as otherwise there would be no
|
not erroring on it here as otherwise there would be no
|
||||||
@ -1698,6 +1725,8 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
|
|||||||
}
|
}
|
||||||
if( sk->protect.s2k.mode == 1001 )
|
if( sk->protect.s2k.mode == 1001 )
|
||||||
sk->protect.ivlen = 0;
|
sk->protect.ivlen = 0;
|
||||||
|
else if( sk->protect.s2k.mode == 1002 )
|
||||||
|
sk->protect.ivlen = 0;
|
||||||
|
|
||||||
if( pktlen < sk->protect.ivlen ) {
|
if( pktlen < sk->protect.ivlen ) {
|
||||||
rc = GPG_ERR_INV_PACKET;
|
rc = GPG_ERR_INV_PACKET;
|
||||||
@ -1719,7 +1748,8 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
|
|||||||
* If the user is so careless, not to protect his secret key,
|
* If the user is so careless, not to protect his secret key,
|
||||||
* we can assume, that he operates an open system :=(.
|
* we can assume, that he operates an open system :=(.
|
||||||
* So we put the key into secure memory when we unprotect it. */
|
* So we put the key into secure memory when we unprotect it. */
|
||||||
if( sk->protect.s2k.mode == 1001 ) {
|
if( sk->protect.s2k.mode == 1001
|
||||||
|
|| sk->protect.s2k.mode == 1002 ) {
|
||||||
/* better set some dummy stuff here */
|
/* better set some dummy stuff here */
|
||||||
sk->skey[npkey] = mpi_set_opaque(NULL, xstrdup ("dummydata"), 10);
|
sk->skey[npkey] = mpi_set_opaque(NULL, xstrdup ("dummydata"), 10);
|
||||||
pktlen = 0;
|
pktlen = 0;
|
||||||
|
@ -794,7 +794,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
|
|||||||
tryagain_text = _(tryagain_text);
|
tryagain_text = _(tryagain_text);
|
||||||
|
|
||||||
/* We allocate 2 time the needed space for atext so that there
|
/* We allocate 2 time the needed space for atext so that there
|
||||||
is nenough space for escaping */
|
is enough space for escaping */
|
||||||
line = xmalloc (15 + 46
|
line = xmalloc (15 + 46
|
||||||
+ 3*strlen (tryagain_text) + 3*strlen (atext) + 2);
|
+ 3*strlen (tryagain_text) + 3*strlen (atext) + 2);
|
||||||
strcpy (line, "GET_PASSPHRASE ");
|
strcpy (line, "GET_PASSPHRASE ");
|
||||||
|
@ -253,6 +253,9 @@ check_secret_key( PKT_secret_key *sk, int n )
|
|||||||
int rc = gpg_error (GPG_ERR_BAD_PASSPHRASE);
|
int rc = gpg_error (GPG_ERR_BAD_PASSPHRASE);
|
||||||
int i,mode;
|
int i,mode;
|
||||||
|
|
||||||
|
if (sk && sk->is_protected && sk->protect.s2k.mode == 1002)
|
||||||
|
return 0; /* Let the scdaemon handle it. */
|
||||||
|
|
||||||
if(n<0)
|
if(n<0)
|
||||||
{
|
{
|
||||||
n=abs(n);
|
n=abs(n);
|
||||||
|
@ -231,3 +231,8 @@ encode_md_value (int pubkey_algo, gcry_md_hd_t md, int hash_algo,
|
|||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
24
g10/sign.c
24
g10/sign.c
@ -263,7 +263,6 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig,
|
|||||||
return GPG_ERR_TIME_CONFLICT;
|
return GPG_ERR_TIME_CONFLICT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
print_pubkey_algo_note(sk->pubkey_algo);
|
print_pubkey_algo_note(sk->pubkey_algo);
|
||||||
|
|
||||||
if( !digest_algo )
|
if( !digest_algo )
|
||||||
@ -274,12 +273,33 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig,
|
|||||||
sig->digest_algo = digest_algo;
|
sig->digest_algo = digest_algo;
|
||||||
sig->digest_start[0] = dp[0];
|
sig->digest_start[0] = dp[0];
|
||||||
sig->digest_start[1] = dp[1];
|
sig->digest_start[1] = dp[1];
|
||||||
|
if (sk->is_protected && sk->protect.s2k.mode == 1002)
|
||||||
|
{ /* FIXME: Note that we do only support RSA for now. */
|
||||||
|
char *rbuf;
|
||||||
|
size_t rbuflen;
|
||||||
|
|
||||||
|
/* FIXME: We need to pass the correct keyid or better the
|
||||||
|
fingerprint to the scdaemon. */
|
||||||
|
rc = agent_scd_pksign ("nokeyid", digest_algo,
|
||||||
|
gcry_md_read (md, digest_algo),
|
||||||
|
gcry_md_get_algo_dlen (digest_algo),
|
||||||
|
&rbuf, &rbuflen);
|
||||||
|
if (!rc)
|
||||||
|
{
|
||||||
|
unsigned int nbytes = rbuflen;
|
||||||
|
if (gcry_mpi_scan (&sig->data[0], GCRYMPI_FMT_USG, rbuf, &nbytes ))
|
||||||
|
BUG ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
frame = encode_md_value( sk->pubkey_algo, md,
|
frame = encode_md_value( sk->pubkey_algo, md,
|
||||||
digest_algo, mpi_get_nbits(sk->skey[0]), 0 );
|
digest_algo, mpi_get_nbits(sk->skey[0]), 0 );
|
||||||
if (!frame)
|
if (!frame)
|
||||||
return GPG_ERR_GENERAL;
|
return GPG_ERR_GENERAL;
|
||||||
rc = pk_sign( sk->pubkey_algo, sig->data, frame, sk->skey );
|
rc = pk_sign( sk->pubkey_algo, sig->data, frame, sk->skey );
|
||||||
gcry_mpi_release (frame);
|
gcry_mpi_release (frame);
|
||||||
|
}
|
||||||
if (!rc && !opt.no_sig_create_check) {
|
if (!rc && !opt.no_sig_create_check) {
|
||||||
/* check that the signature verification worked and nothing is
|
/* check that the signature verification worked and nothing is
|
||||||
* fooling us e.g. by a bug in the signature create
|
* fooling us e.g. by a bug in the signature create
|
||||||
@ -1170,7 +1190,7 @@ sign_symencrypt_file (const char *fname, STRLIST locusr)
|
|||||||
* SIGVERSION gives the minimal required signature packet version;
|
* SIGVERSION gives the minimal required signature packet version;
|
||||||
* this is needed so that special properties like local sign are not
|
* this is needed so that special properties like local sign are not
|
||||||
* applied (actually: dropped) when a v3 key is used. TIMESTAMP is
|
* applied (actually: dropped) when a v3 key is used. TIMESTAMP is
|
||||||
* the timestamp to use for the signature. 0 means "now" */
|
* the timestamp to use for the signature. 0 means "now". */
|
||||||
int
|
int
|
||||||
make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
|
make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
|
||||||
PKT_user_id *uid, PKT_public_key *subpk,
|
PKT_user_id *uid, PKT_public_key *subpk,
|
||||||
|
@ -372,10 +372,11 @@ tdbio_end_transaction()
|
|||||||
else
|
else
|
||||||
is_locked = 1;
|
is_locked = 1;
|
||||||
}
|
}
|
||||||
block_all_signals();
|
#warning block_all_signals is not yet available in ../common/signals.c
|
||||||
|
/* block_all_signals(); */
|
||||||
in_transaction = 0;
|
in_transaction = 0;
|
||||||
rc = tdbio_sync();
|
rc = tdbio_sync();
|
||||||
unblock_all_signals();
|
/* unblock_all_signals(); */
|
||||||
if( !opt.lock_once ) {
|
if( !opt.lock_once ) {
|
||||||
if( !release_dotlock( lockhandle ) )
|
if( !release_dotlock( lockhandle ) )
|
||||||
is_locked = 0;
|
is_locked = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user