From d96f816f89fe7aed729ff77fc48af5722f10eabb Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 27 Jan 2005 11:48:33 +0000 Subject: [PATCH] * keygen.c (generate_subkeypair): Detect primary key on-card and ask for the passphrase. Return an error if the primary key is a plain stub. * keyedit.c (change_passphrase): Don't ever change any stub key. Print a note if a key consists of only stub keys. Reported by Dany Nativel. These are bugs #401 and #402. --- g10/ChangeLog | 10 ++++++++++ g10/keyedit.c | 51 ++++++++++++++++++++++++++++++++++++++++++--------- g10/keygen.c | 32 +++++++++++++++++++++++--------- 3 files changed, 75 insertions(+), 18 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 96dcd0c06..74adadb58 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,13 @@ +2005-01-27 Werner Koch + + * keygen.c (generate_subkeypair): Detect primary key on-card and + ask for the passphrase. Return an error if the primary key is a + plain stub. + + * keyedit.c (change_passphrase): Don't ever change any stub key. + Print a note if a key consists of only stub keys. Reported by + Dany Nativel. These are bugs #401 and #402. + 2005-01-26 Werner Koch * ccid-driver.c (parse_ccid_descriptor): Need the CSM workaround diff --git a/g10/keyedit.c b/g10/keyedit.c index 39a5a6529..84fc6d4cc 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -1069,6 +1069,7 @@ change_passphrase( KBNODE keyblock ) PKT_secret_key *sk; char *passphrase = NULL; int no_primary_secrets = 0; + int any; node = find_kbnode( keyblock, PKT_SECRET_KEY ); if( !node ) { @@ -1077,6 +1078,25 @@ change_passphrase( KBNODE keyblock ) } sk = node->pkt->pkt.secret_key; + for (any = 0, node=keyblock; node; node = node->next) { + if (node->pkt->pkttype == PKT_SECRET_KEY + || node->pkt->pkttype == PKT_SECRET_SUBKEY) { + PKT_secret_key *tmpsk = node->pkt->pkt.secret_key; + if (!(tmpsk->is_protected + && (tmpsk->protect.s2k.mode == 1001 + || tmpsk->protect.s2k.mode == 1002))) { + any = 1; + break; + } + } + } + if (!any) { + tty_printf (_("Key has only stub or on-card key items - " + "no passphrase to change.\n")); + goto leave; + } + + /* See how to handle this key. */ switch( is_secret_key_protected( sk ) ) { case -1: rc = G10ERR_PUBKEY_ALGO; @@ -1089,6 +1109,10 @@ change_passphrase( KBNODE keyblock ) tty_printf(_("Secret parts of primary key are not available.\n")); no_primary_secrets = 1; } + else if( sk->protect.s2k.mode == 1002 ) { + tty_printf(_("Secret parts of primary key are store on-card.\n")); + no_primary_secrets = 1; + } else { tty_printf(_("Key is protected.\n")); rc = check_secret_key( sk, 0 ); @@ -1098,14 +1122,18 @@ change_passphrase( KBNODE keyblock ) break; } - /* unprotect all subkeys (use the supplied passphrase or ask)*/ + /* Unprotect all subkeys (use the supplied passphrase or ask)*/ for(node=keyblock; !rc && node; node = node->next ) { if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { PKT_secret_key *subsk = node->pkt->pkt.secret_key; - set_next_passphrase( passphrase ); - rc = check_secret_key( subsk, 0 ); - if( !rc && !passphrase ) - passphrase = get_last_passphrase(); + if ( !(subsk->is_protected + && (subsk->protect.s2k.mode == 1001 + || subsk->protect.s2k.mode == 1002))) { + set_next_passphrase( passphrase ); + rc = check_secret_key( subsk, 0 ); + if( !rc && !passphrase ) + passphrase = get_last_passphrase(); + } } } @@ -1149,13 +1177,18 @@ change_passphrase( KBNODE keyblock ) for(node=keyblock; !rc && node; node = node->next ) { if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { PKT_secret_key *subsk = node->pkt->pkt.secret_key; - subsk->protect.algo = dek->algo; - subsk->protect.s2k = *s2k; - rc = protect_secret_key( subsk, dek ); + if ( !(subsk->is_protected + && (subsk->protect.s2k.mode == 1001 + || subsk->protect.s2k.mode == 1002))) { + subsk->protect.algo = dek->algo; + subsk->protect.s2k = *s2k; + rc = protect_secret_key( subsk, dek ); + } } } if( rc ) - log_error("protect_secret_key failed: %s\n", g10_errstr(rc) ); + log_error("protect_secret_key failed: %s\n", + g10_errstr(rc) ); else changed++; break; diff --git a/g10/keygen.c b/g10/keygen.c index a20c48c1b..29f1fc6d2 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -1,6 +1,6 @@ /* keygen.c - generate a key pair * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, - * 2004 Free Software Foundation, Inc. + * 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -3002,6 +3002,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) DEK *dek = NULL; STRING2KEY *s2k = NULL; u32 cur_time; + int ask_pass = 0; /* break out the primary secret key */ node = find_kbnode( sec_keyblock, PKT_SECRET_KEY ); @@ -3032,20 +3033,31 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) goto leave; } - /* unprotect to get the passphrase */ + if (pri_sk->is_protected && pri_sk->protect.s2k.mode == 1001) { + tty_printf(_("Secret parts of primary key are not available.\n")); + rc = G10ERR_NO_SECKEY; + goto leave; + } + + + /* Unprotect to get the passphrase. */ switch( is_secret_key_protected( pri_sk ) ) { case -1: rc = G10ERR_PUBKEY_ALGO; break; case 0: - tty_printf("This key is not protected.\n"); + tty_printf(_("This key is not protected.\n")); break; + case -2: + tty_printf(_("Secret parts of primary key are store on-card.\n")); + ask_pass = 1; + break; default: - tty_printf("Key is protected.\n"); - rc = check_secret_key( pri_sk, 0 ); - if( !rc ) - passphrase = get_last_passphrase(); - break; + tty_printf(_("Key is protected.\n")); + rc = check_secret_key( pri_sk, 0 ); + if( !rc ) + passphrase = get_last_passphrase(); + break; } if( rc ) goto leave; @@ -3058,7 +3070,9 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) _("Really create? (y/N) "))) goto leave; - if( passphrase ) { + if (ask_pass) + dek = do_ask_passphrase (&s2k); + else if (passphrase) { s2k = m_alloc_secure( sizeof *s2k ); s2k->mode = opt.s2k_mode; s2k->hash_algo = S2K_DIGEST_ALGO;