diff options
Diffstat (limited to 'g10')
-rw-r--r-- | g10/ChangeLog | 11 | ||||
-rw-r--r-- | g10/build-packet.c | 19 | ||||
-rw-r--r-- | g10/export.c | 31 | ||||
-rw-r--r-- | g10/g10.c | 11 | ||||
-rw-r--r-- | g10/keyedit.c | 26 | ||||
-rw-r--r-- | g10/main.h | 1 | ||||
-rw-r--r-- | g10/packet.h | 2 | ||||
-rw-r--r-- | g10/parse-packet.c | 35 | ||||
-rw-r--r-- | g10/seckey-cert.c | 4 |
9 files changed, 124 insertions, 16 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog index 05dd0b132..a428b72d5 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,14 @@ +Fri Jan 14 18:32:01 CET 2000 Werner Koch <[email protected]> + + * packet.h (STRING2KEY): Changed mode from byte to int. + * parse-packet.c (parse_key): Add the special GNU protection stuff + * build-packet.c (so_secret_key): Ditto. + * seckey-cert.c (do_check): Ditto. + * keyedit.c (change_passphrase): Ditto. + * export.c (export_secsubkeys): New. + (do_export_stream): Hack to export the primary key using mode 1001. + * g10.c: New command --export-secret-subkeys + Thu Jan 13 19:31:58 CET 2000 Werner Koch <[email protected]> * armor.c (is_armored): Check for 1-pass-sig packets. Reported by diff --git a/g10/build-packet.c b/g10/build-packet.c index 0a3bb74ee..3745d51c1 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -371,19 +371,30 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk ) else { iobuf_put(a, 0xff ); iobuf_put(a, sk->protect.algo ); - iobuf_put(a, sk->protect.s2k.mode ); - iobuf_put(a, sk->protect.s2k.hash_algo ); + if( sk->protect.s2k.mode >= 1000 ) { + iobuf_put(a, 101 ); + iobuf_put(a, sk->protect.s2k.hash_algo ); + iobuf_write(a, "GNU", 3 ); + iobuf_put(a, sk->protect.s2k.mode - 1000 ); + } + else { + iobuf_put(a, sk->protect.s2k.mode ); + iobuf_put(a, sk->protect.s2k.hash_algo ); + } if( sk->protect.s2k.mode == 1 || sk->protect.s2k.mode == 3 ) iobuf_write(a, sk->protect.s2k.salt, 8 ); if( sk->protect.s2k.mode == 3 ) iobuf_put(a, sk->protect.s2k.count ); - iobuf_write(a, sk->protect.iv, sk->protect.ivlen ); + if( sk->protect.s2k.mode != 1001 ) + iobuf_write(a, sk->protect.iv, sk->protect.ivlen ); } } else iobuf_put(a, 0 ); - if( sk->is_protected && sk->version >= 4 ) { + if( sk->protect.s2k.mode == 1001 ) + ; + else if( sk->is_protected && sk->version >= 4 ) { byte *p; assert( mpi_is_opaque( sk->skey[npkey] ) ); p = mpi_get_opaque( sk->skey[npkey], &i ); diff --git a/g10/export.c b/g10/export.c index 911a71599..106caa7d7 100644 --- a/g10/export.c +++ b/g10/export.c @@ -71,6 +71,12 @@ export_seckeys( STRLIST users ) return do_export( users, 1, 0 ); } +int +export_secsubkeys( STRLIST users ) +{ + return do_export( users, 2, 0 ); +} + static int do_export( STRLIST users, int secret, int onlyrfc ) { @@ -168,6 +174,16 @@ do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any ) } } + /* we can't apply GNU mode 1001 on an unprotected key */ + if( secret == 2 + && (node = find_kbnode( keyblock, PKT_SECRET_KEY )) + && !node->pkt->pkt.secret_key->is_protected ) + { + log_info(_("key %08lX: not protected - skipped\n"), + (ulong)keyid_from_sk( node->pkt->pkt.secret_key, NULL) ); + continue; + } + /* and write it */ for( kbctx=NULL; (node = walk_kbnode( keyblock, &kbctx, 0 )); ) { /* don't export any comment packets but those in the @@ -183,7 +199,20 @@ do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any ) continue; /* not exportable */ } - if( (rc = build_packet( out, node->pkt )) ) { + if( secret == 2 && node->pkt->pkttype == PKT_SECRET_KEY ) { + /* we don't want to export the secret parts of the + * primary key, this is doen by using GNU protection mode 1001 + */ + int save_mode = node->pkt->pkt.secret_key->protect.s2k.mode; + node->pkt->pkt.secret_key->protect.s2k.mode = 1001; + rc = build_packet( out, node->pkt ); + node->pkt->pkt.secret_key->protect.s2k.mode = save_mode; + } + else { + rc = build_packet( out, node->pkt ); + } + + if( rc ) { log_error("build_packet(%d) failed: %s\n", node->pkt->pkttype, g10_errstr(rc) ); rc = G10ERR_WRITE_FILE; @@ -88,6 +88,7 @@ enum cmd_and_opt_values { aNull = 0, aExport, aExportAll, aExportSecret, + aExportSecretSub, aCheckKeys, aGenRevoke, aPrimegen, @@ -217,6 +218,7 @@ static ARGPARSE_OPTS opts[] = { { aRecvKeys, "recv-keys" , 256, N_("import keys from a key server") }, { aExportAll, "export-all" , 256, "@" }, { aExportSecret, "export-secret-keys" , 256, "@" }, + { aExportSecretSub, "export-secret-subkeys" , 256, "@" }, { aImport, "import", 256 , N_("import/merge keys")}, { aFastImport, "fast-import", 256 , "@"}, { aListPackets, "list-packets",256,N_("list only the sequence of packets")}, @@ -697,6 +699,7 @@ main( int argc, char **argv ) case aListKeys: set_cmd( &cmd, aListKeys); break; case aListSigs: set_cmd( &cmd, aListSigs); break; case aExportSecret: set_cmd( &cmd, aExportSecret); break; + case aExportSecretSub: set_cmd( &cmd, aExportSecretSub); break; case aDeleteSecretKey: set_cmd( &cmd, aDeleteSecretKey); greeting=1; break; case aDeleteKey: set_cmd( &cmd, aDeleteKey); greeting=1; break; @@ -1271,6 +1274,14 @@ main( int argc, char **argv ) free_strlist(sl); break; + case aExportSecretSub: + sl = NULL; + for( ; argc; argc--, argv++ ) + add_to_strlist2( &sl, *argv, utf8_strings ); + export_secsubkeys( sl ); + free_strlist(sl); + break; + case aGenRevoke: if( argc != 1 ) wrong_args("--gen-revoke user-id"); diff --git a/g10/keyedit.c b/g10/keyedit.c index e5157f0ca..bed757922 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -407,6 +407,7 @@ change_passphrase( KBNODE keyblock ) KBNODE node; PKT_secret_key *sk; char *passphrase = NULL; + int no_primary_secrets = 0; node = find_kbnode( keyblock, PKT_SECRET_KEY ); if( !node ) { @@ -423,10 +424,16 @@ change_passphrase( KBNODE keyblock ) tty_printf(_("This key is not protected.\n")); break; default: - tty_printf(_("Key is protected.\n")); - rc = check_secret_key( sk, 0 ); - if( !rc ) - passphrase = get_last_passphrase(); + if( sk->protect.s2k.mode == 1001 ) { + tty_printf(_("Secret parts of primary key are not available.\n")); + no_primary_secrets = 1; + } + else { + tty_printf(_("Key is protected.\n")); + rc = check_secret_key( sk, 0 ); + if( !rc ) + passphrase = get_last_passphrase(); + } break; } @@ -436,6 +443,8 @@ change_passphrase( KBNODE keyblock ) 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(); } } @@ -465,9 +474,12 @@ change_passphrase( KBNODE keyblock ) break; } else { /* okay */ - sk->protect.algo = dek->algo; - sk->protect.s2k = *s2k; - rc = protect_secret_key( sk, dek ); + rc = 0; + if( !no_primary_secrets ) { + sk->protect.algo = dek->algo; + sk->protect.s2k = *s2k; + rc = protect_secret_key( sk, dek ); + } for(node=keyblock; !rc && node; node = node->next ) { if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { PKT_secret_key *subsk = node->pkt->pkt.secret_key; diff --git a/g10/main.h b/g10/main.h index 4be23aecd..6188cefc9 100644 --- a/g10/main.h +++ b/g10/main.h @@ -124,6 +124,7 @@ int collapse_uids( KBNODE *keyblock ); int export_pubkeys( STRLIST users, int onlyrfc ); int export_pubkeys_stream( IOBUF out, STRLIST users, int onlyrfc ); int export_seckeys( STRLIST users ); +int export_secsubkeys( STRLIST users ); /* dearmor.c --*/ int dearmor_file( const char *fname ); diff --git a/g10/packet.h b/g10/packet.h index 302b99289..3a05f0d52 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -54,7 +54,7 @@ typedef enum { typedef struct packet_struct PACKET; typedef struct { - byte mode; + int mode; byte hash_algo; byte salt[8]; u32 count; diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 03e56708c..93dc094db 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -1324,6 +1324,24 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, sk->protect.algo = iobuf_get_noeof(inp); pktlen--; sk->protect.s2k.mode = iobuf_get_noeof(inp); pktlen--; sk->protect.s2k.hash_algo = iobuf_get_noeof(inp); pktlen--; + /* check for the special GNU extension */ + if( is_v4 && sk->protect.s2k.mode == 101 ) { + for(i=0; i < 4 && pktlen; i++, pktlen-- ) + temp[i] = iobuf_get_noeof(inp); + if( i < 4 || memcmp( temp, "GNU", 3 ) ) { + if( list_mode ) + printf( "\tunknown S2K %d\n", + sk->protect.s2k.mode ); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + /* here we know that it is a gnu extension + * What follows is the GNU protection mode: + * All values have special meanings + * and they are mapped in the mode with a base of 1000. + */ + sk->protect.s2k.mode = 1000 + temp[3]; + } switch( sk->protect.s2k.mode ) { case 1: case 3: @@ -1339,10 +1357,13 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, break; case 3: if( list_mode ) printf( "\titer+salt S2K" ); break; + case 1001: if( list_mode ) printf( "\tgnu-dummy S2K" ); + break; default: if( list_mode ) - printf( "\tunknown S2K %d\n", - sk->protect.s2k.mode ); + printf( "\tunknown %sS2K %d\n", + sk->protect.s2k.mode < 1000? "":"GNU ", + sk->protect.s2k.mode ); rc = G10ERR_INVALID_PACKET; goto leave; } @@ -1395,6 +1416,9 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, default: sk->protect.ivlen = 8; } + if( sk->protect.s2k.mode == 1001 ) + sk->protect.ivlen = 0; + if( pktlen < sk->protect.ivlen ) { rc = G10ERR_INVALID_PACKET; goto leave; @@ -1415,7 +1439,12 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, * If the user is so careless, not to protect his secret key, * we can assume, that he operates an open system :=(. * So we put the key into secure memory when we unprotect it. */ - if( is_v4 && sk->is_protected ) { + if( sk->protect.s2k.mode == 1001 ) { + /* better set some dummy stuff here */ + sk->skey[npkey] = mpi_set_opaque(NULL, m_strdup("dummydata"), 10); + pktlen = 0; + } + else if( is_v4 && sk->is_protected ) { /* ugly; the length is encrypted too, so we read all * stuff up to the end of the packet into the first * skey element */ diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index a8fae04d6..91511c68f 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -49,6 +49,10 @@ do_check( PKT_secret_key *sk ) CIPHER_HANDLE cipher_hd=NULL; PKT_secret_key *save_sk; + if( sk->protect.s2k.mode == 1001 ) { + log_info(_("secret key parts are not available\n")); + return G10ERR_GENERAL; + } if( sk->protect.algo == CIPHER_ALGO_NONE ) BUG(); if( check_cipher_algo( sk->protect.algo ) ) { |