diff options
Diffstat (limited to 'g10')
-rw-r--r-- | g10/Makefile.am | 6 | ||||
-rw-r--r-- | g10/Makefile.in | 6 | ||||
-rw-r--r-- | g10/armor.c | 76 | ||||
-rw-r--r-- | g10/comment.c | 27 | ||||
-rw-r--r-- | g10/g10.c | 18 | ||||
-rw-r--r-- | g10/g10maint.c | 12 | ||||
-rw-r--r-- | g10/keygen.c | 9 | ||||
-rw-r--r-- | g10/keyid.c | 10 | ||||
-rw-r--r-- | g10/main.h | 1 | ||||
-rw-r--r-- | g10/parse-packet.c | 4 | ||||
-rw-r--r-- | g10/plaintext.c | 6 | ||||
-rw-r--r-- | g10/pubring.g10 | bin | 0 -> 3017 bytes | |||
-rw-r--r-- | g10/sign.c | 27 |
13 files changed, 168 insertions, 34 deletions
diff --git a/g10/Makefile.am b/g10/Makefile.am index b0a2e9293..5bb3db24b 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -1,7 +1,7 @@ ## Process this file with automake to produce Makefile.in -INCLUDES = -I.. -I$(top_srcdir)/include -EXTRA_DIST = OPTIONS +INCLUDES = -I$(top_srcdir)/include +EXTRA_DIST = OPTIONS pubring.g10 needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a bin_PROGRAMS = g10 g10maint @@ -55,7 +55,7 @@ g10_SOURCES = g10.c \ g10maint_SOURCES = g10maint.c \ $(common_source) -LDADD = $(needed_libs) +LDADD = @INTLLIBS@ $(needed_libs) $(PROGRAMS): $(needed_libs) diff --git a/g10/Makefile.in b/g10/Makefile.in index 808d99fdb..6bcb29e40 100644 --- a/g10/Makefile.in +++ b/g10/Makefile.in @@ -86,8 +86,8 @@ POSUB = @POSUB@ RANLIB = @RANLIB@ VERSION = @VERSION@ -INCLUDES = -I.. -I$(top_srcdir)/include -EXTRA_DIST = OPTIONS +INCLUDES = -I$(top_srcdir)/include +EXTRA_DIST = OPTIONS pubring.g10 needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a bin_PROGRAMS = g10 g10maint @@ -140,7 +140,7 @@ g10_SOURCES = g10.c \ g10maint_SOURCES = g10maint.c \ $(common_source) -LDADD = $(needed_libs) +LDADD = @INTLLIBS@ $(needed_libs) mkinstalldirs = $(SHELL) $(top_srcdir)/scripts/mkinstalldirs CONFIG_HEADER = ../config.h CONFIG_CLEAN_FILES = diff --git a/g10/armor.c b/g10/armor.c index e397346cc..37e37e726 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -172,6 +172,52 @@ invalid_armor(void) /**************** + * check wether the armor header is valid on a signed message. + * this is for security reasons: the header lines are not included in the + * hash and by using some creative formatting rules, Mallory could fake + * any text at the beginning of a document; assuming it is read with + * a simple viewer. We do only allow the Hash Header. + */ +static int +parse_hash_header( const char *line ) +{ + const char *s, *s2; + unsigned found = 0; + + if( strlen(line) < 6 || strlen(line) > 60 ) + return 0; /* too short or too long */ + if( memcmp( line, "Hash:", 5 ) ) + return 0; /* invalid header */ + s = line+5; + for(s=line+5;;s=s2) { + for(; *s && (*s==' ' || *s == '\t'); s++ ) + ; + if( !*s ) + break; + for(s2=s+1; *s2 && *s2!=' ' && *s2 != '\t' && *s2 != ','; s2++ ) + ; + if( !strncmp( s, "RIPEMD160", s2-s ) ) + found |= 1; + else if( !strncmp( s, "SHA1", s2-s ) ) + found |= 2; + else if( !strncmp( s, "MD5", s2-s ) ) + found |= 4; + else if( !strncmp( s, "MD2", s2-s ) ) + found |= 8; + else + return 0; + for(; *s2 && (*s2==' ' || *s2 == '\t'); s2++ ) + ; + if( *s2 && *s2 != ',' ) + return 0; + if( *s2 ) + s2++; + } + return found; +} + + +/**************** * parse an ascii armor. * Returns: the state, * the remaining bytes in BUF are returned in RBUFLEN. @@ -197,15 +243,17 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, do { switch( state ) { case fhdrHASArmor: - /* read 28 bytes, which is the bare minimum for a BEGIN... - * and check wether this has a Armor. */ + /* read at least the first byte to check wether it is armored + * or not */ c = 0; for(n=0; n < 28 && (c=iobuf_get2(a)) != -1 && c != '\n'; ) buf[n++] = c; - if( n < 28 || c == -1 ) + if( !n || c == -1 ) state = fhdrNOArmor; /* too short */ else if( !is_armored( buf ) ) state = fhdrNOArmor; + else if( c == '\n' ) + state = fhdrCHECKBegin; else state = fhdrINITCont; break; @@ -243,7 +291,12 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, log_debug("armor header: "); print_string( stderr, buf, n ); putc('\n', stderr); - state = fhdrWAITHeader; + if( clearsig && !parse_hash_header( buf ) ) { + log_error("invalid clearsig header\n"); + state = fhdrERROR; + } + else + state = fhdrWAITHeader; } else state = fhdrCHECKDashEscaped3; @@ -605,7 +658,6 @@ fake_packet( armor_filter_context_t *afx, IOBUF a, break; case fhdrENDClearsig: - log_debug("endclearsig: emplines=%u n=%u\n", emplines, n ); assert( emplines ); emplines--; /* don't count the last one */ state = fhdrENDClearsigHelp; @@ -760,12 +812,14 @@ armor_filter( void *opaque, int control, int idx, idx2; size_t n=0; u32 crc; + #if 1 static FILE *fp ; if( !fp ) { fp = fopen("armor.out", "w"); assert(fp); } + #endif if( DBG_FILTER ) log_debug("armor-filter: control: %d\n", control ); @@ -794,8 +848,14 @@ armor_filter( void *opaque, int control, rc = fake_packet( afx, a, &n, buf, size ); else if( !afx->inp_checked ) { rc = check_input( afx, a ); - if( afx->inp_bypass ) - ; + if( afx->inp_bypass ) { + for( n=0; n < size && n < afx->helplen; n++ ) + buf[n] = afx->helpbuf[n]; + if( !n ) + rc = -1; + assert( n == afx->helplen ); + afx->helplen = 0; + } else if( afx->faked ) { /* the buffer is at least 30 bytes long, so it * is easy to construct the packets */ @@ -824,9 +884,11 @@ armor_filter( void *opaque, int control, } else rc = radix64_read( afx, a, &n, buf, size ); + #if 1 if( n ) if( fwrite(buf, n, 1, fp ) != 1 ) BUG(); + #endif *ret_len = n; } else if( control == IOBUFCTRL_FLUSH ) { diff --git a/g10/comment.c b/g10/comment.c index 00bbac7dd..ce2e6cc4c 100644 --- a/g10/comment.c +++ b/g10/comment.c @@ -69,3 +69,30 @@ make_comment_node( const char *s ) } +KBNODE +make_mpi_comment_node( const char *s, MPI a ) +{ + PACKET *pkt; + byte *buf, *p, *pp; + unsigned n1, nb1; + size_t n = strlen(s); + + nb1 = mpi_get_nbits( a ); + p = buf = mpi_get_buffer( a, &n1, NULL ); + for( ; !*p && n1; p++, n1-- ) /* skip leading null bytes */ + ; + + pkt = m_alloc_clear( sizeof *pkt ); + pkt->pkttype = PKT_COMMENT; + pkt->pkt.comment = m_alloc( sizeof *pkt->pkt.comment + n + 2 + n1 ); + pkt->pkt.comment->len = n+1+2+n1; + pp = pkt->pkt.comment->data; + memcpy(pp, s, n+1); + pp[n+1] = nb1 >> 8; + pp[n+2] = nb1 ; + memcpy(pp+n+3, p, n1 ); + m_free(buf); + return new_kbnode( pkt ); +} + + @@ -101,8 +101,12 @@ strusage( int level ) static void i18n_init(void) { - #ifdef ENABLE_NLS - setlocale( LC_MESSAGES, "" ); + #ifdef HAVE_LIBINTL + #ifdef HAVE_LC_MESSAGES + setlocale( LC_MESSAGES, "" ); + #else + setlocale( LC_ALL, "" ); + #endif bindtextdomain( PACKAGE, G10_LOCALEDIR ); textdomain( PACKAGE ); #endif @@ -235,8 +239,10 @@ main( int argc, char **argv ) enum cmd_values cmd = 0; const char *trustdb_name = NULL; - - secmem_init( 16384 ); + /* Please note that we may running SUID(ROOT), so be very CAREFUL + * when adding any stuff between here and the call to + * secmem_init() somewhere after the option parsing + */ i18n_init(); opt.compress = -1; /* defaults to standard compress level */ @@ -397,6 +403,10 @@ main( int argc, char **argv ) if( errors ) g10_exit(2); + /* initialize the secure memory. */ + secmem_init( 16384 ); + /* Okay, we are now working under our real uid */ + write_status( STATUS_ENTER ); set_debug(); diff --git a/g10/g10maint.c b/g10/g10maint.c index a6ba7dc63..4352045c1 100644 --- a/g10/g10maint.c +++ b/g10/g10maint.c @@ -101,8 +101,12 @@ strusage( int level ) static void i18n_init(void) { - #ifdef ENABLE_NLS - setlocale( LC_MESSAGES, "" ); + #ifdef HAVE_LIBINTL + #ifdef HAVE_LC_MESSAGES + setlocale( LC_MESSAGES, "" ); + #else + setlocale( LC_ALL, "" ); + #endif bindtextdomain( PACKAGE, G10_LOCALEDIR ); textdomain( PACKAGE ); #endif @@ -449,13 +453,13 @@ main( int argc, char **argv ) } else if( argc == 2 ) { mpi_print( stdout, generate_elg_prime( atoi(argv[0]), - atoi(argv[1]), NULL ), 1); + atoi(argv[1]), NULL,NULL ), 1); putchar('\n'); } else if( argc == 3 ) { MPI g = mpi_alloc(1); mpi_print( stdout, generate_elg_prime( atoi(argv[0]), - atoi(argv[1]), g ), 1); + atoi(argv[1]), g, NULL ), 1); printf("\nGenerator: "); mpi_print( stdout, g, 1 ); putchar('\n'); diff --git a/g10/keygen.c b/g10/keygen.c index a817463db..d73573cb1 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -145,13 +145,15 @@ gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, PKT_secret_cert **ret_skc ) { int rc; + int i; PACKET *pkt; PKT_secret_cert *skc; PKT_public_cert *pkc; ELG_public_key pk; ELG_secret_key sk; + MPI *factors; - elg_generate( &pk, &sk, nbits ); + elg_generate( &pk, &sk, nbits, &factors ); skc = m_alloc_clear( sizeof *skc ); pkc = m_alloc_clear( sizeof *pkc ); @@ -190,10 +192,15 @@ gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, pkt->pkt.public_cert = pkc; add_kbnode(pub_root, new_kbnode( pkt )); + /* don't know wether it make sense to have the factors, so for now + * we store them in the secret keyring (but they are of secret) */ pkt = m_alloc_clear(sizeof *pkt); pkt->pkttype = PKT_SECRET_CERT; pkt->pkt.secret_cert = skc; add_kbnode(sec_root, new_kbnode( pkt )); + for(i=0; factors[i]; i++ ) + add_kbnode( sec_root, + make_mpi_comment_node("#:ELG_factor:", factors[i] )); return 0; } diff --git a/g10/keyid.c b/g10/keyid.c index 5d5a043c5..6e7b120e6 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -59,14 +59,18 @@ v3_elg_fingerprint_md( PKT_public_cert *pkc ) byte *buf1, *buf2, *buf3; byte *p1, *p2, *p3; unsigned n1, n2, n3; + unsigned nb1, nb2, nb3; unsigned n; + nb1 = mpi_get_nbits(pkc->d.elg.p); p1 = buf1 = mpi_get_buffer( pkc->d.elg.p, &n1, NULL ); for( ; !*p1 && n1; p1++, n1-- ) /* skip leading null bytes */ ; + nb2 = mpi_get_nbits(pkc->d.elg.g); p2 = buf2 = mpi_get_buffer( pkc->d.elg.g, &n2, NULL ); for( ; !*p2 && n2; p2++, n2-- ) /* skip leading null bytes */ ; + nb3 = mpi_get_nbits(pkc->d.elg.y); p3 = buf3 = mpi_get_buffer( pkc->d.elg.y, &n3, NULL ); for( ; !*p3 && n3; p3++, n3-- ) /* skip leading null bytes */ ; @@ -90,9 +94,9 @@ v3_elg_fingerprint_md( PKT_public_cert *pkc ) md_putc( md, a ); } md_putc( md, pkc->pubkey_algo ); - md_putc( md, n1>>8); md_putc( md, n1 ); md_write( md, p1, n1 ); - md_putc( md, n2>>8); md_putc( md, n2 ); md_write( md, p2, n2 ); - md_putc( md, n3>>8); md_putc( md, n3 ); md_write( md, p3, n3 ); + 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 ); m_free(buf1); m_free(buf2); m_free(buf3); diff --git a/g10/main.h b/g10/main.h index 67091e7b4..55b99cef1 100644 --- a/g10/main.h +++ b/g10/main.h @@ -76,6 +76,7 @@ MPI encode_md_value( MD_HANDLE md, unsigned nbits ); /*-- comment.c --*/ KBNODE make_comment_node( const char *s ); +KBNODE make_mpi_comment_node( const char *s, MPI a ); /*-- elg.c --*/ void g10_elg_encrypt( PKT_public_cert *pkc, PKT_pubkey_enc *enc, DEK *dek ); diff --git a/g10/parse-packet.c b/g10/parse-packet.c index f364d3b7b..c49b6f513 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -714,7 +714,7 @@ parse_subkey( IOBUF inp, int pkttype, unsigned long pktlen ) version = iobuf_get_noeof(inp); pktlen--; if( pkttype == PKT_PUBKEY_SUBCERT && version == '#' ) { /* early versions of G10 use old comments packets; luckily all those - * comments are are started by a hash */ + * comments are started by a hash */ if( list_mode ) { printf(":old comment packet: \"" ); for( ; pktlen; pktlen-- ) { @@ -829,8 +829,6 @@ parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt ) pktlen = 0; if( list_mode ) { - /* a value if 'c' is used by armor to indicate a faked packet - * it should be considered as 't' */ printf(":literal data packet:\n" "\tmode %c, created %lu, name=\"", mode >= ' ' && mode <'z'? mode : '?', diff --git a/g10/plaintext.c b/g10/plaintext.c index ea43a1e6f..196da81f4 100644 --- a/g10/plaintext.c +++ b/g10/plaintext.c @@ -45,6 +45,10 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx ) FILE *fp = NULL; int rc = 0; int c; +static FILE *abc; +if( !abc ) + abc=fopen("plaintext.out", "wb"); +if( !abc ) BUG(); /* create the filename as C string */ if( opt.outfile ) { @@ -78,6 +82,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx ) rc = G10ERR_READ_FILE; goto leave; } + putc( c, abc ); if( mfx->md ) md_putc(mfx->md, c ); if( putc( c, fp ) == EOF ) { @@ -89,6 +94,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx ) } else { while( (c = iobuf_get(pt->buf)) != -1 ) { + putc( c, abc ); if( mfx->md ) md_putc(mfx->md, c ); if( putc( c, fp ) == EOF ) { diff --git a/g10/pubring.g10 b/g10/pubring.g10 Binary files differnew file mode 100644 index 000000000..f458371d4 --- /dev/null +++ b/g10/pubring.g10 diff --git a/g10/sign.c b/g10/sign.c index 010c6bcc3..883a8d4f1 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -144,7 +144,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, } /* prepare to calculate the MD over the input */ - if( opt.textmode && opt.armor && !outfile ) + if( opt.textmode && !outfile ) iobuf_push_filter( inp, text_filter, &tfx ); mfx.md = md_open(DIGEST_ALGO_RMD160, 0); if( !multifile ) @@ -301,22 +301,36 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, +/**************** + * note: we do not count empty lines at the beginning + */ static int write_dash_escaped( IOBUF inp, IOBUF out, MD_HANDLE md ) { int c; int lastlf = 1; + int skip_empty = 1; while( (c = iobuf_get(inp)) != -1 ) { /* Note: We don't escape "From " because the MUA should cope with it */ - if( lastlf && c == '-' ) { - iobuf_put( out, c ); - iobuf_put( out, ' ' ); + if( lastlf ) { + if( c == '-' ) { + iobuf_put( out, c ); + iobuf_put( out, ' ' ); + skip_empty = 0; + } + else if( skip_empty && c == '\r' ) + skip_empty = 2; + else + skip_empty = 0; } - md_putc(md, c ); + if( !skip_empty ) + md_putc(md, c ); iobuf_put( out, c ); lastlf = c == '\n'; + if( skip_empty == 2 ) + skip_empty = lastlf ? 0 : 1; } return 0; /* fixme: add error handling */ } @@ -368,7 +382,8 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) goto leave; } - iobuf_writestr(out, "-----BEGIN PGP SIGNED MESSAGE-----\n\n" ); + iobuf_writestr(out, "-----BEGIN PGP SIGNED MESSAGE-----\n" + "Hash: RIPEMD160\n\n" ); textmd = md_open(DIGEST_ALGO_RMD160, 0); iobuf_push_filter( inp, text_filter, &tfx ); |