summaryrefslogtreecommitdiff
path: root/libextra/opencdk
diff options
context:
space:
mode:
authorSimon Josefsson <simon@josefsson.org>2007-05-12 13:18:45 +0000
committerSimon Josefsson <simon@josefsson.org>2007-05-12 13:18:45 +0000
commit6d09e7df5fcf8c48ee5e14cd6779adaeaa3083bd (patch)
tree24198ddf6278b3fca3225349f12dd8126053c927 /libextra/opencdk
parentd208af15de2affa8942be09f2914b09f3b7905a1 (diff)
downloadgnutls-6d09e7df5fcf8c48ee5e14cd6779adaeaa3083bd.tar.gz
Update.
Diffstat (limited to 'libextra/opencdk')
-rw-r--r--libextra/opencdk/armor.c4
-rw-r--r--libextra/opencdk/cipher.c209
-rw-r--r--libextra/opencdk/compress.c296
-rw-r--r--libextra/opencdk/context.h9
-rw-r--r--libextra/opencdk/filters.h64
-rw-r--r--libextra/opencdk/kbnode.c42
-rw-r--r--libextra/opencdk/keydb.c118
-rw-r--r--libextra/opencdk/literal.c159
-rw-r--r--libextra/opencdk/main.c52
-rw-r--r--libextra/opencdk/main.h35
-rw-r--r--libextra/opencdk/misc.c230
-rw-r--r--libextra/opencdk/opencdk.h197
-rw-r--r--libextra/opencdk/pubkey.c19
-rw-r--r--libextra/opencdk/read-packet.c189
-rw-r--r--libextra/opencdk/sig-check.c34
-rw-r--r--libextra/opencdk/stream.c183
-rw-r--r--libextra/opencdk/verify.c4
-rw-r--r--libextra/opencdk/write-packet.c587
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;
}
-
-