1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

nearly ready for 0.3.0

This commit is contained in:
Werner Koch 1998-06-25 10:19:08 +00:00
parent e6ac5acbbf
commit 06fd61d081
52 changed files with 1335 additions and 312 deletions

View file

@ -1,3 +1,20 @@
Wed Jun 24 16:40:22 1998 Werner Koch (wk@isil.d.shuttle.de)
* armor.c (armor_filter): Now creates valid onepass_sig packets
with all detected hash algorithms.
* mainproc.c (proc_plaintext): Now uses the hash algos as specified
in the onepass_sig packets (if there are any)
Mon Jun 22 11:54:08 1998 Werner Koch (wk@isil.d.shuttle.de)
* plaintext.c (handle_plaintext): add arg to disable outout
* mainproc.c (proc_plaintext): disable output when in sigs_only mode.
Thu Jun 18 13:17:27 1998 Werner Koch (wk@isil.d.shuttle.de)
* keygen.c: Removed all rsa packet stuff, chnaged defaults
for key generation.
Sun Jun 14 21:28:31 1998 Werner Koch (wk@isil.d.shuttle.de)
* misc.c (checksum_u16): Fixed a stupid bug which caused a

View file

@ -3,7 +3,7 @@
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl -I../intl
EXTRA_DIST = OPTIONS pubring.asc
OMIT_DEPENDENCIES = zlib.h zconf.h
LDFLAGS = -rdynamic
LDFLAGS = @LDFLAGS@ @DYNLINK_LDFLAGS@
needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a
noinst_PROGRAMS = gpgd

View file

@ -100,8 +100,10 @@ static char *tail_strings[] = {
};
static fhdr_state_t find_header( fhdr_state_t state, byte *buf,
size_t *r_buflen, IOBUF a, size_t n, unsigned *r_empty);
static fhdr_state_t find_header( fhdr_state_t state,
byte *buf, size_t *r_buflen,
IOBUF a, size_t n,
unsigned *r_empty, int *r_hashes );
static void
@ -227,7 +229,7 @@ parse_hash_header( const char *line )
found |= 2;
else if( !strncmp( s, "MD5", s2-s ) )
found |= 4;
else if( !strncmp( s, "MD2", s2-s ) )
else if( !strncmp( s, "TIGER", s2-s ) )
found |= 8;
else
return 0;
@ -250,7 +252,7 @@ parse_hash_header( const char *line )
*/
static fhdr_state_t
find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
IOBUF a, size_t n, unsigned *r_empty)
IOBUF a, size_t n, unsigned *r_empty, int *r_hashes )
{
int c=0, i;
const char *s;
@ -319,6 +321,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
if( n < buflen || c == '\n' ) {
if( n && buf[0] != '\r') { /* maybe a header */
if( strchr( buf, ':') ) { /* yes */
int hashes;
if( buf[n-1] == '\r' )
buf[--n] = 0;
if( opt.verbose ) {
@ -326,12 +329,15 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
print_string( stderr, buf, n, 0 );
putc('\n', stderr);
}
if( clearsig && !parse_hash_header( buf ) ) {
if( clearsig && !(hashes=parse_hash_header( buf )) ) {
log_error("invalid clearsig header\n");
state = fhdrERROR;
}
else
else {
state = fhdrWAITHeader;
if( r_hashes )
*r_hashes |= hashes;
}
}
else
state = fhdrCHECKDashEscaped3;
@ -602,7 +608,8 @@ check_input( armor_filter_context_t *afx, IOBUF a )
state = fhdrHASArmor;
n = DIM(afx->helpbuf);
state = find_header( state, afx->helpbuf, &n, a, afx->helplen, &emplines);
state = find_header( state, afx->helpbuf, &n, a,
afx->helplen, &emplines, &afx->hashes);
switch( state ) {
case fhdrNOArmor:
afx->inp_checked = 1;
@ -684,7 +691,8 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
/* read a new one */
n = DIM(afx->helpbuf);
afx->helpidx = 0;
state = find_header( state, afx->helpbuf, &n, a, 0, &emplines );
state = find_header( state, afx->helpbuf, &n, a, 0,
&emplines, &afx->hashes );
switch( state) {
case fhdrERROR:
invalid_armor();
@ -884,7 +892,7 @@ armor_filter( void *opaque, int control,
*ret_len = n;
}
else if( control == IOBUFCTRL_UNDERFLOW ) {
if( size < 30 )
if( size < 15+(4*15) ) /* need space for up to 4 onepass_sigs */
BUG(); /* supplied buffer too short */
if( afx->inp_eof ) {
@ -907,27 +915,53 @@ armor_filter( void *opaque, int control,
afx->helplen = 0;
}
else if( afx->faked ) {
/* the buffer is at least 30 bytes long, so it
unsigned hashes = afx->hashes;
/* the buffer is at least 15+n*15 bytes long, so it
* is easy to construct the packets */
/* first a onepass signature packet */
buf[0] = 0x90; /* old packet format, type 4, 1 length byte */
buf[1] = 13; /* length */
buf[2] = 3; /* version */
buf[3] = 0x01; /* sigclass 0x01 (data in canonical text mode)*/
buf[4] = 0; /* digest algo (don't know) */
buf[5] = 0; /* public key algo (don't know) */
memset(buf+6, 0, 8); /* don't know the keyid */
buf[14] = 1; /* this is the last one */
hashes &= 1|2|4|8;
if( !hashes )
hashes |= 4; /* default to MD 5 */
n=0;
do {
/* first some onepass signature packets */
buf[n++] = 0x90; /* old format, type 4, 1 length byte */
buf[n++] = 13; /* length */
buf[n++] = 3; /* version */
buf[n++] = 0x01; /* sigclass 0x01 (canonical text mode)*/
if( hashes & 1 ) {
hashes &= ~1;
buf[n++] = DIGEST_ALGO_RMD160;
}
else if( hashes & 2 ) {
hashes &= ~2;
buf[n++] = DIGEST_ALGO_SHA1;
}
else if( hashes & 4 ) {
hashes &= ~4;
buf[n++] = DIGEST_ALGO_MD5;
}
else if( hashes & 8 ) {
hashes &= ~8;
buf[n++] = DIGEST_ALGO_TIGER;
}
else
buf[n++] = 0; /* (don't know) */
buf[n++] = 0; /* public key algo (don't know) */
memset(buf+n, 0, 8); /* don't know the keyid */
n += 8;
buf[n++] = !hashes; /* last one */
} while( hashes );
/* followed by a plaintext packet */
buf[15] = 0xaf; /* old packet format, type 11, var length */
buf[16] = 0; /* set the length header */
buf[17] = 6;
buf[18] = 't'; /* canonical text mode */
buf[19] = 0; /* namelength */
memset(buf+20, 0, 4); /* timestamp */
n = 24;
buf[n++] = 0xaf; /* old packet format, type 11, var length */
buf[n++] = 0; /* set the length header */
buf[n++] = 6;
buf[n++] = 't'; /* canonical text mode */
buf[n++] = 0; /* namelength */
memset(buf+n, 0, 4); /* timestamp */
n += 4;
}
else if( !rc )
rc = radix64_read( afx, a, &n, buf, size );

View file

@ -517,6 +517,11 @@ build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
switch( type ) {
case SIGSUBPKT_SIG_CREATED:
case SIGSUBPKT_PRIV_ADD_SIG:
case SIGSUBPKT_PREF_SYM:
case SIGSUBPKT_PREF_HASH:
case SIGSUBPKT_PREF_COMPR:
case SIGSUBPKT_KS_FLAGS:
case SIGSUBPKT_KEY_EXPIRE:
hashed = 1; break;
default: hashed = 0; break;
}
@ -538,8 +543,8 @@ build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
: m_alloc( n+2 );
}
data[n0+0] = (n >> 8) & 0xff;
data[n0+1] = n & 0xff;
data[0] = (n >> 8) & 0xff;
data[1] = n & 0xff;
data[n0+2] = buflen+1;
data[n0+3] = type;
memcpy(data+n0+4, buffer, buflen );

View file

@ -37,6 +37,7 @@ typedef struct {
byte helpbuf[100];
int helpidx, helplen;
unsigned empty; /* empty line counter */
int hashes; /* detected hash algorithms */
int faked;
int parse_state;
int inp_checked; /* set if inp has been checked */

View file

@ -30,6 +30,7 @@
#include "iobuf.h"
#include "keydb.h"
#include "options.h"
#include "main.h"
#define MAX_PKC_CACHE_ENTRIES 500
@ -595,6 +596,58 @@ compare_name( const char *uid, size_t uidlen, const char *name, int mode )
}
/****************
* Assume that knode points to a public key packet and keyblock is
* the entire keyblock. This function adds all relevant information from
* a selfsignature to the public key.
*/
static void
add_stuff_from_selfsig( KBNODE keyblock, KBNODE knode )
{
PKT_public_cert *pkc = knode->pkt->pkt.public_cert;
PKT_signature *sig;
KBNODE k;
u32 kid[2];
assert( knode->pkt->pkttype == PKT_PUBLIC_CERT
|| knode->pkt->pkttype == PKT_PUBKEY_SUBCERT );
if( pkc->version < 4 )
return; /* this is only needed for version >=4 packets */
/* find the selfsignature */
if( knode->pkt->pkttype == PKT_PUBKEY_SUBCERT ) {
k = find_kbnode( keyblock, PKT_PUBLIC_CERT );
if( !k )
BUG(); /* keyblock without primary key!!! */
keyid_from_pkc( knode->pkt->pkt.public_cert, kid );
}
else
keyid_from_pkc( pkc, kid );
for(k=keyblock; k; k = k->next ) {
if( k->pkt->pkttype == PKT_SIGNATURE
&& (sig=k->pkt->pkt.signature)->sig_class >= 0x10
&& sig->sig_class <= 0x13
&& sig->keyid[0] == kid[0]
&& sig->keyid[1] == kid[1]
&& sig->version > 3 ) {
/* okay this is (the first) self-signature which can be used
* fixme: Check how to handle subkey bindings
* FIXME: We should only use this if the signature is valid
* but this is time consuming - we muts provide another
* way to handle this
*/
const byte *p;
p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_KEY_EXPIRE, NULL );
pkc->valid_days = p? ((buffer_to_u32(p)+86399L)/86400L):0;
/* fixme: add usage etc. to pkc */
break;
}
}
}
/****************
* Lookup a key by scanning all keyrings
* mode 1 = lookup by NAME (exact)
@ -718,6 +771,7 @@ lookup( PKT_public_cert *pkc, int mode, u32 *keyid,
assert( k->pkt->pkttype == PKT_PUBLIC_CERT
|| k->pkt->pkttype == PKT_PUBKEY_SUBCERT );
copy_public_cert( pkc, k->pkt->pkt.public_cert );
add_stuff_from_selfsig( keyblock, k );
if( ret_keyblock ) {
*ret_keyblock = keyblock;
keyblock = NULL;

View file

@ -347,7 +347,7 @@ sign_key( const char *username, STRLIST locusr )
node->pkt->pkt.user_id,
NULL,
skc_rover->skc,
0x10, 0 );
0x10, 0, NULL, NULL );
if( rc ) {
log_error("make_keysig_packet failed: %s\n", g10_errstr(rc));
goto leave;
@ -720,7 +720,9 @@ int
make_keysig_packet( PKT_signature **ret_sig, PKT_public_cert *pkc,
PKT_user_id *uid, PKT_public_cert *subpkc,
PKT_secret_cert *skc,
int sigclass, int digest_algo )
int sigclass, int digest_algo,
int (*mksubpkt)(PKT_signature *, void *), void *opaque
)
{
PKT_signature *sig;
int rc=0;
@ -763,45 +765,50 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_cert *pkc,
sig->digest_algo = digest_algo;
sig->timestamp = make_timestamp();
sig->sig_class = sigclass;
if( sig->version >= 4 ) {
if( sig->version >= 4 )
build_sig_subpkt_from_sig( sig );
md_putc( md, sig->version );
}
md_putc( md, sig->sig_class );
if( sig->version < 4 ) {
u32 a = sig->timestamp;
md_putc( md, (a >> 24) & 0xff );
md_putc( md, (a >> 16) & 0xff );
md_putc( md, (a >> 8) & 0xff );
md_putc( md, a & 0xff );
}
else {
byte buf[6];
size_t n;
md_putc( md, sig->pubkey_algo );
md_putc( md, sig->digest_algo );
if( sig->hashed_data ) {
n = (sig->hashed_data[0] << 8) | sig->hashed_data[1];
md_write( md, sig->hashed_data, n+2 );
n += 6;
if( sig->version >= 4 && mksubpkt )
rc = (*mksubpkt)( sig, opaque );
if( !rc ) {
if( sig->version >= 4 )
md_putc( md, sig->version );
md_putc( md, sig->sig_class );
if( sig->version < 4 ) {
u32 a = sig->timestamp;
md_putc( md, (a >> 24) & 0xff );
md_putc( md, (a >> 16) & 0xff );
md_putc( md, (a >> 8) & 0xff );
md_putc( md, a & 0xff );
}
else
n = 6;
/* add some magic */
buf[0] = sig->version;
buf[1] = 0xff;
buf[2] = n >> 24; /* hmmm, n is only 16 bit, so this is always 0 */
buf[3] = n >> 16;
buf[4] = n >> 8;
buf[5] = n;
md_write( md, buf, 6 );
else {
byte buf[6];
size_t n;
md_putc( md, sig->pubkey_algo );
md_putc( md, sig->digest_algo );
if( sig->hashed_data ) {
n = (sig->hashed_data[0] << 8) | sig->hashed_data[1];
md_write( md, sig->hashed_data, n+2 );
n += 6;
}
else
n = 6;
/* add some magic */
buf[0] = sig->version;
buf[1] = 0xff;
buf[2] = n >> 24; /* hmmm, n is only 16 bit, so this is always 0 */
buf[3] = n >> 16;
buf[4] = n >> 8;
buf[5] = n;
md_write( md, buf, 6 );
}
md_final(md);
rc = complete_sig( sig, skc, md );
}
md_final(md);
rc = complete_sig( sig, skc, md );
md_close( md );
if( rc )

View file

@ -35,11 +35,6 @@
#include "i18n.h"
#if 0
#define ENABLE_RSA_KEYGEN 1
#endif
static void
write_uid( KBNODE root, const char *s )
{
@ -54,6 +49,65 @@ write_uid( KBNODE root, const char *s )
}
static int
add_key_expire( PKT_signature *sig, void *opaque )
{
PKT_secret_cert *skc = opaque;
byte buf[8];
u32 u;
if( skc->valid_days ) {
u = skc->valid_days * 86400L;
buf[0] = (u >> 24) & 0xff;
buf[1] = (u >> 16) & 0xff;
buf[2] = (u >> 8) & 0xff;
buf[3] = u & 0xff;
build_sig_subpkt( sig, SIGSUBPKT_KEY_EXPIRE, buf, 4 );
}
return 0;
}
/****************
* Add preference to the self signature packet.
* This is only called for packets with version > 3.
*/
static int
add_prefs( PKT_signature *sig, void *opaque )
{
byte buf[8];
add_key_expire( sig, opaque );
buf[0] = CIPHER_ALGO_BLOWFISH;
buf[1] = CIPHER_ALGO_CAST5;
build_sig_subpkt( sig, SIGSUBPKT_PREF_SYM, buf, 2 );
buf[0] = DIGEST_ALGO_RMD160;
buf[1] = DIGEST_ALGO_SHA1;
buf[2] = DIGEST_ALGO_TIGER;
buf[3] = DIGEST_ALGO_MD5;
build_sig_subpkt( sig, SIGSUBPKT_PREF_HASH, buf, 4 );
buf[0] = 2;
buf[1] = 1;
build_sig_subpkt( sig, SIGSUBPKT_PREF_COMPR, buf, 2 );
buf[0] = 0x80; /* no modify - It is reasonable that a key holder
* has the possibility to reject signatures from users
* who are known to sign everything without any
* validation - so a signed key should be send
* to the holder who in turn can put it on a keyserver
*/
build_sig_subpkt( sig, SIGSUBPKT_KS_FLAGS, buf, 1 );
return 0;
}
static int
write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_cert *skc )
{
@ -79,7 +133,8 @@ write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_cert *skc )
pkc = node->pkt->pkt.public_cert;
/* and make the signature */
rc = make_keysig_packet( &sig, pkc, uid, NULL, skc, 0x13, 0 );
rc = make_keysig_packet( &sig, pkc, uid, NULL, skc, 0x13, 0,
add_prefs, skc );
if( rc ) {
log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) );
return rc;
@ -119,7 +174,8 @@ write_keybinding( KBNODE root, KBNODE pub_root, PKT_secret_cert *skc )
BUG();
/* and make the signature */
rc = make_keysig_packet( &sig, pkc, NULL, subpkc, skc, 0x18, 0 );
rc = make_keysig_packet( &sig, pkc, NULL, subpkc, skc, 0x18, 0,
add_key_expire, skc );
if( rc ) {
log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) );
return rc;
@ -134,7 +190,7 @@ write_keybinding( KBNODE root, KBNODE pub_root, PKT_secret_cert *skc )
static int
gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
STRING2KEY *s2k, PKT_secret_cert **ret_skc, u16 valid_days,
int version )
{
@ -146,7 +202,8 @@ gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
MPI skey[4];
MPI *factors;
rc = pubkey_generate( PUBKEY_ALGO_ELGAMAL, nbits, skey, &factors );
assert( is_ELGAMAL(algo) );
rc = pubkey_generate( algo, nbits, skey, &factors );
if( rc ) {
log_error("pubkey_generate failed: %s\n", g10_errstr(rc) );
return rc;
@ -157,7 +214,7 @@ gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
skc->timestamp = pkc->timestamp = make_timestamp();
skc->version = pkc->version = version;
skc->valid_days = pkc->valid_days = valid_days;
skc->pubkey_algo = pkc->pubkey_algo = PUBKEY_ALGO_ELGAMAL;
skc->pubkey_algo = pkc->pubkey_algo = algo;
pkc->pkey[0] = mpi_copy( skey[0] );
pkc->pkey[1] = mpi_copy( skey[1] );
pkc->pkey[2] = mpi_copy( skey[2] );
@ -203,73 +260,6 @@ gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
}
#ifdef ENABLE_RSA_KEYGEN
static int
gen_rsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
STRING2KEY *s2k, PKT_secret_cert **ret_skc, u16 valid_days )
{
int rc;
PACKET *pkt;
PKT_secret_cert *skc;
PKT_public_cert *pkc;
RSA_public_key pk;
RSA_secret_key sk;
rsa_generate( &pk, &sk, nbits );
skc = m_alloc_clear( sizeof *skc );
pkc = m_alloc_clear( sizeof *pkc );
skc->timestamp = pkc->timestamp = make_timestamp();
skc->valid_days = pkc->valid_days = valid_days;
skc->pubkey_algo = pkc->pubkey_algo = PUBKEY_ALGO_RSA;
memset(&pkc->mfx, 0, sizeof pkc->mfx);
pkc->d.rsa.rsa_n = pk.n;
pkc->d.rsa.rsa_e = pk.e;
skc->d.rsa.rsa_n = sk.n;
skc->d.rsa.rsa_e = sk.e;
skc->d.rsa.rsa_d = sk.d;
skc->d.rsa.rsa_p = sk.p;
skc->d.rsa.rsa_q = sk.q;
skc->d.rsa.rsa_u = sk.u;
skc->d.rsa.csum = checksum_mpi_counted_nbits( skc->d.rsa.rsa_d );
skc->d.rsa.csum += checksum_mpi_counted_nbits( skc->d.rsa.rsa_p );
skc->d.rsa.csum += checksum_mpi_counted_nbits( skc->d.rsa.rsa_q );
skc->d.rsa.csum += checksum_mpi_counted_nbits( skc->d.rsa.rsa_u );
if( ret_skc ) /* not a subkey: return an unprotected version of the skc */
*ret_skc = copy_secret_cert( NULL, skc );
if( dek ) {
skc->d.rsa.is_protected = 1;
skc->d.rsa.protect_algo = CIPHER_ALGO_BLOWFISH;
randomize_buffer( skc->d.rsa.protect.blowfish.iv, 8, 1);
skc->d.rsa.csum += checksum_counted_nbits(
skc->d.rsa.protect.blowfish.iv, 8 );
rc = protect_secret_key( skc, dek );
if( rc ) {
log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
free_public_cert(pkc);
free_secret_cert(skc);
return rc;
}
}
pkt = m_alloc_clear(sizeof *pkt);
pkt->pkttype = ret_skc ? PKT_PUBLIC_CERT : PKT_PUBKEY_SUBCERT;
pkt->pkt.public_cert = pkc;
add_kbnode(pub_root, new_kbnode( pkt ));
pkt = m_alloc_clear(sizeof *pkt);
pkt->pkttype = ret_skc ? PKT_SECRET_CERT : PKT_SECKEY_SUBCERT;
pkt->pkt.secret_cert = skc;
add_kbnode(sec_root, new_kbnode( pkt ));
return rc;
}
#endif /*ENABLE_RSA_KEYGEN*/
/****************
* Generate a DSA key
*/
@ -298,15 +288,12 @@ gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
pkc = m_alloc_clear( sizeof *pkc );
skc->timestamp = pkc->timestamp = make_timestamp();
skc->version = pkc->version = 4;
/* valid days are not stored in the packet, but it is
* used here to put it into the signature.
*/
skc->valid_days = pkc->valid_days = valid_days;
skc->pubkey_algo = pkc->pubkey_algo = PUBKEY_ALGO_DSA;
pkc->pkey[0] = skey[0];
pkc->pkey[1] = skey[1];
pkc->pkey[2] = skey[2];
pkc->pkey[3] = skey[3];
pkc->pkey[0] = mpi_copy( skey[0] );
pkc->pkey[1] = mpi_copy( skey[1] );
pkc->pkey[2] = mpi_copy( skey[2] );
pkc->pkey[3] = mpi_copy( skey[3] );
skc->skey[0] = skey[0];
skc->skey[1] = skey[1];
skc->skey[2] = skey[2];
@ -317,7 +304,7 @@ gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
skc->csum = checksum_mpi_counted_nbits( skc->skey[4] );
if( ret_skc ) /* not a subkey: return an unprotected version of the skc */
*ret_skc = copy_secret_cert( NULL, skc );
*ret_skc = copy_secret_cert( NULL, skc );
if( dek ) {
skc->protect.algo = dek->algo;
@ -383,47 +370,52 @@ check_valid_days( const char *s )
}
/****************
* Returns o to create both a DSA and a ElGamal key.
*/
static int
ask_algo( int *ret_v4 )
ask_algo( int *ret_v4, int addmode )
{
char *answer;
int algo;
tty_printf(_("Please select the algorithm to use:\n"
" (1) ElGamal is the suggested one.\n"
" (2) ElGamal using v4 packets (OpenPGP)\n"
" (3) DSA can only be used for signatures.\n"));
#ifdef ENABLE_RSA_KEYGEN
tty_printf(_(" (4) RSA cannot be used in the U.S.\n"));
#endif
tty_printf(_("Please select what kind of key you want:\n"));
if( !addmode )
tty_printf(_(" (%d) DSA and ElGamal (default)\n"), 1 );
tty_printf( _(" (%d) ElGamal (sign and encrypt)\n"), 2 );
tty_printf( _(" (%d) ElGamal (encrypt only)\n"), 3 );
tty_printf( _(" (%d) DSA (sign only)\n"), 4 );
tty_printf( _(" (%d) ElGamal in a v3 packet\n"), 5 );
*ret_v4 = 0;
*ret_v4 = 1;
for(;;) {
#ifdef ENABLE_RSA_KEYGEN
answer = tty_get(_("Your selection? (1,2,3,4) "));
#else
answer = tty_get(_("Your selection? (1,2,3) "));
#endif
answer = tty_get(_("Your selection? "));
tty_kill_prompt();
algo = *answer? atoi(answer): 1;
m_free(answer);
if( algo == 1 || algo == 2 ) {
if( algo == 2 )
*ret_v4 = 1;
if( algo == 1 && !addmode ) {
algo = 0; /* create both keys */
break;
}
else if( algo == 2 ) {
algo = PUBKEY_ALGO_ELGAMAL;
break;
}
else if( algo == 3 ) {
*ret_v4 = 1;
algo = PUBKEY_ALGO_ELGAMAL_E;
break;
}
else if( algo == 4 ) {
algo = PUBKEY_ALGO_DSA;
break;
}
#ifdef ENABLE_RSA_KEYGEN
else if( algo == 4 ) {
algo = PUBKEY_ALGO_RSA;
else if( algo == 5 ) {
algo = PUBKEY_ALGO_ELGAMAL_E;
*ret_v4 = 0;
break;
}
#endif
else
tty_printf(_("Invalid selection.\n"));
}
return algo;
}
@ -703,13 +695,9 @@ do_create( int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root,
"network and the disks) during the prime generation; this gives the random\n"
"number generator a better chance to gain enough entropy.\n") );
if( algo == PUBKEY_ALGO_ELGAMAL )
rc = gen_elg(nbits, pub_root, sec_root, dek, s2k,
if( algo == PUBKEY_ALGO_ELGAMAL || algo == PUBKEY_ALGO_ELGAMAL_E )
rc = gen_elg(algo, nbits, pub_root, sec_root, dek, s2k,
skc, valid_days, v4_packet? 4:3 );
#ifdef ENABLE_RSA_KEYGEN
else if( algo == PUBKEY_ALGO_RSA )
rc = gen_rsa(nbits, pub_root, sec_root, dek, s2k, skc, valid_days );
#endif
else if( algo == PUBKEY_ALGO_DSA )
rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, skc, valid_days);
else
@ -745,13 +733,19 @@ generate_keypair()
int algo;
int ndays;
int v4;
int both = 0;
if( opt.batch || opt.answer_yes || opt.answer_no ) {
log_error(_("Key generation can only be used in interactive mode\n"));
return;
}
algo = ask_algo( &v4 );
algo = ask_algo( &v4, 0 );
if( !algo ) {
algo = PUBKEY_ALGO_ELGAMAL;
both = 1;
tty_printf(_("DSA keypair will have 1024 bits.\n"));
}
nbits = ask_keysize( algo );
ndays = ask_valid_days();
uid = ask_user_id();
@ -774,7 +768,12 @@ generate_keypair()
pub_root = make_comment_node("#"); delete_kbnode(pub_root);
sec_root = make_comment_node("#"); delete_kbnode(sec_root);
rc = do_create( algo, nbits, pub_root, sec_root, dek, s2k, &skc, ndays, v4);
if( both )
rc = do_create( PUBKEY_ALGO_DSA, 1024, pub_root, sec_root,
dek, s2k, &skc, ndays, 1);
else
rc = do_create( algo, nbits, pub_root, sec_root,
dek, s2k, &skc, ndays, v4);
if( !rc )
write_uid(pub_root, uid );
if( !rc )
@ -784,6 +783,16 @@ generate_keypair()
if( !rc )
rc = write_selfsig(sec_root, pub_root, skc);
if( both ) {
rc = do_create( algo, nbits, pub_root, sec_root,
dek, s2k, NULL, ndays, 1 );
if( !rc )
rc = write_keybinding(pub_root, pub_root, skc);
if( !rc )
rc = write_keybinding(sec_root, pub_root, skc);
}
if( !rc ) {
KBPOS pub_kbpos;
KBPOS sec_kbpos;
@ -958,7 +967,8 @@ generate_subkeypair( const char *username )
goto leave;
algo = ask_algo( &v4 );
algo = ask_algo( &v4, 1 );
assert(algo);
nbits = ask_keysize( algo );
ndays = ask_valid_days();

View file

@ -50,6 +50,7 @@ u16 checksum_u16( unsigned n );
u16 checksum( byte *p, unsigned n );
u16 checksum_mpi( MPI a );
u16 checksum_mpi_counted_nbits( MPI a );
u32 buffer_to_u32( const byte *buffer );
/*-- encode.c --*/
int encode_symmetric( const char *filename );

View file

@ -232,25 +232,42 @@ static void
proc_plaintext( CTX c, PACKET *pkt )
{
PKT_plaintext *pt = pkt->pkt.plaintext;
int rc;
int any, rc;
KBNODE n;
if( opt.verbose )
log_info("original file name='%.*s'\n", pt->namelen, pt->name);
free_md_filter_context( &c->mfx );
/* FIXME: take the digest algo(s) to use from the
* onepass_sig packet (if we have these)
* And look at the sigclass to check whether we should use the
* textmode filter (sigclass 0x01)
/* fixme: look at the sigclass to check whether we should use the
* textmode filter (sigclass 0x01)
*/
c->mfx.md = md_open( DIGEST_ALGO_RMD160, 0);
/*md_start_debug(c->mfx.md, "proc_plaintext");*/
md_enable( c->mfx.md, DIGEST_ALGO_SHA1 );
md_enable( c->mfx.md, DIGEST_ALGO_MD5 );
if( !check_digest_algo(DIGEST_ALGO_TIGER) )
md_enable( c->mfx.md, DIGEST_ALGO_TIGER );
rc = handle_plaintext( pt, &c->mfx );
c->mfx.md = md_open( 0, 0);
any = 0;
for(n=c->list; n; n = n->next ) {
if( n->pkt->pkttype == PKT_ONEPASS_SIG
&& n->pkt->pkt.onepass_sig->digest_algo ) {
md_enable( c->mfx.md, n->pkt->pkt.onepass_sig->digest_algo );
any = 1;
}
}
if( !any ) { /* no onepass sig packet: enable all algos */
md_enable( c->mfx.md, DIGEST_ALGO_RMD160 );
md_enable( c->mfx.md, DIGEST_ALGO_SHA1 );
md_enable( c->mfx.md, DIGEST_ALGO_MD5 );
}
if( c->mfx.md ) {
m_check(c->mfx.md);
if( c->mfx.md->list )
m_check( c->mfx.md->list );
}
rc = handle_plaintext( pt, &c->mfx, c->sigs_only );
if( rc )
log_error( "handle plaintext failed: %s\n", g10_errstr(rc));
if( c->mfx.md ) {
m_check(c->mfx.md);
if( c->mfx.md->list )
m_check( c->mfx.md->list );
}
free_packet(pkt);
c->last_was_session_key = 0;
}
@ -312,6 +329,12 @@ do_check_sig( CTX c, KBNODE node, int *is_selfsig )
if( (rc=check_digest_algo(algo)) )
return rc;
if( c->mfx.md ) {
m_check(c->mfx.md);
if( c->mfx.md->list )
m_check( c->mfx.md->list );
}
if( sig->sig_class == 0x00 ) {
if( c->mfx.md )
md = md_copy( c->mfx.md );
@ -792,7 +815,7 @@ check_sig_and_print( CTX c, KBNODE node )
tstr = asctime(localtime (&stamp));
astr = pubkey_algo_to_string( sig->pubkey_algo );
log_info(_("Signature made %.*s using %s key ID %08lX\n"),
strlen(tstr)-1, tstr, astr? astr: "?", (ulong)sig->keyid[1] );
(int)strlen(tstr)-1, tstr, astr? astr: "?", (ulong)sig->keyid[1] );
rc = do_check_sig(c, node, NULL );
if( !rc || rc == G10ERR_BAD_SIGN ) {

View file

@ -152,3 +152,15 @@ checksum_mpi_counted_nbits( MPI a )
return csum;
}
u32
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;
}

View file

@ -276,7 +276,7 @@ int decrypt_data( PKT_encrypted *ed, DEK *dek );
int encrypt_data( PKT_encrypted *ed, DEK *dek );
/*-- plaintext.c --*/
int handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx );
int handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,int nooutput);
int ask_for_detached_datafile( md_filter_context_t *mfx, const char *inname );
/*-- comment.c --*/
@ -286,6 +286,8 @@ int write_comment( IOBUF out, const char *s );
int make_keysig_packet( PKT_signature **ret_sig, PKT_public_cert *pkc,
PKT_user_id *uid, PKT_public_cert *subpkc,
PKT_secret_cert *skc,
int sigclass, int digest_algo );
int sigclass, int digest_algo,
int (*mksubpkt)(PKT_signature *, void *),
void *opaque );
#endif /*G10_PACKET_H*/

View file

@ -32,6 +32,7 @@
#include "memory.h"
#include "filter.h"
#include "options.h"
#include "main.h"
static int mpi_print_mode = 0;
static int list_mode = 0;
@ -85,16 +86,6 @@ 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 )
@ -622,6 +613,8 @@ parse_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, size_t *ret_n )
*ret_n = n;
switch( type ) {
case SIGSUBPKT_SIG_CREATED:
case SIGSUBPKT_SIG_EXPIRE:
case SIGSUBPKT_KEY_EXPIRE:
if( n < 4 )
break;
return buffer;

View file

@ -40,16 +40,18 @@
* bytes from the plaintext.
*/
int
handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx )
handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, int nooutput )
{
char *fname;
char *fname = NULL;
FILE *fp = NULL;
int rc = 0;
int c;
int convert = pt->mode == 't';
/* create the filename as C string */
if( opt.outfile ) {
if( nooutput )
;
else if( opt.outfile ) {
fname = m_alloc( strlen( opt.outfile ) + 1);
strcpy(fname, opt.outfile );
}
@ -59,14 +61,16 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx )
fname[pt->namelen] = 0;
}
if( !*fname || (*fname=='-' && !fname[1])) {
if( nooutput )
;
else if( !*fname || (*fname=='-' && !fname[1])) {
/* no filename or "-" given; write to stdout */
fp = stdout;
}
else if( overwrite_filep( fname ) )
goto leave;
if( fp )
if( fp || nooutput )
;
else if( !(fp = fopen(fname,"wb")) ) {
log_error("Error creating '%s': %s\n", fname, strerror(errno) );
@ -86,10 +90,13 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx )
md_putc(mfx->md, c );
if( convert && c == '\r' )
continue; /* FIXME: this hack is too simple */
if( putc( c, fp ) == EOF ) {
log_error("Error writing to '%s': %s\n", fname, strerror(errno) );
rc = G10ERR_WRITE_FILE;
goto leave;
if( fp ) {
if( putc( c, fp ) == EOF ) {
log_error("Error writing to '%s': %s\n",
fname, strerror(errno) );
rc = G10ERR_WRITE_FILE;
goto leave;
}
}
}
}
@ -99,11 +106,13 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx )
md_putc(mfx->md, c );
if( convert && c == '\r' )
continue; /* FIXME: this hack is too simple */
if( putc( c, fp ) == EOF ) {
log_error("Error writing to '%s': %s\n",
fname, strerror(errno) );
rc = G10ERR_WRITE_FILE;
goto leave;
if( fp ) {
if( putc( c, fp ) == EOF ) {
log_error("Error writing to '%s': %s\n",
fname, strerror(errno) );
rc = G10ERR_WRITE_FILE;
goto leave;
}
}
}
iobuf_clear_eof(pt->buf);

View file

@ -159,7 +159,7 @@ gen_revoke( const char *uname )
/* create it */
rc = make_keysig_packet( &sig, pkc, NULL, NULL, skc, 0x20, 0);
rc = make_keysig_packet( &sig, pkc, NULL, NULL, skc, 0x20, 0, NULL, NULL);
if( rc ) {
log_error("make_keysig_packet failed: %s\n", g10_errstr(rc));
goto leave;

View file

@ -31,6 +31,7 @@
#include "cipher.h"
#include "main.h"
#include "status.h"
#include "i18n.h"
struct cmp_help_context_s {
PKT_signature *sig;
@ -148,6 +149,7 @@ do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest )
MPI result = NULL;
int rc=0;
struct cmp_help_context_s ctx;
u32 cur_time;
if( pkc->version == 4 && pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) {
log_info("this is a PGP generated "
@ -158,6 +160,21 @@ do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest )
if( pkc->timestamp > sig->timestamp )
return G10ERR_TIME_CONFLICT; /* pubkey newer that signature */
cur_time = make_timestamp();
if( pkc->timestamp > cur_time ) {
log_info(_("public key created in future (time warp or clock problem)\n"));
return G10ERR_TIME_CONFLICT;
}
if( pkc->valid_days && add_days_to_timestamp(pkc->timestamp,
pkc->valid_days) < cur_time ) {
log_info(_("warning: signature key expired %s\n"), strtimestamp(
add_days_to_timestamp(pkc->timestamp,
pkc->valid_days)));
write_status(STATUS_SIGEXPIRED);
}
if( (rc=check_digest_algo(sig->digest_algo)) )
return rc;
if( (rc=check_pubkey_algo(sig->pubkey_algo)) )

View file

@ -98,7 +98,22 @@ hash_for(int pubkey_algo )
return DEFAULT_DIGEST_ALGO;
}
static int
only_old_style( SKC_LIST skc_list )
{
SKC_LIST skc_rover = NULL;
int old_style = 0;
/* if there are only old style capable key we use the old sytle */
for( skc_rover = skc_list; skc_rover; skc_rover = skc_rover->next ) {
PKT_secret_cert *skc = skc_rover->skc;
if( skc->pubkey_algo == PUBKEY_ALGO_RSA && skc->version < 4 )
old_style = 1;
else
return 0;
}
return old_style;
}
/****************
* Sign the files whose names are in FILENAME.
@ -131,6 +146,8 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
SKC_LIST skc_list = NULL;
SKC_LIST skc_rover = NULL;
int multifile = 0;
int old_style = opt.rfc1991;
memset( &afx, 0, sizeof afx);
memset( &zfx, 0, sizeof zfx);
@ -151,6 +168,8 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
if( (rc=build_skc_list( locusr, &skc_list, 1, 1 )) )
goto leave;
if( !old_style )
old_style = only_old_style( skc_list );
if( encrypt ) {
if( (rc=build_pkc_list( remusr, &pkc_list, 2 )) )
goto leave;
@ -204,11 +223,13 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
iobuf_push_filter( out, encrypt_filter, &efx );
}
if( opt.compress && !outfile )
if( opt.compress && !outfile ) {
if( old_style )
zfx.algo = 1;
iobuf_push_filter( out, compress_filter, &zfx );
}
if( !detached && !opt.rfc1991 ) {
if( !detached && !old_style ) {
/* loop over the secret certificates and build headers */
for( skc_rover = skc_list; skc_rover; skc_rover = skc_rover->next ) {
PKT_secret_cert *skc;
@ -439,6 +460,7 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
int rc = 0;
SKC_LIST skc_list = NULL;
SKC_LIST skc_rover = NULL;
int old_style = opt.rfc1991;
memset( &afx, 0, sizeof afx);
memset( &tfx, 0, sizeof tfx);
@ -446,6 +468,8 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
if( (rc=build_skc_list( locusr, &skc_list, 1, 1 )) )
goto leave;
if( !old_style )
old_style = only_old_style( skc_list );
/* prepare iobufs */
if( !(inp = iobuf_open(fname)) ) {
@ -469,9 +493,9 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
goto leave;
}
/* FIXME: This stuff is not correct if mutliple hash algos are used*/
/* FIXME: This stuff is not correct if multiple hash algos are used*/
iobuf_writestr(out, "-----BEGIN PGP SIGNED MESSAGE-----\n" );
if( opt.rfc1991
if( old_style
|| (opt.def_digest_algo?opt.def_digest_algo:DEFAULT_DIGEST_ALGO)
== DIGEST_ALGO_MD5 )
iobuf_writestr(out, "\n" );

View file

@ -53,6 +53,7 @@ write_status_text( int no, const char *text)
case STATUS_LEAVE : s = "LEAVE\n"; break;
case STATUS_ABORT : s = "ABORT\n"; break;
case STATUS_GOODSIG: s = "GOODSIG\n"; break;
case STATUS_SIGEXPIRED: s = "SIGEXPIRED\n"; break;
case STATUS_BADSIG : s = "BADSIG\n"; break;
case STATUS_ERRSIG : s = "ERRSIG\n"; break;
case STATUS_BADARMOR : s = "BADARMOR\n"; break;

View file

@ -33,7 +33,7 @@
#define STATUS_BADARMOR 7
#define STATUS_RSA_OR_IDEA 8
#define STATUS_SIGEXPIRED 9
/*-- status.c --*/
void set_status_fd( int fd );

View file

@ -1705,7 +1705,7 @@ check_trust( PKT_public_cert *pkc, unsigned *r_trustlevel )
TRUSTREC rec;
unsigned trustlevel = TRUST_UNKNOWN;
int rc=0;
int cur_time;
u32 cur_time;
if( DBG_TRUST )
log_info("check_trust() called.\n");