summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2003-07-03 20:08:16 +0200
committerWerner Koch <wk@gnupg.org>2003-07-03 20:08:16 +0200
commit1753a2f3b0ec8c1eda54d9de7b17fa62c43fef39 (patch)
treeec11dfed93129b924a14e921ea110ddcc7506d64
parent* app-openpgp.c (store_fpr): Fixed fingerprint calculation. (diff)
downloadgnupg2-1753a2f3b0ec8c1eda54d9de7b17fa62c43fef39.tar.xz
gnupg2-1753a2f3b0ec8c1eda54d9de7b17fa62c43fef39.zip
* 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.
-rw-r--r--g10/ChangeLog22
-rw-r--r--g10/call-agent.c60
-rw-r--r--g10/call-agent.h10
-rw-r--r--g10/g10.c4
-rw-r--r--g10/getkey.c2
-rw-r--r--g10/keyedit.c2
-rw-r--r--g10/keygen.c196
-rw-r--r--g10/options.h1
-rw-r--r--g10/pkglue.c26
-rw-r--r--g10/pubkey-enc.c286
-rw-r--r--g10/seckey-cert.c5
-rw-r--r--g10/seskey.c8
-rw-r--r--g10/sign.c2
13 files changed, 422 insertions, 202 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index bf394f211..681f4cd55 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -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
diff --git a/g10/call-agent.c b/g10/call-agent.c
index d38e4c0fc..ca4236538 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -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;
+}
+
diff --git a/g10/call-agent.h b/g10/call-agent.h
index 2169a5319..a6edecf47 100644
--- a/g10/call-agent.h
+++ b/g10/call-agent.h
@@ -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);
diff --git a/g10/g10.c b/g10/g10.c
index 6909e0404..d48dada5e 100644
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -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 ());
diff --git a/g10/getkey.c b/g10/getkey.c
index 79fcaf3e2..c13d96dfb 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -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
diff --git a/g10/keyedit.c b/g10/keyedit.c
index 11e2d870e..85f2b92e9 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -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"));
diff --git a/g10/keygen.c b/g10/keygen.c
index 5dab70ff1..bfa76d601 100644
--- a/g10/keygen.c
+++ b/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 = 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 = 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", 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)
{
diff --git a/g10/options.h b/g10/options.h
index a68dc52c4..85d83e572 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -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)
diff --git a/g10/pkglue.c b/g10/pkglue.c
index 3e378822c..7920a5223 100644
--- a/g10/pkglue.c
+++ b/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;
}
+
+
+
+
+
+
+
diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c
index b08394e4a..d052546e3 100644
--- a/g10/pubkey-enc.c
+++ b/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;
-
- /* 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 (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;
+
+ snbuf = serialno_and_fpr_from_sk (sk->protect.iv, sk->protect.ivlen, sk);
+
+ if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &indata, &indatalen,
+ enc->data[0]))
+ BUG();
+
+ rc = agent_scd_pkdecrypt (snbuf, indata, indatalen, &rbuf, &rbuflen);
+ xfree (snbuf);
+ xfree (indata);
+ if (rc)
+ goto leave;
+
+ frame = rbuf;
+ nframe = rbuflen;
+ card = 1;
}
- 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;
+ else
+ {
+ void *indata;
+
+ 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;
}
- if( dek->keylen != gcry_cipher_get_algo_keylen (dek->algo) ) {
- rc = GPG_ERR_WRONG_SECKEY;
- goto leave;
+
+
+ /* 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 */
}
- /* 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( 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);
}
- 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);
+ dek->algo = 0;
+ goto leave;
+ }
+ if( dek->keylen != gcry_cipher_get_algo_keylen (dek->algo) ) {
+ rc = GPG_ERR_WRONG_SECKEY;
+ goto leave;
+ }
- 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 );
- }
+ /* 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;
+ 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) );
- }
- }
+ 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 ( pk && pk->is_revoked ) {
- log_info( _("NOTE: key has been revoked") );
- putc( '\n', log_get_stream() );
- show_revocation_reason( pk, 1 );
+ 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) );
+ }
+ }
- release_kbnode (pkb);
- rc = 0;
+ 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;
+
+ leave:
+ gcry_mpi_release (plain_dek);
+ xfree (frame);
+ return rc;
}
diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c
index dff463c53..65be7a468 100644
--- a/g10/seckey-cert.c
+++ b/g10/seckey-cert.c
@@ -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;
}
diff --git a/g10/seskey.c b/g10/seskey.c
index ae22032a1..11ebe17aa 100644
--- a/g10/seskey.c
+++ b/g10/seskey.c
@@ -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);
diff --git a/g10/sign.c b/g10/sign.c
index d9ce074d4..fa1e07b87 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -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"