mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-21 14:47:03 +01: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)
|
||||
------------------------------------------------
|
||||
|
||||
* gpg does now also use libgcrypt, libgpg-error is required.
|
||||
|
||||
* New gpgsm commands --call-dirmngr and --call-protect-tool.
|
||||
|
||||
* 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>
|
||||
|
||||
* keyid.c (do_fingerprint_md): Made it work again.
|
||||
|
@ -63,8 +63,7 @@ common_source = \
|
||||
plaintext.c \
|
||||
sig-check.c \
|
||||
keylist.c \
|
||||
pkglue.c pkglue.h \
|
||||
signal.c
|
||||
pkglue.c pkglue.h
|
||||
|
||||
gpg_SOURCES = g10.c \
|
||||
$(common_source) \
|
||||
|
@ -415,8 +415,9 @@ do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk )
|
||||
if( sk->protect.s2k.mode == 3 )
|
||||
iobuf_put(a, sk->protect.s2k.count );
|
||||
|
||||
/* For out special mode 1001 we do not need an IV */
|
||||
if( sk->protect.s2k.mode != 1001 )
|
||||
/* For out special modes 1001 and 1002 we do not need an IV */
|
||||
if( sk->protect.s2k.mode != 1001
|
||||
&& sk->protect.s2k.mode != 1002 )
|
||||
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 )
|
||||
; /* 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 ) {
|
||||
/* The secret key is protected - write it out as it is */
|
||||
byte *p;
|
||||
|
313
g10/call-agent.c
313
g10/call-agent.c
@ -47,7 +47,7 @@
|
||||
#endif
|
||||
|
||||
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 {
|
||||
ASSUAN_CONTEXT ctx;
|
||||
@ -61,11 +61,6 @@ struct genkey_parm_s {
|
||||
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
|
||||
@ -292,16 +287,59 @@ start_agent (void)
|
||||
}
|
||||
|
||||
|
||||
static AssuanError
|
||||
membuf_data_cb (void *opaque, const void *buffer, size_t length)
|
||||
/* Return a new malloced string by unescaping the string S. Escaping
|
||||
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)
|
||||
put_membuf (data, buffer, length);
|
||||
return 0;
|
||||
buffer = d = xtrymalloc (strlen (s)+1);
|
||||
if (!buffer)
|
||||
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 */
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
@ -391,10 +429,161 @@ agent_havekey (const char *hexkeygrip)
|
||||
}
|
||||
|
||||
|
||||
/* Ask the agent to change the passphrase of the key identified by
|
||||
HEXKEYGRIP. */
|
||||
static AssuanError
|
||||
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
|
||||
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;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
@ -403,13 +592,95 @@ agent_passwd (const char *hexkeygrip)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (!hexkeygrip || strlen (hexkeygrip) != 40)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
snprintf (line, DIM(line)-1, "PASSWD %s", hexkeygrip);
|
||||
memset (info, 0, sizeof *info);
|
||||
snprintf (line, DIM(line)-1, "SCD GENKEY %s%d",
|
||||
force? "--force ":"", keyno);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
#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
|
||||
is available. Return 0 for yes or an error code. */
|
||||
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
|
||||
key identified by HEXKEYGRIP. */
|
||||
int agent_passwd (const char *hexkeygrip);
|
||||
@ -31,4 +67,7 @@ int agent_passwd (const char *hexkeygrip);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /*GNUPG_G10_CALL_AGENT_H*/
|
||||
|
||||
|
13
g10/g10.c
13
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 add_notation_data( const char *string, int which );
|
||||
static void add_policy_url( const char *string, int which );
|
||||
static void emergency_cleanup (void);
|
||||
|
||||
#ifdef __riscos__
|
||||
RISCOS_GLOBAL_STATICS("GnuPG Heap")
|
||||
@ -1191,7 +1192,7 @@ main( int argc, char **argv )
|
||||
gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
|
||||
|
||||
may_coredump = disable_core_dumps();
|
||||
init_signals (); /* why not gnupg_init_signals. */
|
||||
gnupg_init_signals (0, emergency_cleanup);
|
||||
create_dotlock (NULL); /* register locking cleanup */
|
||||
i18n_init();
|
||||
|
||||
@ -1303,7 +1304,8 @@ main( int argc, char **argv )
|
||||
maybe_setuid = 0;
|
||||
/* Okay, we are now working under our real uid */
|
||||
|
||||
/* malloc hooks gohere ... */
|
||||
/* 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 */
|
||||
|
||||
@ -2894,6 +2896,13 @@ main( int argc, char **argv )
|
||||
return 8; /*NEVER REACHED*/
|
||||
}
|
||||
|
||||
/* Note: This function is used by signal handlers!. */
|
||||
static void
|
||||
emergency_cleanup (void)
|
||||
{
|
||||
gcry_control (GCRYCTL_TERM_SECMEM );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
g10_exit( int rc )
|
||||
|
@ -147,7 +147,7 @@ main( int argc, char **argv )
|
||||
|
||||
set_strusage (my_strusage);
|
||||
log_set_prefix ("gpgv", 1);
|
||||
init_signals();
|
||||
gnupg_init_signals(0, NULL);
|
||||
i18n_init();
|
||||
opt.command_fd = -1; /* no command fd */
|
||||
opt.pgp2_workarounds = 1;
|
||||
|
@ -921,6 +921,10 @@ change_passphrase( KBNODE keyblock )
|
||||
tty_printf(_("Secret parts of primary key are not available.\n"));
|
||||
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 {
|
||||
tty_printf(_("Key is protected.\n"));
|
||||
rc = check_secret_key( sk, 0 );
|
||||
|
960
g10/keygen.c
960
g10/keygen.c
File diff suppressed because it is too large
Load Diff
@ -1634,6 +1634,8 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
|
||||
break;
|
||||
case 1001: if( list_mode ) printf( "\tgnu-dummy S2K" );
|
||||
break;
|
||||
case 1002: if (list_mode) printf("\tgnu-divert-to-card S2K");
|
||||
break;
|
||||
default:
|
||||
if( list_mode )
|
||||
printf( "\tunknown %sS2K %d\n",
|
||||
@ -1669,6 +1671,31 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
|
||||
printf("\tprotect count: %lu\n",
|
||||
(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
|
||||
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 )
|
||||
sk->protect.ivlen = 0;
|
||||
else if( sk->protect.s2k.mode == 1002 )
|
||||
sk->protect.ivlen = 0;
|
||||
|
||||
if( pktlen < sk->protect.ivlen ) {
|
||||
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,
|
||||
* we can assume, that he operates an open system :=(.
|
||||
* 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 */
|
||||
sk->skey[npkey] = mpi_set_opaque(NULL, xstrdup ("dummydata"), 10);
|
||||
pktlen = 0;
|
||||
|
@ -794,7 +794,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
|
||||
tryagain_text = _(tryagain_text);
|
||||
|
||||
/* 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
|
||||
+ 3*strlen (tryagain_text) + 3*strlen (atext) + 2);
|
||||
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 i,mode;
|
||||
|
||||
if (sk && sk->is_protected && sk->protect.s2k.mode == 1002)
|
||||
return 0; /* Let the scdaemon handle it. */
|
||||
|
||||
if(n<0)
|
||||
{
|
||||
n=abs(n);
|
||||
|
@ -231,3 +231,8 @@ encode_md_value (int pubkey_algo, gcry_md_hd_t md, int hash_algo,
|
||||
return frame;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
140
g10/sign.c
140
g10/sign.c
@ -249,74 +249,94 @@ static int
|
||||
do_sign( PKT_secret_key *sk, PKT_signature *sig,
|
||||
MD_HANDLE md, int digest_algo )
|
||||
{
|
||||
gcry_mpi_t frame;
|
||||
byte *dp;
|
||||
int rc;
|
||||
gcry_mpi_t frame;
|
||||
byte *dp;
|
||||
int rc;
|
||||
|
||||
if( sk->timestamp > sig->timestamp ) {
|
||||
ulong d = sk->timestamp - sig->timestamp;
|
||||
log_info( d==1 ? _("key has been created %lu second "
|
||||
"in future (time warp or clock problem)\n")
|
||||
: _("key has been created %lu seconds "
|
||||
"in future (time warp or clock problem)\n"), d );
|
||||
if( !opt.ignore_time_conflict )
|
||||
return GPG_ERR_TIME_CONFLICT;
|
||||
}
|
||||
if( sk->timestamp > sig->timestamp ) {
|
||||
ulong d = sk->timestamp - sig->timestamp;
|
||||
log_info( d==1 ? _("key has been created %lu second "
|
||||
"in future (time warp or clock problem)\n")
|
||||
: _("key has been created %lu seconds "
|
||||
"in future (time warp or clock problem)\n"), d );
|
||||
if( !opt.ignore_time_conflict )
|
||||
return GPG_ERR_TIME_CONFLICT;
|
||||
}
|
||||
|
||||
print_pubkey_algo_note(sk->pubkey_algo);
|
||||
|
||||
print_pubkey_algo_note(sk->pubkey_algo);
|
||||
if( !digest_algo )
|
||||
digest_algo = gcry_md_get_algo(md);
|
||||
|
||||
if( !digest_algo )
|
||||
digest_algo = gcry_md_get_algo(md);
|
||||
print_digest_algo_note( digest_algo );
|
||||
dp = gcry_md_read ( md, digest_algo );
|
||||
sig->digest_algo = digest_algo;
|
||||
sig->digest_start[0] = dp[0];
|
||||
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;
|
||||
|
||||
print_digest_algo_note( digest_algo );
|
||||
dp = gcry_md_read ( md, digest_algo );
|
||||
sig->digest_algo = digest_algo;
|
||||
sig->digest_start[0] = dp[0];
|
||||
sig->digest_start[1] = dp[1];
|
||||
frame = encode_md_value( sk->pubkey_algo, md,
|
||||
digest_algo, mpi_get_nbits(sk->skey[0]), 0 );
|
||||
if (!frame)
|
||||
return GPG_ERR_GENERAL;
|
||||
rc = pk_sign( sk->pubkey_algo, sig->data, frame, sk->skey );
|
||||
gcry_mpi_release (frame);
|
||||
if (!rc && !opt.no_sig_create_check) {
|
||||
/* check that the signature verification worked and nothing is
|
||||
* fooling us e.g. by a bug in the signature create
|
||||
* code or by deliberately introduced faults. */
|
||||
PKT_public_key *pk = xcalloc (1,sizeof *pk);
|
||||
|
||||
if( get_pubkey( pk, sig->keyid ) )
|
||||
rc = GPG_ERR_NO_PUBKEY;
|
||||
else {
|
||||
frame = encode_md_value (pk->pubkey_algo, md,
|
||||
sig->digest_algo,
|
||||
mpi_get_nbits(pk->pkey[0]), 0);
|
||||
if (!frame)
|
||||
rc = GPG_ERR_GENERAL;
|
||||
else
|
||||
rc = pk_verify (pk->pubkey_algo, frame,
|
||||
sig->data, pk->pkey);
|
||||
gcry_mpi_release (frame);
|
||||
/* 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 ();
|
||||
}
|
||||
if (rc)
|
||||
log_error (_("checking created signature failed: %s\n"),
|
||||
gpg_strerror (rc));
|
||||
free_public_key (pk);
|
||||
}
|
||||
if( rc )
|
||||
log_error(_("signing failed: %s\n"), gpg_strerror (rc) );
|
||||
else
|
||||
{
|
||||
frame = encode_md_value( sk->pubkey_algo, md,
|
||||
digest_algo, mpi_get_nbits(sk->skey[0]), 0 );
|
||||
if (!frame)
|
||||
return GPG_ERR_GENERAL;
|
||||
rc = pk_sign( sk->pubkey_algo, sig->data, frame, sk->skey );
|
||||
gcry_mpi_release (frame);
|
||||
}
|
||||
if (!rc && !opt.no_sig_create_check) {
|
||||
/* check that the signature verification worked and nothing is
|
||||
* fooling us e.g. by a bug in the signature create
|
||||
* code or by deliberately introduced faults. */
|
||||
PKT_public_key *pk = xcalloc (1,sizeof *pk);
|
||||
|
||||
if( get_pubkey( pk, sig->keyid ) )
|
||||
rc = GPG_ERR_NO_PUBKEY;
|
||||
else {
|
||||
if( opt.verbose ) {
|
||||
char *ustr = get_user_id_string_printable (sig->keyid);
|
||||
log_info(_("%s/%s signature from: \"%s\"\n"),
|
||||
gcry_pk_algo_name (sk->pubkey_algo),
|
||||
gcry_md_algo_name (sig->digest_algo),
|
||||
ustr );
|
||||
xfree (ustr);
|
||||
}
|
||||
frame = encode_md_value (pk->pubkey_algo, md,
|
||||
sig->digest_algo,
|
||||
mpi_get_nbits(pk->pkey[0]), 0);
|
||||
if (!frame)
|
||||
rc = GPG_ERR_GENERAL;
|
||||
else
|
||||
rc = pk_verify (pk->pubkey_algo, frame,
|
||||
sig->data, pk->pkey);
|
||||
gcry_mpi_release (frame);
|
||||
}
|
||||
return rc;
|
||||
if (rc)
|
||||
log_error (_("checking created signature failed: %s\n"),
|
||||
gpg_strerror (rc));
|
||||
free_public_key (pk);
|
||||
}
|
||||
if( rc )
|
||||
log_error(_("signing failed: %s\n"), gpg_strerror (rc) );
|
||||
else {
|
||||
if( opt.verbose ) {
|
||||
char *ustr = get_user_id_string_printable (sig->keyid);
|
||||
log_info(_("%s/%s signature from: \"%s\"\n"),
|
||||
gcry_pk_algo_name (sk->pubkey_algo),
|
||||
gcry_md_algo_name (sig->digest_algo),
|
||||
ustr );
|
||||
xfree (ustr);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@ -1170,7 +1190,7 @@ sign_symencrypt_file (const char *fname, STRLIST locusr)
|
||||
* SIGVERSION gives the minimal required signature packet version;
|
||||
* this is needed so that special properties like local sign are not
|
||||
* 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
|
||||
make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
|
||||
PKT_user_id *uid, PKT_public_key *subpk,
|
||||
|
@ -372,10 +372,11 @@ tdbio_end_transaction()
|
||||
else
|
||||
is_locked = 1;
|
||||
}
|
||||
block_all_signals();
|
||||
#warning block_all_signals is not yet available in ../common/signals.c
|
||||
/* block_all_signals(); */
|
||||
in_transaction = 0;
|
||||
rc = tdbio_sync();
|
||||
unblock_all_signals();
|
||||
/* unblock_all_signals(); */
|
||||
if( !opt.lock_once ) {
|
||||
if( !release_dotlock( lockhandle ) )
|
||||
is_locked = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user