aboutsummaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
Diffstat (limited to 'g10')
-rw-r--r--g10/ChangeLog11
-rw-r--r--g10/build-packet.c19
-rw-r--r--g10/export.c31
-rw-r--r--g10/g10.c11
-rw-r--r--g10/keyedit.c26
-rw-r--r--g10/main.h1
-rw-r--r--g10/packet.h2
-rw-r--r--g10/parse-packet.c35
-rw-r--r--g10/seckey-cert.c4
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;
diff --git a/g10/g10.c b/g10/g10.c
index c86e3204c..ff50b7aeb 100644
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -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 ) ) {