aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--NEWS10
-rw-r--r--cipher/ChangeLog14
-rw-r--r--cipher/blowfish.c12
-rw-r--r--cipher/cast5.c13
-rw-r--r--cipher/des.c13
-rw-r--r--cipher/md5.c8
-rw-r--r--cipher/rmd160.c8
-rw-r--r--cipher/sha1.c4
-rw-r--r--cipher/tiger.c8
-rw-r--r--cipher/twofish.c27
-rw-r--r--doc/DETAILS9
-rw-r--r--doc/FAQ27
-rw-r--r--doc/OpenPGP9
-rw-r--r--doc/gpg.sgml10
-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
-rw-r--r--mpi/ChangeLog2
25 files changed, 250 insertions, 66 deletions
diff --git a/ChangeLog b/ChangeLog
index cede51453..bc56e4dfa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,6 @@
Thu Jan 13 19:31:58 CET 2000 Werner Koch <[email protected]>
- * configure.in: Do set development version when the version has
+ * configure.in: Do not set development version when the version has
a dash in it. Suggested by Dave Dykstra.
Thu Dec 16 10:07:58 CET 1999 Werner Koch <[email protected]>
diff --git a/NEWS b/NEWS
index caa3d2af8..2cdcf6af7 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,5 @@
+Noteworthy changes in the current test release
+----------------------------------------------
* Some fixes for the W32 version
@@ -7,6 +9,14 @@
* New encryption keys are generated in way which allows a much
faster decryption.
+ * New command --export-secret-subkeys which outputs the
+ the _primary_ key with is's secret parts deleted. This is
+ useful for automated decryption/signature creation as it
+ allows to keep the real secret primary key offline and
+ thereby protecting the key certificates and allowing to
+ create revocations for the subkeys. See the FAQ for a
+ procedure to install such secret keys.
+
Noteworthy changes in version 1.0.1 (1999-12-16)
-----------------------------------
diff --git a/cipher/ChangeLog b/cipher/ChangeLog
index 2a53aff1a..6804a7b19 100644
--- a/cipher/ChangeLog
+++ b/cipher/ChangeLog
@@ -1,3 +1,15 @@
+Fri Jan 14 18:32:01 CET 2000 Werner Koch <[email protected]>
+
+ * rmd160.c (rmd160_get_info): Moved casting to the left side due to a
+ problem with UTS4.3. Suggested by Dave Dykstra.
+ * sha1.c (sha1_get_info): Ditto.
+ * tiger.c (tiger_get_info): Ditto.
+ * md5.c (md5_get_info): Ditto
+ * des.c (des_get_info): Ditto.
+ * blowfish.c (blowfish_get_info): Ditto.
+ * cast5.c (cast5_get_info): Ditto.
+ * twofish.c (twofish_get_info): Ditto.
+
Thu Jan 13 19:31:58 CET 2000 Werner Koch <[email protected]>
* elgamal.c (wiener_map): New.
@@ -5,7 +17,7 @@ Thu Jan 13 19:31:58 CET 2000 Werner Koch <[email protected]>
(generate): Calculate the qbits using the wiener map and
choose an x at a size comparable to the one choosen in gen_k
- * random.c (read_pool): Print a more friendly erro message in
+ * random.c (read_pool): Print a more friendly error message in
cases when too much random is requested in one call.
* Makefile.am (tiger): Replaced -O1 by -O. Suggested by Alec Habig.
diff --git a/cipher/blowfish.c b/cipher/blowfish.c
index 5a829d413..0cb5a861f 100644
--- a/cipher/blowfish.c
+++ b/cipher/blowfish.c
@@ -43,9 +43,6 @@
#define CIPHER_ALGO_BLOWFISH 4 /* blowfish 128 bit key */
-#define FNCCAST_SETKEY(f) (int(*)(void*, byte*, unsigned))(f)
-#define FNCCAST_CRYPT(f) (void(*)(void*, byte*, byte*))(f)
-
#define BLOWFISH_BLOCKSIZE 8
#define BLOWFISH_ROUNDS 16
@@ -584,9 +581,12 @@ blowfish_get_info( int algo, size_t *keylen,
*keylen = 128;
*blocksize = BLOWFISH_BLOCKSIZE;
*contextsize = sizeof(BLOWFISH_context);
- *r_setkey = FNCCAST_SETKEY(bf_setkey);
- *r_encrypt= FNCCAST_CRYPT(encrypt_block);
- *r_decrypt= FNCCAST_CRYPT(decrypt_block);
+ *(int (**)(BLOWFISH_context*, byte*, unsigned))r_setkey
+ = bf_setkey;
+ *(void (**)(BLOWFISH_context*, byte*, byte*))r_encrypt
+ = encrypt_block;
+ *(void (**)(BLOWFISH_context*, byte*, byte*))r_decrypt
+ = decrypt_block;
if( algo == CIPHER_ALGO_BLOWFISH )
return "BLOWFISH";
diff --git a/cipher/cast5.c b/cipher/cast5.c
index 0e602bd2e..329f00ff7 100644
--- a/cipher/cast5.c
+++ b/cipher/cast5.c
@@ -46,9 +46,6 @@
#define CIPHER_ALGO_CAST5 3
-#define FNCCAST_SETKEY(f) (int(*)(void*, byte*, unsigned))(f)
-#define FNCCAST_CRYPT(f) (void(*)(void*, byte*, byte*))(f)
-
#define CAST5_BLOCKSIZE 8
typedef struct {
@@ -610,9 +607,13 @@ cast5_get_info( int algo, size_t *keylen,
*keylen = 128;
*blocksize = CAST5_BLOCKSIZE;
*contextsize = sizeof(CAST5_context);
- *r_setkey = FNCCAST_SETKEY(cast_setkey);
- *r_encrypt= FNCCAST_CRYPT(encrypt_block);
- *r_decrypt= FNCCAST_CRYPT(decrypt_block);
+ *(int (**)(CAST5_context*, byte*, unsigned))r_setkey
+ = cast_setkey;
+ *(void (**)(CAST5_context*, byte*, byte*))r_encrypt
+ = encrypt_block;
+ *(void (**)(CAST5_context*, byte*, byte*))r_decrypt
+ = decrypt_block;
+
if( algo == CIPHER_ALGO_CAST5 )
return "CAST5";
diff --git a/cipher/des.c b/cipher/des.c
index c2ca3f848..847a3473e 100644
--- a/cipher/des.c
+++ b/cipher/des.c
@@ -147,9 +147,6 @@ working_memcmp( const char *a, const char *b, size_t n )
#endif
-/* Macros used by the info function. */
-#define FNCCAST_SETKEY(f) ((int(*)(void*, byte*, unsigned))(f))
-#define FNCCAST_CRYPT(f) ((void(*)(void*, byte*, byte*))(f))
/*
@@ -996,14 +993,16 @@ des_get_info( int algo, size_t *keylen,
}
}
-
if( algo == CIPHER_ALGO_3DES ) {
*keylen = 192;
*blocksize = 8;
*contextsize = sizeof(struct _tripledes_ctx);
- *r_setkey = FNCCAST_SETKEY(do_tripledes_setkey);
- *r_encrypt= FNCCAST_CRYPT(do_tripledes_encrypt);
- *r_decrypt= FNCCAST_CRYPT(do_tripledes_decrypt);
+ *(int (**)(struct _tripledes_ctx*, byte*, unsigned))r_setkey
+ = do_tripledes_setkey;
+ *(void (**)(struct _tripledes_ctx*, byte*, byte*))r_encrypt
+ = do_tripledes_encrypt;
+ *(void (**)(struct _tripledes_ctx*, byte*, byte*))r_decrypt
+ = do_tripledes_decrypt;
return "3DES";
}
return NULL;
diff --git a/cipher/md5.c b/cipher/md5.c
index bb930d042..eb09d261c 100644
--- a/cipher/md5.c
+++ b/cipher/md5.c
@@ -344,10 +344,10 @@ md5_get_info( int algo, size_t *contextsize,
*r_asnoid = asn;
*r_asnlen = DIM(asn);
*r_mdlen = 16;
- *r_init = (void (*)(void *))md5_init;
- *r_write = (void (*)(void *, byte*, size_t))md5_write;
- *r_final = (void (*)(void *))md5_final;
- *r_read = (byte *(*)(void *))md5_read;
+ *(void (**)(MD5_CONTEXT *))r_init = md5_init;
+ *(void (**)(MD5_CONTEXT *, byte*, size_t))r_write = md5_write;
+ *(void (**)(MD5_CONTEXT *))r_final = md5_final;
+ *(byte *(**)(MD5_CONTEXT *))r_read = md5_read;
return "MD5";
}
diff --git a/cipher/rmd160.c b/cipher/rmd160.c
index ecd65b35d..fba910d7e 100644
--- a/cipher/rmd160.c
+++ b/cipher/rmd160.c
@@ -562,10 +562,10 @@ rmd160_get_info( int algo, size_t *contextsize,
*r_asnoid = asn;
*r_asnlen = DIM(asn);
*r_mdlen = 20;
- *r_init = (void (*)(void *))rmd160_init;
- *r_write = (void (*)(void *, byte*, size_t))rmd160_write;
- *r_final = (void (*)(void *))rmd160_final;
- *r_read = (byte *(*)(void *))rmd160_read;
+ *(void (**)(RMD160_CONTEXT *))r_init = rmd160_init;
+ *(void (**)(RMD160_CONTEXT *, byte*, size_t))r_write = rmd160_write;
+ *(void (**)(RMD160_CONTEXT *))r_final = rmd160_final;
+ *(byte *(**)(RMD160_CONTEXT *))r_read = rmd160_read;
return "RIPEMD160";
}
diff --git a/cipher/sha1.c b/cipher/sha1.c
index 40ad62f1f..e47cc5e60 100644
--- a/cipher/sha1.c
+++ b/cipher/sha1.c
@@ -341,6 +341,10 @@ sha1_get_info( int algo, size_t *contextsize,
*r_write = (void (*)(void *, byte*, size_t))sha1_write;
*r_final = (void (*)(void *))sha1_final;
*r_read = (byte *(*)(void *))sha1_read;
+ *(void (**)(SHA1_CONTEXT *))r_init = sha1_init;
+ *(void (**)(SHA1_CONTEXT *, byte*, size_t))r_write = sha1_write;
+ *(void (**)(SHA1_CONTEXT *))r_final = sha1_final;
+ *(byte *(**)(SHA1_CONTEXT *))r_read = sha1_read;
return "SHA1";
}
diff --git a/cipher/tiger.c b/cipher/tiger.c
index 0765f0bbd..e4a7c4daa 100644
--- a/cipher/tiger.c
+++ b/cipher/tiger.c
@@ -899,10 +899,10 @@ tiger_get_info( int algo, size_t *contextsize,
*r_asnoid = asn;
*r_asnlen = DIM(asn);
*r_mdlen = 24;
- *r_init = (void (*)(void *))tiger_init;
- *r_write = (void (*)(void *, byte*, size_t))tiger_write;
- *r_final = (void (*)(void *))tiger_final;
- *r_read = (byte *(*)(void *))tiger_read;
+ *(void (**)(TIGER_CONTEXT *))r_init = tiger_init;
+ *(void (**)(TIGER_CONTEXT *, byte*, size_t))r_write = tiger_write;
+ *(void (**)(TIGER_CONTEXT *))r_final = tiger_final;
+ *(byte *(**)(TIGER_CONTEXT *))r_read = tiger_read;
return "TIGER";
}
diff --git a/cipher/twofish.c b/cipher/twofish.c
index 182f18c49..157a13735 100644
--- a/cipher/twofish.c
+++ b/cipher/twofish.c
@@ -35,10 +35,6 @@
/* Prototype for the self-test function. */
static const char *selftest(void);
-/* Macros used by the info function. */
-#define FNCCAST_SETKEY(f) ((int(*)(void*, byte*, unsigned))(f))
-#define FNCCAST_CRYPT(f) ((void(*)(void*, byte*, byte*))(f))
-
/* Structure for an expanded Twofish key. s contains the key-dependent
* S-boxes composed with the MDS matrix; w contains the eight "whitening"
* subkeys, K[0] through K[7]. k holds the remaining, "round" subkeys. Note
@@ -991,16 +987,19 @@ twofish_get_info (int algo, size_t *keylen,
*keylen = algo==10? 256 : 128;
*blocksize = 16;
*contextsize = sizeof (TWOFISH_context);
- *r_setkey = FNCCAST_SETKEY (twofish_setkey);
- *r_encrypt= FNCCAST_CRYPT (twofish_encrypt);
- *r_decrypt= FNCCAST_CRYPT (twofish_decrypt);
-
- if( algo == 10 )
- return "TWOFISH";
- if (algo == 102) /* This algorithm number is assigned for
- * experiments, so we can use it */
- return "TWOFISH128";
- return NULL;
+ *(int (**)(const TWOFISH_context*, byte*, unsigned))r_setkey
+ = twofish_setkey;
+ *(void (**)(const TWOFISH_context*, byte*, byte*))r_encrypt
+ = twofish_encrypt;
+ *(void (**)(const TWOFISH_context*, byte*, byte*))r_decrypt
+ = twofish_decrypt;
+
+ if( algo == 10 )
+ return "TWOFISH";
+ if (algo == 102) /* This algorithm number is assigned for
+ * experiments, so we can use it */
+ return "TWOFISH128";
+ return NULL;
}
diff --git a/doc/DETAILS b/doc/DETAILS
index 3007ab3de..0ab83ecdf 100644
--- a/doc/DETAILS
+++ b/doc/DETAILS
@@ -494,6 +494,15 @@ There is one enhancement used with the old style packet headers:
+ that this is the last packet.
+GNU extensions to the S2K algorithm
+===================================
+S2K mode 101 is used to identify these extensions.
+After the hash algorithm the 3 bytes "GNU" are used to make
+clear that these are extensions for GNU, the next bytes gives the
+GNU protection mode - 1000. Defined modes are:
+ 1001 - do not store the secret part at all
+
+
Usage of gdbm files for keyrings
================================
The key to store the keyblock is it's fingerprint, other records
diff --git a/doc/FAQ b/doc/FAQ
index 4501b8eb7..1f1312d54 100644
--- a/doc/FAQ
+++ b/doc/FAQ
@@ -372,3 +372,30 @@
message and encrypt it again without this option. The option will
be removed in 1.1, so better re-encrypt your message now.
+ Q: How can I used GnuPG in an automated environment?
+ A: You should use the option --batch and don't use passphrases as
+ there is usually no way to store it more secure than the secret
+ keyring itself. The suggested way to create the keys for the
+ automated envirionment ist:
+ On a secure machine:
+ 1. If you want to do automatic signing, create a signing subkey
+ for your key (edit menu, choose "addkey" and the DSA).
+ 2. Make sure that you use a passphrase (Needed by the current
+ implementation)
+ 3. gpg --export-secret-subkeys --no-comment foo >secring.auto
+ 4. Copy secring.auto and the public keyring to a test directory.
+ 5. Cd to this diectory
+ 6. gpg --homedir . --edit foo
+ and use "passwd" to remove the passphrase from the subkeys.
+ You may also want to remove all unused subkeys.
+ 7. copy secring.auto to a floppy and carry it to the
+ target box
+ On the target machine:
+ 8. Install secring.auto as secret keyring.
+ 9. Now you can start your new service. It is a good idea to
+ install some intrusion detection system so that you hopefully
+ get a notice of an successful intrusion, so that you in turn can
+ revoke all the subkeys installed on that machine and install new
+ subkeys.
+
+
diff --git a/doc/OpenPGP b/doc/OpenPGP
index c73eee4f8..ba44d87fb 100644
--- a/doc/OpenPGP
+++ b/doc/OpenPGP
@@ -33,6 +33,15 @@
which can be considered to be in compliance with RFC1991; this
format is only created if a special option is active.
+ GnuPG uses a S2K mode of 101 for GNU extensions to the secret key
+ protection algorithms. This number is not defined in OpenPGP, but
+ given the fact that this number is in a range which used at many
+ other places in OpenPGP for private/experimenat algorithm identifiers,
+ this should be not a so bad choice. The 3 bytes "GNU" are used
+ to identify this as a GNU extension - see the file DETAILS for a
+ definition of the used data formats.
+
+
Some Notes on OpenPGP / PGP Compatibility:
==========================================
diff --git a/doc/gpg.sgml b/doc/gpg.sgml
index 76f0415bf..ec160679b 100644
--- a/doc/gpg.sgml
+++ b/doc/gpg.sgml
@@ -27,7 +27,7 @@
-->
-<!DOCTYPE RefEntry PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [
+<!DOCTYPE refentry PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [
<!entity ParmDir "<parameter>directory</parameter>">
<!entity ParmFile "<parameter>file</parameter>">
<!entity OptParmFile "<optional>&ParmFile;</optional>">
@@ -157,7 +157,7 @@ and the remaining files are the signed stuff.
</para></listitem></varlistentry>
<varlistentry>
-<term>--verify-files <optional><optional><parameter/files/</optional>
+<term>--verify-files <optional><parameter/files/</optional></term>
<listitem><para>
This is a special version of the --verify command which does not work with
detached signatures. The command expects the files to bee verified either
@@ -431,9 +431,14 @@ are not compatible to OpenPGP.
<varlistentry>
<term>--export-secret-keys &OptParmNames;</term>
+<term>--export-secret-subkeys &OptParmNames;</term>
<listitem><para>
Same as --export, but does export the secret keys.
This is normally not very useful and a security risk.
+the second form of the command has the special property to
+render the secret part of the primary key useless; this is
+a GNU extension to OpenPGP and other implementations can
+not be expected to successful import such a key.
</para></listitem></varlistentry>
@@ -1418,6 +1423,7 @@ constructed by cutting off the extension (".asc" or ".sig") of
<term>GNUPGHOME</term>
<listitem><para>If set directory used instead of "~/.gnupg".</para></listitem>
</varlistentry>
+<varlistentry>
<term>http_proxy</term>
<listitem><para>Only honored when the option --honor-http-proxy is set.</para></listitem>
</varlistentry>
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 ) ) {
diff --git a/mpi/ChangeLog b/mpi/ChangeLog
index ee1cd06fe..7ef20de40 100644
--- a/mpi/ChangeLog
+++ b/mpi/ChangeLog
@@ -5,7 +5,7 @@ Thu Jan 13 19:31:58 CET 2000 Werner Koch <[email protected]>
(mpihelp_mul_karatsuba_case): New.
(mpihelp_mul): Splitted to make use of the new functions.
* mpi-pow.c (mpi_powm): Make use of the new splitted function
- to avoid multiple allocation of temorary memory during the
+ to avoid multiple allocation of temporary memory during the
karatsuba operations.
* mpi_mpow.c: Removed the unused Barrett code.