diff options
author | Werner Koch <wk@gnupg.org> | 2003-07-03 20:08:16 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2003-07-03 20:08:16 +0200 |
commit | 1753a2f3b0ec8c1eda54d9de7b17fa62c43fef39 (patch) | |
tree | ec11dfed93129b924a14e921ea110ddcc7506d64 | |
parent | * app-openpgp.c (store_fpr): Fixed fingerprint calculation. (diff) | |
download | gnupg2-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/ChangeLog | 22 | ||||
-rw-r--r-- | g10/call-agent.c | 60 | ||||
-rw-r--r-- | g10/call-agent.h | 10 | ||||
-rw-r--r-- | g10/g10.c | 4 | ||||
-rw-r--r-- | g10/getkey.c | 2 | ||||
-rw-r--r-- | g10/keyedit.c | 2 | ||||
-rw-r--r-- | g10/keygen.c | 196 | ||||
-rw-r--r-- | g10/options.h | 1 | ||||
-rw-r--r-- | g10/pkglue.c | 26 | ||||
-rw-r--r-- | g10/pubkey-enc.c | 286 | ||||
-rw-r--r-- | g10/seckey-cert.c | 5 | ||||
-rw-r--r-- | g10/seskey.c | 8 | ||||
-rw-r--r-- | g10/sign.c | 2 |
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); @@ -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" |