partial DSA support

This commit is contained in:
Werner Koch 1998-03-09 21:44:06 +00:00
parent 1b1a6d7e77
commit a6a8f1e706
62 changed files with 2247 additions and 447 deletions

View File

@ -1,3 +1,7 @@
Wed Mar 4 10:32:40 1998 Werner Koch (wk@isil.d.shuttle.de)
* configure.in (getrusage,gettimeofday): New tests.
Fri Feb 27 13:14:17 1998 Werner Koch (wk@isil.d.shuttle.de)
* configure.in (--disable-m-guard): New.

14
NEWS
View File

@ -1,3 +1,17 @@
Noteworthy changes in version 0.2.12
------------------------------------
* --delete-key checks that there is no secret key. The new
option --delete-secret-key maybe used to delete a secret key.
* "-kv" now works as expected. Options "--list-{keys,sigs]"
and "--check-sigs" are now working.
* New options "--verify" and "--decrypt" to better support integration
into MUAs (partly done for Mutt).
* New option "--with-colons" to make parsing of key lists easier.
Noteworthy changes in version 0.2.11
------------------------------------

11
README
View File

@ -3,8 +3,6 @@
-------------------------------
THIS IS ALPHA SOFTWARE, EXPECT BUGS AND UNIMPLEMENTED STUFF.
IT MAY HAPPEN THAT SOME DATA FORMATS OR PROGRAMM OPTIONS
CHANGE WITH THE NEXT VERSION.
On a Linux box (version 2.x.x, alpha or x86 CPU) it should
work reliable. You may create your key on such a machine and
@ -105,7 +103,7 @@
8) Continue with step 4 if we did not find a prime in step 7.
9) Find a generator for that prime.
You should make a revocation certificate in cases someone gets
You should make a revocation certificate in case someone gets
knowledge of your secret key or you forgot your passphrase:
gpg --gen-revoke your_user_id
@ -208,12 +206,14 @@
"234567C4"
"0F34E556E"
"01347A56A"
"0xAB123456
* By a complete keyid:
"234AABBCC34567C4"
"0F323456784E56EAB"
"01AB3FED1347A5612"
"0x234AABBCC34567C4"
* By a fingerprint (not yet implemented):
@ -280,11 +280,6 @@
you are asked for the passphrase, so that GNUPG is able to look at the
inner structure of a encrypted packet.
gpgm --quick-random
Do not use the stroing random generator but a faster one. This can be
used to generate keys for tests; those are marked as insecure.
gpgm --list-trustdb
List the contents of the trustdb in a human readable format

2
THANKS
View File

@ -1,4 +1,4 @@
G10 has originally been written by Werner Koch. Other people contributed
GNUPG has originally been written by Werner Koch. Other people contributed
by reporting problems, suggesting various improvements or submitting actual
code. Here is a list of these people. Help me keeping it complete and
exempt of errors.

11
TODO
View File

@ -13,9 +13,7 @@
* complete cipher/cast.c
* complete cipher/dsa.c
* add g10 stuff to Mutt's pgpinvoke.c
* Burn the buffers used by fopen().
* Burn the buffers used by fopen(), or use read(2).
* bug: g10/trustdb.c#build_sigrecs called to often by do_list_path
and remove the bad kludge. Maybe we should put all sigs into the trustdb
@ -34,4 +32,11 @@
them to your key and because the user id which is signed by others has
also be signed by you, all user-ids are bound together.
* add an option to re-create a public key from a secret key
* should we have a simple menu for all the key management options?
* cleanup mainproc.c, much stuff is duplicated.
* remove key management stuff from sign.c.

View File

@ -1 +1 @@
0.2.11
0.2.12a

View File

@ -1,3 +1,18 @@
Mon Mar 9 12:59:08 1998 Werner Koch (wk@isil.d.shuttle.de)
* dsa.c, dsa.h: Removed some unused code.
Wed Mar 4 10:39:22 1998 Werner Koch (wk@isil.d.shuttle.de)
* md.c (md_open): Add call to fast_random_poll.
blowfish.c (blowfish_setkey): Ditto.
Tue Mar 3 13:32:54 1998 Werner Koch (wk@isil.d.shuttle.de)
* rmd160.c (rmd160_mixblock): New.
* random.c: Restructured to start with a new RNG implementation.
* random.h: New.
Mon Mar 2 19:21:46 1998 Werner Koch (wk@isil.d.shuttle.de)
* gost.c, gost.h: Removed because they did only conatin trash.

View File

@ -13,6 +13,7 @@ libcipher_a_SOURCES = blowfish.c \
md5.c \
md5.h \
primegen.c \
random.h \
random.c \
rmd.h \
rmd160.c \

View File

@ -104,6 +104,7 @@ libcipher_a_SOURCES = blowfish.c \
md5.c \
md5.h \
primegen.c \
random.h \
random.c \
rmd.h \
rmd160.c \

View File

@ -37,6 +37,7 @@
#include "util.h"
#include "types.h"
#include "blowfish.h"
#include "random.h"
/* precomputed S boxes */
static const u32 ks0[256] = {
@ -421,6 +422,8 @@ blowfish_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
selftest();
}
fast_random_poll();
for(i=0; i < BLOWFISH_ROUNDS+2; i++ )
c->p[i] = ps[i];
for(i=0; i < 256; i++ ) {

View File

@ -32,6 +32,7 @@ void
dsa_free_public_key( DSA_public_key *pk )
{
mpi_free( pk->p ); pk->p = NULL;
mpi_free( pk->q ); pk->q = NULL;
mpi_free( pk->g ); pk->g = NULL;
mpi_free( pk->y ); pk->y = NULL;
}
@ -40,121 +41,13 @@ void
dsa_free_secret_key( DSA_secret_key *sk )
{
mpi_free( sk->p ); sk->p = NULL;
mpi_free( sk->q ); sk->q = NULL;
mpi_free( sk->g ); sk->g = NULL;
mpi_free( sk->y ); sk->y = NULL;
mpi_free( sk->x ); sk->x = NULL;
}
static void
test_keys( DSA_public_key *pk, DSA_secret_key *sk, unsigned nbits )
{
MPI test = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
MPI out1_a = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
MPI out1_b = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
MPI out2 = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
mpi_set_bytes( test, nbits, get_random_byte, 0 );
dsa_sign( out1_a, out1_b, test, sk );
if( !dsa_verify( out1_a, out1_b, test, pk ) )
log_fatal("DSA operation: sign, verify failed\n");
mpi_free( test );
mpi_free( out1_a );
mpi_free( out1_b );
mpi_free( out2 );
}
/****************
* generate a random secret exponent k from prime p, so
* that k is relatively prime to p-1
*/
static MPI
gen_k( MPI p )
{
MPI k = mpi_alloc_secure( mpi_get_nlimbs(p) );
MPI temp = mpi_alloc( mpi_get_nlimbs(p) );
MPI p_1 = mpi_copy(p);
unsigned nbits = mpi_get_nbits(p);
if( DBG_CIPHER )
log_debug("choosing a random k ");
mpi_sub_ui( p_1, p, 1);
for(;;) {
if( DBG_CIPHER )
fputc('.', stderr);
mpi_set_bytes( k, nbits, get_random_byte, 1 );
mpi_set_highbit( k, nbits-1 ); /* make sure it's high (really needed?) */
if( mpi_cmp( k, p_1 ) >= 0 )
continue; /* is not smaller than (p-1) */
if( mpi_gcd( temp, k, p_1 ) )
break; /* okay, k is relatively prime to (p-1) */
}
if( DBG_CIPHER )
fputc('\n', stderr);
mpi_free(p_1);
mpi_free(temp);
return k;
}
/****************
* Generate a key pair with a key of size NBITS
* Returns: 2 structures filles with all needed values
*/
void
dsa_generate( DSA_public_key *pk, DSA_secret_key *sk, unsigned nbits )
{
MPI p; /* the prime */
MPI g;
MPI x; /* the secret exponent */
MPI y;
p = generate_public_prime( nbits );
/* FIXME: check wether we shall assert that (p-1)/2 is also prime
* Schneier votes against it
*/
g = mpi_alloc_set_ui(3);
/* select a random number */
x = mpi_alloc_secure( nbits/BITS_PER_MPI_LIMB );
if( DBG_CIPHER )
log_debug("choosing a random x ");
do {
if( DBG_CIPHER )
fputc('.', stderr);
mpi_set_bytes( x, nbits, get_random_byte, 1 ); /* fixme: should be 2 */
mpi_set_highbit( x, nbits-1 ); /* make sure it's high (needed?) */
} while( mpi_cmp( x, p ) >= 0 ); /* x must be smaller than p */
y = mpi_alloc(nbits/BITS_PER_MPI_LIMB);
mpi_powm( y, g, x, p );
if( DBG_CIPHER ) {
fputc('\n', stderr);
log_mpidump("dsa p= ", p );
log_mpidump("dsa g= ", g );
log_mpidump("dsa y= ", y );
log_mpidump("dsa x= ", x );
}
/* copy the stuff to the key structures */
pk->p = mpi_copy(p);
pk->g = mpi_copy(g);
pk->y = mpi_copy(y);
sk->p = p;
sk->g = g;
sk->y = y;
sk->x = x;
/* now we can test our keys (this should never fail!) */
test_keys( pk, sk, nbits - 64 );
}
/****************
* Test wether the secret key is valid.
* Returns: if this is a valid key.
@ -174,72 +67,58 @@ dsa_check_secret_key( DSA_secret_key *sk )
/****************
* Make an Elgamal signature out of INPUT
* Make a DSA signature out of INPUT
*/
void
dsa_sign(MPI a, MPI b, MPI input, DSA_secret_key *skey )
dsa_sign(MPI r, MPI s, MPI input, DSA_secret_key *skey )
{
MPI k;
MPI t = mpi_alloc( mpi_get_nlimbs(a) );
MPI inv = mpi_alloc( mpi_get_nlimbs(a) );
MPI p_1 = mpi_copy(skey->p);
/*
* b = (t * inv) mod (p-1)
* b = (t * inv(k,(p-1),(p-1)) mod (p-1)
* b = (((M-x*a) mod (p-1)) * inv(k,(p-1),(p-1))) mod (p-1)
*
*/
mpi_sub_ui(p_1, p_1, 1);
k = gen_k( skey->p );
mpi_powm( a, skey->g, k, skey->p );
mpi_mul(t, skey->x, a );
mpi_subm(t, input, t, p_1 );
while( mpi_is_neg(t) )
mpi_add(t, t, p_1);
mpi_invm(inv, k, p_1 );
mpi_mulm(b, t, inv, p_1 );
#if 0
if( DBG_CIPHER ) {
log_mpidump("dsa sign p= ", skey->p);
log_mpidump("dsa sign g= ", skey->g);
log_mpidump("dsa sign y= ", skey->y);
log_mpidump("dsa sign x= ", skey->x);
log_mpidump("dsa sign k= ", k);
log_mpidump("dsa sign M= ", input);
log_mpidump("dsa sign a= ", a);
log_mpidump("dsa sign b= ", b);
}
#endif
mpi_free(k);
mpi_free(t);
mpi_free(inv);
mpi_free(p_1);
}
/****************
* Returns true if the signature composed from A and B is valid.
* Returns true if the signature composed from R and S is valid.
*/
int
dsa_verify(MPI a, MPI b, MPI input, DSA_public_key *pkey )
dsa_verify(MPI r, MPI s, MPI input, DSA_public_key *pkey )
{
int rc;
MPI t1 = mpi_alloc( mpi_get_nlimbs(a) );
MPI t2 = mpi_alloc( mpi_get_nlimbs(a) );
MPI w, u1, u2, v;
MPI base[3];
MPI exp[3];
mpi_powm( t1, pkey->y, a, pkey->p );
mpi_powm( t2, a, b, pkey->p );
mpi_mulm( t1, t1, t2, pkey->p );
if( !(mpi_cmp_ui( r, 0 ) > 0 && mpi_cmp( r, pkey->q ) < 0) )
return 0; /* assertion 0 < r < q failed */
if( !(mpi_cmp_ui( s, 0 ) > 0 && mpi_cmp( s, pkey->q ) < 0) )
return 0; /* assertion 0 < s < q failed */
mpi_powm( t2, pkey->g, input, pkey->p );
w = mpi_alloc( mpi_get_nlimbs(pkey->q) );
u1 = mpi_alloc( mpi_get_nlimbs(pkey->q) );
u2 = mpi_alloc( mpi_get_nlimbs(pkey->q) );
v = mpi_alloc( mpi_get_nlimbs(pkey->p) );
rc = !mpi_cmp( t1, t2 );
/* w = s^(-1) mod q */
mpi_invm( w, s, pkey->q );
mpi_free(t1);
mpi_free(t2);
/* u1 = (input * w) mod q */
mpi_mulm( u1, input, w, pkey->q );
/* u2 = r * w mod q */
mpi_mulm( u2, r, w, pkey->q );
/* v = g^u1 * y^u2 mod p mod q */
base[0] = pkey->g; exp[0] = u1;
base[1] = pkey->y; exp[1] = u2;
base[2] = NULL; exp[2] = NULL;
mpi_mulpowm( v, base, exp, pkey->p );
mpi_fdiv_r( v, v, pkey->q );
rc = !mpi_cmp( v, r );
mpi_free(w);
mpi_free(u1);
mpi_free(u2);
mpi_free(v);
return rc;
}

View File

@ -43,7 +43,7 @@ void dsa_free_public_key( DSA_public_key *pk );
void dsa_free_secret_key( DSA_secret_key *sk );
void dsa_generate( DSA_public_key *pk, DSA_secret_key *sk, unsigned nbits );
int dsa_check_secret_key( DSA_secret_key *sk );
void dsa_sign(MPI a, MPI b, MPI input, DSA_secret_key *skey);
int dsa_verify(MPI a, MPI b, MPI input, DSA_public_key *pkey);
void dsa_sign(MPI r, MPI s, MPI input, DSA_secret_key *skey);
int dsa_verify(MPI r, MPI s, MPI input, DSA_public_key *pkey);
#endif /*G10_DSA_H*/

View File

@ -42,6 +42,7 @@ md_open( int algo, int secure )
hd->secure = secure;
if( algo )
md_enable( hd, algo );
fast_random_poll();
return hd;
}

View File

@ -174,6 +174,7 @@ check_pubkey_algo( int algo )
{
switch( algo ) {
case PUBKEY_ALGO_ELGAMAL:
case PUBKEY_ALGO_DSA:
#ifdef HAVE_RSA_CIPHER
case PUBKEY_ALGO_RSA:
#endif

View File

@ -18,6 +18,17 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
/****************
* How it works:
*
* See Peter Gutmann's Paper: "Software Generation of Practically
* Strong Random Numbers"
*
* fixme!
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
@ -26,27 +37,88 @@
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef HAVE_GETTIMEOFTIME
#include <sys/times.h>
#endif
#ifdef HAVE_GETRUSAGE
#include <sys/resource.h>
#endif
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "util.h"
#include "cipher.h"
#include "random.h"
#include "rmd.h"
#include "ttyio.h"
#include "i18n.h"
#define BLOCKLEN 64 /* hash this amount of bytes */
#define DIGESTLEN 20 /* into a digest of this length (rmd160) */
/* poolblocks is the number of digests which make up the pool
* and poolsize must be a multiple of the digest length
* to make the AND operations faster, the size should also be
* a multiple of ulong
*/
#define POOLBLOCKS 30
#define POOLSIZE (POOLBLOCKS*DIGESTLEN)
#if (POOLSIZE % SIZEOF_UNSIGNED_LONG)
#error Please make sure that poolsize is a multiple of ulong
#endif
#define POOLWORDS (POOLSIZE / SIZEOF_UNSIGNED_LONG)
#if SIZEOF_UNSIGNED_LONG == 8
#define ADD_VALUE 0xa5a5a5a5a5a5a5a5
#elif SIZEOF_UNSIGNED_LONG == 4
#define ADD_VALUE 0xa5a5a5a5
#else
#error weird size for an unsigned long
#endif
struct cache {
int len;
byte buffer[100]; /* fixme: should be allocated with m_alloc_secure()*/
int size;
byte *buffer;
};
static int is_initialized;
static struct cache cache[3];
#define MASK_LEVEL(a) do {if( a > 2 ) a = 2; else if( a < 0 ) a = 0; } while(0)
static char *rndpool; /* allocated size is POOLSIZE+BLOCKLEN */
static char *keypool; /* allocated size is POOLSIZE+BLOCKLEN */
static size_t pool_readpos;
static size_t pool_writepos;
static int pool_filled;
static int just_mixed;
static void fill_buffer( byte *buffer, size_t length, int level );
static int secure_alloc;
static int quick_test;
static void read_pool( byte *buffer, size_t length, int level );
static void read_dev_random( byte *buffer, size_t length, int level );
static void
initialize()
{
/* The data buffer is allocated somewhat larger, so that
* we can use this extra space (which is allocated in secure memory)
* as a temporary hash buffer */
rndpool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN)
: m_alloc_clear(POOLSIZE+BLOCKLEN);
keypool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN)
: m_alloc_clear(POOLSIZE+BLOCKLEN);
is_initialized = 1;
}
void
secure_random_alloc()
{
secure_alloc = 1;
}
int
quick_random_gen( int onoff )
{
@ -78,14 +150,174 @@ get_random_byte( int level )
{
MASK_LEVEL(level);
if( !cache[level].len ) {
fill_buffer(cache[level].buffer, DIM(cache[level].buffer), level );
cache[level].len = DIM(cache[level].buffer);
if( !is_initialized )
initialize();
if( !cache[level].buffer ) {
cache[level].size = 100;
cache[level].buffer = level && secure_alloc?
m_alloc_secure( cache[level].size )
: m_alloc( cache[level].size );
}
read_pool(cache[level].buffer, cache[level].size, level );
cache[level].len = cache[level].size;
}
return cache[level].buffer[--cache[level].len];
}
/****************
* Mix the pool
*/
static void
mix_pool(byte *pool)
{
char *hashbuf = pool + POOLSIZE;
char *p, *pend;
int i, n;
RMD160_CONTEXT md;
rmd160_init( &md );
#if DIGESTLEN != 20
#error must have a digest length of 20 for ripe-md-160
#endif
/* loop over the pool */
pend = pool + POOLSIZE;
memcpy(hashbuf, pend - DIGESTLEN, DIGESTLEN );
memcpy(hashbuf+DIGESTLEN, pool, BLOCKLEN-DIGESTLEN);
rmd160_mixblock( &md, hashbuf);
memcpy(pool, hashbuf, 20 );
p = pool;
for( n=1; n < POOLBLOCKS; n++ ) {
memcpy(hashbuf, p, DIGESTLEN );
p += DIGESTLEN;
if( p+DIGESTLEN+BLOCKLEN < pend )
memcpy(hashbuf+DIGESTLEN, p+DIGESTLEN, BLOCKLEN-DIGESTLEN);
else {
char *pp = p+DIGESTLEN;
for(i=DIGESTLEN; i < BLOCKLEN; i++ ) {
if( pp >= pend )
pp = pool;
hashbuf[i] = *pp++;
}
}
rmd160_mixblock( &md, hashbuf);
memcpy(p, hashbuf, 20 );
}
}
static void
read_pool( byte *buffer, size_t length, int level )
{
int i;
ulong *sp, *dp;
if( length >= POOLSIZE )
BUG(); /* not allowed */
if( !level ) { /* read simple random bytes */
read_dev_random( buffer, length, level );
return;
}
/* always do a random poll if we need strong numbers */
if( pool_filled && level == 2 )
random_poll();
/* make sure the pool is filled */
while( !pool_filled )
random_poll();
/* do always a fast random poll */
fast_random_poll();
/* mix the pool (if add_randomness() didn't it) */
if( !just_mixed )
mix_pool(rndpool);
/* create a new pool */
for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool;
i < POOLWORDS; i++, dp++, sp++ )
*dp = *sp + ADD_VALUE;
/* and mix both pools */
mix_pool(rndpool);
mix_pool(keypool);
/* read the required data
* we use a readpoiter to read from a different postion each
* time */
while( length-- ) {
*buffer++ = keypool[pool_readpos++];
if( pool_readpos >= POOLSIZE )
pool_readpos = 0;
}
/* and clear the keypool */
memset( keypool, 0, POOLSIZE );
}
/****************
* Add LENGTH bytes of randomness from buffer to the pool.
* source may be used to specify the randomeness source.
*/
void
add_randomness( const void *buffer, size_t length, int source )
{
if( !is_initialized )
initialize();
while( length-- ) {
rndpool[pool_writepos++] = *((byte*)buffer)++;
if( pool_writepos >= POOLSIZE ) {
pool_filled = 1;
pool_writepos = 0;
mix_pool(rndpool);
just_mixed = !length;
}
}
}
/********************
* FIXME: move these functions to rand_unix.c
*/
void
random_poll()
{
char buf[POOLSIZE/5];
read_dev_random( buf, POOLSIZE/5, 1 ); /* read /dev/urandom */
add_randomness( buf, POOLSIZE/5, 2);
memset( buf, 0, POOLSIZE/5);
}
void
fast_random_poll()
{
#ifdef HAVE_GETTIMEOFTIME
{ struct timeval tv;
if( gettimeofday( &tv, NULL ) )
BUG();
add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 );
add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), 1 );
}
#else /* use times */
{ struct tms buf;
times( &buf );
add_randomness( &buf, sizeof buf, 1 );
}
#endif
#ifdef HAVE_GETRUSAGE
{ struct rusage buf;
if( getrusage( RUSAGE_SELF, &buf ) )
BUG();
add_randomness( &buf, sizeof buf, 1 );
memset( &buf, 0, sizeof buf );
}
#endif
}
#ifdef HAVE_DEV_RANDOM
@ -111,7 +343,7 @@ open_device( const char *name, int minor )
static void
fill_buffer( byte *buffer, size_t length, int level )
read_dev_random( byte *buffer, size_t length, int level )
{
static int fd_urandom = -1;
static int fd_random = -1;
@ -125,6 +357,9 @@ fill_buffer( byte *buffer, size_t length, int level )
fd = fd_random;
}
else {
/* fixme: we should use a simpler one for level 0,
* because reading from /dev/urandom removes entropy
* and the next read on /dev/random may have to wait */
if( fd_urandom == -1 )
fd_urandom = open_device( "/dev/urandom", 9 );
fd = fd_urandom;
@ -154,7 +389,7 @@ fill_buffer( byte *buffer, size_t length, int level )
continue;
}
assert( length < 200 );
assert( length < 500 );
do {
n = read(fd, buffer, length );
if( n >= 0 && n > length ) {
@ -178,7 +413,7 @@ fill_buffer( byte *buffer, size_t length, int level )
#endif
static void
fill_buffer( byte *buffer, size_t length, int level )
read_dev_random( byte *buffer, size_t length, int level )
{
static int initialized=0;

39
cipher/random.h Normal file
View File

@ -0,0 +1,39 @@
/* random.h - random functions
* Copyright (C) 1998 Free Software Foundation, Inc.
*
* This file is part of GNUPG.
*
* GNUPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GNUPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifndef G10_RANDOM_H
#define G10_RANDOM_H
#include "types.h"
/*-- random.c --*/
void secure_random_alloc(void);
int quick_random_gen( int onoff );
void randomize_buffer( byte *buffer, size_t length, int level );
byte get_random_byte( int level );
void add_randomness( const void *buffer, size_t length, int source );
/*-- the next two functions are implemented by all the system
specific source files rand_xxxx.s --*/
void random_poll(void);
void fast_random_poll(void);
#endif /*G10_RANDOM_H*/

View File

@ -33,6 +33,7 @@ typedef struct {
void rmd160_init( RMD160_CONTEXT *c );
void rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen);
void rmd160_final(RMD160_CONTEXT *hd);
void rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer );
#define rmd160_read(h) ( (h)->buf )
#endif /*G10_RMD_H*/

View File

@ -300,6 +300,27 @@ rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen)
}
/****************
* Apply the rmd160 transform function on the buffer which must have
* a length 64 bytes. Do not use this function together with the
* other functions, use rmd160_init to initialize intzernal variables.
* Returns: 16 bytes in buffer with the mixed contentes of buffer.
*/
void
rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer )
{
char *p = buffer;
transform( hd, buffer );
#define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0)
X(0);
X(1);
X(2);
X(3);
X(4);
#undef X
}
/* The routine terminates the computation
*/

View File

@ -142,6 +142,12 @@
/* Define if you have the getpagesize function. */
#undef HAVE_GETPAGESIZE
/* Define if you have the getrusage function. */
#undef HAVE_GETRUSAGE
/* Define if you have the gettimeofday function. */
#undef HAVE_GETTIMEOFDAY
/* Define if you have the mlock function. */
#undef HAVE_MLOCK

View File

@ -133,6 +133,7 @@ fi
dnl Checks for library functions.
AC_FUNC_VPRINTF
AC_CHECK_FUNCS(strerror stpcpy strlwr tcgetattr rand strtoul mlock mmap)
AC_CHECK_FUNCS(gettimeofday getrusage)

View File

@ -32,13 +32,30 @@ B<-c>, B<--symmetric>
This command asks for a passphrase.
B<--store>
store only (make a RFC1991 packet).
store only (make a simple RFC1991 packet).
B<-d>, B<--decrypt>
Decrypt data. This is the default operation for data
files.
B<--decrypt> [I<file>]
Decrypt file (or stdin if no file is specified) and
write it to stdout (or the file specified with
B<--output>). If the decrypted file is signed, the
signature is also verified. This command differs
from the default operation, as it never write to the
filename which is included in the file and that it
rejects files which don't begin with an encrypted
message.
B<-k> [I<keyring>]
B<--verify> [[I<sigfile>] {I<signed-files>}]
Assume that I<filename> is a signature and verify it
without generating any output. With no arguments,
the signature packet is read from stdin (it may be a
detached signature when not used in batch mode). If
only a sigfile is given, is maybe a complete signature
or a detached signature in which case the signed stuff
is expected from stdin. With more than 1 argument, the
first should be a detached signature and the remaining
files are the signed stuff.
B<-k> [I<username>] [I<keyring>]
Kludge to be somewhat compatibe to PGP.
Without arguments, all public key-rings are listed,
with one argument, only I<keyring> is listed.
@ -50,15 +67,21 @@ B<-k> [I<keyring>]
B<-kvc> List fingerprints
B<-kvvc> List fingerprints and signatures
B<--list-keys>
List all keys in all public key-rings and check the
signatures.
B<--list-keys> [I<names>]
List all keys from the default public keyring or just the ones
given on the commandline.
B<--check-keys>
Check signatures on a key in the keyring
B<--list-sigs> [I<names>]
Same as B<--list-keys>, but the signatures are listed too.
B<--fingerprint>
Show the fingerprints
B<--check-sigs> [I<names>]
Same as B<--list-sigs>, but the signatures are verified.
B<--fingerprint> [I<names>]
List all keys with their fingerprints. This is the
same output as B<list-keys> but with the additonal output
of a line with the fingerprint. May also be combined
with B<--list-sigs> or B<--check-sigs>.
B<--list-packets>
List only the sequence of packets. This is mainly
@ -84,7 +107,10 @@ B<--sign-key> I<name>
B<--delete-key>
Remove key from the public keyring
B<--edit-sig>
B<--delete-secret-key>
Remove key from the secret and public keyring
B<--edit-key>
Edit/remove a key signature.
B<--change-passphrase>
@ -124,9 +150,13 @@ B<-o> I<file>, B<--output> I<file>
B<-u> I<name>, B<--local-user> I<name>
Use I<name> as the user-id to sign.
This option is silently ignored for the list commands,
so that it can be used in an options file.
B<-r> I<name>, B<--remote-user> I<name>
Use I<name> as the user-id for encryption.
Use I<name> as the user-id for encryption.
This option is silently ignored for the list commands,
so that it can be used in an options file.
B<-v>, B<--verbose>
Give more informations during processing. If used
@ -181,7 +211,7 @@ B<--options> I<file>
(see B<--homedir>). This option is ignored when used
in an options file.
B<no-options>
B<--no-options>
Shortcut for B<--options> I</dev/null>. This option is
detected before an attempt to open an option file.
@ -227,17 +257,17 @@ B<--passphrase-fd> I<n>
can only be used if only one passphrase is supplied.
B<Don't use this option if you can avoid it>
B<no-verbose>
B<--no-verbose>
Reset verbose level to 0.
B<no-greeting>
B<--no-greeting>
Suppress the initial copyright message but do not
enter batch mode.
B<no-armor>
B<--no-armor>
Assume the input data is not in ASCCI armored format.
B<no-default-keyring>
B<--no-default-keyring>
Do not add the default key-rings to the list of
key-rings.
@ -245,6 +275,9 @@ B<--version>
Print version information along with a list
of supported algorithms.
B<--with-colons>
Print key listings delimited by colons.
B<--warranty>
Print warranty information.

View File

@ -1,3 +1,49 @@
Mon Mar 9 12:43:42 1998 Werner Koch (wk@isil.d.shuttle.de)
* dsa.c: New
* packet.h, free-packet.c, parse-packet.c : Add support for DSA
* sig-check.c, getkey.c, keyid.c, ringedit.c: Ditto.
* seckey-cert.c: Ditto.
* packet.h : Moved .digest_algo of signature packets to outer
structure. Changed all references
Sun Mar 8 13:06:42 1998 Werner Koch (wk@isil.d.shuttle.de)
* openfile.c : Support for stdout filename "-".
* mainproc.c (check_sig_and_print): Enhanced status output:
* status.c (write_status_text): New.
Fri Mar 6 16:10:54 1998 Werner Koch (wk@isil.d.shuttle.de)
* kbnode.c (clone_kbnode): Fixed private_flag.
* mainproc.c (list_node): Output of string "Revoked" as user-id.
Fri Mar 6 14:26:39 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (main): Add userids to "-kv" and cleaned up this stuff.
Fri Mar 6 12:45:58 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (main): Changed semantics of the list-... commands
and added a new one. Removed option "-d"
* decrypt.c: New.
* trustdb.c (init_trustdb): Autocreate directory only if it ends
in "/.gnupg".
Thu Mar 5 12:12:11 1998 Werner Koch (wk@isil.d.shuttle.de)
* mainproc.c (do_proc_packets): New. Common part of proc_packet.
(proc_signature_packets): special version to handle signature data.
* verify.c: New.
* g10.c (aVerify): New.
* plaintext.c (hash_datafiles): New.
* compress.c (handle_compressed): Add callback arg, changed caller.
Thu Mar 5 10:20:06 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c: Is nom the common source for gpg and gpgm

View File

@ -26,6 +26,7 @@ common_source = \
textfilter.c \
cipher.c \
elg.c \
dsa.c \
rsa.c \
options.h \
openfile.c \
@ -48,16 +49,18 @@ common_source = \
encr-data.c \
encode.c \
revoke.c \
keylist.c \
sig-check.c
gpg_SOURCES = g10.c \
$(common_source) \
verify.c \
decrypt.c \
keygen.c
gpgm_SOURCES = g10maint.c \
dearmor.c \
keylist.c \
$(common_source)
LDADD = @INTLLIBS@ $(needed_libs) @ZLIBS@

View File

@ -118,6 +118,7 @@ common_source = \
textfilter.c \
cipher.c \
elg.c \
dsa.c \
rsa.c \
options.h \
openfile.c \
@ -140,15 +141,17 @@ common_source = \
encr-data.c \
encode.c \
revoke.c \
keylist.c \
sig-check.c
gpg_SOURCES = g10.c \
$(common_source) \
verify.c \
decrypt.c \
keygen.c
gpgm_SOURCES = g10maint.c \
dearmor.c \
keylist.c \
$(common_source)
LDADD = @INTLLIBS@ $(needed_libs) @ZLIBS@
@ -164,20 +167,20 @@ LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
gpg_OBJECTS = g10.o build-packet.o compress.o free-packet.o getkey.o \
pkclist.o skclist.o ringedit.o kbnode.o mainproc.o armor.o mdfilter.o \
textfilter.o cipher.o elg.o rsa.o openfile.o keyid.o trustdb.o \
textfilter.o cipher.o elg.o dsa.o rsa.o openfile.o keyid.o trustdb.o \
parse-packet.o passphrase.o pubkey-enc.o seckey-cert.o seskey.o \
import.o export.o comment.o status.o sign.o plaintext.o encr-data.o \
encode.o revoke.o sig-check.o keygen.o
encode.o revoke.o keylist.o sig-check.o verify.o decrypt.o keygen.o
gpg_LDADD = $(LDADD)
gpg_DEPENDENCIES = ../cipher/libcipher.a ../mpi/libmpi.a \
../util/libutil.a
gpg_LDFLAGS =
gpgm_OBJECTS = g10maint.o dearmor.o keylist.o build-packet.o compress.o \
gpgm_OBJECTS = g10maint.o dearmor.o build-packet.o compress.o \
free-packet.o getkey.o pkclist.o skclist.o ringedit.o kbnode.o \
mainproc.o armor.o mdfilter.o textfilter.o cipher.o elg.o rsa.o \
mainproc.o armor.o mdfilter.o textfilter.o cipher.o elg.o dsa.o rsa.o \
openfile.o keyid.o trustdb.o parse-packet.o passphrase.o pubkey-enc.o \
seckey-cert.o seskey.o import.o export.o comment.o status.o sign.o \
plaintext.o encr-data.o encode.o revoke.o sig-check.o
plaintext.o encr-data.o encode.o revoke.o keylist.o sig-check.o
gpgm_LDADD = $(LDADD)
gpgm_DEPENDENCIES = ../cipher/libcipher.a ../mpi/libmpi.a \
../util/libutil.a
@ -193,16 +196,16 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP = --best
DEP_FILES = .deps/armor.P .deps/build-packet.P .deps/cipher.P \
.deps/comment.P .deps/compress.P .deps/dearmor.P .deps/elg.P \
.deps/encode.P .deps/encr-data.P .deps/export.P .deps/free-packet.P \
.deps/g10.P .deps/g10maint .deps/g10maint.P .deps/getkey.P \
.deps/import.P .deps/kbnode.P .deps/keygen.P .deps/keyid.P \
.deps/keylist.P .deps/mainproc.P .deps/mdfilter.P .deps/openfile.P \
.deps/parse-packet.P .deps/passphrase.P .deps/pkclist.P \
.deps/plaintext.P .deps/pubkey-enc.P .deps/revoke.P .deps/ringedit.P \
.deps/rsa.P .deps/seckey-cert.P .deps/seskey.P .deps/sig-check.P \
.deps/sign.P .deps/skclist.P .deps/status.P .deps/textfilter.P \
.deps/trustdb.P
.deps/comment.P .deps/compress.P .deps/dearmor.P .deps/decrypt.P \
.deps/dsa.P .deps/elg.P .deps/encode.P .deps/encr-data.P .deps/export.P \
.deps/free-packet.P .deps/g10.P .deps/g10maint .deps/g10maint.P \
.deps/getkey.P .deps/import.P .deps/kbnode.P .deps/keygen.P \
.deps/keyid.P .deps/keylist.P .deps/mainproc.P .deps/mdfilter.P \
.deps/openfile.P .deps/parse-packet.P .deps/passphrase.P \
.deps/pkclist.P .deps/plaintext.P .deps/pubkey-enc.P .deps/revoke.P \
.deps/ringedit.P .deps/rsa.P .deps/seckey-cert.P .deps/seskey.P \
.deps/sig-check.P .deps/sign.P .deps/skclist.P .deps/status.P \
.deps/textfilter.P .deps/trustdb.P .deps/verify.P
SOURCES = $(gpg_SOURCES) $(gpgm_SOURCES)
OBJECTS = $(gpg_OBJECTS) $(gpgm_OBJECTS)

View File

@ -322,7 +322,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
buf[--n] = 0;
if( opt.verbose ) {
log_info("armor header: ");
print_string( stderr, buf, n );
print_string( stderr, buf, n, 0 );
putc('\n', stderr);
}
if( clearsig && !parse_hash_header( buf ) ) {
@ -348,7 +348,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
}
else {
log_error("invalid armor header: ");
print_string( stderr, buf, n );
print_string( stderr, buf, n, 0 );
putc('\n', stderr);
state = fhdrERROR;
}
@ -357,7 +357,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
if( strchr( buf, ':') ) { /* buffer to short, but this is okay*/
if( opt.verbose ) {
log_info("armor header: ");
print_string( stderr, buf, n );
print_string( stderr, buf, n, 0 );
fputs("[...]\n", stderr); /* indicate it is truncated */
}
state = fhdrSKIPHeader; /* skip rest of line */
@ -462,7 +462,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
}
else {
log_error("invalid dash escaped line: ");
print_string( stderr, buf, n );
print_string( stderr, buf, n, 0 );
putc('\n', stderr);
state = fhdrERROR;
}
@ -531,7 +531,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
case fhdrERRORShow:
log_error("invalid clear text header: ");
print_string( stderr, buf, n );
print_string( stderr, buf, n, 0 );
putc('\n', stderr);
state = fhdrERROR;
break;

View File

@ -175,13 +175,20 @@ do_public_cert( IOBUF out, int ctb, PKT_public_cert *pkc )
else
iobuf_put( a, pkc->version );
write_32(a, pkc->timestamp );
write_16(a, pkc->valid_days );
if( pkc->version < 4 )
write_16(a, pkc->valid_days );
iobuf_put(a, pkc->pubkey_algo );
if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
mpi_write(a, pkc->d.elg.p );
mpi_write(a, pkc->d.elg.g );
mpi_write(a, pkc->d.elg.y );
}
else if( pkc->pubkey_algo == PUBKEY_ALGO_DSA ) {
mpi_write(a, pkc->d.dsa.p );
mpi_write(a, pkc->d.dsa.q );
mpi_write(a, pkc->d.dsa.g );
mpi_write(a, pkc->d.dsa.y );
}
else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
mpi_write(a, pkc->d.rsa.rsa_n );
mpi_write(a, pkc->d.rsa.rsa_e );
@ -253,7 +260,8 @@ do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc )
else
iobuf_put( a, skc->version );
write_32(a, skc->timestamp );
write_16(a, skc->valid_days );
if( skc->version < 4 )
write_16(a, skc->valid_days );
iobuf_put(a, skc->pubkey_algo );
if( skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
mpi_write(a, skc->d.elg.p );
@ -416,24 +424,35 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig )
int rc = 0;
IOBUF a = iobuf_temp();
write_version( a, ctb );
iobuf_put(a, 5 ); /* constant */
if( !sig->version )
iobuf_put( a, 3 );
else
iobuf_put( a, sig->version );
if( sig->version < 4 )
iobuf_put(a, 5 ); /* constant */
iobuf_put(a, sig->sig_class );
write_32(a, sig->timestamp );
write_32(a, sig->keyid[0] );
write_32(a, sig->keyid[1] );
if( sig->version < 4 ) {
write_32(a, sig->timestamp );
write_32(a, sig->keyid[0] );
write_32(a, sig->keyid[1] );
}
iobuf_put(a, sig->pubkey_algo );
iobuf_put(a, sig->digest_algo );
if( sig->version >= 4 ) {
/* fixme: write v4 subpackets here */
log_error("WARNING: note writing of v4 subpackets is not implemented\n");
}
iobuf_put(a, sig->digest_start[0] );
iobuf_put(a, sig->digest_start[1] );
if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
iobuf_put(a, sig->d.elg.digest_algo );
iobuf_put(a, sig->d.elg.digest_start[0] );
iobuf_put(a, sig->d.elg.digest_start[1] );
mpi_write(a, sig->d.elg.a );
mpi_write(a, sig->d.elg.b );
}
else if( sig->pubkey_algo == PUBKEY_ALGO_DSA ) {
mpi_write(a, sig->d.dsa.r );
mpi_write(a, sig->d.dsa.s );
}
else if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) {
iobuf_put(a, sig->d.rsa.digest_algo );
iobuf_put(a, sig->d.rsa.digest_start[0] );
iobuf_put(a, sig->d.rsa.digest_start[1] );
mpi_write(a, sig->d.rsa.rsa_integer );
}
else {

View File

@ -230,9 +230,11 @@ compress_filter( void *opaque, int control,
* Handle a compressed packet
*/
int
handle_compressed( PKT_compressed *cd )
handle_compressed( PKT_compressed *cd,
int (*callback)(IOBUF, void *), void *passthru )
{
compress_filter_context_t cfx;
int rc;
memset( &cfx, 0, sizeof cfx );
if( cd->algorithm == 1 )
@ -241,7 +243,10 @@ handle_compressed( PKT_compressed *cd )
return G10ERR_COMPR_ALGO;
iobuf_push_filter( cd->buf, compress_filter, &cfx );
proc_packets(cd->buf);
if( callback )
rc = callback(cd->buf, passthru );
else
rc = proc_packets(cd->buf);
iobuf_pop_filter( cd->buf, compress_filter, &cfx );
#if 0
if( cd->len )
@ -250,6 +255,6 @@ handle_compressed( PKT_compressed *cd )
iobuf_clear_eof( cd->buf );
#endif
cd->buf = NULL;
return 0;
return rc;
}

82
g10/decrypt.c Normal file
View File

@ -0,0 +1,82 @@
/* verify.c - verify signed data
* Copyright (C) 1998 Free Software Foundation, Inc.
*
* This file is part of GNUPG.
*
* GNUPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GNUPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include "options.h"
#include "packet.h"
#include "errors.h"
#include "iobuf.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "main.h"
#include "i18n.h"
/****************
* Assume that the input is an encrypted message and decrypt
* (and if signed, verify the signature) it.
* This command differs from the default operation, as it never
* write to the filename which is included in the file and that it
* rejects files which don't begin with an encrypted message.
*/
int
decrypt_message( const char *filename )
{
IOBUF fp;
armor_filter_context_t afx;
int rc;
int no_out=0;
/* open the message file */
fp = iobuf_open(filename);
if( !fp ) {
log_error(_("can't open '%s'\n"), print_fname_stdin(filename));
return G10ERR_OPEN_FILE;
}
if( !opt.no_armor ) {
if( use_armor_filter( fp ) ) {
memset( &afx, 0, sizeof afx);
iobuf_push_filter( fp, armor_filter, &afx );
}
}
if( !opt.outfile ) {
no_out = 1;
opt.outfile = "-";
}
rc = proc_encryption_packets( fp );
if( no_out )
opt.outfile = NULL;
iobuf_close(fp);
return rc;
}

71
g10/dsa.c Normal file
View File

@ -0,0 +1,71 @@
/* dsa.c
* Copyright (C) 1998 Free Software Foundation, Inc.
*
* This file is part of GNUPG.
*
* GNUPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GNUPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include "options.h"
#include "packet.h"
#include "errors.h"
#include "iobuf.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "main.h"
void
g10_dsa_sign( PKT_secret_cert *skc, PKT_signature *sig,
MD_HANDLE md, int digest_algo )
{
DSA_secret_key skey;
MPI frame;
byte *dp;
assert( sig->pubkey_algo == PUBKEY_ALGO_DSA );
if( !digest_algo )
digest_algo = md_get_algo(md);
dp = md_read( md, digest_algo );
keyid_from_skc( skc, sig->keyid );
sig->digest_algo = digest_algo;
sig->digest_start[0] = dp[0];
sig->digest_start[1] = dp[1];
sig->d.dsa.r = mpi_alloc( mpi_get_nlimbs(skc->d.dsa.p) );
sig->d.dsa.s = mpi_alloc( mpi_get_nlimbs(skc->d.dsa.p) );
frame = encode_md_value( md, mpi_get_nbits(skc->d.dsa.p));
skey.p = skc->d.elg.p;
skey.g = skc->d.elg.g;
skey.y = skc->d.elg.y;
skey.x = skc->d.elg.x;
dsa_sign( sig->d.dsa.r, sig->d.dsa.s, frame, &skey);
memset( &skey, 0, sizeof skey );
mpi_free(frame);
if( opt.verbose ) {
char *ustr = get_user_id_string( sig->keyid );
log_info("DSA signature from: %s\n", ustr );
m_free(ustr);
}
}

View File

@ -79,9 +79,9 @@ g10_elg_sign( PKT_secret_cert *skc, PKT_signature *sig,
dp = md_read( md, digest_algo );
keyid_from_skc( skc, sig->keyid );
sig->d.elg.digest_algo = digest_algo;
sig->d.elg.digest_start[0] = dp[0];
sig->d.elg.digest_start[1] = dp[1];
sig->digest_algo = digest_algo;
sig->digest_start[0] = dp[0];
sig->digest_start[1] = dp[1];
sig->d.elg.a = mpi_alloc( mpi_get_nlimbs(skc->d.elg.p) );
sig->d.elg.b = mpi_alloc( mpi_get_nlimbs(skc->d.elg.p) );
frame = encode_md_value( md, mpi_get_nbits(skc->d.elg.p));

View File

@ -45,31 +45,41 @@ free_pubkey_enc( PKT_pubkey_enc *enc )
}
void
free_seckey_enc( PKT_signature *enc )
free_seckey_enc( PKT_signature *sig )
{
if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
mpi_free( enc->d.elg.a );
mpi_free( enc->d.elg.b );
if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
mpi_free( sig->d.elg.a );
mpi_free( sig->d.elg.b );
}
else if( enc->pubkey_algo == PUBKEY_ALGO_RSA )
mpi_free( enc->d.rsa.rsa_integer );
m_free(enc);
else if( sig->pubkey_algo == PUBKEY_ALGO_DSA ) {
mpi_free( sig->d.dsa.r );
mpi_free( sig->d.dsa.s );
}
else if( sig->pubkey_algo == PUBKEY_ALGO_RSA )
mpi_free( sig->d.rsa.rsa_integer );
m_free(sig->hashed_data);
m_free(sig->unhashed_data);
m_free(sig);
}
/****************
* Return the digest algorith from the signature packet.
* Return the digest algorithm from the signature packet.
* We need this function because the digeste algo depends on the
* used pubkey algorithm.
*/
int
digest_algo_from_sig( PKT_signature *sig )
{
#if 0 /* not used anymore */
switch( sig->pubkey_algo ) {
case PUBKEY_ALGO_ELGAMAL: return sig->d.elg.digest_algo;
case PUBKEY_ALGO_DSA: return sig->d.dsa.digest_algo;
case PUBKEY_ALGO_RSA: return sig->d.rsa.digest_algo;
default: return 0;
}
#endif
return sig->digest_algo;
}
@ -83,6 +93,12 @@ release_public_cert_parts( PKT_public_cert *cert )
mpi_free( cert->d.elg.g ); cert->d.elg.g = NULL;
mpi_free( cert->d.elg.y ); cert->d.elg.y = NULL;
}
else if( cert->pubkey_algo == PUBKEY_ALGO_DSA ) {
mpi_free( cert->d.dsa.p ); cert->d.dsa.p = NULL;
mpi_free( cert->d.dsa.q ); cert->d.dsa.q = NULL;
mpi_free( cert->d.dsa.g ); cert->d.dsa.g = NULL;
mpi_free( cert->d.dsa.y ); cert->d.dsa.y = NULL;
}
else if( cert->pubkey_algo == PUBKEY_ALGO_RSA ) {
mpi_free( cert->d.rsa.rsa_n ); cert->d.rsa.rsa_n = NULL;
mpi_free( cert->d.rsa.rsa_e ); cert->d.rsa.rsa_e = NULL;
@ -107,6 +123,12 @@ copy_public_cert( PKT_public_cert *d, PKT_public_cert *s )
d->d.elg.g = mpi_copy( s->d.elg.g );
d->d.elg.y = mpi_copy( s->d.elg.y );
}
else if( s->pubkey_algo == PUBKEY_ALGO_DSA ) {
d->d.dsa.p = mpi_copy( s->d.dsa.p );
d->d.dsa.q = mpi_copy( s->d.dsa.q );
d->d.dsa.g = mpi_copy( s->d.dsa.g );
d->d.dsa.y = mpi_copy( s->d.dsa.y );
}
else if( s->pubkey_algo == PUBKEY_ALGO_RSA ) {
d->d.rsa.rsa_n = mpi_copy( s->d.rsa.rsa_n );
d->d.rsa.rsa_e = mpi_copy( s->d.rsa.rsa_e );
@ -123,6 +145,13 @@ release_secret_cert_parts( PKT_secret_cert *cert )
mpi_free( cert->d.elg.y ); cert->d.elg.y = NULL;
mpi_free( cert->d.elg.x ); cert->d.elg.x = NULL;
}
else if( cert->pubkey_algo == PUBKEY_ALGO_DSA ) {
mpi_free( cert->d.dsa.p ); cert->d.dsa.p = NULL;
mpi_free( cert->d.dsa.q ); cert->d.dsa.q = NULL;
mpi_free( cert->d.dsa.g ); cert->d.dsa.g = NULL;
mpi_free( cert->d.dsa.y ); cert->d.dsa.y = NULL;
mpi_free( cert->d.dsa.x ); cert->d.dsa.x = NULL;
}
else if( cert->pubkey_algo == PUBKEY_ALGO_RSA ) {
mpi_free( cert->d.rsa.rsa_n ); cert->d.rsa.rsa_n = NULL;
mpi_free( cert->d.rsa.rsa_e ); cert->d.rsa.rsa_e = NULL;
@ -152,6 +181,13 @@ copy_secret_cert( PKT_secret_cert *d, PKT_secret_cert *s )
d->d.elg.y = mpi_copy( s->d.elg.y );
d->d.elg.x = mpi_copy( s->d.elg.x );
}
else if( s->pubkey_algo == PUBKEY_ALGO_DSA ) {
d->d.dsa.p = mpi_copy( s->d.dsa.p );
d->d.dsa.q = mpi_copy( s->d.dsa.q );
d->d.dsa.g = mpi_copy( s->d.dsa.g );
d->d.dsa.y = mpi_copy( s->d.dsa.y );
d->d.dsa.x = mpi_copy( s->d.dsa.x );
}
else if( s->pubkey_algo == PUBKEY_ALGO_RSA ) {
d->d.rsa.rsa_n = mpi_copy( s->d.rsa.rsa_n );
d->d.rsa.rsa_e = mpi_copy( s->d.rsa.rsa_e );
@ -290,6 +326,16 @@ cmp_public_certs( PKT_public_cert *a, PKT_public_cert *b )
if( mpi_cmp( a->d.elg.y , b->d.elg.y ) )
return -1;
}
else if( a->pubkey_algo == PUBKEY_ALGO_DSA ) {
if( mpi_cmp( a->d.dsa.p , b->d.dsa.p ) )
return -1;
if( mpi_cmp( a->d.dsa.q , b->d.dsa.q ) )
return -1;
if( mpi_cmp( a->d.dsa.g , b->d.dsa.g ) )
return -1;
if( mpi_cmp( a->d.dsa.y , b->d.dsa.y ) )
return -1;
}
else if( a->pubkey_algo == PUBKEY_ALGO_RSA ) {
if( mpi_cmp( a->d.rsa.rsa_n , b->d.rsa.rsa_n ) )
return -1;
@ -321,6 +367,16 @@ cmp_public_secret_cert( PKT_public_cert *pkc, PKT_secret_cert *skc )
if( mpi_cmp( pkc->d.elg.y , skc->d.elg.y ) )
return -1;
}
else if( pkc->pubkey_algo == PUBKEY_ALGO_DSA ) {
if( mpi_cmp( pkc->d.dsa.p , skc->d.dsa.p ) )
return -1;
if( mpi_cmp( pkc->d.dsa.q , skc->d.dsa.q ) )
return -1;
if( mpi_cmp( pkc->d.dsa.g , skc->d.dsa.g ) )
return -1;
if( mpi_cmp( pkc->d.dsa.y , skc->d.dsa.y ) )
return -1;
}
else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
if( mpi_cmp( pkc->d.rsa.rsa_n , skc->d.rsa.rsa_n ) )
return -1;

157
g10/g10.c
View File

@ -63,9 +63,13 @@ static ARGPARSE_OPTS opts[] = {
{ 'c', "symmetric", 0, N_("encryption only with symmetric cipher")},
{ 507, "store", 0, N_("store only")},
{ 'd', "decrypt", 0, N_("decrypt data (default)")},
{ 'k', "list-keys", 0, N_("list keys")},
{ 508, "check-keys",0, N_("check signatures on a key in the keyring")},
{ 515, "fingerprint", 0, N_("show the fingerprints")},
{ 550, "verify" , 0, N_("verify a signature")},
#endif
{ 551, "list-keys", 0, N_("list keys")},
{ 552, "list-sigs", 0, N_("list keys and signatures")},
{ 508, "check-sigs",0, N_("check key signatures")},
{ 515, "fingerprint", 0, N_("list keys and fingerprints")},
#ifdef IS_G10
{ 503, "gen-key", 0, N_("generate a new key pair")},
{ 506, "sign-key" ,0, N_("make a signature on a key in the keyring")},
{ 505, "delete-key",0, N_("remove key from the public keyring")},
@ -82,7 +86,6 @@ static ARGPARSE_OPTS opts[] = {
{ 516, "print-mds" , 0, N_("print all message digests")},
{ 513, "gen-prime" , 0, "\r" },
{ 548, "gen-random" , 0, "\r" },
{ 549, "ext-list-keys", 0, "Print a parsable list of keys" },
#endif
{ 301, NULL, 0, N_("\v\nOptions:\n ") },
@ -132,6 +135,7 @@ static ARGPARSE_OPTS opts[] = {
{ 533, "list-trust-path",0, "\r"},
#endif
#ifdef IS_G10
{ 'k', NULL, 0, "\r"},
{ 504, "delete-secret-key",0, "\r" },
{ 524, "edit-sig" ,0, "\r"}, /* alias for edit-key */
{ 523, "passphrase-fd",1, "\r" },
@ -147,6 +151,10 @@ static ARGPARSE_OPTS opts[] = {
{ 543, "no-options", 0, "\r" }, /* shortcut for --options /dev/null */
{ 544, "homedir", 2, "\r" }, /* defaults to "~/.gnupg" */
{ 545, "no-batch", 0, "\r" },
{ 549, "with-colons", 0, "\r"},
{ 551, "list-key", 0, "\r" }, /* alias */
{ 552, "list-sig", 0, "\r" }, /* alias */
{ 508, "check-sig",0, "\r" }, /* alias */
{0} };
@ -157,8 +165,9 @@ static ARGPARSE_OPTS opts[] = {
enum cmd_values { aNull = 0,
aSym, aStore, aEncr, aKeygen, aSign, aSignEncr,
aSignKey, aClearsign, aListPackets, aEditSig, aDeleteKey, aDeleteSecretKey,
aKMode, aKModeC, aChangePass, aImport,
aExport, aCheckKeys, aGenRevoke, aPrimegen, aPrintMDs, aExtKeyList,
aKMode, aKModeC, aChangePass, aImport, aVerify, aDecrypt, aListKeys,
aListSigs,
aExport, aCheckKeys, aGenRevoke, aPrimegen, aPrintMDs,
aListTrustDB, aListTrustPath, aDeArmor, aEnArmor, aGenRandom, aTest,
aNOP };
@ -358,7 +367,7 @@ main( int argc, char **argv )
int rc=0;
int orig_argc;
char **orig_argv;
const char *fname, *fname_print;
const char *fname;
STRLIST sl, remusr= NULL, locusr=NULL;
int nrings=0, sec_nrings=0;
armor_filter_context_t afx;
@ -458,11 +467,10 @@ main( int argc, char **argv )
#ifdef IS_G10
case 'a': opt.armor = 1; opt.no_armor=0; break;
case 'b': detached_sig = 1; /* fall trough */
case 'c': set_cmd( &cmd , aSym); break;
case 'd': break; /* it is default */
case 'b': detached_sig = 1; set_cmd( &cmd, aSign ); break;
case 'c': set_cmd( &cmd, aSym); break;
case 'd': set_cmd( &cmd, aDecrypt); break;
case 'e': set_cmd( &cmd, aEncr); break;
case 'k': set_cmd( &cmd, aKMode ); break;
case 'r': /* store the remote users */
sl = m_alloc( sizeof *sl + strlen(pargs.r.ret_str));
strcpy(sl->d, pargs.r.ret_str);
@ -483,9 +491,6 @@ main( int argc, char **argv )
case 505: set_cmd( &cmd, aDeleteKey); break;
case 506: set_cmd( &cmd, aSignKey); break;
case 507: set_cmd( &cmd, aStore); break;
case 508: set_cmd( &cmd, aCheckKeys);
opt.check_sigs = 1; opt.list_sigs = 1; break;
case 515: opt.fingerprint = 1; 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;
@ -501,6 +506,7 @@ main( int argc, char **argv )
case 539: set_cmd( &cmd, aClearsign); break;
case 540: secmem_set_flags( secmem_get_flags() | 1 ); break;
case 542: set_cmd( &cmd, aGenRevoke); break;
case 550: set_cmd( &cmd, aVerify); break;
#endif /* IS_G10 */
#ifdef IS_G10MAINT
@ -513,19 +519,21 @@ main( int argc, char **argv )
case 546: set_cmd( &cmd, aDeArmor); break;
case 547: set_cmd( &cmd, aEnArmor); break;
case 548: set_cmd( &cmd, aGenRandom); break;
case 549: set_cmd( &cmd, aExtKeyList); break;
#endif /* IS_G10MAINT */
case 'o': opt.outfile = pargs.r.ret_str; break;
case 'v': opt.verbose++; opt.list_sigs=1; break;
case 'k': set_cmd( &cmd, aKMode ); break;
case 500: opt.batch = 1; greeting = 0; break;
case 501: opt.answer_yes = 1; break;
case 502: opt.answer_no = 1; break;
case 508: set_cmd( &cmd, aCheckKeys); break;
case 509: add_keyring(pargs.r.ret_str); nrings++; break;
case 510: opt.debug |= pargs.r.ret_ulong; break;
case 511: opt.debug = ~0; break;
case 512: set_status_fd( pargs.r.ret_int ); break;
case 515: opt.fingerprint = 1; break;
case 517: add_secret_keyring(pargs.r.ret_str); sec_nrings++; break;
case 518:
/* config files may not be nested (silently ignore them) */
@ -551,6 +559,9 @@ main( int argc, char **argv )
case 543: break; /* no-options */
case 544: opt.homedir = pargs.r.ret_str; break;
case 545: opt.batch = 0; break;
case 549: opt.with_colons=':'; break;
case 551: set_cmd( &cmd, aListKeys); break;
case 552: set_cmd( &cmd, aListSigs); break;
default : errors++; pargs.err = configfp? 1:2; break;
}
}
@ -576,9 +587,12 @@ main( int argc, char **argv )
/* Okay, we are now working under our real uid */
#endif
write_status( STATUS_ENTER );
/*write_status( STATUS_ENTER );*/
set_debug();
if( !cmd && opt.fingerprint )
set_cmd( &cmd, aListKeys);
if( cmd == aKMode || cmd == aKModeC ) { /* kludge to be compatible to pgp */
if( cmd == aKModeC ) {
opt.fingerprint = 1;
@ -593,6 +607,7 @@ main( int argc, char **argv )
opt.verbose = opt.verbose > 1;
}
/* kludge to let -sat generate a clear text signature */
if( opt.textmode && !detached_sig && opt.armor && cmd == aSign )
cmd = aClearsign;
@ -600,23 +615,24 @@ main( int argc, char **argv )
if( opt.verbose > 1 )
set_packet_list_mode(1);
if( cmd != aDeArmor && cmd != aEnArmor ) {
/* add the keyrings, but not for some special commands and
* not in case of "-kvv userid keyring" */
if( cmd != aDeArmor && cmd != aEnArmor
&& !(cmd == aKMode && argc == 2 ) ) {
if( !sec_nrings || default_keyring ) /* add default secret rings */
add_secret_keyring("secring.gpg");
if( !nrings || default_keyring ) /* add default ring */
add_keyring("pubring.gpg");
}
if( argc ) {
fname_print = fname = *argv;
}
if( argc )
fname = *argv;
else {
fname_print = "[stdin]";
fname = NULL;
if( get_passphrase_fd() == 0 ) {
/* reading data and passphrase form stdin:
* we assume the first line is the passphrase, so
* we read it now
* we better should read it now.
*/
/* FIXME: doit */
}
@ -629,6 +645,10 @@ main( int argc, char **argv )
case aDeArmor:
case aEnArmor:
break;
case aKMode:
case aListKeys:
case aCheckKeys:
break;
case aListTrustDB: rc = init_trustdb( argc? 1:0, trustdb_name ); break;
default: rc = init_trustdb(1, trustdb_name ); break;
}
@ -642,21 +662,22 @@ main( int argc, char **argv )
wrong_args(_("--store [filename]"));
if( (rc = encode_store(fname)) )
log_error("%s: store failed: %s\n",
fname_print, g10_errstr(rc) );
print_fname_stdin(fname), g10_errstr(rc) );
break;
#ifdef IS_G10
case aSym: /* encrypt the given file only with the symmetric cipher */
if( argc > 1 )
wrong_args(_("--symmetric [filename]"));
if( (rc = encode_symmetric(fname)) )
log_error("%s: symmetric encryption failed: %s\n", fname_print, g10_errstr(rc) );
log_error("%s: symmetric encryption failed: %s\n",
print_fname_stdin(fname), g10_errstr(rc) );
break;
case aEncr: /* encrypt the given file */
if( argc > 1 )
wrong_args(_("--encrypt [filename]"));
if( (rc = encode_crypt(fname,remusr)) )
log_error("%s: encryption failed: %s\n", fname_print, g10_errstr(rc) );
log_error("%s: encryption failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
break;
case aSign: /* sign the given file */
@ -688,7 +709,7 @@ main( int argc, char **argv )
else
sl = NULL;
if( (rc = sign_file(sl, detached_sig, locusr, 1, remusr, NULL)) )
log_error("%s: sign+encrypt failed: %s\n", fname_print, g10_errstr(rc) );
log_error("%s: sign+encrypt failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
free_strlist(sl);
break;
@ -696,7 +717,19 @@ main( int argc, char **argv )
if( argc > 1 )
wrong_args(_("--clearsign [filename]"));
if( (rc = clearsign_file(fname, locusr, NULL)) )
log_error("%s: clearsign failed: %s\n", fname_print, g10_errstr(rc) );
log_error("%s: clearsign failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
break;
case aVerify:
if( (rc = verify_signatures( argc, argv ) ))
log_error("verify signatures failed: %s\n", g10_errstr(rc) );
break;
case aDecrypt:
if( argc > 1 )
wrong_args(_("--decrypt [filename]"));
if( (rc = decrypt_message( fname ) ))
log_error("decrypt_message failed: %s\n", g10_errstr(rc) );
break;
@ -705,7 +738,7 @@ main( int argc, char **argv )
wrong_args(_("--sign-key username"));
/* note: fname is the user id! */
if( (rc = sign_key(fname, locusr)) )
log_error("%s: sign key failed: %s\n", fname_print, g10_errstr(rc) );
log_error("%s: sign key failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
break;
case aEditSig: /* Edit a key signature */
@ -713,7 +746,7 @@ main( int argc, char **argv )
wrong_args(_("--edit-sig username"));
/* note: fname is the user id! */
if( (rc = edit_keysigs(fname)) )
log_error("%s: edit signature failed: %s\n", fname_print, g10_errstr(rc) );
log_error("%s: edit signature failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
break;
case aDeleteSecretKey:
@ -724,7 +757,7 @@ main( int argc, char **argv )
wrong_args(_("--delete-key username"));
/* note: fname is the user id! */
if( (rc = delete_key(fname, cmd==aDeleteSecretKey)) )
log_error("%s: delete key failed: %s\n", fname_print, g10_errstr(rc) );
log_error("%s: delete key failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
break;
case aChangePass: /* Change the passphrase */
@ -732,51 +765,36 @@ main( int argc, char **argv )
wrong_args(_("--change-passphrase [username]"));
/* note: fname is the user id! */
if( (rc = change_passphrase(fname)) )
log_error("%s: change passphrase failed: %s\n", fname_print,
log_error("%s: change passphrase failed: %s\n", print_fname_stdin(fname),
g10_errstr(rc) );
break;
#endif /* IS_G10 */
case aCheckKeys:
opt.check_sigs = 1;
case aListSigs:
opt.list_sigs = 1;
case aListKeys:
std_key_list( argc, argv );
break;
case aKMode: /* list keyring */
if( !argc ) { /* list the default public keyrings */
int i, seq=0;
const char *s;
while( (s=get_keyring(seq++)) ) {
if( !(a = iobuf_open(s)) ) {
log_error(_("can't open '%s'\n"), s);
continue;
}
if( seq > 1 )
putchar('\n');
printf("%s\n", s );
for(i=strlen(s); i; i-- )
putchar('-');
putchar('\n');
proc_packets( a );
iobuf_close(a);
if( argc < 2 ) /* -kv [userid] */
std_key_list( (argc && **argv)? 1:0, argv );
else if( argc == 2 ) { /* -kv userid keyring */
if( access( argv[1], R_OK ) ) {
log_error(_("can't open %s: %s\n"),
print_fname_stdin(argv[1]), strerror(errno));
}
}
else if( cmd == aCheckKeys ) {
log_error("will be soon: --check-keys user-ids\n");
}
else if( argc == 1) { /* list the given keyring */
if( !(a = iobuf_open(fname)) )
log_error(_("can't open '%s'\n"), fname_print);
else {
if( !opt.no_armor ) {
memset( &afx, 0, sizeof afx);
iobuf_push_filter( a, armor_filter, &afx );
}
proc_packets( a );
iobuf_close(a);
/* add keyring (default keyrings are not registered in this
* special case */
add_keyring( argv[1] );
std_key_list( **argv?1:0, argv );
}
}
else
wrong_args(_("-k[v][v][v][c] [keyring]") );
wrong_args(_("-k[v][v][v][c] [userid] [keyring]") );
break;
#ifdef IS_G10
@ -901,13 +919,6 @@ main( int argc, char **argv )
list_trust_path( atoi(*argv), argv[1] );
break;
case aExtKeyList:
sl = NULL;
for( ; argc; argc--, argv++ )
add_to_strlist( &sl, *argv );
ext_key_list( sl );
free_strlist(sl);
break;
#endif /* IS_G10MAINT */
@ -921,7 +932,7 @@ main( int argc, char **argv )
if( argc > 1 )
wrong_args(_("[filename]"));
if( !(a = iobuf_open(fname)) )
log_error(_("can't open '%s'\n"), fname_print);
log_error(_("can't open '%s'\n"), print_fname_stdin(fname));
else {
if( !opt.no_armor ) {
if( use_armor_filter( a ) ) {
@ -953,7 +964,7 @@ g10_exit( int rc )
secmem_dump_stats();
secmem_term();
rc = rc? rc : log_get_errorcount(0)? 2:0;
write_status( STATUS_LEAVE );
/*write_status( STATUS_LEAVE );*/
exit(rc );
}

View File

@ -168,6 +168,7 @@ cache_public_cert( PKT_public_cert *pkc )
u32 keyid[2];
if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL
|| pkc->pubkey_algo == PUBKEY_ALGO_DSA
|| pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
keyid_from_pkc( pkc, keyid );
}
@ -545,6 +546,7 @@ scan_keyring( PKT_public_cert *pkc, u32 *keyid,
else if( keyid && pkt.pkttype == PKT_PUBLIC_CERT ) {
switch( pkt.pkt.public_cert->pubkey_algo ) {
case PUBKEY_ALGO_ELGAMAL:
case PUBKEY_ALGO_DSA:
case PUBKEY_ALGO_RSA:
keyid_from_pkc( pkt.pkt.public_cert, akeyid );
if( (shortkeyid || akeyid[0] == keyid[0])
@ -596,6 +598,7 @@ scan_keyring( PKT_public_cert *pkc, u32 *keyid,
pkt.pkt.user_id->len, pkt.pkt.user_id->name);
else {
if( last_pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL
|| last_pk->pubkey_algo == PUBKEY_ALGO_DSA
|| last_pk->pubkey_algo == PUBKEY_ALGO_RSA ) {
keyid_from_pkc( last_pk, akeyid );
cache_user_id( pkt.pkt.user_id, akeyid );
@ -657,6 +660,7 @@ scan_secret_keyring( PKT_secret_cert *skc, u32 *keyid,
else if( keyid && pkt.pkttype == PKT_SECRET_CERT ) {
switch( pkt.pkt.secret_cert->pubkey_algo ) {
case PUBKEY_ALGO_ELGAMAL:
case PUBKEY_ALGO_DSA:
case PUBKEY_ALGO_RSA:
if( get_first ) {
copy_secret_cert( skc, pkt.pkt.secret_cert );
@ -712,6 +716,7 @@ scan_secret_keyring( PKT_secret_cert *skc, u32 *keyid,
pkt.pkt.user_id->len, pkt.pkt.user_id->name);
else {
if( last_pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL
|| last_pk->pubkey_algo == PUBKEY_ALGO_DSA
|| last_pk->pubkey_algo == PUBKEY_ALGO_RSA ) {
keyid_from_skc( last_pk, akeyid );
cache_user_id( pkt.pkt.user_id, akeyid );

View File

@ -259,7 +259,7 @@ import_one( const char *fname, KBNODE keyblock )
(ulong)keyid[1], datestr_from_pkc(pkc) );
if( uidnode )
print_string( stderr, uidnode->pkt->pkt.user_id->name,
uidnode->pkt->pkt.user_id->len );
uidnode->pkt->pkt.user_id->len, 0 );
putc('\n', stderr);
}
if( !uidnode ) {
@ -532,7 +532,7 @@ delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid )
log_info("%s: key %08lX, removed userid '",
fname, (ulong)keyid[1]);
print_string( stderr, node->pkt->pkt.user_id->name,
node->pkt->pkt.user_id->len );
node->pkt->pkt.user_id->len, 0 );
fputs("'\n", stderr );
}
delete_kbnode( node ); /* the user-id */

View File

@ -48,8 +48,8 @@ clone_kbnode( KBNODE node )
KBNODE n = m_alloc( sizeof *n );
n->next = NULL;
n->pkt = node->pkt;
n->private_flag |= 2; /* mark cloned */
n->flag = 0;
n->private_flag = node->private_flag | 2; /* mark cloned */
return n;
}
@ -268,7 +268,7 @@ dump_kbnode( KBNODE node )
if( node->pkt->pkttype == PKT_USER_ID ) {
fputs(" \"", stderr);
print_string( stderr, node->pkt->pkt.user_id->name,
node->pkt->pkt.user_id->len );
node->pkt->pkt.user_id->len, 0 );
fputs("\"\n", stderr);
}
else if( node->pkt->pkttype == PKT_SIGNATURE ) {

View File

@ -105,6 +105,60 @@ v3_elg_fingerprint_md( PKT_public_cert *pkc )
return md;
}
static MD_HANDLE
dsa_fingerprint_md( PKT_public_cert *pkc )
{
MD_HANDLE md;
byte *buf1, *buf2, *buf3, *buf4 ;
byte *p1, *p2, *p3, *p4;
unsigned n1, n2, n3, n4;
unsigned nb1, nb2, nb3, nb4;
unsigned n;
nb1 = mpi_get_nbits(pkc->d.dsa.p);
p1 = buf1 = mpi_get_buffer( pkc->d.dsa.p, &n1, NULL );
for( ; !*p1 && n1; p1++, n1-- ) /* skip leading null bytes */
;
nb2 = mpi_get_nbits(pkc->d.dsa.q);
p2 = buf2 = mpi_get_buffer( pkc->d.dsa.q, &n2, NULL );
for( ; !*p2 && n2; p2++, n2-- )
;
nb3 = mpi_get_nbits(pkc->d.dsa.g);
p3 = buf3 = mpi_get_buffer( pkc->d.dsa.g, &n3, NULL );
for( ; !*p3 && n3; p3++, n3-- )
;
nb4 = mpi_get_nbits(pkc->d.dsa.y);
p4 = buf4 = mpi_get_buffer( pkc->d.dsa.y, &n4, NULL );
for( ; !*p4 && n4; p4++, n4-- )
;
/* calculate length of packet */
n = 14 + n1 + n2 + n3 +n4 ;
md = md_open( DIGEST_ALGO_SHA1, 0);
md_putc( md, 0x99 ); /* ctb */
md_putc( md, n >> 8 ); /* 2 byte length header */
md_putc( md, n );
md_putc( md, 4 ); /* version */
{ u32 a = pkc->timestamp;
md_putc( md, a >> 24 );
md_putc( md, a >> 16 );
md_putc( md, a >> 8 );
md_putc( md, a );
}
md_putc( md, pkc->pubkey_algo );
md_putc( md, nb1>>8); md_putc( md, nb1 ); md_write( md, p1, n1 );
md_putc( md, nb2>>8); md_putc( md, nb2 ); md_write( md, p2, n2 );
md_putc( md, nb3>>8); md_putc( md, nb3 ); md_write( md, p3, n3 );
md_putc( md, nb4>>8); md_putc( md, nb4 ); md_write( md, p4, n4 );
m_free(buf1);
m_free(buf2);
m_free(buf3);
m_free(buf4);
md_final( md );
return md;
}
static MD_HANDLE
v3_elg_fingerprint_md_skc( PKT_secret_cert *skc )
@ -121,6 +175,21 @@ v3_elg_fingerprint_md_skc( PKT_secret_cert *skc )
return v3_elg_fingerprint_md( &pkc );
}
static MD_HANDLE
dsa_fingerprint_md_skc( PKT_secret_cert *skc )
{
PKT_public_cert pkc;
pkc.pubkey_algo = skc->pubkey_algo;
pkc.timestamp = skc->timestamp;
pkc.pubkey_algo = skc->pubkey_algo;
pkc.d.dsa.p = skc->d.dsa.p;
pkc.d.dsa.q = skc->d.dsa.q;
pkc.d.dsa.g = skc->d.dsa.g;
pkc.d.dsa.y = skc->d.dsa.y;
return dsa_fingerprint_md( &pkc );
}
/****************
* Get the keyid from the secret key certificate and put it into keyid
@ -145,6 +214,16 @@ keyid_from_skc( PKT_secret_cert *skc, u32 *keyid )
lowbits = keyid[1];
md_close(md);
}
else if( skc->pubkey_algo == PUBKEY_ALGO_DSA ) {
const byte *dp;
MD_HANDLE md;
md = dsa_fingerprint_md_skc(skc);
dp = md_read( md, DIGEST_ALGO_SHA1 );
keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
lowbits = keyid[1];
md_close(md);
}
else if( skc->pubkey_algo == PUBKEY_ALGO_RSA ) {
lowbits = mpi_get_keyid( skc->d.rsa.rsa_n, keyid );
}
@ -178,6 +257,16 @@ keyid_from_pkc( PKT_public_cert *pkc, u32 *keyid )
lowbits = keyid[1];
md_close(md);
}
else if( pkc->pubkey_algo == PUBKEY_ALGO_DSA ) {
const byte *dp;
MD_HANDLE md;
md = dsa_fingerprint_md(pkc);
dp = md_read( md, DIGEST_ALGO_SHA1 );
keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
lowbits = keyid[1];
md_close(md);
}
else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
lowbits = mpi_get_keyid( pkc->d.rsa.rsa_n, keyid );
}
@ -208,6 +297,9 @@ nbits_from_pkc( PKT_public_cert *pkc )
if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
return mpi_get_nbits( pkc->d.elg.p );
}
else if( pkc->pubkey_algo == PUBKEY_ALGO_DSA ) {
return mpi_get_nbits( pkc->d.dsa.p );
}
else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
return mpi_get_nbits( pkc->d.rsa.rsa_n );
}
@ -224,6 +316,9 @@ nbits_from_skc( PKT_secret_cert *skc )
if( skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
return mpi_get_nbits( skc->d.elg.p );
}
else if( skc->pubkey_algo == PUBKEY_ALGO_DSA ) {
return mpi_get_nbits( skc->d.dsa.p );
}
else if( skc->pubkey_algo == PUBKEY_ALGO_RSA ) {
return mpi_get_nbits( skc->d.rsa.rsa_n );
}
@ -293,6 +388,15 @@ fingerprint_from_skc( PKT_secret_cert *skc, size_t *ret_len )
pkc.d.elg.g = skc->d.elg.g;
pkc.d.elg.y = skc->d.elg.y;
}
else if( pkc.pubkey_algo == PUBKEY_ALGO_DSA ) {
pkc.timestamp = skc->timestamp;
pkc.valid_days = skc->valid_days;
pkc.pubkey_algo = skc->pubkey_algo;
pkc.d.dsa.p = skc->d.dsa.p;
pkc.d.dsa.q = skc->d.dsa.q;
pkc.d.dsa.g = skc->d.dsa.g;
pkc.d.dsa.y = skc->d.dsa.y;
}
else if( pkc.pubkey_algo == PUBKEY_ALGO_RSA ) {
pkc.d.rsa.rsa_n = skc->d.rsa.rsa_n;
pkc.d.rsa.rsa_e = skc->d.rsa.rsa_e;
@ -322,6 +426,15 @@ fingerprint_from_pkc( PKT_public_cert *pkc, size_t *ret_len )
memcpy(array, dp, 20 );
md_close(md);
}
else if( pkc->pubkey_algo == PUBKEY_ALGO_DSA ) {
MD_HANDLE md;
md = dsa_fingerprint_md(pkc);
dp = md_read( md, DIGEST_ALGO_SHA1 );
array = m_alloc( 20 );
len = 20;
memcpy(array, dp, 20 );
md_close(md);
}
else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
MD_HANDLE md;

View File

@ -32,17 +32,231 @@
#include "memory.h"
#include "util.h"
#include "trustdb.h"
#include "ttyio.h"
#include "main.h"
#include "i18n.h"
static void list_all(void);
static void list_one(const char *name);
static void fingerprint( PKT_public_cert *pkc );
/****************
* List the keys in a special forma which is extensible and easy to parse
* If NAMES is NULL; the complte keyring is listed
*
* List the keys
* If NNAMES is 0; all available keys are listed
*/
void
ext_key_list( STRLIST names )
std_key_list( int nnames, char **names )
{
if( !nnames )
list_all();
else { /* List by user id */
for( ; nnames ; nnames--, names++ )
list_one( *names );
}
}
static void
list_all()
{
int i, seq=0;
const char *s;
IOBUF a;
while( (s=get_keyring(seq++)) ) {
if( !(a = iobuf_open(s)) ) {
log_error(_("can't open %s: %s\n"), s, strerror(errno));
continue;
}
if( seq > 1 )
putchar('\n');
printf("%s\n", s );
for(i=strlen(s); i; i-- )
putchar('-');
putchar('\n');
proc_packets( a );
iobuf_close(a);
}
}
static void
list_one( const char *name )
{
int rc = 0;
KBNODE keyblock = NULL;
KBNODE kbctx;
KBNODE node;
KBPOS kbpos;
PKT_public_cert *pkc;
u32 keyid[2];
int any=0;
/* search the userid */
rc = find_keyblock_byname( &kbpos, name );
if( rc ) {
log_error("%s: user not found\n", name );
goto leave;
}
/* read the keyblock */
rc = read_keyblock( &kbpos, &keyblock );
if( rc ) {
log_error("%s: keyblock read problem: %s\n", name, g10_errstr(rc) );
goto leave;
}
/* get the keyid from the keyblock */
node = find_kbnode( keyblock, PKT_PUBLIC_CERT );
if( !node ) {
log_error("Oops; public key not found anymore!\n");
goto leave;
}
pkc = node->pkt->pkt.public_cert;
keyid_from_pkc( pkc, keyid );
if( opt.with_colons )
printf("pub::%u:%d:%08lX%08lX:%s:::",
/* fixme: add trust value here */
nbits_from_pkc( pkc ),
pkc->pubkey_algo,
(ulong)keyid[0],(ulong)keyid[1],
datestr_from_pkc( pkc )
/* fixme: add LID and ownertrust here */
);
else
printf("pub %4u%c/%08lX %s ", nbits_from_pkc( pkc ),
pubkey_letter( pkc->pubkey_algo ),
(ulong)keyid[1],
datestr_from_pkc( pkc ) );
for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
if( node->pkt->pkttype == PKT_USER_ID ) {
if( any ) {
if( opt.with_colons )
printf("uid::::::::");
else
printf("uid%*s", 28, "");
}
print_string( stdout, node->pkt->pkt.user_id->name,
node->pkt->pkt.user_id->len, opt.with_colons );
if( opt.with_colons )
putchar(':');
putchar('\n');
if( !any ) {
if( opt.fingerprint )
fingerprint( pkc );
any = 1;
}
}
else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) {
PKT_signature *sig = node->pkt->pkt.signature;
int sigrc;
if( !any ) { /* no user id, (maybe a revocation follows)*/
if( sig->sig_class == 0x20 )
puts("[revoked]");
else
putchar('\n');
if( opt.fingerprint )
fingerprint( pkc );
any=1;
}
if( sig->sig_class == 0x20 || sig->sig_class == 0x30 )
fputs("rev", stdout);
else if( (sig->sig_class&~3) == 0x10 )
fputs("sig", stdout);
else {
if( opt.with_colons )
printf("sig:::::::::%02x:\n",sig->sig_class );
else
printf("sig "
"[unexpected signature class 0x%02x]\n",sig->sig_class );
continue;
}
if( opt.check_sigs ) {
fflush(stdout);
rc = check_key_signature( keyblock, node, NULL );
switch( rc ) {
case 0: sigrc = '!'; break;
case G10ERR_BAD_SIGN: sigrc = '-'; break;
case G10ERR_NO_PUBKEY: sigrc = '?'; break;
default: sigrc = '%'; break;
}
}
else {
rc = 0;
sigrc = ' ';
}
if( opt.with_colons ) {
putchar(':');
if( sigrc != ' ' )
putchar(sigrc);
printf(":::%08lX%08lX:%s:::", (ulong)sig->keyid[0],
(ulong)sig->keyid[1], datestr_from_sig(sig));
}
else
printf("%c %08lX %s ",
sigrc, (ulong)sig->keyid[1], datestr_from_sig(sig));
if( sigrc == '%' )
printf("[%s] ", g10_errstr(rc) );
else if( sigrc == '?' )
;
else {
size_t n;
char *p = get_user_id( sig->keyid, &n );
print_string( stdout, p, n, opt.with_colons );
m_free(p);
}
if( opt.with_colons )
printf(":%02x:", sig->sig_class );
putchar('\n');
}
}
if( !any ) {/* oops, no user id */
if( opt.with_colons )
putchar(':');
putchar('\n');
}
leave:
release_kbnode( keyblock );
}
static void
fingerprint( PKT_public_cert *pkc )
{
byte *array, *p;
size_t i, n;
p = array = fingerprint_from_pkc( pkc, &n );
if( opt.with_colons ) {
printf("fpr::::::::");
for(i=0; i < n ; i++, p++ )
printf("%02X", *p );
putchar(':');
}
else {
printf(" Key fingerprint =");
if( n == 20 ) {
for(i=0; i < n ; i++, i++, p += 2 ) {
if( i == 10 )
putchar(' ');
printf(" %02X%02X", *p, p[1] );
}
}
else {
for(i=0; i < n ; i++, p++ ) {
if( i && !(i%8) )
putchar(' ');
printf(" %02X", *p );
}
}
}
putchar('\n');
m_free(array);
}

View File

@ -81,6 +81,10 @@ void g10_elg_encrypt( PKT_public_cert *pkc, PKT_pubkey_enc *enc, DEK *dek );
void g10_elg_sign( PKT_secret_cert *skc, PKT_signature *sig,
MD_HANDLE md, int digest_algo );
/*-- dsa.c --*/
void g10_dsa_sign( PKT_secret_cert *skc, PKT_signature *sig,
MD_HANDLE md, int digest_algo );
/*-- rsa.c --*/
void g10_rsa_encrypt( PKT_public_cert *pkc, PKT_pubkey_enc *enc, DEK *dek );
void g10_rsa_sign( PKT_secret_cert *skc, PKT_signature *sig,
@ -98,6 +102,15 @@ int enarmor_file( const char *fname );
int gen_revoke( const char *uname );
/*-- keylist.c --*/
void ext_key_list( STRLIST names );
void std_key_list( int nnames, char **names );
/*-- verify.c --*/
int verify_signatures( int nfiles, char **files );
/*-- decrypt.c --*/
int decrypt_message( const char *filename );
/*-- plaintext.c --*/
int hash_datafiles( MD_HANDLE md, STRLIST files, int textmode );
#endif /*G10_MAIN_H*/

View File

@ -21,6 +21,7 @@
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "packet.h"
@ -45,6 +46,9 @@ typedef struct {
PKT_secret_cert *last_seckey;
PKT_user_id *last_user_id;
md_filter_context_t mfx;
int sigs_only; /* process only signatures and reject all other stuff */
int encrypt_only; /* process onyl encrytion messages */
STRLIST signed_data;
DEK *dek;
int last_was_pubkey_enc;
KBNODE list; /* the current list of packets */
@ -53,6 +57,7 @@ typedef struct {
} *CTX;
static int do_proc_packets( CTX c, IOBUF a );
static void list_node( CTX c, KBNODE node );
static void proc_tree( CTX c, KBNODE node );
@ -155,6 +160,7 @@ proc_pubkey_enc( CTX c, PACKET *pkt )
enc = pkt->pkt.pubkey_enc;
/*printf("enc: encrypted by a pubkey with keyid %08lX\n", enc->keyid[1] );*/
if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL
|| enc->pubkey_algo == PUBKEY_ALGO_DSA
|| enc->pubkey_algo == PUBKEY_ALGO_RSA ) {
m_free(c->dek ); /* paranoid: delete a pending DEK */
c->dek = m_alloc_secure( sizeof *c->dek );
@ -234,6 +240,18 @@ proc_plaintext( CTX c, PACKET *pkt )
}
static int
proc_compressed_cb( IOBUF a, void *info )
{
return proc_signature_packets( a, ((CTX)info)->signed_data );
}
static int
proc_encrypt_cb( IOBUF a, void *info )
{
return proc_encryption_packets( a );
}
static void
proc_compressed( CTX c, PACKET *pkt )
{
@ -241,7 +259,12 @@ proc_compressed( CTX c, PACKET *pkt )
int rc;
/*printf("zip: compressed data packet\n");*/
rc = handle_compressed( zd );
if( c->sigs_only )
rc = handle_compressed( zd, proc_compressed_cb, c );
else if( c->encrypt_only )
rc = handle_compressed( zd, proc_encrypt_cb, c );
else
rc = handle_compressed( zd, NULL, NULL );
if( rc )
log_error("uncompressing failed: %s\n", g10_errstr(rc));
free_packet(pkt);
@ -337,7 +360,8 @@ print_userid( PACKET *pkt )
printf("ERROR: unexpected packet type %d", pkt->pkttype );
return;
}
print_string( stdout, pkt->pkt.user_id->name, pkt->pkt.user_id->len );
print_string( stdout, pkt->pkt.user_id->name, pkt->pkt.user_id->len,
opt.with_colons );
}
@ -349,19 +373,27 @@ print_fingerprint( PKT_public_cert *pkc, PKT_secret_cert *skc )
p = array = skc? fingerprint_from_skc( skc, &n )
: fingerprint_from_pkc( pkc, &n );
printf(" Key fingerprint =");
if( n == 20 ) {
for(i=0; i < n ; i++, i++, p += 2 ) {
if( i == 10 )
putchar(' ');
printf(" %02X%02X", *p, p[1] );
}
if( opt.with_colons ) {
printf("fpr::::::::");
for(i=0; i < n ; i++, p++ )
printf("%02X", *p );
putchar(':');
}
else {
for(i=0; i < n ; i++, p++ ) {
if( i && !(i%8) )
putchar(' ');
printf(" %02X", *p );
printf(" Key fingerprint =");
if( n == 20 ) {
for(i=0; i < n ; i++, i++, p += 2 ) {
if( i == 10 )
putchar(' ');
printf(" %02X%02X", *p, p[1] );
}
}
else {
for(i=0; i < n ; i++, p++ ) {
if( i && !(i%8) )
putchar(' ');
printf(" %02X", *p );
}
}
}
putchar('\n');
@ -383,24 +415,47 @@ list_node( CTX c, KBNODE node )
else if( node->pkt->pkttype == PKT_PUBLIC_CERT ) {
PKT_public_cert *pkc = node->pkt->pkt.public_cert;
printf("pub %4u%c/%08lX %s ", nbits_from_pkc( pkc ),
if( opt.with_colons ) {
u32 keyid[2];
keyid_from_pkc( pkc, keyid );
printf("pub::%u:%d:%08lX%08lX:%s:::",
/* fixme: add trust value here */
nbits_from_pkc( pkc ),
pkc->pubkey_algo,
(ulong)keyid[0],(ulong)keyid[1],
datestr_from_pkc( pkc )
/* fixme: add LID and ownertrust here */
);
}
else
printf("pub %4u%c/%08lX %s ", nbits_from_pkc( pkc ),
pubkey_letter( pkc->pubkey_algo ),
(ulong)keyid_from_pkc( pkc, NULL ),
datestr_from_pkc( pkc ) );
/* and now list all userids with their signatures */
for( node = node->next; node; node = node->next ) {
if( any != 2 && node->pkt->pkttype == PKT_SIGNATURE ) {
if( !any )
putchar('\n');
if( !any ) {
if( node->pkt->pkt.signature->sig_class == 0x20 )
puts("[revoked]");
else
putchar('\n');
}
list_node(c, node );
any = 1;
}
else if( node->pkt->pkttype == PKT_USER_ID ) {
KBNODE n;
if( any )
printf( "%*s", 31, "" );
if( any ) {
if( opt.with_colons )
printf("uid::::::::");
else
printf( "uid%*s", 28, "" );
}
print_userid( node->pkt );
if( opt.with_colons )
putchar(':');
putchar('\n');
if( opt.fingerprint && !any )
print_fingerprint( pkc, NULL );
@ -457,17 +512,27 @@ list_node( CTX c, KBNODE node )
default: sigrc = '%'; break;
}
}
printf("%c %08lX %s ",
sigrc, (ulong)sig->keyid[1], datestr_from_sig(sig));
if( opt.with_colons ) {
putchar(':');
if( sigrc != ' ' )
putchar(sigrc);
printf(":::%08lX%08lX:%s:::", (ulong)sig->keyid[0],
(ulong)sig->keyid[1], datestr_from_sig(sig));
}
else
printf("%c %08lX %s ",
sigrc, (ulong)sig->keyid[1], datestr_from_sig(sig));
if( sigrc == '%' )
printf("[%s] ", g10_errstr(rc2) );
else if( sigrc == '?' )
;
else {
p = get_user_id( sig->keyid, &n );
print_string( stdout, p, n );
print_string( stdout, p, n, opt.with_colons );
m_free(p);
}
if( opt.with_colons )
printf(":%02x:", sig->sig_class );
putchar('\n');
}
else
@ -479,8 +544,40 @@ int
proc_packets( IOBUF a )
{
CTX c = m_alloc_clear( sizeof *c );
PACKET *pkt = m_alloc( sizeof *pkt );
int rc = do_proc_packets( c, a );
m_free( c );
return rc;
}
int
proc_signature_packets( IOBUF a, STRLIST signedfiles )
{
CTX c = m_alloc_clear( sizeof *c );
int rc;
c->sigs_only = 1;
c->signed_data = signedfiles;
rc = do_proc_packets( c, a );
m_free( c );
return rc;
}
int
proc_encryption_packets( IOBUF a )
{
CTX c = m_alloc_clear( sizeof *c );
int rc;
c->encrypt_only = 1;
rc = do_proc_packets( c, a );
m_free( c );
return rc;
}
int
do_proc_packets( CTX c, IOBUF a )
{
PACKET *pkt = m_alloc( sizeof *pkt );
int rc=0;
int newpkt;
c->iobuf = a;
@ -507,6 +604,38 @@ proc_packets( IOBUF a )
default: newpkt = 0; break;
}
}
else if( c->sigs_only ) {
switch( pkt->pkttype ) {
case PKT_PUBLIC_CERT:
case PKT_SECRET_CERT:
case PKT_USER_ID:
case PKT_PUBKEY_ENC:
case PKT_ENCRYPTED:
rc = G10ERR_UNEXPECTED;
goto leave;
case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break;
case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break;
case PKT_COMPRESSED: proc_compressed( c, pkt ); break;
case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break;
default: newpkt = 0; break;
}
}
else if( c->encrypt_only ) {
switch( pkt->pkttype ) {
case PKT_PUBLIC_CERT:
case PKT_SECRET_CERT:
case PKT_USER_ID:
rc = G10ERR_UNEXPECTED;
goto leave;
case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break;
case PKT_PUBKEY_ENC: proc_pubkey_enc( c, pkt ); break;
case PKT_ENCRYPTED: proc_encrypted( c, pkt ); break;
case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break;
case PKT_COMPRESSED: proc_compressed( c, pkt ); break;
case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break;
default: newpkt = 0; break;
}
}
else {
switch( pkt->pkttype ) {
case PKT_PUBLIC_CERT: newpkt = add_public_cert( c, pkt ); break;
@ -533,14 +662,15 @@ proc_packets( IOBUF a )
else
free_packet(pkt);
}
rc = 0;
leave:
release_list( c );
m_free(c->dek);
free_packet( pkt );
m_free( pkt );
free_md_filter_context( &c->mfx );
m_free( c );
return 0;
return rc;
}
@ -549,7 +679,7 @@ print_keyid( FILE *fp, u32 *keyid )
{
size_t n;
char *p = get_user_id( keyid, &n );
print_string( fp, p, n );
print_string( fp, p, n, opt.with_colons );
m_free(p);
}
@ -562,15 +692,18 @@ check_sig_and_print( CTX c, KBNODE node )
int rc;
rc = do_check_sig(c, node );
if( !rc ) {
write_status( STATUS_GOODSIG );
log_info("Good signature from ");
print_keyid( stderr, sig->keyid );
putc('\n', stderr);
}
else if( rc == G10ERR_BAD_SIGN ) {
write_status( STATUS_BADSIG );
log_error("BAD signature from ");
if( !rc || rc == G10ERR_BAD_SIGN ) {
char *p, *buf;
p = get_user_id_string( sig->keyid );
buf = m_alloc( 20 + strlen(p) );
sprintf(buf, "%lu %s", (ulong)sig->timestamp, p );
m_free(p);
if( (p=strchr(buf,'\n')) )
*p = 0; /* just in case ... */
write_status_text( rc? STATUS_BADSIG : STATUS_GOODSIG, buf );
m_free(buf);
log_info("%s signature from ", rc? "BAD":"Good");
print_keyid( stderr, sig->keyid );
putc('\n', stderr);
if( opt.batch )
@ -607,12 +740,17 @@ proc_tree( CTX c, KBNODE node )
free_md_filter_context( &c->mfx );
/* prepare to create all requested message digests */
c->mfx.md = md_open(0, 0);
/* fixme: why looking for the signature packet and not 1passpacket*/
for( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); ) {
md_enable( c->mfx.md,
digest_algo_from_sig(n1->pkt->pkt.signature));
}
/* ask for file and hash it */
rc = ask_for_detached_datafile( &c->mfx,
if( c->sigs_only )
rc = hash_datafiles( c->mfx.md, c->signed_data,
n1->pkt->pkt.onepass_sig->sig_class == 0x01 );
else
rc = ask_for_detached_datafile( &c->mfx,
iobuf_get_fname(c->iobuf));
if( rc ) {
log_error("can't hash datafile: %s\n", g10_errstr(rc));
@ -629,7 +767,11 @@ proc_tree( CTX c, KBNODE node )
if( !c->have_data ) {
free_md_filter_context( &c->mfx );
c->mfx.md = md_open(digest_algo_from_sig(sig), 0);
rc = ask_for_detached_datafile( &c->mfx,
if( c->sigs_only )
rc = hash_datafiles( c->mfx.md, c->signed_data,
sig->sig_class == 0x01 );
else
rc = ask_for_detached_datafile( &c->mfx,
iobuf_get_fname(c->iobuf));
if( rc ) {
log_error("can't hash datafile: %s\n", g10_errstr(rc));

View File

@ -42,6 +42,8 @@
int
overwrite_filep( const char *fname )
{
if( !fname || (*fname == '-' && !fname[1]) )
return 0; /* stdout */
if( !access( fname, F_OK ) ) {
char *p;
int okay;
@ -55,7 +57,6 @@ overwrite_filep( const char *fname )
okay = 0;
while( !okay ) {
if( !okay )
if( first ) {
tty_printf("File '%s' exists. ", fname);
first = 0;
@ -91,7 +92,7 @@ open_outfile( const char *iname, int mode )
IOBUF a = NULL;
int rc;
if( !iname && !opt.outfile ) {
if( (!iname || (*iname=='-' && !iname[1])) && !opt.outfile ) {
if( !(a = iobuf_create(NULL)) )
log_error("can't open [stdout]: %s\n", strerror(errno) );
else if( opt.verbose )
@ -133,7 +134,7 @@ open_sigfile( const char *iname )
IOBUF a = NULL;
size_t len;
if( iname ) {
if( iname && !(*iname == '-' && !iname[1]) ) {
len = strlen(iname);
if( len > 4 && ( !strcmp(iname + len - 4, ".sig")
|| !strcmp(iname + len - 4, ".asc")) ) {

View File

@ -31,7 +31,7 @@ struct {
int answer_yes; /* answer yes on most questions */
int answer_no; /* answer no on most questions */
int check_sigs; /* check key signatures */
int reserved1;
int with_colons;
int fingerprint; /* list fingerprints */
int list_sigs; /* list signatures */
int no_armor;

View File

@ -75,18 +75,22 @@ typedef struct {
u32 keyid[2]; /* 64 bit keyid */
ulong local_id; /* internal use, valid if > 0 */
u32 timestamp; /* signature made */
byte version;
byte sig_class; /* sig classification, append for MD calculation*/
byte pubkey_algo; /* algorithm used for public key scheme */
/* (PUBKEY_ALGO_xxx) */
byte digest_algo; /* algorithm used for digest (DIGEST_ALGO_xxxx) */
byte *hashed_data; /* all subpackets with hashed data (v4 only) */
byte *unhashed_data; /* ditto for unhashed data */
byte digest_start[2]; /* first 2 bytes of the digest */
union {
struct {
byte digest_algo; /* algorithm used for digest (DIGEST_ALGO_xxxx) */
byte digest_start[2]; /* first 2 byte of the digest */
MPI a, b; /* integers with the digest */
} elg;
struct {
byte digest_algo; /* algorithm used for digest (DIGEST_ALGO_xxxx) */
byte digest_start[2]; /* first 2 byte of the digest */
MPI r, s; /* integers with the digest */
} dsa;
struct {
MPI rsa_integer; /* the encrypted digest */
} rsa;
} d;
@ -106,6 +110,12 @@ typedef struct {
MPI g; /* group generator */
MPI y; /* g^x mod p */
} elg;
struct {
MPI p; /* prime */
MPI q; /* group order */
MPI g; /* group generator */
MPI y; /* g^x mod p */
} dsa;
struct {
MPI rsa_n; /* public modulus */
MPI rsa_e; /* public exponent */
@ -138,6 +148,25 @@ typedef struct {
} protect; /* when protected, the MPIs above are pointers
* to plain storage */
} elg;
struct {
MPI p; /* prime */
MPI q; /* group order */
MPI g; /* group generator */
MPI y; /* g^x mod p */
MPI x; /* secret exponent */
u16 csum; /* checksum */
byte is_protected; /* The above infos are protected and must */
/* be decrypteded before use. */
struct {
byte algo; /* cipher used to protect the secret informations*/
byte s2k;
byte hash;
byte salt[8];
byte count;
byte iv[8]; /* initialization vector for CFB mode */
} protect; /* when protected, the MPIs above are pointers
* to plain storage */
} dsa;
struct {
MPI rsa_n; /* public modulus */
MPI rsa_e; /* public exponent */
@ -215,6 +244,8 @@ struct packet_struct {
/*-- mainproc.c --*/
int proc_packets( IOBUF a );
int proc_signature_packets( IOBUF a, STRLIST signedfiles );
int proc_encryption_packets( IOBUF a );
int list_packets( IOBUF a );
/*-- parse-packet.c --*/
@ -260,7 +291,8 @@ int protect_secret_key( PKT_secret_cert *cert, DEK *dek );
int get_session_key( PKT_pubkey_enc *k, DEK *dek );
/*-- compress.c --*/
int handle_compressed( PKT_compressed *zd );
int handle_compressed( PKT_compressed *cd,
int (*callback)(IOBUF, void *), void *passthru );
/*-- encr-data.c --*/
int decrypt_data( PKT_encrypted *ed, DEK *dek );

View File

@ -96,6 +96,17 @@ read_32(IOBUF inp)
return a;
}
static unsigned long
buffer_to_u32( const byte *buffer )
{
unsigned long a;
a = *buffer << 24;
a |= buffer[1] << 16;
a |= buffer[2] << 8;
a |= buffer[3];
return a;
}
int
set_packet_list_mode( int mode )
{
@ -466,49 +477,210 @@ parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
}
static const byte *
parse_subpkt( const byte *buffer, int reqtype )
{
int buflen = (*buffer << 8) | buffer[1];
int type;
int critical;
size_t n;
buffer += 2;
for(;;) {
if( !buflen )
return NULL; /* end of packets; not found */
n = *buffer++; buflen--;
if( n >= 192 ) {
if( buflen < 2 )
goto too_short;
n = (( n - 192 ) << 8) + *buffer + 192;
buflen--;
}
if( buflen < n )
goto too_short;
type = *buffer;
if( type & 0x80 ) {
type &= 0x7f;
critical = 1;
}
else
critical = 0;
if( reqtype < 0 ) { /* list packets */
printf("\t%ssubpacket %d of length %u (%s)\n",
reqtype == -1 ? "hashed ":"", type, n,
type == 2 ? "signature creation time"
: type == 3 ? "signature expiration time"
: type == 4 ? "exportable"
: type == 5 ? "trust signature"
: type == 6 ? "regular expression"
: type == 7 ? "revocable"
: type == 9 ? "key expiration time"
: type ==10 ? "additional recipient request"
: type ==11 ? "preferred symmetric algorithms"
: type ==12 ? "revocation key"
: type ==16 ? "issuer key ID"
: type ==20 ? "notation data"
: type ==21 ? "preferred hash algorithms"
: type ==22 ? "preferred compression algorithms"
: type ==23 ? "key server preferences"
: type ==24 ? "preferred key server"
: "?");
}
else if( type == reqtype )
break; /* found */
buffer += n; buflen -=n;
}
buffer++;
n--;
if( n > buflen )
goto too_short;
switch( type ) {
case 2: /* signature creation time */
if( n < 4 )
break;
return buffer;
case 16:/* issuer key ID */
if( n < 8 )
break;
return buffer;
case 3: /* signature expiration time */
case 4: /* exportable */
case 5: /* trust signature */
case 6: /* regular expression */
case 7: /* revocable */
case 9: /* key expiration time */
case 10:/* additional recipient request */
case 11:/* preferred symmetric algorithms */
case 12:/* revocation key */
case 20:/* notation data */
case 21:/* preferred hash algorithms */
case 22:/* preferred compression algorithms */
case 23:/* key server preferences */
case 24:/* preferred key server */
default: BUG(); /* not yet needed */
}
log_error("subpacket of type %d too short\n", type);
return NULL;
too_short:
log_error("buffer shorter than subpacket\n");
return NULL;
}
static int
parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
PKT_signature *sig )
{
int version, md5_len;
int md5_len=0;
unsigned n;
int is_v4=0;
int rc=0;
if( pktlen < 16 ) {
log_error("packet(%d) too short\n", pkttype);
goto leave;
}
version = iobuf_get_noeof(inp); pktlen--;
if( version != 2 && version != 3 ) {
log_error("packet(%d) with unknown version %d\n", pkttype, version);
sig->version = iobuf_get_noeof(inp); pktlen--;
if( sig->version == 4 )
is_v4=1;
else if( sig->version != 2 && sig->version != 3 ) {
log_error("packet(%d) with unknown version %d\n", pkttype, sig->version);
goto leave;
}
md5_len = iobuf_get_noeof(inp); pktlen--;
if( !is_v4 ) {
md5_len = iobuf_get_noeof(inp); pktlen--;
}
sig->sig_class = iobuf_get_noeof(inp); pktlen--;
sig->timestamp = read_32(inp); pktlen -= 4;
sig->keyid[0] = read_32(inp); pktlen -= 4;
sig->keyid[1] = read_32(inp); pktlen -= 4;
if( !is_v4 ) {
sig->timestamp = read_32(inp); pktlen -= 4;
sig->keyid[0] = read_32(inp); pktlen -= 4;
sig->keyid[1] = read_32(inp); pktlen -= 4;
}
sig->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
if( list_mode )
printf(":signature packet: keyid %08lX%08lX\n"
"\tversion %d, created %lu, md5len %d, sigclass %02x\n",
(ulong)sig->keyid[0], (ulong)sig->keyid[1],
version, (ulong)sig->timestamp, md5_len, sig->sig_class );
if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
if( pktlen < 5 ) {
log_error("packet(%d) too short\n", pkttype);
sig->digest_algo = iobuf_get_noeof(inp); pktlen--;
if( is_v4 ) { /* read subpackets */
n = read_16(inp); pktlen -= 2; /* length of hashed data */
if( n > 10000 ) {
log_error("signature packet: hashed data too long\n");
rc = G10ERR_INVALID_PACKET;
goto leave;
}
sig->d.elg.digest_algo = iobuf_get_noeof(inp); pktlen--;
sig->d.elg.digest_start[0] = iobuf_get_noeof(inp); pktlen--;
sig->d.elg.digest_start[1] = iobuf_get_noeof(inp); pktlen--;
if( n ) {
sig->hashed_data = m_alloc( n + 2 );
sig->hashed_data[0] = n << 8;
sig->hashed_data[1] = n;
if( iobuf_read(inp, sig->hashed_data+2, n ) != n ) {
log_error("premature eof while reading hashed signature data\n");
rc = -1;
goto leave;
}
pktlen -= n;
}
n = read_16(inp); pktlen -= 2; /* length of unhashed data */
if( n > 10000 ) {
log_error("signature packet: unhashed data too long\n");
rc = G10ERR_INVALID_PACKET;
goto leave;
}
if( n ) {
sig->unhashed_data = m_alloc( n + 2 );
sig->unhashed_data[0] = n << 8;
sig->unhashed_data[1] = n;
if( iobuf_read(inp, sig->unhashed_data+2, n ) != n ) {
log_error("premature eof while reading unhashed signature data\n");
rc = -1;
goto leave;
}
pktlen -= n;
}
}
if( pktlen < 5 ) { /* sanity check */
log_error("packet(%d) too short\n", pkttype);
rc = G10ERR_INVALID_PACKET;
goto leave;
}
sig->digest_start[0] = iobuf_get_noeof(inp); pktlen--;
sig->digest_start[1] = iobuf_get_noeof(inp); pktlen--;
if( is_v4 ) { /*extract required informations */
const byte *p;
p = parse_subpkt( sig->hashed_data, 2 );
if( !p )
log_error("signature packet without timestamp\n");
else
sig->timestamp = buffer_to_u32(p);
p = parse_subpkt( sig->unhashed_data, 16 );
if( !p )
log_error("signature packet without keyid\n");
else {
sig->keyid[0] = buffer_to_u32(p);
sig->keyid[1] = buffer_to_u32(p+4);
}
}
if( list_mode ) {
printf(":signature packet: keyid %08lX%08lX\n"
"\tversion %d, created %lu, md5len %d, sigclass %02x\n"
"\tdigest algo %d, begin of digest %02x %02x\n",
(ulong)sig->keyid[0], (ulong)sig->keyid[1],
sig->version, (ulong)sig->timestamp, md5_len, sig->sig_class,
sig->digest_algo,
sig->digest_start[0], sig->digest_start[1] );
if( is_v4 ) {
parse_subpkt( sig->hashed_data, -1 );
parse_subpkt( sig->unhashed_data, -2 );
}
}
if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
n = pktlen;
sig->d.elg.a = mpi_read(inp, &n, 0 ); pktlen -=n;
n = pktlen;
sig->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) {
printf("\tdigest algo %d, begin of digest %02x %02x\n",
sig->d.elg.digest_algo,
sig->d.elg.digest_start[0], sig->d.elg.digest_start[1] );
printf("\telg a: ");
mpi_print(stdout, sig->d.elg.a, mpi_print_mode );
printf("\n\telg b: ");
@ -516,20 +688,23 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
putchar('\n');
}
}
else if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) {
if( pktlen < 5 ) {
log_error("packet(%d) too short\n", pkttype);
goto leave;
else if( sig->pubkey_algo == PUBKEY_ALGO_DSA ) {
n = pktlen;
sig->d.dsa.r = mpi_read(inp, &n, 0 ); pktlen -=n;
n = pktlen;
sig->d.dsa.s = mpi_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) {
printf("\tdsa r: ");
mpi_print(stdout, sig->d.elg.a, mpi_print_mode );
printf("\n\tdsa s: ");
mpi_print(stdout, sig->d.elg.b, mpi_print_mode );
putchar('\n');
}
sig->d.rsa.digest_algo = iobuf_get_noeof(inp); pktlen--;
sig->d.rsa.digest_start[0] = iobuf_get_noeof(inp); pktlen--;
sig->d.rsa.digest_start[1] = iobuf_get_noeof(inp); pktlen--;
}
else if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) {
n = pktlen;
sig->d.rsa.rsa_integer = mpi_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) {
printf("\tdigest algo %d, begin of digest %02x %02x\n",
sig->d.rsa.digest_algo,
sig->d.rsa.digest_start[0], sig->d.rsa.digest_start[1] );
printf("\trsa integer: ");
mpi_print(stdout, sig->d.rsa.rsa_integer, mpi_print_mode );
putchar('\n');
@ -541,7 +716,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
leave:
skip_rest(inp, pktlen);
return 0;
return rc;
}
@ -761,6 +936,137 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
log_mpidump("elg x=", cert->d.elg.x ); */
}
}
else if( algorithm == PUBKEY_ALGO_DSA ) {
MPI dsa_p, dsa_q, dsa_g, dsa_y;
n = pktlen; dsa_p = mpi_read(inp, &n, 0 ); pktlen -=n;
n = pktlen; dsa_q = mpi_read(inp, &n, 0 ); pktlen -=n;
n = pktlen; dsa_g = mpi_read(inp, &n, 0 ); pktlen -=n;
n = pktlen; dsa_y = mpi_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) {
printf( "\tdsa p: ");
mpi_print(stdout, dsa_p, mpi_print_mode );
printf("\n\tdsa q: ");
mpi_print(stdout, dsa_q, mpi_print_mode );
printf("\n\tdsa g: ");
mpi_print(stdout, dsa_g, mpi_print_mode );
printf("\n\tdsa y: ");
mpi_print(stdout, dsa_y, mpi_print_mode );
putchar('\n');
}
if( pkttype == PKT_PUBLIC_CERT ) {
pkt->pkt.public_cert->d.dsa.p = dsa_p;
pkt->pkt.public_cert->d.dsa.q = dsa_q;
pkt->pkt.public_cert->d.dsa.g = dsa_g;
pkt->pkt.public_cert->d.dsa.y = dsa_y;
}
else {
PKT_secret_cert *cert = pkt->pkt.secret_cert;
byte temp[8];
pkt->pkt.secret_cert->d.dsa.p = dsa_p;
pkt->pkt.secret_cert->d.dsa.q = dsa_q;
pkt->pkt.secret_cert->d.dsa.g = dsa_g;
pkt->pkt.secret_cert->d.dsa.y = dsa_y;
cert->d.dsa.protect.algo = iobuf_get_noeof(inp); pktlen--;
if( cert->d.dsa.protect.algo ) {
cert->d.dsa.is_protected = 1;
cert->d.dsa.protect.count = 0;
if( cert->d.dsa.protect.algo == 255 ) {
if( pktlen < 3 ) {
rc = G10ERR_INVALID_PACKET;
goto leave;
}
cert->d.dsa.protect.algo = iobuf_get_noeof(inp); pktlen--;
cert->d.dsa.protect.s2k = iobuf_get_noeof(inp); pktlen--;
cert->d.dsa.protect.hash = iobuf_get_noeof(inp); pktlen--;
switch( cert->d.dsa.protect.s2k ) {
case 1:
case 3:
for(i=0; i < 8 && pktlen; i++, pktlen-- )
temp[i] = iobuf_get_noeof(inp);
memcpy(cert->d.dsa.protect.salt, temp, 8 );
break;
}
switch( cert->d.dsa.protect.s2k ) {
case 0: if( list_mode ) printf( "\tsimple S2K" );
break;
case 1: if( list_mode ) printf( "\tsalted S2K" );
break;
case 3: if( list_mode ) printf( "\titer+salt S2K" );
break;
default:
if( list_mode )
printf( "\tunknown S2K %d\n",
cert->d.dsa.protect.s2k );
rc = G10ERR_INVALID_PACKET;
goto leave;
}
if( list_mode ) {
printf(", algo: %d, hash: %d",
cert->d.dsa.protect.algo,
cert->d.dsa.protect.hash );
if( cert->d.dsa.protect.s2k == 1
|| cert->d.dsa.protect.s2k == 3 ) {
printf(", salt: ");
for(i=0; i < 8; i++ )
printf("%02x", cert->d.dsa.protect.salt[i]);
}
putchar('\n');
}
if( cert->d.dsa.protect.s2k == 3 ) {
if( !pktlen ) {
rc = G10ERR_INVALID_PACKET;
goto leave;
}
cert->d.dsa.protect.count = iobuf_get_noeof(inp);
pktlen--;
}
}
else {
if( list_mode )
printf( "\tprotect algo: %d\n",
cert->d.dsa.protect.algo);
/* old version, we don't have a S2K, so we fake one */
cert->d.dsa.protect.s2k = 0;
cert->d.dsa.protect.hash = DIGEST_ALGO_MD5;
}
if( pktlen < 8 ) {
rc = G10ERR_INVALID_PACKET;
goto leave;
}
for(i=0; i < 8 && pktlen; i++, pktlen-- )
temp[i] = iobuf_get_noeof(inp);
if( list_mode ) {
printf( "\tprotect IV: ");
for(i=0; i < 8; i++ )
printf(" %02x", temp[i] );
putchar('\n');
}
memcpy(cert->d.dsa.protect.iv, temp, 8 );
}
else
cert->d.dsa.is_protected = 0;
/* It does not make sense to read it into secure memory.
* 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 him. */
n = pktlen; cert->d.dsa.x = mpi_read(inp, &n, 0 ); pktlen -=n;
cert->d.dsa.csum = read_16(inp); pktlen -= 2;
if( list_mode ) {
printf("\t[secret value x is not shown]\n"
"\tchecksum: %04hx\n", cert->d.dsa.csum);
}
/*log_mpidump("dsa p=", cert->d.dsa.p );
log_mpidump("dsa q=", cert->d.dsa.q );
log_mpidump("dsa g=", cert->d.dsa.g );
log_mpidump("dsa y=", cert->d.dsa.y );
log_mpidump("dsa x=", cert->d.dsa.x ); */
}
}
else if( algorithm == PUBKEY_ALGO_RSA ) {
MPI rsa_pub_mod, rsa_pub_exp;
@ -1023,3 +1329,4 @@ parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
}

View File

@ -30,6 +30,7 @@
#include "ttyio.h"
#include "filter.h"
#include "main.h"
#include "i18n.h"
/****************
@ -58,7 +59,8 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx )
fname[pt->namelen] = 0;
}
if( !*fname ) { /* no filename given; write to stdout */
if( !*fname || (*fname=='-' && !fname[1])) {
/* no filename or "-" given; write to stdout */
fp = stdout;
}
else if( overwrite_filep( fname ) )
@ -181,3 +183,44 @@ ask_for_detached_datafile( md_filter_context_t *mfx, const char *inname )
}
/****************
* Hash the given files and append the hash to hash context md.
* If FILES is NULL, hash stdin.
*/
int
hash_datafiles( MD_HANDLE md, STRLIST files, int textmode )
{
IOBUF fp;
STRLIST sl=NULL;
text_filter_context_t tfx;
int c;
if( !files )
add_to_strlist( &sl, "-");
else
sl = files;
for( ; sl; sl = sl->next ) {
fp = iobuf_open( sl->d );
if( !fp ) {
log_error(_("can't open signed data '%s'\n"),
print_fname_stdin(sl->d));
if( !files )
free_strlist(sl);
return G10ERR_OPEN_FILE;
}
if( textmode ) {
memset( &tfx, 0, sizeof tfx);
iobuf_push_filter( fp, text_filter, &tfx );
}
while( (c = iobuf_get(fp)) != -1 )
md_putc(md, c );
iobuf_close(fp);
}
if( !files )
free_strlist(sl);
return 0;
}

View File

@ -517,6 +517,13 @@ keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname )
&& !mpi_cmp( req_skc->d.elg.y, skc->d.elg.y )
&& !mpi_cmp( req_skc->d.elg.x, skc->d.elg.x )
)
|| ( skc->pubkey_algo == PUBKEY_ALGO_DSA
&& !mpi_cmp( req_skc->d.dsa.p, skc->d.dsa.p )
&& !mpi_cmp( req_skc->d.dsa.q, skc->d.dsa.q )
&& !mpi_cmp( req_skc->d.dsa.g, skc->d.dsa.g )
&& !mpi_cmp( req_skc->d.dsa.y, skc->d.dsa.y )
&& !mpi_cmp( req_skc->d.dsa.x, skc->d.dsa.x )
)
|| ( skc->pubkey_algo == PUBKEY_ALGO_RSA
&& !mpi_cmp( req_skc->d.rsa.rsa_n, skc->d.rsa.rsa_n )
&& !mpi_cmp( req_skc->d.rsa.rsa_e, skc->d.rsa.rsa_e )
@ -537,6 +544,12 @@ keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname )
&& !mpi_cmp( req_pkc->d.elg.g, pkc->d.elg.g )
&& !mpi_cmp( req_pkc->d.elg.y, pkc->d.elg.y )
)
|| ( pkc->pubkey_algo == PUBKEY_ALGO_DSA
&& !mpi_cmp( req_pkc->d.dsa.p, pkc->d.dsa.p )
&& !mpi_cmp( req_pkc->d.dsa.q, pkc->d.dsa.q )
&& !mpi_cmp( req_pkc->d.dsa.g, pkc->d.dsa.g )
&& !mpi_cmp( req_pkc->d.dsa.y, pkc->d.dsa.y )
)
|| ( pkc->pubkey_algo == PUBKEY_ALGO_RSA
&& !mpi_cmp( req_pkc->d.rsa.rsa_n, pkc->d.rsa.rsa_n )
&& !mpi_cmp( req_pkc->d.rsa.rsa_e, pkc->d.rsa.rsa_e )

View File

@ -77,9 +77,9 @@ g10_rsa_sign( PKT_secret_cert *skc, PKT_signature *sig,
dp = md_read( md, digest_algo );
keyid_from_skc( skc, sig->keyid );
sig->d.rsa.digest_algo = digest_algo;
sig->d.rsa.digest_start[0] = dp[0];
sig->d.rsa.digest_start[1] = dp[1];
sig->digest_algo = digest_algo;
sig->digest_start[0] = dp[0];
sig->digest_start[1] = dp[1];
sig->d.rsa.rsa_integer =
encode_md_value( md, mpi_get_nbits(skc->d.rsa.rsa_n));
skey.e = skc->d.rsa.rsa_e;

View File

@ -141,6 +141,7 @@ check_elg( PKT_secret_cert *cert )
return 0;
}
static int
protect_elg( PKT_secret_cert *cert, DEK *dek )
{
@ -174,6 +175,126 @@ protect_elg( PKT_secret_cert *cert, DEK *dek )
return 0;
}
static int
check_dsa( PKT_secret_cert *cert )
{
byte *buffer;
u16 csum=0;
int res;
unsigned nbytes;
u32 keyid[2];
DSA_secret_key skey;
char save_iv[8];
if( cert->d.dsa.is_protected ) { /* remove the protection */
DEK *dek = NULL;
MPI test_x;
BLOWFISH_context *blowfish_ctx=NULL;
switch( cert->d.dsa.protect.algo ) {
case CIPHER_ALGO_NONE: BUG(); break;
case CIPHER_ALGO_BLOWFISH:
keyid_from_skc( cert, keyid );
if( cert->d.dsa.protect.s2k == 1
|| cert->d.dsa.protect.s2k == 3 )
dek = get_passphrase_hash( keyid, NULL,
cert->d.dsa.protect.salt );
else
dek = get_passphrase_hash( keyid, NULL, NULL );
blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
m_free(dek); /* pw is in secure memory, so m_free() burns it */
blowfish_setiv( blowfish_ctx, NULL );
memcpy(save_iv, cert->d.dsa.protect.iv, 8 );
blowfish_decode_cfb( blowfish_ctx,
cert->d.dsa.protect.iv,
cert->d.dsa.protect.iv, 8 );
mpi_set_secure(cert->d.dsa.x );
/*fixme: maybe it is better to set the buffer secure with a
* new get_buffer_secure() function */
buffer = mpi_get_buffer( cert->d.dsa.x, &nbytes, NULL );
csum = checksum_u16( nbytes*8 );
blowfish_decode_cfb( blowfish_ctx, buffer, buffer, nbytes );
csum += checksum( buffer, nbytes );
test_x = mpi_alloc_secure( mpi_get_nlimbs(cert->d.dsa.x) );
mpi_set_buffer( test_x, buffer, nbytes, 0 );
m_free( buffer );
m_free( blowfish_ctx );
/* now let's see wether we have used the right passphrase */
if( csum != cert->d.dsa.csum ) {
mpi_free(test_x);
memcpy( cert->d.dsa.protect.iv, save_iv, 8 );
return G10ERR_BAD_PASS;
}
skey.p = cert->d.dsa.p;
skey.q = cert->d.dsa.q;
skey.g = cert->d.dsa.g;
skey.y = cert->d.dsa.y;
skey.x = test_x;
res = dsa_check_secret_key( &skey );
memset( &skey, 0, sizeof skey );
if( !res ) {
mpi_free(test_x);
memcpy( cert->d.dsa.protect.iv, save_iv, 8 );
return G10ERR_BAD_PASS;
}
mpi_set(cert->d.dsa.x, test_x);
mpi_free(test_x);
cert->d.dsa.is_protected = 0;
break;
default:
return G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
}
}
else { /* not protected */
buffer = mpi_get_buffer( cert->d.dsa.x, &nbytes, NULL );
csum = checksum_u16( nbytes*8 );
csum += checksum( buffer, nbytes );
m_free( buffer );
if( csum != cert->d.dsa.csum )
return G10ERR_CHECKSUM;
}
return 0;
}
static int
protect_dsa( PKT_secret_cert *cert, DEK *dek )
{
byte *buffer;
unsigned nbytes;
if( !cert->d.dsa.is_protected ) { /* add the protection */
BLOWFISH_context *blowfish_ctx=NULL;
switch( cert->d.dsa.protect.algo ) {
case CIPHER_ALGO_NONE: BUG(); break;
case CIPHER_ALGO_BLOWFISH:
blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
blowfish_setiv( blowfish_ctx, NULL );
blowfish_encode_cfb( blowfish_ctx,
cert->d.dsa.protect.iv,
cert->d.dsa.protect.iv, 8 );
buffer = mpi_get_buffer( cert->d.dsa.x, &nbytes, NULL );
blowfish_encode_cfb( blowfish_ctx, buffer, buffer, nbytes );
mpi_set_buffer( cert->d.dsa.x, buffer, nbytes, 0 );
m_free( buffer );
m_free( blowfish_ctx );
cert->d.dsa.is_protected = 1;
break;
default:
return G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
}
}
return 0;
}
#ifdef HAVE_RSA_CIPHER
static int
@ -282,6 +403,8 @@ check_secret_key( PKT_secret_cert *cert )
log_error("Invalid passphrase; please try again ...\n");
if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
rc = check_elg( cert );
else if( cert->pubkey_algo == PUBKEY_ALGO_DSA )
rc = check_dsa( cert );
#ifdef HAVE_RSA_CIPHER
else if( cert->pubkey_algo == PUBKEY_ALGO_RSA )
rc = check_rsa( cert );
@ -303,6 +426,8 @@ 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;
else if( cert->pubkey_algo == PUBKEY_ALGO_DSA )
return cert->d.dsa.is_protected? cert->d.dsa.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;
@ -323,6 +448,8 @@ protect_secret_key( PKT_secret_cert *cert, DEK *dek )
if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
return protect_elg( cert, dek );
else if( cert->pubkey_algo == PUBKEY_ALGO_DSA )
return protect_dsa( cert, dek );
else
return G10ERR_PUBKEY_ALGO;
}

View File

@ -66,11 +66,11 @@ do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest )
if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
ELG_public_key pkey;
if( (rc=check_digest_algo(sig->d.elg.digest_algo)) )
if( (rc=check_digest_algo(sig->digest_algo)) )
goto leave;
/* make sure the digest algo is enabled (in case of a detached
* signature */
md_enable( digest, sig->d.elg.digest_algo );
md_enable( digest, sig->digest_algo );
/* complete the digest */
md_putc( digest, sig->sig_class );
{ u32 a = sig->timestamp;
@ -87,6 +87,59 @@ do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest )
if( !elg_verify( sig->d.elg.a, sig->d.elg.b, result, &pkey ) )
rc = G10ERR_BAD_SIGN;
}
else if( pkc->pubkey_algo == PUBKEY_ALGO_DSA ) {
DSA_public_key pkey;
if( (rc=check_digest_algo(sig->digest_algo)) )
goto leave;
/* make sure the digest algo is enabled (in case of a detached
* signature */
md_enable( digest, sig->digest_algo );
assert( sig->digest_algo == DIGEST_ALGO_SHA1 );
/* complete the digest */
if( sig->version >= 4 )
md_putc( digest, sig->version );
md_putc( digest, sig->sig_class );
if( sig->version < 4 ) {
u32 a = sig->timestamp;
md_putc( digest, (a >> 24) & 0xff );
md_putc( digest, (a >> 16) & 0xff );
md_putc( digest, (a >> 8) & 0xff );
md_putc( digest, a & 0xff );
}
else {
byte buf[6];
size_t n;
md_putc( digest, sig->pubkey_algo );
md_putc( digest, sig->digest_algo );
if( sig->hashed_data ) {
n = (sig->hashed_data[0] << 8) | sig->hashed_data[1];
md_write( digest, sig->hashed_data, n+2 );
n += 4;
}
else
n = 4;
/* add some magic */
buf[0] = sig->version;
buf[1] = 0xff;
buf[2] = n >> 24;
buf[3] = n >> 16;
buf[4] = n >> 8;
buf[5] = n;
md_write( digest, buf, 6 );
}
md_final( digest );
log_hexdump("digest is: ", md_read(digest, DIGEST_ALGO_SHA1), 20);
result = encode_md_value( digest, mpi_get_nbits(pkc->d.dsa.p));
pkey.p = pkc->d.dsa.p;
pkey.q = pkc->d.dsa.q;
pkey.g = pkc->d.dsa.g;
pkey.y = pkc->d.dsa.y;
if( !dsa_verify( sig->d.dsa.r, sig->d.dsa.s, result, &pkey ) )
rc = G10ERR_BAD_SIGN;
}
#ifdef HAVE_RSA_CIPHER
else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
int i, j, c, old_enc;
@ -125,10 +178,10 @@ do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest )
goto leave;
}
if( (rc=check_digest_algo(sig->d.rsa.digest_algo)) )
if( (rc=check_digest_algo(sig->digest_algo)) )
goto leave; /* unsupported algo */
md_enable( digest, sig->d.rsa.digest_algo );
asn = md_asn_oid( sig->d.rsa.digest_algo, &asnlen, &mdlen );
md_enable( digest, sig->digest_algo );
asn = md_asn_oid( sig->digest_algo, &asnlen, &mdlen );
for(i=mdlen,j=asnlen-1; (c=mpi_getbyte(result, i)) != -1 && j >= 0;
i++, j-- )
@ -142,7 +195,7 @@ do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest )
if( c != 0xff )
break;
i++;
if( c != sig->d.rsa.digest_algo || mpi_getbyte(result, i) ) {
if( c != sig->digest_algo || mpi_getbyte(result, i) ) {
/* Padding or leading bytes in signature is wrong */
rc = G10ERR_BAD_PUBKEY;
goto leave;
@ -163,7 +216,7 @@ do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest )
md_putc( digest, a & 0xff );
}
md_final( digest );
dp = md_read( digest, sig->d.rsa.digest_algo );
dp = md_read( digest, sig->digest_algo );
for(i=mdlen-1; i >= 0; i--, dp++ ) {
if( mpi_getbyte( result, i ) != *dp ) {
rc = G10ERR_BAD_SIGN;
@ -188,7 +241,7 @@ do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest )
/****************
* check the signature pointed to by NODE. This is a key signatures.
* If the function detects a elf signature, it uses the PKC from
* If the function detects a self-signature, it uses the PKC from
* NODE and does not read the any public key.
*/
int
@ -210,9 +263,11 @@ check_key_signature( KBNODE root, KBNODE node, int *is_selfsig )
sig = node->pkt->pkt.signature;
if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
algo = sig->d.elg.digest_algo;
algo = sig->digest_algo;
else if( sig->pubkey_algo == PUBKEY_ALGO_DSA )
algo = sig->digest_algo;
else if(sig->pubkey_algo == PUBKEY_ALGO_RSA )
algo = sig->d.rsa.digest_algo;
algo = sig->digest_algo;
else
return G10ERR_PUBKEY_ALGO;
if( (rc=check_digest_algo(algo)) )
@ -233,7 +288,18 @@ check_key_signature( KBNODE root, KBNODE node, int *is_selfsig )
keyid_from_pkc( pkc, keyid );
md = md_open( algo, 0 );
if( sig->sig_class== 16 )
md->debug = fopen("dsahashsig","w");
hash_public_cert( md, pkc );
if( sig->version >=4 ) {
byte buf[5];
buf[0] = 0xb4; /* indicates a userid packet */
buf[1] = uid->len >> 24; /* but use 4 length bytes */
buf[2] = uid->len >> 16;
buf[3] = uid->len >> 8;
buf[4] = uid->len;
md_write( md, buf, 5 );
}
md_write( md, uid->name, uid->len );
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) {
if( is_selfsig )
@ -243,6 +309,8 @@ check_key_signature( KBNODE root, KBNODE node, int *is_selfsig )
else
rc = signature_check( sig, md );
md_close(md);
if( sig->sig_class== 16 )
fclose(md->debug);
}
else {
log_error("no user id for key signature packet\n");

View File

@ -50,6 +50,8 @@ complete_sig( PKT_signature *sig, PKT_secret_cert *skc, MD_HANDLE md )
;
else if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
g10_elg_sign( skc, sig, md, 0 );
else if( sig->pubkey_algo == PUBKEY_ALGO_DSA )
g10_dsa_sign( skc, sig, md, 0 );
else if( sig->pubkey_algo == PUBKEY_ALGO_RSA )
g10_rsa_sign( skc, sig, md, 0 );
else
@ -274,6 +276,8 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
g10_elg_sign( skc, sig, md, DIGEST_ALGO_RMD160 );
else if( sig->pubkey_algo == PUBKEY_ALGO_DSA )
g10_dsa_sign( skc, sig, md, DIGEST_ALGO_SHA1 );
else if( sig->pubkey_algo == PUBKEY_ALGO_RSA )
g10_rsa_sign( skc, sig, md, DIGEST_ALGO_RMD160 );
else
@ -428,6 +432,8 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
g10_elg_sign( skc, sig, md, DIGEST_ALGO_RMD160 );
else if( sig->pubkey_algo == PUBKEY_ALGO_DSA )
g10_dsa_sign( skc, sig, md, DIGEST_ALGO_SHA1 );
else if( sig->pubkey_algo == PUBKEY_ALGO_RSA )
g10_rsa_sign( skc, sig, md, DIGEST_ALGO_RMD160 );
else
@ -1066,6 +1072,7 @@ change_passphrase( const char *username )
break;
}
else { /* okay */
/* FIXME: what about dsa */
skc->d.elg.protect.algo = CIPHER_ALGO_BLOWFISH;
skc->d.elg.protect.s2k = 1;
skc->d.elg.protect.hash = DIGEST_ALGO_RMD160;

View File

@ -36,6 +36,12 @@ set_status_fd( int newfd )
void
write_status( int no )
{
write_status_text( no, NULL );
}
void
write_status_text( int no, const char *text)
{
const char *s;
@ -53,7 +59,13 @@ write_status( int no )
default: s = "?\n"; break;
}
write( fd, s, strlen(s) );
if( text ) {
write( fd, s, strlen(s)-1 );
write( fd, " ", 1 );
write( fd, text, strlen(text) );
write( fd, "\n", 1 );
}
else
write( fd, s, strlen(s) );
}

View File

@ -37,6 +37,7 @@
/*-- status.c --*/
void set_status_fd( int fd );
void write_status( int no );
void write_status_text( int no, const char *text);
#endif /*G10_STATUS_H*/

View File

@ -912,7 +912,7 @@ print_user_id( const char *text, u32 *keyid )
putchar(' ');
}
putchar('\"');
print_string( stdout, p, n );
print_string( stdout, p, n, 0 );
putchar('\"');
putchar('\n');
m_free(p);
@ -1520,13 +1520,18 @@ init_trustdb( int level, const char *dbname )
assert(p);
*p = 0;
if( access( fname, F_OK ) ) {
#if __MINGW32__
if( mkdir( fname ) )
#else
if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) )
#endif
log_fatal("can't create directory '%s': %s\n",
fname, strerror(errno) );
if( strlen(fname) >= 7
&& !strcmp(fname+strlen(fname)-7, "/.gnupg" ) ) {
#if __MINGW32__
if( mkdir( fname ) )
#else
if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) )
#endif
log_fatal("can't create directory '%s': %s\n",
fname, strerror(errno) );
}
else
log_fatal("directory '%s' does not exist!\n", fname );
}
*p = '/';
create_db( fname );
@ -1539,7 +1544,7 @@ init_trustdb( int level, const char *dbname )
return 0;
/* we can verify a signature about our local data (secring and trustdb)
* in ~/.g10/ here */
* in ~/.gnupg/ here */
rc = verify_private_data();
if( !rc ) {
/* verify, that our own certificates are in the trustDB

87
g10/verify.c Normal file
View File

@ -0,0 +1,87 @@
/* verify.c - verify signed data
* Copyright (C) 1998 Free Software Foundation, Inc.
*
* This file is part of GNUPG.
*
* GNUPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GNUPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include "options.h"
#include "packet.h"
#include "errors.h"
#include "iobuf.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "main.h"
#include "filter.h"
#include "ttyio.h"
#include "i18n.h"
/****************
* Assume that the input is a signature and verify it without
* generating any output. With no arguments, the sigature packet
* is read from stdin (it may be a detached signature when not
* used in batch mode). If only a sigfile is given, is maybe a complete
* signature or a detached signature in which case the signed stuff
* is expected from stdin. With more than 1 argument, the first should
* be a detached signature and the remaining files are the signed stuff.
*/
int
verify_signatures( int nfiles, char **files )
{
IOBUF fp;
armor_filter_context_t afx;
const char *sigfile;
int i, rc;
STRLIST sl;
sigfile = nfiles? *files : NULL;
/* open the signature file */
fp = iobuf_open(sigfile);
if( !fp ) {
log_error(_("can't open '%s'\n"), print_fname_stdin(sigfile));
return G10ERR_OPEN_FILE;
}
if( !opt.no_armor ) {
if( use_armor_filter( fp ) ) {
memset( &afx, 0, sizeof afx);
iobuf_push_filter( fp, armor_filter, &afx );
}
}
sl = NULL;
for(i=1 ; i < nfiles; i++ )
add_to_strlist( &sl, files[i] );
rc = proc_signature_packets( fp, sl );
free_strlist(sl);
iobuf_close(fp);
return rc;
}

View File

@ -0,0 +1,9 @@
Mon Mar 9 12:59:55 1998 Werner Koch (wk@isil.d.shuttle.de)
* cipher.h: Included dsa.h.
Tue Mar 3 15:11:21 1998 Werner Koch (wk@isil.d.shuttle.de)
* cipher.h (random.h): Add new header and move all relevalt
functions to this header.

View File

@ -34,6 +34,8 @@
#endif
#include "../cipher/blowfish.h"
#include "../cipher/elgamal.h"
#include "../cipher/dsa.h"
#include "../cipher/random.h"
#define CIPHER_ALGO_NONE 0
@ -78,10 +80,6 @@ int check_cipher_algo( int algo );
int check_pubkey_algo( int algo );
int check_digest_algo( int algo );
/*-- random.c --*/
int quick_random_gen( int onoff );
void randomize_buffer( byte *buffer, size_t length, int level );
byte get_random_byte( int level );
/*-- smallprime.c --*/
extern ushort small_prime_numbers[];

View File

@ -58,5 +58,6 @@
#define G10ERR_CLOSE_FILE 36
#define G10ERR_RENAME_FILE 37
#define G10ERR_DELETE_FILE 38
#define G10ERR_UNEXPECTED 39
#endif /*G10_ERRORS_H*/

View File

@ -101,10 +101,13 @@ const char *strusage( int level );
/*-- fileutil.c --*/
char *make_filename( const char *first_part, ... );
const char *print_fname_stdin( const char *s );
const char *print_fname_stdout( const char *s );
/*-- miscutil.c --*/
u32 make_timestamp(void);
void print_string( FILE *fp, byte *p, size_t n );
void print_string( FILE *fp, byte *p, size_t n, int delim );
int answer_is_yes( const char *s );
/*-- strgutil.c --*/

View File

@ -1,3 +1,16 @@
Sat Mar 7 11:54:35 1998 Werner Koch (wk@isil.d.shuttle.de)
* miscutil.c (print_string): New arg delim; changed all callers.
Thu Mar 5 12:19:30 1998 Werner Koch (wk@isil.d.shuttle.de)
* errors.c: New strings.
Thu Mar 5 12:06:31 1998 Werner Koch (wk@isil.d.shuttle.de)
* iobuf.c (iobuf_open): A name of "-" now opens stdin.
* fileutil.c (print_fname_stdout, print_fname_stdin): New.
Fri Feb 27 10:20:03 1998 Werner Koch (wk@isil.d.shuttle.de)
* memory.c (m_is_secure): Removed.

View File

@ -64,9 +64,13 @@ g10_errstr( int err )
X(NI_PUBKEY ,"Unimplemented pubkey algorithm")
X(NI_CIPHER ,"Unimplemented cipher algorithm")
X(SIG_CLASS ,"Unknown signature class")
X(TRUSTDB ,"TrustDB error")
X(TRUSTDB ,"Trust database error")
X(BAD_CERT ,"Bad certificate")
X(INV_USER_ID ,"malformed user id")
X(INV_USER_ID ,"Malformed user id")
X(CLOSE_FILE ,"File close error")
X(RENAME_FILE ,"File rename error")
X(DELETE_FILE ,"File delete error")
X(UNEXPECTED ,"Unexpected data")
default: p = buf; sprintf(buf, "g10err=%d", err); break;
}

View File

@ -64,3 +64,26 @@ make_filename( const char *first_part, ... )
return name;
}
/****************
* A simple function to decide, wether the filename ist stdout
* or a real filename.
*/
const char *
print_fname_stdout( const char *s )
{
if( !s || (*s == '-' && !s[1]) )
return "[stdout]";
return s;
}
const char *
print_fname_stdin( const char *s )
{
if( !s || (*s == '-' && !s[1]) )
return "[stdin]";
return s;
}

View File

@ -371,7 +371,7 @@ iobuf_open( const char *fname )
file_filter_ctx_t *fcx;
size_t len;
if( !fname ) {
if( !fname || (*fname=='-' && !fname[1]) ) {
fp = stdin; /* fixme: set binary mode for msdoze */
fname = "[stdin]";
}

View File

@ -37,13 +37,21 @@ make_timestamp()
* Print a string to FP, but filter all control characters out.
*/
void
print_string( FILE *fp, byte *p, size_t n )
print_string( FILE *fp, byte *p, size_t n, int delim )
{
for( ; n; n--, p++ )
if( iscntrl( *p ) ) {
if( iscntrl( *p ) || *p == delim ) {
putc('\\', fp);
if( *p == '\n' )
putc('n', fp);
else if( *p == '\r' )
putc('r', fp);
else if( *p == '\f' )
putc('f', fp);
else if( *p == '\v' )
putc('v', fp);
else if( *p == '\b' )
putc('b', fp);
else if( !*p )
putc('0', fp);
else