From 0d9ffec5efcafa9f6499a2c4e4e2784290faec2f Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 6 Jan 1998 21:01:36 +0000 Subject: [PATCH] Bug in blowfish behoben --- cipher/blowfish.c | 163 +++++++++++++++++++++++++-------- cipher/md5.c | 6 ++ cipher/rmd160.c | 221 +++++++++++++++++++++++++-------------------- cipher/sha1.c | 1 - g10/build-packet.c | 14 +-- g10/g10.c | 14 ++- g10/getkey.c | 10 +- g10/keydb.h | 7 +- g10/keygen.c | 12 +-- g10/main.h | 1 + g10/packet.h | 1 + g10/ringedit.c | 39 ++++++-- g10/seckey-cert.c | 17 ++++ g10/sign.c | 123 +++++++++++++++++++++++++ mpi/config.links | 2 +- 15 files changed, 467 insertions(+), 164 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 #include #include @@ -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; + u16 a, b, c, d; - 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]; + #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 y; + 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 #include 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 = 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 = 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" ;; *)