* 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:
Werner Koch 2003-07-03 18:08:16 +00:00
parent 39046ea7ec
commit 1753a2f3b0
13 changed files with 428 additions and 208 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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 ());

View File

@ -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

View File

@ -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"));

View File

@ -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)
{

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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"