summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>1998-01-06 22:01:36 +0100
committerWerner Koch <wk@gnupg.org>1998-01-06 22:01:36 +0100
commit0d9ffec5efcafa9f6499a2c4e4e2784290faec2f (patch)
treed0fa2cef628b9f8c57753c5110ee2f6ad48cb66f
parentdistributed version 0.1.0 (diff)
downloadgnupg2-0d9ffec5efcafa9f6499a2c4e4e2784290faec2f.tar.xz
gnupg2-0d9ffec5efcafa9f6499a2c4e4e2784290faec2f.zip
Bug in blowfish behoben
-rw-r--r--cipher/blowfish.c167
-rw-r--r--cipher/md5.c6
-rw-r--r--cipher/rmd160.c223
-rw-r--r--cipher/sha1.c1
-rw-r--r--g10/build-packet.c14
-rw-r--r--g10/g10.c14
-rw-r--r--g10/getkey.c10
-rw-r--r--g10/keydb.h7
-rw-r--r--g10/keygen.c12
-rw-r--r--g10/main.h1
-rw-r--r--g10/packet.h1
-rw-r--r--g10/ringedit.c39
-rw-r--r--g10/seckey-cert.c17
-rw-r--r--g10/sign.c123
-rw-r--r--mpi/config.links2
15 files changed, 470 insertions, 167 deletions
diff --git a/cipher/blowfish.c b/cipher/blowfish.c
index 97817e33d..72d617a5c 100644
--- a/cipher/blowfish.c
+++ b/cipher/blowfish.c
@@ -22,6 +22,12 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
+/* Test values:
+ * key "abcdefghijklmnopqrstuvwxyz";
+ * plain "BLOWFISH"
+ * cipher 32 4E D0 FE F4 13 A2 03
+ */
+
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
@@ -224,25 +230,26 @@ static const u32 ps[BLOWFISH_ROUNDS+2] = {
static u32
function_F( BLOWFISH_context *bc, u32 x )
{
- u16 a, b, c, d, y;
-
- d = x & 0x00ff;
- x >>= 8;
- c = x & 0x00ff;
- x >>= 8;
- b = x & 0x00ff;
- x >>= 8;
- a = x & 0x00ff;
- y = bc->s0[a] + bc->s1[b];
- y ^= bc->s2[c];
- y += bc->s3[d];
-
- return y;
+ u16 a, b, c, d;
+
+ #ifdef BIG_ENDIAN_HOST
+ a = ((byte*)&x)[0];
+ b = ((byte*)&x)[1];
+ c = ((byte*)&x)[2];
+ d = ((byte*)&x)[3];
+ #else
+ a = ((byte*)&x)[3];
+ b = ((byte*)&x)[2];
+ c = ((byte*)&x)[1];
+ d = ((byte*)&x)[0];
+ #endif
+
+ return ((bc->s0[a] + bc->s1[b]) ^ bc->s2[c] ) + bc->s3[d];
}
static void
-encrypted( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
+encrypt( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
{
u32 xl, xr, temp;
int i;
@@ -269,8 +276,9 @@ encrypted( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
*ret_xr = xr;
}
+
static void
-decrypted( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
+decrypt( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
{
u32 xl, xr, temp;
int i;
@@ -298,35 +306,108 @@ decrypted( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
}
static void
-encrypted_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
+encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
{
u32 d1, d2;
- d1 = ((u32*)inbuf)[0];
+ #ifdef BIG_ENDIAN_HOST
+ d1 = ((u32*)inbuf)[0]; /* fixme: this may not be aligned */
d2 = ((u32*)inbuf)[1];
- encrypted( bc, &d1, &d2 );
+ #else
+ ((byte*)&d1)[3] = inbuf[0];
+ ((byte*)&d1)[2] = inbuf[1];
+ ((byte*)&d1)[1] = inbuf[2];
+ ((byte*)&d1)[0] = inbuf[3];
+ ((byte*)&d2)[3] = inbuf[4];
+ ((byte*)&d2)[2] = inbuf[5];
+ ((byte*)&d2)[1] = inbuf[6];
+ ((byte*)&d2)[0] = inbuf[7];
+ #endif
+
+ encrypt( bc, &d1, &d2 );
+
+ #ifdef BIG_ENDIAN_HOST
((u32*)outbuf)[0] = d1;
((u32*)outbuf)[1] = d2;
+ #else
+ outbuf[0] = ((byte*)&d1)[3];
+ outbuf[1] = ((byte*)&d1)[2];
+ outbuf[2] = ((byte*)&d1)[1];
+ outbuf[3] = ((byte*)&d1)[0];
+ outbuf[4] = ((byte*)&d2)[3];
+ outbuf[5] = ((byte*)&d2)[2];
+ outbuf[6] = ((byte*)&d2)[1];
+ outbuf[7] = ((byte*)&d2)[0];
+ #endif
}
+
static void
-decrypted_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
+decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
{
u32 d1, d2;
- d1 = ((u32*)inbuf)[0];
+ #ifdef BIG_ENDIAN_HOST
+ d1 = ((u32*)inbuf)[0]; /* fixme: this may not be aligned */
d2 = ((u32*)inbuf)[1];
- decrypted( bc, &d1, &d2 );
+ #else
+ ((byte*)&d1)[3] = inbuf[0];
+ ((byte*)&d1)[2] = inbuf[1];
+ ((byte*)&d1)[1] = inbuf[2];
+ ((byte*)&d1)[0] = inbuf[3];
+ ((byte*)&d2)[3] = inbuf[4];
+ ((byte*)&d2)[2] = inbuf[5];
+ ((byte*)&d2)[1] = inbuf[6];
+ ((byte*)&d2)[0] = inbuf[7];
+ #endif
+
+ decrypt( bc, &d1, &d2 );
+
+ #ifdef BIG_ENDIAN_HOST
((u32*)outbuf)[0] = d1;
((u32*)outbuf)[1] = d2;
+ #else
+ outbuf[0] = ((byte*)&d1)[3];
+ outbuf[1] = ((byte*)&d1)[2];
+ outbuf[2] = ((byte*)&d1)[1];
+ outbuf[3] = ((byte*)&d1)[0];
+ outbuf[4] = ((byte*)&d2)[3];
+ outbuf[5] = ((byte*)&d2)[2];
+ outbuf[6] = ((byte*)&d2)[1];
+ outbuf[7] = ((byte*)&d2)[0];
+ #endif
}
+static void
+selftest()
+{
+ BLOWFISH_context c;
+ byte plain[] = "BLOWFISH";
+ byte buffer[8];
+
+ blowfish_setkey( &c, "abcdefghijklmnopqrstuvwxyz", 26 );
+ encrypt_block( &c, buffer, plain );
+ if( memcmp( buffer, "\x32\x4E\xD0\xFE\xF4\x13\xA2\x03", 8 ) )
+ log_error("wrong blowfish encryption\n");
+ decrypt_block( &c, buffer, buffer );
+ if( memcmp( buffer, plain, 8 ) )
+ log_bug("blowfish failed\n");
+}
+
+
+
void
blowfish_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
{
int i, j, k;
u32 data, datal, datar;
+ static int initialized;
+
+ if( !initialized ) {
+ initialized = 1;
+ selftest();
+ }
for(i=0; i < BLOWFISH_ROUNDS+2; i++ )
c->p[i] = ps[i];
@@ -338,38 +419,44 @@ blowfish_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
}
for(i=j=0; i < BLOWFISH_ROUNDS+2; i++ ) {
- data = 0;
- for(k=0; k < 4; k++) {
- data = (data << 8) | key[j];
- if( ++j >= keylen )
- j = 0;
- }
+ #ifdef BIG_ENDIAN_HOST
+ ((byte*)&data)[0] = key[j];
+ ((byte*)&data)[1] = key[(j+1)%keylen];
+ ((byte*)&data)[2] = key[(j+2)%keylen];
+ ((byte*)&data)[3] = key[(j+3)%keylen];
+ #else
+ ((byte*)&data)[3] = key[j];
+ ((byte*)&data)[2] = key[(j+1)%keylen];
+ ((byte*)&data)[1] = key[(j+2)%keylen];
+ ((byte*)&data)[0] = key[(j+3)%keylen];
+ #endif
c->p[i] ^= data;
+ j = (j+4) % keylen;
}
datal = datar = 0;
for(i=0; i < BLOWFISH_ROUNDS+2; i += 2 ) {
- encrypted( c, &datal, &datar );
+ encrypt( c, &datal, &datar );
c->p[i] = datal;
c->p[i+1] = datar;
}
for(i=0; i < 256; i += 2 ) {
- encrypted( c, &datal, &datar );
+ encrypt( c, &datal, &datar );
c->s0[i] = datal;
c->s0[i+1] = datar;
}
for(i=0; i < 256; i += 2 ) {
- encrypted( c, &datal, &datar );
+ encrypt( c, &datal, &datar );
c->s1[i] = datal;
c->s1[i+1] = datar;
}
for(i=0; i < 256; i += 2 ) {
- encrypted( c, &datal, &datar );
+ encrypt( c, &datal, &datar );
c->s2[i] = datal;
c->s2[i+1] = datar;
}
for(i=0; i < 256; i += 2 ) {
- encrypted( c, &datal, &datar );
+ encrypt( c, &datal, &datar );
c->s3[i] = datal;
c->s3[i+1] = datar;
}
@@ -384,7 +471,7 @@ blowfish_setiv( BLOWFISH_context *c, byte *iv )
else
memset( c->iv, 0, BLOWFISH_BLOCKSIZE );
c->count = 0;
- encrypted_block( c, c->eniv, c->iv );
+ encrypt_block( c, c->eniv, c->iv );
}
@@ -395,7 +482,7 @@ blowfish_encode( BLOWFISH_context *c, byte *outbuf, byte *inbuf,
unsigned n;
for(n=0; n < nblocks; n++ ) {
- encrypted_block( c, outbuf, inbuf );
+ encrypt_block( c, outbuf, inbuf );
inbuf += BLOWFISH_BLOCKSIZE;;
outbuf += BLOWFISH_BLOCKSIZE;
}
@@ -408,7 +495,7 @@ blowfish_decode( BLOWFISH_context *c, byte *outbuf, byte *inbuf,
unsigned n;
for(n=0; n < nblocks; n++ ) {
- decrypted_block( c, outbuf, inbuf );
+ decrypt_block( c, outbuf, inbuf );
inbuf += BLOWFISH_BLOCKSIZE;;
outbuf += BLOWFISH_BLOCKSIZE;
}
@@ -451,7 +538,7 @@ blowfish_encode_cfb( BLOWFISH_context *c, byte *outbuf,
outbuf += n;
assert( c->count <= BLOWFISH_BLOCKSIZE);
if( c->count == BLOWFISH_BLOCKSIZE ) {
- encrypted_block( c, c->eniv, c->iv );
+ encrypt_block( c, c->eniv, c->iv );
c->count = 0;
}
else
@@ -461,7 +548,7 @@ blowfish_encode_cfb( BLOWFISH_context *c, byte *outbuf,
while( nbytes >= BLOWFISH_BLOCKSIZE ) {
xorblock( outbuf, c->eniv, inbuf, BLOWFISH_BLOCKSIZE);
memcpy( c->iv, outbuf, BLOWFISH_BLOCKSIZE);
- encrypted_block( c, c->eniv, c->iv );
+ encrypt_block( c, c->eniv, c->iv );
nbytes -= BLOWFISH_BLOCKSIZE;
inbuf += BLOWFISH_BLOCKSIZE;
outbuf += BLOWFISH_BLOCKSIZE;
@@ -495,7 +582,7 @@ blowfish_decode_cfb( BLOWFISH_context *c, byte *outbuf,
outbuf += n;
assert( c->count <= BLOWFISH_BLOCKSIZE);
if( c->count == BLOWFISH_BLOCKSIZE ) {
- encrypted_block( c, c->eniv, c->iv );
+ encrypt_block( c, c->eniv, c->iv );
c->count = 0;
}
else
@@ -506,7 +593,7 @@ blowfish_decode_cfb( BLOWFISH_context *c, byte *outbuf,
while( nbytes >= BLOWFISH_BLOCKSIZE ) {
memcpy( c->iv, inbuf, BLOWFISH_BLOCKSIZE);
xorblock( outbuf, c->eniv, inbuf, BLOWFISH_BLOCKSIZE);
- encrypted_block( c, c->eniv, c->iv );
+ encrypt_block( c, c->eniv, c->iv );
nbytes -= BLOWFISH_BLOCKSIZE;
inbuf += BLOWFISH_BLOCKSIZE;
outbuf += BLOWFISH_BLOCKSIZE;
diff --git a/cipher/md5.c b/cipher/md5.c
index 06e3a88f4..be2602695 100644
--- a/cipher/md5.c
+++ b/cipher/md5.c
@@ -47,6 +47,12 @@
* with RFC1113 !
*/
+/* Test values:
+ * "" D4 1D 8C D9 8F 00 B2 04 E9 80 09 98 EC F8 42 7E
+ * "a" 0C C1 75 B9 C0 F1 B6 A8 31 C3 99 E2 69 77 26 61
+ * "abc 90 01 50 98 3C D2 4F B0 D6 96 3F 7D 28 E1 7F 72
+ * "message digest" F9 6B 69 7D 7C B7 93 8D 52 5A 2F 31 AA F1 61 D0
+ */
#include <config.h>
#include <stdio.h>
diff --git a/cipher/rmd160.c b/cipher/rmd160.c
index 2b2b34c9e..24c904a5b 100644
--- a/cipher/rmd160.c
+++ b/cipher/rmd160.c
@@ -1,5 +1,5 @@
-/* rmd160.c - RIPE-MD160
- * Copyright (c) 1997 by Werner Koch (dd9jn)
+/* rmd160.c - RIPE-MD160
+ * Copyright (c) 1997 by Werner Koch (dd9jn)
*
* This file is part of G10.
*
@@ -48,20 +48,20 @@
*
* nonlinear functions at bit level: exor, mux, -, mux, -
*
- * f(j, x, y, z) = x XOR y XOR z (0 <= j <= 15)
+ * f(j, x, y, z) = x XOR y XOR z (0 <= j <= 15)
* f(j, x, y, z) = (x AND y) OR (NOT(x) AND z) (16 <= j <= 31)
- * f(j, x, y, z) = (x OR NOT(y)) XOR z (32 <= j <= 47)
+ * f(j, x, y, z) = (x OR NOT(y)) XOR z (32 <= j <= 47)
* f(j, x, y, z) = (x AND z) OR (y AND NOT(z)) (48 <= j <= 63)
- * f(j, x, y, z) = x XOR (y OR NOT(z)) (64 <= j <= 79)
+ * f(j, x, y, z) = x XOR (y OR NOT(z)) (64 <= j <= 79)
*
*
* added constants (hexadecimal)
*
- * K(j) = 0x00000000 (0 <= j <= 15)
- * K(j) = 0x5A827999 (16 <= j <= 31) int(2**30 x sqrt(2))
- * K(j) = 0x6ED9EBA1 (32 <= j <= 47) int(2**30 x sqrt(3))
- * K(j) = 0x8F1BBCDC (48 <= j <= 63) int(2**30 x sqrt(5))
- * K(j) = 0xA953FD4E (64 <= j <= 79) int(2**30 x sqrt(7))
+ * K(j) = 0x00000000 (0 <= j <= 15)
+ * K(j) = 0x5A827999 (16 <= j <= 31) int(2**30 x sqrt(2))
+ * K(j) = 0x6ED9EBA1 (32 <= j <= 47) int(2**30 x sqrt(3))
+ * K(j) = 0x8F1BBCDC (48 <= j <= 63) int(2**30 x sqrt(5))
+ * K(j) = 0xA953FD4E (64 <= j <= 79) int(2**30 x sqrt(7))
* K'(j) = 0x50A28BE6 (0 <= j <= 15) int(2**30 x cbrt(2))
* K'(j) = 0x5C4DD124 (16 <= j <= 31) int(2**30 x cbrt(3))
* K'(j) = 0x6D703EF3 (32 <= j <= 47) int(2**30 x cbrt(5))
@@ -71,7 +71,7 @@
*
* selection of message word
*
- * r(j) = j (0 <= j <= 15)
+ * r(j) = j (0 <= j <= 15)
* r(16..31) = 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8
* r(32..47) = 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12
* r(48..63) = 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2
@@ -100,7 +100,7 @@
* initial value (hexadecimal)
*
* h0 = 0x67452301; h1 = 0xEFCDAB89; h2 = 0x98BADCFE; h3 = 0x10325476;
- * h4 = 0xC3D2E1F0;
+ * h4 = 0xC3D2E1F0;
*
*
* RIPEMD-160: pseudo-code
@@ -112,17 +112,17 @@
*
*
* for i := 0 to t-1 {
- * A := h0; B := h1; C := h2; D = h3; E = h4;
- * A' := h0; B' := h1; C' := h2; D' = h3; E' = h4;
- * for j := 0 to 79 {
- * T := rol_s(j)(A [+] f(j, B, C, D) [+] X[i][r(j)] [+] K(j)) [+] E;
- * A := E; E := D; D := rol_10(C); C := B; B := T;
- * T := rol_s'(j)(A' [+] f(79-j, B', C', D') [+] X[i][r'(j)]
- [+] K'(j)) [+] E';
- * A' := E'; E' := D'; D' := rol_10(C'); C' := B'; B' := T;
- * }
- * T := h1 [+] C [+] D'; h1 := h2 [+] D [+] E'; h2 := h3 [+] E [+] A';
- * h3 := h4 [+] A [+] B'; h4 := h0 [+] B [+] C'; h0 := T;
+ * A := h0; B := h1; C := h2; D = h3; E = h4;
+ * A' := h0; B' := h1; C' := h2; D' = h3; E' = h4;
+ * for j := 0 to 79 {
+ * T := rol_s(j)(A [+] f(j, B, C, D) [+] X[i][r(j)] [+] K(j)) [+] E;
+ * A := E; E := D; D := rol_10(C); C := B; B := T;
+ * T := rol_s'(j)(A' [+] f(79-j, B', C', D') [+] X[i][r'(j)]
+ [+] K'(j)) [+] E';
+ * A' := E'; E' := D'; D' := rol_10(C'); C' := B'; B' := T;
+ * }
+ * T := h1 [+] C [+] D'; h1 := h2 [+] D [+] E'; h2 := h3 [+] E [+] A';
+ * h3 := h4 [+] A [+] B'; h4 := h0 [+] B [+] C'; h0 := T;
* }
*/
@@ -156,43 +156,48 @@ initialize( RMDHANDLE hd )
* Transform the message X which consists of 16 32-bit-words
*/
static void
-transform( RMDHANDLE hd, u32 *x )
+transform( RMDHANDLE hd, byte *data )
{
static int r[80] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
- 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
- 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
- 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 };
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
+ 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
+ 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
+ 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 };
static int rr[80] = {
- 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
- 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
- 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
- 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
- 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 };
+ 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
+ 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
+ 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
+ 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
+ 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 };
static int s[80] = {
- 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
- 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
- 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
- 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
- 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 };
+ 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
+ 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
+ 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
+ 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
+ 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 };
static int ss[80] = {
- 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
- 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
- 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
- 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
- 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 };
+ 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
+ 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
+ 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
+ 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
+ 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 };
u32 a,b,c,d,e,aa,bb,cc,dd,ee,t;
int rbits, j;
+ #ifdef BIG_ENDIAN_HOST
+ u32 x[16];
+ #else
+ u32 *x;
+ #endif
-#define K(a) ( (a) < 16 ? 0x00000000 : \
- (a) < 32 ? 0x5A827999 : \
- (a) < 48 ? 0x6ED9EBA1 : \
- (a) < 64 ? 0x8F1BBCDC : 0xA953FD4E )
-#define KK(a) ( (a) < 16 ? 0x50A28BE6 : \
- (a) < 32 ? 0x5C4DD124 : \
- (a) < 48 ? 0x6D703EF3 : \
- (a) < 64 ? 0x7A6D76E9 : 0x00000000 )
+#define K(a) ( (a) < 16 ? 0x00000000 : \
+ (a) < 32 ? 0x5A827999 : \
+ (a) < 48 ? 0x6ED9EBA1 : \
+ (a) < 64 ? 0x8F1BBCDC : 0xA953FD4E )
+#define KK(a) ( (a) < 16 ? 0x50A28BE6 : \
+ (a) < 32 ? 0x5C4DD124 : \
+ (a) < 48 ? 0x6D703EF3 : \
+ (a) < 64 ? 0x7A6D76E9 : 0x00000000 )
#define F0(x,y,z) ( (x) ^ (y) ^ (z) )
#define F1(x,y,z) ( ((x) & (y)) | (~(x) & (z)) )
@@ -200,13 +205,28 @@ transform( RMDHANDLE hd, u32 *x )
#define F3(x,y,z) ( ((x) & (z)) | ((y) & ~(z)) )
#define F4(x,y,z) ( (x) ^ ((y) | ~(z)) )
#define F(a,x,y,z) ( (a) < 16 ? F0((x),(y),(z)) : \
- (a) < 32 ? F1((x),(y),(z)) : \
- (a) < 48 ? F2((x),(y),(z)) : \
- (a) < 64 ? F3((x),(y),(z)) : \
- F4((x),(y),(z)) )
+ (a) < 32 ? F1((x),(y),(z)) : \
+ (a) < 48 ? F2((x),(y),(z)) : \
+ (a) < 64 ? F3((x),(y),(z)) : \
+ F4((x),(y),(z)) )
#define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) )
+
+ #ifdef BIG_ENDIAN_HOST
+ { int i;
+ byte *p2, *p1;
+ for(i=0, p1=data, p2=(byte*)x; i < 16; i++, p2 += 4 ) {
+ p2[3] = *p1++;
+ p2[2] = *p1++;
+ p2[1] = *p1++;
+ p2[0] = *p1++;
+ }
+ }
+ #else
+ x = data;
+ #endif
+
a = aa = hd->h0;
b = bb = hd->h1;
c = cc = hd->h2;
@@ -214,20 +234,20 @@ transform( RMDHANDLE hd, u32 *x )
e = ee = hd->h4;
for(j=0; j < 80; j++ ) {
- t = a + F( j, b, c, d ) + x[ r[j] ] + K(j);
- rbits = s[j];
- a = rol(rbits, t) + e;
- c = rol(10,c);
- t = a; a = e; e = d; d = c; c = b; b = t;
-
- t = aa + F(79-j, bb, cc, dd ) + x[ rr[j] ] + KK(j);
- rbits = ss[j];
- aa = rol(rbits, t) + ee;
- cc = rol(10,cc);
- t = aa; aa = ee; ee = dd; dd = cc; cc = bb; bb = t;
+ t = a + F( j, b, c, d ) + x[ r[j] ] + K(j);
+ rbits = s[j];
+ a = rol(rbits, t) + e;
+ c = rol(10,c);
+ t = a; a = e; e = d; d = c; c = b; b = t;
+
+ t = aa + F(79-j, bb, cc, dd ) + x[ rr[j] ] + KK(j);
+ rbits = ss[j];
+ aa = rol(rbits, t) + ee;
+ cc = rol(10,cc);
+ t = aa; aa = ee; ee = dd; dd = cc; cc = bb; bb = t;
}
- t = hd->h1 + c + dd;
+ t = hd->h1 + c + dd;
hd->h1 = hd->h2 + d + ee;
hd->h2 = hd->h3 + e + aa;
hd->h3 = hd->h4 + a + bb;
@@ -244,7 +264,7 @@ rmd160_open( int secure )
RMDHANDLE hd;
hd = secure? m_alloc_secure( sizeof *hd )
- : m_alloc( sizeof *hd );
+ : m_alloc( sizeof *hd );
initialize(hd);
return hd;
}
@@ -257,7 +277,7 @@ rmd160_copy( RMDHANDLE a )
assert(a);
b = m_is_secure(a)? m_alloc_secure( sizeof *b )
- : m_alloc( sizeof *b );
+ : m_alloc( sizeof *b );
memcpy( b, a, sizeof *a );
return b;
}
@@ -278,7 +298,7 @@ void
rmd160_close(RMDHANDLE hd)
{
if( hd )
- m_free(hd);
+ m_free(hd);
}
@@ -290,29 +310,29 @@ void
rmd160_write( RMDHANDLE hd, byte *inbuf, size_t inlen)
{
if( hd->bufcount == 64 ) { /* flush the buffer */
- transform( hd, (u32*)hd->buffer );
- hd->bufcount = 0;
- hd->nblocks++;
+ transform( hd, hd->buffer );
+ hd->bufcount = 0;
+ hd->nblocks++;
}
if( !inbuf )
- return;
+ return;
if( hd->bufcount ) {
- for( ; inlen && hd->bufcount < 64; inlen-- )
- hd->buffer[hd->bufcount++] = *inbuf++;
- rmd160_write( hd, NULL, 0 );
- if( !inlen )
- return;
+ for( ; inlen && hd->bufcount < 64; inlen-- )
+ hd->buffer[hd->bufcount++] = *inbuf++;
+ rmd160_write( hd, NULL, 0 );
+ if( !inlen )
+ return;
}
while( inlen >= 64 ) {
- transform( hd, (u32*)inbuf );
- hd->bufcount = 0;
- hd->nblocks++;
- inlen -= 64;
- inbuf += 64;
+ transform( hd, inbuf );
+ hd->bufcount = 0;
+ hd->nblocks++;
+ inlen -= 64;
+ inbuf += 64;
}
for( ; inlen && hd->bufcount < 64; inlen-- )
- hd->buffer[hd->bufcount++] = *inbuf++;
+ hd->buffer[hd->bufcount++] = *inbuf++;
}
@@ -334,27 +354,27 @@ rmd160_final(RMDHANDLE hd)
msb = 0;
t = hd->nblocks;
if( (lsb = t << 6) < t ) /* multiply by 64 to make a byte count */
- msb++;
+ msb++;
msb += t >> 26;
t = lsb;
if( (lsb = t + hd->bufcount) < t ) /* add the bufcount */
- msb++;
+ msb++;
t = lsb;
if( (lsb = t << 3) < t ) /* multiply by 8 to make a bit count */
- msb++;
+ msb++;
msb += t >> 29;
if( hd->bufcount < 56 ) { /* enough room */
- hd->buffer[hd->bufcount++] = 0x80; /* pad */
- while( hd->bufcount < 56 )
- hd->buffer[hd->bufcount++] = 0; /* pad */
+ hd->buffer[hd->bufcount++] = 0x80; /* pad */
+ while( hd->bufcount < 56 )
+ hd->buffer[hd->bufcount++] = 0; /* pad */
}
else { /* need one extra block */
- hd->buffer[hd->bufcount++] = 0x80; /* pad character */
- while( hd->bufcount < 64 )
- hd->buffer[hd->bufcount++] = 0;
- rmd160_write(hd, NULL, 0); /* flush */;
- memset(hd->buffer, 0, 56 ); /* fill next block with zeroes */
+ hd->buffer[hd->bufcount++] = 0x80; /* pad character */
+ while( hd->bufcount < 64 )
+ hd->buffer[hd->bufcount++] = 0;
+ rmd160_write(hd, NULL, 0); /* flush */;
+ memset(hd->buffer, 0, 56 ); /* fill next block with zeroes */
}
/* append the 64 bit count */
hd->buffer[56] = lsb ;
@@ -365,12 +385,12 @@ rmd160_final(RMDHANDLE hd)
hd->buffer[61] = msb >> 8;
hd->buffer[62] = msb >> 16;
hd->buffer[63] = msb >> 24;
- transform( hd, (u32*)hd->buffer );
+ transform( hd, hd->buffer );
p = hd->buffer;
#ifdef BIG_ENDIAN_HOST
- #define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \
- *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0)
+ #define X(a) do { *p++ = hd->h##a ; *p++ = hd->h##a >> 8; \
+ *p++ = hd->h##a >> 16; *p++ = hd->h##a >> 24; } while(0)
#else /* little endian */
#define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0)
#endif
@@ -381,8 +401,9 @@ rmd160_final(RMDHANDLE hd)
X(4);
#undef X
- initialize( hd ); /* prepare for next cycle */
+ initialize( hd ); /* prepare for next cycle */
return hd->buffer; /* now contains the digest */
}
+
diff --git a/cipher/sha1.c b/cipher/sha1.c
index afb815e44..1685058f3 100644
--- a/cipher/sha1.c
+++ b/cipher/sha1.c
@@ -397,4 +397,3 @@ sha1_final(SHA1HANDLE hd)
}
-
diff --git a/g10/build-packet.c b/g10/build-packet.c
index 25d708ceb..6c526e346 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -230,12 +230,13 @@ do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc )
mpi_write(a, skc->d.elg.p );
mpi_write(a, skc->d.elg.g );
mpi_write(a, skc->d.elg.y );
- iobuf_put(a, skc->d.elg.protect_algo );
- if( skc->d.elg.protect_algo ) {
- assert( skc->d.elg.is_protected == 1 );
+ if( skc->d.elg.is_protected ) {
assert( skc->d.elg.protect_algo == CIPHER_ALGO_BLOWFISH );
+ iobuf_put(a, skc->d.elg.protect_algo );
iobuf_write(a, skc->d.elg.protect.blowfish.iv, 8 );
}
+ else
+ iobuf_put(a, 0 );
mpi_write(a, skc->d.elg.x );
write_16(a, skc->d.elg.csum );
@@ -243,12 +244,13 @@ do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc )
else if( skc->pubkey_algo == PUBKEY_ALGO_RSA ) {
mpi_write(a, skc->d.rsa.rsa_n );
mpi_write(a, skc->d.rsa.rsa_e );
- iobuf_put(a, skc->d.rsa.protect_algo );
- if( skc->d.rsa.protect_algo ) {
- assert( skc->d.rsa.is_protected == 1 );
+ if( skc->d.rsa.is_protected ) {
assert( skc->d.rsa.protect_algo == CIPHER_ALGO_BLOWFISH );
+ iobuf_put(a, skc->d.rsa.protect_algo );
iobuf_write(a, skc->d.rsa.protect.blowfish.iv, 8 );
}
+ else
+ iobuf_put(a, 0 );
mpi_write(a, skc->d.rsa.rsa_d );
mpi_write(a, skc->d.rsa.rsa_p );
mpi_write(a, skc->d.rsa.rsa_q );
diff --git a/g10/g10.c b/g10/g10.c
index cac8672ed..ac12d52db 100644
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -38,7 +38,7 @@
enum cmd_values { aNull = 0,
aSym, aStore, aEncr, aPrimegen, aKeygen, aSign, aSignEncr,
aPrintMDs, aSignKey, aClearsig, aListPackets, aEditSig,
- aKMode, aKModeC,
+ aKMode, aKModeC, aChangePass,
aTest };
@@ -158,7 +158,6 @@ main( int argc, char **argv )
{ 512, "cache-all" ,0, "hold everything in memory"},
{ 513, "gen-prime" , 0, "\r" },
{ 514, "test" , 0, "\r" },
- { 515, "change-passphrase", 0, "change the passphrase of your secret keyring"},
{ 515, "fingerprint", 0, "show the fingerprints"},
{ 516, "print-mds" , 0, "print all message digests"},
{ 517, "secret-keyring" ,2, "add this secret keyring to the list" },
@@ -169,6 +168,7 @@ main( int argc, char **argv )
{ 522, "no-greeting", 0, "\r" },
{ 523, "passphrase-fd",1, "\r" },
{ 524, "edit-sig" ,0, "edit a key signature" },
+ { 525, "change-passphrase", 0, "change the passphrase of your secret keyring"},
{0} };
ARGPARSE_ARGS pargs;
@@ -297,6 +297,7 @@ main( int argc, char **argv )
case 522: greeting = 0; break;
case 523: set_passphrase_fd( pargs.r.ret_int ); break;
case 524: set_cmd( &cmd, aEditSig); break;
+ case 525: set_cmd( &cmd, aChangePass); break;
default : errors++; pargs.err = configfp? 1:2; break;
}
}
@@ -406,6 +407,15 @@ main( int argc, char **argv )
log_error("edit_keysig('%s'): %s\n", fname_print, g10_errstr(rc) );
break;
+ case aChangePass: /* Chnage the passphrase */
+ if( argc > 1 ) /* no arg: use default, 1 arg use this one */
+ usage(1);
+ /* note: fname is the user id! */
+ if( (rc = change_passphrase(fname)) )
+ log_error("change_passphrase('%s'): %s\n", fname_print,
+ g10_errstr(rc) );
+ break;
+
case aKMode: /* list keyring */
if( !argc ) { /* list the default public keyrings */
int i, seq=0;
diff --git a/g10/getkey.c b/g10/getkey.c
index 2195762f5..3ec6a6bf4 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -83,7 +83,7 @@ add_keyring( const char *name )
* combine it with the keyblock stuff from ringedit.c
* For now we will simple add the filename as keyblock resource
*/
- rc = add_keyblock_resource( name, 0 );
+ rc = add_keyblock_resource( name, 0, 0 );
if( rc )
log_error("keyblock resource '%s': %s\n", name, g10_errstr(rc) );
}
@@ -115,6 +115,14 @@ add_secret_keyring( const char *name )
strcpy(sl->d, name );
sl->next = secret_keyrings;
secret_keyrings = sl;
+
+ /* FIXME: We should remove much out of this mpdule and
+ * combine it with the keyblock stuff from ringedit.c
+ * For now we will simple add the filename as keyblock resource
+ */
+ rc = add_keyblock_resource( name, 0, 1 );
+ if( rc )
+ log_error("secret keyblock resource '%s': %s\n", name, g10_errstr(rc) );
}
diff --git a/g10/keydb.h b/g10/keydb.h
index f3a42caba..6770f866e 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -125,10 +125,11 @@ KBNODE walk_kbtree2( KBNODE root, KBNODE *context, int all );
void clear_kbnode_flags( KBNODE n );
/*-- ringedit.c --*/
-int add_keyblock_resource( const char *filename, int force );
-int get_keyblock_handle( const char *filename, KBPOS *kbpos );
-int search_keyblock( PACKET *pkt, KBPOS *kbpos );
+int add_keyblock_resource( const char *filename, int force, int secret );
+int get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos );
+int search_keyblock( PACKET *pkt, KBPOS *kbpos, int secret );
int search_keyblock_byname( KBPOS *kbpos, const char *username );
+int search_secret_keyblock_byname( KBPOS *kbpos, const char *username );
int lock_keyblock( KBPOS *kbpos );
void unlock_keyblock( KBPOS *kbpos );
int read_keyblock( KBPOS *kbpos, KBNODE *ret_root );
diff --git a/g10/keygen.c b/g10/keygen.c
index 43924395c..958be3af4 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -507,24 +507,24 @@ generate_keypair()
/* we can now write the certificates */
/* FIXME: should we check wether the user-id already exists? */
- if( get_keyblock_handle( pub_fname, &pub_kbpos ) ) {
- if( add_keyblock_resource( pub_fname, 1 ) ) {
+ if( get_keyblock_handle( pub_fname, 0, &pub_kbpos ) ) {
+ if( add_keyblock_resource( pub_fname, 1, 0 ) ) {
log_error("can add keyblock file '%s'\n", pub_fname );
rc = G10ERR_CREATE_FILE;
}
- else if( get_keyblock_handle( pub_fname, &pub_kbpos ) ) {
+ else if( get_keyblock_handle( pub_fname, 0, &pub_kbpos ) ) {
log_error("can get keyblock handle for '%s'\n", pub_fname );
rc = G10ERR_CREATE_FILE;
}
}
if( rc )
;
- else if( get_keyblock_handle( sec_fname, &sec_kbpos ) ) {
- if( add_keyblock_resource( sec_fname, 1 ) ) {
+ else if( get_keyblock_handle( sec_fname, 1, &sec_kbpos ) ) {
+ if( add_keyblock_resource( sec_fname, 1, 1 ) ) {
log_error("can add keyblock file '%s'\n", sec_fname );
rc = G10ERR_CREATE_FILE;
}
- else if( get_keyblock_handle( sec_fname, &sec_kbpos ) ) {
+ else if( get_keyblock_handle( sec_fname, 1, &sec_kbpos ) ) {
log_error("can get keyblock handle for '%s'\n", sec_fname );
rc = G10ERR_CREATE_FILE;
}
diff --git a/g10/main.h b/g10/main.h
index 15caaab9a..02b0a277c 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -49,6 +49,7 @@ int sign_file( const char *filename, int detached, STRLIST locusr,
int encrypt, STRLIST remusr );
int sign_key( const char *username, STRLIST locusr );
int edit_keysigs( const char *username );
+int change_passphrase( const char *username );
/*-- sig-check.c --*/
int check_key_signature( KBNODE root, KBNODE node );
diff --git a/g10/packet.h b/g10/packet.h
index 4a5a5a3cc..03a7f328f 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -238,6 +238,7 @@ PKT_secret_cert *copy_secret_cert( PKT_secret_cert *d, PKT_secret_cert *s );
int signature_check( PKT_signature *sig, MD_HANDLE *digest );
/*-- seckey-cert.c --*/
+int is_secret_key_protected( PKT_secret_cert *cert );
int check_secret_key( PKT_secret_cert *cert );
int protect_secret_key( PKT_secret_cert *cert, DEK *dek );
diff --git a/g10/ringedit.c b/g10/ringedit.c
index 05a8bb299..8b7431961 100644
--- a/g10/ringedit.c
+++ b/g10/ringedit.c
@@ -58,6 +58,7 @@
struct resource_table_struct {
int used;
+ int secret; /* this is a secret keyring */
char *fname;
IOBUF iobuf;
};
@@ -94,7 +95,7 @@ check_pos( KBPOS *kbpos )
* Register a resource (which currently may ionly be a keyring file).
*/
int
-add_keyblock_resource( const char *filename, int force )
+add_keyblock_resource( const char *filename, int force, int secret )
{
IOBUF iobuf;
int i;
@@ -109,6 +110,7 @@ add_keyblock_resource( const char *filename, int force )
if( !iobuf && !force )
return G10ERR_OPEN_FILE;
resource_table[i].used = 1;
+ resource_table[i].secret = !!secret;
resource_table[i].fname = m_strdup(filename);
resource_table[i].iobuf = iobuf;
return 0;
@@ -120,12 +122,12 @@ add_keyblock_resource( const char *filename, int force )
* to get a handle for insert_keyblock for a new keyblock.
*/
int
-get_keyblock_handle( const char *filename, KBPOS *kbpos )
+get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos )
{
int i;
for(i=0; i < MAX_RESOURCES; i++ )
- if( resource_table[i].used ) {
+ if( resource_table[i].used && !resource_table[i].secret == !secret ) {
/* fixme: dos needs case insensitive file compare */
if( !strcmp( resource_table[i].fname, filename ) ) {
memset( kbpos, 0, sizeof *kbpos );
@@ -148,12 +150,12 @@ get_keyblock_handle( const char *filename, KBPOS *kbpos )
* Returns: 0 if found, -1 if not found or an errorcode.
*/
int
-search_keyblock( PACKET *pkt, KBPOS *kbpos )
+search_keyblock( PACKET *pkt, KBPOS *kbpos, int secret )
{
int i, rc, last_rc=-1;
for(i=0; i < MAX_RESOURCES; i++ ) {
- if( resource_table[i].used ) {
+ if( resource_table[i].used && !resource_table[i].secret == !secret ) {
/* note: here we have to add different search functions,
* depending on the type of the resource */
rc = keyring_search( pkt, kbpos, resource_table[i].iobuf );
@@ -192,11 +194,36 @@ search_keyblock_byname( KBPOS *kbpos, const char *username )
init_packet( &pkt );
pkt.pkttype = PKT_PUBLIC_CERT;
pkt.pkt.public_cert = pkc;
- rc = search_keyblock( &pkt, kbpos );
+ rc = search_keyblock( &pkt, kbpos, 0 );
free_public_cert(pkc);
return rc;
}
+/****************
+ * Combined function to search for a username and get the position
+ * of the keyblock. This function does not unprotect the secret key.
+ */
+int
+search_secret_keyblock_byname( KBPOS *kbpos, const char *username )
+{
+ PACKET pkt;
+ PKT_secret_cert *skc = m_alloc_clear( sizeof *skc );
+ int rc;
+
+ rc = get_seckey_byname( skc, username, 0 );
+ if( rc ) {
+ free_secret_cert(skc);
+ return rc;
+ }
+
+ init_packet( &pkt );
+ pkt.pkttype = PKT_SECRET_CERT;
+ pkt.pkt.secret_cert = skc;
+ rc = search_keyblock( &pkt, kbpos, 1 );
+ free_secret_cert(skc);
+ return rc;
+}
+
/****************
* Lock the keyblock; wait until it's available
diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c
index c1ea596ac..7f76b31e8 100644
--- a/g10/seckey-cert.c
+++ b/g10/seckey-cert.c
@@ -284,6 +284,23 @@ check_secret_key( PKT_secret_cert *cert )
return rc;
}
+/****************
+ * check wether the secret key is protected.
+ * Returns: 0 not protected, -1 on error or the protection algorithm
+ */
+int
+is_secret_key_protected( PKT_secret_cert *cert )
+{
+ if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
+ return cert->d.elg.is_protected? cert->d.elg.protect_algo : 0;
+ #ifdef HAVE_RSA_CIPHER
+ else if( cert->pubkey_algo == PUBKEY_ALGO_RSA )
+ return cert->d.rsa.is_protected? cert->d.rsa.protect_algo : 0;
+ #endif
+ else
+ return -1; /* unsupported */
+}
+
/****************
* Protect the secret key certificate with the passphrase from DEK
diff --git a/g10/sign.c b/g10/sign.c
index a8541391d..d0596d669 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -695,6 +695,129 @@ edit_keysigs( const char *username )
}
+int
+change_passphrase( const char *username )
+{
+ int rc = 0;
+ KBNODE keyblock = NULL;
+ KBNODE kbctx, node;
+ KBPOS kbpos;
+ PKT_secret_cert *skc;
+ int any;
+ u32 skc_keyid[2];
+ char *answer;
+ int changed=0;
+
+ /* search the userid */
+ rc = search_secret_keyblock_byname( &kbpos, username );
+ if( rc ) {
+ log_error("secret key for user '%s' not found\n", username );
+ goto leave;
+ }
+
+ /* read the keyblock */
+ rc = read_keyblock( &kbpos, &keyblock );
+ if( rc ) {
+ log_error("error reading the certificate: %s\n", g10_errstr(rc) );
+ goto leave;
+ }
+
+ /* get the keyid from the keyblock */
+ for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
+ if( node->pkt->pkttype == PKT_SECRET_CERT )
+ break;
+ }
+ if( !node ) {
+ log_error("Oops; secret key not found anymore!\n");
+ rc = G10ERR_GENERAL;
+ goto leave;
+ }
+
+ skc = node->pkt->pkt.secret_cert;
+ keyid_from_skc( skc, skc_keyid );
+ tty_printf("sec %4u%c/%08lX %s ",
+ nbits_from_skc( skc ),
+ pubkey_letter( skc->pubkey_algo ),
+ skc_keyid[1], datestr_from_skc(skc) );
+ {
+ size_t n;
+ char *p = get_user_id( skc_keyid, &n );
+ tty_print_string( p, n );
+ m_free(p);
+ tty_printf("\n");
+ }
+
+ clear_kbnode_flags( keyblock );
+ switch( is_secret_key_protected( skc ) ) {
+ case -1:
+ rc = G10ERR_PUBKEY_ALGO;
+ break;
+ case 0:
+ tty_printf("This key is not protected.\n");
+ break;
+ default:
+ tty_printf("Key is protected.\n");
+ rc = check_secret_key( skc );
+ break;
+ }
+
+ if( rc )
+ tty_printf("Can't edit this key: %s\n", g10_errstr(rc));
+ else {
+ DEK *dek = m_alloc_secure( sizeof *dek );
+
+ tty_printf( "Enter the new passphrase for this secret key.\n\n" );
+
+ for(;;) {
+ dek->algo = CIPHER_ALGO_BLOWFISH;
+ rc = make_dek_from_passphrase( dek , 2 );
+ if( rc == -1 ) {
+ rc = 0;
+ tty_printf( "You don't want a passphrase -"
+ " this is probably a *bad* idea!\n\n");
+ answer = tty_get("Do you really want to do this? ");
+ tty_kill_prompt();
+ if( answer_is_yes(answer) )
+ changed++;
+ m_free(answer);
+ break;
+ }
+ else if( rc == G10ERR_PASSPHRASE ) {
+ tty_printf("passphrase not correctly repeated; try again.\n");
+ }
+ else if( rc ) {
+ m_free(dek); dek = NULL;
+ log_error("Error getting the passphrase: %s\n", g10_errstr(rc));
+ break;
+ }
+ else { /* okay */
+ skc->d.elg.protect_algo = CIPHER_ALGO_BLOWFISH;
+ randomize_buffer(skc->d.elg.protect.blowfish.iv, 8, 1);
+ rc = protect_secret_key( skc, dek );
+ if( rc )
+ log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
+ else
+ changed++;
+ break;
+ }
+ }
+ m_free(dek);
+ }
+
+
+ if( changed ) {
+ rc = update_keyblock( &kbpos, keyblock );
+ if( rc ) {
+ log_error("update_keyblock failed: %s\n", g10_errstr(rc) );
+ goto leave;
+ }
+ }
+
+ leave:
+ release_kbnode( keyblock );
+ return rc;
+}
+
/****************
* Create a signature packet for the given public key certificate
diff --git a/mpi/config.links b/mpi/config.links
index 0560b7de5..9ee1d0568 100644
--- a/mpi/config.links
+++ b/mpi/config.links
@@ -58,7 +58,7 @@ case "${target}" in
*-*-linuxaout* | *-*-linuxoldld*)
needs_underscore="y"
;;
- *-*-linux* | *-sysv* | *-solaris*)
+ *-*-linux* | *-sysv* | *-solaris* | *-gnu*)
needs_underscore="n"
;;
*)