diff options
author | Simon Josefsson <simon@josefsson.org> | 2007-05-12 13:18:45 +0000 |
---|---|---|
committer | Simon Josefsson <simon@josefsson.org> | 2007-05-12 13:18:45 +0000 |
commit | 6d09e7df5fcf8c48ee5e14cd6779adaeaa3083bd (patch) | |
tree | 24198ddf6278b3fca3225349f12dd8126053c927 /libextra | |
parent | d208af15de2affa8942be09f2914b09f3b7905a1 (diff) | |
download | gnutls-6d09e7df5fcf8c48ee5e14cd6779adaeaa3083bd.tar.gz |
Update.
Diffstat (limited to 'libextra')
-rw-r--r-- | libextra/opencdk/armor.c | 4 | ||||
-rw-r--r-- | libextra/opencdk/cipher.c | 209 | ||||
-rw-r--r-- | libextra/opencdk/compress.c | 296 | ||||
-rw-r--r-- | libextra/opencdk/context.h | 9 | ||||
-rw-r--r-- | libextra/opencdk/filters.h | 64 | ||||
-rw-r--r-- | libextra/opencdk/kbnode.c | 42 | ||||
-rw-r--r-- | libextra/opencdk/keydb.c | 118 | ||||
-rw-r--r-- | libextra/opencdk/literal.c | 159 | ||||
-rw-r--r-- | libextra/opencdk/main.c | 52 | ||||
-rw-r--r-- | libextra/opencdk/main.h | 35 | ||||
-rw-r--r-- | libextra/opencdk/misc.c | 230 | ||||
-rw-r--r-- | libextra/opencdk/opencdk.h | 197 | ||||
-rw-r--r-- | libextra/opencdk/pubkey.c | 19 | ||||
-rw-r--r-- | libextra/opencdk/read-packet.c | 189 | ||||
-rw-r--r-- | libextra/opencdk/sig-check.c | 34 | ||||
-rw-r--r-- | libextra/opencdk/stream.c | 183 | ||||
-rw-r--r-- | libextra/opencdk/verify.c | 4 | ||||
-rw-r--r-- | libextra/opencdk/write-packet.c | 587 |
18 files changed, 1347 insertions, 1084 deletions
diff --git a/libextra/opencdk/armor.c b/libextra/opencdk/armor.c index 48164f2e77..07d3b39134 100644 --- a/libextra/opencdk/armor.c +++ b/libextra/opencdk/armor.c @@ -659,6 +659,8 @@ cdk_armor_encode_buffer (const byte *inbuf, size_t inlen, char tempout[128]; size_t pos, off, len, rest; + if (!inbuf || !nwritten) + return CDK_Inv_Value; if (type > CDK_ARMOR_SIGNATURE) return CDK_Inv_Mode; @@ -706,6 +708,8 @@ cdk_armor_encode_buffer (const byte *inbuf, size_t inlen, memcpy (outbuf+pos, tempout, strlen (tempout)); pos += strlen (tempout); memcpy (outbuf+pos, le, strlen (le)); pos += strlen (le); } + + /* FIXME: We do not generate a CRC for the data, which is legal. */ memcpy (outbuf+pos, "-----", 5); pos += 5; memcpy (outbuf+pos, tail, strlen (tail)); pos += strlen (tail); memcpy (outbuf+pos, "-----", 5); pos += 5; diff --git a/libextra/opencdk/cipher.c b/libextra/opencdk/cipher.c index 90ddce6d84..3fb7f94e55 100644 --- a/libextra/opencdk/cipher.c +++ b/libextra/opencdk/cipher.c @@ -26,16 +26,12 @@ #include "filters.h" -/* FIXME: We cannot use a static progress callback because the library - might be MT. We need a progress cb per context. */ - - static off_t fp_get_length (FILE *fp) { struct stat statbuf; - if (fstat( fileno (fp), &statbuf)) + if (fstat (fileno (fp), &statbuf)) return (off_t)-1; return statbuf.st_size; } @@ -52,7 +48,7 @@ hash_encode (void *opaque, FILE *in, FILE *out) if (!mfx) return CDK_Inv_Value; - _cdk_log_debug( "hash filter: encode (algo=%d)\n", mfx->digest_algo ); + _cdk_log_debug ("hash filter: encode (algo=%d)\n", mfx->digest_algo); if (!mfx->md) { @@ -106,13 +102,15 @@ write_header (cipher_filter_t *cfx, FILE *out) cdk_error_t rc = 0; gcry_error_t err; - blocksize = gcry_cipher_get_algo_blklen( dek->algo ); + blocksize = gcry_cipher_get_algo_blklen (dek->algo); if (blocksize < 8 || blocksize > 16) return CDK_Inv_Algo; + /* It might be possible the receiver does not understand the MDC + output and thus we offer to supress the MDC packet. */ use_mdc = dek->use_mdc; - if (blocksize != 8) - use_mdc = 1; /* Enabled by default for all 128-bit block cipher */ + if (blocksize == 8) + use_mdc = 0; /* Enabled by default for all 128-bit block cipher */ if (use_mdc && cfx->datalen) cfx->datalen += 22; @@ -125,7 +123,7 @@ write_header (cipher_filter_t *cfx, FILE *out) ed->extralen = blocksize + 2; } else - cfx->blkmode.nleft = BUFSIZE; + cfx->blkmode.nleft = DEF_BLOCKSIZE; if (use_mdc) { @@ -135,7 +133,12 @@ write_header (cipher_filter_t *cfx, FILE *out) return map_gcry_error (err); } - pkt->old_ctb = cfx->dek->rfc1991 && !cfx->blkmode.on? 1 : 0; + /* When we use partial bodies, the MDC feature or a blocksize + larger than 8, we force the use of the new packet format. */ + if (cfx->blkmode.on || use_mdc || blocksize != 8) + pkt->old_ctb = 0; + else + pkt->old_ctb = 1; pkt->pkttype = use_mdc? CDK_PKT_ENCRYPTED_MDC : CDK_PKT_ENCRYPTED; rc = _cdk_pkt_write_fp (out, pkt); cdk_pkt_release (pkt); @@ -163,9 +166,9 @@ write_header (cipher_filter_t *cfx, FILE *out) fwrite (temp, 1, nprefix+2, out); if (cfx->blkmode.on) { - cfx->blkmode.nleft -= (blocksize+2); + cfx->blkmode.nleft -= (nprefix+2); if (use_mdc) - cfx->blkmode.nleft -= (22+1); /* 22 mdc packet, 1 byte version */ + cfx->blkmode.nleft--; /* 1 byte version */ } return rc; } @@ -183,7 +186,7 @@ write_mdc_packet (FILE *out, cipher_filter_t *cfx) return CDK_Inv_Algo; /* We must hash the prefix of the MDC packet here */ - pktdata[0] = 0xd3; + pktdata[0] = 0xD3; pktdata[1] = 0x14; gcry_md_write (cfx->mdc, pktdata, 2); gcry_md_final (cfx->mdc); @@ -200,87 +203,91 @@ num2bits (size_t n) { size_t i; - if (!n) - return -1; for (i = 0; n > 1; i++) n >>= 1; return i; } -static __inline__ size_t -pow2 (size_t y) -{ - size_t x = 1, i; - for (i = 0; i < y; i++) - x <<= 1; - return x; -} - - static cdk_error_t write_partial_block (FILE *in, FILE *out, off_t *r_len, - cipher_filter_t *cfx ) + cipher_filter_t *cfx) { - byte buf[BUFSIZE+1]; - size_t n; - int nread; - cdk_error_t rc; - - if( !out || !cfx ) - return CDK_Inv_Value; + byte buf[DEF_BLOCKSIZE]; + size_t n; + int nread; + gcry_error_t err; + + if (!out || !cfx) + return CDK_Inv_Value; - if( !cfx->blkmode.nleft ) { - if( *r_len > BUFSIZE ) { - fputc( (0xE0|DEF_BLOCKBITS), out ); - cfx->blkmode.nleft = BUFSIZE; - (*r_len) -= BUFSIZE; - } - else if( *r_len > 512 ) { - n = num2bits( *r_len ); - cfx->blkmode.nleft = pow2( n ); - fputc( (0xE0|n), out ); - (*r_len) -= cfx->blkmode.nleft ; + if (!cfx->blkmode.nleft && *r_len > 0) + { + if (*r_len > DEF_BLOCKSIZE) + { + /*_cdk_log_debug ("write_partial_block: size %lu block %d\n", + *r_len, DEF_BLOCKSIZE);*/ + fputc ((0xE0|DEF_BLOCKBITS), out); + cfx->blkmode.nleft = DEF_BLOCKSIZE; + (*r_len) -= DEF_BLOCKSIZE; + } + else if (*r_len > 512) + { + n = num2bits (*r_len); + cfx->blkmode.nleft = (1 << n); + /*_cdk_log_debug ("write_partial_block: size %lu bits %d block %d\n", + *r_len, n, (1<<n));*/ + fputc ((0xE0|n), out); + (*r_len) -= cfx->blkmode.nleft; } - else { - size_t pktlen = *r_len; - if( pktlen < 192 ) - fputc( pktlen, out ); - else if( pktlen < 8384 ) { - pktlen -= 192; - fputc( (pktlen/256) + 192, out ); - fputc( (pktlen % 256), out ); - } - cfx->blkmode.nleft = pktlen; - (*r_len) -= pktlen; + else + { + size_t pktlen = *r_len; + + /* If we use the MDC mode, we need to increase the final + partial body length to hold the mdc packet itself. */ + if (cfx->mdc) + pktlen += 22; + + if (pktlen < 192) + fputc (pktlen, out); + else if (pktlen < 8384) + { + pktlen -= 192; + fputc ((pktlen/256) + 192, out); + fputc ((pktlen % 256), out); + } + cfx->blkmode.nleft = pktlen; + /*_cdk_log_debug ("write_partial_block: end %d block\n", pktlen);*/ + (*r_len) -= pktlen; } } - else - (*r_len) -= cfx->blkmode.nleft; - - n = cfx->blkmode.nleft < DIM (buf)? cfx->blkmode.nleft : DIM (buf); - nread = fread( buf, 1, n, in ); - if( !nread ) - return CDK_EOF; - if( cfx->mdc ) - gcry_md_write( cfx->mdc, buf, nread ); - rc = gcry_cipher_encrypt (cfx->hd, buf, nread, NULL, 0); - if( !rc ) { - fwrite( buf, 1, nread, out ); - cfx->blkmode.nleft -= nread; - } - return rc; + else + (*r_len) -= cfx->blkmode.nleft; + + n = cfx->blkmode.nleft < DIM (buf)? cfx->blkmode.nleft : DIM (buf); + nread = fread (buf, 1, n, in); + if (!nread) + return CDK_EOF; + if (cfx->mdc) + gcry_md_write (cfx->mdc, buf, nread); + err = gcry_cipher_encrypt (cfx->hd, buf, nread, NULL, 0); + if (err) + return map_gcry_error (err); + fwrite (buf, 1, nread, out); + cfx->blkmode.nleft -= nread; + return 0; } static cdk_error_t -cipher_encode_file( void * opaque, FILE * in, FILE * out ) +cipher_encode_file (void *opaque, FILE *in, FILE *out) { - cipher_filter_t * cfx = opaque; + cipher_filter_t *cfx = opaque; byte buf[BUFSIZE]; off_t len, len2; int nread; - cdk_error_t rc = 0; + cdk_error_t rc; if (!cfx || !in || !out) return CDK_Inv_Value; @@ -293,8 +300,13 @@ cipher_encode_file( void * opaque, FILE * in, FILE * out ) if (cfx->blkmode.on) { rc = write_partial_block (in, out, &len2, cfx); - if (rc) + if (rc == CDK_EOF) break; + if (rc) + { + wipemem (buf, sizeof (buf)); + return rc; + } continue; } nread = fread (buf, 1, DIM (buf), in); @@ -305,12 +317,12 @@ cipher_encode_file( void * opaque, FILE * in, FILE * out ) gcry_cipher_encrypt (cfx->hd, buf, nread, NULL, 0); fwrite (buf, 1, nread, out); } + if (cfx->mdc) + rc = write_mdc_packet (out, cfx); + else + rc = 0; + wipemem (buf, sizeof (buf)); - if (!rc) - { - if (cfx->mdc) - rc = write_mdc_packet (out, cfx); - } return rc; } @@ -367,10 +379,7 @@ read_header (cipher_filter_t * cfx, FILE * in) if (cfx->mdc) gcry_md_write (cfx->mdc, temp, nprefix + 2); if (cfx->blkmode.on) - { - cfx->blkmode.size -= (nprefix + 2); - /* FIXME: to sub the MDC packet len (23) here seems to be wrong. */ - } + cfx->blkmode.size -= (nprefix + 2); return 0; } @@ -456,7 +465,7 @@ cipher_decode( void * opaque, FILE * in, FILE * out ) cipher_filter_t * cfx = opaque; cdk_error_t rc; - _cdk_log_debug( "cipher filter: decode\n" ); + _cdk_log_debug ("cipher filter: decode\n"); if( !cfx || !in || !out ) return CDK_Inv_Value; @@ -469,23 +478,23 @@ cipher_decode( void * opaque, FILE * in, FILE * out ) static cdk_error_t -cipher_encode( void * opaque, FILE * in, FILE * out ) +cipher_encode (void *opaque, FILE *in, FILE *out) { - cipher_filter_t * cfx = opaque; - cdk_error_t rc; - - _cdk_log_debug( "cipher filter: encode\n" ); + cipher_filter_t * cfx = opaque; + cdk_error_t rc; - if( !cfx || !in || !out ) - return CDK_Inv_Value; - - cfx->datalen = fp_get_length (in); - if (cfx->datalen < BUFSIZE && cfx->blkmode.on) - cfx->blkmode.on = 0; - rc = write_header (cfx, out); - if( !rc ) - rc = cipher_encode_file (cfx, in, out); - return rc; + _cdk_log_debug ("cipher filter: encode\n"); + + if (!cfx || !in || !out) + return CDK_Inv_Value; + + cfx->datalen = fp_get_length (in); + if (cfx->datalen < BUFSIZE && cfx->blkmode.on) + cfx->blkmode.on = 0; + rc = write_header (cfx, out); + if (!rc) + rc = cipher_encode_file (cfx, in, out); + return rc; } diff --git a/libextra/opencdk/compress.c b/libextra/opencdk/compress.c index 91d605830c..b67bffdd43 100644 --- a/libextra/opencdk/compress.c +++ b/libextra/opencdk/compress.c @@ -31,26 +31,27 @@ static int compress_data (z_stream *zs, int flush, byte *inbuf, size_t insize, FILE *out) { - int nbytes, zrc; - byte buf[4096]; + int nbytes, zrc; + byte buf[4096]; - zs->next_in = inbuf; - zs->avail_in = insize; - - do { - zs->next_out = buf; - zs->avail_out = DIM (buf); + zs->next_in = inbuf; + zs->avail_in = insize; + + do + { + zs->next_out = buf; + zs->avail_out = DIM (buf); - zrc = deflate (zs, flush); - if (zrc == Z_STREAM_END && flush == Z_FINISH) - ; - else if (zrc != Z_OK) - break; - nbytes = DIM (buf) - zs->avail_out; - fwrite (buf, 1, nbytes, out); + zrc = deflate (zs, flush); + if (zrc == Z_STREAM_END && flush == Z_FINISH) + ; + else if (zrc != Z_OK) + break; + nbytes = DIM (buf) - zs->avail_out; + fwrite (buf, 1, nbytes, out); } - while (zs->avail_out == 0 || (flush == Z_FINISH && zrc != Z_STREAM_END)); - return zrc; + while (zs->avail_out == 0 || (flush == Z_FINISH && zrc != Z_STREAM_END)); + return zrc; } @@ -58,169 +59,180 @@ static int decompress_data (compress_filter_t *zfx, z_stream *zs, FILE *in, size_t *ret_len) { - int nread, nold; - int rc, zrc; - - rc = 0; - nread = 0; - while (zs->avail_out != 0) { - if (!zs->avail_in) { - nread = fread (zfx->inbuf, 1, zfx->inbufsize, in); - zs->next_in = zfx->inbuf; - zs->avail_in = nread; + int nread, nold; + int rc, zrc; + + rc = 0; + nread = 0; + while (zs->avail_out != 0) + { + if (!zs->avail_in) + { + nread = fread (zfx->inbuf, 1, zfx->inbufsize, in); + zs->next_in = zfx->inbuf; + zs->avail_in = nread; } - nold = zs->avail_out; - zrc = inflate (zs, Z_SYNC_FLUSH); - if (zrc != Z_OK && zrc != Z_STREAM_END) { - rc = CDK_Zlib_Error; - break; + nold = zs->avail_out; + zrc = inflate (zs, Z_SYNC_FLUSH); + if (zrc != Z_OK && zrc != Z_STREAM_END) + { + rc = CDK_Zlib_Error; + break; } - *ret_len = zfx->outbufsize - zs->avail_out; - if (nold == zs->avail_out) - break; - if (zrc == Z_STREAM_END) { - rc = EOF; /* eof */ - break; + *ret_len = zfx->outbufsize - zs->avail_out; + if (nold == zs->avail_out) + break; + if (zrc == Z_STREAM_END) + { + rc = EOF; /* eof */ + break; } } - if (!nread && feof (in)) - rc = -1; - return rc; + if (!nread && feof (in)) + rc = -1; + return rc; } static cdk_error_t compress_decode (void *opaque, FILE *in, FILE *out) { - compress_filter_t *zfx = opaque; - z_stream * zs; - size_t nbytes; - int zrc; - cdk_error_t rc = 0; - - _cdk_log_debug ("compress filter: decode (algo=%d)\n", zfx->algo); + compress_filter_t *zfx = opaque; + z_stream * zs; + size_t nbytes; + int zrc; + cdk_error_t rc = 0; - if (!zfx || !in || !out) - return CDK_Inv_Value; + _cdk_log_debug ("compress filter: decode (algo=%d)\n", zfx->algo); - zs = cdk_calloc (1, sizeof *zs); - if (!zs) - return CDK_Out_Of_Core; - if (zfx->algo == CDK_COMPRESS_ZIP) - zrc = inflateInit2 (zs, -13); - else - zrc = inflateInit (zs); - if (zrc != Z_OK) - return CDK_Zlib_Error; - - zfx->outbufsize = 8192; - zfx->inbufsize = 2048; - memset (zfx->inbuf, 0, sizeof zfx->inbuf); - zs->avail_in = 0; - - nbytes = 0; - while (rc != -1) { - zs->next_out = zfx->outbuf; - zs->avail_out = 8192; - rc = decompress_data (zfx, zs, in, &nbytes); - fwrite (zfx->outbuf, 1, nbytes, out); + if (!zfx || !in || !out) + return CDK_Inv_Value; + + zs = cdk_calloc (1, sizeof *zs); + if (!zs) + return CDK_Out_Of_Core; + if (zfx->algo == CDK_COMPRESS_ZIP) + zrc = inflateInit2 (zs, -13); + else + zrc = inflateInit (zs); + if (zrc != Z_OK) + return CDK_Zlib_Error; + + zfx->outbufsize = 8192; + zfx->inbufsize = 2048; + memset (zfx->inbuf, 0, sizeof zfx->inbuf); + zs->avail_in = 0; + + nbytes = 0; + while (rc != -1) + { + zs->next_out = zfx->outbuf; + zs->avail_out = 8192; + rc = decompress_data (zfx, zs, in, &nbytes); + fwrite (zfx->outbuf, 1, nbytes, out); } - inflateEnd (zs); - cdk_free (zs); - if (rc == CDK_EOF) - rc = 0; - return rc; + inflateEnd (zs); + cdk_free (zs); + if (rc == CDK_EOF) + rc = 0; + return rc; } static cdk_error_t compress_encode(void *opaque, FILE *in, FILE *out) { - compress_filter_t *zfx = opaque; - z_stream *zs; - struct cdk_pkt_compressed_s cd; - struct cdk_packet_s pkt; - int zrc, nread; - cdk_error_t rc = 0; - - _cdk_log_debug ("compress filter: encode\n"); + compress_filter_t *zfx = opaque; + z_stream *zs; + struct cdk_pkt_compressed_s cd; + struct cdk_packet_s pkt; + int zrc, nread; + cdk_error_t rc; - if (!zfx || !in || !out) - return CDK_Inv_Value; - - if (!zfx->algo) - zfx->algo = CDK_COMPRESS_ZIP; - - memset (&cd, 0, sizeof (cd)); - cd.len = 0; - cd.algorithm = zfx->algo; - pkt.pkttype = CDK_PKT_COMPRESSED; - pkt.pkt.compressed = &cd; - rc = _cdk_pkt_write_fp (out, &pkt); - if (rc) - return rc; - - zs = cdk_calloc (1, sizeof *zs); - if (!zs) - return CDK_Out_Of_Core; - if (zfx->algo == CDK_COMPRESS_ZIP) - rc = deflateInit2 (zs, zfx->level, Z_DEFLATED, -13, 8, - Z_DEFAULT_STRATEGY); - else - rc = deflateInit (zs, zfx->level); - if (rc != Z_OK) { - cdk_free (zs); - return CDK_Zlib_Error; + _cdk_log_debug ("compress filter: encode\n"); + + if (!zfx || !in || !out) + return CDK_Inv_Value; + + if (!zfx->algo) + zfx->algo = CDK_COMPRESS_ZIP; + + memset (&cd, 0, sizeof (cd)); + cd.len = 0; + cd.algorithm = zfx->algo; + pkt.pkttype = CDK_PKT_COMPRESSED; + pkt.pkt.compressed = &cd; + rc = _cdk_pkt_write_fp (out, &pkt); + if (rc) + return rc; + + zs = cdk_calloc (1, sizeof *zs); + if (!zs) + return CDK_Out_Of_Core; + if (zfx->algo == CDK_COMPRESS_ZIP) + rc = deflateInit2 (zs, zfx->level, Z_DEFLATED, -13, 8, + Z_DEFAULT_STRATEGY); + else + rc = deflateInit (zs, zfx->level); + if (rc != Z_OK) + { + cdk_free (zs); + return CDK_Zlib_Error; } - zfx->outbufsize = 8192; - memset (zfx->outbuf, 0, sizeof zfx->outbuf); - - while (!feof (in)) { - nread = fread (zfx->outbuf, 1, zfx->outbufsize, in); - if (!nread) - break; - zrc = compress_data (zs, Z_NO_FLUSH, zfx->outbuf, nread, out); - if (zrc) { - rc = CDK_Zlib_Error; - break; + zfx->outbufsize = 8192; + memset (zfx->outbuf, 0, sizeof zfx->outbuf); + + while (!feof (in)) + { + nread = fread (zfx->outbuf, 1, zfx->outbufsize, in); + if (!nread) + break; + zrc = compress_data (zs, Z_NO_FLUSH, zfx->outbuf, nread, out); + if (zrc) + { + rc = CDK_Zlib_Error; + break; } } - if (!rc) { - nread = 0; - zrc = compress_data (zs, Z_FINISH, zfx->outbuf, nread, out); - if (zrc != Z_STREAM_END) - rc = CDK_Zlib_Error; + if (!rc) + { + nread = 0; + zrc = compress_data (zs, Z_FINISH, zfx->outbuf, nread, out); + if (zrc != Z_STREAM_END) + rc = CDK_Zlib_Error; } - deflateEnd (zs); - cdk_free (zs); - return rc; + deflateEnd (zs); + cdk_free (zs); + return rc; } cdk_error_t _cdk_filter_compress (void *opaque, int ctl, FILE *in, FILE *out) { - if (ctl == STREAMCTL_READ) - return compress_decode (opaque, in, out); - else if (ctl == STREAMCTL_WRITE) - return compress_encode (opaque, in, out); - else if (ctl == STREAMCTL_FREE) { - compress_filter_t * zfx = opaque; - if (zfx) { - _cdk_log_debug ("free compress filter\n"); - zfx->level = 0; - zfx->algo = 0; + if (ctl == STREAMCTL_READ) + return compress_decode (opaque, in, out); + else if (ctl == STREAMCTL_WRITE) + return compress_encode (opaque, in, out); + else if (ctl == STREAMCTL_FREE) + { + compress_filter_t * zfx = opaque; + if (zfx) + { + _cdk_log_debug ("free compress filter\n"); + zfx->level = 0; + zfx->algo = 0; } - return 0; + return 0; } - return CDK_Inv_Mode; + return CDK_Inv_Mode; } #else cdk_error_t _cdk_filter_compress (void *opaque, int ctl, FILE *in, FILE *out) { - return CDK_Not_Implemented; + return CDK_Not_Implemented; } #endif /* HAVE_LIBZ */ diff --git a/libextra/opencdk/context.h b/libextra/opencdk/context.h index 32b274469b..7ff2a9c401 100644 --- a/libextra/opencdk/context.h +++ b/libextra/opencdk/context.h @@ -54,8 +54,6 @@ struct cdk_ctx_s { unsigned textmode:1; unsigned compress:1; unsigned mdc:1; - unsigned compat:1; - unsigned rfc1991:1; unsigned overwrite; unsigned force_digest:1; } opt; @@ -95,12 +93,6 @@ struct cdk_subpkt_s { byte d[1]; }; -struct key_idx_s { - off_t offset; - u32 keyid[2]; - byte fpr[KEY_FPR_LEN]; -}; - struct cdk_dbsearch_s { union { @@ -152,7 +144,6 @@ struct cdk_dek_s { int algo; int keylen; int use_mdc; - unsigned rfc1991:1; byte key[32]; /* 256-bit */ }; diff --git a/libextra/opencdk/filters.h b/libextra/opencdk/filters.h index f7c4627ec4..2c1b2014e0 100644 --- a/libextra/opencdk/filters.h +++ b/libextra/opencdk/filters.h @@ -23,50 +23,50 @@ enum { }; typedef struct { - gcry_cipher_hd_t hd; - gcry_md_hd_t mdc; - int mdc_method; - cdk_dek_t dek; - u32 datalen; - struct { - size_t on; - off_t size; - off_t nleft; - } blkmode; - cdk_stream_t s; + gcry_cipher_hd_t hd; + gcry_md_hd_t mdc; + int mdc_method; + cdk_dek_t dek; + u32 datalen; + struct { + size_t on; + off_t size; + off_t nleft; + } blkmode; + cdk_stream_t s; } cipher_filter_t; typedef struct { - int digest_algo; - gcry_md_hd_t md; + int digest_algo; + gcry_md_hd_t md; } md_filter_t; typedef struct { - const char * le; /* line endings */ - const char * hdrlines; - u32 crc; - int crc_okay; - int idx, idx2; + const char *le; /* line endings */ + const char *hdrlines; + u32 crc; + int crc_okay; + int idx, idx2; } armor_filter_t; typedef struct { - int mode; - unsigned rfc1991:1; - char * filename; - gcry_md_hd_t md; - struct { - size_t on; - off_t size; - } blkmode; + int mode; + char *orig_filename; /* This original name of the input file. */ + char *filename; + gcry_md_hd_t md; + struct { + size_t on; + off_t size; + } blkmode; } literal_filter_t; typedef struct { - size_t inbufsize; - byte inbuf[8192]; - size_t outbufsize; - byte outbuf[8192]; - int algo; /* compress algo */ - int level; + size_t inbufsize; + byte inbuf[8192]; + size_t outbufsize; + byte outbuf[8192]; + int algo; /* compress algo */ + int level; } compress_filter_t; typedef struct { diff --git a/libextra/opencdk/kbnode.c b/libextra/opencdk/kbnode.c index 5d9b13fce1..4595f18b2b 100644 --- a/libextra/opencdk/kbnode.c +++ b/libextra/opencdk/kbnode.c @@ -396,7 +396,7 @@ cdk_kbnode_read_from_mem (cdk_kbnode_t *ret_node, cdk_stream_t inp; cdk_error_t rc; - if (!buflen || !ret_node) + if (!buflen || !ret_node || !buf) return CDK_Inv_Value; *ret_node = NULL; @@ -428,7 +428,10 @@ cdk_kbnode_write_to_mem_alloc (cdk_kbnode_t node, if (!node) return CDK_Inv_Value; - + + *r_buf = NULL; + *r_buflen = 0; + rc = cdk_stream_tmp_new (&s); if (rc) return rc; @@ -436,13 +439,13 @@ cdk_kbnode_write_to_mem_alloc (cdk_kbnode_t node, for (n = node; n; n = n->next) { /* Skip all packets which cannot occur in a key composition. */ - if (n->pkt->pkttype != CDK_PKT_PUBLIC_KEY - && n->pkt->pkttype != CDK_PKT_PUBLIC_SUBKEY - && n->pkt->pkttype != CDK_PKT_SECRET_KEY - && n->pkt->pkttype != CDK_PKT_SECRET_SUBKEY - && n->pkt->pkttype != CDK_PKT_SIGNATURE - && n->pkt->pkttype != CDK_PKT_USER_ID - && n->pkt->pkttype != CDK_PKT_ATTRIBUTE) + if (n->pkt->pkttype != CDK_PKT_PUBLIC_KEY && + n->pkt->pkttype != CDK_PKT_PUBLIC_SUBKEY && + n->pkt->pkttype != CDK_PKT_SECRET_KEY && + n->pkt->pkttype != CDK_PKT_SECRET_SUBKEY && + n->pkt->pkttype != CDK_PKT_SIGNATURE && + n->pkt->pkttype != CDK_PKT_USER_ID && + n->pkt->pkttype != CDK_PKT_ATTRIBUTE) continue; rc = cdk_pkt_write (s, n->pkt); if (rc) @@ -457,7 +460,7 @@ cdk_kbnode_write_to_mem_alloc (cdk_kbnode_t node, *r_buf = cdk_calloc (1, len); *r_buflen = cdk_stream_read (s, *r_buf, len); cdk_stream_close (s); - return rc; + return 0; } @@ -480,7 +483,6 @@ cdk_kbnode_write_to_mem (cdk_kbnode_t node, byte *buf, size_t *r_nbytes) size_t len; cdk_error_t rc; - /* FIXME: Mark the function as deprecated!. */ if (!node) return CDK_Inv_Value; @@ -491,13 +493,13 @@ cdk_kbnode_write_to_mem (cdk_kbnode_t node, byte *buf, size_t *r_nbytes) for (n = node; n; n = n->next) { /* Skip all packets which cannot occur in a key composition. */ - if (n->pkt->pkttype != CDK_PKT_PUBLIC_KEY - && n->pkt->pkttype != CDK_PKT_PUBLIC_SUBKEY - && n->pkt->pkttype != CDK_PKT_SECRET_KEY - && n->pkt->pkttype != CDK_PKT_SECRET_SUBKEY - && n->pkt->pkttype != CDK_PKT_SIGNATURE - && n->pkt->pkttype != CDK_PKT_USER_ID - && n->pkt->pkttype != CDK_PKT_ATTRIBUTE) + if (n->pkt->pkttype != CDK_PKT_PUBLIC_KEY && + n->pkt->pkttype != CDK_PKT_PUBLIC_SUBKEY && + n->pkt->pkttype != CDK_PKT_SECRET_KEY && + n->pkt->pkttype != CDK_PKT_SECRET_SUBKEY && + n->pkt->pkttype != CDK_PKT_SIGNATURE && + n->pkt->pkttype != CDK_PKT_USER_ID && + n->pkt->pkttype != CDK_PKT_ATTRIBUTE) continue; rc = cdk_pkt_write (s, n->pkt); if (rc) @@ -511,10 +513,8 @@ cdk_kbnode_write_to_mem (cdk_kbnode_t node, byte *buf, size_t *r_nbytes) len = cdk_stream_get_length (s); if (!buf) { - *r_nbytes = len; /* only return the length of the buffer */ + *r_nbytes = len; /* Only return the length of the buffer */ cdk_stream_close (s); - /* FIXME: A patch from the nmav-0-5-x has set the return - to CDK_Too_Short which is clerly wrong! */ return 0; } if (*r_nbytes < len) diff --git a/libextra/opencdk/keydb.c b/libextra/opencdk/keydb.c index 1b676040b0..26bc6dd1a7 100644 --- a/libextra/opencdk/keydb.c +++ b/libextra/opencdk/keydb.c @@ -34,6 +34,13 @@ #define KEYDB_CACHE_ENTRIES 8 typedef struct key_table_s *key_table_t; + +struct key_idx_s +{ + off_t offset; + u32 keyid[2]; + byte fpr[KEY_FPR_LEN]; +}; typedef struct key_idx_s *key_idx_t; @@ -47,12 +54,13 @@ static cdk_kbnode_t find_selfsig_node (cdk_kbnode_t key, cdk_pkt_pubkey_t pk); static char* keydb_idx_mkname (const char *file) { - char *fname; + char *fname, *fmt; - fname = cdk_calloc (1, strlen (file) + 4 + 1); + fmt = "%s.idx"; + fname = cdk_calloc (1, strlen (file) + strlen (fmt) + 1); if (!fname) return NULL; - sprintf (fname, "%s.idx", file); + sprintf (fname, fmt, file); return fname; } @@ -63,7 +71,7 @@ keydb_idx_mkname (const char *file) -------- 4 octets offset of the packet 8 octets keyid - KEY_FPR_LEN (=20) octets fingerprint + 20 octets fingerprint -------- We store the keyid and the fingerprint due to the fact we can't get the keyid from a v3 fingerprint directly. @@ -73,9 +81,8 @@ keydb_idx_build (const char *file) { cdk_packet_t pkt; cdk_stream_t inp, out = NULL; - byte buf[8], fpr[KEY_FPR_LEN]; - char *fname; - off_t pos; + byte buf[4+8+KEY_FPR_LEN]; + char *idx_name; u32 keyid[2]; cdk_error_t rc; @@ -86,43 +93,47 @@ keydb_idx_build (const char *file) if (rc) return rc; - fname = keydb_idx_mkname (file); - if (!fname) + idx_name = keydb_idx_mkname (file); + if (!idx_name) { cdk_stream_close (inp); return CDK_Out_Of_Core; } - rc = cdk_stream_create (fname, &out); - cdk_free (fname); + rc = cdk_stream_create (idx_name, &out); + cdk_free (idx_name); if (rc) goto leave; - + cdk_pkt_new (&pkt); while (!cdk_stream_eof (inp)) { - pos = cdk_stream_tell (inp); + off_t pos = cdk_stream_tell (inp); + rc = cdk_pkt_read (inp, pkt); if (rc) - break; + { + _cdk_log_debug ("index build failed packet off=%lu\n", pos); + /* FIXME: The index is incomplete */ + break; + } if (pkt->pkttype == CDK_PKT_PUBLIC_KEY || pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY) { _cdk_u32tobuf (pos, buf); - cdk_stream_write (out, buf, 4); cdk_pk_get_keyid (pkt->pkt.public_key, keyid); - _cdk_u32tobuf (keyid[0], buf + 0); - _cdk_u32tobuf (keyid[1], buf + 4); - cdk_stream_write (out, buf, 8); - cdk_pk_get_fingerprint (pkt->pkt.public_key, fpr); - cdk_stream_write (out, fpr, KEY_FPR_LEN); + _cdk_u32tobuf (keyid[0], buf + 4); + _cdk_u32tobuf (keyid[1], buf + 8); + cdk_pk_get_fingerprint (pkt->pkt.public_key, buf+12); + cdk_stream_write (out, buf, 4+8+KEY_FPR_LEN); } cdk_pkt_free (pkt); } - + + cdk_pkt_release (pkt); + leave: cdk_stream_close (out); cdk_stream_close (inp); - cdk_pkt_release (pkt); return rc; } @@ -176,9 +187,8 @@ keydb_idx_parse (cdk_stream_t inp, key_idx_t *r_idx) { key_idx_t idx; byte buf[4]; - int i; - if( !inp || !r_idx ) + if (!inp || !r_idx) return CDK_Inv_Value; idx = cdk_calloc (1, sizeof *idx); @@ -187,8 +197,7 @@ keydb_idx_parse (cdk_stream_t inp, key_idx_t *r_idx) while (!cdk_stream_eof (inp)) { - i = cdk_stream_read (inp, buf, 4); - if (i == CDK_EOF) + if (cdk_stream_read (inp, buf, 4) == CDK_EOF) break; idx->offset = _cdk_buftou32 (buf); cdk_stream_read (inp, buf, 4); @@ -204,8 +213,7 @@ keydb_idx_parse (cdk_stream_t inp, key_idx_t *r_idx) static int -keydb_idx_search (cdk_stream_t inp, u32 *keyid, - const byte *fpr, off_t *r_off) +keydb_idx_search (cdk_stream_t inp, u32 *keyid, const byte *fpr, off_t *r_off) { key_idx_t idx; @@ -214,6 +222,9 @@ keydb_idx_search (cdk_stream_t inp, u32 *keyid, if ((keyid && fpr) || (!keyid && !fpr)) return CDK_Inv_Mode; + /* We need an initialize the offset var with a value + because it might be possible the returned offset will + be 0 and then we cannot differ between the begin and an EOF. */ *r_off = 0xFFFFFFFF; cdk_stream_seek (inp, 0); while (keydb_idx_parse (inp, &idx) != CDK_EOF) @@ -449,7 +460,7 @@ _cdk_keydb_open (cdk_keydb_hd_t hd, cdk_stream_t *ret_kr) /* This is no real error, it just means we can't create the index at the given directory. maybe we've no write access. in this case, we simply disable the index. */ - _cdk_log_debug ("disable key index table\n"); + _cdk_log_debug ("disable key index table err=%d\n", rc); rc = 0; hd->no_cache = 1; } @@ -837,43 +848,45 @@ keydb_pos_from_cache (cdk_keydb_hd_t hd, cdk_dbsearch_t ks, int *r_cache_hit, off_t *r_off) { key_table_t c; - off_t off; - int cache_hit; if (!hd || !r_cache_hit || !r_off) return CDK_Inv_Value; - /* Reset */ - off = 0; - cache_hit = 0; + /* Reset the values. */ + *r_cache_hit = 0; + *r_off = 0; c = keydb_cache_find (hd->cache, ks); if (c != NULL) { _cdk_log_debug ("Cache: found entry in cache.\n"); - cache_hit = 1; - off = c->offset; + *r_cache_hit = 1; + *r_off = c->offset; + return 0; } - if (hd->idx && !c) + /* No index cache available so we just return here. */ + if (!hd->idx) + return 0; + + if (hd->idx) { if (ks->type == CDK_DBSEARCH_KEYID) { - if (keydb_idx_search (hd->idx, ks->u.keyid, NULL, &off)) + if (keydb_idx_search (hd->idx, ks->u.keyid, NULL, r_off)) return CDK_Error_No_Key; _cdk_log_debug ("Cache: found keyid entry in idx table.\n"); - cache_hit = 1; + *r_cache_hit = 1; } else if (ks->type == CDK_DBSEARCH_FPR) { - if (keydb_idx_search (hd->idx, NULL, ks->u.fpr, &off)) + if (keydb_idx_search (hd->idx, NULL, ks->u.fpr, r_off)) return CDK_Error_No_Key; _cdk_log_debug ("Cache: found fpr entry in idx table.\n"); - cache_hit = 1; + *r_cache_hit = 1; } } - *r_off = off; - *r_cache_hit = cache_hit; + return 0; } @@ -907,12 +920,15 @@ cdk_keydb_search (cdk_keydb_hd_t hd, cdk_kbnode_t *ret_key) return rc; if (!hd->no_cache) - { - /* FIXME: pubkey offset seems wrong */ + { + /* It is possible the index is not up-to-date and thus we do + not find the requesed key. In this case, we reset cache hit + and continue our normal search procedure. */ rc = keydb_pos_from_cache (hd, hd->dbs, &cache_hit, &off); if (rc) - return rc; + cache_hit = 0; } + ks = hd->dbs; while (!key_found && !rc) { @@ -1270,15 +1286,15 @@ cdk_keydb_get_pk (cdk_keydb_hd_t hd, u32 *keyid, cdk_pkt_pubkey_t *r_pk) cdk_error_t -cdk_keydb_get_sk (cdk_keydb_hd_t hd, u32 *keyid, cdk_pkt_seckey_t *ret_sk) +cdk_keydb_get_sk (cdk_keydb_hd_t hd, u32 *keyid, cdk_seckey_t *ret_sk) { cdk_kbnode_t snode, node; - cdk_pkt_seckey_t sk; + cdk_seckey_t sk; cdk_error_t rc; if (!keyid || !ret_sk) return CDK_Inv_Value; - if (!hd ) + if (!hd) return CDK_Error_No_Keyring; *ret_sk = NULL; @@ -1445,7 +1461,7 @@ keydb_merge_selfsig (cdk_kbnode_t key, u32 *keyid) if (key_expire) { pk->expiredate = pk->timestamp + key_expire; - pk->has_expired = pk->expiredate> _cdk_timestamp ()?0 :1; + pk->has_expired = pk->expiredate> (u32)time (NULL)?0 :1; } if (key_usage) @@ -1464,7 +1480,7 @@ keydb_parse_allsigs (cdk_kbnode_t knode, cdk_keydb_hd_t hd, int check) cdk_pkt_signature_t sig; cdk_pkt_pubkey_t pk; cdk_subpkt_t s=NULL; - u32 expiredate = 0, curtime = _cdk_timestamp (); + u32 expiredate = 0, curtime = (u32)time (NULL); u32 keyid[2]; if (!knode) diff --git a/libextra/opencdk/literal.c b/libextra/opencdk/literal.c index 28cae67df0..5fae806f02 100644 --- a/libextra/opencdk/literal.c +++ b/libextra/opencdk/literal.c @@ -17,14 +17,31 @@ # include <config.h> #endif #include <stdio.h> +#include <time.h> #include "opencdk.h" #include "main.h" #include "filters.h" +/* Duplicate the string @s but strip of possible + relative folder names of it. */ +static char* +dup_trim_filename (const char *s) +{ + char *p = NULL; + + p = strrchr (s, '/'); + if (!p) + p = strrchr (s, '\\'); + if (!p) + return cdk_strdup (s); + return cdk_strdup (p + 1); +} + + static cdk_error_t -literal_decode (void * opaque, FILE * in, FILE * out) +literal_decode (void *opaque, FILE *in, FILE *out) { literal_filter_t *pfx = opaque; cdk_stream_t si, so; @@ -35,7 +52,7 @@ literal_decode (void * opaque, FILE * in, FILE * out) int bufsize; cdk_error_t rc; - _cdk_log_debug( "literal filter: decode\n" ); + _cdk_log_debug ("literal filter: decode\n"); if (!pfx || !in || !out) return CDK_Inv_Value; @@ -68,21 +85,43 @@ literal_decode (void * opaque, FILE * in, FILE * out) pt = pkt->pkt.literal; pfx->mode = pt->mode; - pfx->filename = cdk_strdup (pt->name? pt->name : " "); - if (!pfx->filename) + + if (pfx->filename && pt->namelen > 0) { - /* FIXME: release streams. */ - cdk_pkt_release (pkt); - return CDK_Out_Of_Core; + /* The name in the literal packet is more authorative. */ + cdk_free (pfx->filename); + pfx->filename = dup_trim_filename (pt->name); + } + else if (!pfx->filename && pt->namelen > 0) + pfx->filename = dup_trim_filename (pt->name); + else if (!pt->namelen && !pfx->filename && pfx->orig_filename) + { + /* In this case, we need to derrive the output file name + from the original name and cut off the OpenPGP extension. + If this is not possible, we return an error. */ + if (!stristr (pfx->orig_filename, ".gpg") && + !stristr (pfx->orig_filename, ".pgp") && + !stristr (pfx->orig_filename, ".asc")) + { + cdk_pkt_release (pkt); + cdk_stream_close (si); + cdk_stream_close (so); + _cdk_log_debug ("literal filter: no file name and no PGP extension\n"); + return CDK_Inv_Mode; + } + _cdk_log_debug ("literal filter: derrive file name from original\n"); + pfx->filename = dup_trim_filename (pfx->orig_filename); + pfx->filename[strlen (pfx->filename)-4] = '\0'; } + while (!feof (in)) { - /*_cdk_log_debug( "partial on=%d size=%lu\n", - pfx->blkmode.on, pfx->blkmode.size );*/ + _cdk_log_debug ("literal_decode: part on %d size %lu\n", + pfx->blkmode.on, pfx->blkmode.size); if (pfx->blkmode.on) bufsize = pfx->blkmode.size; else - bufsize = pt->len < DIM (buf)-1? pt->len : DIM (buf)-1; + bufsize = pt->len < DIM (buf)? pt->len : DIM (buf); nread = cdk_stream_read (pt->buf, buf, bufsize); if (nread == EOF) { @@ -128,7 +167,7 @@ literal_encode (void *opaque, FILE *in, FILE *out) { pfx->filename = cdk_strdup ("_CONSOLE"); if (!pfx->filename) - return CDK_Out_Of_Core; + return CDK_Out_Of_Core; } rc = _cdk_stream_fpopen (in, STREAMCTL_READ, &si); @@ -147,11 +186,11 @@ literal_encode (void *opaque, FILE *in, FILE *out) memcpy (pt->name, pfx->filename, filelen); pt->namelen = filelen; pt->name[pt->namelen] = '\0'; - pt->timestamp = _cdk_timestamp (); + pt->timestamp = (u32)time (NULL); pt->mode = pfx->mode ? 't' : 'b'; pt->len = cdk_stream_get_length (si); pt->buf = si; - pkt->old_ctb = pfx->rfc1991? 1 : 0; + pkt->old_ctb = 1; pkt->pkttype = CDK_PKT_LITERAL; pkt->pkt.literal = pt; rc = _cdk_pkt_write_fp (out, pkt); @@ -163,21 +202,25 @@ literal_encode (void *opaque, FILE *in, FILE *out) int -_cdk_filter_literal( void * opaque, int ctl, FILE * in, FILE * out ) +_cdk_filter_literal (void * opaque, int ctl, FILE * in, FILE * out) { - if( ctl == STREAMCTL_READ ) - return literal_decode( opaque, in, out ); - else if( ctl == STREAMCTL_WRITE ) - return literal_encode( opaque, in, out ); - else if( ctl == STREAMCTL_FREE ) { - literal_filter_t * pfx = opaque; - if( pfx ) { - _cdk_log_debug( "free literal filter\n" ); - cdk_free( pfx->filename ); - pfx->filename = NULL; - } + if (ctl == STREAMCTL_READ) + return literal_decode( opaque, in, out ); + else if (ctl == STREAMCTL_WRITE) + return literal_encode (opaque, in, out); + else if (ctl == STREAMCTL_FREE) + { + literal_filter_t *pfx = opaque; + if (pfx) + { + _cdk_log_debug ("free literal filter\n"); + cdk_free (pfx->filename); + pfx->filename = NULL; + cdk_free (pfx->orig_filename); + pfx->orig_filename = NULL; + } } - return CDK_Inv_Mode; + return CDK_Inv_Mode; } @@ -185,11 +228,12 @@ static int text_encode (void *opaque, FILE *in, FILE *out) { const char *s; - char buf[1024]; + char buf[2048]; if (!in || !out) return CDK_Inv_Value; + /* FIXME: This code does not work for very long lines. */ while (!feof (in)) { s = fgets (buf, DIM (buf)-1, in); @@ -204,41 +248,44 @@ text_encode (void *opaque, FILE *in, FILE *out) static int -text_decode( void * opaque, FILE * in, FILE * out ) +text_decode (void * opaque, FILE * in, FILE * out) { - text_filter_t * tfx = opaque; - const char * s; - char buf[1024]; - - if( !tfx || !in || !out ) - return CDK_Inv_Value; - - while( !feof( in ) ) { - s = fgets( buf, DIM (buf)-1, in ); - if( !s ) - break; - _cdk_trim_string( buf, 0 ); - fwrite( buf, 1, strlen( buf ), out ); - fwrite( tfx->lf, 1, strlen( tfx->lf ), out ); + text_filter_t *tfx = opaque; + const char *s; + char buf[2048]; + + if (!tfx || !in || !out) + return CDK_Inv_Value; + + while (!feof (in)) + { + s = fgets (buf, DIM (buf)-1, in); + if (!s) + break; + _cdk_trim_string (buf, 0); + fwrite (buf, 1, strlen (buf), out); + fwrite (tfx->lf, 1, strlen (tfx->lf), out); } - - return 0; + + return 0; } int -_cdk_filter_text( void * opaque, int ctl, FILE * in, FILE * out ) +_cdk_filter_text (void *opaque, int ctl, FILE *in, FILE *out) { - if( ctl == STREAMCTL_READ ) - return text_encode( opaque, in, out ); - else if( ctl == STREAMCTL_WRITE ) - return text_decode( opaque, in, out ); - else if( ctl == STREAMCTL_FREE ) { - text_filter_t * tfx = opaque; - if( tfx ) { - _cdk_log_debug( "free text filter\n" ); - tfx->lf = NULL; - } + if (ctl == STREAMCTL_READ) + return text_encode (opaque, in, out); + else if (ctl == STREAMCTL_WRITE) + return text_decode (opaque, in, out); + else if (ctl == STREAMCTL_FREE) + { + text_filter_t * tfx = opaque; + if (tfx) + { + _cdk_log_debug ("free text filter\n"); + tfx->lf = NULL; + } } - return CDK_Inv_Mode; + return CDK_Inv_Mode; } diff --git a/libextra/opencdk/main.c b/libextra/opencdk/main.c index 51f8d8be06..3f863b6cec 100644 --- a/libextra/opencdk/main.c +++ b/libextra/opencdk/main.c @@ -95,6 +95,7 @@ cdk_strerror (int ec) case CDK_Too_Short: return "Buffer or object is too short"; case CDK_Unusable_Key: return "Unusable public key"; case CDK_No_Data: return "No data"; + case CDK_No_Passphrase: return "No passphrase supplied"; default: sprintf (buf, "ec=%d", ec); return buf; } return NULL; @@ -191,8 +192,8 @@ _secmem_init (size_t size) static void _secmem_end (void) { - gcry_control (GCRYCTL_TERM_SECMEM); - secmem_init = 0; + gcry_control (GCRYCTL_TERM_SECMEM); + secmem_init = 0; } @@ -435,25 +436,6 @@ handle_set_s2k (cdk_ctx_t hd, int mode, int digest, int cipher) static void -handle_set_compat (cdk_ctx_t hd, int val) -{ - if (!hd) - return; - hd->opt.compat = val; - if (!val) - return; - hd->opt.mdc = 0; - hd->opt.rfc1991 = val == -1? 1: 0; - hd->compress.algo = CDK_COMPRESS_ZIP; - hd->compress.level = -1; - hd->cipher_algo = val == -1? GCRY_CIPHER_IDEA : DEFAULT_CIPHER_ALGO; - hd->digest_algo = val == -1? GCRY_MD_MD5: DEFAULT_DIGEST_ALGO; - if (val == -1) - handle_set_s2k (hd, 0, hd->digest_algo, hd->cipher_algo); -} - - -static void handle_set_compress (cdk_ctx_t hd, int algo, int level) { if (!hd) @@ -510,22 +492,15 @@ cdk_handle_control (cdk_ctx_t hd, int action, int cmd, ...) break; case CDK_CTL_DIGEST: - if( set ) + if (set) handle_set_digest( hd, va_arg( arg_ptr, int ) ); else val = hd->digest_algo; break; - case CDK_CTL_COMPAT: - if( set ) - handle_set_compat( hd, va_arg( arg_ptr, int ) ); - else - val = hd->opt.compat; - break; - case CDK_CTL_OVERWRITE: if (set) - hd->opt.overwrite = va_arg( arg_ptr, int ); + hd->opt.overwrite = va_arg (arg_ptr, int); else val = hd->opt.overwrite; break; @@ -552,21 +527,9 @@ cdk_handle_control (cdk_ctx_t hd, int action, int cmd, ...) val = hd->_s2k.mode; break; - case CDK_CTL_KEYCACHE_ON: - if (set) - hd->cache.on = va_arg (arg_ptr, int); - else - val = hd->cache.on; - break; - - case CDK_CTL_KEYCACHE_FREE: - cdk_sk_release (hd->cache.sk); - hd->cache.sk = NULL; - break; - case CDK_CTL_FORCE_DIGEST: - if( set ) - hd->opt.force_digest = va_arg( arg_ptr, int ); + if (set) + hd->opt.force_digest = va_arg (arg_ptr, int); else val = hd->opt.force_digest; break; @@ -738,7 +701,6 @@ cdk_handle_free (cdk_ctx_t hd) if (!hd) return; _cdk_result_verify_free (hd->result.verify); - cdk_sk_release (hd->cache.sk); /* If cdk_handle_set_keyring() were used, we need to free the key db handles here because the handles are not controlled by the user. */ diff --git a/libextra/opencdk/main.h b/libextra/opencdk/main.h index e84f346b44..10ef55711a 100644 --- a/libextra/opencdk/main.h +++ b/libextra/opencdk/main.h @@ -34,7 +34,7 @@ #include "context.h" /* The maximal amount of bits a multi precsion integer can have. */ -#define MAX_MPI_BITS 8192 +#define MAX_MPI_BITS 16384 #define MAX_MPI_BYTES (MAX_MPI_BITS/8) @@ -42,11 +42,14 @@ that SHA-512 is used and increase the buffer size of the digest. */ #define MAX_DIGEST_LEN 64 +/* Helper to find out if the signature were made over a user ID + or if the signature revokes a previous user ID. */ #define IS_UID_SIG(s) (((s)->sig_class & ~3) == 0x10) #define IS_UID_REV(s) ((s)->sig_class == 0x30) #define DEBUG_PKT (_cdk_get_log_level () == (CDK_LOG_DEBUG+1)) +/* Helper to find out if a key has the requested capability. */ #define KEY_CAN_ENCRYPT(a) (_cdk_pk_algo_usage ((a)) & CDK_KEY_USG_ENCR) #define KEY_CAN_SIGN(a) (_cdk_pk_algo_usage ((a)) & CDK_KEY_USG_SIGN) #define KEY_CAN_AUTH(a) (_cdk_pk_algo_usage ((a)) & CDK_KEY_USG_AUTH) @@ -72,12 +75,10 @@ void _cdk_log_debug (const char * fmt, ...); char * _cdk_passphrase_get (cdk_ctx_t hd, const char *prompt); /*-- misc.c --*/ -int _cdk_check_file( const char * file ); -u32 _cdk_timestamp( void ); -int _cdk_strcmp( const char * a, const char * b ); -u32 _cdk_buftou32( const byte * buf ); -void _cdk_u32tobuf( u32 u, byte * buf ); -const char * _cdk_memistr( const char * buf, size_t buflen, const char * sub ); +int _cdk_check_args( int overwrite, const char * in, const char * out ); +u32 _cdk_buftou32 (const byte * buf); +void _cdk_u32tobuf (u32 u, byte * buf); +const char *_cdk_memistr (const char * buf, size_t buflen, const char * sub); cdk_error_t map_gcry_error (gcry_error_t err); /* Helper to provide case insentensive strstr version. */ @@ -106,7 +107,7 @@ cdk_error_t _cdk_subpkt_copy (cdk_subpkt_t * r_dst, cdk_subpkt_t src); int _cdk_sig_check (cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig, gcry_md_hd_t digest, int * r_expired); cdk_error_t _cdk_hash_sig_data (cdk_pkt_signature_t sig, gcry_md_hd_t hd); -void _cdk_hash_userid( cdk_pkt_userid_t uid, int sig_version, gcry_md_hd_t md); +void _cdk_hash_userid (cdk_pkt_userid_t uid, int sig_version, gcry_md_hd_t md); int _cdk_hash_pubkey (cdk_pkt_pubkey_t pk, gcry_md_hd_t md, int use_fpr); cdk_error_t _cdk_pk_check_sig (cdk_keydb_hd_t hd, cdk_kbnode_t knode, @@ -117,17 +118,17 @@ void _cdk_kbnode_add (cdk_kbnode_t root, cdk_kbnode_t node); void _cdk_kbnode_clone (cdk_kbnode_t node); /*-- sesskey.c --*/ -int _cdk_digest_encode_pkcs1( byte ** r_md, size_t * r_mdlen, int pk_algo, +int _cdk_digest_encode_pkcs1 (byte ** r_md, size_t * r_mdlen, int pk_algo, const byte * md, - int digest_algo, unsigned nbits ); -int _cdk_sk_unprotect_auto( cdk_ctx_t hd, cdk_pkt_seckey_t sk ); + int digest_algo, unsigned nbits); +int _cdk_sk_unprotect_auto (cdk_ctx_t hd, cdk_pkt_seckey_t sk); /*-- keydb.c --*/ -int _cdk_keydb_get_pk_byusage( cdk_keydb_hd_t hd, const char * name, - cdk_pkt_pubkey_t * ret_pk, int usage ); -int _cdk_keydb_get_sk_byusage( cdk_keydb_hd_t hd, const char * name, - cdk_pkt_seckey_t * ret_sk, int usage ); -int _cdk_keydb_check_userid( cdk_keydb_hd_t hd, u32 * keyid, const char * id ); +int _cdk_keydb_get_pk_byusage (cdk_keydb_hd_t hd, const char * name, + cdk_pkt_pubkey_t * ret_pk, int usage); +int _cdk_keydb_get_sk_byusage (cdk_keydb_hd_t hd, const char * name, + cdk_pkt_seckey_t * ret_sk, int usage); +int _cdk_keydb_check_userid (cdk_keydb_hd_t hd, u32 * keyid, const char * id); /*-- sign.c --*/ int _cdk_sig_create( cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig ); @@ -156,8 +157,6 @@ cdk_error_t _cdk_stream_fpopen (FILE * fp, unsigned write_mode, void _cdk_result_verify_free (cdk_verify_result_t res); cdk_verify_result_t _cdk_result_verify_new (void); -/*-- encrypt.c --*/ -int _cdk_check_args( int overwrite, const char * in, const char * out ); /*-- read-packet.c --*/ size_t _cdk_pkt_read_len (FILE * inp, size_t *ret_partial); diff --git a/libextra/opencdk/misc.c b/libextra/opencdk/misc.c index 3164bf1ca0..85a567fef0 100644 --- a/libextra/opencdk/misc.c +++ b/libextra/opencdk/misc.c @@ -20,36 +20,12 @@ #include <stdio.h> #include <string.h> #include <ctype.h> -#include <time.h> +#include <sys/stat.h> #include "opencdk.h" #include "main.h" -/* Return 0 if the file exists. otherwise 1 */ -int -_cdk_check_file (const char *file) -{ - FILE *fp; - int check; - - if (!file) - return 1; - fp = fopen (file, "r"); - check = fp? 0 : 1; - if (fp) - fclose (fp); - return check; -} - - -u32 -_cdk_timestamp (void) -{ - return (u32)time (NULL); -} - - u32 _cdk_buftou32 (const byte *buf) { @@ -77,19 +53,6 @@ _cdk_u32tobuf (u32 u, byte *buf) } -int -_cdk_strcmp (const char *a, const char *b) -{ - int alen, blen; - - alen = strlen( a ); - blen = strlen( b ); - if( alen != blen ) - return alen > blen? 1 : -1; - return strcmp( a, b ); -} - - static const char * parse_version_number( const char *s, int *number ) { @@ -168,11 +131,12 @@ cdk_check_version (const char *req_version) void cdk_strlist_free (cdk_strlist_t sl) { - cdk_strlist_t sl2; - - for(; sl; sl = sl2 ) { - sl2 = sl->next; - cdk_free (sl); + cdk_strlist_t sl2; + + for(; sl; sl = sl2 ) + { + sl2 = sl->next; + cdk_free (sl); } } @@ -180,87 +144,97 @@ cdk_strlist_free (cdk_strlist_t sl) cdk_strlist_t cdk_strlist_add (cdk_strlist_t *list, const char *string) { - cdk_strlist_t sl; - - if (!string) - return NULL; + cdk_strlist_t sl; - sl = cdk_calloc (1, sizeof *sl + strlen (string) + 1); - if (!sl) - return NULL; - strcpy (sl->d, string); - sl->next = *list; - *list = sl; - return sl; + if (!string) + return NULL; + + sl = cdk_calloc (1, sizeof *sl + strlen (string) + 1); + if (!sl) + return NULL; + strcpy (sl->d, string); + sl->next = *list; + *list = sl; + return sl; } -const char * -cdk_strlist_walk (cdk_strlist_t root, cdk_strlist_t * context) +/** + * cdk_strlist_next: + * @root: the opaque string list. + * @r_str: optional argument to store the string data. + * + * Return the next string list node from @root. The optional + * argument @r_str return the data of the current (!) node. + **/ +cdk_strlist_t +cdk_strlist_next (cdk_strlist_t root, const char **r_str) { - cdk_strlist_t n; - - if( ! *context ) { - *context = root; - n = root; - } - else { - n = (*context)->next; - *context = n; - } + cdk_strlist_t node; + + if (root && r_str) + *r_str = root->d; + for (node = root->next; node; node = node->next) + return node; - return n? n->d : NULL; + return NULL; } -const char * +const char* _cdk_memistr (const char *buf, size_t buflen, const char *sub) { - const byte *t, *s; - size_t n; - - for (t = (byte*)buf, n = buflen, s = (byte*)sub ; n ; t++, n--) { - if (toupper (*t) == toupper (*s)) { - for (buf = t++, buflen = n--, s++; - n && toupper (*t) == toupper ((byte)*s); t++, s++, n--) - ; - if (!*s) - return buf; - t = (byte*)buf; - n = buflen; - s = (byte*)sub; + const byte *t, *s; + size_t n; + + for (t = (byte*)buf, n = buflen, s = (byte*)sub ; n ; t++, n--) + { + if (toupper (*t) == toupper (*s)) + { + for (buf = t++, buflen = n--, s++; + n && toupper (*t) == toupper ((byte)*s); t++, s++, n--) + ; + if (!*s) + return buf; + t = (byte*)buf; + n = buflen; + s = (byte*)sub; } } - - return NULL; + + return NULL; } -char * -cdk_utf8_encode (const char * string) +char* +cdk_utf8_encode (const char *string) { - const byte * s; - char * buffer; - byte * p; - size_t length = 0; - - for (s = string; *s; s++) { - length++; - if (*s & 0x80) - length++; + const byte *s; + char *buffer; + byte *p; + size_t length; + + /* FIXME: We should use iconv if possible for utf8 issues. */ + for (s = (const byte*)string, length = 0; *s; s++) + { + length++; + if (*s & 0x80) + length++; } buffer = cdk_calloc (1, length + 1); - for (p = buffer, s = string; *s; s++) { - if (*s & 0x80) { - *p++ = 0xc0 | ((*s >> 6) & 3); - *p++ = 0x80 | (*s & 0x3f); + for (p = (byte*)buffer, s = (byte*)string; *s; s++) + { + if (*s & 0x80) + { + *p++ = 0xc0 | ((*s >> 6) & 3); + *p++ = 0x80 | (*s & 0x3f); } - else - *p++ = *s; + else + *p++ = *s; } - *p = 0; - return buffer; + *p = 0; + return buffer; } @@ -503,13 +477,59 @@ _cdk_trim_string (char *s, int canon) int _cdk_check_args (int overwrite, const char *in, const char *out) -{ +{ + struct stat stbuf; + if (!in || !out) return CDK_Inv_Value; - if (!_cdk_strcmp (in, out)) + if (strlen (in) == strlen (out) && strcmp (in, out)) return CDK_Inv_Mode; - if (!overwrite && !_cdk_check_file (out)) + if (!overwrite && !stat (out, &stbuf)) return CDK_Inv_Mode; return 0; } +#ifdef _WIN32 +#include <io.h> +#include <fcntl.h> + +FILE * +my_tmpfile (void) +{ + /* Because the tmpfile() version of wine is not really useful, + we implement our own version to avoid problems with 'make check'. */ + static const char *letters = "abcdefghijklmnopqrstuvwxyz"; + char buf[512], rnd[24]; + FILE *fp; + int fd, i; + + gcry_create_nonce (rnd, DIM (rnd)); + for (i=0; i < DIM (rnd)-1; i++) + { + char c = letters[(unsigned char)rnd[i] % 26]; + rnd[i] = c; + } + rnd[DIM (rnd)-1]=0; + if (!GetTempPath (464, buf)) + return NULL; + strcat (buf, "_cdk_"); + strcat (buf, rnd); + + /* We need to make sure the file will be deleted when it is closed. */ + fd = _open (buf, _O_CREAT | _O_EXCL | _O_TEMPORARY | + _O_RDWR | _O_BINARY, _S_IREAD | _S_IWRITE); + if (fd == -1) + return NULL; + fp = fdopen (fd, "w+b"); + if (fp != NULL) + return fp; + _close (fd); + return NULL; +} +#else +FILE* +my_tmpfile (void) +{ + return tmpfile (); +} +#endif diff --git a/libextra/opencdk/opencdk.h b/libextra/opencdk/opencdk.h index d47f335f9c..d7ff7bbb27 100644 --- a/libextra/opencdk/opencdk.h +++ b/libextra/opencdk/opencdk.h @@ -23,12 +23,12 @@ #include <gcrypt.h> /* The OpenCDK version as a string. */ -#define OPENCDK_VERSION "0.6.0" +#define OPENCDK_VERSION "0.6.1" /* The OpenCDK version as integer components major.minor.path */ #define OPENCDK_VERSION_MAJOR 0 #define OPENCDK_VERSION_MINOR 6 -#define OPENCDK_VERSION_PATCH 0 +#define OPENCDK_VERSION_PATCH 1 #ifdef __cplusplus extern "C" { @@ -123,7 +123,8 @@ typedef enum { CDK_Inv_Packet_Ver = 23, CDK_Too_Short = 24, CDK_Unusable_Key = 25, - CDK_No_Data = 26 + CDK_No_Data = 26, + CDK_No_Passphrase = 27 } cdk_error_t; @@ -137,8 +138,6 @@ enum cdk_control_flags { CDK_CTL_COMPAT = 14, /* Option to switch in compat mode. */ CDK_CTL_OVERWRITE = 15, /* Option to enable file overwritting. */ CDK_CTL_S2K = 16, /* Option to set S2K values. */ - CDK_CTL_KEYCACHE_ON = 17, - CDK_CTL_KEYCACHE_FREE = 18, CDK_CTL_FORCE_DIGEST = 19, /* Force the use of a digest algorithm. */ CDK_CTL_BLOCKMODE_ON = 20 /* Enable partial body lengths */ }; @@ -362,6 +361,14 @@ typedef enum { CDK_PKT_MDC = 19 } cdk_packet_type_t; +/* Define the maximal number of multiprecion integers for + a public key. */ +#define MAX_CDK_PK_PARTS 4 + +/* Define the maximal number of multiprecision integers for + a signature/encrypted blob issued by a secret key. */ +#define MAX_CDK_DATA_PARTS 2 + /* Helper macro to figure out if the packet is encrypted */ #define CDK_PKT_IS_ENCRYPTED(pkttype) (\ @@ -382,7 +389,7 @@ struct cdk_pkt_signature_s { cdk_subpkt_t hashed; unsigned short unhashed_size; cdk_subpkt_t unhashed; - gcry_mpi_t mpi[2]; + gcry_mpi_t mpi[MAX_CDK_DATA_PARTS]; cdk_desig_revoker_t revkeys; struct { unsigned exportable:1; @@ -422,7 +429,7 @@ struct cdk_pkt_pubkey_s { unsigned int main_keyid[2]; unsigned int timestamp; unsigned int expiredate; - gcry_mpi_t mpi[4]; + gcry_mpi_t mpi[MAX_CDK_PK_PARTS]; unsigned is_revoked:1; unsigned is_invalid:1; unsigned has_expired:1; @@ -454,7 +461,7 @@ struct cdk_pkt_seckey_s { unsigned char ivlen; } protect; unsigned short csum; - gcry_mpi_t mpi[4]; + gcry_mpi_t mpi[MAX_CDK_PK_PARTS]; unsigned char * encdata; size_t enclen; unsigned char is_protected; @@ -484,7 +491,7 @@ struct cdk_pkt_pubkey_enc_s { unsigned int keyid[2]; int throw_keyid; unsigned char pubkey_algo; - gcry_mpi_t mpi[2]; + gcry_mpi_t mpi[MAX_CDK_DATA_PARTS]; }; typedef struct cdk_pkt_pubkey_enc_s * cdk_pkt_pubkey_enc_t; @@ -561,12 +568,21 @@ typedef void (*cdk_log_fnc_t) (void *, int, const char *, va_list); void cdk_set_log_level (int lvl); void cdk_set_log_handler (cdk_log_fnc_t logfnc, void *opaque); const char* cdk_strerror (int ec); + +/* Allow the user to set custom hooks for memory allocation. + If this function is not used, the standard allocation functions + will be used. Extra care must be taken for the 'secure' alloc + function. */ void cdk_set_malloc_hooks (void *(*new_alloc_func) (size_t n), void *(*new_alloc_secure_func) (size_t n), void *(*new_realloc_func) (void *p, size_t n), void *(*new_calloc_func) (size_t m, size_t n), void (*new_free_func) (void *)); + +/* Return 1 if the malloc hooks were already set via the function above. */ int cdk_malloc_hook_initialized (void); + +/* Standard memory wrapper. */ void *cdk_malloc (size_t size); void *cdk_calloc (size_t n, size_t m); void *cdk_realloc (void * ptr, size_t size); @@ -584,8 +600,8 @@ void cdk_lib_startup (void); to allow the lib to cleanup its internal structures. */ void cdk_lib_shutdown (void); -/* session handle routines */ -cdk_error_t cdk_handle_new( cdk_ctx_t * r_ctx ); +/* Session handle routines */ +cdk_error_t cdk_handle_new (cdk_ctx_t *r_ctx); void cdk_handle_free (cdk_ctx_t c); /* Set the key database handle for the given session handle. @@ -609,12 +625,18 @@ void cdk_handle_set_passphrase_cb (cdk_ctx_t hd, void *cb_value); /* shortcuts for some controls */ + +/* Enable or disable armor output. */ #define cdk_handle_set_armor(a, val) \ cdk_handle_control ((a), CDK_CTLF_SET, CDK_CTL_ARMOR, (val)) -#define cdk_handle_set_compress (a, algo, level) \ +/* Set the compression algorithm and level. 0 means disable compression. */ +#define cdk_handle_set_compress(a, algo, level) \ cdk_handle_control ((a), CDK_CTLF_SET, CDK_CTL_COMPRESS, (algo), (level)) +/* Activate partial bodies for the output. This is needed if the length + of the data is not known in advance or for the use with sockets + or pipes. */ #define cdk_handle_set_blockmode(a, val) \ cdk_handle_control ((a), CDK_CTLF_SET, CDK_CTL_BLOCKMODE_ON, (val)) @@ -652,6 +674,8 @@ typedef struct cdk_verify_result_s *cdk_verify_result_t; cdk_verify_result_t cdk_handle_verify_get_result (cdk_ctx_t hd); /* Raw packet routines. */ + +/* Allocate a new packet or a new packet with the given packet type. */ cdk_error_t cdk_pkt_new (cdk_packet_t *r_pkt); cdk_error_t cdk_pkt_alloc (cdk_packet_t *r_pkt, int pkttype); @@ -690,25 +714,42 @@ const unsigned char* cdk_key_desig_revoker_walk (cdk_desig_revoker_t root, #define is_ELG(a) ((a) == CDK_PK_ELG_E) #define is_DSA(a) ((a) == CDK_PK_DSA) +/* Encrypt the given session key @SK with the public key @PK + and write the contents into the packet @PKE. */ cdk_error_t cdk_pk_encrypt (cdk_pubkey_t pk, cdk_pkt_pubkey_enc_t pke, - gcry_mpi_t esk); + gcry_mpi_t sk); + +/* Decrypt the given encrypted session key in @PKE with the secret key + @SK and store it in @R_SK. */ cdk_error_t cdk_pk_decrypt (cdk_seckey_t sk, cdk_pkt_pubkey_enc_t pke, gcry_mpi_t *r_sk); + +/* Sign the given message digest @MD with the secret key @SK and + store the signature in the packet @SIG. */ cdk_error_t cdk_pk_sign (cdk_seckey_t sk, cdk_pkt_signature_t sig, - const unsigned char * md); + const unsigned char *md); + +/* Verify the given signature in @SIG with the public key @PK + and compare it against the message digest @MD. */ cdk_error_t cdk_pk_verify (cdk_pubkey_t pk, cdk_pkt_signature_t sig, - const unsigned char * md); + const unsigned char *md); /* Use cdk_pk_get_npkey() and cdk_pk_get_nskey to find out how much multiprecision integers a key consists of. */ + +/* Return a multi precision integer of the public key with the index @IDX + in the buffer @BUF. @R_NWRITTEN will contain the length in octets. + Optional @R_NBITS may contain the size in bits. */ cdk_error_t cdk_pk_get_mpi (cdk_pubkey_t pk, size_t idx, unsigned char *buf, size_t buflen, size_t *r_nwritten, size_t *r_nbits); + +/* Same as the function above but of the secret key. */ cdk_error_t cdk_sk_get_mpi (cdk_seckey_t sk, size_t idx, unsigned char * buf, size_t buflen, size_t *r_nwritten, size_t *r_nbits); -/* Helper to get the exact number of multiprecision integers +/* Helper to get the exact number of multi precision integers for the given object. */ int cdk_pk_get_nbits (cdk_pubkey_t pk); int cdk_pk_get_npkey (int algo); @@ -724,7 +765,7 @@ unsigned int cdk_pk_fingerprint_get_keyid (const unsigned char *fpr, unsigned int cdk_pk_get_keyid (cdk_pubkey_t pk, unsigned int *keyid); unsigned int cdk_sk_get_keyid (cdk_seckey_t sk, unsigned int *keyid); unsigned int cdk_sig_get_keyid (cdk_pkt_signature_t sig, - unsigned int * keyid); + unsigned int *keyid); /* Key release functions. */ void cdk_pk_release (cdk_pubkey_t pk); @@ -732,7 +773,9 @@ void cdk_sk_release (cdk_seckey_t sk); /* Secret key related functions. */ cdk_error_t cdk_sk_unprotect (cdk_seckey_t sk, const char *pw); -cdk_error_t cdk_sk_protect( cdk_seckey_t sk, const char *pw); +cdk_error_t cdk_sk_protect (cdk_seckey_t sk, const char *pw); + +/* Create a public key with the data from the secret key @SK. */ cdk_error_t cdk_pk_from_secret_key (cdk_seckey_t sk, cdk_pubkey_t *ret_pk); @@ -838,9 +881,12 @@ int cdk_stream_peek (cdk_stream_t inp, unsigned char *buf, size_t buflen); functions should be preferred. */ cdk_error_t cdk_keydb_new (cdk_keydb_hd_t *r_hd, int type, void *data, size_t count); - + +/* Create a new key db handle from a memory buffer. */ cdk_error_t cdk_keydb_new_from_mem (cdk_keydb_hd_t *r_hd, int secret, const void *data, size_t datlen); + +/* Create a new key db which uses an existing file. */ cdk_error_t cdk_keydb_new_from_file (cdk_keydb_hd_t *r_hd, int secret, const char *fname); @@ -853,31 +899,60 @@ cdk_error_t cdk_keydb_new_from_stream (cdk_keydb_hd_t *r_hd, int secret, /* Check that a secret key with the given key ID is available. */ cdk_error_t cdk_keydb_check_sk (cdk_keydb_hd_t hd, unsigned int *keyid); +/* Prepare the key db search. */ cdk_error_t cdk_keydb_search_start (cdk_keydb_hd_t hd, int type, void *desc); + +/* Return a key which matches a valid description given in + cdk_keydb_search_start(). */ cdk_error_t cdk_keydb_search (cdk_keydb_hd_t hd, cdk_kbnode_t *ret_key); -void cdk_keydb_free( cdk_keydb_hd_t hd ); -cdk_error_t cdk_keydb_get_bykeyid( cdk_keydb_hd_t hd, unsigned int * keyid, - cdk_kbnode_t * ret_pk ); -cdk_error_t cdk_keydb_get_byfpr( cdk_keydb_hd_t hd, const unsigned char * fpr, - cdk_kbnode_t * ret_pk ); -cdk_error_t cdk_keydb_get_bypattern( cdk_keydb_hd_t hd, const char * patt, - cdk_kbnode_t * ret_pk ); -cdk_error_t cdk_keydb_get_pk( cdk_keydb_hd_t khd, unsigned int * keyid, - cdk_pubkey_t* ret_pk ); -cdk_error_t cdk_keydb_get_sk( cdk_keydb_hd_t khd, unsigned int * keyid, - cdk_seckey_t* ret_sk ); + +/* Release the key db handle and all its resources. */ +void cdk_keydb_free (cdk_keydb_hd_t hd); + +/* The following functions will try to find a key in the given key + db handle either by keyid, by fingerprint or by some pattern. */ +cdk_error_t cdk_keydb_get_bykeyid (cdk_keydb_hd_t hd, unsigned int *keyid, + cdk_kbnode_t *ret_pk); +cdk_error_t cdk_keydb_get_byfpr (cdk_keydb_hd_t hd, const unsigned char *fpr, + cdk_kbnode_t *ret_pk); +cdk_error_t cdk_keydb_get_bypattern (cdk_keydb_hd_t hd, const char *patt, + cdk_kbnode_t *ret_pk); + +/* These function, in contrast to most other key db functions, only + return the public or secret key packet without the additional + signatures and user IDs. */ +cdk_error_t cdk_keydb_get_pk (cdk_keydb_hd_t khd, unsigned int * keyid, + cdk_pubkey_t *ret_pk); +cdk_error_t cdk_keydb_get_sk (cdk_keydb_hd_t khd, unsigned int * keyid, + cdk_seckey_t *ret_sk); + +/* Try to read the next key block from the given input stream. + The key will be returned in @RET_KEY on success. */ cdk_error_t cdk_keydb_get_keyblock (cdk_stream_t inp, cdk_kbnode_t * ret_key); + +/* Rebuild the key db index if possible. */ cdk_error_t cdk_keydb_idx_rebuild (cdk_keydb_hd_t hd); + +/* Export one or more keys from the given key db handle into + the stream @OUT. The export is done by substring search and + uses the string list @REMUSR for the pattern. */ cdk_error_t cdk_keydb_export (cdk_keydb_hd_t hd, cdk_stream_t out, cdk_strlist_t remusr); + +/* Import the given key node @knode into the key db. */ cdk_error_t cdk_keydb_import (cdk_keydb_hd_t hd, cdk_kbnode_t knode); -/* listing keys */ -cdk_error_t cdk_listkey_start( cdk_listkey_t * r_ctx, cdk_keydb_hd_t db, - const char * patt, cdk_strlist_t fpatt ); -void cdk_listkey_close( cdk_listkey_t ctx ); -cdk_error_t cdk_listkey_next( cdk_listkey_t ctx, cdk_kbnode_t * ret_key ); +/* List or enumerate keys from a given key db handle. */ + +/* Start the key list process. Either use @PATT for a pattern search + or @FPATT for a list of pattern. */ +cdk_error_t cdk_listkey_start (cdk_listkey_t *r_ctx, cdk_keydb_hd_t db, + const char *patt, cdk_strlist_t fpatt); +void cdk_listkey_close (cdk_listkey_t ctx); + +/* Return the next key which matches the pattern. */ +cdk_error_t cdk_listkey_next (cdk_listkey_t ctx, cdk_kbnode_t *ret_key); /*-- kbnode.c --*/ cdk_kbnode_t cdk_kbnode_new (cdk_packet_t pkt); @@ -912,6 +987,8 @@ cdk_error_t cdk_pk_check_sigs (cdk_kbnode_t knode, cdk_keydb_hd_t hd, cdk_error_t cdk_pk_check_self_sig (cdk_kbnode_t knode, int *r_status); /*-- keylist.c --*/ +/* Return a matching algorithm from the given public key list. + @PREFTYPE can be either sym-cipher/compress/digest. */ int cdk_pklist_select_algo (cdk_keylist_t pkl, int preftype); int cdk_pklist_use_mdc (cdk_keylist_t pkl); cdk_error_t cdk_pklist_build (cdk_keylist_t *ret_pkl, cdk_keydb_hd_t hd, @@ -920,7 +997,7 @@ void cdk_pklist_release (cdk_keylist_t pkl); cdk_error_t cdk_pklist_encrypt (cdk_keylist_t pkl, cdk_dek_t dek, cdk_stream_t out); -/* secret key list */ +/* Secret key lists */ cdk_error_t cdk_sklist_build (cdk_keylist_t * ret_skl, cdk_keydb_hd_t db, cdk_ctx_t hd, cdk_strlist_t locusr, @@ -933,15 +1010,27 @@ cdk_error_t cdk_sklist_write_onepass (cdk_keylist_t skl, cdk_stream_t outp, int sigclass, int mdalgo); /*-- encrypt.c --*/ + +/* Encrypt the given stream @INP with the recipients given in @REMUSR. + If @REMUSR is NULL, symmetric encryption will be used. The output + will be written to @OUT. */ cdk_error_t cdk_stream_encrypt (cdk_ctx_t hd, cdk_strlist_t remusr, cdk_stream_t inp, cdk_stream_t out); + +/* Decrypt the @INP stream into @OUT. */ cdk_error_t cdk_stream_decrypt (cdk_ctx_t hd, cdk_stream_t inp, cdk_stream_t out); - + +/* Same as the function above but it works on files. */ cdk_error_t cdk_file_encrypt (cdk_ctx_t hd, cdk_strlist_t remusr, - const char * file, const char * output); + const char *file, const char *output); cdk_error_t cdk_file_decrypt (cdk_ctx_t hd, const char * file, - const char * output); + const char *output); + +/* Generic function to transform data. The mode can be either sign, + verify, encrypt, decrypt, import or export. The meanings of the + parameters are similar to the functions above. + @OUTBUF will contain the output and @OUTSIZE the length of it. */ cdk_error_t cdk_data_transform (cdk_ctx_t hd, enum cdk_crypto_mode_t mode, cdk_strlist_t locusr, cdk_strlist_t remusr, const void * inbuf, size_t insize, @@ -949,18 +1038,28 @@ cdk_error_t cdk_data_transform (cdk_ctx_t hd, enum cdk_crypto_mode_t mode, int modval); /*-- sign.c --*/ +/* Sign the stream @INP. Optionally, the output will be encrypted + if @REMUSR is not NULL and the @ENCRYPTFLAG is set. + The output will be written to @OUT. + @LOCUSR contains one ore more pattern for the secret key(s) to use. */ cdk_error_t cdk_stream_sign (cdk_ctx_t hd, cdk_stream_t inp, cdk_stream_t out, cdk_strlist_t locusr, cdk_strlist_t remusr, - int encryptflag, int sigmode ); + int encryptflag, int sigmode); + +/* Same as the function above but it works on files. */ cdk_error_t cdk_file_sign (cdk_ctx_t hd, cdk_strlist_t locusr, cdk_strlist_t remusr, - const char * file, const char * output, + const char *file, const char *output, int sigmode, int encryptflag); /*-- verify.c --*/ cdk_error_t cdk_stream_verify (cdk_ctx_t hd, cdk_stream_t inp, cdk_stream_t data, cdk_stream_t out); + +/* Verify the given file @FILE. For a detached signature, @DATA_FILE + contains the actual file data and @FILE is only the signature. + If the @OUTPUT is not NULL, the plaintext will be written to this file. */ cdk_error_t cdk_file_verify (cdk_ctx_t hd, const char *file, const char *data_file, const char *output); @@ -968,28 +1067,30 @@ cdk_error_t cdk_file_verify (cdk_ctx_t hd, const char *file, int cdk_trustdb_get_validity (cdk_stream_t inp, cdk_pkt_userid_t id, int *r_val); int cdk_trustdb_get_ownertrust (cdk_stream_t inp, cdk_pubkey_t pk, - int * r_val, int * r_flags); + int *r_val, int *r_flags); /*-- misc.c --*/ void cdk_strlist_free (cdk_strlist_t sl); cdk_strlist_t cdk_strlist_add (cdk_strlist_t * list, const char * string); -const char * cdk_strlist_walk (cdk_strlist_t root, cdk_strlist_t * context); +cdk_strlist_t cdk_strlist_next (cdk_strlist_t root, const char **r_str); const char * cdk_check_version (const char * req_version); /* UTF8 */ char* cdk_utf8_encode (const char * string); char* cdk_utf8_decode (const char * string, size_t length, int delim); /*-- keyserver.c --*/ -cdk_error_t cdk_keyserver_recv_key (const char * host, int port, - const unsigned char * keyid, int kid_type, - cdk_kbnode_t * r_key); +/* Try to receive the key, which has the key ID @KEYID, from the + keyserver host @HOST and the port @PORT. */ +cdk_error_t cdk_keyserver_recv_key (const char *host, int port, + const unsigned char *keyid, int kid_type, + cdk_kbnode_t *r_key); /*-- keygen.c --*/ cdk_error_t cdk_keygen_new (cdk_keygen_ctx_t * r_hd); void cdk_keygen_free (cdk_keygen_ctx_t hd); -cdk_error_t cdk_keygen_set_prefs( cdk_keygen_ctx_t hd, +cdk_error_t cdk_keygen_set_prefs (cdk_keygen_ctx_t hd, enum cdk_pref_type_t type, - const unsigned char * array, size_t n ); + const unsigned char * array, size_t n); cdk_error_t cdk_keygen_set_algo_info( cdk_keygen_ctx_t hd, int type, int usage, enum cdk_pubkey_algo_t algo, unsigned int bits ); diff --git a/libextra/opencdk/pubkey.c b/libextra/opencdk/pubkey.c index 77eec0020e..d8c23bbb63 100644 --- a/libextra/opencdk/pubkey.c +++ b/libextra/opencdk/pubkey.c @@ -298,7 +298,8 @@ cdk_pk_encrypt (cdk_pubkey_t pk, cdk_pkt_pubkey_enc_t pke, gcry_mpi_t esk) { gcry_sexp_t s_data = NULL, s_pkey = NULL, s_ciph = NULL; - int rc; + gcry_error_t err; + cdk_error_t rc; if (!pk || !esk || !pke) return CDK_Inv_Value; @@ -310,7 +311,11 @@ cdk_pk_encrypt (cdk_pubkey_t pk, cdk_pkt_pubkey_enc_t pke, if (!rc) rc = pubkey_to_sexp (&s_pkey, pk); if (!rc) - rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey); + { + err = gcry_pk_encrypt (&s_ciph, s_data, s_pkey); + if (err) + return map_gcry_error (err); + } if (!rc) rc = sexp_to_pubenc (pke, s_ciph); @@ -595,7 +600,7 @@ mpi_to_buffer (gcry_mpi_t a, byte *buf, size_t buflen, cdk_error_t -cdk_pk_get_mpi (cdk_pkt_pubkey_t pk, size_t idx, +cdk_pk_get_mpi (cdk_pubkey_t pk, size_t idx, byte *buf, size_t buflen, size_t *r_nwritten, size_t *r_nbits) { if (!pk || !r_nwritten) @@ -859,7 +864,7 @@ cdk_sk_protect (cdk_pkt_seckey_t sk, const char *pass) * Create a new public key from a secret key. **/ cdk_error_t -cdk_pk_from_secret_key (cdk_pkt_seckey_t sk, cdk_pkt_pubkey_t *ret_pk) +cdk_pk_from_secret_key (cdk_pkt_seckey_t sk, cdk_pubkey_t *ret_pk) { if (!sk) return CDK_Inv_Value; @@ -939,7 +944,7 @@ _cdk_sk_get_csum (cdk_pkt_seckey_t sk) cdk_error_t -cdk_pk_get_fingerprint (cdk_pkt_pubkey_t pk, byte *fpr) +cdk_pk_get_fingerprint (cdk_pubkey_t pk, byte *fpr) { gcry_md_hd_t hd; int md_algo; @@ -989,7 +994,7 @@ cdk_pk_fingerprint_get_keyid (const byte *fpr, size_t fprlen, u32 *keyid) u32 -cdk_pk_get_keyid (cdk_pkt_pubkey_t pk, u32 *keyid) +cdk_pk_get_keyid (cdk_pubkey_t pk, u32 *keyid) { u32 lowbits = 0; byte buf[24]; @@ -1120,7 +1125,7 @@ _cdk_pkt_get_fingerprint (cdk_packet_t pkt, byte *fpr) * (GCRYSEXP_FMT_CANON). **/ cdk_error_t -cdk_pubkey_to_sexp (cdk_pkt_pubkey_t pk, char **sexp, size_t * len) +cdk_pubkey_to_sexp (cdk_pubkey_t pk, char **sexp, size_t * len) { char *buf; size_t sexp_len; diff --git a/libextra/opencdk/read-packet.c b/libextra/opencdk/read-packet.c index 5242278251..992d84ab96 100644 --- a/libextra/opencdk/read-packet.c +++ b/libextra/opencdk/read-packet.c @@ -14,10 +14,11 @@ * GNU General Public License for more details. */ #ifdef HAVE_CONFIG_H -# include <config.h> +#include <config.h> #endif #include <string.h> #include <stdio.h> +#include <time.h> #include <assert.h> #include "opencdk.h" @@ -44,7 +45,7 @@ read_32 (cdk_stream_t s) byte buf[4]; size_t nread; - assert (buf != NULL); + assert (s != NULL); stream_read (s, buf, 4, &nread); if (nread != 4) @@ -73,15 +74,13 @@ static int read_s2k (cdk_stream_t inp, cdk_s2k_t s2k) { size_t nread; - cdk_error_t rc; if (!inp || !s2k) return CDK_Inv_Value; if (DEBUG_PKT) - _cdk_log_debug ("** read S2K part\n"); + _cdk_log_debug ("read_s2k:\n"); - rc = 0; s2k->mode = cdk_stream_getc (inp); if (cdk_stream_eof (inp)) return CDK_Inv_Packet; @@ -94,11 +93,10 @@ read_s2k (cdk_stream_t inp, cdk_s2k_t s2k) else if (s2k->mode == CDK_S2K_SALTED || s2k->mode == CDK_S2K_ITERSALTED) { - rc = stream_read (inp, s2k->salt, DIM (s2k->salt), &nread); - if (rc) + if (stream_read (inp, s2k->salt, DIM (s2k->salt), &nread)) return CDK_Inv_Packet; if (nread != DIM (s2k->salt)) - return CDK_Too_Short; + return CDK_Inv_Packet; if (s2k->mode == CDK_S2K_ITERSALTED) { s2k->count = cdk_stream_getc (inp); @@ -108,34 +106,38 @@ read_s2k (cdk_stream_t inp, cdk_s2k_t s2k) } else return CDK_Inv_Mode; - return rc; + return 0; } static cdk_error_t -read_mpi (cdk_stream_t inp, gcry_mpi_t * ret_m, int secure) +read_mpi (cdk_stream_t inp, gcry_mpi_t *ret_m, int secure) { gcry_mpi_t m; + gcry_error_t err; byte buf[MAX_MPI_BYTES+2]; size_t nread, nbits; cdk_error_t rc; - gcry_error_t err; if (!inp || !ret_m) return CDK_Inv_Value; - if (DEBUG_PKT) - _cdk_log_debug ("** read MPI part\n"); - *ret_m = NULL; nbits = read_16 (inp); nread = (nbits+7)/8; + if (nbits > MAX_MPI_BITS || nbits == 0) - return CDK_MPI_Error; /* Sanity check */ + { + _cdk_log_debug ("read_mpi: too large %d bits\n", nbits); + return CDK_MPI_Error; /* Sanity check */ + } rc = stream_read (inp, buf+2, nread, &nread); if (!rc && nread != ((nbits+7)/8)) - return CDK_MPI_Error; + { + _cdk_log_debug ("read_mpi: too short %d < %d\n", nread, (nbits+7)/8); + return CDK_MPI_Error; + } buf[0] = nbits >> 8; buf[1] = nbits >> 0; @@ -148,6 +150,7 @@ read_mpi (cdk_stream_t inp, gcry_mpi_t * ret_m, int secure) return rc; } + /* Read the encoded packet length directly from the file object INP and return it. Reset RET_PARTIAL if this is the last packet in block mode. */ @@ -186,13 +189,13 @@ _cdk_pkt_read_len (FILE *inp, size_t *ret_partial) static cdk_error_t read_encrypted (cdk_stream_t inp, size_t pktlen, cdk_pkt_encrypted_t enc, - int partial, int is_mdc) + int is_partial, int is_mdc) { if (!inp || !enc) return CDK_Inv_Value; if (DEBUG_PKT) - _cdk_log_debug ("** read encrypted packet %d bytes\n", pktlen); + _cdk_log_debug ("read_encrypted: %d octets\n", pktlen); if (is_mdc) { @@ -205,7 +208,7 @@ read_encrypted (cdk_stream_t inp, size_t pktlen, cdk_pkt_encrypted_t enc, /* The packet must at least contain blocksize + 2 octets. */ if (pktlen < 10) return CDK_Inv_Packet; - if (partial) + if (is_partial) _cdk_stream_set_blockmode (inp, pktlen); enc->len = pktlen; enc->buf = inp; @@ -217,14 +220,14 @@ static cdk_error_t read_symkey_enc (cdk_stream_t inp, size_t pktlen, cdk_pkt_symkey_enc_t ske) { cdk_s2k_t s2k; - size_t nread, minlen; - cdk_error_t rc; + size_t minlen; + size_t nread, nleft; if (!inp || !ske) return CDK_Inv_Value; if (DEBUG_PKT) - _cdk_log_debug ("** read symmetric key encrypted packet\n"); + _cdk_log_debug ("read_symkey_enc: %d octets\n", pktlen); ske->version = cdk_stream_getc (inp); if (ske->version != 4 || cdk_stream_eof (inp)) @@ -250,11 +253,10 @@ read_symkey_enc (cdk_stream_t inp, size_t pktlen, cdk_pkt_symkey_enc_t ske) s2k->hash_algo = cdk_stream_getc (inp); if (s2k->mode == CDK_S2K_SALTED || s2k->mode == CDK_S2K_ITERSALTED) { - rc = stream_read (inp, s2k->salt, DIM (s2k->salt), &nread); - if (rc) + if (stream_read (inp, s2k->salt, DIM (s2k->salt), &nread)) return CDK_Inv_Packet; if (nread != DIM (s2k->salt)) - return CDK_Too_Short; + return CDK_Inv_Packet; if (s2k->mode == CDK_S2K_ITERSALTED) s2k->count = cdk_stream_getc (inp); @@ -265,11 +267,12 @@ read_symkey_enc (cdk_stream_t inp, size_t pktlen, cdk_pkt_symkey_enc_t ske) the buffer. The maximal key length is 256-bit. */ if (ske->seskeylen > DIM (ske->seskey)) return CDK_Inv_Packet; + nleft = ske->seskeylen; for (nread = 0; nread < ske->seskeylen; nread++) { ske->seskey[nread] = cdk_stream_getc (inp); - if (cdk_stream_eof (inp)) - return CDK_Too_Short; + if (cdk_stream_eof (inp) && --nleft > 0) + return CDK_Inv_Packet; } return 0; @@ -280,13 +283,12 @@ static cdk_error_t read_pubkey_enc (cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_enc_t pke) { size_t i, nenc; - cdk_error_t rc; if (!inp || !pke) return CDK_Inv_Value; if (DEBUG_PKT) - _cdk_log_debug ("** read public key encrypted packet\n"); + _cdk_log_debug ("read_pubkey_enc: %d octets\n", pktlen); if (pktlen < 12) return CDK_Inv_Packet; @@ -303,7 +305,7 @@ read_pubkey_enc (cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_enc_t pke) return CDK_Inv_Algo; for (i = 0; i < nenc; i++) { - rc = read_mpi (inp, &pke->mpi[i], 0); + cdk_error_t rc = read_mpi (inp, &pke->mpi[i], 0); if (rc) return rc; } @@ -312,6 +314,7 @@ read_pubkey_enc (cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_enc_t pke) } + static cdk_error_t read_mdc (cdk_stream_t inp, cdk_pkt_mdc_t mdc) { @@ -322,7 +325,7 @@ read_mdc (cdk_stream_t inp, cdk_pkt_mdc_t mdc) return CDK_Inv_Value; if (DEBUG_PKT) - _cdk_log_debug ("** read MDC packet\n"); + _cdk_log_debug ("read_mdc:\n"); rc = stream_read (inp, mdc->hash, 20, &n); if (rc) @@ -339,7 +342,7 @@ read_compressed (cdk_stream_t inp, size_t pktlen, cdk_pkt_compressed_t c) return CDK_Inv_Value; if (DEBUG_PKT) - _cdk_log_debug ("** read compressed packet\n"); + _cdk_log_debug ("read_compressed: %d octets\n", pktlen); c->algorithm = cdk_stream_getc (inp); if (c->algorithm > 3) @@ -358,16 +361,15 @@ read_compressed (cdk_stream_t inp, size_t pktlen, cdk_pkt_compressed_t c) static cdk_error_t -read_public_key (cdk_stream_t inp, cdk_pkt_pubkey_t pk) +read_public_key (cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_t pk) { - cdk_error_t rc; size_t i, ndays, npkey; if (!inp || !pk) return CDK_Inv_Value; if (DEBUG_PKT) - _cdk_log_debug( "** read public key packet\n" ); + _cdk_log_debug ("read_public_key: %d octets\n", pktlen); pk->is_invalid = 1; /* default to detect missing self signatures */ pk->is_revoked = 0; @@ -387,28 +389,30 @@ read_public_key (cdk_stream_t inp, cdk_pkt_pubkey_t pk) pk->pubkey_algo = cdk_stream_getc (inp); npkey = cdk_pk_get_npkey (pk->pubkey_algo); if (!npkey) - return CDK_Inv_Algo; - rc = 0; + { + _cdk_log_debug ("invalid public key algorithm %d\n", pk->pubkey_algo); + return CDK_Inv_Algo; + } for (i = 0; i < npkey; i++) { - rc = read_mpi (inp, &pk->mpi[i], 0); + cdk_error_t rc = read_mpi (inp, &pk->mpi[i], 0); if (rc) - break; + return rc; } /* These values are just for the first run and should be replaced with the actual key flags from the self signature. */ pk->pubkey_usage = _cdk_pk_algo_usage (pk->pubkey_algo); - return rc; + return 0; } static cdk_error_t -read_public_subkey (cdk_stream_t inp, cdk_pkt_pubkey_t pk) +read_public_subkey (cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_t pk) { if (!inp || !pk) return CDK_Inv_Value; - return read_public_key (inp, pk); + return read_public_key (inp, pktlen, pk); } @@ -423,10 +427,10 @@ read_secret_key (cdk_stream_t inp, size_t pktlen, cdk_pkt_seckey_t sk) return CDK_Inv_Value; if (DEBUG_PKT) - _cdk_log_debug ("** read secret key\n"); + _cdk_log_debug ("read_secret_key: %d octets\n", pktlen); p1 = cdk_stream_tell (inp); - rc = read_public_key (inp, sk->pk); + rc = read_public_key (inp, pktlen, sk->pk); if (rc) return rc; @@ -529,15 +533,17 @@ read_secret_subkey (cdk_stream_t inp, size_t pktlen, cdk_pkt_seckey_t sk) static cdk_error_t read_attribute (cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t attr) { - size_t nread; - byte *buf; const byte *p; - size_t len; + byte *buf; + size_t len, nread; cdk_error_t rc; if (!inp || !attr || !pktlen) return CDK_Inv_Value; + if (DEBUG_PKT) + _cdk_log_debug ("read_attribute: %d octets\n", pktlen); + strcpy (attr->name, "[attribute]"); attr->len = strlen (attr->name); buf = cdk_calloc (1, pktlen); @@ -550,12 +556,11 @@ read_attribute (cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t attr) return CDK_Inv_Packet; } p = buf; - len = *p++; + len = *p++; pktlen--; if (len == 255) { len = _cdk_buftou32 (p); - p += 4; - pktlen -= 4; + p += 4; pktlen -= 4; } else if (len >= 192) { @@ -563,31 +568,26 @@ read_attribute (cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t attr) { cdk_free (buf); return CDK_Inv_Packet; - } + } len = ((len - 192) << 8) + *p + 192; - p++; - pktlen--; + p++; pktlen--; } - if (*p != 1) - { /* ATTRIBUTE IMAGE */ - cdk_free (buf); - return CDK_Inv_Packet; - } - p++; - - /* There is no maximum for the attribute data length - but even so we dissalow images larger than 100K. */ - if (len > 100000) + + if (*p != 1) /* Currently only 1, meaning an image, is defined. */ { cdk_free (buf); return CDK_Inv_Packet; - } + } + p++; len--; + + if (pktlen - (len+1) > 0) + return CDK_Inv_Packet; attr->attrib_img = cdk_calloc (1, len); if (!attr->attrib_img) { cdk_free (buf); return CDK_Out_Of_Core; - } + } attr->attrib_len = len; memcpy (attr->attrib_img, p, len); cdk_free (buf); @@ -607,7 +607,7 @@ read_user_id (cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t user_id) return CDK_Inv_Packet; if (DEBUG_PKT) - _cdk_log_debug ("** read user ID packet\n"); + _cdk_log_debug ("read_user_id: %lu octets\n", pktlen); user_id->len = pktlen; rc = stream_read (inp, user_id->name, pktlen, &nread); @@ -632,7 +632,7 @@ read_subpkt( cdk_stream_t inp, cdk_subpkt_t * r_ctx, size_t * r_nbytes ) return CDK_Inv_Value; if (DEBUG_PKT) - _cdk_log_debug ("** read sub packet"); + _cdk_log_debug ("read_subpkt:\n"); n = 0; *r_nbytes = 0; @@ -657,13 +657,12 @@ read_subpkt( cdk_stream_t inp, cdk_subpkt_t * r_ctx, size_t * r_nbytes ) return CDK_Inv_Packet; node = cdk_subpkt_new (size); - if (DEBUG_PKT) - _cdk_log_debug (" `%d' bytes\n", size); - if (!node) - return CDK_Out_Of_Core; + return CDK_Out_Of_Core; node->size = size; node->type = cdk_stream_getc (inp); + if (DEBUG_PKT) + _cdk_log_debug (" %d octets %d type\n", node->size, node->type); n++; node->size--; rc = stream_read (inp, node->d, node->size, &nread); @@ -686,7 +685,7 @@ read_onepass_sig (cdk_stream_t inp, size_t pktlen, cdk_pkt_onepass_sig_t sig) return CDK_Inv_Value; if (DEBUG_PKT) - _cdk_log_debug ("** read one pass signature packet\n"); + _cdk_log_debug ("read_onepass_sig: %d octets\n", pktlen); if (pktlen != 13) return CDK_Inv_Packet; @@ -709,7 +708,7 @@ parse_sig_subpackets (cdk_pkt_signature_t sig) cdk_subpkt_t node; /* Setup the standard packet entries, so we can use V4 - signatures similar to V3. */ + signatures similar to V3. */ for (node = sig->unhashed; node; node = node->next) { if (node->type == CDK_SIGSUBPKT_ISSUER && node->size >= 8) @@ -732,7 +731,7 @@ parse_sig_subpackets (cdk_pkt_signature_t sig) { sig->expiredate = _cdk_buftou32 (node->d); if (sig->expiredate > 0 && - sig->expiredate < _cdk_timestamp ()) + sig->expiredate < (u32)time (NULL)) sig->flags.expired = 1; } else if (node->type == CDK_SIGSUBPKT_POLICY) @@ -747,6 +746,7 @@ parse_sig_subpackets (cdk_pkt_signature_t sig) if (sig->sig_class == 0x1F) { cdk_desig_revoker_t r, rnode; + for (node = sig->hashed; node; node = node->next) { if (node->type == CDK_SIGSUBPKT_REV_KEY) @@ -774,6 +774,7 @@ parse_sig_subpackets (cdk_pkt_signature_t sig) return 0; } + static cdk_error_t read_signature (cdk_stream_t inp, size_t pktlen, cdk_pkt_signature_t sig) { @@ -785,9 +786,9 @@ read_signature (cdk_stream_t inp, size_t pktlen, cdk_pkt_signature_t sig) return CDK_Inv_Value; if (DEBUG_PKT) - _cdk_log_debug( "** read signature packet\n" ); + _cdk_log_debug ("read_signature: %d octets\n", pktlen); - if (pktlen < 10) + if (pktlen < 16) return CDK_Inv_Packet; sig->version = cdk_stream_getc (inp); if (sig->version < 2 || sig->version > 4) @@ -866,8 +867,8 @@ read_signature (cdk_stream_t inp, size_t pktlen, cdk_pkt_signature_t sig) static cdk_error_t -read_literal (cdk_stream_t inp, size_t pktlen, cdk_pkt_literal_t *ret_pt, - int partial) +read_literal (cdk_stream_t inp, size_t pktlen, + cdk_pkt_literal_t *ret_pt, int is_partial) { cdk_pkt_literal_t pt = *ret_pt; size_t nread ; @@ -877,7 +878,7 @@ read_literal (cdk_stream_t inp, size_t pktlen, cdk_pkt_literal_t *ret_pt, return CDK_Inv_Value; if (DEBUG_PKT) - _cdk_log_debug ("** read literal packet\n"); + _cdk_log_debug ("read_literal: %d octets\n", pktlen); pt->mode = cdk_stream_getc (inp); if (pt->mode != 0x62 && pt->mode != 0x74) @@ -886,7 +887,7 @@ read_literal (cdk_stream_t inp, size_t pktlen, cdk_pkt_literal_t *ret_pt, return CDK_Inv_Packet; pt->namelen = cdk_stream_getc (inp); - if (pt->namelen) + if (pt->namelen > 0) { *ret_pt = pt = cdk_realloc (pt, sizeof * pt + pt->namelen + 1); if (!pt) @@ -898,9 +899,9 @@ read_literal (cdk_stream_t inp, size_t pktlen, cdk_pkt_literal_t *ret_pt, return CDK_Inv_Packet; pt->name[pt->namelen] = '\0'; } - pt->timestamp = read_32 (inp); + pt->timestamp = read_32 (inp); pktlen = pktlen - 6 - pt->namelen; - if (partial) + if (is_partial) _cdk_stream_set_blockmode (inp, pktlen); pt->buf = inp; pt->len = pktlen; @@ -956,7 +957,7 @@ read_new_length (cdk_stream_t inp, } else if (c == 255) { - *r_len = read_32( inp ); + *r_len = read_32 (inp); (*r_size) += 4; } else @@ -967,7 +968,7 @@ read_new_length (cdk_stream_t inp, } -/* Skip an unwanted packet. Use a large buffer to speed up the read process. */ +/* Skip the current packet body. */ static void skip_packet (cdk_stream_t inp, size_t pktlen) { @@ -1012,18 +1013,18 @@ cdk_pkt_read (cdk_stream_t inp, cdk_packet_t pkt) pktsize++; if (!(ctb & 0x80)) { - _cdk_log_info ("no valid openpgp data found. " + _cdk_log_info ("cdk_pkt_read: no openpgp data found. " "(ctb=%02X; fpos=%02X)\n",ctb, cdk_stream_tell (inp)); return CDK_Inv_Packet; } - if (ctb & 0x40) - { /* RFC2440 */ + if (ctb & 0x40) /* RFC2440 packet format. */ + { pkttype = ctb & 0x3f; is_newctb = 1; } - else - { /* RFC1991 */ + else /* the old RFC1991 packet format. */ + { pkttype = ctb & 0x3f; pkttype >>= 2; is_newctb = 0; @@ -1031,7 +1032,7 @@ cdk_pkt_read (cdk_stream_t inp, cdk_packet_t pkt) if (pkttype > 63) { - _cdk_log_info ("unknown packet type (%d)\n", pkttype); + _cdk_log_info ("cdk_pkt_read: unknown type %d\n", pkttype); return CDK_Inv_Packet; } @@ -1050,11 +1051,11 @@ cdk_pkt_read (cdk_stream_t inp, cdk_packet_t pkt) { case CDK_PKT_ATTRIBUTE: pkt->pkt.user_id = cdk_calloc (1, sizeof *pkt->pkt.user_id - + pkt->pktlen); + + pkt->pktlen + 16 + 1); if (!pkt->pkt.user_id) return CDK_Out_Of_Core; rc = read_attribute (inp, pktlen, pkt->pkt.user_id); - pkt->pkttype = CDK_PKT_USER_ID; /* treated as an user id (??) */ + pkt->pkttype = CDK_PKT_ATTRIBUTE; break; case CDK_PKT_USER_ID: @@ -1069,14 +1070,14 @@ cdk_pkt_read (cdk_stream_t inp, cdk_packet_t pkt) pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key); if (!pkt->pkt.public_key) return CDK_Out_Of_Core; - rc = read_public_key (inp, pkt->pkt.public_key); + rc = read_public_key (inp, pktlen, pkt->pkt.public_key); break; case CDK_PKT_PUBLIC_SUBKEY: pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key); if (!pkt->pkt.public_key) return CDK_Out_Of_Core; - rc = read_public_subkey (inp, pkt->pkt.public_key); + rc = read_public_subkey (inp, pktlen, pkt->pkt.public_key); break; case CDK_PKT_SECRET_KEY: diff --git a/libextra/opencdk/sig-check.c b/libextra/opencdk/sig-check.c index 219891e1aa..edd445e824 100644 --- a/libextra/opencdk/sig-check.c +++ b/libextra/opencdk/sig-check.c @@ -27,10 +27,10 @@ #include "packet.h" -/* Hash all multiprecision integers of the key PK with the given +/* Hash all multi precision integers of the key PK with the given message digest context MD. */ static int -hash_mpibuf (cdk_pkt_pubkey_t pk, gcry_md_hd_t md, int usefpr) +hash_mpibuf (cdk_pubkey_t pk, gcry_md_hd_t md, int usefpr) { byte buf[MAX_MPI_BYTES]; size_t nbytes; @@ -60,7 +60,7 @@ hash_mpibuf (cdk_pkt_pubkey_t pk, gcry_md_hd_t md, int usefpr) MD. The USEFPR param is only valid for version 3 keys because of the different way to calculate the fingerprint. */ int -_cdk_hash_pubkey (cdk_pkt_pubkey_t pk, gcry_md_hd_t md, int usefpr) +_cdk_hash_pubkey (cdk_pubkey_t pk, gcry_md_hd_t md, int usefpr) { byte buf[12]; u16 n; @@ -188,26 +188,28 @@ _cdk_hash_sig_data (cdk_pkt_signature_t sig, gcry_md_hd_t md) static void cache_sig_result (cdk_pkt_signature_t sig, int res) { - sig->flags.checked = 0; - sig->flags.valid = 0; - if (!res) { - sig->flags.checked = 1; - sig->flags.valid = 1; + sig->flags.checked = 0; + sig->flags.valid = 0; + if (!res) + { + sig->flags.checked = 1; + sig->flags.valid = 1; } - else if (res == CDK_Bad_Sig) { - sig->flags.checked = 1; - sig->flags.valid = 0; + else if (res == CDK_Bad_Sig) + { + sig->flags.checked = 1; + sig->flags.valid = 0; } } cdk_error_t -_cdk_sig_check (cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig, +_cdk_sig_check (cdk_pubkey_t pk, cdk_pkt_signature_t sig, gcry_md_hd_t digest, int *r_expired) { byte md[MAX_DIGEST_LEN]; - time_t cur_time = _cdk_timestamp (); - int rc; + time_t cur_time = (u32)time (NULL); + cdk_error_t rc; if (!pk || !sig || !digest) return CDK_Inv_Value; @@ -243,7 +245,7 @@ _cdk_pk_check_sig (cdk_keydb_hd_t keydb, cdk_kbnode_t knode, cdk_kbnode_t snode, int *is_selfsig) { gcry_md_hd_t md; - cdk_pkt_pubkey_t pk; + cdk_pubkey_t pk; cdk_pkt_signature_t sig; cdk_kbnode_t node; int is_expired; @@ -318,7 +320,7 @@ _cdk_pk_check_sig (cdk_keydb_hd_t keydb, } else if (keydb != NULL) { - cdk_pkt_pubkey_t sig_pk; + cdk_pubkey_t sig_pk; rc = cdk_keydb_get_pk (keydb, sig->keyid, &sig_pk); if (!rc) diff --git a/libextra/opencdk/stream.c b/libextra/opencdk/stream.c index bfc0c5978b..40e31dd8c5 100644 --- a/libextra/opencdk/stream.c +++ b/libextra/opencdk/stream.c @@ -39,6 +39,14 @@ static int stream_flush (cdk_stream_t s); static int stream_filter_write (cdk_stream_t s); static int stream_cache_flush (cdk_stream_t s, FILE *fp); +/* Customized tmpfile() version from misc.c */ +FILE *my_tmpfile (void); + + +/* FIXME: The read/write/putc/getc function cannot directly + return an error code. It is stored in an error variable + inside the string. Right now there is no code to + return the error code or to reset it. */ /** * cdk_stream_open: @@ -104,7 +112,7 @@ cdk_stream_new_from_cbs (cdk_stream_cbs_t cbs, void *opa, { cdk_stream_t s; - if (!opa) + if (!cbs || !opa || !ret_s) return CDK_Inv_Value; *ret_s = NULL; @@ -158,7 +166,7 @@ cdk_stream_new (const char *file, cdk_stream_t *ret_s) return CDK_Out_Of_Core; } } - s->fp = tmpfile (); + s->fp = my_tmpfile (); if (!s->fp) { cdk_free (s->fname); @@ -251,7 +259,7 @@ cdk_stream_tmp_from_mem (const void *buf, size_t buflen, cdk_stream_t *r_out) if (nwritten == EOF) { cdk_stream_close (s); - return CDK_File_Error; + return s->error; } cdk_stream_seek (s, 0); *r_out = s; @@ -457,7 +465,11 @@ cdk_stream_eof (cdk_stream_t s) const char* _cdk_stream_get_fname (cdk_stream_t s) { - return s? s->fname : NULL; + if (!s) + return NULL; + if (s->flags.temp) + return NULL; + return s->fname? s->fname : NULL; } @@ -664,41 +676,45 @@ stream_filter_write (cdk_stream_t s) if( s->flags.filtrated ) return CDK_Inv_Value; - for( f = s->filters; f; f = f->next ) { - if( !f->flags.enabled ) - continue; - /* if there is no next filter, create the final output file */ - _cdk_log_debug( "filter [write]: last filter=%d fname=%s\n", - f->next? 1 : 0, s->fname ); - if( !f->next && s->fname ) - f->tmp = fopen( s->fname, "w+b" ); - else - f->tmp = tmpfile( ); - if( !f->tmp ) { - rc = CDK_File_Error; - break; - } - /* If there is no next filter, flush the cache. We also do this - when the next filter is the armor filter because this filter - is special and before it starts, all data should be written. */ - if( (!f->next || f->next->type == fARMOR) && s->cache.size ) { - rc = stream_cache_flush( s, f->tmp ); - if( rc ) - break; + for( f = s->filters; f; f = f->next ) + { + if (!f->flags.enabled) + continue; + /* if there is no next filter, create the final output file */ + _cdk_log_debug( "filter [write]: last filter=%d fname=%s\n", + f->next? 1 : 0, s->fname ); + if (!f->next && s->fname) + f->tmp = fopen (s->fname, "w+b"); + else + f->tmp = my_tmpfile (); + if (!f->tmp) + { + rc = CDK_File_Error; + break; } - rc = f->fnct( f->opaque, f->ctl, s->fp, f->tmp ); - _cdk_log_debug ("filter [write]: type=%d rc=%d\n", f->type, rc); - if( !rc ) - rc = stream_fp_replace( s, &f->tmp ); - if( !rc ) - rc = cdk_stream_seek( s, 0 ); - if( rc ) { - _cdk_log_debug ("filter [close]: fd=%d\n", fileno (f->tmp)); - fclose( f->tmp ); - break; + /* If there is no next filter, flush the cache. We also do this + when the next filter is the armor filter because this filter + is special and before it starts, all data should be written. */ + if( (!f->next || f->next->type == fARMOR) && s->cache.size ) + { + rc = stream_cache_flush (s, f->tmp); + if (rc) + break; } + rc = f->fnct( f->opaque, f->ctl, s->fp, f->tmp ); + _cdk_log_debug ("filter [write]: type=%d rc=%d\n", f->type, rc); + if (!rc) + rc = stream_fp_replace (s, &f->tmp); + if (!rc) + rc = cdk_stream_seek (s, 0); + if (rc) + { + _cdk_log_debug ("filter [close]: fd=%d\n", fileno (f->tmp)); + fclose (f->tmp); + break; + } } - return rc; + return rc; } @@ -729,7 +745,7 @@ stream_filter_read (cdk_stream_t s) continue; } - f->tmp = tmpfile (); + f->tmp = my_tmpfile (); if (!f->tmp) { rc = CDK_File_Error; @@ -801,23 +817,29 @@ _cdk_stream_get_opaque (cdk_stream_t s, int fid) * need to add the filters in reserved order. **/ int -cdk_stream_read (cdk_stream_t s, void * buf, size_t count) +cdk_stream_read (cdk_stream_t s, void *buf, size_t buflen) { int nread; int rc; if (!s) - return EOF; + { + s->error = CDK_Inv_Value; + return EOF; + } if (s->cbs_hd) { if (s->cbs.read) - return s->cbs.read (s->cbs_hd, buf, count); + return s->cbs.read (s->cbs_hd, buf, buflen); return 0; } if (s->flags.write && !s->flags.temp) - return EOF; /* this is a write stream */ + { + s->error = CDK_Inv_Mode; + return EOF; /* This is a write stream */ + } if (!s->flags.no_filter && !s->cache.on && !s->flags.filtrated) { @@ -831,13 +853,16 @@ cdk_stream_read (cdk_stream_t s, void * buf, size_t count) } s->flags.filtrated = 1; } - if (!buf && !count) + if (!buf && !buflen) return 0; - nread = fread (buf, 1, count, s->fp); + nread = fread (buf, 1, buflen, s->fp); if (!nread) nread = EOF; if (feof (s->fp)) - s->flags.eof = 1; + { + s->error = 0; + s->flags.eof = 1; + } return nread; } @@ -849,7 +874,10 @@ cdk_stream_getc (cdk_stream_t s) int nread; if (!s) - return EOF; + { + s->error = CDK_Inv_Value; + return EOF; + } nread = cdk_stream_read (s, buf, 1); if (nread == EOF) { @@ -876,7 +904,10 @@ cdk_stream_write (cdk_stream_t s, const void * buf, size_t count) int nwritten; if (!s) - return EOF; + { + s->error = CDK_Inv_Value; + return EOF; + } if (s->cbs_hd) { @@ -917,7 +948,10 @@ cdk_stream_putc (cdk_stream_t s, int c) int nwritten; if (!s) - return EOF; + { + s->error = CDK_Inv_Value; + return EOF; + } buf[0] = c; nwritten = cdk_stream_write (s, buf, 1); if (nwritten == EOF) @@ -936,7 +970,7 @@ cdk_stream_tell (cdk_stream_t s) cdk_error_t cdk_stream_seek (cdk_stream_t s, off_t offset) { - cdk_error_t rc; + off_t len; if (!s) return CDK_Inv_Value; @@ -947,13 +981,17 @@ cdk_stream_seek (cdk_stream_t s, off_t offset) return s->cbs.seek (s->cbs_hd, offset); return 0; } - - if (offset < cdk_stream_get_length (s)) + + /* Set or reset the EOF flag. */ + len = cdk_stream_get_length (s); + if (len == offset) + s->flags.eof = 1; + else s->flags.eof = 0; - rc = fseek (s->fp, offset, SEEK_SET); - if (rc) - rc = CDK_File_Error; - return rc; + + if (fseek (s->fp, offset, SEEK_SET)) + return CDK_File_Error; + return 0; } @@ -985,19 +1023,25 @@ cdk_stream_set_armor_flag (cdk_stream_t s, int type) cdk_error_t -cdk_stream_set_literal_flag( cdk_stream_t s, int mode, const char * fname ) +cdk_stream_set_literal_flag (cdk_stream_t s, int mode, const char *fname) { - struct stream_filter_s * f; + struct stream_filter_s *f; + const char *orig_fname; + + _cdk_log_debug ("stream: enable literal mode.\n"); if (!s) return CDK_Inv_Value; + + orig_fname = _cdk_stream_get_fname (s); f = filter_add (s, _cdk_filter_literal, fLITERAL); if (!f) return CDK_Out_Of_Core; f->u.pfx.mode = mode; - f->u.pfx.filename = fname? cdk_strdup( fname ) : NULL; + f->u.pfx.filename = fname? cdk_strdup (fname) : NULL; + f->u.pfx.orig_filename = orig_fname? cdk_strdup (orig_fname): NULL; f->ctl = stream_get_mode (s); - if (s->blkmode) + if (s->blkmode > 0) { f->u.pfx.blkmode.on = 1; f->u.pfx.blkmode.size = s->blkmode; @@ -1007,20 +1051,21 @@ cdk_stream_set_literal_flag( cdk_stream_t s, int mode, const char * fname ) cdk_error_t -cdk_stream_set_cipher_flag( cdk_stream_t s, cdk_dek_t dek, int use_mdc ) +cdk_stream_set_cipher_flag (cdk_stream_t s, cdk_dek_t dek, int use_mdc) { struct stream_filter_s * f; + _cdk_log_debug ("stream: enable cipher mode\n"); if (!s) return CDK_Inv_Value; f = filter_add (s, _cdk_filter_cipher, fCIPHER); - if( !f ) + if (!f) return CDK_Out_Of_Core; dek->use_mdc = use_mdc; f->ctl = stream_get_mode (s); f->u.cfx.dek = dek; f->u.cfx.mdc_method = use_mdc? GCRY_MD_SHA1 : 0; - if (s->blkmode) + if (s->blkmode > 0) { f->u.cfx.blkmode.on = 1; f->u.cfx.blkmode.size = s->blkmode; @@ -1056,16 +1101,16 @@ cdk_stream_set_text_flag (cdk_stream_t s, const char *lf) f = filter_add (s, _cdk_filter_text, fTEXT); if (!f) return CDK_Out_Of_Core; - f->ctl = stream_get_mode( s ); + f->ctl = stream_get_mode (s); f->u.tfx.lf = lf; return 0; } cdk_error_t -cdk_stream_set_hash_flag (cdk_stream_t s, int algo) +cdk_stream_set_hash_flag (cdk_stream_t s, int digest_algo) { - struct stream_filter_s * f; + struct stream_filter_s *f; if (!s) return CDK_Inv_Value; @@ -1075,7 +1120,7 @@ cdk_stream_set_hash_flag (cdk_stream_t s, int algo) if (!f) return CDK_Out_Of_Core; f->ctl = stream_get_mode (s); - f->u.mfx.digest_algo = algo; + f->u.mfx.digest_algo = digest_algo; f->flags.rdonly = 1; return 0; } @@ -1149,7 +1194,7 @@ cdk_stream_kick_off (cdk_stream_t inp, cdk_stream_t out) { /* In case of errors, we leave the loop. */ rc = inp->error; break; - } + } } wipemem (buf, sizeof (buf)); @@ -1225,18 +1270,18 @@ cdk_stream_mmap (cdk_stream_t inp, byte **buf, size_t *buflen) * the file pointer is moved to the old position after the bytes were read. **/ int -cdk_stream_peek (cdk_stream_t inp, byte *s, size_t count) +cdk_stream_peek (cdk_stream_t inp, byte *buf, size_t buflen) { off_t off; int nbytes; - if (!inp || !s) + if (!inp || !buf) return 0; if (inp->cbs_hd) return 0; off = cdk_stream_tell (inp); - nbytes = _cdk_stream_gets (inp, (char*)s, count); + nbytes = cdk_stream_read (inp, buf, buflen); if (nbytes == -1) return 0; if (cdk_stream_seek (inp, off)) diff --git a/libextra/opencdk/verify.c b/libextra/opencdk/verify.c index 3debeab879..7bd388afe5 100644 --- a/libextra/opencdk/verify.c +++ b/libextra/opencdk/verify.c @@ -19,6 +19,7 @@ #include <stdio.h> #include <string.h> #include <assert.h> +#include <sys/stat.h> #include "opencdk.h" #include "main.h" @@ -75,6 +76,7 @@ cdk_error_t cdk_file_verify (cdk_ctx_t hd, const char *file, const char *data_file, const char *output) { + struct stat stbuf; cdk_stream_t inp, data; char buf[4096]; int n; @@ -82,7 +84,7 @@ cdk_file_verify (cdk_ctx_t hd, const char *file, const char *data_file, if (!hd || !file) return CDK_Inv_Value; - if (output && !hd->opt.overwrite && !_cdk_check_file (output)) + if (output && !hd->opt.overwrite && !stat (output, &stbuf)) return CDK_Inv_Mode; rc = cdk_stream_open (file, &inp); diff --git a/libextra/opencdk/write-packet.c b/libextra/opencdk/write-packet.c index 12488bd422..6b8f8eaecb 100644 --- a/libextra/opencdk/write-packet.c +++ b/libextra/opencdk/write-packet.c @@ -14,10 +14,11 @@ * GNU General Public License for more details. */ #ifdef HAVE_CONFIG_H -# include <config.h> +#include <config.h> #endif #include <string.h> #include <stdio.h> +#include <assert.h> #include "opencdk.h" #include "main.h" @@ -39,12 +40,12 @@ static int stream_read (cdk_stream_t s, void *buf, size_t buflen, size_t *r_nread) { int nread; - - if (!r_nread) - return CDK_Inv_Value; + + assert (r_nread); + nread = cdk_stream_read (s, buf, buflen); if (nread == EOF) - return CDK_File_Error; + return _cdk_stream_get_errno (s); *r_nread = nread; return 0; } @@ -55,7 +56,7 @@ stream_putc (cdk_stream_t s, int c) { int nwritten = cdk_stream_putc (s, c); if (nwritten == EOF) - return CDK_File_Error; + return _cdk_stream_get_errno (s); return 0; } @@ -85,13 +86,13 @@ write_16 (cdk_stream_t out, u16 u) static size_t -calc_mpisize (gcry_mpi_t mpi[4], size_t ncount) +calc_mpisize (gcry_mpi_t mpi[MAX_CDK_PK_PARTS], size_t ncount) { size_t size, i; - size=0; + size = 0; for (i = 0; i < ncount; i++) - size += (gcry_mpi_get_nbits (mpi[i])+7)/8 + 2; + size += (gcry_mpi_get_nbits (mpi[i]) + 7) / 8 + 2; return size; } @@ -116,7 +117,7 @@ write_mpi (cdk_stream_t out, gcry_mpi_t m) static cdk_error_t -write_mpibuf (cdk_stream_t out, gcry_mpi_t mpi[4], size_t count) +write_mpibuf (cdk_stream_t out, gcry_mpi_t mpi[MAX_CDK_PK_PARTS], size_t count) { size_t i; cdk_error_t rc; @@ -136,8 +137,8 @@ pkt_encode_len (cdk_stream_t out, size_t pktlen) { cdk_error_t rc; - if (!out) - return CDK_Inv_Value; + assert (out); + rc = 0; if (!pktlen) { @@ -169,8 +170,8 @@ write_head_new (cdk_stream_t out, size_t size, int type) { cdk_error_t rc; - if (!out) - return CDK_Inv_Value; + assert (out); + if (type < 0 || type > 63) return CDK_Inv_Packet; rc = stream_putc (out, (0xC0 | type)); @@ -186,8 +187,8 @@ write_head_old (cdk_stream_t out, size_t size, int type) cdk_error_t rc; int ctb; - if (!out) - return CDK_Inv_Value; + assert (out); + if (type < 0 || type > 16) return CDK_Inv_Packet; ctb = 0x80 | (type << 2); @@ -216,12 +217,14 @@ write_head_old (cdk_stream_t out, size_t size, int type) } -/* write special PGP2 packet header. PGP2 (wrongly) uses two byte header +/* Write special PGP2 packet header. PGP2 (wrongly) uses two byte header length for signatures and keys even if the size is < 256. */ static cdk_error_t pkt_write_head2 (cdk_stream_t out, size_t size, int type) { - int rc = cdk_stream_putc (out, 0x80 | (type << 2) | 1); + cdk_error_t rc; + + rc = cdk_stream_putc (out, 0x80 | (type << 2) | 1); if (!rc) rc = cdk_stream_putc (out, size >> 8); if (!rc) @@ -245,11 +248,11 @@ write_encrypted (cdk_stream_t out, cdk_pkt_encrypted_t enc, int old_ctb) size_t nbytes; cdk_error_t rc; - if (!out || !enc) - return CDK_Inv_Value; + assert (out); + assert (enc); if (DEBUG_PKT) - _cdk_log_debug ("** write encrypted packet %lu bytes\n", enc->len); + _cdk_log_debug ("write_encrypted: %lu bytes\n", enc->len); nbytes = enc->len ? (enc->len + enc->extralen) : 0; rc = pkt_write_head (out, old_ctb, nbytes, CDK_PKT_ENCRYPTED); @@ -264,13 +267,14 @@ write_encrypted_mdc (cdk_stream_t out, cdk_pkt_encrypted_t enc) size_t nbytes; cdk_error_t rc; - if (!out || !enc) - return CDK_Inv_Value; + assert (out); + assert (enc); + if (!enc->mdc_method) return CDK_Inv_Packet; if (DEBUG_PKT) - _cdk_log_debug ("** write encrypted mdc packet %lu bytes\n", enc->len); + _cdk_log_debug ("write_encrypted_mdc: %lu bytes\n", enc->len); nbytes = enc->len ? (enc->len + enc->extralen + 1) : 0; rc = pkt_write_head (out, 0, nbytes, CDK_PKT_ENCRYPTED_MDC); @@ -288,13 +292,14 @@ write_symkey_enc (cdk_stream_t out, cdk_pkt_symkey_enc_t ske) size_t size = 0, s2k_size = 0; cdk_error_t rc; - if (!out || !ske) - return CDK_Inv_Value; + assert (out); + assert (ske); + if (ske->version != 4) return CDK_Inv_Packet; if (DEBUG_PKT) - _cdk_log_debug ("** write symmetric key encrypted packet\n"); + _cdk_log_debug ("write_symkey_enc:\n"); s2k = ske->s2k; if (s2k->mode == CDK_S2K_SALTED || s2k->mode == CDK_S2K_ITERSALTED) @@ -330,15 +335,16 @@ write_pubkey_enc (cdk_stream_t out, cdk_pkt_pubkey_enc_t pke, int old_ctb) size_t size; int rc, nenc; - if (!out || !pke) - return CDK_Inv_Value; + assert (out); + assert (pke); + if (pke->version < 2 || pke->version > 3) return CDK_Inv_Packet; if (!KEY_CAN_ENCRYPT (pke->pubkey_algo)) return CDK_Inv_Algo; if (DEBUG_PKT) - _cdk_log_debug ("** write public key encrypted packet\n"); + _cdk_log_debug ("write_pubkey_enc:\n"); nenc = cdk_pk_get_nenc (pke->pubkey_algo); size = 10 + calc_mpisize (pke->mpi, nenc); @@ -364,11 +370,11 @@ write_mdc (cdk_stream_t out, cdk_pkt_mdc_t mdc) { cdk_error_t rc; - if (!out || !mdc) - return CDK_Inv_Value; + assert (mdc); + assert (out); if (DEBUG_PKT) - _cdk_log_debug ("** write_mdc packet\n"); + _cdk_log_debug ("write_mdc:\n"); /* This packet requires a fixed header encoding */ rc = stream_putc (out, 0xD3); /* packet ID and 1 byte length */ @@ -392,279 +398,305 @@ calc_subpktsize (cdk_subpkt_t s) static cdk_error_t +write_v3_sig (cdk_stream_t out, cdk_pkt_signature_t sig, int nsig) +{ + size_t size; + cdk_error_t rc; + + size = 19 + calc_mpisize (sig->mpi, nsig); + if (is_RSA (sig->pubkey_algo)) + rc = pkt_write_head2 (out, size, CDK_PKT_SIGNATURE); + else + rc = pkt_write_head (out, 1, size, CDK_PKT_SIGNATURE); + if (!rc) + rc = stream_putc (out, sig->version); + if (!rc) + rc = stream_putc (out, 5); + if (!rc) + rc = stream_putc (out, sig->sig_class); + if (!rc) + rc = write_32 (out, sig->timestamp); + if (!rc) + rc = write_32 (out, sig->keyid[0]); + if (!rc) + rc = write_32 (out, sig->keyid[1]); + if (!rc) + rc = stream_putc (out, sig->pubkey_algo); + if (!rc) + rc = stream_putc (out, sig->digest_algo); + if (!rc) + rc = stream_putc (out, sig->digest_start[0]); + if (!rc) + rc = stream_putc (out, sig->digest_start[1]); + if (!rc) + rc = write_mpibuf (out, sig->mpi, nsig); + return rc; +} + + +static cdk_error_t write_signature (cdk_stream_t out, cdk_pkt_signature_t sig, int old_ctb) { byte *buf; size_t nbytes, size, nsig; cdk_error_t rc; - if (!out || !sig) - return CDK_Inv_Value; + assert (out); + assert (sig); - if (!KEY_CAN_SIGN( sig->pubkey_algo)) + if (!KEY_CAN_SIGN (sig->pubkey_algo)) return CDK_Inv_Algo; if (sig->version < 2 || sig->version > 4) return CDK_Inv_Packet; if (DEBUG_PKT) - _cdk_log_debug ("** write signature packet\n"); + _cdk_log_debug ("write_signature:\n"); nsig = cdk_pk_get_nsig (sig->pubkey_algo); if (!nsig) return CDK_Inv_Algo; if (sig->version < 4) + return write_v3_sig (out, sig, nsig); + + size = 10 + calc_subpktsize (sig->hashed) + + calc_subpktsize (sig->unhashed) + + calc_mpisize (sig->mpi, nsig); + rc = pkt_write_head (out, 0, size, CDK_PKT_SIGNATURE); + if (!rc) + rc = stream_putc (out, 4); + if (!rc) + rc = stream_putc (out, sig->sig_class); + if (!rc) + rc = stream_putc (out, sig->pubkey_algo); + if (!rc) + rc = stream_putc (out, sig->digest_algo); + if (!rc) + rc = write_16 (out, sig->hashed_size); + if (!rc) { - size = 19 + calc_mpisize( sig->mpi, nsig ); - if (is_RSA (sig->pubkey_algo)) - rc = pkt_write_head2 (out, size, CDK_PKT_SIGNATURE); - else - rc = pkt_write_head (out, old_ctb, size, CDK_PKT_SIGNATURE); - if (!rc) - rc = stream_putc (out, sig->version); - if (!rc) - rc = stream_putc (out, 5); - if (!rc) - rc = stream_putc (out, sig->sig_class); - if (!rc) - rc = write_32 (out, sig->timestamp); - if (!rc) - rc = write_32 (out, sig->keyid[0]); - if (!rc) - rc = write_32 (out, sig->keyid[1]); - if (!rc) - rc = stream_putc (out, sig->pubkey_algo); - if (!rc) - rc = stream_putc (out, sig->digest_algo); - if (!rc) - rc = stream_putc (out, sig->digest_start[0]); - if (!rc) - rc = stream_putc (out, sig->digest_start[1]); + buf = _cdk_subpkt_get_array (sig->hashed, 0, &nbytes); + if (!buf) + return CDK_Out_Of_Core; + rc = stream_write (out, buf, nbytes); + cdk_free (buf); } - else + if (!rc) + rc = write_16 (out, sig->unhashed_size); + if (!rc) { - size = 10 + calc_subpktsize (sig->hashed) - + calc_subpktsize (sig->unhashed) - + calc_mpisize (sig->mpi, nsig); - rc = pkt_write_head (out, 0, size, CDK_PKT_SIGNATURE); - if( !rc) - rc = stream_putc (out, 4); - if (!rc) - rc = stream_putc (out, sig->sig_class); - if( !rc ) - rc = stream_putc (out, sig->pubkey_algo); - if( !rc ) - rc = stream_putc (out, sig->digest_algo); - if( !rc ) - rc = write_16 (out, sig->hashed_size); - if( !rc ) { - buf = _cdk_subpkt_get_array (sig->hashed, 0, &nbytes); - if (!buf) - return CDK_Out_Of_Core; - rc = stream_write (out, buf, nbytes); - cdk_free (buf); - } - if (!rc) - rc = write_16 (out, sig->unhashed_size); - if (!rc) - { - buf = _cdk_subpkt_get_array (sig->unhashed, 0, &nbytes); - if (!buf) - return CDK_Out_Of_Core; - rc = stream_write (out, buf, nbytes); - cdk_free (buf); - } - if (!rc) - rc = stream_putc (out, sig->digest_start[0]); - if (!rc) - rc = stream_putc (out, sig->digest_start[1]); + buf = _cdk_subpkt_get_array (sig->unhashed, 0, &nbytes); + if (!buf) + return CDK_Out_Of_Core; + rc = stream_write (out, buf, nbytes); + cdk_free (buf); } if (!rc) + rc = stream_putc (out, sig->digest_start[0]); + if (!rc) + rc = stream_putc (out, sig->digest_start[1]); + if (!rc) rc = write_mpibuf (out, sig->mpi, nsig); return rc; } -static int -write_public_key( cdk_stream_t out, cdk_pkt_pubkey_t pk, - int is_subkey, int old_ctb ) +static cdk_error_t +write_public_key (cdk_stream_t out, cdk_pkt_pubkey_t pk, + int is_subkey, int old_ctb) { - int rc = 0; - int pkttype, ndays = 0; - size_t npkey = 0, size = 6; - - if( !out || !pk ) - return CDK_Inv_Value; - if( pk->version < 2 || pk->version > 4 ) - return CDK_Inv_Packet; - - if (DEBUG_PKT) - _cdk_log_debug ("** write public key packet\n"); - - pkttype = is_subkey? CDK_PKT_PUBLIC_SUBKEY : CDK_PKT_PUBLIC_KEY; - npkey = cdk_pk_get_npkey( pk->pubkey_algo ); - if( !npkey ) - return CDK_Inv_Algo; - if( pk->version < 4 ) - size += 2; /* expire date */ - if( is_subkey ) - old_ctb = 0; - size += calc_mpisize( pk->mpi, npkey ); - if( old_ctb ) - rc = pkt_write_head2( out, size, pkttype ); - else - rc = pkt_write_head( out, old_ctb, size, pkttype ); - if( !rc ) - rc = stream_putc( out, pk->version ); - if( !rc ) - rc = write_32( out, pk->timestamp ); - if( !rc && pk->version < 4 ) { - if( pk->expiredate ) - ndays = (u16) ((pk->expiredate - pk->timestamp) / 86400L); - rc = write_16( out, ndays ); + int pkttype, ndays = 0; + size_t npkey = 0, size = 6; + cdk_error_t rc; + + assert (out); + assert (pk); + + if (pk->version < 2 || pk->version > 4) + return CDK_Inv_Packet; + + if (DEBUG_PKT) + _cdk_log_debug ("write_public_key: subkey=%d\n", is_subkey); + + pkttype = is_subkey? CDK_PKT_PUBLIC_SUBKEY : CDK_PKT_PUBLIC_KEY; + npkey = cdk_pk_get_npkey (pk->pubkey_algo); + if (!npkey) + return CDK_Inv_Algo; + if (pk->version < 4) + size += 2; /* expire date */ + if (is_subkey) + old_ctb = 0; + size += calc_mpisize (pk->mpi, npkey); + if (old_ctb) + rc = pkt_write_head2 (out, size, pkttype); + else + rc = pkt_write_head (out, old_ctb, size, pkttype); + if (!rc) + rc = stream_putc (out, pk->version); + if (!rc) + rc = write_32 (out, pk->timestamp); + if (!rc && pk->version < 4) + { + if (pk->expiredate) + ndays = (u16) ((pk->expiredate - pk->timestamp) / 86400L); + rc = write_16 (out, ndays); } - if( !rc ) - rc = stream_putc( out, pk->pubkey_algo ); - if( !rc ) - rc = write_mpibuf( out, pk->mpi, npkey ); - return rc; + if (!rc) + rc = stream_putc (out, pk->pubkey_algo); + if (!rc) + rc = write_mpibuf (out, pk->mpi, npkey); + return rc; } static int -calc_s2ksize( cdk_pkt_seckey_t sk ) +calc_s2ksize (cdk_pkt_seckey_t sk) { - size_t nbytes = 0; - - if( !sk->is_protected ) - return 0; - switch( sk->protect.s2k->mode ) { - case CDK_S2K_SIMPLE : nbytes = 2; break; - case CDK_S2K_SALTED : nbytes = 10; break; - case CDK_S2K_ITERSALTED: nbytes = 11; break; + size_t nbytes = 0; + + if (!sk->is_protected) + return 0; + switch (sk->protect.s2k->mode) + { + case CDK_S2K_SIMPLE : nbytes = 2; break; + case CDK_S2K_SALTED : nbytes = 10; break; + case CDK_S2K_ITERSALTED: nbytes = 11; break; } - nbytes += sk->protect.ivlen; - nbytes++; /* single cipher byte */ - return nbytes; + nbytes += sk->protect.ivlen; + nbytes++; /* single cipher byte */ + return nbytes; } -static int +static cdk_error_t write_secret_key( cdk_stream_t out, cdk_pkt_seckey_t sk, int is_subkey, int old_ctb ) { - cdk_pkt_pubkey_t pk = NULL; - size_t size = 6, npkey, nskey; - int pkttype, s2k_mode; - int rc = 0; - - if( !out || !sk || !sk->pk ) - return CDK_Inv_Value; - - pk = sk->pk; - if( pk->version < 2 || pk->version > 4 ) - return CDK_Inv_Packet; - - if (DEBUG_PKT) - _cdk_log_debug ("** write secret key packet\n"); - - npkey = cdk_pk_get_npkey( pk->pubkey_algo ); - nskey = cdk_pk_get_nskey( pk->pubkey_algo ); - if( !npkey || !nskey ) - return CDK_Inv_Algo; - if( pk->version < 4 ) - size += 2; - /* if the key is unprotected, the 1 extra byte: - 1 octet - cipher algorithm byte (0x00) + cdk_pkt_pubkey_t pk = NULL; + size_t size = 6, npkey, nskey; + int pkttype, s2k_mode; + cdk_error_t rc; + + assert (out); + assert (sk); + + if (!sk->pk) + return CDK_Inv_Value; + pk = sk->pk; + if (pk->version < 2 || pk->version > 4) + return CDK_Inv_Packet; + + if (DEBUG_PKT) + _cdk_log_debug ("write_secret_key:\n"); + + npkey = cdk_pk_get_npkey (pk->pubkey_algo); + nskey = cdk_pk_get_nskey (pk->pubkey_algo); + if (!npkey || !nskey) + return CDK_Inv_Algo; + if (pk->version < 4) + size += 2; + /* If the key is unprotected, the 1 extra byte: + 1 octet - cipher algorithm byte (0x00) the other bytes depend on the mode: - a) simple checksum - 2 octets - b) sha-1 checksum - 20 octets */ - size = !sk->is_protected? size + 1 : size + 1 + calc_s2ksize( sk ); - size += calc_mpisize( pk->mpi, npkey ); - if( sk->version == 3 || !sk->is_protected ) { - if( sk->version == 3 ) { - size += 2; /* force simple checksum */ - sk->protect.sha1chk = 0; - } - else - size += sk->protect.sha1chk? 20 : 2; - size += calc_mpisize( sk->mpi, nskey ); + a) simple checksum - 2 octets + b) sha-1 checksum - 20 octets */ + size = !sk->is_protected? size + 1 : size + 1 + calc_s2ksize (sk); + size += calc_mpisize (pk->mpi, npkey); + if (sk->version == 3 || !sk->is_protected) + { + if (sk->version == 3) + { + size += 2; /* force simple checksum */ + sk->protect.sha1chk = 0; + } + else + size += sk->protect.sha1chk? 20 : 2; + size += calc_mpisize (sk->mpi, nskey); } - else /* we do not know anything about the encrypted mpi's so we - treat the data as opaque. */ - size += sk->enclen; - - pkttype = is_subkey? CDK_PKT_SECRET_SUBKEY : CDK_PKT_SECRET_KEY; - rc = pkt_write_head( out, old_ctb, size, pkttype ); - if( !rc ) - rc = stream_putc( out, pk->version ); - if( !rc ) - rc = write_32( out, pk->timestamp ); - if( !rc && pk->version < 4 ) { - u16 ndays = 0; - if( pk->expiredate ) - ndays = (u16) ((pk->expiredate - pk->timestamp) / 86400L); - rc = write_16( out, ndays ); + else /* We do not know anything about the encrypted mpi's so we + treat the data as opaque. */ + size += sk->enclen; + + pkttype = is_subkey? CDK_PKT_SECRET_SUBKEY : CDK_PKT_SECRET_KEY; + rc = pkt_write_head (out, old_ctb, size, pkttype); + if (!rc) + rc = stream_putc (out, pk->version); + if (!rc) + rc = write_32 (out, pk->timestamp); + if (!rc && pk->version < 4) + { + u16 ndays = 0; + if (pk->expiredate) + ndays = (u16) ((pk->expiredate - pk->timestamp) / 86400L); + rc = write_16 (out, ndays); } - if( !rc ) - rc = stream_putc( out, pk->pubkey_algo ); - if( !rc ) - rc = write_mpibuf( out, pk->mpi, npkey ); - if( sk->is_protected == 0 ) - rc = stream_putc( out, 0x00 ); - else { - if( is_RSA( pk->pubkey_algo ) && pk->version < 4 ) - stream_putc( out, sk->protect.algo ); - else if( sk->protect.s2k ) { - s2k_mode = sk->protect.s2k->mode; - rc = stream_putc( out, sk->protect.sha1chk? 0xFE : 0xFF ); - if( !rc ) - rc = stream_putc( out, sk->protect.algo ); - if( !rc ) - rc = stream_putc( out, sk->protect.s2k->mode ); - if( !rc ) - rc = stream_putc( out, sk->protect.s2k->hash_algo ); - if( !rc && (s2k_mode == 1 || s2k_mode == 3) ) { - rc = stream_write( out, sk->protect.s2k->salt, 8 ); - if( !rc && s2k_mode == 3 ) - rc = stream_putc( out, sk->protect.s2k->count ); + if (!rc) + rc = stream_putc (out, pk->pubkey_algo); + if( !rc ) + rc = write_mpibuf (out, pk->mpi, npkey); + if (sk->is_protected == 0) + rc = stream_putc (out, 0x00); + else + { + if (is_RSA (pk->pubkey_algo) && pk->version < 4) + stream_putc (out, sk->protect.algo); + else if (sk->protect.s2k) + { + s2k_mode = sk->protect.s2k->mode; + rc = stream_putc (out, sk->protect.sha1chk? 0xFE : 0xFF); + if (!rc) + rc = stream_putc (out, sk->protect.algo); + if (!rc) + rc = stream_putc (out, sk->protect.s2k->mode); + if (!rc) + rc = stream_putc( out, sk->protect.s2k->hash_algo); + if (!rc && (s2k_mode == 1 || s2k_mode == 3)) + { + rc = stream_write (out, sk->protect.s2k->salt, 8); + if (!rc && s2k_mode == 3) + rc = stream_putc (out, sk->protect.s2k->count); } } - else - return CDK_Inv_Value; - rc = stream_write( out, sk->protect.iv, sk->protect.ivlen ); + else + return CDK_Inv_Value; + rc = stream_write (out, sk->protect.iv, sk->protect.ivlen); } - if( !rc && sk->is_protected && pk->version == 4 ) { - if( sk->encdata && sk->enclen ) - rc = stream_write( out, sk->encdata, sk->enclen ); + if (!rc && sk->is_protected && pk->version == 4) + { + if (sk->encdata && sk->enclen) + rc = stream_write (out, sk->encdata, sk->enclen); } - else { - if( !rc ) - rc = write_mpibuf( out, sk->mpi, nskey ); - if( !rc ) { - if( !sk->csum ) - sk->csum = _cdk_sk_get_csum( sk ); - rc = write_16( out, sk->csum ); - } + else + { + if (!rc) + rc = write_mpibuf (out, sk->mpi, nskey); + if (!rc) + { + if (!sk->csum) + sk->csum = _cdk_sk_get_csum (sk); + rc = write_16 (out, sk->csum); + } } - return rc; + + return rc; } -static int -write_compressed( cdk_stream_t out, cdk_pkt_compressed_t cd ) +static cdk_error_t +write_compressed (cdk_stream_t out, cdk_pkt_compressed_t cd ) { - int rc; - - if( !out || !cd ) - return CDK_Inv_Value; - - if (DEBUG_PKT) - _cdk_log_debug ("** write compressed packet\n"); + cdk_error_t rc; - rc = pkt_write_head( out, 1, 0, CDK_PKT_COMPRESSED ); - if( !rc ) - rc = stream_putc( out, cd->algorithm ); - return rc; + assert (out); + assert (cd); + + if (DEBUG_PKT) + _cdk_log_debug ("packet: write_compressed\n"); + + /* Use an old (RFC1991) header for this packet. */ + rc = pkt_write_head (out, 1, 0, CDK_PKT_COMPRESSED); + if (!rc) + rc = stream_putc (out, cd->algorithm); + return rc; } @@ -675,15 +707,16 @@ write_literal (cdk_stream_t out, cdk_pkt_literal_t pt, int old_ctb) size_t size; cdk_error_t rc; - if (!out || !pt) - return CDK_Inv_Value; + assert (out); + assert (pt); + /* We consider a packet without a body as an invalid packet. At least one octet must be present. */ if (!pt->len) return CDK_Inv_Packet; if (DEBUG_PKT) - _cdk_log_debug ("** write literal packet\n"); + _cdk_log_debug ("write_literal:\n"); size = 6 + pt->namelen + pt->len; rc = pkt_write_head (out, old_ctb, size, CDK_PKT_LITERAL); @@ -720,14 +753,15 @@ static cdk_error_t write_onepass_sig (cdk_stream_t out, cdk_pkt_onepass_sig_t sig) { cdk_error_t rc; - - if (!out || !sig) - return CDK_Inv_Value; + + assert (out); + assert (sig); + if (sig->version != 3) return CDK_Inv_Packet; if (DEBUG_PKT) - _cdk_log_debug ("** write one pass signature packet\n"); + _cdk_log_debug ("write_onepass_sig:\n"); rc = pkt_write_head (out, 0, 13, CDK_PKT_ONEPASS_SIG); if (!rc) @@ -749,24 +783,36 @@ write_onepass_sig (cdk_stream_t out, cdk_pkt_onepass_sig_t sig) static cdk_error_t -write_user_id (cdk_stream_t out, cdk_pkt_userid_t id, int old_ctb) +write_user_id (cdk_stream_t out, cdk_pkt_userid_t id, int old_ctb, int pkttype) { cdk_error_t rc; - if (!out || !id || !id->name) + if (!out || !id) return CDK_Inv_Value; - if (id->attrib_img) - ; /* FIXME: Implement to store attribute packets. */ + if (pkttype == CDK_PKT_ATTRIBUTE) + { + if (!id->attrib_img) + return CDK_Inv_Value; + rc = pkt_write_head (out, old_ctb, id->attrib_len+6, CDK_PKT_ATTRIBUTE); + if (rc) + return rc; + /* Write subpacket part. */ + stream_putc (out, 255); + write_32 (out, id->attrib_len+1); + stream_putc (out, 1); + rc = stream_write (out, id->attrib_img, id->attrib_len); + } else { + if (!id->name) + return CDK_Inv_Value; rc = pkt_write_head (out, old_ctb, id->len, CDK_PKT_USER_ID); if (!rc) - rc = stream_write( out, id->name, id->len ); - return rc; + rc = stream_write (out, id->name, id->len); } - - return CDK_Not_Implemented; + + return rc; } @@ -829,13 +875,16 @@ cdk_pkt_write (cdk_stream_t out, cdk_packet_t pkt) rc = write_secret_key (out, pkt->pkt.secret_key, 1, pkt->old_ctb); break; case CDK_PKT_USER_ID: - rc = write_user_id (out, pkt->pkt.user_id, pkt->old_ctb); + case CDK_PKT_ATTRIBUTE: + rc = write_user_id (out, pkt->pkt.user_id, pkt->old_ctb, pkt->pkttype); break; default: rc = CDK_Inv_Packet; break; } + if (DEBUG_PKT) + _cdk_log_debug ("write_packet rc=%d pkttype=%d\n", rc, pkt->pkttype); return rc; } @@ -888,5 +937,3 @@ _cdk_pkt_write_fp (FILE *out, cdk_packet_t pkt) cdk_stream_close (so); return rc; } - - |