mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-21 14:47:03 +01:00
* options.h (DBG_CIPHER): Reintroduced it.
* seskey.c (encode_session_key): Debug output of the session key. * pubkey-enc.c (get_it): Handle card case. * call-agent.c (agent_scd_pkdecrypt): New. * pkglue.c (pk_encrypt): Add RSA support. * g10.c (main): Default to --use-agent. * keygen.c (show_smartcard): Print info about the public key. (check_smartcard): Check for existing key here. (gen_card_key): And not anymore here. (fpr_is_zero): New. (generate_keypair): Generate both keys for a card. (smartcard_change_url): Nw.
This commit is contained in:
parent
39046ea7ec
commit
1753a2f3b0
@ -1,3 +1,25 @@
|
||||
2003-07-03 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* options.h (DBG_CIPHER): Reintroduced it.
|
||||
* seskey.c (encode_session_key): Debug output of the session key.
|
||||
|
||||
* pubkey-enc.c (get_it): Handle card case.
|
||||
* call-agent.c (agent_scd_pkdecrypt): New.
|
||||
* pkglue.c (pk_encrypt): Add RSA support.
|
||||
|
||||
* g10.c (main): Default to --use-agent.
|
||||
|
||||
* keygen.c (show_smartcard): Print info about the public key.
|
||||
(check_smartcard): Check for existing key here.
|
||||
(gen_card_key): And not anymore here.
|
||||
(fpr_is_zero): New.
|
||||
(generate_keypair): Generate both keys for a card.
|
||||
(smartcard_change_url): Nw.
|
||||
|
||||
2003-07-02 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* seckey-cert.c (is_secret_key_protected): Let it handle mode 1002.
|
||||
|
||||
2003-07-01 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* keygen.c (gen_card_key): Obviously we should use the creation
|
||||
|
@ -456,7 +456,6 @@ learn_status_cb (void *opaque, const char *line)
|
||||
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))
|
||||
@ -470,7 +469,7 @@ learn_status_cb (void *opaque, const char *line)
|
||||
{
|
||||
parm->disp_name = unescape_status_string (line);
|
||||
}
|
||||
else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY_URL", keywordlen))
|
||||
else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
|
||||
{
|
||||
parm->pubkey_url = unescape_status_string (line);
|
||||
}
|
||||
@ -670,7 +669,7 @@ agent_scd_pksign (const char *serialno, int hashalgo,
|
||||
sprintf (p, "%02X", indata[i]);
|
||||
rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (rc)
|
||||
return rc;
|
||||
return map_assuan_err (rc);
|
||||
|
||||
init_membuf (&data, 1024);
|
||||
snprintf (line, DIM(line)-1, "SCD PKSIGN %s", serialno);
|
||||
@ -680,9 +679,62 @@ agent_scd_pksign (const char *serialno, int hashalgo,
|
||||
if (rc)
|
||||
{
|
||||
xfree (get_membuf (&data, &len));
|
||||
return rc;
|
||||
return map_assuan_err (rc);
|
||||
}
|
||||
*r_buf = get_membuf (&data, r_buflen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Decrypt INDATA of length INDATALEN using the card identified by
|
||||
SERIALNO. Return the plaintext in a nwly allocated buffer stored
|
||||
at the address of R_BUF.
|
||||
|
||||
Note, we currently support only RSA or more exactly algorithms
|
||||
taking one input data element. */
|
||||
int
|
||||
agent_scd_pkdecrypt (const char *serialno,
|
||||
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;
|
||||
|
||||
*r_buf = NULL;
|
||||
rc = start_agent ();
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* FIXME: use secure memory where appropriate */
|
||||
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 map_assuan_err (rc);
|
||||
|
||||
init_membuf (&data, 1024);
|
||||
snprintf (line, DIM(line)-1, "SCD PKDECRYPT %s", serialno);
|
||||
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 map_assuan_err (rc);
|
||||
}
|
||||
*r_buf = get_membuf (&data, r_buflen);
|
||||
if (!*r_buf)
|
||||
return gpg_error (GPG_ERR_ENOMEM);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -61,12 +61,10 @@ 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);
|
||||
|
||||
|
||||
|
||||
/* Send a PKDECRYPT command to the SCdaemon. */
|
||||
int agent_scd_pkdecrypt (const char *serialno,
|
||||
const unsigned char *indata, size_t indatalen,
|
||||
char **r_buf, size_t *r_buflen);
|
||||
|
||||
|
||||
|
||||
|
@ -1228,6 +1228,7 @@ main( int argc, char **argv )
|
||||
opt.verify_options=VERIFY_SHOW_POLICY|VERIFY_SHOW_NOTATION;
|
||||
opt.trust_model=TM_AUTO;
|
||||
opt.mangle_dos_filenames = 1;
|
||||
opt.use_agent = 1;
|
||||
|
||||
#if defined (__MINGW32__)
|
||||
set_homedir ( read_w32_registry_string( NULL,
|
||||
@ -1984,6 +1985,9 @@ main( int argc, char **argv )
|
||||
}
|
||||
#endif
|
||||
|
||||
#warning locking does not work - disabled
|
||||
disable_dotlock ();
|
||||
|
||||
if (opt.verbose > 2)
|
||||
log_info ("using character set `%s'\n", get_native_charset ());
|
||||
|
||||
|
@ -898,7 +898,7 @@ get_pubkey_end( GETKEY_CTX ctx )
|
||||
/****************
|
||||
* Search for a key with the given fingerprint.
|
||||
* FIXME:
|
||||
* We should replace this with the _byname function. Thiscsan be done
|
||||
* We should replace this with the _byname function. This can be done
|
||||
* by creating a userID conforming to the unified fingerprint style.
|
||||
*/
|
||||
int
|
||||
|
@ -923,7 +923,7 @@ change_passphrase( KBNODE keyblock )
|
||||
}
|
||||
else if( sk->protect.s2k.mode == 1002 ) {
|
||||
tty_printf(_("Secret key is actually stored on a card.\n"));
|
||||
no_primary_secrets = 1;
|
||||
goto leave;
|
||||
}
|
||||
else {
|
||||
tty_printf(_("Key is protected.\n"));
|
||||
|
198
g10/keygen.c
198
g10/keygen.c
@ -2096,8 +2096,6 @@ generate_keypair( const char *fname )
|
||||
card = check_smartcard (&serialno);
|
||||
if (card < 0)
|
||||
return;
|
||||
if (card > 1)
|
||||
log_error (_("can't generate subkey here\n"));
|
||||
}
|
||||
while (card > 1);
|
||||
|
||||
@ -2114,55 +2112,75 @@ generate_keypair( const char *fname )
|
||||
if (card)
|
||||
{
|
||||
algo = PUBKEY_ALGO_RSA;
|
||||
use = PUBKEY_USAGE_SIG;
|
||||
}
|
||||
else
|
||||
algo = ask_algo (0, &use);
|
||||
|
||||
if (!algo)
|
||||
{ /* default: DSA with ElG subkey of the specified size */
|
||||
both = 1;
|
||||
r = xcalloc (1, sizeof *r + 20 );
|
||||
r->key = pKEYTYPE;
|
||||
sprintf( r->u.value, "%d", PUBKEY_ALGO_DSA );
|
||||
sprintf( r->u.value, "%d", algo );
|
||||
r->next = para;
|
||||
para = r;
|
||||
tty_printf(_("DSA keypair will have 1024 bits.\n"));
|
||||
r = xcalloc (1, sizeof *r + 20 );
|
||||
r->key = pKEYLENGTH;
|
||||
strcpy( r->u.value, "1024" );
|
||||
r->key = pKEYUSAGE;
|
||||
strcpy (r->u.value, "sign");
|
||||
r->next = para;
|
||||
para = r;
|
||||
|
||||
algo = PUBKEY_ALGO_ELGAMAL_E;
|
||||
|
||||
r = xcalloc (1, sizeof *r + 20 );
|
||||
r->key = pSUBKEYTYPE;
|
||||
sprintf( r->u.value, "%d", algo );
|
||||
r->next = para;
|
||||
para = r;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = xcalloc (1, sizeof *r + 20 );
|
||||
r->key = pKEYTYPE;
|
||||
sprintf( r->u.value, "%d", algo );
|
||||
r->key = pSUBKEYUSAGE;
|
||||
strcpy (r->u.value, "encrypt");
|
||||
r->next = para;
|
||||
para = r;
|
||||
}
|
||||
else
|
||||
{
|
||||
algo = ask_algo (0, &use);
|
||||
|
||||
if (use)
|
||||
{
|
||||
if (!algo)
|
||||
{ /* default: DSA with ElG subkey of the specified size */
|
||||
both = 1;
|
||||
r = xcalloc (1, sizeof *r + 20 );
|
||||
r->key = pKEYUSAGE;
|
||||
sprintf( r->u.value, "%s%s",
|
||||
(use & PUBKEY_USAGE_SIG)? "sign ":"",
|
||||
(use & PUBKEY_USAGE_ENC)? "encrypt ":"" );
|
||||
r->key = pKEYTYPE;
|
||||
sprintf( r->u.value, "%d", PUBKEY_ALGO_DSA );
|
||||
r->next = para;
|
||||
para = r;
|
||||
tty_printf(_("DSA keypair will have 1024 bits.\n"));
|
||||
r = xcalloc (1, sizeof *r + 20 );
|
||||
r->key = pKEYLENGTH;
|
||||
strcpy( r->u.value, "1024" );
|
||||
r->next = para;
|
||||
para = r;
|
||||
|
||||
algo = PUBKEY_ALGO_ELGAMAL_E;
|
||||
r = xcalloc (1, sizeof *r + 20 );
|
||||
r->key = pSUBKEYTYPE;
|
||||
sprintf( r->u.value, "%d", algo );
|
||||
r->next = para;
|
||||
para = r;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
r = xcalloc (1, sizeof *r + 20 );
|
||||
r->key = pKEYTYPE;
|
||||
sprintf( r->u.value, "%d", algo );
|
||||
r->next = para;
|
||||
para = r;
|
||||
|
||||
if (use)
|
||||
{
|
||||
r = xcalloc (1, sizeof *r + 20 );
|
||||
r->key = pKEYUSAGE;
|
||||
sprintf( r->u.value, "%s%s",
|
||||
(use & PUBKEY_USAGE_SIG)? "sign ":"",
|
||||
(use & PUBKEY_USAGE_ENC)? "encrypt ":"" );
|
||||
r->next = para;
|
||||
para = r;
|
||||
}
|
||||
}
|
||||
|
||||
if (!card)
|
||||
{
|
||||
nbits = ask_keysize( algo );
|
||||
r = xcalloc (1, sizeof *r + 20 );
|
||||
r->key = both? pSUBKEYLENGTH : pKEYLENGTH;
|
||||
@ -2367,12 +2385,21 @@ do_generate_keypair (struct para_data_s *para,
|
||||
|
||||
if (get_parameter (para, pSUBKEYTYPE))
|
||||
{
|
||||
rc = do_create (get_parameter_algo (para, pSUBKEYTYPE),
|
||||
get_parameter_uint (para, pSUBKEYLENGTH),
|
||||
pub_root, sec_root,
|
||||
get_parameter_dek (para, pPASSPHRASE_DEK),
|
||||
get_parameter_s2k (para, pPASSPHRASE_S2K),
|
||||
NULL, get_parameter_u32 (para, pSUBKEYEXPIRE));
|
||||
if (!card)
|
||||
{
|
||||
rc = do_create (get_parameter_algo (para, pSUBKEYTYPE),
|
||||
get_parameter_uint (para, pSUBKEYLENGTH),
|
||||
pub_root, sec_root,
|
||||
get_parameter_dek (para, pPASSPHRASE_DEK),
|
||||
get_parameter_s2k (para, pPASSPHRASE_S2K),
|
||||
NULL, get_parameter_u32 (para, pSUBKEYEXPIRE));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = gen_card_key (PUBKEY_ALGO_RSA, 2, pub_root, sec_root,
|
||||
get_parameter_u32 (para, pKEYEXPIRE), para);
|
||||
}
|
||||
|
||||
if (!rc)
|
||||
rc = write_keybinding (pub_root, pub_root, sk,
|
||||
get_parameter_uint (para, pSUBKEYUSAGE));
|
||||
@ -2642,13 +2669,15 @@ show_sha1_fpr (const unsigned char *fpr)
|
||||
}
|
||||
}
|
||||
else
|
||||
tty_printf ("[none]");
|
||||
tty_printf (" [none]");
|
||||
tty_printf ("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
show_smartcard (struct agent_card_info_s *info)
|
||||
{
|
||||
PKT_public_key *pk = xcalloc (1, sizeof *pk);
|
||||
|
||||
/* FIXME: Sanitize what we show. */
|
||||
tty_printf ("Name of cardholder: %s\n",
|
||||
info->disp_name && *info->disp_name? info->disp_name
|
||||
@ -2656,12 +2685,17 @@ show_smartcard (struct agent_card_info_s *info)
|
||||
tty_printf ("URL of public key : %s\n",
|
||||
info->pubkey_url && *info->pubkey_url? info->pubkey_url
|
||||
: "[not set]");
|
||||
tty_printf ("Signature key ....: ");
|
||||
tty_printf ("Signature key ....:");
|
||||
show_sha1_fpr (info->fpr1valid? info->fpr1:NULL);
|
||||
tty_printf ("Encryption key....: ");
|
||||
tty_printf ("Encryption key....:");
|
||||
show_sha1_fpr (info->fpr2valid? info->fpr2:NULL);
|
||||
tty_printf ("Authentication key: ");
|
||||
tty_printf ("Authentication key:");
|
||||
show_sha1_fpr (info->fpr3valid? info->fpr3:NULL);
|
||||
|
||||
if (info->fpr1valid && !get_pubkey_byfprint (pk, info->fpr1, 20))
|
||||
print_pubkey_info (pk);
|
||||
|
||||
free_public_key( pk );
|
||||
}
|
||||
|
||||
|
||||
@ -2726,17 +2760,48 @@ smartcard_change_name (const char *current_name)
|
||||
if (rc)
|
||||
log_error ("error setting Name: %s\n", gpg_strerror (rc));
|
||||
|
||||
xfree (isoname);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
smartcard_change_url (const char *current_url)
|
||||
{
|
||||
char *url;
|
||||
int rc;
|
||||
|
||||
url = cpr_get ("keygen.smartcard.url", _("URL to retrieve public key: "));
|
||||
if (!url)
|
||||
return -1;
|
||||
trim_spaces (url);
|
||||
cpr_kill_prompt ();
|
||||
|
||||
rc = agent_scd_setattr ("PUBKEY-URL", url, strlen (url) );
|
||||
if (rc)
|
||||
log_error ("error setting URL: %s\n", gpg_strerror (rc));
|
||||
xfree (url);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/* Return true if the SHA1 fingerprint FPR consists only of zeroes. */
|
||||
static int
|
||||
fpr_is_zero (const char *fpr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < 20 && !fpr[i]; i++)
|
||||
;
|
||||
return (i == 20);
|
||||
}
|
||||
|
||||
/* 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
|
||||
1 = Generate keypair
|
||||
*/
|
||||
static int
|
||||
check_smartcard (char **r_serialno)
|
||||
@ -2767,9 +2832,8 @@ check_smartcard (char **r_serialno)
|
||||
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"
|
||||
"K - generate signature and encryption key\n"
|
||||
"A - generate authentication key\n"
|
||||
"Q - quit\n"
|
||||
"\n");
|
||||
|
||||
@ -2786,13 +2850,31 @@ check_smartcard (char **r_serialno)
|
||||
}
|
||||
else if ( *answer == 'U' || *answer == 'u')
|
||||
{
|
||||
if (!smartcard_change_url (info.pubkey_url))
|
||||
reread = 1;
|
||||
}
|
||||
else if ( *answer == '1' || *answer == '2')
|
||||
else if ( *answer == 'K' || *answer == 'k')
|
||||
{
|
||||
rc = *answer - '0';
|
||||
break;
|
||||
if ( (info.fpr1valid && !fpr_is_zero (info.fpr1))
|
||||
|| (info.fpr2valid && !fpr_is_zero (info.fpr2)))
|
||||
{
|
||||
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 = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ( *answer == '3' )
|
||||
else if ( *answer == 'A' || *answer == 'a' )
|
||||
{
|
||||
tty_printf (_("Generation of authentication key"
|
||||
" not yet implemented\n"));
|
||||
@ -2844,16 +2926,16 @@ gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root,
|
||||
|
||||
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);
|
||||
}
|
||||
rc = agent_scd_genkey (&info, keyno, 1);
|
||||
/* 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)
|
||||
{
|
||||
|
@ -201,6 +201,7 @@ struct {
|
||||
|
||||
|
||||
#define DBG_PACKET (opt.debug & DBG_PACKET_VALUE)
|
||||
#define DBG_CIPHER (opt.debug & DBG_CIPHER_VALUE)
|
||||
#define DBG_FILTER (opt.debug & DBG_FILTER_VALUE)
|
||||
#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE)
|
||||
#define DBG_TRUST (opt.debug & DBG_TRUST_VALUE)
|
||||
|
26
g10/pkglue.c
26
g10/pkglue.c
@ -177,6 +177,12 @@ pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, gcry_mpi_t * pkey)
|
||||
"(public-key(elg(p%m)(g%m)(y%m)))",
|
||||
pkey[0], pkey[1], pkey[2]);
|
||||
}
|
||||
else if (algo == GCRY_PK_RSA)
|
||||
{
|
||||
rc = gcry_sexp_build (&s_pkey, NULL,
|
||||
"(public-key(rsa(n%m)(e%m)))",
|
||||
pkey[0], pkey[1]);
|
||||
}
|
||||
else
|
||||
return GPG_ERR_PUBKEY_ALGO;
|
||||
|
||||
@ -202,11 +208,14 @@ pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, gcry_mpi_t * pkey)
|
||||
assert (resarr[0]);
|
||||
gcry_sexp_release (list);
|
||||
|
||||
list = gcry_sexp_find_token (s_ciph, "b", 0);
|
||||
assert (list);
|
||||
resarr[1] = gcry_sexp_nth_mpi (list, 1, 0);
|
||||
assert (resarr[1]);
|
||||
gcry_sexp_release (list);
|
||||
if (algo != GCRY_PK_RSA)
|
||||
{
|
||||
list = gcry_sexp_find_token (s_ciph, "b", 0);
|
||||
assert (list);
|
||||
resarr[1] = gcry_sexp_nth_mpi (list, 1, 0);
|
||||
assert (resarr[1]);
|
||||
gcry_sexp_release (list);
|
||||
}
|
||||
}
|
||||
|
||||
gcry_sexp_release (s_ciph);
|
||||
@ -276,3 +285,10 @@ pk_decrypt (int algo, gcry_mpi_t * result, gcry_mpi_t * data,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
296
g10/pubkey-enc.c
296
g10/pubkey-enc.c
@ -38,6 +38,7 @@
|
||||
#include "main.h"
|
||||
#include "i18n.h"
|
||||
#include "pkglue.h"
|
||||
#include "call-agent.h"
|
||||
|
||||
static int get_it( PKT_pubkey_enc *k,
|
||||
DEK *dek, PKT_secret_key *sk, u32 *keyid );
|
||||
@ -136,146 +137,181 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
|
||||
static int
|
||||
get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid )
|
||||
{
|
||||
int rc;
|
||||
gcry_mpi_t plain_dek = NULL;
|
||||
byte *frame = NULL;
|
||||
unsigned n, nframe;
|
||||
u16 csum, csum2;
|
||||
int rc;
|
||||
gcry_mpi_t plain_dek = NULL;
|
||||
byte *frame = NULL;
|
||||
unsigned n, nframe;
|
||||
u16 csum, csum2;
|
||||
int card = 0;
|
||||
|
||||
rc = pk_decrypt (sk->pubkey_algo, &plain_dek, enc->data, sk->skey);
|
||||
if( rc )
|
||||
goto leave;
|
||||
if ( gcry_mpi_aprint (GCRYMPI_FMT_USG, &frame, &nframe, plain_dek))
|
||||
BUG();
|
||||
gcry_mpi_release (plain_dek); plain_dek = NULL;
|
||||
if (sk->is_protected && sk->protect.s2k.mode == 1002)
|
||||
{ /* FIXME: Note that we do only support RSA for now. */
|
||||
char *rbuf;
|
||||
size_t rbuflen;
|
||||
char *snbuf;
|
||||
void *indata = NULL;
|
||||
unsigned int indatalen;
|
||||
|
||||
/* Now get the DEK (data encryption key) from the frame
|
||||
*
|
||||
* Old versions encode the DEK in in this format (msb is left):
|
||||
*
|
||||
* 0 1 DEK(16 bytes) CSUM(2 bytes) 0 RND(n bytes) 2
|
||||
*
|
||||
* Later versions encode the DEK like this:
|
||||
*
|
||||
* 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes)
|
||||
*
|
||||
* (mpi_get_buffer already removed the leading zero).
|
||||
*
|
||||
* RND are non-zero randow bytes.
|
||||
* A is the cipher algorithm
|
||||
* DEK is the encryption key (session key) with length k
|
||||
* CSUM
|
||||
*/
|
||||
if( DBG_CIPHER )
|
||||
log_printhex ("DEK frame:", frame, nframe );
|
||||
n=0;
|
||||
if( n + 7 > nframe )
|
||||
{ rc = GPG_ERR_WRONG_SECKEY; goto leave; }
|
||||
if( frame[n] == 1 && frame[nframe-1] == 2 ) {
|
||||
log_info(_("old encoding of the DEK is not supported\n"));
|
||||
rc = GPG_ERR_CIPHER_ALGO;
|
||||
goto leave;
|
||||
}
|
||||
if( frame[n] != 2 ) /* somethink is wrong */
|
||||
{ rc = GPG_ERR_WRONG_SECKEY; goto leave; }
|
||||
for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */
|
||||
;
|
||||
n++; /* and the zero byte */
|
||||
if( n + 4 > nframe )
|
||||
{ rc = GPG_ERR_WRONG_SECKEY; goto leave; }
|
||||
snbuf = serialno_and_fpr_from_sk (sk->protect.iv, sk->protect.ivlen, sk);
|
||||
|
||||
dek->keylen = nframe - (n+1) - 2;
|
||||
dek->algo = frame[n++];
|
||||
if( dek->algo == CIPHER_ALGO_IDEA )
|
||||
write_status(STATUS_RSA_OR_IDEA);
|
||||
rc = openpgp_cipher_test_algo (dek->algo);
|
||||
if( rc ) {
|
||||
if( !opt.quiet && gpg_err_code (rc) == GPG_ERR_CIPHER_ALGO ) {
|
||||
log_info(_("cipher algorithm %d%s is unknown or disabled\n"),
|
||||
dek->algo, dek->algo == CIPHER_ALGO_IDEA? " (IDEA)":"");
|
||||
if(dek->algo==CIPHER_ALGO_IDEA)
|
||||
idea_cipher_warn(0);
|
||||
}
|
||||
dek->algo = 0;
|
||||
goto leave;
|
||||
}
|
||||
if( dek->keylen != gcry_cipher_get_algo_keylen (dek->algo) ) {
|
||||
rc = GPG_ERR_WRONG_SECKEY;
|
||||
goto leave;
|
||||
}
|
||||
if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &indata, &indatalen,
|
||||
enc->data[0]))
|
||||
BUG();
|
||||
|
||||
/* copy the key to DEK and compare the checksum */
|
||||
csum = frame[nframe-2] << 8;
|
||||
csum |= frame[nframe-1];
|
||||
memcpy( dek->key, frame+n, dek->keylen );
|
||||
for( csum2=0, n=0; n < dek->keylen; n++ )
|
||||
csum2 += dek->key[n];
|
||||
if( csum != csum2 ) {
|
||||
rc = GPG_ERR_WRONG_SECKEY;
|
||||
goto leave;
|
||||
rc = agent_scd_pkdecrypt (snbuf, indata, indatalen, &rbuf, &rbuflen);
|
||||
xfree (snbuf);
|
||||
xfree (indata);
|
||||
if (rc)
|
||||
goto leave;
|
||||
|
||||
frame = rbuf;
|
||||
nframe = rbuflen;
|
||||
card = 1;
|
||||
}
|
||||
if( DBG_CIPHER )
|
||||
log_printhex ("DEK is:", dek->key, dek->keylen );
|
||||
/* check that the algo is in the preferences and whether it has expired */
|
||||
else
|
||||
{
|
||||
PKT_public_key *pk = NULL;
|
||||
KBNODE pkb = get_pubkeyblock (keyid);
|
||||
void *indata;
|
||||
|
||||
if( !pkb ) {
|
||||
rc = -1;
|
||||
log_error("oops: public key not found for preference check\n");
|
||||
}
|
||||
else if( pkb->pkt->pkt.public_key->selfsigversion > 3
|
||||
&& dek->algo != CIPHER_ALGO_3DES
|
||||
&& !is_algo_in_prefs( pkb, PREFTYPE_SYM, dek->algo ) ) {
|
||||
/* Don't print a note while we are not on verbose mode,
|
||||
* the cipher is blowfish and the preferences have twofish
|
||||
* listed */
|
||||
if( opt.verbose || dek->algo != CIPHER_ALGO_BLOWFISH
|
||||
|| !is_algo_in_prefs( pkb, PREFTYPE_SYM, CIPHER_ALGO_TWOFISH))
|
||||
log_info(_(
|
||||
"NOTE: cipher algorithm %d not found in preferences\n"),
|
||||
dek->algo );
|
||||
}
|
||||
|
||||
if (!rc) {
|
||||
KBNODE k;
|
||||
|
||||
for (k=pkb; k; k = k->next) {
|
||||
if (k->pkt->pkttype == PKT_PUBLIC_KEY
|
||||
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY){
|
||||
u32 aki[2];
|
||||
keyid_from_pk(k->pkt->pkt.public_key, aki);
|
||||
|
||||
if (aki[0]==keyid[0] && aki[1]==keyid[1]) {
|
||||
pk = k->pkt->pkt.public_key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!pk)
|
||||
BUG ();
|
||||
if ( pk->expiredate && pk->expiredate <= make_timestamp() ) {
|
||||
log_info(_("NOTE: secret key %08lX expired at %s\n"),
|
||||
(ulong)keyid[1], asctimestamp( pk->expiredate) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( pk && pk->is_revoked ) {
|
||||
log_info( _("NOTE: key has been revoked") );
|
||||
putc( '\n', log_get_stream() );
|
||||
show_revocation_reason( pk, 1 );
|
||||
}
|
||||
|
||||
release_kbnode (pkb);
|
||||
rc = 0;
|
||||
rc = pk_decrypt (sk->pubkey_algo, &plain_dek, enc->data, sk->skey);
|
||||
if( rc )
|
||||
goto leave;
|
||||
if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &indata, &nframe, plain_dek))
|
||||
BUG();
|
||||
frame = indata;
|
||||
gcry_mpi_release (plain_dek); plain_dek = NULL;
|
||||
}
|
||||
|
||||
|
||||
leave:
|
||||
gcry_mpi_release (plain_dek);
|
||||
xfree (frame);
|
||||
return rc;
|
||||
/* Now get the DEK (data encryption key) from the frame
|
||||
*
|
||||
* Old versions encode the DEK in in this format (msb is left):
|
||||
*
|
||||
* 0 1 DEK(16 bytes) CSUM(2 bytes) 0 RND(n bytes) 2
|
||||
*
|
||||
* Later versions encode the DEK like this:
|
||||
*
|
||||
* 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes)
|
||||
*
|
||||
* (mpi_get_buffer already removed the leading zero).
|
||||
*
|
||||
* RND are non-zero randow bytes.
|
||||
* A is the cipher algorithm
|
||||
* DEK is the encryption key (session key) with length k
|
||||
* CSUM
|
||||
*/
|
||||
if( DBG_CIPHER )
|
||||
log_printhex ("DEK frame:", frame, nframe );
|
||||
n=0;
|
||||
if (!card)
|
||||
{
|
||||
if( n + 7 > nframe )
|
||||
{ rc = GPG_ERR_WRONG_SECKEY; goto leave; }
|
||||
if( frame[n] == 1 && frame[nframe-1] == 2 ) {
|
||||
log_info(_("old encoding of the DEK is not supported\n"));
|
||||
rc = GPG_ERR_CIPHER_ALGO;
|
||||
goto leave;
|
||||
}
|
||||
if( frame[n] != 2 ) /* somethink is wrong */
|
||||
{ rc = GPG_ERR_WRONG_SECKEY; goto leave; }
|
||||
for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */
|
||||
;
|
||||
n++; /* and the zero byte */
|
||||
}
|
||||
|
||||
if( n + 4 > nframe )
|
||||
{ rc = GPG_ERR_WRONG_SECKEY; goto leave; }
|
||||
dek->keylen = nframe - (n+1) - 2;
|
||||
dek->algo = frame[n++];
|
||||
if( dek->algo == CIPHER_ALGO_IDEA )
|
||||
write_status(STATUS_RSA_OR_IDEA);
|
||||
rc = openpgp_cipher_test_algo (dek->algo);
|
||||
if( rc ) {
|
||||
if( !opt.quiet && gpg_err_code (rc) == GPG_ERR_CIPHER_ALGO ) {
|
||||
log_info(_("cipher algorithm %d%s is unknown or disabled\n"),
|
||||
dek->algo, dek->algo == CIPHER_ALGO_IDEA? " (IDEA)":"");
|
||||
if(dek->algo==CIPHER_ALGO_IDEA)
|
||||
idea_cipher_warn(0);
|
||||
}
|
||||
dek->algo = 0;
|
||||
goto leave;
|
||||
}
|
||||
if( dek->keylen != gcry_cipher_get_algo_keylen (dek->algo) ) {
|
||||
rc = GPG_ERR_WRONG_SECKEY;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* copy the key to DEK and compare the checksum */
|
||||
csum = frame[nframe-2] << 8;
|
||||
csum |= frame[nframe-1];
|
||||
memcpy( dek->key, frame+n, dek->keylen );
|
||||
for( csum2=0, n=0; n < dek->keylen; n++ )
|
||||
csum2 += dek->key[n];
|
||||
if( csum != csum2 ) {
|
||||
rc = GPG_ERR_WRONG_SECKEY;
|
||||
goto leave;
|
||||
}
|
||||
if( DBG_CIPHER )
|
||||
log_printhex ("DEK is:", dek->key, dek->keylen );
|
||||
/* check that the algo is in the preferences and whether it has expired */
|
||||
{
|
||||
PKT_public_key *pk = NULL;
|
||||
KBNODE pkb = get_pubkeyblock (keyid);
|
||||
|
||||
if( !pkb ) {
|
||||
rc = -1;
|
||||
log_error("oops: public key not found for preference check\n");
|
||||
}
|
||||
else if( pkb->pkt->pkt.public_key->selfsigversion > 3
|
||||
&& dek->algo != CIPHER_ALGO_3DES
|
||||
&& !is_algo_in_prefs( pkb, PREFTYPE_SYM, dek->algo ) ) {
|
||||
/* Don't print a note while we are not on verbose mode,
|
||||
* the cipher is blowfish and the preferences have twofish
|
||||
* listed */
|
||||
if( opt.verbose || dek->algo != CIPHER_ALGO_BLOWFISH
|
||||
|| !is_algo_in_prefs( pkb, PREFTYPE_SYM, CIPHER_ALGO_TWOFISH))
|
||||
log_info(_(
|
||||
"NOTE: cipher algorithm %d not found in preferences\n"),
|
||||
dek->algo );
|
||||
}
|
||||
|
||||
if (!rc) {
|
||||
KBNODE k;
|
||||
|
||||
for (k=pkb; k; k = k->next) {
|
||||
if (k->pkt->pkttype == PKT_PUBLIC_KEY
|
||||
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY){
|
||||
u32 aki[2];
|
||||
keyid_from_pk(k->pkt->pkt.public_key, aki);
|
||||
|
||||
if (aki[0]==keyid[0] && aki[1]==keyid[1]) {
|
||||
pk = k->pkt->pkt.public_key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!pk)
|
||||
BUG ();
|
||||
if ( pk->expiredate && pk->expiredate <= make_timestamp() ) {
|
||||
log_info(_("NOTE: secret key %08lX expired at %s\n"),
|
||||
(ulong)keyid[1], asctimestamp( pk->expiredate) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( pk && pk->is_revoked ) {
|
||||
log_info( _("NOTE: key has been revoked") );
|
||||
putc( '\n', log_get_stream() );
|
||||
show_revocation_reason( pk, 1 );
|
||||
}
|
||||
|
||||
release_kbnode (pkb);
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
|
||||
leave:
|
||||
gcry_mpi_release (plain_dek);
|
||||
xfree (frame);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
@ -297,11 +297,14 @@ check_secret_key( PKT_secret_key *sk, int n )
|
||||
/****************
|
||||
* check whether the secret key is protected.
|
||||
* Returns: 0 not protected, -1 on error or the protection algorithm
|
||||
* -2 indicates a card stub.
|
||||
*/
|
||||
int
|
||||
is_secret_key_protected( PKT_secret_key *sk )
|
||||
{
|
||||
return sk->is_protected? sk->protect.algo : 0;
|
||||
return sk->is_protected?
|
||||
sk->protect.s2k.mode == 1002? -2
|
||||
: sk->protect.algo : 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include "mpi.h"
|
||||
#include "main.h"
|
||||
#include "i18n.h"
|
||||
|
||||
#include "options.h"
|
||||
|
||||
/****************
|
||||
* Make a session key and put it into DEK
|
||||
@ -143,7 +143,11 @@ encode_session_key (DEK *dek, unsigned int nbits)
|
||||
memcpy( frame+n, dek->key, dek->keylen ); n += dek->keylen;
|
||||
frame[n++] = csum >>8;
|
||||
frame[n++] = csum;
|
||||
assert( n == nframe );
|
||||
assert (n == nframe);
|
||||
|
||||
if (DBG_CIPHER)
|
||||
log_printhex ("encoded session key:", frame, nframe );
|
||||
|
||||
if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, &nframe))
|
||||
BUG();
|
||||
xfree (frame);
|
||||
|
@ -41,6 +41,8 @@
|
||||
#include "status.h"
|
||||
#include "i18n.h"
|
||||
#include "pkglue.h"
|
||||
#include "call-agent.h"
|
||||
|
||||
|
||||
#ifdef HAVE_DOSISH_SYSTEM
|
||||
#define LF "\r\n"
|
||||
|
Loading…
x
Reference in New Issue
Block a user