diff options
Diffstat (limited to 'g10/encode.c')
-rw-r--r-- | g10/encode.c | 167 |
1 files changed, 162 insertions, 5 deletions
diff --git a/g10/encode.c b/g10/encode.c index 5b599ef00..ad8d3f720 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -56,8 +56,51 @@ typedef struct { } cipher_filter_context_t; +typedef struct { + int status; + int what; + byte buf[3]; + int idx, idx2; + u32 crc; +} armor_filter_context_t; + +#define CRCINIT 0xB704CE +#define CRCPOLY 0X864CFB +#define CRCUPDATE(a,c) do { \ + a = ((a) << 8) ^ crc_table[((a)&0xff >> 16) ^ (c)]; \ + a &= 0x00ffffff; \ + } while(0) +static u32 crc_table[256]; +static int crc_table_initialized; + + + +static void +init_crc_table(void) +{ + int i, j; + u32 t; + + crc_table[0] = 0; + for(i=j=0; j < 128; j++ ) { + t = crc_table[j]; + if( t & 0x00800000 ) { + t <<= 1; + crc_table[i++] = t ^ CRCPOLY; + crc_table[i++] = t; + } + else { + t <<= 1; + crc_table[i++] = t; + crc_table[i++] = t ^ CRCPOLY; + } + } + + crc_table_initialized=1; +} + /**************** @@ -106,8 +149,10 @@ encode_simple( const char *filename, int mode ) int rc = 0; u32 filesize; cipher_filter_context_t cfx; + armor_filter_context_t afx; memset( &cfx, 0, sizeof cfx); + memset( &afx, 0, sizeof afx); /* prepare iobufs */ if( !(inp = iobuf_open(filename)) ) { @@ -135,7 +180,7 @@ encode_simple( const char *filename, int mode ) } if( opt.armor ) - iobuf_push_filter( out, armor_filter, NULL ); + iobuf_push_filter( out, armor_filter, &afx ); write_comment( out, "#Created by G10 pre-release " VERSION ); @@ -197,11 +242,13 @@ encode_crypt( const char *filename, STRLIST remusr ) int last_rc, rc = 0; u32 filesize; cipher_filter_context_t cfx; + armor_filter_context_t afx; int any_names = 0; STRLIST local_remusr = NULL; char *ustr; memset( &cfx, 0, sizeof cfx); + memset( &afx, 0, sizeof afx); if( !remusr ) { remusr = NULL; /* fixme: ask */ @@ -225,7 +272,7 @@ encode_crypt( const char *filename, STRLIST remusr ) } if( opt.armor ) - iobuf_push_filter( out, armor_filter, NULL ); + iobuf_push_filter( out, armor_filter, &afx ); write_comment( out, "#Created by G10 pre-release " VERSION ); @@ -389,11 +436,121 @@ open_outfile( const char *iname ) static int armor_filter( void *opaque, int control, - IOBUF chain, byte *buf, size_t *ret_len) + IOBUF a, byte *buffer, size_t *ret_len) { - if( control == IOBUFCTRL_DESC ) { - *(char**)buf = "armor_filter"; + static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + size_t size = *ret_len; + armor_filter_context_t *afx = opaque; + int rc=0, i, c; + byte buf[3]; + int idx, idx2; + u32 crc; + + + if( control == IOBUFCTRL_FLUSH ) { + if( !afx->status ) { /* write the header line */ + if( !afx->what ) + iobuf_writestr(a, "-----BEGIN PGP MESSAGE-----\n"); + else + iobuf_writestr(a, "-----BEGIN PGP PUBLIC KEY BLOCK-----\n"); + iobuf_writestr(a, "Version: G10 pre-release " VERSION "\n"); + iobuf_writestr(a, "Comment: This is a alpha test version!\n\n"); + afx->status++; + afx->idx = 0; + afx->idx2 = 0; + afx->crc = CRCINIT; + } + crc = afx->crc; + idx = afx->idx; + idx2 = afx->idx2; + for(i=0; i < idx; i++ ) + buf[i] = afx->buf[i]; + + for(i=0; i < size; i++ ) + crc = (crc << 8) ^ crc_table[(crc >> 16)&0xff ^ buffer[i]]; + crc &= 0x00ffffff; + + for( ; size; buffer++, size-- ) { + buf[idx++] = *buffer; + if( idx > 2 ) { + idx = 0; + c = bintoasc[(*buf >> 2) & 077]; + iobuf_put(a, c); + c = bintoasc[(((*buf<<4)&060)|((buf[1] >> 4)&017))&077]; + iobuf_put(a, c); + c = bintoasc[(((buf[1]<<2)&074)|((buf[2]>>6)&03))&077]; + iobuf_put(a, c); + c = bintoasc[buf[2]&077]; + iobuf_put(a, c); + if( ++idx2 > (72/4) ) { + iobuf_put(a, '\n'); + idx2=0; + } + } + } + for(i=0; i < idx; i++ ) + afx->buf[i] = buf[i]; + afx->idx = idx; + afx->idx2 = idx2; + afx->crc = crc; } + else if( control == IOBUFCTRL_INIT ) { + if( !crc_table_initialized ) + init_crc_table(); + } + else if( control == IOBUFCTRL_FREE ) { + if( afx->status ) { /* pad, write cecksum, and bottom line */ + crc = afx->crc; + idx = afx->idx; + idx2 = afx->idx2; + for(i=0; i < idx; i++ ) + buf[i] = afx->buf[i]; + if( idx ) { + c = bintoasc[(*buf>>2)&077]; + iobuf_put(a, c); + if( idx == 1 ) { + c = bintoasc[((*buf << 4) & 060) & 077]; + iobuf_put(a, c); + iobuf_put(a, '='); + iobuf_put(a, '='); + } + else { /* 2 */ + c = bintoasc[(((*buf<<4)&060)|((buf[1]>>4)&017))&077]; + iobuf_put(a, c); + c = bintoasc[((buf[1] << 2) & 074) & 077]; + iobuf_put(a, c); + iobuf_put(a, '='); + } + ++idx2; + } + /* may need a linefeed */ + if( idx2 < (72/4) ) + iobuf_put(a, '\n'); + /* write the CRC */ + iobuf_put(a, '='); + buf[0] = crc >>16; + buf[1] = crc >> 8; + buf[2] = crc; + c = bintoasc[(*buf >> 2) & 077]; + iobuf_put(a, c); + c = bintoasc[(((*buf<<4)&060)|((buf[1] >> 4)&017))&077]; + iobuf_put(a, c); + c = bintoasc[(((buf[1]<<2)&074)|((buf[2]>>6)&03))&077]; + iobuf_put(a, c); + c = bintoasc[buf[2]&077]; + iobuf_put(a, c); + iobuf_put(a, '\n'); + /* and the the trailer */ + if( !afx->what ) + iobuf_writestr(a, "-----END PGP MESSAGE-----\n"); + else + iobuf_writestr(a, "-----END PGP PUBLIC KEY BLOCK-----\n"); + } + } + else if( control == IOBUFCTRL_DESC ) + *(char**)buf = "armor_filter"; return 0; } |