summaryrefslogtreecommitdiff
path: root/libextra
diff options
context:
space:
mode:
authorTimo Schulz <twoaday@gnutls.org>2007-04-22 11:48:09 +0000
committerTimo Schulz <twoaday@gnutls.org>2007-04-22 11:48:09 +0000
commiteaa772addd9da595c0ecf79b7b1f470634565d6d (patch)
tree47ea950ead326be75416e7ff4b3fb6f3d5d4e8bc /libextra
parent5bc7dc03b401d1814a8e9b3c7340840bafdf12f6 (diff)
downloadgnutls-eaa772addd9da595c0ecf79b7b1f470634565d6d.tar.gz
replace the old build-in opencdk version with the most
recent cvs version.
Diffstat (limited to 'libextra')
-rw-r--r--libextra/opencdk/Makefile.am11
-rw-r--r--libextra/opencdk/README6
-rw-r--r--libextra/opencdk/armor.c655
-rw-r--r--libextra/opencdk/cipher.c669
-rw-r--r--libextra/opencdk/cipher.h79
-rw-r--r--libextra/opencdk/compress.c162
-rw-r--r--libextra/opencdk/context.h232
-rw-r--r--libextra/opencdk/encrypt.c1020
-rw-r--r--libextra/opencdk/filters.h35
-rw-r--r--libextra/opencdk/kbnode.c659
-rw-r--r--libextra/opencdk/keydb.c2964
-rw-r--r--libextra/opencdk/keygen.c872
-rw-r--r--libextra/opencdk/keylist.c508
-rw-r--r--libextra/opencdk/keyserver.c188
-rw-r--r--libextra/opencdk/main.c742
-rw-r--r--libextra/opencdk/main.h156
-rw-r--r--libextra/opencdk/md.c184
-rw-r--r--libextra/opencdk/md.h40
-rw-r--r--libextra/opencdk/misc.c269
-rw-r--r--libextra/opencdk/new-packet.c843
-rw-r--r--libextra/opencdk/opencdk.h784
-rw-r--r--libextra/opencdk/packet.h39
-rw-r--r--libextra/opencdk/plaintext.c229
-rw-r--r--libextra/opencdk/pubkey.c1633
-rw-r--r--libextra/opencdk/read-packet.c1842
-rw-r--r--libextra/opencdk/seskey.c865
-rw-r--r--libextra/opencdk/sig-check.c652
-rw-r--r--libextra/opencdk/sign.c494
-rw-r--r--libextra/opencdk/stream.c1496
-rw-r--r--libextra/opencdk/stream.h105
-rw-r--r--libextra/opencdk/sym-cipher.c187
-rw-r--r--libextra/opencdk/trustdb.c269
-rw-r--r--libextra/opencdk/types.h13
-rw-r--r--libextra/opencdk/verify.c439
-rw-r--r--libextra/opencdk/write-packet.c990
35 files changed, 8701 insertions, 11630 deletions
diff --git a/libextra/opencdk/Makefile.am b/libextra/opencdk/Makefile.am
index 880926b506..c5dde9be3e 100644
--- a/libextra/opencdk/Makefile.am
+++ b/libextra/opencdk/Makefile.am
@@ -25,11 +25,10 @@ INCLUDES = -I$(top_srcdir)/lib \
noinst_LTLIBRARIES = libminiopencdk.la
-libminiopencdk_la_SOURCES = md.h packet.h opencdk.h context.h main.h \
- cipher.h stream.h types.h filters.h new-packet.c read-packet.c \
- write-packet.c main.c verify.c armor.c sig-check.c sign.c \
- keydb.c keylist.c seskey.c pubkey.c misc.c encrypt.c trustdb.c \
- kbnode.c compress.c plaintext.c cipher.c sym-cipher.c stream.c \
- keyserver.c keygen.c md.c
+libminiopencdk_la_SOURCES = armor.c filters.h main.c seskey.c types.h \
+ cipher.c kbnode.c main.h packet.h dummy.c \
+ sig-check.c verify.c compress.c keydb.c \
+ misc.c pubkey.c stream.c write-packet.c \
+ context.h literal.c new-packet.c read-packet.c stream.h
EXTRA_DIST = README
diff --git a/libextra/opencdk/README b/libextra/opencdk/README
index 16c1379c38..2cf780e04c 100644
--- a/libextra/opencdk/README
+++ b/libextra/opencdk/README
@@ -1,3 +1,5 @@
-This is just a mirror of the files in the opencdk's src/
-directory.
+This is a stripped down mirror of the files in OpenCDK
+src/. To avoid to link proc-packets.c, dummy.c is included.
+In Makefile.am libminiopencdk_la_SOURCES contains the list
+of all needed files.
diff --git a/libextra/opencdk/armor.c b/libextra/opencdk/armor.c
index e267ad1659..48164f2e77 100644
--- a/libextra/opencdk/armor.c
+++ b/libextra/opencdk/armor.c
@@ -1,6 +1,5 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * armor.c - Armor filters
- * Copyright (C) 2001, 2002, 2003 Timo Schulz
+/* armor.c - Armor filters
+ * Copyright (C) 2001, 2002, 2003, 2007 Timo Schulz
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
*
* This file is part of OpenCDK.
@@ -14,18 +13,12 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- *
*
* ChangeLog for basic BASE64 code (base64_encode, base64_decode):
* Original author: Eric S. Raymond (Fetchmail)
* Heavily modified by Brendan Cully <brendan@kublai.com> (Mutt)
* Modify the code for generic use by Timo Schulz <twoaday@freakmail.de>
*/
-/* X-TODO-STATUS: OK */
#ifdef HAVE_CONFIG_H
# include <config.h>
@@ -85,7 +78,7 @@ static u32 crc_table[] = {
0x42FA2F, 0xC4B6D4, 0xC82F22, 0x4E63D9, 0xD11CCE, 0x575035, 0x5BC9C3, 0xDD8538
};
-static const char * armor_begin[] = {
+static const char *armor_begin[] = {
"BEGIN PGP MESSAGE",
"BEGIN PGP PUBLIC KEY BLOCK",
"BEGIN PGP PRIVATE KEY BLOCK",
@@ -93,7 +86,7 @@ static const char * armor_begin[] = {
NULL
};
-static const char * armor_end[] = {
+static const char *armor_end[] = {
"END PGP MESSAGE",
"END PGP PUBLIC KEY BLOCK",
"END PGP PRIVATE KEY BLOCK",
@@ -101,7 +94,7 @@ static const char * armor_end[] = {
NULL
};
-static const char * valid_headers[] = {
+static const char *valid_headers[] = {
"Comment",
"Version",
"MessageID",
@@ -110,7 +103,7 @@ static const char * valid_headers[] = {
NULL
};
-static char b64chars[64] =
+static char b64chars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static int index64[128] = {
@@ -127,139 +120,157 @@ static int index64[128] = {
/* encode a raw binary buffer to a null-terminated base64 strings */
static int
-base64_encode( byte * out, const byte * in, size_t len, size_t olen )
+base64_encode (char *out, const byte *in, size_t len, size_t olen)
{
- if( !out || !in )
- return CDK_Inv_Value;
-
- while( len >= 3 && olen > 10 ) {
- *out++ = b64chars[in[0] >> 2];
- *out++ = b64chars[((in[0] << 4) & 0x30) | (in[1] >> 4)];
- *out++ = b64chars[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
- *out++ = b64chars[in[2] & 0x3f];
- olen -= 4;
- len -= 3;
- in += 3;
+ if (!out || !in)
+ return CDK_Inv_Value;
+
+ while (len >= 3 && olen > 10)
+ {
+ *out++ = b64chars[in[0] >> 2];
+ *out++ = b64chars[((in[0] << 4) & 0x30) | (in[1] >> 4)];
+ *out++ = b64chars[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
+ *out++ = b64chars[in[2] & 0x3f];
+ olen -= 4;
+ len -= 3;
+ in += 3;
}
-
- /* clean up remainder */
- if( len > 0 && olen > 4 ) {
- byte fragment = 0;
- *out++ = b64chars[in[0] >> 2];
- fragment = (in[0] << 4) & 0x30;
- if( len > 1 )
- fragment |= in[1] >> 4;
- *out++ = b64chars[fragment];
- *out++ = (len < 2) ? '=' : b64chars[(in[1] << 2) & 0x3c];
- *out++ = '=';
+
+ /* clean up remainder */
+ if (len > 0 && olen > 4)
+ {
+ byte fragment = 0;
+ *out++ = b64chars[in[0] >> 2];
+ fragment = (in[0] << 4) & 0x30;
+ if (len > 1)
+ fragment |= in[1] >> 4;
+ *out++ = b64chars[fragment];
+ *out++ = (len < 2) ? '=' : b64chars[(in[1] << 2) & 0x3c];
+ *out++ = '=';
}
- *out = '\0';
- return 0;
+ *out = '\0';
+ return 0;
}
/* Convert '\0'-terminated base64 string to raw byte buffer.
Returns length of returned buffer, or -1 on error. */
static int
-base64_decode( char * out, const char * in )
+base64_decode (byte *out, const char *in)
{
- int len = 0;
- byte digit1, digit2, digit3, digit4;
-
- if( !out || !in )
- return -1;
-
- do {
- digit1 = in[0];
- if( digit1 > 127 || b64val (digit1) == BAD )
- return -1;
- digit2 = in[1];
- if( digit2 > 127 || b64val (digit2) == BAD )
- return -1;
- digit3 = in[2];
- if( digit3 > 127 || ((digit3 != '=') && (b64val (digit3) == BAD)) )
- return -1;
- digit4 = in[3];
- if( digit4 > 127 || ((digit4 != '=') && (b64val (digit4) == BAD)) )
- return -1;
- in += 4;
-
- /* digits are already sanity-checked */
- *out++ = (b64val (digit1) << 2) | (b64val (digit2) >> 4);
- len++;
- if( digit3 != '=' ) {
- *out++ = ((b64val (digit2) << 4) & 0xf0) | (b64val (digit3) >> 2);
- len++;
- if( digit4 != '=' ) {
- *out++ = ((b64val (digit3) << 6) & 0xc0) | b64val (digit4);
- len++;
+ size_t len;
+ byte digit1, digit2, digit3, digit4;
+
+ if (!out || !in)
+ return -1;
+
+ len = 0;
+ do
+ {
+ digit1 = in[0];
+ if (digit1 > 127 || b64val (digit1) == BAD)
+ return -1;
+ digit2 = in[1];
+ if( digit2 > 127 || b64val (digit2) == BAD )
+ return -1;
+ digit3 = in[2];
+ if (digit3 > 127 || ((digit3 != '=') && (b64val (digit3) == BAD)))
+ return -1;
+ digit4 = in[3];
+ if (digit4 > 127 || ((digit4 != '=') && (b64val (digit4) == BAD)))
+ return -1;
+ in += 4;
+
+ /* digits are already sanity-checked */
+ *out++ = (b64val (digit1) << 2) | (b64val (digit2) >> 4);
+ len++;
+ if (digit3 != '=')
+ {
+ *out++ = ((b64val (digit2) << 4) & 0xf0) | (b64val (digit3) >> 2);
+ len++;
+ if (digit4 != '=')
+ {
+ *out++ = ((b64val (digit3) << 6) & 0xc0) | b64val (digit4);
+ len++;
}
}
- } while( *in && digit4 != '=' );
- return len;
+ }
+ while (*in && digit4 != '=');
+
+ return len;
}
+/* Return the compression algorithm in @r_zipalgo.
+ If the parameter is not set after execution,
+ the stream is not compressed. */
static int
-is_compressed( cdk_stream_t inp, int *r_zipalgo )
+compress_get_algo (cdk_stream_t inp, int *r_zipalgo)
+
{
- char buf[128], plain[256];
- int nread, check = 0, pkttype;
-
- if( r_zipalgo )
- *r_zipalgo = 0;
- cdk_stream_seek( inp, 0 );
- while( !cdk_stream_eof( inp ) ) {
- nread = _cdk_stream_gets( inp, buf, sizeof buf-1 );
- if( !nread )
- break;
- if( nread == 1 && !cdk_stream_eof( inp )
- && (nread = _cdk_stream_gets( inp, buf, sizeof buf-1)) ) {
- base64_decode( plain, buf );
- if( !(*plain & 0x80) )
- break;
- pkttype = *plain & 0x40 ? (*plain & 0x3f) : ((*plain >> 2) & 0xf);
- if( pkttype == CDK_PKT_COMPRESSED && r_zipalgo ) {
- _cdk_log_debug( "armor compressed (algo=%d)\n", *(plain+1) );
- *r_zipalgo = *(plain + 1);
- }
- break;
- }
+ byte plain[512];
+ char buf[128];
+ int nread, pkttype;
+
+ *r_zipalgo = 0;
+ cdk_stream_seek (inp, 0);
+ while (!cdk_stream_eof (inp))
+ {
+ nread = _cdk_stream_gets (inp, buf, DIM (buf)-1);
+ if (!nread || nread == -1)
+ break;
+ if (nread == 1 && !cdk_stream_eof (inp)
+ && (nread = _cdk_stream_gets (inp, buf, DIM (buf)-1)) > 0)
+ {
+ base64_decode (plain, buf);
+ if (!(*plain & 0x80))
+ break;
+ pkttype = *plain & 0x40 ? (*plain & 0x3f) : ((*plain >> 2) & 0xf);
+ if (pkttype == CDK_PKT_COMPRESSED && r_zipalgo)
+ {
+ _cdk_log_debug ("armor compressed (algo=%d)\n", *(plain+1));
+ *r_zipalgo = *(plain + 1);
+ }
+ break;
+ }
}
- return check;
+ return 0;
}
static int
-check_armor( cdk_stream_t inp, int *r_zipalgo )
+check_armor (cdk_stream_t inp, int *r_zipalgo)
{
- char buf[4096];
- size_t nread;
- int check = 0;
-
- nread = cdk_stream_read( inp, buf, sizeof buf-1 );
- if( nread > 0 ) {
- buf[nread] = '\0';
- if( strstr( buf, "-----BEGIN PGP" ) ) {
- is_compressed( inp, r_zipalgo );
- check = 1;
- }
- cdk_stream_seek( inp, 0 );
+ char buf[4096];
+ size_t nread;
+ int check;
+
+ check = 0;
+ nread = cdk_stream_read (inp, buf, DIM (buf)-1);
+ if (nread > 0)
+ {
+ buf[nread] = '\0';
+ if (strstr (buf, "-----BEGIN PGP"))
+ {
+ compress_get_algo (inp, r_zipalgo);
+ check = 1;
+ }
+ cdk_stream_seek (inp, 0);
}
- return check;
+ return check;
}
static int
-is_armored( int ctb )
+is_armored (int ctb)
{
- int pkttype = 0;
-
- if( !(ctb & 0x80) )
- return 1; /* invalid packet: assume it is armored */
- pkttype = ctb & 0x40 ? (ctb & 0x3f) : ((ctb >> 2) & 0xf);
+ int pkttype = 0;
- switch( pkttype ) {
+ if (!(ctb & 0x80))
+ return 1; /* invalid packet: assume it is armored */
+ pkttype = ctb & 0x40 ? (ctb & 0x3f) : ((ctb >> 2) & 0xf);
+ switch (pkttype)
+ {
case CDK_PKT_MARKER:
case CDK_PKT_SYMKEY_ENC:
case CDK_PKT_ONEPASS_SIG:
@@ -267,32 +278,32 @@ is_armored( int ctb )
case CDK_PKT_SECRET_KEY:
case CDK_PKT_PUBKEY_ENC:
case CDK_PKT_SIGNATURE:
- case CDK_PKT_OLD_COMMENT:
case CDK_PKT_LITERAL:
case CDK_PKT_COMPRESSED:
case CDK_PKT_ENCRYPTED:
- return 0; /* seems to be a regular packet: not armored */
+ return 0; /* seems to be a regular packet: not armored */
}
- return 1;
+ return 1;
}
-static unsigned
-update_crc( unsigned crc, const byte *buf, size_t count )
+static u32
+update_crc (u32 crc, const byte *buf, size_t buflen)
{
- int j;
-
- if( !crc )
- crc = CRCINIT;
- for( j = 0; j < count; j++ )
- crc = (crc << 8) ^ crc_table[0xff & ((crc >> 16) ^ buf[j])];
- crc &= 0xffffff;
- return crc;
+ int j;
+
+ if (!crc)
+ crc = CRCINIT;
+
+ for (j = 0; j < buflen; j++)
+ crc = (crc << 8) ^ crc_table[0xff & ((crc >> 16) ^ buf[j])];
+ crc &= 0xffffff;
+ return crc;
}
-static int
-armor_encode( void * opaque, FILE * in, FILE * out )
+static cdk_error_t
+armor_encode (void *opaque, FILE *in, FILE *out)
{
armor_filter_t * afx = opaque;
struct stat statbuf;
@@ -300,40 +311,38 @@ armor_encode( void * opaque, FILE * in, FILE * out )
byte crcbuf2[3];
size_t nread = 0;
const char * lf;
- int rc = 0;
+ cdk_error_t rc = 0;
if( !afx )
return CDK_Inv_Value;
-
- afx->crc = 0;
if( afx->idx < 0 || afx->idx > DIM (armor_begin)
|| afx->idx2 < 0 || afx->idx2 > DIM (armor_end) )
return CDK_Inv_Value;
- _cdk_log_debug( "armor filter: encode\n" );
+ _cdk_log_debug ("armor filter: encode\n");
- memset( crcbuf, 0, sizeof crcbuf );
+ memset (crcbuf, 0, sizeof (crcbuf));
lf = afx->le ? afx->le : LF;
fprintf( out, "-----%s-----%s", armor_begin[afx->idx], lf );
fprintf( out, "Version: OpenPrivacy "PACKAGE_VERSION"%s", lf );
if( afx->hdrlines)
- fwrite( afx->hdrlines, 1, strlen( afx->hdrlines), out );
+ fwrite( afx->hdrlines, 1, strlen( afx->hdrlines ), out );
fprintf( out, "%s", lf );
if( fstat( fileno( in ), &statbuf ) )
return CDK_General_Error;
while( !feof( in ) ) {
- nread = fread( raw, 1, sizeof raw-1, in );
+ nread = fread( raw, 1, DIM (raw)-1, in );
if( !nread )
break;
if( ferror( in ) ) {
rc = CDK_File_Error;
break;
}
- afx->crc = update_crc( afx->crc, raw, nread );
- base64_encode( buf, raw, nread, sizeof buf-1 );
+ afx->crc = update_crc (afx->crc, (byte*)raw, nread);
+ base64_encode (buf, (byte*)raw, nread, DIM (buf)-1);
fprintf( out, "%s%s", buf, lf );
}
@@ -359,28 +368,30 @@ armor_encode( void * opaque, FILE * in, FILE * out )
*
* Check if the stream contains armored data.
**/
-cdk_error_t
-cdk_armor_filter_use( cdk_stream_t inp )
+int
+cdk_armor_filter_use (cdk_stream_t inp)
{
- int c = 0, check = 0;
- int zipalgo;
-
- c = cdk_stream_getc( inp );
- if( c == EOF )
- return 0; /* EOF, doesn't matter whether armored or not */
- cdk_stream_seek( inp, 0 );
- check = is_armored( c );
- if( check ) {
- check = check_armor( inp, &zipalgo );
- if( zipalgo )
- cdk_stream_control( inp, CDK_STREAMCTL_COMPRESSED, zipalgo );
+ int c, check;
+ int zipalgo;
+
+ zipalgo = 0;
+ c = cdk_stream_getc (inp);
+ if (c == EOF)
+ return 0; /* EOF, doesn't matter whether armored or not */
+ cdk_stream_seek (inp, 0);
+ check = is_armored (c);
+ if (check)
+ {
+ check = check_armor (inp, &zipalgo);
+ if (zipalgo)
+ _cdk_stream_set_compress_algo (inp, zipalgo);
}
- return check;
+ return check;
}
static int
-search_header( const char *buf, const char **array )
+search_header (const char *buf, const char **array)
{
const char *s;
int i;
@@ -402,111 +413,117 @@ _cdk_armor_get_lineend( void )
}
-static int
-armor_decode (void * opaque, FILE *in, FILE *out)
+static cdk_error_t
+armor_decode (void *opaque, FILE *in, FILE *out)
{
- armor_filter_t * afx = opaque;
- const char * s = NULL;
- unsigned char buf[127], crcbuf[4];
- byte raw[128];
- u32 crc2 = 0;
- size_t nread = 0;
- int i, pgp_data = 0;
- int rc = 0;
-
- if( !afx )
- return CDK_Inv_Value;
+ armor_filter_t * afx = opaque;
+ const char *s;
+ char buf[127];
+ byte raw[128], crcbuf[4];
+ u32 crc2 = 0;
+ size_t nread = 0;
+ int i, pgp_data = 0;
+ cdk_error_t rc = 0;
- _cdk_log_debug ("armor filter: decode\n");
+ if (!afx)
+ return CDK_Inv_Value;
- fseek( in, 0, SEEK_SET );
-
- /* Search the begin of the message */
- while( !feof( in ) && !pgp_data ) {
- s = fgets( buf, sizeof buf-1, in );
- if( !s )
- break;
- afx->idx = search_header( buf, armor_begin );
- if( afx->idx >= 0 )
- pgp_data = 1;
- }
-
- if( feof( in ) || !pgp_data ) {
- rc = CDK_Armor_Error; /* no data found */
- goto leave;
+ _cdk_log_debug ("armor filter: decode\n");
+
+ fseek (in, 0, SEEK_SET);
+ /* Search the begin of the message */
+ while (!feof (in) && !pgp_data)
+ {
+ s = fgets (buf, DIM (buf)-1, in);
+ if (!s)
+ break;
+ afx->idx = search_header (buf, armor_begin);
+ if (afx->idx >= 0)
+ pgp_data = 1;
}
-
- /* Parse header until the empty line is reached */
- while( !feof( in ) ) {
- s = fgets( buf, sizeof buf-1, in );
- if( !s )
- goto leave;
- if( strlen( s ) == strlen( LF ) ) {
- rc = 0;
- break; /* empty line */
- }
- /* From RFC2440: OpenPGP should consider improperly formatted Armor
- Headers to be corruption of the ASCII Armor. A colon and a single
- space separate the key and value. */
- if( !strstr( buf, ": " ) ) {
- rc = CDK_Armor_Error;
- goto leave;
+
+ if (feof (in) || !pgp_data)
+ return CDK_Armor_Error; /* no data found */
+
+ /* Parse header until the empty line is reached */
+ while (!feof (in))
+ {
+ s = fgets (buf, DIM (buf)-1, in);
+ if (!s)
+ return CDK_EOF;
+ if (strlen (s) == strlen (LF))
+ {
+ rc = 0;
+ break; /* empty line */
}
- rc = CDK_General_Error;
- for( i = 0; (s = valid_headers[i]); i++ ) {
- if( !strncmp( s, buf, strlen( s ) ) )
- rc = 0;
+ /* From RFC2440: OpenPGP should consider improperly formatted Armor
+ Headers to be corruption of the ASCII Armor. A colon and a single
+ space separate the key and value. */
+ if (!strstr (buf, ": "))
+ return CDK_Armor_Error;
+ rc = CDK_General_Error;
+ for (i = 0; (s = valid_headers[i]); i++)
+ {
+ if (!strncmp (s, buf, strlen (s)))
+ rc = 0;
}
- if( rc ) {
- /* From RFC2440: Unknown keys should be reported to the user,
- but OpenPGP should continue to process the message. */
- _cdk_log_info ("unknown header: `%s'\n", buf);
- rc = 0;
+ if (rc)
+ {
+ /* From RFC2440: Unknown keys should be reported to the user,
+ but OpenPGP should continue to process the message. */
+ _cdk_log_info ("unknown header: `%s'\n", buf);
+ rc = 0;
}
}
- /* Read the data body */
- while( !feof( in ) ) {
- s = fgets( buf, sizeof buf-1, in );
- if( !s )
- break;
- buf[strlen (buf) - strlen (LF)] = '\0';
- if( buf[0] == '=' && strlen( s ) == 5 ) { /* CRC */
- memset( crcbuf, 0, sizeof crcbuf );
- base64_decode( crcbuf, buf + 1 );
- crc2 = crcbuf[0] << 16 | crcbuf[1] << 8 | crcbuf[2];
- break; /* stop here */
+ /* Read the data body */
+ while (!feof (in))
+ {
+ s = fgets (buf, DIM (buf)-1, in);
+ if (!s)
+ break;
+ buf[strlen (buf) - strlen (LF)] = '\0';
+ if (buf[0] == '=' && strlen (s) == 5)
+ { /* CRC */
+ memset (crcbuf, 0, sizeof (crcbuf));
+ base64_decode (crcbuf, buf + 1);
+ crc2 = (crcbuf[0] << 16) | (crcbuf[1] << 8) | crcbuf[2];
+ break; /* stop here */
}
- else {
- nread = base64_decode( raw, buf );
- if( !nread )
- break;
- afx->crc = update_crc( afx->crc, raw, nread );
- fwrite( raw, 1, nread, out );
+ else
+ {
+ nread = base64_decode(raw, buf);
+ if (nread == -1 || nread == 0)
+ break;
+ afx->crc = update_crc (afx->crc, raw, nread);
+ fwrite (raw, 1, nread, out);
}
}
-
- /* Search the tail of the message */
- s = fgets( buf, sizeof buf-1, in );
- if( s ) {
- buf[strlen (buf) - strlen (LF)] = '\0';
- rc = CDK_General_Error;
- afx->idx2 = search_header( buf, armor_end );
- if( afx->idx2 >= 0 )
- rc = 0;
+
+ /* Search the tail of the message */
+ s = fgets (buf, DIM (buf)-1, in);
+ if (s)
+ {
+ buf[strlen (buf) - strlen (LF)] = '\0';
+ rc = CDK_General_Error;
+ afx->idx2 = search_header (buf, armor_end);
+ if (afx->idx2 >= 0)
+ rc = 0;
}
-
- /* this catches error when no tail was found or the header is
- different then the tail line. */
- if( rc || afx->idx != afx->idx2 )
- rc = CDK_Armor_Error;
-
- afx->crc_okay = (afx->crc == crc2) ? 1 : 0;
- if( !afx->crc_okay && !rc )
- rc = CDK_Armor_CRC_Error;
-
- leave:
- return rc;
+
+ /* This catches error when no tail was found or the header is
+ different then the tail line. */
+ if (rc || afx->idx != afx->idx2)
+ rc = CDK_Armor_Error;
+
+ afx->crc_okay = (afx->crc == crc2) ? 1 : 0;
+ if (!afx->crc_okay && !rc)
+ {
+ _cdk_log_debug ("file crc=%08lX afx_crc=%08lX\n", crc2, afx->crc);
+ rc = CDK_Armor_CRC_Error;
+ }
+
+ return rc;
}
@@ -519,39 +536,40 @@ armor_decode (void * opaque, FILE *in, FILE *out)
* Protect a file with ASCII armor.
**/
cdk_error_t
-cdk_file_armor( cdk_ctx_t hd, const char * file, const char * output )
+cdk_file_armor (cdk_ctx_t hd, const char * file, const char * output)
{
- cdk_stream_t inp, out;
- int rc;
-
- rc = _cdk_check_args( hd->opt.overwrite, file, output );
- if( rc )
- return rc;
-
- rc = cdk_stream_open( file, &inp );
- if( rc )
- return rc;
+ cdk_stream_t inp, out;
+ cdk_error_t rc;
+
+ rc = _cdk_check_args (hd->opt.overwrite, file, output);
+ if (rc)
+ return rc;
+
+ rc = cdk_stream_open (file, &inp);
+ if (rc)
+ return rc;
- rc = cdk_stream_new( output, &out );
- if( rc ) {
- cdk_stream_close( inp );
- return rc;
+ rc = cdk_stream_new (output, &out);
+ if (rc)
+ {
+ cdk_stream_close (inp);
+ return rc;
}
-
- cdk_stream_set_armor_flag( out, CDK_ARMOR_MESSAGE );
- if( hd->opt.compress )
- rc = cdk_stream_set_compress_flag( out, hd->compress.algo,
- hd->compress.level );
- if( !rc )
- rc = cdk_stream_set_literal_flag( out, 0, file );
- if( !rc )
- rc = cdk_stream_kick_off( inp, out );
- if( !rc )
- rc = _cdk_stream_get_errno( out );
-
- cdk_stream_close( out );
- cdk_stream_close( inp );
- return rc;
+
+ cdk_stream_set_armor_flag (out, CDK_ARMOR_MESSAGE);
+ if (hd->opt.compress)
+ rc = cdk_stream_set_compress_flag (out, hd->compress.algo,
+ hd->compress.level);
+ if (!rc)
+ rc = cdk_stream_set_literal_flag (out, 0, file);
+ if (!rc)
+ rc = cdk_stream_kick_off (inp, out);
+ if (!rc)
+ rc = _cdk_stream_get_errno (out);
+
+ cdk_stream_close (out);
+ cdk_stream_close (inp);
+ return rc;
}
@@ -584,7 +602,7 @@ cdk_file_dearmor (const char * file, const char * output)
if( cdk_armor_filter_use( inp ) ) {
rc = cdk_stream_set_literal_flag( inp, 0, NULL );
- zipalgo = cdk_stream_control( inp, CDK_STREAMCTL_COMPRESSED, -1 );
+ zipalgo = cdk_stream_is_compressed (inp);
if( zipalgo )
rc = cdk_stream_set_compress_flag( inp, zipalgo, 0 );
if( !rc )
@@ -602,7 +620,7 @@ cdk_file_dearmor (const char * file, const char * output)
int
-_cdk_filter_armor( void * opaque, int ctl, FILE * in, FILE * out )
+_cdk_filter_armor (void *opaque, int ctl, FILE * in, FILE *out)
{
if( ctl == STREAMCTL_READ )
return armor_decode( opaque, in, out );
@@ -619,4 +637,79 @@ _cdk_filter_armor( void * opaque, int ctl, FILE * in, FILE * out )
return CDK_Inv_Mode;
}
-
+
+/**
+ * cdk_armor_encode_buffer:
+ * @inbuf: the raw input buffer
+ * @inlen: raw buffer len
+ * @outbuf: the destination buffer for the base64 output
+ * @outlen: destination buffer len
+ * @nwritten: actual length of the base64 data
+ * @type: the base64 file type.
+ *
+ * Encode the given buffer into base64 format.
+ **/
+cdk_error_t
+cdk_armor_encode_buffer (const byte *inbuf, size_t inlen,
+ char *outbuf, size_t outlen,
+ size_t *nwritten, int type)
+{
+ const char *head, *tail, *le;
+ byte tempbuf[48];
+ char tempout[128];
+ size_t pos, off, len, rest;
+
+ if (type > CDK_ARMOR_SIGNATURE)
+ return CDK_Inv_Mode;
+
+ head = armor_begin [type];
+ tail = armor_end [type];
+ le = _cdk_armor_get_lineend ();
+ pos = strlen (head) + 10 + 2 + 2 + strlen (tail) + 10 + 2 + 5 + 2;
+ /* The output data is 4/3 times larger, plus a line end for each line. */
+ pos += (4*inlen/3) + 2*(4*inlen/3/64);
+
+ if (outbuf && outlen < pos)
+ return CDK_Too_Short;
+
+ /* Only return the size of the output. */
+ if (!outbuf)
+ {
+ *nwritten = pos;
+ return 0;
+ }
+
+ pos = 0;
+ memset (outbuf, 0, outlen);
+ memcpy (outbuf+pos, "-----", 5); pos += 5;
+ memcpy (outbuf+pos, head, strlen (head)); pos += strlen (head);
+ memcpy (outbuf+pos, "-----", 5); pos += 5;
+ memcpy (outbuf+pos, le, strlen (le)); pos += strlen (le);
+ memcpy (outbuf+pos, le, strlen (le)); pos += strlen (le);
+ rest = inlen;
+ for (off = 0; off < inlen;)
+ {
+ if (rest > 48)
+ {
+ memcpy (tempbuf, inbuf+off, 48);
+ off += 48;
+ len = 48;
+ }
+ else
+ {
+ memcpy (tempbuf, inbuf+off, rest);
+ off += rest;
+ len = rest;
+ }
+ rest -= len;
+ base64_encode (tempout, tempbuf, len, DIM (tempout)-1);
+ memcpy (outbuf+pos, tempout, strlen (tempout)); pos += strlen (tempout);
+ memcpy (outbuf+pos, le, strlen (le)); pos += strlen (le);
+ }
+ memcpy (outbuf+pos, "-----", 5); pos += 5;
+ memcpy (outbuf+pos, tail, strlen (tail)); pos += strlen (tail);
+ memcpy (outbuf+pos, "-----", 5); pos += 5;
+ memcpy (outbuf+pos, le, strlen (le)); pos += strlen (le);
+ *nwritten = pos;
+ return 0;
+}
diff --git a/libextra/opencdk/cipher.c b/libextra/opencdk/cipher.c
index 5d18c534c1..90ddce6d84 100644
--- a/libextra/opencdk/cipher.c
+++ b/libextra/opencdk/cipher.c
@@ -1,7 +1,6 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * cipher.c - Cipher filters
- * Copyright (C) 2002, 2003 Timo Schulz
- * Copyright (C) 1998-2001 Free Software Foundation
+/* cipher.c - Cipher filters
+ * Copyright (C) 2002, 2003, 2007 Timo Schulz
+ * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
*
* This file is part of OpenCDK.
*
@@ -14,12 +13,7 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
@@ -30,379 +24,437 @@
#include "opencdk.h"
#include "main.h"
#include "filters.h"
-#include "cipher.h"
-static void (*progress_cb)( void * hd, unsigned off, unsigned len );
-static void * progress_cb_value = NULL;
+/* 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 )
+fp_get_length (FILE *fp)
{
- struct stat statbuf;
+ struct stat statbuf;
- if( fstat( fileno( fp ), &statbuf ) )
- return (off_t)-1;
- return statbuf.st_size;
+ if (fstat( fileno (fp), &statbuf))
+ return (off_t)-1;
+ return statbuf.st_size;
}
-static int
-hash_encode( void * opaque, FILE * in, FILE * out )
+static cdk_error_t
+hash_encode (void *opaque, FILE *in, FILE *out)
{
- md_filter_t * mfx = opaque;
- byte buf[8192];
- int nread;
-
- if( !mfx )
- return CDK_Inv_Value;
-
- _cdk_log_debug( "hash filter: encode (algo=%d)\n", mfx->digest_algo );
-
- if( !mfx->md ) {
- mfx->md = cdk_md_open( mfx->digest_algo, 0 );
- if( !mfx->md )
- return CDK_Inv_Algo;
+ md_filter_t * mfx = opaque;
+ byte buf[BUFSIZE];
+ gcry_error_t err;
+ int nread;
+
+ if (!mfx)
+ return CDK_Inv_Value;
+
+ _cdk_log_debug( "hash filter: encode (algo=%d)\n", mfx->digest_algo );
+
+ if (!mfx->md)
+ {
+ err = gcry_md_open (&mfx->md, mfx->digest_algo, 0);
+ if (err)
+ return map_gcry_error (err);
}
- while( !feof( in ) ) {
- nread = fread( buf, 1, sizeof buf-1, in );
- if( !nread )
- break;
- cdk_md_write( mfx->md, buf, nread );
+ while (!feof (in))
+ {
+ nread = fread (buf, 1, BUFSIZE, in);
+ if (!nread)
+ break;
+ gcry_md_write (mfx->md, buf, nread);
}
-
- wipemem( buf, sizeof buf );
- return 0;
+
+ wipemem (buf, sizeof (buf));
+ return 0;
}
-int
-_cdk_filter_hash( void * opaque, int ctl, FILE * in, FILE * out )
+cdk_error_t
+_cdk_filter_hash (void *opaque, int ctl, FILE *in, FILE *out)
{
- if( ctl == STREAMCTL_READ )
- return hash_encode( opaque, in, out );
- else if( ctl == STREAMCTL_FREE ) {
- md_filter_t * mfx = opaque;
- if( mfx ) {
- _cdk_log_debug( "free hash filter\n" );
- cdk_md_close( mfx->md );
- mfx->md = NULL;
- return 0;
+ if (ctl == STREAMCTL_READ)
+ return hash_encode (opaque, in, out);
+ else if (ctl == STREAMCTL_FREE)
+ {
+ md_filter_t *mfx = opaque;
+ if (mfx)
+ {
+ _cdk_log_debug ("free hash filter\n");
+ gcry_md_close (mfx->md);
+ mfx->md = NULL;
+ return 0;
}
}
return CDK_Inv_Mode;
}
-static int
-write_header( cipher_filter_t * cfx, FILE * out )
+static cdk_error_t
+write_header (cipher_filter_t *cfx, FILE *out)
{
- struct cdk_pkt_encrypted_s ed;
- CDK_PACKET pkt;
- cdk_dek_t dek = cfx->dek;
- byte temp[18];
- size_t blocksize = 0;
- int use_mdc = 0, nprefix;
- int rc = 0;
-
- blocksize = cdk_cipher_get_algo_blklen( dek->algo );
- if( blocksize < 8 || blocksize > 16 )
- return CDK_Inv_Algo;
-
- use_mdc = dek->use_mdc;
- if( blocksize != 8 )
- use_mdc = 1; /* enabled by default for all 128-bit block cipher */
-
- if( use_mdc && cfx->datalen )
- cfx->datalen += 22;
+ cdk_pkt_encrypted_t ed;
+ cdk_packet_t pkt;
+ cdk_dek_t dek = cfx->dek;
+ byte temp[18];
+ size_t blocksize;
+ int use_mdc, nprefix;
+ cdk_error_t rc = 0;
+ gcry_error_t err;
- memset( &ed, 0, sizeof ed );
- if( !cfx->blkmode.on ) {
- ed.len = cfx->datalen;
- ed.extralen = blocksize + 2;
+ blocksize = gcry_cipher_get_algo_blklen( dek->algo );
+ if (blocksize < 8 || blocksize > 16)
+ return CDK_Inv_Algo;
+
+ use_mdc = dek->use_mdc;
+ if (blocksize != 8)
+ use_mdc = 1; /* Enabled by default for all 128-bit block cipher */
+
+ if (use_mdc && cfx->datalen)
+ cfx->datalen += 22;
+
+ cdk_pkt_alloc (&pkt, CDK_PKT_ENCRYPTED_MDC);
+ ed = pkt->pkt.encrypted;
+ if (!cfx->blkmode.on)
+ {
+ ed->len = cfx->datalen;
+ ed->extralen = blocksize + 2;
}
-
- if( use_mdc ) {
- ed.mdc_method = CDK_MD_SHA1;
- cfx->mdc = cdk_md_open( CDK_MD_SHA1, 0 );
- if( !cfx->mdc )
- return CDK_Inv_Algo;
+ else
+ cfx->blkmode.nleft = BUFSIZE;
+
+ if (use_mdc)
+ {
+ ed->mdc_method = GCRY_MD_SHA1;
+ err = gcry_md_open (&cfx->mdc, GCRY_MD_SHA1, 0);
+ if (err)
+ return map_gcry_error (err);
}
-
- cdk_pkt_init( &pkt );
- pkt.old_ctb = cfx->dek->rfc1991 && !cfx->blkmode.on? 1 : 0;
- pkt.pkttype = use_mdc ? CDK_PKT_ENCRYPTED_MDC : CDK_PKT_ENCRYPTED;
- pkt.pkt.encrypted = &ed;
- rc = _cdk_pkt_write_fp( out, &pkt );
- if( rc )
- return rc;
- nprefix = blocksize;
- gcry_randomize( temp, nprefix, GCRY_STRONG_RANDOM );
- temp[nprefix] = temp[nprefix - 2];
- temp[nprefix + 1] = temp[nprefix - 1];
- cfx->hd = cdk_cipher_open( dek->algo, use_mdc==0? 1 : 0,
- dek->key, dek->keylen, NULL, 0 );
- if( !cfx->hd )
- return CDK_Inv_Algo;
- if( cfx->mdc )
- cdk_md_write( cfx->mdc, temp, nprefix + 2 );
- rc = cdk_cipher_encrypt( cfx->hd, temp, temp, nprefix + 2 );
- cdk_cipher_sync( cfx->hd );
- if( !rc )
- fwrite( temp, 1, nprefix+2, out );
+
+ pkt->old_ctb = cfx->dek->rfc1991 && !cfx->blkmode.on? 1 : 0;
+ pkt->pkttype = use_mdc? CDK_PKT_ENCRYPTED_MDC : CDK_PKT_ENCRYPTED;
+ rc = _cdk_pkt_write_fp (out, pkt);
+ cdk_pkt_release (pkt);
+ if (rc)
return rc;
+
+ nprefix = blocksize;
+ gcry_randomize (temp, nprefix, GCRY_STRONG_RANDOM);
+ temp[nprefix] = temp[nprefix - 2];
+ temp[nprefix + 1] = temp[nprefix - 1];
+ err = gcry_cipher_open (&cfx->hd, dek->algo, GCRY_CIPHER_MODE_CFB,
+ use_mdc? 0 : GCRY_CIPHER_ENABLE_SYNC);
+ if (err)
+ return map_gcry_error (err);
+ err = gcry_cipher_setiv (cfx->hd, NULL, 0);
+ if (err)
+ return map_gcry_error (err);
+ err = gcry_cipher_setkey (cfx->hd, dek->key, dek->keylen);
+ if (err)
+ return map_gcry_error (err);
+ if (cfx->mdc)
+ gcry_md_write (cfx->mdc, temp, nprefix + 2);
+ gcry_cipher_encrypt (cfx->hd, temp, nprefix + 2, NULL, 0);
+ gcry_cipher_sync (cfx->hd);
+ fwrite (temp, 1, nprefix+2, out);
+ if (cfx->blkmode.on)
+ {
+ cfx->blkmode.nleft -= (blocksize+2);
+ if (use_mdc)
+ cfx->blkmode.nleft -= (22+1); /* 22 mdc packet, 1 byte version */
+ }
+ return rc;
}
-static int
-write_mdc_packet( FILE * out, cipher_filter_t * cfx )
+static cdk_error_t
+write_mdc_packet (FILE *out, cipher_filter_t *cfx)
{
- byte pktdata[22];
- int dlen = cdk_md_get_algo_dlen( CDK_MD_SHA1 );
- int rc;
+ byte pktdata[22];
+ int dlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
- if( !out || !cfx )
- return CDK_Inv_Value;
+ if (!out || !cfx)
+ return CDK_Inv_Value;
+ if (dlen != 20)
+ return CDK_Inv_Algo;
- if( dlen != 20 )
- return CDK_Inv_Algo;
- /* we must hash the prefix of the MDC packet here */
- pktdata[0] = 0xd3;
- pktdata[1] = 0x14;
- cdk_md_putc( cfx->mdc, pktdata[0] );
- cdk_md_putc( cfx->mdc, pktdata[1] );
- cdk_md_final( cfx->mdc );
- memcpy( pktdata + 2, cdk_md_read( cfx->mdc, CDK_MD_SHA1 ), dlen );
- rc = cdk_cipher_encrypt( cfx->hd, pktdata, pktdata, dlen+2 );
- if( !rc )
- fwrite( pktdata, 1, dlen+2, out );
- wipemem( pktdata, sizeof pktdata );
- return rc;
+ /* We must hash the prefix of the MDC packet here */
+ pktdata[0] = 0xd3;
+ pktdata[1] = 0x14;
+ gcry_md_write (cfx->mdc, pktdata, 2);
+ gcry_md_final (cfx->mdc);
+ memcpy (pktdata + 2, gcry_md_read (cfx->mdc, GCRY_MD_SHA1), dlen);
+ gcry_cipher_encrypt (cfx->hd, pktdata, dlen+2, NULL, 0);
+ fwrite (pktdata, 1, dlen+2, out);
+ wipemem (pktdata, sizeof (pktdata));
+ return 0;
}
-static int
-num2bits( size_t n )
+static __inline__ int
+num2bits (size_t n)
{
- int i;
- if( !n )
- return -1;
- for( i = 0; n > 1; i++ )
- n >>= 1;
- return i;
+ size_t i;
+
+ if (!n)
+ return -1;
+ for (i = 0; n > 1; i++)
+ n >>= 1;
+ return i;
}
-static size_t
-pow2( size_t y )
+static __inline__ size_t
+pow2 (size_t y)
{
- size_t x = 1, i;
- for( i = 0; i < y; i++ )
- x <<= 1;
- return x;
+ size_t x = 1, i;
+ for (i = 0; i < y; i++)
+ x <<= 1;
+ return x;
}
-static int
-write_partial_block( FILE * in, FILE * out, size_t * r_len,
- cipher_filter_t * cfx )
+static cdk_error_t
+write_partial_block (FILE *in, FILE *out, off_t *r_len,
+ cipher_filter_t *cfx )
{
- size_t n, nbytes;
- int nread, rc;
- byte buf[8193];
+ byte buf[BUFSIZE+1];
+ size_t n;
+ int nread;
+ cdk_error_t rc;
if( !out || !cfx )
return CDK_Inv_Value;
- if( *r_len > 512 ) {
- n = num2bits( *r_len );
- nbytes = pow2( n );
- fputc( 0xe0 | n, out );
- (*r_len) -= nbytes;
- }
- else {
- size_t pktlen = nbytes = *r_len;
- if( pktlen < 192 )
- fputc( pktlen, out );
- else if( pktlen < 8384 ) {
- pktlen -= 192;
- fputc( (pktlen/256) + 192, out );
- fputc( pktlen % 256, out );
+ 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 ;
+ }
+ 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;
}
- (*r_len) -= nbytes;
}
- while( nbytes > 0 ) {
- nread = fread( buf, 1, sizeof buf-1, in );
- if( !nread )
- break;
- if( cfx->mdc )
- cdk_md_write( cfx->mdc, buf, nread );
- rc = cdk_cipher_encrypt( cfx->hd, buf, buf, nread );
- if( rc )
- break;
- nbytes -= nread;
+ 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 0;
+ return rc;
}
-static int
+static cdk_error_t
cipher_encode_file( void * opaque, FILE * in, FILE * out )
{
- struct stat statbuf;
- cipher_filter_t * cfx = opaque;
- byte buf[8192];
- size_t len, len2;
- int rc = 0, nread;
-
- if( !cfx || !in || !out )
- return CDK_Inv_Value;
-
- if( fstat( fileno( in ), &statbuf ) )
- return CDK_File_Error;
- len = len2 = statbuf.st_size;
- while( !feof( in ) ) {
- if( cfx->blkmode.on ) {
- rc = write_partial_block( in, out, &len2, cfx );
- if( rc )
- break;
- continue;
+ cipher_filter_t * cfx = opaque;
+ byte buf[BUFSIZE];
+ off_t len, len2;
+ int nread;
+ cdk_error_t rc = 0;
+
+ if (!cfx || !in || !out)
+ return CDK_Inv_Value;
+
+ len = len2 = fp_get_length (in);
+ if (len == (off_t)-1)
+ return CDK_File_Error;
+ while (!feof (in))
+ {
+ if (cfx->blkmode.on)
+ {
+ rc = write_partial_block (in, out, &len2, cfx);
+ if (rc)
+ break;
+ continue;
}
- nread = fread( buf, 1, sizeof buf -1, in );
- if( !nread )
- break;
- if( cfx->mdc )
- cdk_md_write( cfx->mdc, buf, nread );
- rc = cdk_cipher_encrypt( cfx->hd, buf, buf, nread );
- if( rc )
- break;
- if( progress_cb )
- progress_cb( progress_cb_value, ftell( in ), len );
- fwrite( buf, 1, nread, out );
+ nread = fread (buf, 1, DIM (buf), in);
+ if (!nread)
+ break;
+ if (cfx->mdc)
+ gcry_md_write (cfx->mdc, buf, nread);
+ gcry_cipher_encrypt (cfx->hd, buf, nread, NULL, 0);
+ fwrite (buf, 1, nread, out);
}
- wipemem( buf, sizeof buf );
- if( !rc && cfx->mdc )
- rc = write_mdc_packet( out, cfx );
- return rc;
+ wipemem (buf, sizeof (buf));
+ if (!rc)
+ {
+ if (cfx->mdc)
+ rc = write_mdc_packet (out, cfx);
+ }
+ return rc;
}
-static int
-read_header( cipher_filter_t * cfx, FILE * in )
+static cdk_error_t
+read_header (cipher_filter_t * cfx, FILE * in)
{
- cdk_dek_t dek;
- byte temp[32];
- int blocksize, nprefix;
- int i = 0, c = 0, rc = 0;
-
- if( !cfx || !in )
- return CDK_Inv_Value;
-
- dek = cfx->dek;
- blocksize = cdk_cipher_get_algo_blklen( dek->algo );
- if( blocksize < 8 || blocksize > 16 )
- return CDK_Inv_Algo;
+ cdk_dek_t dek;
+ byte temp[32];
+ int blocksize, nprefix;
+ int i, c;
+ gcry_error_t err;
- nprefix = blocksize;
- if( cfx->datalen && cfx->datalen < (nprefix + 2) )
- return CDK_Inv_Value;
- if( cfx->mdc_method ) {
- cfx->mdc = cdk_md_open( cfx->mdc_method, 0 );
- if( !cfx->mdc )
- return CDK_Inv_Algo;
+ if (!cfx || !in)
+ return CDK_Inv_Value;
+
+ dek = cfx->dek;
+ blocksize = gcry_cipher_get_algo_blklen (dek->algo);
+ if (blocksize < 8 || blocksize > 16)
+ return CDK_Inv_Algo;
+
+ nprefix = blocksize;
+ if (cfx->datalen > 0 && cfx->datalen < (nprefix + 2))
+ return CDK_Inv_Value;
+ if (cfx->mdc_method)
+ {
+ err = gcry_md_open (&cfx->mdc, cfx->mdc_method, 0);
+ if (err)
+ return map_gcry_error (err);
}
- cfx->hd = cdk_cipher_open( dek->algo, cfx->mdc_method==0? 1 : 0,
- dek->key, dek->keylen, NULL, 0 );
- if( !cfx->hd )
- return CDK_Inv_Algo;
- for( i = 0; i < (nprefix + 2); i++ ) {
- c = fgetc( in );
- if( c == EOF )
- return CDK_File_Error;
- temp[i] = c;
+ err = gcry_cipher_open (&cfx->hd, dek->algo, GCRY_CIPHER_MODE_CFB,
+ cfx->mdc_method? 0 : GCRY_CIPHER_ENABLE_SYNC);
+ if (err)
+ return map_gcry_error (err);
+ err = gcry_cipher_setiv (cfx->hd, NULL, 0);
+ if (err)
+ return map_gcry_error (err);
+ err = gcry_cipher_setkey (cfx->hd, dek->key, dek->keylen);
+ if (err)
+ return map_gcry_error (err);
+
+ for (i = 0; i < (nprefix + 2); i++ )
+ {
+ c = fgetc (in);
+ if (c == EOF)
+ return CDK_File_Error;
+ temp[i] = c;
}
- rc = cdk_cipher_decrypt( cfx->hd, temp, temp, nprefix + 2 );
- if( rc )
- return rc;
- cdk_cipher_sync( cfx->hd );
- i = nprefix;
- if( temp[i - 2] != temp[i] || temp[i - 1] != temp[i + 1] )
- rc = CDK_Chksum_Error;
- if( cfx->mdc )
- cdk_md_write( cfx->mdc, temp, nprefix + 2 );
- if( cfx->blkmode.on )
- cfx->blkmode.size -= (nprefix + 2);
- return rc;
+ gcry_cipher_decrypt (cfx->hd, temp, nprefix + 2, NULL, 0);
+ gcry_cipher_sync (cfx->hd);
+ i = nprefix;
+ if (temp[i - 2] != temp[i] || temp[i - 1] != temp[i + 1])
+ return CDK_Chksum_Error;
+ 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. */
+ }
+ return 0;
}
-static int
-finalize_mdc( cdk_md_hd_t md, const byte * buf, size_t nread )
+static cdk_error_t
+finalize_mdc (gcry_md_hd_t md, const byte *buf, size_t nread)
{
- byte mdcbuf[20];
- int dlen = cdk_md_get_algo_dlen( CDK_MD_SHA1 );
- int rc = 0;
-
- if( cdk_md_get_algo( md ) != CDK_MD_SHA1 || dlen != 20 )
- return CDK_Inv_Algo;
-
- if( buf[nread - dlen - 2] == 0xd3 && buf[nread - dlen - 1] == 0x14 ) {
- cdk_md_write( md, buf, nread - dlen );
- cdk_md_final( md );
- memcpy( mdcbuf, cdk_md_read( md, 0 ), dlen );
- if( memcmp( mdcbuf, buf + nread - dlen, dlen ) )
- rc = CDK_Bad_MDC;
- return rc;
+ byte mdcbuf[20];
+ int dlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
+ cdk_error_t rc;
+
+ if (dlen != 20)
+ return CDK_Inv_Algo;
+
+ if (buf[nread - dlen - 2] == 0xD3 && buf[nread - dlen - 1] == 0x14)
+ {
+ gcry_md_write (md, buf, nread - dlen);
+ gcry_md_final (md);
+ memcpy (mdcbuf, gcry_md_read (md, GCRY_MD_SHA1), dlen);
+ if (memcmp (mdcbuf, buf + nread - dlen, dlen))
+ rc = CDK_Bad_MDC;
+ else
+ rc = CDK_Success;
+ wipemem (mdcbuf, sizeof (mdcbuf));
+ return rc;
}
- wipemem( mdcbuf, sizeof mdcbuf );
- return CDK_Inv_Packet;
+
+ return CDK_Inv_Packet;
}
-static int
-cipher_decode_file( void * opaque, FILE * in, FILE * out )
+static cdk_error_t
+cipher_decode_file (void *opaque, FILE *in, FILE *out)
{
- cipher_filter_t * cfx = opaque;
- byte buf[8192];
- int rc = 0, nread, nreq;
-
- if( !cfx || !in || !out )
- return CDK_Inv_Value;
+ cipher_filter_t *cfx = opaque;
+ byte buf[BUFSIZE];
+ int nread, nreq;
+ cdk_error_t rc;
- while( !feof( in ) ) {
- _cdk_log_debug( "partial on=%d size=%lu\n",
- cfx->blkmode.on, cfx->blkmode.size );
- nreq = cfx->blkmode.on? cfx->blkmode.size: sizeof buf-1;
- nread = fread( buf, 1, nreq, in );
- if( !nread )
- break;
- rc = cdk_cipher_decrypt( cfx->hd, buf, buf, nread );
- if( rc )
- break;
- if( feof( in ) && cfx->mdc )
- rc = finalize_mdc( cfx->mdc, buf, nread );
- else if( cfx->mdc )
- cdk_md_write( cfx->mdc, buf, nread );
- fwrite( buf, 1, nread, out );
- if( cfx->blkmode.on ) {
- cfx->blkmode.size = _cdk_pkt_read_len( in, &cfx->blkmode.on );
- if( cfx->blkmode.size == (size_t)EOF )
- return CDK_Inv_Packet;
+ if (!cfx || !in || !out)
+ return CDK_Inv_Value;
+
+ while (!feof (in))
+ {
+ _cdk_log_debug ("partial on=%d size=%lu\n",
+ cfx->blkmode.on, cfx->blkmode.size);
+ nreq = cfx->blkmode.on? cfx->blkmode.size : DIM (buf);
+ nread = fread (buf, 1, nreq, in);
+ if (!nread)
+ break;
+ gcry_cipher_decrypt (cfx->hd, buf, nread, NULL, 0);
+ if (feof (in) && cfx->mdc)
+ {
+ rc = finalize_mdc (cfx->mdc, buf, nread);
+ if (rc)
+ {
+ wipemem (buf, sizeof (buf));
+ return rc;
+ }
+ /* We need to correct the size here to avoid the MDC
+ packet will be written to the output. */
+ nread -= 22;
+ }
+ else if (cfx->mdc)
+ gcry_md_write (cfx->mdc, buf, nread);
+ fwrite (buf, 1, nread, out);
+ if (cfx->blkmode.on)
+ {
+ cfx->blkmode.size = _cdk_pkt_read_len (in, &cfx->blkmode.on);
+ if (cfx->blkmode.size == (size_t)EOF)
+ return CDK_Inv_Packet;
}
}
- wipemem( buf, sizeof buf );
- return rc;
+
+ wipemem (buf, sizeof (buf));
+ return 0;
}
-int
+static cdk_error_t
cipher_decode( void * opaque, FILE * in, FILE * out )
{
cipher_filter_t * cfx = opaque;
- int rc;
+ cdk_error_t rc;
_cdk_log_debug( "cipher filter: decode\n" );
@@ -416,28 +468,28 @@ cipher_decode( void * opaque, FILE * in, FILE * out )
}
-int
+static cdk_error_t
cipher_encode( void * opaque, FILE * in, FILE * out )
{
cipher_filter_t * cfx = opaque;
- int rc;
+ cdk_error_t 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 < 8192 && cfx->blkmode.on )
+ cfx->datalen = fp_get_length (in);
+ if (cfx->datalen < BUFSIZE && cfx->blkmode.on)
cfx->blkmode.on = 0;
- rc = write_header( cfx, out );
+ rc = write_header (cfx, out);
if( !rc )
- rc = cipher_encode_file( cfx, in, out );
+ rc = cipher_encode_file (cfx, in, out);
return rc;
}
-int
+cdk_error_t
_cdk_filter_cipher( void * opaque, int ctl, FILE * in, FILE * out )
{
if( ctl == STREAMCTL_READ )
@@ -448,21 +500,12 @@ _cdk_filter_cipher( void * opaque, int ctl, FILE * in, FILE * out )
cipher_filter_t * cfx = opaque;
if( cfx ) {
_cdk_log_debug( "free cipher filter\n" );
- cdk_md_close( cfx->mdc );
+ gcry_md_close( cfx->mdc );
cfx->mdc = NULL;
- cdk_cipher_close( cfx->hd );
+ gcry_cipher_close( cfx->hd );
cfx->hd = NULL;
}
}
return CDK_Inv_Mode;
}
-
-void
-cdk_set_progress_handler( void (*cb)(void * hd, unsigned off, unsigned size),
- void * cb_value )
-{
- progress_cb = cb;
- progress_cb_value = cb_value;
-}
-
diff --git a/libextra/opencdk/cipher.h b/libextra/opencdk/cipher.h
deleted file mode 100644
index c18ff2c3c8..0000000000
--- a/libextra/opencdk/cipher.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * cipher.h
- * Copyright (C) 2003 Timo Schulz
- *
- * This file is part of OpenCDK.
- *
- * OpenCDK is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * OpenCDK is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#ifndef CDK_CIPHER_H
-#define CDK_CIPHER_H
-
-#define MAX_BLOCKSIZE 16
-
-
-typedef int (*cipher_setkey_t) (void *c,
- const unsigned char *key,
- unsigned keylen);
-
-typedef void (*cipher_encrypt_t) (void *c,
- unsigned char *outbuf,
- const unsigned char *inbuf);
-
-typedef void (*cipher_decrypt_t) (void *c,
- unsigned char *outbuf,
- const unsigned char *inbuf);
-
-typedef struct {
- const char *name;
- int id;
- size_t blocksize;
- size_t keylen;
- size_t contextsize;
- cipher_setkey_t setkey;
- cipher_encrypt_t encrypt;
- cipher_decrypt_t decrypt;
-} cipher_spec_t;
-
-extern cipher_spec_t cipher_spec_blowfish;
-extern cipher_spec_t cipher_spec_twofish;
-extern cipher_spec_t cipher_spec_3des;
-extern cipher_spec_t cipher_spec_cast5;
-extern cipher_spec_t cipher_spec_aes;
-extern cipher_spec_t cipher_spec_aes192;
-extern cipher_spec_t cipher_spec_aes256;
-
-
-cdk_cipher_hd_t cdk_cipher_new( int algo, int pgp_sync );
-cdk_cipher_hd_t cdk_cipher_open( int algo, int pgp_sync,
- const byte * key, size_t keylen,
- const byte * ivbuf, size_t ivlen );
-void cdk_cipher_close( cdk_cipher_hd_t hd );
-int cdk_cipher_encrypt( cdk_cipher_hd_t hd,
- byte * outbuf, const byte *inbuf, size_t n );
-int cdk_cipher_decrypt( cdk_cipher_hd_t hd,
- byte * outbuf, const byte *inbuf, size_t n );
-void cdk_cipher_sync( cdk_cipher_hd_t hd );
-int cdk_cipher_setiv( cdk_cipher_hd_t hd, const byte *ivbuf, size_t n );
-int cdk_cipher_setkey( cdk_cipher_hd_t hd, const byte *keybuf, size_t n );
-int cdk_cipher_get_algo_blklen( int algo );
-int cdk_cipher_get_algo_keylen( int algo );
-int cdk_cipher_test_algo( int algo );
-
-#endif /*CDK_CIPHER_H*/
-
-
-
diff --git a/libextra/opencdk/compress.c b/libextra/opencdk/compress.c
index 2b530e2c0e..91d605830c 100644
--- a/libextra/opencdk/compress.c
+++ b/libextra/opencdk/compress.c
@@ -1,7 +1,6 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * compress.c - Compression filters
+/* compress.c - Compression filters
* Copyright (C) 2002, 2003 Timo Schulz
- * Copyright (C) 1998-2002 Free Software Foundation
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation
*
* This file is part of OpenCDK.
*
@@ -14,12 +13,7 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
@@ -35,8 +29,7 @@
#ifdef HAVE_LIBZ
static int
-compress_data( z_stream * zs, int flush,
- byte * inbuf, size_t insize, FILE * out )
+compress_data (z_stream *zs, int flush, byte *inbuf, size_t insize, FILE *out)
{
int nbytes, zrc;
byte buf[4096];
@@ -46,81 +39,64 @@ compress_data( z_stream * zs, int flush,
do {
zs->next_out = buf;
- zs->avail_out = sizeof buf;
+ zs->avail_out = DIM (buf);
- zrc = deflate( zs, flush );
- if( zrc == Z_STREAM_END && flush == Z_FINISH )
+ zrc = deflate (zs, flush);
+ if (zrc == Z_STREAM_END && flush == Z_FINISH)
;
- else if( zrc != Z_OK )
+ else if (zrc != Z_OK)
break;
- nbytes = sizeof( buf ) - zs->avail_out;
- fwrite( buf, 1, nbytes, out );
+ 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;
}
static int
-decompress_data( compress_filter_t * zfx, z_stream * zs,
- FILE * in, size_t * ret_len )
+decompress_data (compress_filter_t *zfx, z_stream *zs,
+ FILE *in, size_t *ret_len)
{
- int nread = 0, nold;
- int rc = 0, zrc = 0;
-
- while( zs->avail_out != 0 ) {
- if( !zs->avail_in ) {
- nread = fread( zfx->inbuf, 1, zfx->inbufsize, in );
+ 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 ) {
+ 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 )
+ if (nold == zs->avail_out)
break;
- if( zrc == Z_STREAM_END ) {
+ if (zrc == Z_STREAM_END) {
rc = EOF; /* eof */
break;
}
}
- if( !nread && feof( in ) )
+ if (!nread && feof (in))
rc = -1;
return rc;
}
-/* in some cases it might be possible that the packet header was not
- readed, so we do it here. but we assume the the algo was already set. */
-static void
-skip_pktheader( FILE * in )
-{
- int ctb, pkttype, pos;
-
- pos = ftell (in);
- ctb = fgetc (in);
- if (ctb & 0x80) {
- pkttype = ctb & 0x40 ? (ctb & 0x3f) : ((ctb >> 2) & 0xf);
- if (pkttype == CDK_PKT_COMPRESSED) {
- fgetc (in);
- return;
- }
- }
- fseek (in, pos, SEEK_SET);
-}
-
-
-static int
-compress_decode( void * opaque, FILE * in, FILE * out )
+static cdk_error_t
+compress_decode (void *opaque, FILE *in, FILE *out)
{
- compress_filter_t * zfx = opaque;
+ compress_filter_t *zfx = opaque;
z_stream * zs;
- int zrc, rc = 0;
size_t nbytes;
+ int zrc;
+ cdk_error_t rc = 0;
_cdk_log_debug ("compress filter: decode (algo=%d)\n", zfx->algo);
@@ -130,7 +106,6 @@ compress_decode( void * opaque, FILE * in, FILE * out )
zs = cdk_calloc (1, sizeof *zs);
if (!zs)
return CDK_Out_Of_Core;
-
if (zfx->algo == CDK_COMPRESS_ZIP)
zrc = inflateInit2 (zs, -13);
else
@@ -141,9 +116,9 @@ compress_decode( void * opaque, FILE * in, FILE * out )
zfx->outbufsize = 8192;
zfx->inbufsize = 2048;
memset (zfx->inbuf, 0, sizeof zfx->inbuf);
- zs->avail_in = 0;
+ zs->avail_in = 0;
- skip_pktheader (in);
+ nbytes = 0;
while (rc != -1) {
zs->next_out = zfx->outbuf;
zs->avail_out = 8192;
@@ -156,51 +131,50 @@ compress_decode( void * opaque, FILE * in, FILE * out )
rc = 0;
return rc;
}
-
-static int
-compress_encode( void * opaque, FILE * in, FILE * out )
+
+static cdk_error_t
+compress_encode(void *opaque, FILE *in, FILE *out)
{
- compress_filter_t * zfx = opaque;
- z_stream * zs;
+ compress_filter_t *zfx = opaque;
+ z_stream *zs;
struct cdk_pkt_compressed_s cd;
- CDK_PACKET pkt;
- clock_t start, end;
- int rc, zrc, nread;
+ struct cdk_packet_s pkt;
+ int zrc, nread;
+ cdk_error_t rc = 0;
_cdk_log_debug ("compress filter: encode\n");
- if( !zfx || !in || !out )
+ if (!zfx || !in || !out)
return CDK_Inv_Value;
- if( !zfx->algo )
+ if (!zfx->algo)
zfx->algo = CDK_COMPRESS_ZIP;
- memset( &cd, 0, sizeof cd );
+ 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 )
+ rc = _cdk_pkt_write_fp (out, &pkt);
+ if (rc)
return rc;
- zs = cdk_calloc( 1, sizeof *zs );
- if( !zs )
+ 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 );
+ 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 );
+ 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 );
+ memset (zfx->outbuf, 0, sizeof zfx->outbuf);
- start = clock ();
while (!feof (in)) {
nread = fread (zfx->outbuf, 1, zfx->outbufsize, in);
if (!nread)
@@ -217,34 +191,34 @@ compress_encode( void * opaque, FILE * in, FILE * out )
if (zrc != Z_STREAM_END)
rc = CDK_Zlib_Error;
}
- end = clock ();
- /*printf ("compress encode: elapsed time %d\n", end - start);*/
deflateEnd (zs);
cdk_free (zs);
return rc;
}
-int
-_cdk_filter_compress( void * opaque, int ctl, FILE * in, FILE * out )
+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 ) {
+ 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" );
+ if (zfx) {
+ _cdk_log_debug ("free compress filter\n");
zfx->level = 0;
zfx->algo = 0;
}
+ return 0;
}
return CDK_Inv_Mode;
}
+
#else
-int
-_cdk_filter_compress( void * opaque, int ctl, FILE * in, FILE * out )
+cdk_error_t
+_cdk_filter_compress (void *opaque, int ctl, FILE *in, FILE *out)
{
return CDK_Not_Implemented;
}
diff --git a/libextra/opencdk/context.h b/libextra/opencdk/context.h
index a78a0eecc8..32b274469b 100644
--- a/libextra/opencdk/context.h
+++ b/libextra/opencdk/context.h
@@ -1,6 +1,5 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * context.h
- * Copyright (C) 2002, 2003 Timo Schulz
+/* context.h
+ * Copyright (C) 2002, 2003, 2007 Timo Schulz
*
* This file is part of OpenCDK.
*
@@ -13,184 +12,153 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
#ifndef CDK_CONTEXT_H
#define CDK_CONTEXT_H
#include "types.h"
struct cdk_listkey_s {
- unsigned init:1;
- cdk_stream_t inp;
- cdk_keydb_hd_t db;
- int type;
- union {
- char * patt;
- cdk_strlist_t fpatt;
- } u;
- cdk_strlist_t t;
-};
-
-struct cdk_sesskey_s {
- gcry_mpi_t a;
-};
-
-struct cdk_verify_result_s {
- int sig_ver;
- int sig_len;
- int sig_status;
- int sig_flags;
- unsigned int keyid[2];
- unsigned int created;
- unsigned int expires;
- int pubkey_algo;
- int digest_algo;
- char * notation;
- unsigned char * sig_data;
+ unsigned init:1;
+ cdk_stream_t inp;
+ cdk_keydb_hd_t db;
+ int type;
+ union {
+ char *patt;
+ cdk_strlist_t fpatt;
+ } u;
+ cdk_strlist_t t;
};
struct cdk_s2k_s {
- int mode;
- unsigned char hash_algo;
- unsigned char salt[8];
- unsigned int count;
+ int mode;
+ byte hash_algo;
+ byte salt[8];
+ u32 count;
};
struct cdk_ctx_s {
- int trust_model;
- int cipher_algo;
+ int cipher_algo;
+ int digest_algo;
+ struct {
+ int algo;
+ int level;
+ } compress;
+ struct {
+ int mode;
int digest_algo;
- struct {
- int algo;
- int level;
- } compress;
- struct {
- int mode;
- int digest_algo;
- int cipher_algo;
- } _s2k;
- struct {
- unsigned armor:1;
- unsigned textmode:1;
- unsigned compress:1;
- unsigned mdc:1;
- unsigned compat:1;
- unsigned rfc1991:1;
- unsigned overwrite;
- unsigned force_digest:1;
- } opt;
- struct {
- _cdk_verify_result_t verify;
- } result;
- struct {
- cdk_pkt_seckey_t sk;
- unsigned on:1;
- } cache;
- cdk_dek_t dek;
- cdk_s2k_t s2k;
- struct {
- cdk_keydb_hd_t sec;
- cdk_keydb_hd_t pub;
- } db;
- void (*callback) (void * opaque, int type, const char * s);
- void * callback_value;
- char *(*passphrase)(void * opaque, const char * prompt);
- void * passphrase_value;
+ } _s2k;
+ struct {
+ unsigned blockmode:1;
+ unsigned armor:1;
+ unsigned textmode:1;
+ unsigned compress:1;
+ unsigned mdc:1;
+ unsigned compat:1;
+ unsigned rfc1991:1;
+ unsigned overwrite;
+ unsigned force_digest:1;
+ } opt;
+ struct {
+ cdk_verify_result_t verify;
+ } result;
+ struct {
+ cdk_pkt_seckey_t sk;
+ unsigned on:1;
+ } cache;
+ cdk_dek_t dek;
+ struct {
+ cdk_keydb_hd_t sec;
+ cdk_keydb_hd_t pub;
+ unsigned int close_db:1;
+ } db;
+ char *(*passphrase_cb) (void *opaque, const char *prompt);
+ void * passphrase_cb_value;
};
struct cdk_prefitem_s {
- unsigned char type;
- unsigned char value;
+ byte type;
+ byte value;
};
struct cdk_desig_revoker_s {
- struct cdk_desig_revoker_s * next;
- unsigned char class;
- unsigned char algid;
- unsigned char fpr[20];
+ struct cdk_desig_revoker_s * next;
+ byte r_class;
+ byte algid;
+ byte fpr[KEY_FPR_LEN];
};
struct cdk_subpkt_s {
- struct cdk_subpkt_s * next;
- unsigned int size;
- unsigned char type;
- unsigned char d[1];
-};
-
-struct cdk_mpi_s {
- unsigned short bits;
- unsigned short bytes;
- unsigned char data[1];
+ struct cdk_subpkt_s * next;
+ u32 size;
+ byte type;
+ byte d[1];
};
struct key_idx_s {
- unsigned int offset;
- unsigned int keyid[2];
- unsigned char fpr[20];
+ off_t offset;
+ u32 keyid[2];
+ byte fpr[KEY_FPR_LEN];
};
-struct cdk_dbsearch_s
-{
- union {
- char * pattern;
- unsigned int keyid[2];
- unsigned char fpr[20];
- } u;
- int type;
+struct cdk_dbsearch_s {
+ union {
+ char *pattern;
+ u32 keyid[2];
+ byte fpr[KEY_FPR_LEN];
+ } u;
+ int type;
};
typedef struct cdk_dbsearch_s *cdk_dbsearch_t;
struct key_table_s {
- struct key_table_s * next;
- unsigned int offset;
- cdk_dbsearch_t desc;
+ struct key_table_s * next;
+ off_t offset;
+ cdk_dbsearch_t desc;
};
struct cdk_keydb_hd_s {
- int type;
- cdk_stream_t buf; /* NULL if the name item is valid */
- cdk_stream_t idx;
- cdk_dbsearch_t dbs;
- char * name;
- char * idx_name;
- struct key_table_s * cache;
- int ncache;
- unsigned int secret:1;
- unsigned int isopen:1;
- unsigned int no_cache:1;
- unsigned int search:1;
+ int type;
+ int buf_ref; /* 1=means it is a reference and shall not be closed. */
+ cdk_stream_t buf;
+ cdk_stream_t idx;
+ cdk_dbsearch_t dbs;
+ char *name;
+ char *idx_name;
+ struct key_table_s *cache;
+ size_t ncache;
+ unsigned int secret:1;
+ unsigned int isopen:1;
+ unsigned int no_cache:1;
+ unsigned int search:1;
};
struct cdk_keylist_s {
- struct cdk_keylist_s * next;
- union {
- cdk_pkt_pubkey_t pk;
- cdk_pkt_seckey_t sk;
- } key;
- int type;
+ struct cdk_keylist_s * next;
+ union {
+ cdk_pkt_pubkey_t pk;
+ cdk_pkt_seckey_t sk;
+ } key;
+ int version;
+ int type;
};
struct cdk_dek_s {
- int algo;
- int keylen;
- int use_mdc;
- unsigned rfc1991:1;
- unsigned char key[32]; /* 256-bit */
+ int algo;
+ int keylen;
+ int use_mdc;
+ unsigned rfc1991:1;
+ byte key[32]; /* 256-bit */
};
struct cdk_strlist_s {
- struct cdk_strlist_s * next;
- char d[1];
+ struct cdk_strlist_s * next;
+ char d[1];
};
#endif /* CDK_CONTEXT_H */
diff --git a/libextra/opencdk/encrypt.c b/libextra/opencdk/encrypt.c
deleted file mode 100644
index 2ad7c294f6..0000000000
--- a/libextra/opencdk/encrypt.c
+++ /dev/null
@@ -1,1020 +0,0 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * encrypt.c
- * Copyright (C) 2006 Free Software Foundation, Inc.
- * Copyright (C) 2002, 2003 Timo Schulz
- *
- * This file is part of OpenCDK.
- *
- * OpenCDK is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * OpenCDK is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include <stdio.h>
-#include <stdarg.h>
-#include <assert.h>
-
-#include "opencdk.h"
-#include "main.h"
-#include "filters.h"
-#include "stream.h"
-#include "packet.h"
-
-
-struct mainproc_ctx_s {
- cdk_dek_t dek;
- cdk_stream_t s;
- cdk_kbnode_t node;
- cdk_stream_t tmpfp;
- struct {
- unsigned present:1;
- unsigned one_pass:1;
- cdk_md_hd_t md;
- int digest_algo;
- int is_expired;
- cdk_pkt_pubkey_t pk;
- unsigned pt_offset;
- } sig;
- unsigned eof_seen:1;
- unsigned key_seen:1;
- char * file; /* for detached signatures */
- const char * output;
-};
-typedef struct mainproc_ctx_s * CTX;
-
-
-static void
-write_marker_packet( cdk_stream_t out )
-{
- byte buf[5];
-
- buf[0] = (0x80 | (10<<2));
- buf[1] = 3;
- buf[2] = 0x50;
- buf[3] = 0x47;
- buf[4] = 0x50;
- cdk_stream_write( out, buf, 5 );
-}
-
-
-static void
-literal_set_rfc1991( cdk_stream_t out )
-{
- literal_filter_t * pfx;
- pfx = _cdk_stream_get_opaque( out, fLITERAL );
- if( pfx )
- pfx->rfc1991 = 1;
-}
-
-
-static int
-sym_stream_encrypt (cdk_ctx_t hd, cdk_stream_t inp, cdk_stream_t out)
-{
- cdk_packet_t pkt = NULL;
- cdk_pkt_symkey_enc_t enc;
- char * pw = NULL;
- int rc = 0;
-
- if( !hd || !inp || !out )
- return CDK_Inv_Value;
-
- pw = _cdk_passphrase_get( hd, "Enter Passphrase: " );
- if( !pw )
- goto fail;
-
- cdk_free( hd->s2k );
- rc = cdk_s2k_new( &hd->s2k, hd->_s2k.mode, hd->_s2k.digest_algo, NULL );
- if( rc )
- goto fail;
-
- cdk_dek_free( hd->dek );
- rc = cdk_dek_from_passphrase( &hd->dek, hd->cipher_algo, hd->s2k, 2, pw );
- if( rc )
- goto fail;
-
- if( hd->opt.rfc1991 ) {
- hd->dek->rfc1991 = 1;
- goto start; /* skip the pkt_symkey_enc packet. */
- }
-
- cdk_stream_set_cache( out, 1 );
- if( hd->opt.compat )
- write_marker_packet( out );
-
- enc = cdk_calloc( 1, sizeof *enc );
- if( !enc ) {
- rc = CDK_Out_Of_Core;
- goto fail;
- }
- pkt = cdk_calloc( 1, sizeof * pkt );
- if( !pkt ) {
- rc = CDK_Out_Of_Core;
- goto fail;
- }
- enc->version = 4;
- enc->cipher_algo = hd->dek->algo;
- enc->s2k = hd->s2k;
- pkt->pkttype = CDK_PKT_SYMKEY_ENC;
- pkt->pkt.symkey_enc = enc;
- rc = cdk_pkt_write( out, pkt );
- cdk_free( enc );
- if( rc )
- goto fail;
- cdk_stream_set_cache( out, 0 );
-
- start:
- if( hd->opt.armor )
- cdk_stream_set_armor_flag( out, 0 );
- cdk_stream_set_cipher_flag( out, hd->dek, hd->opt.mdc );
- if( hd->opt.compress )
- cdk_stream_set_compress_flag( out, hd->compress.algo,
- hd->compress.level );
- cdk_stream_set_literal_flag( out, 0, _cdk_stream_get_fname( inp ) );
- if( hd->opt.rfc1991 )
- literal_set_rfc1991( out );
- rc = cdk_stream_kick_off( inp, out );
-
-fail:
- _cdk_passphrase_free( pw, pw? strlen( pw ) : 0 );
- cdk_free( pkt );
- return rc;
-}
-
-
-static int
-use_rfc1991_format( cdk_ctx_t hd, cdk_keylist_t kl )
-{
- cdk_keylist_t l;
-
- if( hd->opt.rfc1991 )
- return 1;
- for( l = kl; l; l = l->next ) {
- if( l->type == CDK_PKT_PUBLIC_KEY && l->key.pk->version == 3 )
- return 1;
- }
- return 0;
-}
-
-
-static int
-select_cipher_algo( int rfc1991, cdk_keylist_t kl )
-{
- int pgp2 = _cdk_is_idea_available( );
- int def_cipher = pgp2 && rfc1991? CDK_CIPHER_IDEA : CDK_CIPHER_CAST5;
- return rfc1991?def_cipher : cdk_pklist_select_algo( kl, CDK_PREFTYPE_SYM );
-}
-
-
-int
-_cdk_check_args( int overwrite, const char * in, const char * out )
-{
- if( !in || !out )
- return CDK_Inv_Value;
- if( !_cdk_strcmp( in, out ) )
- return CDK_Inv_Mode;
- if( !overwrite && !_cdk_check_file( out ) )
- return CDK_Inv_Mode;
- return 0;
-}
-
-
-/**
- * cdk_stream_encrypt: Encrypt a stream.
- * @hd: Handle
- * @remusr: List of recipients
- * @inp: Input stream handle
- * @out: Output stream handle
- *
- * If remusr is NULL, then symmetric encryption is used. Via the
- * handle the caller can set or unset multiple options.
- */
-cdk_error_t
-cdk_stream_encrypt( cdk_ctx_t hd, cdk_strlist_t remusr,
- cdk_stream_t inp, cdk_stream_t out )
-{
- cdk_keylist_t pkl = NULL;
- int cipher_algo, compress_algo = 0;
- int use_rfc1991 = 0;
- int rc = 0;
-
- if( !hd || !inp || !out )
- return CDK_Inv_Value;
-
- if( !remusr )
- return sym_stream_encrypt( hd, inp, out );
-
- rc = cdk_pklist_build( &pkl, hd->db.pub, remusr, PK_USAGE_ENCR );
- if( rc )
- return rc;
-
- use_rfc1991 = use_rfc1991_format( hd, pkl );
- cipher_algo = select_cipher_algo( use_rfc1991, pkl );
- cdk_dek_free( hd->dek );
- rc = cdk_dek_new( &hd->dek );
- if( !rc )
- rc = cdk_dek_set_cipher( hd->dek, cipher_algo );
- if( !rc )
- rc = cdk_dek_set_key( hd->dek, NULL, 0 );
- if( rc ) {
- cdk_pklist_release( pkl );
- return rc;
- }
- compress_algo = use_rfc1991? CDK_COMPRESS_ZIP: hd->compress.algo;
-
- if( !hd->opt.rfc1991 && !hd->opt.compat )
- cdk_dek_set_mdc_flag( hd->dek, cdk_pklist_use_mdc( pkl ) );
- hd->dek->rfc1991 = use_rfc1991;
-
- cdk_stream_set_cache( out, 1 );
- if( hd->opt.compat && !hd->opt.rfc1991 )
- write_marker_packet( out );
-
- rc = cdk_pklist_encrypt( pkl, hd->dek, out );
- cdk_pklist_release( pkl );
- if( rc )
- return rc;
-
- cdk_stream_set_cache( out, 0 );
-
- if( hd->opt.armor )
- cdk_stream_set_armor_flag( out, 0 );
- cdk_stream_set_cipher_flag( out, hd->dek, 0 );
- if( hd->opt.compress )
- cdk_stream_set_compress_flag( out, compress_algo, hd->compress.level );
- cdk_stream_set_literal_flag( out, 0, _cdk_stream_get_fname( inp ) );
- if( hd->dek->rfc1991 )
- literal_set_rfc1991( out );
-
- return cdk_stream_kick_off( inp, out );
-}
-
-
-/**
- * cdk_file_encrypt: Encrypt a file.
- * @hd: Handle
- * @remusr: List of recipient
- * @file: Input file
- * @output: Output file
- *
- **/
-cdk_error_t
-cdk_file_encrypt (cdk_ctx_t hd, cdk_strlist_t remusr,
- const char * file, const char * output)
-{
- cdk_stream_t inp = NULL, out = NULL;
- int rc;
-
- rc = _cdk_check_args( hd->opt.overwrite, file, output );
- if( !rc )
- rc = cdk_stream_open( file, &inp );
- if( !rc )
- rc = cdk_stream_new( output, &out );
- if( !rc )
- rc = cdk_stream_encrypt( hd, remusr, inp, out );
- cdk_stream_close( inp );
- cdk_stream_close( out );
- return rc;
-}
-
-
-static void
-write_status (cdk_ctx_t hd, int type, const char * fmt, ...)
-{
- va_list arg_ptr;
- char * buf;
- int n;
-
- if (!hd->callback)
- return;
-
- va_start (arg_ptr, fmt);
- n = _cdk_vasprintf (&buf, fmt, arg_ptr);
- buf[n] = '\0';
- hd->callback (hd->callback_value, type, buf);
- _cdk_vasprintf_free (buf);
- va_end (arg_ptr);
-}
-
-
-static int
-is_openpgp_ext (const char * file)
-{
- return (strstr (file, ".asc") || strstr (file, ".sig")
- || strstr (file, ".gpg") || strstr (file, ".pgp")) ? 1 : 0;
-}
-
-
-static int
-hash_data_file( char * file, int digest_algo, cdk_md_hd_t * r_md )
-{
- md_filter_t * mfx;
- cdk_stream_t s;
- int rc;
-
- if( file && is_openpgp_ext( file ) )
- file[strlen( file ) - 4] = '\0';
- else
- return CDK_General_Error;
-
- rc = cdk_stream_open( file, &s );
- if( rc )
- return rc;
-
- cdk_stream_set_hash_flag( s, digest_algo );
- cdk_stream_read( s, NULL, 0 );
- mfx = _cdk_stream_get_opaque( s, fHASH );
- if( mfx && mfx->md )
- *r_md = cdk_md_copy( mfx->md );
- cdk_stream_close( s );
- return 0;
-}
-
-
-static int
-handle_symkey_enc (CTX c, cdk_ctx_t hd, cdk_packet_t pkt)
-{
- cdk_pkt_symkey_enc_t key;
- char * pw = NULL;
- int rc = 0;
-
- assert (pkt->pkttype == CDK_PKT_SYMKEY_ENC);
-
- c->key_seen = 1;
- if (c->dek)
- return 0; /* we already decrypted the session key */
-
- pw = _cdk_passphrase_get( hd, "Enter Passphrase: " );
- if( !pw )
- return CDK_Out_Of_Core;
-
- key = pkt->pkt.symkey_enc;
- rc = cdk_dek_from_passphrase( &c->dek, key->cipher_algo, key->s2k, 0, pw );
- _cdk_passphrase_free( pw, pw? strlen( pw ) : 0 );
- return rc;
-}
-
-
-static int
-get_seckey( cdk_ctx_t hd, cdk_keydb_hd_t db, u32 * keyid,
- cdk_pkt_seckey_t*r_sk )
-{
- int rc;
-
- if( !r_sk )
- return CDK_Inv_Value;
- if( hd->cache.on && hd->cache.sk ) {
- cdk_pkt_seckey_t sk = hd->cache.sk;
- cdk_sk_get_keyid( sk, NULL );
- if( sk->keyid[0] == keyid[0] && sk->keyid[1] == keyid[1] ) {
- *r_sk = sk;
- return 0;
- }
- }
- rc = cdk_keydb_get_sk( db, keyid, r_sk );
- if( hd->cache.on )
- hd->cache.sk = *r_sk;
- return rc;
-}
-
-
-static int
-handle_pubkey_enc( CTX c, cdk_ctx_t hd, cdk_packet_t pkt )
-{
- cdk_pkt_pubkey_enc_t enc;
- cdk_pkt_seckey_t sk = NULL;
- int rc = 0;
-
- assert( pkt->pkttype == CDK_PKT_PUBKEY_ENC );
-
- c->key_seen = 1;
- enc = pkt->pkt.pubkey_enc;
- write_status( hd, CDK_CB_PUBKEY_ENC, "%08lX%08lX %d %d",
- enc->keyid[0], enc->keyid[1], enc->pubkey_algo,
- (enc->mpi[0]->bits+7)/8*8 );
-
- if( c->dek )
- return 0; /* we already decrypted the session key */
-
- /* we checked before that there is at least one secret key so we
- skip this packet and continue without errors */
- if( cdk_keydb_check_sk( hd->db.sec, enc->keyid ) )
- return 0;
- rc = get_seckey( hd, hd->db.sec, enc->keyid, &sk );
- if( !rc )
- rc = cdk_dek_extract( &c->dek, hd, enc, sk );
- if( !hd->cache.on )
- _cdk_free_seckey( sk );
- return rc;
-}
-
-
-static int
-rfc1991_get_sesskey (cdk_dek_t * r_dek, cdk_ctx_t hd)
-{
- cdk_s2k_t s2k;
- char * pw;
- int rc;
-
- if (!r_dek)
- return CDK_Inv_Value;
-
- pw = _cdk_passphrase_get (hd, "Enter Passphrase: ");
- if (!pw)
- return CDK_Out_Of_Core;
- rc = cdk_s2k_new( &s2k, 0, CDK_MD_MD5, NULL );
- if( rc ) {
- _cdk_passphrase_free( pw, pw? strlen( pw ) : 0 );
- return CDK_Out_Of_Core;
- }
- rc = cdk_dek_from_passphrase( r_dek, CDK_CIPHER_IDEA, s2k, 0, pw );
- _cdk_passphrase_free( pw, pw? strlen( pw ) : 0 );
- cdk_free( s2k );
- return rc;
-}
-
-
-static int
-handle_encrypted (CTX c, cdk_ctx_t hd, cdk_packet_t pkt, int use_mdc)
-{
- cdk_pkt_encrypted_t enc;
- int pgp2_compat = _cdk_is_idea_available ();
- int rc = 0, pkttype = pkt->pkttype;
-
- assert (CDK_PKT_IS_ENCRYPTED (pkttype));
-
- if (!c->dek) {
- if (!pgp2_compat)
- return CDK_Error_No_Key;
- else if (!c->key_seen) {
- _cdk_log_debug ("RFC1991 message was detected.\n");
- rc = rfc1991_get_sesskey (&c->dek, hd);
- if (rc)
- return rc;
- }
- else
- return CDK_Error_No_Key;
- }
-
- enc = pkt->pkt.encrypted;
- cdk_stream_set_cipher_flag (enc->buf, c->dek, use_mdc);
- rc = cdk_stream_read (enc->buf, NULL, 0);
- if (!rc)
- c->s = enc->buf;
- else
- rc = _cdk_stream_get_errno (enc->buf);
- return rc;
-}
-
-
-static int
-handle_compressed( CTX c, cdk_packet_t pkt )
-{
- cdk_pkt_compressed_t zip;
- int rc;
-
- assert( pkt->pkttype == CDK_PKT_COMPRESSED );
-
- zip = pkt->pkt.compressed;
- cdk_stream_set_compress_flag( c->s, zip->algorithm, 0 );
- rc = cdk_stream_read( c->s, NULL, 0 );
- if( rc )
- rc = _cdk_stream_get_errno( c->s );
- return rc;
-}
-
-
-static int
-handle_onepass_sig( CTX c, cdk_packet_t pkt )
-{
- int rc = 0;
-
- assert (pkt->pkttype == CDK_PKT_ONEPASS_SIG);
-
- if( c->sig.md )
- return 0; /* already open */
- c->sig.digest_algo = pkt->pkt.onepass_sig->digest_algo;
- if( cdk_md_test_algo( c->sig.digest_algo ) )
- return CDK_Inv_Algo;
- c->sig.md = cdk_md_open( c->sig.digest_algo, 0 );
- if( !c->sig.md )
- rc = CDK_Gcry_Error;
- return rc;
-}
-
-
-static int
-handle_literal( CTX c, cdk_packet_t pkt, cdk_stream_t * ret_out )
-{
- literal_filter_t * pfx;
- cdk_pkt_literal_t pt;
- cdk_stream_t out;
- const char * s;
- int rc = 0;
-
- assert( pkt->pkttype == CDK_PKT_LITERAL );
-
- if( !ret_out )
- return CDK_Inv_Value;
-
- if( !c->tmpfp ) {
- /* fixme: handle _CONSOLE */
- s = c->output? c->output : pkt->pkt.literal->name;
- rc = cdk_stream_create( s, ret_out );
- if( rc )
- return rc;
- }
- else
- *ret_out = c->tmpfp;
- out = *ret_out;
- pt = pkt->pkt.literal;
- cdk_stream_seek( c->s, c->sig.present? c->sig.pt_offset : 0 );
- cdk_stream_set_literal_flag( c->s, 0, NULL );
- if( c->sig.present ) {
- _cdk_log_debug( "enable hash filter (algo=%d)\n", c->sig.digest_algo );
- pfx = _cdk_stream_get_opaque( c->s, fLITERAL );
- if( pfx )
- pfx->md = c->sig.md;
- }
- return cdk_stream_kick_off( c->s, out );
-}
-
-
-static byte *
-mpi_encode( cdk_pkt_signature_t sig )
-{
- cdk_mpi_t a;
- byte * p;
- size_t len, i, nsig = 0, pos = 0;
-
- nsig = cdk_pk_get_nsig( sig->pubkey_algo );
- for( i = 0, len = 0; i < nsig; i++ )
- len += sig->mpi[i]->bytes + 2;
- p = cdk_calloc( 1, len + 1 );
- if( !p )
- return NULL;
- for( i = 0; i < nsig; i++ ) {
- a = sig->mpi[i];
- p[pos++] = a->bits >> 8;
- p[pos++] = a->bits;
- memcpy( p + pos, a->data, a->bytes );
- pos += a->bytes;
- }
- return p;
-}
-
-
-static void
-store_verify_result( cdk_pkt_signature_t sig, _cdk_verify_result_t res )
-{
- res->sig_len = sig->mpi[0]->bits;
- res->sig_ver = sig->version;
- res->keyid[0] = sig->keyid[0];
- res->keyid[1] = sig->keyid[1];
- res->created = sig->timestamp;
- res->pubkey_algo = sig->pubkey_algo;
- res->digest_algo = sig->digest_algo;
- if( sig->flags.expired )
- res->sig_flags |= CDK_FLAG_SIG_EXPIRED;
- res->sig_data = mpi_encode( sig );
-}
-
-
-static int
-handle_signature (cdk_ctx_t hd, CTX c, cdk_packet_t pkt)
-{
- _cdk_verify_result_t res;
- cdk_pkt_signature_t sig;
- u32 keyid[2];
- int rc;
-
- assert( pkt->pkttype == CDK_PKT_SIGNATURE );
-
- if( !c->sig.present )
- return CDK_Inv_Packet;
-
- _cdk_result_verify_free( hd->result.verify );
- res = hd->result.verify = _cdk_result_verify_new( );
- if( !hd->result.verify )
- return CDK_Out_Of_Core;
-
- sig = pkt->pkt.signature;
- if( !c->sig.one_pass && !c->sig.md ) {
- if( cdk_md_test_algo( sig->digest_algo ) )
- return CDK_Inv_Algo;
- rc = hash_data_file( c->file, sig->digest_algo, &c->sig.md );
- if( rc )
- return rc;
- }
-
- cdk_sig_get_keyid( sig, keyid );
- store_verify_result( sig, res );
-
- rc = cdk_keydb_get_pk( hd->db.pub, keyid, &c->sig.pk );
- if( rc ) {
- res->sig_status = CDK_SIGSTAT_NOKEY;
- return rc;
- }
- if( c->sig.pk->is_revoked )
- res->sig_flags |= CDK_FLAG_KEY_REVOKED;
- if( c->sig.pk->has_expired )
- res->sig_flags |= CDK_FLAG_KEY_EXPIRED;
-
- rc = _cdk_sig_check( c->sig.pk, sig, c->sig.md, &c->sig.is_expired );
- res->sig_status = !rc? CDK_SIGSTAT_GOOD : CDK_SIGSTAT_BAD;
- if( !rc )
- _cdk_log_debug("good signature from %08lX%08lX (expired %d)\n",
- keyid[0], keyid[1], c->sig.is_expired );
- return rc;
-}
-
-
-static void
-free_mainproc( CTX c )
-{
- if( !c )
- return;
- cdk_kbnode_release( c->node );
- c->node = NULL;
- if( c->sig.present ) {
- cdk_md_close( c->sig.md );
- c->sig.md = NULL;
- _cdk_free_pubkey( c->sig.pk );
- c->sig.pk = NULL;
- }
- cdk_free (c->file);
- c->file = NULL;
- cdk_free (c->dek);
- c->dek = NULL;
- cdk_free (c);
-}
-
-
-static int
-do_proc_packets( cdk_ctx_t hd, CTX c, cdk_stream_t inp,
- cdk_stream_t * ret_out )
-{
- cdk_packet_t pkt = NULL;
- cdk_kbnode_t n = NULL, node;
- const char * s;
- int rc = 0, npos, with_mdc = 0;
-
- if( !hd || !c )
- return CDK_Inv_Value;
-
- s = _cdk_stream_get_fname (inp);
- c->file = cdk_strdup (s? s : " ");
- if (!c->file) {
- cdk_free (c);
- return CDK_Out_Of_Core;
- }
-
- while (!cdk_stream_eof (inp)) {
- pkt = cdk_calloc (1, sizeof *pkt);
- if (!pkt)
- return CDK_Out_Of_Core;
- rc = cdk_pkt_read (inp, pkt);
- _cdk_log_debug ("type=%d old_ctb=%d len=%d (%d)\n",
- pkt->pkttype, pkt->old_ctb, pkt->pktlen, rc);
- if (rc == CDK_EOF)
- c->eof_seen = 1;
- if (rc)
- break;
-
- n = cdk_kbnode_new (pkt);
- if (!c->node)
- c->node = n;
- else
- _cdk_kbnode_add (c->node, n);
-
- switch (pkt->pkttype) {
- case CDK_PKT_SYMKEY_ENC:
- rc = handle_symkey_enc (c, hd, pkt);
- _cdk_log_debug (" handle_symkey_enc (%d)\n", rc);
- break;
-
- case CDK_PKT_PUBKEY_ENC:
- rc = handle_pubkey_enc (c, hd, pkt);
- _cdk_log_debug (" handle_pubkey_enc (%d)\n", rc);
- break;
-
- case CDK_PKT_ENCRYPTED_MDC:
- case CDK_PKT_ENCRYPTED:
- with_mdc = pkt->pkttype == CDK_PKT_ENCRYPTED_MDC;
- rc = handle_encrypted (c, hd, pkt, with_mdc);
- _cdk_log_debug (" handle_encrypted (%d)\n", rc);
- if (!rc)
- inp = c->s;
- break;
-
- case CDK_PKT_COMPRESSED:
- if (!c->s)
- c->s = inp;
- rc = handle_compressed (c, pkt);
- _cdk_log_debug (" handle_compressed (%d)\n", rc);
- break;
-
- case CDK_PKT_ONEPASS_SIG:
- if (!c->s)
- c->s = inp;
- _cdk_log_debug (" handle_onepass_sig (0)\n");
- c->sig.present = 1;
- c->sig.one_pass = 1;
- c->sig.pt_offset = cdk_stream_tell (c->s);
- break;
-
- case CDK_PKT_LITERAL:
- /* skip rest of the packet */
- if (!c->s)
- c->s = inp;
- if( !_cdk_stream_get_blockmode( c->s ) ) {
- npos = cdk_stream_tell (c->s) + pkt->pkt.literal->len;
- cdk_stream_seek (c->s, npos);
- }
- else
- cdk_stream_seek( c->s, cdk_stream_get_length( c->s ) );
- break;
-
- case CDK_PKT_SIGNATURE:
- if (!c->sig.present)
- c->sig.present = 1;
- break; /* handle it later */
-
- case CDK_PKT_MDC:
- _cdk_log_debug( "MDC packet detected.\n" );
- break;
-
- case CDK_PKT_MARKER:
- _cdk_log_debug( "marker packet detected.\n" );
- break;
-
- default:
- rc = CDK_Inv_Packet;
- break;
- }
- if (rc)
- break;
- }
- if( c->eof_seen == 1 )
- rc = 0;
- for( node = c->node; !rc && node; node = node->next ) {
- pkt = node->pkt;
- switch (pkt->pkttype) {
- case CDK_PKT_ONEPASS_SIG:
- rc = handle_onepass_sig (c, pkt);
- _cdk_log_debug (" _handle_onepass_sig (%d)\n", rc);
- break;
-
- case CDK_PKT_LITERAL:
- rc = handle_literal (c, pkt, ret_out);
- _cdk_log_debug (" _handle_literal (%d)\n", rc);
- break;
-
- case CDK_PKT_SIGNATURE:
- rc = handle_signature (hd, c, pkt);
- _cdk_log_debug (" _handle_signature (%d)\n", rc);
- break;
-
- default:
- _cdk_log_debug ("skip packet type %d\n", pkt->pkttype);
- break;
- }
- if (rc)
- break;
- }
- if( rc == CDK_EOF )
- rc = CDK_Wrong_Seckey;
- return rc;
-}
-
-
-int
-_cdk_proc_packets( cdk_ctx_t hd, cdk_stream_t inp,
- const char * output, cdk_stream_t outstream,
- cdk_md_hd_t md )
-{
- cdk_stream_t out = NULL;
- CTX c;
- int rc;
-
- if( !inp )
- return CDK_Inv_Value;
- if( output && outstream )
- return CDK_Inv_Mode;
-
- c = cdk_calloc( 1, sizeof *c );
- if( !c )
- return CDK_Out_Of_Core;
- if( output )
- c->output = output;
- if( outstream )
- c->tmpfp = outstream;
- if( md )
- c->sig.md = md;
- rc = do_proc_packets( hd, c, inp, &out );
- if( !c->tmpfp )
- cdk_stream_close( out );
- free_mainproc( c );
- return rc;
-}
-
-
-static int
-check_pubkey_enc_list( cdk_stream_t in, cdk_keydb_hd_t hd )
-{
- cdk_packet_t pkt;
- int n = 0, nenc = 0;
-
- if( !in || !hd )
- return CDK_Inv_Value;
-
- if( cdk_armor_filter_use( in ) )
- cdk_stream_set_armor_flag( in, 0 );
- pkt = cdk_calloc( 1, sizeof * pkt );
- cdk_pkt_init( pkt );
- while( !cdk_pkt_read( in, pkt ) ) {
- if( pkt->pkttype != CDK_PKT_PUBKEY_ENC ) {
- if( CDK_PKT_IS_ENCRYPTED( pkt->pkttype ) )
- cdk_free( pkt->pkt.encrypted );
- else
- cdk_pkt_free( pkt );
- break;
- }
- nenc++;
- if( !cdk_keydb_check_sk( hd, pkt->pkt.pubkey_enc->keyid ) )
- n++;
- cdk_pkt_free( pkt );
- cdk_pkt_init( pkt );
- }
- cdk_free( pkt );
- cdk_stream_seek( in, 0 );
- if( !nenc )
- return 0;
- _cdk_log_debug( "found %d secret keys\n", n );
- return n? 0 : CDK_Error_No_Key;
-}
-
-
-/**
- * cdk_file_decrypt - Decrypt a file.
- * @hd: Handle.
- * @file: Name of the file to decrypt.
- * @output: Output filename.
- *
- * When the operation was successfull, hd can contain information about
- * the signature (when present) and more.
- **/
-cdk_error_t
-cdk_file_decrypt( cdk_ctx_t hd, const char * file, const char * output )
-{
- cdk_stream_t inp = NULL;
- int rc = 0;
-
- if( !file )
- return CDK_Inv_Value;
-
- if( file && output )
- rc = _cdk_check_args( hd->opt.overwrite, file, output );
- if( !rc )
- rc = cdk_stream_open( file, &inp );
- if( !rc )
- rc = check_pubkey_enc_list( inp, hd->db.sec );
- if( !rc )
- rc = _cdk_proc_packets( hd, inp, output, NULL, NULL );
-
- cdk_stream_close( inp );
- return rc;
-}
-
-
-cdk_error_t
-cdk_stream_decrypt( cdk_ctx_t hd, cdk_stream_t inp, cdk_stream_t out )
-{
- int rc;
-
- rc = check_pubkey_enc_list( inp, hd->db.sec );
- if( !rc )
- rc = _cdk_proc_packets( hd, inp, NULL, out, NULL );
- return rc;
-}
-
-
-/**
- * cdk_data_transform:
- * @hd: session handle
- * @mode: crypto mode
- * @locusr: local user list (sign mode only)
- * @remusr: remote users 'recipients'
- * @inbuf: input buffer with data
- * @insize: length of data in bytes
- * @outbuf: pointer to the output data (will be allocated)
- * @outsize: size of the new data in bytes
- * @modval: value for the modus (for example sign mode)
- *
- * This function transforms data into the given openpgp mode. It works
- * exactly like the cdk_file_xxx functions with the exception that it can
- * be used with memory and not with streams or files.
- **/
-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,
- byte ** outbuf, size_t * outsize,
- int modval )
-{
- cdk_stream_t inp, out;
- cdk_keydb_hd_t db;
- cdk_kbnode_t knode = NULL;
- int rc, res[4];
-
- if( !hd )
- return CDK_Inv_Value;
- if( !mode )
- return 0;
- if( mode == CDK_CRYPTYPE_SIGN && !locusr )
- return CDK_Inv_Value;
- if( !inbuf || !insize || !outbuf )
- return CDK_Inv_Value;
-
- inp = cdk_stream_tmp_from_mem( inbuf, insize );
- if( !inp )
- return CDK_Out_Of_Core;
- out = cdk_stream_tmp( );
- if( !out ) {
- cdk_stream_close( inp );
- return CDK_Out_Of_Core;
- }
-
- cdk_stream_tmp_set_mode( inp, 0 );
- cdk_stream_tmp_set_mode( out, 1 );
-
- switch( mode ) {
- case CDK_CRYPTYPE_ENCRYPT:
- rc = cdk_stream_encrypt( hd, remusr, inp, out );
- break;
-
- case CDK_CRYPTYPE_DECRYPT:
- rc = cdk_stream_decrypt( hd, inp, out );
- break;
-
- case CDK_CRYPTYPE_SIGN:
- rc = cdk_stream_sign( hd, inp, out, locusr, remusr, 0, modval );
- break;
-
- case CDK_CRYPTYPE_VERIFY:
- rc = cdk_stream_verify( hd, inp, out );
- break;
-
- case CDK_CRYPTYPE_EXPORT:
- if( cdk_handle_control( hd, CDK_CTLF_GET, CDK_CTL_ARMOR ) )
- cdk_stream_set_armor_flag( out, CDK_ARMOR_PUBKEY );
- db = cdk_handle_get_keydb( hd, CDK_DBTYPE_PK_KEYRING );
- rc = cdk_keydb_export( db, out, remusr );
- break;
-
- case CDK_CRYPTYPE_IMPORT:
- if( cdk_armor_filter_use( inp ) )
- cdk_stream_set_armor_flag( inp, 0 );
- rc = cdk_keydb_get_keyblock( inp, &knode );
- if( knode ) {
- db = cdk_handle_get_keydb( hd, CDK_DBTYPE_PK_KEYRING );
- rc = cdk_keydb_import( db, knode, res );
- if( !rc ) {
- *outbuf = NULL; /* FIXME */
- *outsize = 0;
- }
- cdk_kbnode_release( knode );
- }
- break;
-
- default:
- rc = CDK_Inv_Mode;
- break;
- }
-
- cdk_stream_close( inp );
- if( !rc && mode != CDK_CRYPTYPE_VERIFY ) {
- cdk_stream_tmp_set_mode( out, 0 );
- rc = cdk_stream_mmap( out, outbuf, outsize );
- }
- else if( !rc && mode == CDK_CRYPTYPE_VERIFY ) {
- *outbuf = NULL; /* FIXME */
- *outsize = *outbuf? strlen( *outbuf ) : 0;
- }
- cdk_stream_close( out );
- return rc;
-}
-
-
diff --git a/libextra/opencdk/filters.h b/libextra/opencdk/filters.h
index c68982326b..f7c4627ec4 100644
--- a/libextra/opencdk/filters.h
+++ b/libextra/opencdk/filters.h
@@ -1,5 +1,4 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * filters.h - Filter structs
+/* filters.h - Filter structs
* Copyright (C) 2002, 2003 Timo Schulz
*
* This file is part of OpenCDK.
@@ -13,12 +12,7 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
#ifndef CDK_FILTERS_H
#define CDK_FILTERS_H
@@ -29,21 +23,22 @@ enum {
};
typedef struct {
- cdk_cipher_hd_t hd;
- cdk_md_hd_t mdc;
+ gcry_cipher_hd_t hd;
+ gcry_md_hd_t mdc;
int mdc_method;
cdk_dek_t dek;
u32 datalen;
struct {
- int on;
- size_t size;
+ size_t on;
+ off_t size;
+ off_t nleft;
} blkmode;
cdk_stream_t s;
} cipher_filter_t;
typedef struct {
int digest_algo;
- cdk_md_hd_t md;
+ gcry_md_hd_t md;
} md_filter_t;
typedef struct {
@@ -58,10 +53,10 @@ typedef struct {
int mode;
unsigned rfc1991:1;
char * filename;
- cdk_md_hd_t md;
+ gcry_md_hd_t md;
struct {
- int on;
- size_t size;
+ size_t on;
+ off_t size;
} blkmode;
} literal_filter_t;
@@ -83,15 +78,17 @@ typedef struct {
int _cdk_filter_armor( void * opaque, int ctl, FILE * in, FILE * out );
/*-- cipher.c --*/
-int _cdk_filter_hash( void * opaque, int ctl, FILE * in, FILE * out );
-int _cdk_filter_cipher( void * opaque, int ctl, FILE * in, FILE * out );
+cdk_error_t _cdk_filter_hash( void * opaque, int ctl, FILE * in, FILE * out );
+cdk_error_t _cdk_filter_cipher( void * opaque, int ctl,
+ FILE * in, FILE * out );
-/*-- plaintext.c --*/
+/*-- literal.c --*/
int _cdk_filter_literal( void * opaque, int ctl, FILE * in, FILE * out );
int _cdk_filter_text( void * opaque, int ctl, FILE * in, FILE * out );
/*-- compress.c --*/
-int _cdk_filter_compress( void * opaque, int ctl, FILE * in, FILE * out );
+cdk_error_t _cdk_filter_compress( void * opaque, int ctl,
+ FILE * in, FILE * out );
#endif /* CDK_FILTERS_H */
diff --git a/libextra/opencdk/kbnode.c b/libextra/opencdk/kbnode.c
index 758a08a8f9..5d9b13fce1 100644
--- a/libextra/opencdk/kbnode.c
+++ b/libextra/opencdk/kbnode.c
@@ -1,7 +1,6 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * kbnode.c - keyblock node utility functions
- * Copyright (C) 1998, 1999, 2000, 2001, 2006 Free Software Foundation, Inc.
- * Copyright (C) 2002, 2003 Timo Schulz
+/* kbnode.c - keyblock node utility functions
+ * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ * Copyright (C) 2002, 2003, 2007 Timo Schulz
*
* This file is part of OpenCDK.
*
@@ -14,13 +13,7 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-/* X-TODO-STATUS: OK */
-
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
@@ -33,9 +26,6 @@
#include "main.h"
#include "packet.h"
-#define is_deleted_kbnode(a) ((a)->private_flag & 1)
-#define is_cloned_kbnode(a) ((a)->private_flag & 2)
-
/**
* cdk_kbnode_new:
@@ -44,72 +34,73 @@
* Allocate a new key node and add the packet.
**/
cdk_kbnode_t
-cdk_kbnode_new( cdk_packet_t pkt )
+cdk_kbnode_new (cdk_packet_t pkt)
{
- cdk_kbnode_t n;
- n = cdk_calloc( 1, sizeof * n );
- if( !n )
- return NULL;
- n->pkt = pkt;
- return n;
+ cdk_kbnode_t n;
+
+ n = cdk_calloc (1, sizeof *n);
+ if (!n)
+ return NULL;
+ n->pkt = pkt;
+ return n;
}
void
-_cdk_kbnode_clone( cdk_kbnode_t node )
+_cdk_kbnode_clone (cdk_kbnode_t node)
{
- if( node )
- node->private_flag |= 2; /* mark cloned */
+ /* Mark the node as clone which means that the packet
+ will not be freed, just the node itself. */
+ if (node)
+ node->is_cloned = 1;
}
/**
* cdk_kbnode_release:
- * @node: the key node
+ * @n: the key node
*
* Release the memory of the node.
**/
void
-cdk_kbnode_release( cdk_kbnode_t node )
+cdk_kbnode_release (cdk_kbnode_t node)
{
- cdk_kbnode_t n2;
-
- while( node ) {
- n2 = node->next;
- node->pkt->pkttype = 0;
- if( !is_cloned_kbnode( node ) )
- cdk_pkt_release( node->pkt );
- cdk_free( node );
- node = n2;
+ cdk_kbnode_t n2;
+
+ while (node)
+ {
+ n2 = node->next;
+ if (!node->is_cloned)
+ cdk_pkt_release (node->pkt);
+ cdk_free (node);
+ node = n2;
}
}
/**
* cdk_kbnode_delete:
- * @node: the ke keynode.
+ * @node: the key node
*
- * Delete @node.
+ * Mark the given node as deleted.
**/
void
-cdk_kbnode_delete( cdk_kbnode_t node )
+cdk_kbnode_delete (cdk_kbnode_t node)
{
- if( node )
- node->private_flag |= 1;
+ if (node)
+ node->is_deleted = 1;
}
-/****************
- * Append NODE to ROOT. ROOT must exist!
- */
+/* Append NODE to ROOT. ROOT must exist! */
void
-_cdk_kbnode_add( cdk_kbnode_t root, cdk_kbnode_t node )
+_cdk_kbnode_add (cdk_kbnode_t root, cdk_kbnode_t node)
{
- cdk_kbnode_t n1;
-
- for( n1 = root; n1->next; n1 = n1->next )
- ;
- n1->next = node;
+ cdk_kbnode_t n1;
+
+ for (n1 = root; n1->next; n1 = n1->next)
+ ;
+ n1->next = node;
}
@@ -123,23 +114,27 @@ _cdk_kbnode_add( cdk_kbnode_t root, cdk_kbnode_t node )
* type @pkttype (only if @pkttype != 0).
**/
void
-cdk_kbnode_insert( cdk_kbnode_t root, cdk_kbnode_t node, int pkttype )
+cdk_kbnode_insert (cdk_kbnode_t root, cdk_kbnode_t node, int pkttype)
{
- if( !pkttype ) {
- node->next = root->next;
- root->next = node;
+ if (!pkttype)
+ {
+ node->next = root->next;
+ root->next = node;
}
- else {
- cdk_kbnode_t n1;
- for( n1 = root; n1->next; n1 = n1->next )
- if( pkttype != n1->next->pkt->pkttype ) {
- node->next = n1->next;
- n1->next = node;
- return;
- }
- /* no such packet, append */
- node->next = NULL;
- n1->next = node;
+ else
+ {
+ cdk_kbnode_t n1;
+
+ for (n1 = root; n1->next; n1 = n1->next)
+ if (pkttype != n1->next->pkt->pkttype)
+ {
+ node->next = n1->next;
+ n1->next = node;
+ return;
+ }
+ /* No such packet, append */
+ node->next = NULL;
+ n1->next = node;
}
}
@@ -154,15 +149,16 @@ cdk_kbnode_insert( cdk_kbnode_t root, cdk_kbnode_t node, int pkttype )
* with pkttype @pkttype in the list starting with @root of @node.
**/
cdk_kbnode_t
-cdk_kbnode_find_prev( cdk_kbnode_t root, cdk_kbnode_t node, int pkttype )
+cdk_kbnode_find_prev (cdk_kbnode_t root, cdk_kbnode_t node, int pkttype)
{
- cdk_kbnode_t n1;
-
- for( n1 = NULL; root && root != node; root = root->next ) {
- if( !pkttype || root->pkt->pkttype == pkttype )
- n1 = root;
+ cdk_kbnode_t n1;
+
+ for (n1 = NULL; root && root != node; root = root->next)
+ {
+ if (!pkttype || root->pkt->pkttype == pkttype)
+ n1 = root;
}
- return n1;
+ return n1;
}
@@ -179,24 +175,25 @@ cdk_kbnode_find_prev( cdk_kbnode_t root, cdk_kbnode_t node, int pkttype )
* a user-id.
**/
cdk_kbnode_t
-cdk_kbnode_find_next( cdk_kbnode_t node, int pkttype )
+cdk_kbnode_find_next (cdk_kbnode_t node, int pkttype)
{
- for( node = node->next; node; node = node->next ) {
- if( !pkttype )
- return node;
- else if( pkttype == CDK_PKT_USER_ID
- && (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY
- || node->pkt->pkttype == CDK_PKT_SECRET_KEY))
- return NULL;
- else if (pkttype == CDK_PKT_SIGNATURE
- && (node->pkt->pkttype == CDK_PKT_USER_ID
- || node->pkt->pkttype == CDK_PKT_PUBLIC_KEY
- || node->pkt->pkttype == CDK_PKT_SECRET_KEY))
- return NULL;
- else if (node->pkt->pkttype == pkttype)
- return node;
+ for (node = node->next; node; node = node->next)
+ {
+ if (!pkttype)
+ return node;
+ else if (pkttype == CDK_PKT_USER_ID &&
+ (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
+ node->pkt->pkttype == CDK_PKT_SECRET_KEY))
+ return NULL;
+ else if (pkttype == CDK_PKT_SIGNATURE &&
+ (node->pkt->pkttype == CDK_PKT_USER_ID ||
+ node->pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
+ node->pkt->pkttype == CDK_PKT_SECRET_KEY))
+ return NULL;
+ else if (node->pkt->pkttype == pkttype)
+ return node;
}
- return NULL;
+ return NULL;
}
@@ -208,13 +205,14 @@ cdk_kbnode_find_next( cdk_kbnode_t node, int pkttype )
* Try to find the next node with the packettype @pkttype.
**/
cdk_kbnode_t
-cdk_kbnode_find( cdk_kbnode_t node, int pkttype )
+cdk_kbnode_find (cdk_kbnode_t node, int pkttype)
{
- for( ; node; node = node->next ) {
- if( node->pkt->pkttype == pkttype )
- return node;
+ for (; node; node = node->next)
+ {
+ if (node->pkt->pkttype == pkttype)
+ return node;
}
- return NULL;
+ return NULL;
}
@@ -226,14 +224,12 @@ cdk_kbnode_find( cdk_kbnode_t node, int pkttype )
* Same as cdk_kbnode_find but it returns the packet instead of the node.
**/
cdk_packet_t
-cdk_kbnode_find_packet( cdk_kbnode_t node, int pkttype )
+cdk_kbnode_find_packet (cdk_kbnode_t node, int pkttype)
{
- cdk_kbnode_t res;
+ cdk_kbnode_t res;
- res = cdk_kbnode_find( node, pkttype );
- if( res )
- return res->pkt;
- return NULL;
+ res = cdk_kbnode_find (node, pkttype);
+ return res? res->pkt : NULL;
}
@@ -244,110 +240,129 @@ cdk_kbnode_find_packet( cdk_kbnode_t node, int pkttype )
* to start with ROOT).
*/
cdk_kbnode_t
-cdk_kbnode_walk( cdk_kbnode_t root, cdk_kbnode_t * context, int all )
+cdk_kbnode_walk (cdk_kbnode_t root, cdk_kbnode_t * context, int all)
{
- cdk_kbnode_t n;
-
- do {
- if( !*context ) {
- *context = root;
- n = root;
+ cdk_kbnode_t n;
+
+ do
+ {
+ if(! *context )
+ {
+ *context = root;
+ n = root;
}
- else {
- n = (*context)->next;
- *context = n;
+ else
+ {
+ n = (*context)->next;
+ *context = n;
}
}
- while( !all && n && is_deleted_kbnode( n ) );
- return n;
+ while (!all && n && n->is_deleted);
+ return n;
}
-/****************
+/**
+ * cdk_kbnode_commit:
+ * @root: the nodes
+ *
* Commit changes made to the kblist at ROOT. Note that ROOT my change,
* and it is therefore passed by reference.
* The function has the effect of removing all nodes marked as deleted.
- * returns true if any node has been changed
+ * returns true if any node has been changed
*/
int
-cdk_kbnode_commit( cdk_kbnode_t * root )
+cdk_kbnode_commit (cdk_kbnode_t * root)
{
- cdk_kbnode_t n, nl;
- int changed = 0;
-
- for( n = *root, nl = NULL; n; n = nl->next ) {
- if (is_deleted_kbnode (n)) {
- if( n == *root )
- *root = nl = n->next;
- else
- nl->next = n->next;
- if( !is_cloned_kbnode( n ) ) {
- cdk_pkt_release( n->pkt );
- cdk_free( n->pkt );
- }
- cdk_free( n );
- changed = 1;
+ cdk_kbnode_t n, nl;
+ int changed = 0;
+
+ for (n = *root, nl = NULL; n; n = nl->next)
+ {
+ if (n->is_deleted)
+ {
+ if (n == *root)
+ *root = nl = n->next;
+ else
+ nl->next = n->next;
+ if (!n->is_cloned)
+ cdk_pkt_release (n->pkt);
+ cdk_free (n);
+ changed = 1;
}
- else
- nl = n;
+ else
+ nl = n;
}
- return changed;
+ return changed;
}
+/**
+ * cdk_kbnode_remove:
+ * @root: the root node
+ * @node: the node to delete
+ *
+ * Remove a node from the root node.
+ */
void
-cdk_kbnode_remove( cdk_kbnode_t * root, cdk_kbnode_t node )
+cdk_kbnode_remove (cdk_kbnode_t *root, cdk_kbnode_t node)
{
- cdk_kbnode_t n, nl;
-
- for( n = *root, nl = NULL; n; n = nl->next ) {
- if( n == node ) {
- if( n == *root )
- *root = nl = n->next;
- else
- nl->next = n->next;
- if( !is_cloned_kbnode( n ) ) {
- cdk_pkt_release( n->pkt );
- cdk_free( n->pkt);
- }
- cdk_free( n );
+ cdk_kbnode_t n, nl;
+
+ for (n = *root, nl = NULL; n; n = nl->next)
+ {
+ if (n == node)
+ {
+ if (n == *root)
+ *root = nl = n->next;
+ else
+ nl->next = n->next;
+ if (!n->is_cloned)
+ cdk_pkt_release (n->pkt);
+ cdk_free (n);
}
- else
- nl = n;
+ else
+ nl = n;
}
}
-/****************
+
+/**
+ * cdk_cdknode_move:
+ * @root: root node
+ * @node: the node to move
+ * @where: destination place where to move the node.
+ *
* Move NODE behind right after WHERE or to the beginning if WHERE is NULL.
*/
void
cdk_kbnode_move (cdk_kbnode_t * root, cdk_kbnode_t node, cdk_kbnode_t where)
{
- cdk_kbnode_t tmp, prev;
-
- if (!root || !*root || !node)
- return; /* sanity check */
- for (prev = *root; prev && prev->next != node; prev = prev->next)
- ;
- if (!prev)
- return; /* node is not in the list */
-
- if (!where) { /* move node before root */
- if (node == *root) /* move to itself */
- return;
- prev->next = node->next;
- node->next = *root;
- *root = node;
- return;
+ cdk_kbnode_t tmp, prev;
+
+ if (!root || !*root || !node)
+ return;
+ for (prev = *root; prev && prev->next != node; prev = prev->next)
+ ;
+ if (!prev)
+ return; /* Node is not in the list */
+
+ if (!where)
+ { /* Move node before root */
+ if (node == *root)
+ return;
+ prev->next = node->next;
+ node->next = *root;
+ *root = node;
+ return;
}
- /* move it after where */
- if (node == where)
- return;
- tmp = node->next;
- node->next = where->next;
- where->next = node;
- prev->next = tmp;
+ if (node == where) /* Move it after where. */
+ return;
+ tmp = node->next;
+ node->next = where->next;
+ where->next = node;
+ prev->next = tmp;
}
@@ -358,11 +373,11 @@ cdk_kbnode_move (cdk_kbnode_t * root, cdk_kbnode_t node, cdk_kbnode_t where)
* Return the packet which is stored inside the node in @node.
**/
cdk_packet_t
-cdk_kbnode_get_packet( cdk_kbnode_t node )
+cdk_kbnode_get_packet (cdk_kbnode_t node)
{
- if( node )
- return node->pkt;
- return NULL;
+ if (node)
+ return node->pkt;
+ return NULL;
}
@@ -375,27 +390,77 @@ cdk_kbnode_get_packet( cdk_kbnode_t node )
* Try to read a key node from the memory buffer @buf.
**/
cdk_error_t
-cdk_kbnode_read_from_mem( cdk_kbnode_t * ret_node,
- const byte * buf, size_t buflen )
+cdk_kbnode_read_from_mem (cdk_kbnode_t *ret_node,
+ const byte *buf, size_t buflen)
{
- cdk_stream_t inp;
- int rc;
-
- if( !buflen || !ret_node )
- return CDK_Inv_Value;
-
- *ret_node = NULL;
- inp = cdk_stream_tmp_from_mem( buf, buflen );
- if( !inp )
- return CDK_Out_Of_Core;
- rc = cdk_keydb_get_keyblock( inp, ret_node );
- if( rc == CDK_EOF && *ret_node )
- rc = 0;
- cdk_stream_close( inp );
+ cdk_stream_t inp;
+ cdk_error_t rc;
+
+ if (!buflen || !ret_node)
+ return CDK_Inv_Value;
+
+ *ret_node = NULL;
+ rc = cdk_stream_tmp_from_mem (buf, buflen, &inp);
+ if (rc)
return rc;
+ rc = cdk_keydb_get_keyblock (inp, ret_node);
+ cdk_stream_close (inp);
+ return rc;
}
+/**
+ * cdk_kbnode_write_to_mem_alloc:
+ * @node: the key node
+ * @r_buf: buffer to hold the raw data
+ * @r_buflen: buffer length of the allocated raw data.
+ *
+ * The function acts similar to cdk_kbnode_write_to_mem but
+ * it allocates the buffer to avoid the lengthy second run.
+ */
+cdk_error_t
+cdk_kbnode_write_to_mem_alloc (cdk_kbnode_t node,
+ byte **r_buf, size_t *r_buflen)
+{
+ cdk_kbnode_t n;
+ cdk_stream_t s;
+ cdk_error_t rc;
+ size_t len;
+
+ if (!node)
+ return CDK_Inv_Value;
+ rc = cdk_stream_tmp_new (&s);
+ if (rc)
+ return rc;
+
+ 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)
+ continue;
+ rc = cdk_pkt_write (s, n->pkt);
+ if (rc)
+ {
+ cdk_stream_close (s);
+ return rc;
+ }
+ }
+
+ cdk_stream_seek (s, 0);
+ len = cdk_stream_get_length (s);
+ *r_buf = cdk_calloc (1, len);
+ *r_buflen = cdk_stream_read (s, *r_buf, len);
+ cdk_stream_close (s);
+ return rc;
+}
+
+
/**
* cdk_kbnode_write_to_mem:
* @node: the key node
@@ -405,134 +470,66 @@ cdk_kbnode_read_from_mem( cdk_kbnode_t * ret_node,
* Try to write the contents of the key node to the buffer @buf and
* return the length of it in @r_nbytes. If buf is zero, only the
* length of the node is calculated and returned in @r_nbytes.
+ * Whenever it is possible, the cdk_kbnode_write_to_mem_alloc should be used.
**/
cdk_error_t
-cdk_kbnode_write_to_mem( cdk_kbnode_t node, byte * buf, size_t * r_nbytes )
+cdk_kbnode_write_to_mem (cdk_kbnode_t node, byte *buf, size_t *r_nbytes)
{
- cdk_kbnode_t n;
- cdk_stream_t s;
- int rc = 0, len;
-
- if( !node )
- return CDK_Inv_Value;
-
- s = cdk_stream_tmp( );
- if( !s )
- return CDK_Out_Of_Core;
+ cdk_kbnode_t n;
+ cdk_stream_t s;
+ size_t len;
+ cdk_error_t rc;
- for( n = node; n; n = n->next ) {
- 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 )
- continue;
- rc = cdk_pkt_write( s, n->pkt );
- if( rc )
- break;
- }
- if( !rc ) {
- cdk_stream_seek( s, 0 );
- len = cdk_stream_get_length( s );
- if( !buf ) {
- *r_nbytes = len; /* only return the length of the buffer */
- cdk_stream_close( s );
- return CDK_Too_Short;
- }
- if( *r_nbytes < len )
- rc = CDK_Too_Short;
- if( !rc )
- *r_nbytes = cdk_stream_read( s, buf, len );
- }
- cdk_stream_close( s );
+ /* FIXME: Mark the function as deprecated!. */
+ if (!node)
+ return CDK_Inv_Value;
+
+ rc = cdk_stream_tmp_new (&s);
+ if (rc)
return rc;
-}
-
-
-/**
- * cdk_kbnode_get_attr:
- * @node: the key node
- * @pkttype: the packet type which the attribute should be retrieved from
- * @attr: the attribute to retrive
- *
- * Extract a single attribute from the specified packet type. If no
- * packet type is given, it is assumed that the public key is meant.
- * If the attr was found, it is returned as a pointer which can be cast
- * to a proper type.
- **/
-void *
-cdk_kbnode_get_attr( cdk_kbnode_t node, int pkttype, int attr )
-{
- cdk_packet_t pkt;
- cdk_pkt_pubkey_t pk;
- cdk_pkt_userid_t id;
- cdk_pkt_signature_t sig;
-
- if( !node || !attr )
- return NULL;
- if( !pkttype )
- pkttype = CDK_PKT_PUBLIC_KEY;
- pkt = cdk_kbnode_find_packet( node, pkttype );
- if( !pkt )
- return NULL;
- switch( pkttype ) {
- case CDK_PKT_SECRET_KEY:
- case CDK_PKT_PUBLIC_KEY:
- if( pkttype == CDK_PKT_PUBLIC_KEY )
- pk = pkt->pkt.public_key;
- else
- pk = pkt->pkt.secret_key->pk;
- assert( pk );
- switch( attr ) {
- case CDK_ATTR_CREATED: return (long *)pk->timestamp;
- case CDK_ATTR_EXPIRE : return (long *)pk->expiredate;
- case CDK_ATTR_VERSION: return (byte *)pk->version;
- case CDK_ATTR_LEN : return (long *)cdk_pk_get_nbits( pk );
- case CDK_ATTR_KEYID:
- if( !pk->keyid[0] || !pk->keyid[1] )
- cdk_pk_get_keyid( pk, pk->keyid );
- return pk->keyid;
- case CDK_ATTR_FPR:
- if( !pk->fpr[0] )
- cdk_pk_get_fingerprint( pk, pk->fpr );
- return pk->fpr;
- case CDK_ATTR_ALGO_PK: return (byte *)pk->pubkey_algo;
- default: return NULL;
- }
- break;
-
- case CDK_PKT_USER_ID:
- id = pkt->pkt.user_id;
- switch( attr ) {
- case CDK_ATTR_LEN : return (long *)id->len;
- case CDK_ATTR_NAME: return id->name;
- default: return NULL;
- }
- break;
-
- case CDK_PKT_SIGNATURE:
- sig = pkt->pkt.signature;
- switch( attr ) {
- case CDK_ATTR_ALGO_MD: return (byte *)sig->digest_algo;
- case CDK_ATTR_ALGO_PK: return (byte *)sig->pubkey_algo;
- case CDK_ATTR_VERSION: return (byte *)sig->version;
- case CDK_ATTR_KEYID : return (u32 *)cdk_sig_get_keyid( sig, NULL );
- default: return NULL;
- }
- break;
-
- default:
- return NULL;
+
+ 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)
+ continue;
+ rc = cdk_pkt_write (s, n->pkt);
+ if (rc)
+ {
+ cdk_stream_close (s);
+ return rc;
+ }
}
- return NULL;
+
+ cdk_stream_seek (s, 0);
+ len = cdk_stream_get_length (s);
+ if (!buf)
+ {
+ *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)
+ rc = CDK_Too_Short;
+ if (!rc)
+ *r_nbytes = cdk_stream_read (s, buf, len);
+ cdk_stream_close (s);
+ return rc;
}
/**
* cdk_kbnode_hash:
* @node: the key node
- * @md: opaque pointer to the hash context
+ * @hashctx: opaque pointer to the hash context
* @is_v4: OpenPGP signature (yes=1, no=0)
* @pkttype: packet type to hash (if zero use the packet type from the node)
* @flags: flags which depend on the operation
@@ -543,30 +540,42 @@ cdk_kbnode_get_attr( cdk_kbnode_t node, int pkttype, int attr )
* is extracted from it.
**/
cdk_error_t
-cdk_kbnode_hash( cdk_kbnode_t node, cdk_md_hd_t md, int is_v4,
- int pkttype, int flags )
+cdk_kbnode_hash (cdk_kbnode_t node, gcry_md_hd_t md, int is_v4,
+ int pkttype, int flags)
{
- cdk_packet_t pkt;
-
- if( !node || !md )
- return CDK_Inv_Value;
- if( !pkttype )
- pkttype = node->pkt->pkttype;
- pkt = cdk_kbnode_find_packet( node, pkttype );
- if( !pkt )
- return CDK_Inv_Packet;
- switch( pkttype ) {
+ cdk_packet_t pkt;
+
+ if (!node || !md)
+ return CDK_Inv_Value;
+ if (!pkttype)
+ {
+ pkt = cdk_kbnode_get_packet (node);
+ pkttype = pkt->pkttype;
+ }
+ else
+ {
+ pkt = cdk_kbnode_find_packet (node, pkttype);
+ if (!pkt)
+ return CDK_Inv_Packet;
+ }
+
+ switch (pkttype)
+ {
case CDK_PKT_PUBLIC_KEY:
case CDK_PKT_PUBLIC_SUBKEY:
- _cdk_hash_pubkey( pkt->pkt.public_key, md, flags & 1 ); break;
+ _cdk_hash_pubkey (pkt->pkt.public_key, md, flags & 1);
+ break;
+
case CDK_PKT_USER_ID:
- _cdk_hash_userid( pkt->pkt.user_id, is_v4, md ); break;
+ _cdk_hash_userid (pkt->pkt.user_id, is_v4, md);
+ break;
+
case CDK_PKT_SIGNATURE:
- _cdk_hash_sig_data( pkt->pkt.signature, md ); break;
+ _cdk_hash_sig_data (pkt->pkt.signature, md);
+ break;
+
default:
- return CDK_Inv_Mode;
+ return CDK_Inv_Mode;
}
- return 0;
+ return 0;
}
-
-
diff --git a/libextra/opencdk/keydb.c b/libextra/opencdk/keydb.c
index 21da7066d0..1b676040b0 100644
--- a/libextra/opencdk/keydb.c
+++ b/libextra/opencdk/keydb.c
@@ -1,7 +1,5 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * keydb.c - Key database routines
- * Copyright (C) 2006 Free Software Foundation, Inc.
- * Copyright (C) 2002, 2003 Timo Schulz
+/* keydb.c - Key database routines
+ * Copyright (C) 2002, 2003, 2007 Timo Schulz
*
* This file is part of OpenCDK.
*
@@ -14,15 +12,11 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
+#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -36,29 +30,30 @@
#include "stream.h"
-#define KEYID_CMP( a, b ) ((a[0]) == (b[0]) && (a[1]) == (b[1]))
+#define KEYID_CMP(a, b) ((a[0]) == (b[0]) && (a[1]) == (b[1]))
#define KEYDB_CACHE_ENTRIES 8
-typedef struct key_table_s * key_table_t;
-typedef struct key_idx_s * key_idx_t;
+typedef struct key_table_s *key_table_t;
+typedef struct key_idx_s *key_idx_t;
-static void keydb_cache_free( key_table_t cache );
-static int keydb_search_copy( cdk_dbsearch_t * r_dst, cdk_dbsearch_t src );
-static int classify_data( const byte * buf, size_t len );
-void keydb_search_free( cdk_dbsearch_t dbs );
+static void keydb_cache_free (key_table_t cache);
+static int keydb_search_copy (cdk_dbsearch_t *r_dst, cdk_dbsearch_t src);
+static void keydb_search_free (cdk_dbsearch_t dbs);
+static int classify_data (const byte * buf, size_t len);
+static cdk_kbnode_t find_selfsig_node (cdk_kbnode_t key, cdk_pkt_pubkey_t pk);
-static char *
-keydb_idx_mkname( const char * file )
+static char*
+keydb_idx_mkname (const char *file)
{
- char * fname;
+ char *fname;
- fname = cdk_calloc( 1, strlen( file ) + 5 );
- if( !fname )
- return NULL;
- sprintf( fname, "%s.idx", file );
- return fname;
+ fname = cdk_calloc (1, strlen (file) + 4 + 1);
+ if (!fname)
+ return NULL;
+ sprintf (fname, "%s.idx", file);
+ return fname;
}
@@ -68,65 +63,67 @@ keydb_idx_mkname( const char * file )
--------
4 octets offset of the packet
8 octets keyid
- 20 octets fingerprint
+ KEY_FPR_LEN (=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.
*/
-static int
-keydb_idx_build( const char * file )
+static cdk_error_t
+keydb_idx_build (const char *file)
{
- cdk_packet_t pkt;
- cdk_stream_t inp, out = NULL;
- byte buf[8], fpr[20];
- char * fname;
- u32 keyid[2];
- int rc, pos;
-
- if( !file )
- return CDK_Inv_Value;
-
- pkt = cdk_calloc( 1, sizeof * pkt );
- if( !pkt )
- return CDK_Out_Of_Core;
-
- fname = keydb_idx_mkname( file );
- if( !fname ) {
- rc = CDK_Out_Of_Core;
- goto leave;
- }
+ cdk_packet_t pkt;
+ cdk_stream_t inp, out = NULL;
+ byte buf[8], fpr[KEY_FPR_LEN];
+ char *fname;
+ off_t pos;
+ u32 keyid[2];
+ cdk_error_t rc;
- rc = cdk_stream_open( file, &inp );
- if( !rc )
- rc = cdk_stream_create( fname, &out );
- if( rc )
- goto leave;
-
- while( !cdk_stream_eof( inp ) ) {
- pos = cdk_stream_tell( inp );
- rc = cdk_pkt_read( inp, pkt );
- if( rc )
- 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 );
- _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, 20 );
+ if (!file)
+ return CDK_Inv_Value;
+
+ rc = cdk_stream_open (file, &inp);
+ if (rc)
+ return rc;
+
+ fname = keydb_idx_mkname (file);
+ if (!fname)
+ {
+ cdk_stream_close (inp);
+ return CDK_Out_Of_Core;
+ }
+ rc = cdk_stream_create (fname, &out);
+ cdk_free (fname);
+ if (rc)
+ goto leave;
+
+ cdk_pkt_new (&pkt);
+ while (!cdk_stream_eof (inp))
+ {
+ pos = cdk_stream_tell (inp);
+ rc = cdk_pkt_read (inp, pkt);
+ if (rc)
+ 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_pkt_free( pkt );
- cdk_pkt_init( pkt );
+ cdk_pkt_free (pkt);
}
- cdk_stream_close( out );
- leave:
- cdk_stream_close( inp );
- cdk_free( fname );
- cdk_free( pkt );
- return rc;
+
+ leave:
+ cdk_stream_close (out);
+ cdk_stream_close (inp);
+ cdk_pkt_release (pkt);
+ return rc;
}
@@ -137,96 +134,200 @@ keydb_idx_build( const char * file )
* Rebuild the key index files for the given key database.
**/
cdk_error_t
-cdk_keydb_idx_rebuild( cdk_keydb_hd_t hd )
+cdk_keydb_idx_rebuild (cdk_keydb_hd_t hd)
{
- int rc;
-
- if( !hd || !hd->name )
- return CDK_Inv_Value;
- if( hd->secret )
- return 0;
-
- cdk_stream_close( hd->idx );
- if( !hd->idx_name ) {
- hd->idx_name = keydb_idx_mkname( hd->name );
- if( !hd->idx_name )
- return CDK_Out_Of_Core;
+ struct stat stbuf;
+ char *tmp_idx_name;
+ cdk_error_t rc;
+ int err;
+
+ if (!hd || !hd->name)
+ return CDK_Inv_Value;
+ if (hd->secret)
+ return 0;
+
+ tmp_idx_name = keydb_idx_mkname (hd->name);
+ if (!tmp_idx_name)
+ return CDK_Out_Of_Core;
+ err = stat (tmp_idx_name, &stbuf);
+ cdk_free (tmp_idx_name);
+ /* This function expects an existing index which can be rebuild,
+ if no index exists we do not build one and just return. */
+ if (err)
+ return 0;
+
+ cdk_stream_close (hd->idx);
+ hd->idx = NULL;
+ if (!hd->idx_name)
+ {
+ hd->idx_name = keydb_idx_mkname (hd->name);
+ if (!hd->idx_name)
+ return CDK_Out_Of_Core;
}
- rc = keydb_idx_build( hd->name );
- if( !rc )
- rc = cdk_stream_open( hd->idx_name, &hd->idx );
- return rc;
+ rc = keydb_idx_build (hd->name);
+ if (!rc)
+ rc = cdk_stream_open (hd->idx_name, &hd->idx);
+ return rc;
}
static int
-keydb_idx_parse( cdk_stream_t inp, key_idx_t * r_idx )
+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 )
- return CDK_Inv_Value;
-
- idx = cdk_calloc( 1, sizeof * idx );
- if( !idx )
- return CDK_Out_Of_Core;
-
- while( !cdk_stream_eof( inp ) ) {
- i = cdk_stream_read( inp, buf, 4 );
- if( i == CDK_EOF )
- break;
- idx->offset = _cdk_buftou32( buf );
- cdk_stream_read( inp, buf, 4 );
- idx->keyid[0] = _cdk_buftou32( buf );
- cdk_stream_read( inp, buf, 4 );
- idx->keyid[1] = _cdk_buftou32( buf );
- cdk_stream_read( inp, idx->fpr, 20 );
-#if 0
- _cdk_log_debug( "%08lu: keyid=%08lX fpr=", idx->offset,idx->keyid[1] );
- for( i = 0; i < 20; i++ )
- _cdk_log_debug( "%02X", idx->fpr[i] );
- _cdk_log_debug( "\n" );
-#endif
- break;
+ key_idx_t idx;
+ byte buf[4];
+ int i;
+
+ if( !inp || !r_idx )
+ return CDK_Inv_Value;
+
+ idx = cdk_calloc (1, sizeof *idx);
+ if (!idx)
+ return CDK_Out_Of_Core;
+
+ while (!cdk_stream_eof (inp))
+ {
+ i = cdk_stream_read (inp, buf, 4);
+ if (i == CDK_EOF)
+ break;
+ idx->offset = _cdk_buftou32 (buf);
+ cdk_stream_read (inp, buf, 4);
+ idx->keyid[0] = _cdk_buftou32 (buf);
+ cdk_stream_read (inp, buf, 4);
+ idx->keyid[1] = _cdk_buftou32 (buf);
+ cdk_stream_read (inp, idx->fpr, KEY_FPR_LEN);
+ break;
}
- *r_idx = idx;
- return cdk_stream_eof( inp )? CDK_EOF : 0;
+ *r_idx = idx;
+ return cdk_stream_eof (inp)? CDK_EOF : 0;
}
static int
-keydb_idx_search( cdk_stream_t inp, u32 * keyid,
- const byte * fpr, u32 * r_off )
+keydb_idx_search (cdk_stream_t inp, u32 *keyid,
+ const byte *fpr, off_t *r_off)
{
- key_idx_t idx;
-
- if( !inp || !r_off )
- return CDK_Inv_Value;
- if( (keyid && fpr) || (!keyid && !fpr) )
- return CDK_Inv_Mode;
-
- *r_off = 0xFFFFFFFF;
- cdk_stream_seek( inp, 0 );
- while( keydb_idx_parse( inp, &idx ) != CDK_EOF ) {
- if( keyid && KEYID_CMP( keyid, idx->keyid ) ) {
- *r_off = idx->offset;
- break;
- }
- else if( fpr && !memcmp( idx->fpr, fpr, 20 ) ) {
- *r_off = idx->offset;
- break;
+ key_idx_t idx;
+
+ if (!inp || !r_off)
+ return CDK_Inv_Value;
+ if ((keyid && fpr) || (!keyid && !fpr))
+ return CDK_Inv_Mode;
+
+ *r_off = 0xFFFFFFFF;
+ cdk_stream_seek (inp, 0);
+ while (keydb_idx_parse (inp, &idx) != CDK_EOF)
+ {
+ if (keyid && KEYID_CMP (keyid, idx->keyid))
+ {
+ *r_off = idx->offset;
+ break;
+ }
+ else if (fpr && !memcmp (idx->fpr, fpr, KEY_FPR_LEN))
+ {
+ *r_off = idx->offset;
+ break;
}
- cdk_free( idx );
- idx = NULL;
+ cdk_free (idx);
+ idx = NULL;
+ }
+ cdk_free (idx);
+ return *r_off != 0xFFFFFFFF? 0 : CDK_EOF;
+}
+
+
+/**
+ * cdk_keydb_new_from_mem:
+ * @r_hd: The keydb output handle.
+ * @data: The raw key data.
+ * @datlen: The length of the raw data.
+ *
+ * Create a new keyring db handle from the contents of a buffer.
+ */
+cdk_error_t
+cdk_keydb_new_from_mem (cdk_keydb_hd_t *r_hd, int secret,
+ const void *data, size_t datlen)
+{
+ cdk_keydb_hd_t hd;
+ cdk_error_t rc;
+
+ if (!r_hd)
+ return CDK_Inv_Value;
+ *r_hd = NULL;
+ hd = calloc (1, sizeof *hd);
+ rc = cdk_stream_tmp_from_mem (data, datlen, &hd->buf);
+ if (!hd->buf)
+ {
+ cdk_free (hd);
+ return rc;
}
- cdk_free( idx );
- return *r_off != 0xFFFFFFFF ? 0 : CDK_EOF;
+ if (cdk_armor_filter_use (hd->buf))
+ cdk_stream_set_armor_flag (hd->buf, 0);
+ hd->type = CDK_DBTYPE_DATA;
+ hd->secret = secret;
+ *r_hd = hd;
+ return 0;
}
/**
+ * cdk_keydb_new_from_stream:
+ * @r_hd: the output keydb handle
+ * @secret: does the stream contain secret key data
+ * @in: the input stream to use
+ *
+ * This function creates a new keydb handle based on the given
+ * stream. The stream is not closed in cdk_keydb_free() and it
+ * is up to the caller to close it. No decoding is done.
+ */
+cdk_error_t
+cdk_keydb_new_from_stream (cdk_keydb_hd_t *r_hd, int secret,
+ cdk_stream_t in)
+{
+ cdk_keydb_hd_t hd;
+
+ if (!r_hd)
+ return CDK_Inv_Value;
+ *r_hd = NULL;
+
+ hd = calloc (1, sizeof *hd);
+ hd->buf = in;
+ hd->buf_ref = 1;
+ hd->type = CDK_DBTYPE_STREAM;
+ hd->secret = secret;
+ *r_hd = hd;
+
+ /* We do not push any filters and thus we expect that the format
+ of the stream has the format the user wanted. */
+
+ return 0;
+}
+
+
+cdk_error_t
+cdk_keydb_new_from_file (cdk_keydb_hd_t *r_hd, int secret, const char *fname)
+{
+ cdk_keydb_hd_t hd;
+
+ if (!r_hd)
+ return CDK_Inv_Value;
+ *r_hd = NULL;
+ hd = calloc (1, sizeof *hd);
+ hd->name = cdk_strdup (fname);
+ if (!hd->name)
+ {
+ cdk_free (hd);
+ return CDK_Out_Of_Core;
+ }
+ hd->type = secret? CDK_DBTYPE_SK_KEYRING : CDK_DBTYPE_PK_KEYRING;
+ hd->secret = secret;
+ *r_hd = hd;
+ return 0;
+}
+
+
+
+/**
* cdk_keydb_new:
* @r_hd: handle to store the new keydb object
* @type: type of the keyring
@@ -236,44 +337,25 @@ keydb_idx_search( cdk_stream_t inp, u32 * keyid,
* Create a new keydb object
**/
cdk_error_t
-cdk_keydb_new( cdk_keydb_hd_t * r_hd, int type, void * data, size_t count )
+cdk_keydb_new (cdk_keydb_hd_t *r_hd, int type, void *data, size_t count)
{
- cdk_keydb_hd_t hd;
-
- if( !r_hd )
- return CDK_Inv_Value;
-
- hd = cdk_calloc( 1, sizeof *hd );
- if( !hd )
- return CDK_Out_Of_Core;
-
- switch( type ) {
+ switch (type)
+ {
case CDK_DBTYPE_PK_KEYRING:
case CDK_DBTYPE_SK_KEYRING:
- hd->name = cdk_strdup( data );
- if( !hd->name ) {
- cdk_free( hd );
- return CDK_Out_Of_Core;
- }
- break;
+ return cdk_keydb_new_from_file (r_hd, type == CDK_DBTYPE_SK_KEYRING,
+ (const char*)data);
case CDK_DBTYPE_DATA:
- hd->buf = cdk_stream_tmp_from_mem( data, count );
- if( !hd->buf ) {
- cdk_free( hd );
- return CDK_Out_Of_Core;
- }
- break;
-
+ return cdk_keydb_new_from_mem (r_hd, 0, data, count);
+
+ case CDK_DBTYPE_STREAM:
+ return cdk_keydb_new_from_stream (r_hd, 0, (cdk_stream_t)data);
+
default:
- cdk_free( hd );
- return CDK_Inv_Mode;
+ return CDK_Inv_Mode;
}
- hd->type = type;
- if( type == CDK_DBTYPE_SK_KEYRING )
- hd->secret = 1;
- *r_hd = hd;
- return 0;
+ return CDK_Inv_Mode;
}
@@ -284,323 +366,346 @@ cdk_keydb_new( cdk_keydb_hd_t * r_hd, int type, void * data, size_t count )
* Free the keydb object.
**/
void
-cdk_keydb_free( cdk_keydb_hd_t hd )
+cdk_keydb_free (cdk_keydb_hd_t hd)
{
- if( !hd )
- return;
- if( hd->isopen && hd->name ) {
- hd->isopen = 0;
- cdk_free( hd->name );
- hd->name = NULL;
- cdk_stream_close( hd->buf );
- hd->buf = NULL;
+ if (!hd)
+ return;
+
+ if (hd->name)
+ {
+ cdk_free (hd->name);
+ hd->name = NULL;
}
- if( !hd->secret ) {
- cdk_stream_close( hd->idx );
- hd->idx = NULL;
+
+ if (hd->buf && !hd->buf_ref)
+ {
+ cdk_stream_close (hd->buf);
+ hd->buf = NULL;
+ }
+
+ if (hd->idx)
+ {
+ cdk_stream_close (hd->idx);
+ hd->idx = NULL;
}
- hd->no_cache = 0;
- hd->secret = 0;
- keydb_cache_free( hd->cache );
- hd->cache = NULL;
- keydb_search_free( hd->dbs );
- hd->dbs = NULL;
- cdk_free( hd );
+
+ hd->isopen = 0;
+ hd->no_cache = 0;
+ hd->secret = 0;
+ keydb_cache_free (hd->cache);
+ hd->cache = NULL;
+ keydb_search_free (hd->dbs);
+ hd->dbs = NULL;
+ cdk_free (hd);
}
-/**
- * cdk_keydb_open:
- * @hd: keydb object
- * @ret_kr: the STREAM object which contains the data of the keyring
- *
- * Open a STREAM with the contents of the keyring from @hd
- **/
cdk_error_t
-cdk_keydb_open( cdk_keydb_hd_t hd, cdk_stream_t * ret_kr )
+_cdk_keydb_open (cdk_keydb_hd_t hd, cdk_stream_t *ret_kr)
{
- int rc = 0, ec;
-
- if( !hd || !ret_kr )
- return CDK_Inv_Value;
-
- if( hd->type == CDK_DBTYPE_DATA && hd->buf )
- cdk_stream_seek( hd->buf, 0 );
- else if( hd->type == CDK_DBTYPE_PK_KEYRING
- || hd->type == CDK_DBTYPE_SK_KEYRING ) {
- if( !hd->isopen && hd->name ) {
- rc = cdk_stream_open( hd->name, &hd->buf );
- if( rc )
- goto leave;
- if( cdk_armor_filter_use( hd->buf ) )
- cdk_stream_set_armor_flag( hd->buf, 0 );
- hd->isopen = 1;
- cdk_free( hd->idx_name );
- hd->idx_name = keydb_idx_mkname( hd->name );
- if( !hd->idx_name ) {
- rc = CDK_Out_Of_Core;
- goto leave;
+ cdk_error_t rc, ec;
+
+ if (!hd || !ret_kr)
+ return CDK_Inv_Value;
+
+ rc = 0;
+ if ((hd->type == CDK_DBTYPE_DATA || hd->type == CDK_DBTYPE_STREAM)
+ && hd->buf)
+ cdk_stream_seek (hd->buf, 0);
+ else if (hd->type == CDK_DBTYPE_PK_KEYRING ||
+ hd->type == CDK_DBTYPE_SK_KEYRING)
+ {
+ if (!hd->isopen && hd->name)
+ {
+ rc = cdk_stream_open (hd->name, &hd->buf);
+ if (rc)
+ goto leave;
+ if (cdk_armor_filter_use (hd->buf))
+ cdk_stream_set_armor_flag (hd->buf, 0);
+ hd->isopen = 1;
+ /* We disable the index cache for smaller keyrings. */
+ if (cdk_stream_get_length (hd->buf) < 524288)
+ {
+ hd->no_cache = 1;
+ goto leave;
+ }
+ cdk_free (hd->idx_name);
+ hd->idx_name = keydb_idx_mkname (hd->name);
+ if (!hd->idx_name)
+ {
+ rc = CDK_Out_Of_Core;
+ goto leave;
}
- ec = cdk_stream_open( hd->idx_name, &hd->idx );
- if( ec && !hd->secret ) {
- rc = keydb_idx_build( hd->name );
- if( !rc )
- rc = cdk_stream_open( hd->idx_name, &hd->idx );
- if( !rc )
- _cdk_log_debug( "create key index table\n" );
- if( rc ) {
- /* 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" );
- rc = 0;
- hd->no_cache = 1;
- }
+ ec = cdk_stream_open (hd->idx_name, &hd->idx);
+ if (ec && !hd->secret)
+ {
+ rc = keydb_idx_build (hd->name);
+ if (!rc)
+ rc = cdk_stream_open (hd->idx_name, &hd->idx);
+ if (!rc)
+ _cdk_log_debug ("create key index table\n");
+ else
+ {
+ /* 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");
+ rc = 0;
+ hd->no_cache = 1;
+ }
}
}
- else {
- /* We use the cache to search keys, so we always rewind the
- STREAM. Except when the _NEXT search mode is used because
- this mode is an enumeration and no seeking is needed. */
- if( !hd->search ||
- (hd->search && hd->dbs->type != CDK_DBSEARCH_NEXT) )
- cdk_stream_seek( hd->buf, 0 );
+ else
+ {
+ /* We use the cache to search keys, so we always rewind the
+ STREAM. Except when the _NEXT search mode is used because
+ this mode is an enumeration and no seeking is needed. */
+ if (!hd->search ||
+ (hd->search && hd->dbs->type != CDK_DBSEARCH_NEXT))
+ cdk_stream_seek (hd->buf, 0);
}
}
- else
- return CDK_Inv_Mode;
+ else
+ return CDK_Inv_Mode;
- leave:
- if( rc ) {
- cdk_stream_close( hd->buf );
- hd->buf = NULL;
+ leave:
+ if (rc)
+ {
+ cdk_stream_close (hd->buf);
+ hd->buf = NULL;
}
- *ret_kr = hd->buf;
- return rc;
+ *ret_kr = hd->buf;
+ return rc;
}
static int
-find_by_keyid( cdk_kbnode_t knode, cdk_dbsearch_t ks )
+find_by_keyid (cdk_kbnode_t knode, cdk_dbsearch_t ks)
{
- cdk_kbnode_t node;
- u32 keyid[2];
- int found = 0;
-
- for( node = knode; node; node = node->next ) {
- if( node->pkt->pkttype == CDK_PKT_PUBLIC_KEY
- || node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY
- || node->pkt->pkttype == CDK_PKT_SECRET_KEY
- || node->pkt->pkttype == CDK_PKT_SECRET_SUBKEY ) {
- _cdk_pkt_get_keyid( node->pkt, keyid );
- switch( ks->type ) {
- case CDK_DBSEARCH_SHORT_KEYID:
- if( keyid[1] == ks->u.keyid[1] ) {
- found = 1;
- break;
- }
- break;
-
- case CDK_DBSEARCH_KEYID:
- if( KEYID_CMP( keyid, ks->u.keyid ) ) {
- found = 1;
- break;
- }
- break;
-
- default: /* invalid mode */
- return 0;
+ cdk_kbnode_t node;
+ u32 keyid[2];
+
+ for (node = knode; node; node = node->next)
+ {
+ if (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
+ node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY ||
+ node->pkt->pkttype == CDK_PKT_SECRET_KEY ||
+ node->pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
+ {
+ _cdk_pkt_get_keyid (node->pkt, keyid);
+ switch (ks->type)
+ {
+ case CDK_DBSEARCH_SHORT_KEYID:
+ if (keyid[1] == ks->u.keyid[1])
+ return 1;
+ break;
+
+ case CDK_DBSEARCH_KEYID:
+ if (KEYID_CMP (keyid, ks->u.keyid))
+ return 1;
+ break;
+
+ default: /* Invalid mode */
+ return 0;
}
}
}
- return found;
+ return 0;
}
static int
-find_by_fpr( cdk_kbnode_t knode, cdk_dbsearch_t ks )
+find_by_fpr (cdk_kbnode_t knode, cdk_dbsearch_t ks)
{
- cdk_kbnode_t node;
- int found = 0;
- byte fpr[20];
-
- if( ks->type != CDK_DBSEARCH_FPR )
- return found;
-
- for( node = knode; node; node = node->next ) {
- if( node->pkt->pkttype == CDK_PKT_PUBLIC_KEY
- || node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY
- || node->pkt->pkttype == CDK_PKT_SECRET_KEY
- || node->pkt->pkttype == CDK_PKT_SECRET_SUBKEY ) {
- _cdk_pkt_get_fingerprint( node->pkt, fpr );
- if( !memcmp( ks->u.fpr, fpr, 20 ) ) {
- found = 1;
- break;
- }
- }
+ cdk_kbnode_t node;
+ byte fpr[KEY_FPR_LEN];
+
+ if (ks->type != CDK_DBSEARCH_FPR)
+ return 0;
+
+ for (node = knode; node; node = node->next)
+ {
+ if (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
+ node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY ||
+ node->pkt->pkttype == CDK_PKT_SECRET_KEY ||
+ node->pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
+ {
+ _cdk_pkt_get_fingerprint (node->pkt, fpr);
+ if (!memcmp (ks->u.fpr, fpr, KEY_FPR_LEN))
+ return 1;
+ break;
+ }
}
- return found;
+
+ return 0;
}
static int
-find_by_pattern( cdk_kbnode_t knode, cdk_dbsearch_t ks )
+find_by_pattern (cdk_kbnode_t knode, cdk_dbsearch_t ks)
{
- cdk_kbnode_t node;
- size_t uidlen;
- char * name;
- int found = 0;
-
- for( node = knode; node; node = node->next ) {
- if( node->pkt->pkttype != CDK_PKT_USER_ID )
- continue;
- uidlen = node->pkt->pkt.user_id->len;
- name = node->pkt->pkt.user_id->name;
- switch( ks->type ) {
- case CDK_DBSEARCH_EXACT:
- if( name && (strlen( ks->u.pattern ) == uidlen
- && !strncmp( ks->u.pattern, name, uidlen ) ) ) {
- found = 1;
- break;
- }
- break;
-
- case CDK_DBSEARCH_SUBSTR:
- if( uidlen > 65536 )
- break;
- if( name && strlen( ks->u.pattern ) > uidlen )
- break;
- if( name && _cdk_memistr( name, uidlen, ks->u.pattern ) ) {
- found = 1;
- break;
- }
- break;
-
- default: /* invalid mode */
- return 0;
+ cdk_kbnode_t node;
+ size_t uidlen;
+ char *name;
+
+ for (node = knode; node; node = node->next)
+ {
+ if (node->pkt->pkttype != CDK_PKT_USER_ID)
+ continue;
+ if (node->pkt->pkt.user_id->attrib_img != NULL)
+ continue; /* Skip attribute packets. */
+ uidlen = node->pkt->pkt.user_id->len;
+ name = node->pkt->pkt.user_id->name;
+ switch (ks->type)
+ {
+ case CDK_DBSEARCH_EXACT:
+ if (name &&
+ (strlen (ks->u.pattern) == uidlen &&
+ !strncmp (ks->u.pattern, name, uidlen)))
+ return 1;
+ break;
+
+ case CDK_DBSEARCH_SUBSTR:
+ if (uidlen > 65536)
+ break;
+ if (name && strlen (ks->u.pattern) > uidlen)
+ break;
+ if (name && _cdk_memistr (name, uidlen, ks->u.pattern))
+ return 1;
+ break;
+
+ default: /* Invalid mode */
+ return 0;
}
}
- return found;
+ return 0;
}
-void
-keydb_search_free( cdk_dbsearch_t dbs )
+static void
+keydb_search_free (cdk_dbsearch_t dbs)
{
- if( !dbs )
- return;
- if( dbs->type == CDK_DBSEARCH_EXACT || dbs->type == CDK_DBSEARCH_SUBSTR )
- cdk_free( dbs->u.pattern );
- dbs->type = 0;
- cdk_free( dbs );
+ if (!dbs)
+ return;
+ if (dbs->type == CDK_DBSEARCH_EXACT ||
+ dbs->type == CDK_DBSEARCH_SUBSTR)
+ cdk_free( dbs->u.pattern );
+ dbs->type = 0;
+ cdk_free (dbs);
}
static void
-keydb_cache_free( key_table_t cache )
+keydb_cache_free (key_table_t cache)
{
- key_table_t c2;
-
- while( cache ) {
- c2 = cache->next;
- cache->offset = 0;
- keydb_search_free( cache->desc );
- cdk_free( cache );
- cache = c2;
+ key_table_t c2;
+
+ while (cache)
+ {
+ c2 = cache->next;
+ cache->offset = 0;
+ keydb_search_free (cache->desc);
+ cdk_free (cache);
+ cache = c2;
}
}
static key_table_t
-keydb_cache_find( key_table_t cache, cdk_dbsearch_t desc )
+keydb_cache_find (key_table_t cache, cdk_dbsearch_t desc)
{
- key_table_t t;
-
- for( t = cache; t; t = t->next ) {
- if( t->desc->type != desc->type )
- continue;
- switch( t->desc->type ) {
- case CDK_DBSEARCH_SHORT_KEYID:
- case CDK_DBSEARCH_KEYID:
- if( KEYID_CMP( t->desc->u.keyid, desc->u.keyid ) )
- return t;
- break;
-
- case CDK_DBSEARCH_EXACT:
- if( strlen( t->desc->u.pattern ) == strlen( desc->u.pattern )
- && !strcmp( t->desc->u.pattern, desc->u.pattern ) )
- return t;
- break;
-
- case CDK_DBSEARCH_SUBSTR:
- if( strstr( t->desc->u.pattern, desc->u.pattern ) )
- return t;
- break;
-
- case CDK_DBSEARCH_FPR:
- if( !memcmp( t->desc->u.fpr, desc->u.fpr, 20 ) )
- return t;
- break;
+ key_table_t t;
+
+ for (t = cache; t; t = t->next)
+ {
+ if (t->desc->type != desc->type)
+ continue;
+ switch (t->desc->type)
+ {
+ case CDK_DBSEARCH_SHORT_KEYID:
+ case CDK_DBSEARCH_KEYID:
+ if (KEYID_CMP (t->desc->u.keyid, desc->u.keyid))
+ return t;
+ break;
+
+ case CDK_DBSEARCH_EXACT:
+ if (strlen (t->desc->u.pattern) == strlen (desc->u.pattern) &&
+ !strcmp (t->desc->u.pattern, desc->u.pattern))
+ return t;
+ break;
+
+ case CDK_DBSEARCH_SUBSTR:
+ if (strstr (t->desc->u.pattern, desc->u.pattern))
+ return t;
+ break;
+
+ case CDK_DBSEARCH_FPR:
+ if (!memcmp (t->desc->u.fpr, desc->u.fpr, KEY_FPR_LEN))
+ return t;
+ break;
}
}
- return NULL;
+
+ return NULL;
}
static int
-keydb_cache_add (cdk_keydb_hd_t hd, cdk_dbsearch_t dbs, u32 offset)
+keydb_cache_add (cdk_keydb_hd_t hd, cdk_dbsearch_t dbs, off_t offset)
{
- key_table_t k;
-
- if( !hd )
- return CDK_Inv_Value;
- if( hd->ncache > KEYDB_CACHE_ENTRIES )
- return 0;
- k = cdk_calloc( 1, sizeof *k );
- if( !k )
- return CDK_Out_Of_Core;
- k->offset = offset;
- keydb_search_copy( &k->desc, dbs );
- k->next = hd->cache;
- hd->cache = k;
- hd->ncache++;
- _cdk_log_debug ("add entry [o=%d t=%d] to the cache\n", offset, dbs->type);
- return 0;
+ key_table_t k;
+
+ if (!hd)
+ return CDK_Inv_Value;
+
+ if (hd->ncache > KEYDB_CACHE_ENTRIES)
+ return 0; /* FIXME: we should replace the last entry. */
+ k = cdk_calloc (1, sizeof *k);
+ if (!k)
+ return CDK_Out_Of_Core;
+ k->offset = offset;
+ keydb_search_copy (&k->desc, dbs);
+ k->next = hd->cache;
+ hd->cache = k;
+ hd->ncache++;
+ _cdk_log_debug ("cache: add entry [o=%d t=%d]\n", offset, dbs->type);
+ return 0;
}
-static int
-keydb_search_copy (cdk_dbsearch_t * r_dst, cdk_dbsearch_t src)
+static cdk_error_t
+keydb_search_copy (cdk_dbsearch_t *r_dst, cdk_dbsearch_t src)
{
- cdk_dbsearch_t dst;
+ cdk_dbsearch_t dst;
- if (!r_dst || !src)
- return CDK_Inv_Value;
-
- dst = cdk_calloc( 1, sizeof *dst );
- if( !dst )
- return CDK_Out_Of_Core;
- dst->type = src->type;
- switch( src->type ) {
+ if (!r_dst || !src)
+ return CDK_Inv_Value;
+
+ dst = cdk_calloc (1, sizeof *dst);
+ if (!dst)
+ return CDK_Out_Of_Core;
+ dst->type = src->type;
+ switch (src->type)
+ {
case CDK_DBSEARCH_EXACT:
case CDK_DBSEARCH_SUBSTR:
- dst->u.pattern = cdk_strdup( src->u.pattern );
- if( !dst->u.pattern )
- return CDK_Out_Of_Core;
- break;
-
+ dst->u.pattern = cdk_strdup (src->u.pattern);
+ if (!dst->u.pattern)
+ return CDK_Out_Of_Core;
+ break;
+
case CDK_DBSEARCH_SHORT_KEYID:
case CDK_DBSEARCH_KEYID:
- dst->u.keyid[0] = src->u.keyid[0];
- dst->u.keyid[1] = src->u.keyid[1];
- break;
-
+ dst->u.keyid[0] = src->u.keyid[0];
+ dst->u.keyid[1] = src->u.keyid[1];
+ break;
+
case CDK_DBSEARCH_FPR:
- memcpy( dst->u.fpr, src->u.fpr, 20 );
- break;
+ memcpy (dst->u.fpr, src->u.fpr, KEY_FPR_LEN);
+ break;
}
- *r_dst = dst;
- return 0;
+ *r_dst = dst;
+ return 0;
}
@@ -613,1004 +718,1245 @@ keydb_search_copy (cdk_dbsearch_t * r_dst, cdk_dbsearch_t src)
* Create a new keydb search object.
**/
cdk_error_t
-cdk_keydb_search_start( cdk_keydb_hd_t db, int type, void * desc )
+cdk_keydb_search_start (cdk_keydb_hd_t db, int type, void *desc)
{
- cdk_dbsearch_t dbs;
- u32 * keyid;
- char * p, tmp[3];
- int i;
-
- if( !db )
- return CDK_Inv_Value;
- if( type != CDK_DBSEARCH_NEXT && !desc )
- return CDK_Inv_Mode;
-
- dbs = cdk_calloc( 1, sizeof *dbs );
- if( !dbs )
- return CDK_Out_Of_Core;
- dbs->type = type;
- switch( type ) {
+ cdk_dbsearch_t dbs;
+ u32 *keyid;
+ char *p, tmp[3];
+ int i;
+
+ if (!db)
+ return CDK_Inv_Value;
+ if (type != CDK_DBSEARCH_NEXT && !desc)
+ return CDK_Inv_Mode;
+
+ dbs = cdk_calloc (1, sizeof *dbs);
+ if (!dbs)
+ return CDK_Out_Of_Core;
+ dbs->type = type;
+ switch (type)
+ {
case CDK_DBSEARCH_EXACT:
case CDK_DBSEARCH_SUBSTR:
- cdk_free( dbs->u.pattern );
- dbs->u.pattern = cdk_strdup( desc );
- if( !dbs->u.pattern ) {
- cdk_free( dbs );
- return CDK_Out_Of_Core;
- }
- break;
-
+ cdk_free (dbs->u.pattern);
+ dbs->u.pattern = cdk_strdup (desc);
+ if (!dbs->u.pattern)
+ {
+ cdk_free( dbs );
+ return CDK_Out_Of_Core;
+ }
+ break;
+
case CDK_DBSEARCH_SHORT_KEYID:
- keyid = desc;
- dbs->u.keyid[1] = keyid[0];
- break;
+ keyid = desc;
+ dbs->u.keyid[1] = keyid[0];
+ break;
case CDK_DBSEARCH_KEYID:
- keyid = desc;
- dbs->u.keyid[0] = keyid[0];
- dbs->u.keyid[1] = keyid[1];
- break;
-
+ keyid = desc;
+ dbs->u.keyid[0] = keyid[0];
+ dbs->u.keyid[1] = keyid[1];
+ break;
+
case CDK_DBSEARCH_FPR:
- memcpy( dbs->u.fpr, desc, 20 );
- break;
-
+ memcpy (dbs->u.fpr, desc, KEY_FPR_LEN);
+ break;
+
case CDK_DBSEARCH_NEXT:
- break;
-
+ break;
+
case CDK_DBSEARCH_AUTO:
- /* override the type with the actual db search type. */
- dbs->type = classify_data( desc, strlen( desc ) );
- switch( dbs->type ) {
- case CDK_DBSEARCH_SUBSTR:
- case CDK_DBSEARCH_EXACT:
- cdk_free( dbs->u.pattern );
- p = dbs->u.pattern = cdk_strdup( desc );
- if( !p ) {
- cdk_free( dbs );
- return CDK_Out_Of_Core;
- }
- break;
-
- case CDK_DBSEARCH_SHORT_KEYID:
- case CDK_DBSEARCH_KEYID:
- p = desc;
- if( !strncmp( p, "0x", 2 ) )
- p += 2;
- if( strlen( p ) == 8 ) {
- dbs->u.keyid[0] = 0;
- dbs->u.keyid[1] = strtoul( p, NULL, 16 );
- }
- else if( strlen( p ) == 16 ) {
- dbs->u.keyid[0] = strtoul( p , NULL, 16 );
- dbs->u.keyid[1] = strtoul( p + 8, NULL, 16 );
- }
- else { /* should never happen */
- cdk_free( dbs );
- return CDK_Inv_Mode;
- }
- break;
-
- case CDK_DBSEARCH_FPR:
- p = desc;
- if( strlen( p ) != 40 ) {
- cdk_free( dbs );
- return CDK_Inv_Mode;
- }
- for( i = 0; i < 20; i++ ) {
- tmp[0] = p[2*i];
- tmp[1] = p[2*i+1];
- tmp[2] = 0x00;
- dbs->u.fpr[i] = strtoul( tmp, NULL, 16 );
- }
- break;
- }
- break;
-
+ /* Override the type with the actual db search type. */
+ dbs->type = classify_data (desc, strlen (desc));
+ switch (dbs->type)
+ {
+ case CDK_DBSEARCH_SUBSTR:
+ case CDK_DBSEARCH_EXACT:
+ cdk_free (dbs->u.pattern);
+ p = dbs->u.pattern = cdk_strdup (desc);
+ if (!p)
+ {
+ cdk_free (dbs);
+ return CDK_Out_Of_Core;
+ }
+ break;
+
+ case CDK_DBSEARCH_SHORT_KEYID:
+ case CDK_DBSEARCH_KEYID:
+ p = desc;
+ if (!strncmp (p, "0x", 2))
+ p += 2;
+ if (strlen (p) == 8 )
+ {
+ dbs->u.keyid[0] = 0;
+ dbs->u.keyid[1] = strtoul (p, NULL, 16);
+ }
+ else if (strlen (p) == 16 )
+ {
+ dbs->u.keyid[0] = strtoul (p , NULL, 16);
+ dbs->u.keyid[1] = strtoul (p + 8, NULL, 16);
+ }
+ else
+ { /* Invalid key ID object. */
+ cdk_free (dbs);
+ return CDK_Inv_Mode;
+ }
+ break;
+
+ case CDK_DBSEARCH_FPR:
+ p = desc;
+ if (strlen (p) != 2*KEY_FPR_LEN)
+ {
+ cdk_free (dbs);
+ return CDK_Inv_Mode;
+ }
+ for (i = 0; i < KEY_FPR_LEN; i++)
+ {
+ tmp[0] = p[2*i];
+ tmp[1] = p[2*i+1];
+ tmp[2] = 0x00;
+ dbs->u.fpr[i] = strtoul (tmp, NULL, 16);
+ }
+ break;
+ }
+ break;
+
default:
- cdk_free( dbs );
- return CDK_Inv_Mode;
+ cdk_free (dbs);
+ return CDK_Inv_Mode;
}
- keydb_search_free( db->dbs );
- db->dbs = dbs;
- return 0;
+
+ keydb_search_free (db->dbs);
+ db->dbs = dbs;
+ return 0;
}
static int
-keydb_pos_from_cache( cdk_keydb_hd_t hd, cdk_dbsearch_t ks,
- int * r_cache_hit, u32 * r_off )
+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;
- u32 off = 0;
- int cache_hit = 0;
-
- if( !hd || !r_cache_hit || !r_off )
- return CDK_Inv_Value;
-
- c = keydb_cache_find( hd->cache, ks );
- if( c ) {
- _cdk_log_debug( "found entry in cache.\n" );
- cache_hit = 1;
- off = c->offset;
- }
+ key_table_t c;
+ off_t off;
+ int cache_hit;
- if( hd->idx && !c ) {
- if( ks->type == CDK_DBSEARCH_KEYID ) {
- if( keydb_idx_search( hd->idx, ks->u.keyid, NULL, &off ) )
- return CDK_Error_No_Key;
- _cdk_log_debug( "found keyid entry in idx table.\n" );
- cache_hit = 1;
- }
- else if( ks->type == CDK_DBSEARCH_FPR ) {
- if( keydb_idx_search( hd->idx, NULL, ks->u.fpr, &off ) )
- return CDK_Error_No_Key;
- _cdk_log_debug( "found fpr entry in idx table.\n" );
- cache_hit = 1;
+ if (!hd || !r_cache_hit || !r_off)
+ return CDK_Inv_Value;
+
+ /* Reset */
+ off = 0;
+ cache_hit = 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;
+ }
+
+ if (hd->idx && !c)
+ {
+ if (ks->type == CDK_DBSEARCH_KEYID)
+ {
+ if (keydb_idx_search (hd->idx, ks->u.keyid, NULL, &off))
+ return CDK_Error_No_Key;
+ _cdk_log_debug ("Cache: found keyid entry in idx table.\n");
+ cache_hit = 1;
}
+ else if (ks->type == CDK_DBSEARCH_FPR)
+ {
+ if (keydb_idx_search (hd->idx, NULL, ks->u.fpr, &off))
+ return CDK_Error_No_Key;
+ _cdk_log_debug ("Cache: found fpr entry in idx table.\n");
+ cache_hit = 1;
+ }
}
- *r_off = off;
- *r_cache_hit = cache_hit;
- return 0;
+ *r_off = off;
+ *r_cache_hit = cache_hit;
+ return 0;
}
/**
* cdk_keydb_search:
* @hd: the keydb object
+ * @ks: the keydb search object
* @ret_key: kbnode object to store the key
*
- * Search for a key in the given keyring. If the key was found,
- * @ret_key contains the key data.
+ * Search for a key in the given keyring. The search mode is handled
+ * via @ks. If the key was found, @ret_key contains the key data.
**/
cdk_error_t
-cdk_keydb_search( cdk_keydb_hd_t hd, cdk_kbnode_t * ret_key )
+cdk_keydb_search (cdk_keydb_hd_t hd, cdk_kbnode_t *ret_key)
{
- cdk_stream_t kr = NULL;
- cdk_kbnode_t knode = NULL;
- cdk_dbsearch_t ks;
- u32 off = 0;
- size_t pos = 0;
- int key_found = 0, cache_hit = 0;
- int rc = 0;
-
- if( !hd || !ret_key )
- return CDK_Inv_Value;
-
- *ret_key = NULL;
- hd->search = 1;
- rc = cdk_keydb_open( hd, &kr );
- if( rc )
- return rc;
- rc = keydb_pos_from_cache( hd, hd->dbs, &cache_hit, &off );
- if( rc )
+ cdk_stream_t kr = NULL;
+ cdk_kbnode_t knode = NULL;
+ cdk_dbsearch_t ks;
+ off_t pos = 0, off = 0;
+ int key_found = 0, cache_hit = 0;
+ cdk_error_t rc = 0;
+
+ if (!hd || !ret_key)
+ return CDK_Inv_Value;
+
+ *ret_key = NULL;
+ hd->search = 1;
+ rc = _cdk_keydb_open (hd, &kr);
+ if (rc)
+ return rc;
+
+ if (!hd->no_cache)
+ {
+ /* FIXME: pubkey offset seems wrong */
+ rc = keydb_pos_from_cache (hd, hd->dbs, &cache_hit, &off);
+ if (rc)
return rc;
-
- ks = hd->dbs;
- while( !key_found && !rc ) {
- if( cache_hit && ks->type != CDK_DBSEARCH_NEXT )
- cdk_stream_seek( kr, off );
- pos = cdk_stream_tell( kr );
- rc = cdk_keydb_get_keyblock( kr, &knode );
- if( rc ) {
- if( rc == CDK_EOF && knode )
- rc = 0;
- if( !knode && rc == CDK_EOF )
- rc = CDK_Error_No_Key;
- if( rc )
- break;
- }
-
- switch( ks->type ) {
- case CDK_DBSEARCH_SHORT_KEYID:
- case CDK_DBSEARCH_KEYID:
- key_found = find_by_keyid( knode, ks );
- break;
-
- case CDK_DBSEARCH_FPR:
- key_found = find_by_fpr( knode, ks );
- break;
+ }
+ ks = hd->dbs;
+ while (!key_found && !rc)
+ {
+ if (cache_hit && ks->type != CDK_DBSEARCH_NEXT)
+ cdk_stream_seek (kr, off);
+ pos = cdk_stream_tell (kr);
+ rc = cdk_keydb_get_keyblock (kr, &knode);
+ if (rc)
+ {
+ if (rc == CDK_EOF)
+ break;
+ else
+ return rc;
+ }
+
+ switch (ks->type)
+ {
+ case CDK_DBSEARCH_SHORT_KEYID:
+ case CDK_DBSEARCH_KEYID:
+ key_found = find_by_keyid (knode, ks);
+ break;
+
+ case CDK_DBSEARCH_FPR:
+ key_found = find_by_fpr (knode, ks);
+ break;
case CDK_DBSEARCH_EXACT:
case CDK_DBSEARCH_SUBSTR:
- key_found = find_by_pattern( knode, ks );
- break;
-
- case CDK_DBSEARCH_NEXT:
- key_found = knode? 1 : 0;
- break;
+ key_found = find_by_pattern (knode, ks);
+ break;
+
+ case CDK_DBSEARCH_NEXT:
+ key_found = knode? 1 : 0;
+ break;
}
-
- if( key_found ) {
- if( !keydb_cache_find( hd->cache, ks ) )
- keydb_cache_add( hd, ks, pos );
- break;
+
+ if (key_found)
+ {
+ if (!keydb_cache_find (hd->cache, ks))
+ keydb_cache_add (hd, ks, pos);
+ break;
}
-
- cdk_kbnode_release( knode );
- knode = NULL;
+
+ cdk_kbnode_release (knode);
+ knode = NULL;
}
- hd->search = 0;
- *ret_key = key_found? knode : NULL;
- return rc;
+ hd->search = 0;
+ if (key_found && rc == CDK_EOF)
+ rc = 0;
+ else if (rc == CDK_EOF && !key_found)
+ rc = CDK_Error_No_Key;
+ *ret_key = key_found? knode : NULL;
+ return rc;
}
cdk_error_t
-cdk_keydb_get_bykeyid( cdk_keydb_hd_t hd, u32 * keyid, cdk_kbnode_t * ret_pk )
+cdk_keydb_get_bykeyid (cdk_keydb_hd_t hd, u32 *keyid, cdk_kbnode_t *ret_key)
{
- int rc;
-
- if( !hd || !keyid || !ret_pk )
- return CDK_Inv_Value;
-
- rc = cdk_keydb_search_start( hd, CDK_DBSEARCH_KEYID, keyid );
- if( !rc )
- rc = cdk_keydb_search( hd, ret_pk );
- return rc;
+ cdk_error_t rc;
+
+ if (!hd || !keyid || !ret_key)
+ return CDK_Inv_Value;
+
+ rc = cdk_keydb_search_start (hd, CDK_DBSEARCH_KEYID, keyid);
+ if (!rc)
+ rc = cdk_keydb_search (hd, ret_key);
+ return rc;
}
cdk_error_t
-cdk_keydb_get_byfpr( cdk_keydb_hd_t hd, const byte * fpr, cdk_kbnode_t * r_pk )
+cdk_keydb_get_byfpr (cdk_keydb_hd_t hd, const byte *fpr, cdk_kbnode_t *r_key)
{
- int rc;
-
- if( !hd || !fpr || !r_pk )
- return CDK_Inv_Value;
-
- rc = cdk_keydb_search_start( hd, CDK_DBSEARCH_FPR, (byte *)fpr );
- if( !rc )
- rc = cdk_keydb_search( hd, r_pk );
- return rc;
+ cdk_error_t rc;
+
+ if (!hd || !fpr || !r_key)
+ return CDK_Inv_Value;
+
+ rc = cdk_keydb_search_start (hd, CDK_DBSEARCH_FPR, (byte *)fpr);
+ if (!rc)
+ rc = cdk_keydb_search (hd, r_key);
+ return rc;
}
cdk_error_t
-cdk_keydb_get_bypattern( cdk_keydb_hd_t hd, const char * patt,
- cdk_kbnode_t * ret_pk )
+cdk_keydb_get_bypattern (cdk_keydb_hd_t hd, const char *patt,
+ cdk_kbnode_t * ret_key)
{
- int rc;
-
- if( !hd || !patt || !ret_pk )
- return CDK_Inv_Value;
-
- rc = cdk_keydb_search_start( hd, CDK_DBSEARCH_SUBSTR, (char *)patt );
- if( !rc )
- rc = cdk_keydb_search( hd, ret_pk );
- return rc;
+ cdk_error_t rc;
+
+ if (!hd || !patt || !ret_key)
+ return CDK_Inv_Value;
+
+ rc = cdk_keydb_search_start (hd, CDK_DBSEARCH_SUBSTR, (char *)patt);
+ if (!rc)
+ rc = cdk_keydb_search (hd, ret_key);
+ return rc;
}
static int
-keydb_check_key( cdk_packet_t pkt )
+keydb_check_key (cdk_packet_t pkt)
{
- cdk_pkt_pubkey_t pk;
- int is_sk = 0, valid = 0;
-
- if( pkt->pkttype == CDK_PKT_PUBLIC_KEY
- || pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY )
- pk = pkt->pkt.public_key;
- else if( pkt->pkttype == CDK_PKT_SECRET_KEY
- || pkt->pkttype == CDK_PKT_SECRET_SUBKEY ) {
- pk = pkt->pkt.secret_key->pk;
- is_sk = 1;
+ cdk_pkt_pubkey_t pk;
+ int is_sk = 0, valid = 0;
+
+ if (pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
+ pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
+ pk = pkt->pkt.public_key;
+ else if (pkt->pkttype == CDK_PKT_SECRET_KEY ||
+ pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
+ {
+ pk = pkt->pkt.secret_key->pk;
+ is_sk = 1;
}
- else
- return 0;
- valid = !pk->is_revoked && !pk->has_expired;
- if( is_sk )
- return valid;
- return valid && !pk->is_invalid;
+ else /* No key object. */
+ return 0;
+ valid = !pk->is_revoked && !pk->has_expired;
+ if (is_sk)
+ return valid;
+ return valid && !pk->is_invalid;
}
+/* Find the first kbnode with the requested packet type
+ that represents a valid key. */
static cdk_kbnode_t
-keydb_find_byusage( cdk_kbnode_t root, int req_usage, int is_pk )
+kbnode_find_valid (cdk_kbnode_t root, int pkttype)
{
- cdk_kbnode_t node;
- int pkttype = 0, req_type = 0;
-
- req_type = is_pk? CDK_PKT_PUBLIC_KEY : CDK_PKT_SECRET_KEY;
- if( !req_usage )
- return cdk_kbnode_find( root, req_type );
-
- node = cdk_kbnode_find( root, req_type );
- if( node && !keydb_check_key( node->pkt ) )
- return NULL;
-
- /* xxx: if there are more subkeys, use the one with the requested
- usage and the newest timestamp. */
- for( node = root; node; node = node->next ) {
- pkttype = node->pkt->pkttype;
- if( is_pk && (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY
- || node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
- && keydb_check_key( node->pkt )
- && (node->pkt->pkt.public_key->pubkey_usage & req_usage) )
- return node;
- if( !is_pk && (node->pkt->pkttype == CDK_PKT_SECRET_KEY
- || node->pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
- && keydb_check_key( node->pkt )
- && (node->pkt->pkt.secret_key->pk->pubkey_usage & req_usage) )
- return node;
+ cdk_kbnode_t n;
+
+ for (n = root; n ; n = n->next)
+ {
+ if (n->pkt->pkttype != pkttype)
+ continue;
+ if (keydb_check_key (n->pkt))
+ return n;
}
- return NULL;
+
+ return NULL;
}
static cdk_kbnode_t
-keydb_find_bykeyid( cdk_kbnode_t root, u32 * keyid )
+keydb_find_byusage (cdk_kbnode_t root, int req_usage, int is_pk)
{
- cdk_kbnode_t node;
- u32 kid[2];
+ cdk_kbnode_t node, key = NULL;
+ int req_type;
+ long timestamp;
+
+ req_type = is_pk? CDK_PKT_PUBLIC_KEY : CDK_PKT_SECRET_KEY;
+ if (!req_usage)
+ return kbnode_find_valid (root, req_type);
+
+ node = cdk_kbnode_find (root, req_type);
+ if (node && !keydb_check_key (node->pkt))
+ return NULL;
- for( node = root; node; node = node->next ) {
- _cdk_pkt_get_keyid (node->pkt, kid);
- if( kid[1] == keyid[1] )
- return node;
+ timestamp = 0;
+ /* We iteratre over the all nodes and search for keys or
+ subkeys which match the usage and which are not invalid.
+ A timestamp is used to figure out the newest valid key. */
+ for (node = root; node; node = node->next)
+ {
+ if (is_pk && (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
+ node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
+ && keydb_check_key (node->pkt)
+ && (node->pkt->pkt.public_key->pubkey_usage & req_usage))
+ {
+ if (node->pkt->pkt.public_key->timestamp > timestamp)
+ key = node;
+ }
+ if (!is_pk && (node->pkt->pkttype == CDK_PKT_SECRET_KEY ||
+ node->pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
+ && keydb_check_key (node->pkt)
+ && (node->pkt->pkt.secret_key->pk->pubkey_usage & req_usage))
+ {
+ if (node->pkt->pkt.secret_key->pk->timestamp > timestamp)
+ key = node;
+ }
+
}
- return NULL;
+ return key;
}
-int
-_cdk_keydb_get_sk_byusage( cdk_keydb_hd_t hd, const char * name,
- cdk_pkt_seckey_t* ret_sk, int usage )
+static cdk_kbnode_t
+keydb_find_bykeyid (cdk_kbnode_t root, const u32 *keyid, int search_mode)
{
- cdk_kbnode_t knode = NULL, node = NULL;
- cdk_pkt_seckey_t sk = NULL;
- int rc = 0;
-
- if( !ret_sk || !usage )
- return CDK_Inv_Value;
- if( !hd )
- return CDK_Error_No_Keyring;
-
- rc = cdk_keydb_search_start( hd, CDK_DBSEARCH_AUTO, (char *)name );
- if( !rc )
- rc = cdk_keydb_search( hd, &knode );
- if( rc )
- goto leave;
- node = keydb_find_byusage( knode, usage, 0 );
- if( !node ) {
- rc = CDK_Unusable_Key;
- goto leave;
+ cdk_kbnode_t node;
+ u32 kid[2];
+
+ for (node = root; node; node = node->next)
+ {
+ if (!_cdk_pkt_get_keyid (node->pkt, kid))
+ continue;
+ if (search_mode == CDK_DBSEARCH_SHORT_KEYID &&
+ kid[1] == keyid[1])
+ return node;
+ if (kid[0] == keyid[0] && kid[1] == keyid[1])
+ return node;
}
+ return NULL;
+}
- sk = node->pkt->pkt.secret_key;
- _cdk_kbnode_clone( node );
- cdk_kbnode_release( knode );
-leave:
- *ret_sk = sk;
+int
+_cdk_keydb_get_sk_byusage (cdk_keydb_hd_t hd, const char *name,
+ cdk_pkt_seckey_t* ret_sk, int usage)
+{
+ cdk_kbnode_t knode = NULL, node;
+ cdk_pkt_seckey_t sk;
+ const char *s;
+ cdk_error_t rc;
+
+ if (!ret_sk || !usage)
+ return CDK_Inv_Value;
+ if (!hd)
+ return CDK_Error_No_Keyring;
+
+ *ret_sk = NULL;
+ rc = cdk_keydb_search_start (hd, CDK_DBSEARCH_AUTO, (char *)name);
+ if (rc)
return rc;
+
+ rc = cdk_keydb_search (hd, &knode);
+ if (rc)
+ return rc;
+
+ node = keydb_find_byusage (knode, usage, 0);
+ if (!node)
+ {
+ cdk_kbnode_release (knode);
+ return CDK_Unusable_Key;
+ }
+
+ /* We return the packet so make sure it is not released. */
+ _cdk_kbnode_clone (node);
+ sk = node->pkt->pkt.secret_key;
+
+ for (node = knode; node; node = node->next)
+ {
+ if (node->pkt->pkttype == CDK_PKT_USER_ID)
+ {
+ s = node->pkt->pkt.user_id->name;
+ if (sk && !sk->pk->uid && _cdk_memistr (s, strlen (s), name))
+ {
+ _cdk_copy_userid (&sk->pk->uid, node->pkt->pkt.user_id);
+ break;
+ }
+ }
+ }
+
+ node = find_selfsig_node (knode, sk->pk);
+ if (sk->pk->uid && node)
+ _cdk_copy_signature (&sk->pk->uid->selfsig, node->pkt->pkt.signature);
+
+ cdk_kbnode_release (knode);
+ *ret_sk = sk;
+ return rc;
}
int
-_cdk_keydb_get_pk_byusage( cdk_keydb_hd_t hd, const char * name,
- cdk_pkt_pubkey_t* ret_pk, int usage )
+_cdk_keydb_get_pk_byusage (cdk_keydb_hd_t hd, const char *name,
+ cdk_pkt_pubkey_t *ret_pk, int usage)
{
- cdk_kbnode_t knode, node = NULL;
- cdk_pkt_pubkey_t pk = NULL;
- const char * s;
- int rc = 0;
-
- if( !ret_pk || !usage )
- return CDK_Inv_Value;
- if( !hd )
- return CDK_Error_No_Keyring;
-
- rc = cdk_keydb_search_start( hd, CDK_DBSEARCH_AUTO, (char *)name );
- if( !rc )
- rc = cdk_keydb_search( hd, &knode );
- if( rc )
- goto leave;
- node = keydb_find_byusage( knode, usage, 1 );
- if( !node ) {
- rc = CDK_Unusable_Key;
- goto leave;
- }
-
- _cdk_copy_pubkey( &pk, node->pkt->pkt.public_key );
- for( node = knode; node; node = node->next ) {
- if( node->pkt->pkttype == CDK_PKT_USER_ID ) {
- s = node->pkt->pkt.user_id->name;
- if( pk && !pk->uid && _cdk_memistr( s, strlen( s ), name ) ) {
- _cdk_copy_userid( &pk->uid, node->pkt->pkt.user_id );
- break;
+ cdk_kbnode_t knode, node = NULL;
+ cdk_pkt_pubkey_t pk = NULL;
+ const char *s;
+ cdk_error_t rc;
+
+ if (!ret_pk || !usage)
+ return CDK_Inv_Value;
+ if (!hd)
+ return CDK_Error_No_Keyring;
+
+ *ret_pk = NULL;
+ rc = cdk_keydb_search_start (hd, CDK_DBSEARCH_AUTO, (char *)name);
+ if (!rc)
+ rc = cdk_keydb_search (hd, &knode);
+ if (rc)
+ return rc;
+
+ node = keydb_find_byusage (knode, usage, 1);
+ if (!node)
+ {
+ cdk_kbnode_release (knode);
+ return CDK_Unusable_Key;
+ }
+
+ _cdk_copy_pubkey (&pk, node->pkt->pkt.public_key);
+ for (node = knode; node; node = node->next)
+ {
+ if (node->pkt->pkttype == CDK_PKT_USER_ID)
+ {
+ s = node->pkt->pkt.user_id->name;
+ if (pk && !pk->uid && _cdk_memistr (s, strlen (s), name))
+ {
+ _cdk_copy_userid (&pk->uid, node->pkt->pkt.user_id);
+ break;
}
}
}
- cdk_kbnode_release( knode );
+
+ node = find_selfsig_node (knode, pk);
+ if (pk->uid && node)
+ _cdk_copy_signature (&pk->uid->selfsig, node->pkt->pkt.signature);
+ cdk_kbnode_release (knode);
-leave:
- *ret_pk = pk;
- return rc;
+ *ret_pk = pk;
+ return rc;
}
cdk_error_t
-cdk_keydb_get_pk( cdk_keydb_hd_t hd, u32 * keyid, cdk_pkt_pubkey_t* r_pk )
+cdk_keydb_get_pk (cdk_keydb_hd_t hd, u32 *keyid, cdk_pkt_pubkey_t *r_pk)
{
- cdk_kbnode_t knode = NULL, node = NULL;
- cdk_pkt_pubkey_t pk = NULL;
- int rc = 0;
-
- if( !keyid || !r_pk )
- return CDK_Inv_Value;
- if( !hd )
- return CDK_Error_No_Keyring;
-
- rc = cdk_keydb_search_start( hd, !keyid[0]?
- CDK_DBSEARCH_SHORT_KEYID : CDK_DBSEARCH_KEYID,
- keyid );
- if( !rc )
- rc = cdk_keydb_search( hd, &knode );
- if( rc )
- goto leave;
- node = keydb_find_bykeyid( knode, keyid );
- if( !node ) {
- rc = CDK_Error_No_Key;
- goto leave;
+ cdk_kbnode_t knode = NULL, node;
+ cdk_pkt_pubkey_t pk;
+ size_t s_type;
+ int rc;
+
+ if (!keyid || !r_pk)
+ return CDK_Inv_Value;
+ if (!hd)
+ return CDK_Error_No_Keyring;
+
+ *r_pk = NULL;
+ s_type = !keyid[0]? CDK_DBSEARCH_SHORT_KEYID : CDK_DBSEARCH_KEYID;
+ rc = cdk_keydb_search_start (hd, s_type, keyid);
+ if (rc)
+ return rc;
+ rc = cdk_keydb_search (hd, &knode);
+ if (rc)
+ return rc;
+
+ node = keydb_find_bykeyid (knode, keyid, s_type);
+ if (!node)
+ {
+ cdk_kbnode_release (knode);
+ return CDK_Error_No_Key;
}
- _cdk_copy_pubkey( &pk, node->pkt->pkt.public_key );
- cdk_kbnode_release( knode );
-leave:
- *r_pk = pk;
- return rc;
+ pk = node->pkt->pkt.public_key;
+ _cdk_kbnode_clone (node);
+ cdk_kbnode_release (knode);
+
+ *r_pk = pk;
+ return rc;
}
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_pkt_seckey_t *ret_sk)
{
- cdk_kbnode_t snode, node;
- cdk_pkt_seckey_t sk = NULL;
- int rc = 0;
-
- if( !keyid || !ret_sk )
- return CDK_Inv_Value;
- if( !hd )
- return CDK_Error_No_Keyring;
-
- rc = cdk_keydb_get_bykeyid( hd, keyid, &snode );
- if( rc )
- goto leave;
-
- node = keydb_find_bykeyid( snode, keyid );
- if( !node ) {
- rc = CDK_Error_No_Key;
- goto leave;
- }
+ cdk_kbnode_t snode, node;
+ cdk_pkt_seckey_t sk;
+ cdk_error_t rc;
+
+ if (!keyid || !ret_sk)
+ return CDK_Inv_Value;
+ if (!hd )
+ return CDK_Error_No_Keyring;
+
+ *ret_sk = NULL;
+ rc = cdk_keydb_get_bykeyid (hd, keyid, &snode);
+ if (rc)
+ return rc;
- sk = node->pkt->pkt.secret_key;
- _cdk_kbnode_clone( node );
- cdk_kbnode_release( snode );
+ node = keydb_find_bykeyid (snode, keyid, CDK_DBSEARCH_KEYID);
+ if (!node)
+ {
+ cdk_kbnode_release (snode);
+ return CDK_Error_No_Key;
+ }
- leave:
- *ret_sk = sk;
- return rc;
+ sk = node->pkt->pkt.secret_key;
+ _cdk_kbnode_clone (node);
+ cdk_kbnode_release (snode);
+
+ *ret_sk = sk;
+ return 0;
}
static int
-is_selfsig( cdk_kbnode_t node, u32 * keyid )
+is_selfsig (cdk_kbnode_t node, const u32 *keyid)
{
- cdk_pkt_signature_t sig;
-
- if( node->pkt->pkttype != CDK_PKT_SIGNATURE )
- return 0;
- sig = node->pkt->pkt.signature;
- if( (sig->sig_class == 0x13 || sig->sig_class == 0x10) &&
- sig->keyid[0] == keyid[0] && sig->keyid[1] == keyid[1] )
- return 1;
+ cdk_pkt_signature_t sig;
+
+ if (node->pkt->pkttype != CDK_PKT_SIGNATURE)
return 0;
+ sig = node->pkt->pkt.signature;
+ if ((sig->sig_class == 0x13 || sig->sig_class == 0x10) &&
+ sig->keyid[0] == keyid[0] && sig->keyid[1] == keyid[1])
+ return 1;
+ return 0;
}
+
+static cdk_kbnode_t
+find_selfsig_node (cdk_kbnode_t key, cdk_pkt_pubkey_t pk)
+{
+ cdk_kbnode_t n;
+ u32 keyid[2];
+
+ cdk_pk_get_keyid (pk, keyid);
+ for (n = key; n; n = n->next)
+ {
+ if (is_selfsig (n, keyid))
+ break;
+ }
+
+ return n;
+}
+
+
static int
-keydb_merge_selfsig( cdk_kbnode_t key, u32 * keyid )
+keydb_merge_selfsig (cdk_kbnode_t key, u32 *keyid)
{
- cdk_kbnode_t node, kbnode, unode;
- cdk_subpkt_t s = NULL;
- cdk_pkt_signature_t sig = NULL;
- cdk_pkt_userid_t uid = NULL;
- const byte * symalg = NULL, * hashalg = NULL, * compalg = NULL;
- size_t nsymalg = 0, nhashalg = 0, ncompalg = 0, n = 0;
- int key_usage = 0, key_expire = 0;
-
- if (!key)
- return CDK_Inv_Value;
-
- for( node = key; node; node = node->next ) {
- if( !is_selfsig( node, keyid ) )
- continue;
- unode = cdk_kbnode_find_prev( key, node, CDK_PKT_USER_ID );
- if( !unode )
- return CDK_Error_No_Key;
- uid = unode->pkt->pkt.user_id;
- sig = node->pkt->pkt.signature;
- s = cdk_subpkt_find( sig->hashed, CDK_SIGSUBPKT_PRIMARY_UID );
- if( s )
- uid->is_primary = 1;
- s = cdk_subpkt_find( sig->hashed, CDK_SIGSUBPKT_FEATURES );
- if( s && s->size == 1 && s->d[0] & 0x01 )
- uid->mdc_feature = 1;
- s = cdk_subpkt_find( sig->hashed, CDK_SIGSUBPKT_KEY_EXPIRE );
- if( s && s->size == 4 )
- key_expire = _cdk_buftou32( s->d );
- s = cdk_subpkt_find( sig->hashed, CDK_SIGSUBPKT_KEY_FLAGS );
- if( s ) {
- if( s->d[0] & 3 ) /* cert + sign data */
- key_usage |= PK_USAGE_SIGN;
- if( s->d[0] & 12 ) /* encrypt comm. + storage */
- key_usage |= PK_USAGE_ENCR;
+ cdk_kbnode_t node, kbnode, unode;
+ cdk_subpkt_t s = NULL;
+ cdk_pkt_signature_t sig = NULL;
+ cdk_pkt_userid_t uid = NULL;
+ const byte *symalg = NULL, *hashalg = NULL, *compalg = NULL;
+ size_t nsymalg = 0, nhashalg = 0, ncompalg = 0, n = 0;
+ size_t key_usage = 0, key_expire = 0;
+
+ if (!key)
+ return CDK_Inv_Value;
+
+ for (node = key; node; node = node->next)
+ {
+ if (!is_selfsig (node, keyid))
+ continue;
+ unode = cdk_kbnode_find_prev (key, node, CDK_PKT_USER_ID);
+ if (!unode)
+ return CDK_Error_No_Key;
+ uid = unode->pkt->pkt.user_id;
+ sig = node->pkt->pkt.signature;
+ s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PRIMARY_UID);
+ if (s)
+ uid->is_primary = 1;
+ s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_FEATURES);
+ if (s && s->size == 1 && s->d[0] & 0x01)
+ uid->mdc_feature = 1;
+ s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_KEY_EXPIRE);
+ if (s && s->size == 4)
+ key_expire = _cdk_buftou32 (s->d);
+ s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_KEY_FLAGS);
+ if (s)
+ {
+ if (s->d[0] & 0x03) /* cert + sign data */
+ key_usage |= CDK_KEY_USG_SIGN;
+ if (s->d[0] & 0x0C) /* encrypt comm. + storage */
+ key_usage |= CDK_KEY_USG_ENCR;
+ if (s->d[0] & 0x20)
+ key_usage |= CDK_KEY_USG_AUTH;
}
- s = cdk_subpkt_find( sig->hashed, CDK_SIGSUBPKT_PREFS_SYM );
- if( s ) {
- symalg = s->d;
- nsymalg = s->size;
- n += s->size + 1;
+ s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PREFS_SYM);
+ if (s)
+ {
+ symalg = s->d;
+ nsymalg = s->size;
+ n += s->size + 1;
}
- s = cdk_subpkt_find( sig->hashed, CDK_SIGSUBPKT_PREFS_HASH );
- if( s ) {
- hashalg = s->d;
- nhashalg = s->size;
- n += s->size + 1;
+ s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PREFS_HASH);
+ if (s)
+ {
+ hashalg = s->d;
+ nhashalg = s->size;
+ n += s->size + 1;
}
- s = cdk_subpkt_find( sig->hashed, CDK_SIGSUBPKT_PREFS_ZIP );
- if( s ) {
- compalg = s->d;
- ncompalg = s->size;
- n += s->size + 1;
+ s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PREFS_ZIP);
+ if (s)
+ {
+ compalg = s->d;
+ ncompalg = s->size;
+ n += s->size + 1;
}
- if( !n || !hashalg || !compalg || !symalg )
- uid->prefs = NULL;
- else {
- uid->prefs = cdk_calloc( 1, sizeof (*uid->prefs) * (n + 1) );
- if( !uid->prefs )
- return CDK_Out_Of_Core;
- n = 0;
- for( ; nsymalg; nsymalg--, n++ ) {
- uid->prefs[n].type = CDK_PREFTYPE_SYM;
- uid->prefs[n].value = *symalg++;
- }
- for( ; nhashalg; nhashalg--, n++ ) {
- uid->prefs[n].type = CDK_PREFTYPE_HASH;
- uid->prefs[n].value = *hashalg++;
+ if (uid->prefs != NULL)
+ cdk_free (uid->prefs);
+ if (!n || !hashalg || !compalg || !symalg)
+ uid->prefs = NULL;
+ else
+ {
+ uid->prefs = cdk_calloc (1, sizeof (*uid->prefs) * (n + 1));
+ if (!uid->prefs)
+ return CDK_Out_Of_Core;
+ n = 0;
+ for (; nsymalg; nsymalg--, n++)
+ {
+ uid->prefs[n].type = CDK_PREFTYPE_SYM;
+ uid->prefs[n].value = *symalg++;
}
- for( ; ncompalg; ncompalg--, n++ ) {
- uid->prefs[n].type = CDK_PREFTYPE_ZIP;
- uid->prefs[n].value = *compalg++;
+ for (; nhashalg; nhashalg--, n++)
+ {
+ uid->prefs[n].type = CDK_PREFTYPE_HASH;
+ uid->prefs[n].value = *hashalg++;
}
- /* end of list marker */
- uid->prefs[n].type = CDK_PREFTYPE_NONE;
- uid->prefs[n].value = 0;
- uid->prefs_size = n;
-
- kbnode = cdk_kbnode_find_prev( key, node, CDK_PKT_PUBLIC_KEY );
- if( kbnode ) {
- cdk_pkt_pubkey_t pk = kbnode->pkt->pkt.public_key;
- if( uid->prefs && n ) {
- pk->prefs = _cdk_copy_prefs( uid->prefs );
- pk->prefs_size = n;
- }
- if( key_expire ) {
- pk->expiredate = pk->timestamp + key_expire;
- pk->has_expired = pk->expiredate> _cdk_timestamp ()?0 :1;
- }
- if( key_usage && !pk->pubkey_usage )
- pk->pubkey_usage = key_usage;
- pk->is_invalid = 0;
+ for (; ncompalg; ncompalg--, n++)
+ {
+ uid->prefs[n].type = CDK_PREFTYPE_ZIP;
+ uid->prefs[n].value = *compalg++;
}
- }
+
+ uid->prefs[n].type = CDK_PREFTYPE_NONE; /* end of list marker */
+ uid->prefs[n].value = 0;
+ uid->prefs_size = n;
+ }
}
- return 0;
+
+ /* Now we add the extracted information to the primary key. */
+ kbnode = cdk_kbnode_find (key, CDK_PKT_PUBLIC_KEY);
+ if (kbnode)
+ {
+ cdk_pkt_pubkey_t pk = kbnode->pkt->pkt.public_key;
+ if (uid && uid->prefs && n)
+ {
+ if (pk->prefs != NULL)
+ cdk_free (pk->prefs);
+ pk->prefs = _cdk_copy_prefs (uid->prefs);
+ pk->prefs_size = n;
+ }
+ if (key_expire)
+ {
+ pk->expiredate = pk->timestamp + key_expire;
+ pk->has_expired = pk->expiredate> _cdk_timestamp ()?0 :1;
+ }
+
+ if (key_usage)
+ pk->pubkey_usage = key_usage;
+ pk->is_invalid = 0;
+ }
+
+ return 0;
}
-static int
-keydb_parse_allsigs( cdk_kbnode_t knode, cdk_keydb_hd_t hd, int check )
+static cdk_error_t
+keydb_parse_allsigs (cdk_kbnode_t knode, cdk_keydb_hd_t hd, int check)
{
- cdk_kbnode_t node, kb;
- cdk_pkt_signature_t sig;
- cdk_pkt_pubkey_t pk;
- struct cdk_subpkt_s * s = NULL;
- u32 expiredate = 0, curtime = _cdk_timestamp ();
- u32 keyid[2];
- int rc = 0;
-
- if( !knode )
- return CDK_Inv_Value;
- if( check && !hd )
- return CDK_Inv_Mode;
-
- kb = cdk_kbnode_find( knode, CDK_PKT_SECRET_KEY );
- if( kb )
- return 0;
-
- /* reset */
- for( node = knode; node; node = node->next ) {
- if( node->pkt->pkttype == CDK_PKT_USER_ID )
- node->pkt->pkt.user_id->is_revoked = 0;
- else if( node->pkt->pkttype == CDK_PKT_PUBLIC_KEY
- || node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY )
- node->pkt->pkt.public_key->is_revoked = 0;
- }
+ cdk_kbnode_t node, kb;
+ cdk_pkt_signature_t sig;
+ cdk_pkt_pubkey_t pk;
+ cdk_subpkt_t s=NULL;
+ u32 expiredate = 0, curtime = _cdk_timestamp ();
+ u32 keyid[2];
+
+ if (!knode)
+ return CDK_Inv_Value;
+ if (check && !hd)
+ return CDK_Inv_Mode;
+
+ kb = cdk_kbnode_find (knode, CDK_PKT_SECRET_KEY);
+ if (kb)
+ return 0;
- kb = cdk_kbnode_find( knode, CDK_PKT_PUBLIC_KEY );
- if( !kb )
- return CDK_Inv_Packet;
- cdk_pk_get_keyid( kb->pkt->pkt.public_key, keyid );
-
- for( node = knode; node; node = node->next) {
- if( node->pkt->pkttype == CDK_PKT_SIGNATURE ) {
- sig = node->pkt->pkt.signature;
- /* Revocation certificates for primary keys */
- if( sig->sig_class == 0x20 ) {
- kb = cdk_kbnode_find_prev( knode, node, CDK_PKT_PUBLIC_KEY );
- if( kb ) {
- kb->pkt->pkt.public_key->is_revoked = 1;
- if( check )
- _cdk_pk_check_sig (hd, kb, node, NULL);
+ /* Reset */
+ for (node = knode; node; node = node->next)
+ {
+ if (node->pkt->pkttype == CDK_PKT_USER_ID)
+ node->pkt->pkt.user_id->is_revoked = 0;
+ else if (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
+ node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
+ node->pkt->pkt.public_key->is_revoked = 0;
+ }
+
+ kb = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY);
+ if (!kb)
+ return CDK_Wrong_Format;
+ cdk_pk_get_keyid (kb->pkt->pkt.public_key, keyid);
+
+ for (node = knode; node; node = node->next)
+ {
+ if (node->pkt->pkttype == CDK_PKT_SIGNATURE)
+ {
+ sig = node->pkt->pkt.signature;
+ /* Revocation certificates for primary keys */
+ if (sig->sig_class == 0x20)
+ {
+ kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_KEY);
+ if (kb)
+ {
+ kb->pkt->pkt.public_key->is_revoked = 1;
+ if (check)
+ _cdk_pk_check_sig (hd, kb, node, NULL);
}
- else
- return CDK_Error_No_Key;
+ else
+ return CDK_Error_No_Key;
}
- /* Revocation certificates for subkeys */
- else if( sig->sig_class == 0x28 ) {
- kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_SUBKEY);
- if( kb ) {
- kb->pkt->pkt.public_key->is_revoked = 1;
- if( check )
- _cdk_pk_check_sig( hd, kb, node, NULL );
+ /* Revocation certificates for subkeys */
+ else if (sig->sig_class == 0x28)
+ {
+ kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_SUBKEY);
+ if (kb)
+ {
+ kb->pkt->pkt.public_key->is_revoked = 1;
+ if (check)
+ _cdk_pk_check_sig (hd, kb, node, NULL);
}
- else
- return CDK_Error_No_Key;
+ else
+ return CDK_Error_No_Key;
}
- /* Revocation certifcates for user ID's */
- else if( sig->sig_class == 0x30 ) {
- if( sig->keyid[0] != keyid[0] || sig->keyid[1] != keyid[1] )
- continue; /* revokes an earlier signature, no userID. */
- kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_USER_ID);
- if( kb ) {
- kb->pkt->pkt.user_id->is_revoked = 1;
- if( check )
- _cdk_pk_check_sig( hd, kb, node, NULL );
+ /* Revocation certifcates for user ID's */
+ else if (sig->sig_class == 0x30)
+ {
+ if( sig->keyid[0] != keyid[0] || sig->keyid[1] != keyid[1] )
+ continue; /* revokes an earlier signature, no userID. */
+ kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_USER_ID);
+ if (kb)
+ {
+ kb->pkt->pkt.user_id->is_revoked = 1;
+ if (check)
+ _cdk_pk_check_sig (hd, kb, node, NULL);
}
- else
- return CDK_Error_No_Key;
+ else
+ return CDK_Error_No_Key;
}
- /* Direct certificates for primary keys */
- else if( sig->sig_class == 0x1F ) {
- kb = cdk_kbnode_find_prev( knode, node, CDK_PKT_PUBLIC_KEY );
- if( kb ) {
- pk = kb->pkt->pkt.public_key;
- pk->is_invalid = 0;
- s = cdk_subpkt_find( node->pkt->pkt.signature->hashed,
- CDK_SIGSUBPKT_KEY_EXPIRE );
- if( s ) {
- expiredate = _cdk_buftou32( s->d );
- pk->expiredate = pk->timestamp + expiredate;
- pk->has_expired = pk->expiredate > curtime? 0 : 1;
+ /* Direct certificates for primary keys */
+ else if (sig->sig_class == 0x1F)
+ {
+ kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_KEY);
+ if (kb)
+ {
+ pk = kb->pkt->pkt.public_key;
+ pk->is_invalid = 0;
+ s = cdk_subpkt_find (node->pkt->pkt.signature->hashed,
+ CDK_SIGSUBPKT_KEY_EXPIRE);
+ if (s)
+ {
+ expiredate = _cdk_buftou32( s->d );
+ pk->expiredate = pk->timestamp + expiredate;
+ pk->has_expired = pk->expiredate > curtime? 0 : 1;
}
- if( check )
- _cdk_pk_check_sig( hd, kb, node, NULL );
+ if (check)
+ _cdk_pk_check_sig (hd, kb, node, NULL);
}
- else
- return CDK_Error_No_Key;
+ else
+ return CDK_Error_No_Key;
}
- /* Direct certificates for subkeys */
- else if( sig->sig_class == 0x18 ) {
- kb = cdk_kbnode_find_prev( knode, node, CDK_PKT_PUBLIC_SUBKEY);
- if( kb ) {
- pk = kb->pkt->pkt.public_key;
- pk->is_invalid = 0;
- s = cdk_subpkt_find( node->pkt->pkt.signature->hashed,
- CDK_SIGSUBPKT_KEY_EXPIRE );
- if( s ) {
- expiredate = _cdk_buftou32( s->d );
- pk->expiredate = pk->timestamp + expiredate;
- pk->has_expired = pk->expiredate > curtime? 0 : 1;
+ /* Direct certificates for subkeys */
+ else if( sig->sig_class == 0x18 )
+ {
+ kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_SUBKEY);
+ if (kb)
+ {
+ pk = kb->pkt->pkt.public_key;
+ pk->is_invalid = 0;
+ s = cdk_subpkt_find (node->pkt->pkt.signature->hashed,
+ CDK_SIGSUBPKT_KEY_EXPIRE);
+ if (s)
+ {
+ expiredate = _cdk_buftou32 (s->d);
+ pk->expiredate = pk->timestamp + expiredate;
+ pk->has_expired = pk->expiredate > curtime? 0 : 1;
}
- if( check )
- _cdk_pk_check_sig( hd, kb, node, NULL );
+ if (check)
+ _cdk_pk_check_sig (hd, kb, node, NULL);
}
- else
- return CDK_Error_No_Key;
- }
+ else
+ return CDK_Error_No_Key;
+ }
}
}
- node = cdk_kbnode_find( knode, CDK_PKT_PUBLIC_KEY );
- if( node && node->pkt->pkt.public_key->version == 3 ) {
- /* v3 public keys have no additonal signatures for the key directly.
- we say the key is valid when we have at least a self signature. */
- pk = node->pkt->pkt.public_key;
- for( node = knode; node; node = node->next ) {
- if( is_selfsig( node, keyid ) ) {
- pk->is_invalid = 0;
- break;
- }
- }
+ node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY);
+ if (node && node->pkt->pkt.public_key->version == 3)
+ {
+ /* v3 public keys have no additonal signatures for the key directly.
+ we say the key is valid when we have at least a self signature. */
+ pk = node->pkt->pkt.public_key;
+ for (node = knode; node; node = node->next)
+ {
+ if (is_selfsig (node, keyid))
+ {
+ pk->is_invalid = 0;
+ break;
+ }
+ }
}
- if( node && (node->pkt->pkt.public_key->is_revoked
- || node->pkt->pkt.public_key->has_expired) ) {
- /* if the primary key has been revoked, mark all subkeys as invalid
- because without a primary key they are not useable */
- for( node = knode; node; node = node->next ) {
- if( node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY )
- node->pkt->pkt.public_key->is_invalid = 1;
- }
+ if (node && (node->pkt->pkt.public_key->is_revoked ||
+ node->pkt->pkt.public_key->has_expired) )
+ {
+ /* If the primary key has been revoked, mark all subkeys as invalid
+ because without a primary key they are not useable */
+ for (node = knode; node; node = node->next)
+ {
+ if (node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
+ node->pkt->pkt.public_key->is_invalid = 1;
+ }
}
- return rc;
+
+ return 0;
}
cdk_error_t
-cdk_keydb_get_keyblock( cdk_stream_t inp, cdk_kbnode_t * r_knode )
+cdk_keydb_get_keyblock (cdk_stream_t inp, cdk_kbnode_t *r_knode)
{
- cdk_packet_t pkt = NULL;
- cdk_kbnode_t knode = NULL, node = NULL;
- cdk_desig_revoker_t revkeys = NULL;
- u32 keyid[2], main_keyid[2];
- int rc = 0, old_off;
- int key_seen = 0, got_key = 0;
-
- if( !inp || !r_knode )
- return CDK_Inv_Value;
-
- memset( keyid, 0, sizeof keyid );
- memset( main_keyid, 0, sizeof main_keyid );
-
- while( 1 ) {
- pkt = cdk_calloc( 1, sizeof *pkt );
- if( !pkt )
- return CDK_Out_Of_Core;
- old_off = cdk_stream_tell( inp );
- rc = cdk_pkt_read( inp, pkt );
- if( rc )
- break;
- if( pkt->pkttype == CDK_PKT_PUBLIC_KEY
- || pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY
- || pkt->pkttype == CDK_PKT_SECRET_KEY
- || pkt->pkttype == CDK_PKT_SECRET_SUBKEY) {
- if (key_seen && (pkt->pkttype == CDK_PKT_PUBLIC_KEY
- || pkt->pkttype == CDK_PKT_SECRET_KEY) ) {
- cdk_stream_seek( inp, old_off );
- break;
+ cdk_packet_t pkt;
+ cdk_kbnode_t knode, node;
+ cdk_desig_revoker_t revkeys;
+ u32 keyid[2], main_keyid[2];
+ off_t old_off;
+ int key_seen = 0, got_key = 0;
+ cdk_error_t rc;
+
+ if (!inp || !r_knode)
+ return CDK_Inv_Value;
+
+ keyid[0] = keyid[1] = 0;
+ main_keyid[0] = main_keyid[1] = 0;
+ revkeys = NULL;
+ knode = NULL;
+
+ *r_knode = NULL;
+ rc = CDK_EOF;
+ while (!cdk_stream_eof (inp))
+ {
+ cdk_pkt_new (&pkt);
+ old_off = cdk_stream_tell (inp);
+ rc = cdk_pkt_read (inp, pkt);
+ if (rc)
+ {
+ cdk_pkt_release (pkt);
+ if (rc == CDK_EOF)
+ break;
+ else
+ return rc;
+ }
+ if (pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
+ pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY ||
+ pkt->pkttype == CDK_PKT_SECRET_KEY ||
+ pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
+ {
+ if (key_seen && (pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
+ pkt->pkttype == CDK_PKT_SECRET_KEY))
+ {
+ /* The next key starts here so set the file pointer
+ and leave the loop. */
+ cdk_stream_seek (inp, old_off);
+ cdk_pkt_release (pkt);
+ break;
}
- if( pkt->pkttype == CDK_PKT_PUBLIC_KEY
- || pkt->pkttype == CDK_PKT_SECRET_KEY ) {
- _cdk_pkt_get_keyid( pkt, main_keyid );
- key_seen = 1;
- }
- else if( pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY
- || pkt->pkttype == CDK_PKT_SECRET_SUBKEY ) {
- if( pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY ) {
- pkt->pkt.public_key->main_keyid[0] = main_keyid[0];
- pkt->pkt.public_key->main_keyid[1] = main_keyid[1];
- }
- else {
- pkt->pkt.secret_key->main_keyid[0] = main_keyid[0];
- pkt->pkt.secret_key->main_keyid[1] = main_keyid[1];
- }
+ if (pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
+ pkt->pkttype == CDK_PKT_SECRET_KEY)
+ {
+ _cdk_pkt_get_keyid (pkt, main_keyid);
+ key_seen = 1;
}
- /* we save this for the signature */
- _cdk_pkt_get_keyid( pkt, keyid );
- got_key = 1;
- }
- else if( pkt->pkttype == CDK_PKT_USER_ID )
- ;
- else if( pkt->pkttype == CDK_PKT_SIGNATURE ) {
- pkt->pkt.signature->key[0] = keyid[0];
- pkt->pkt.signature->key[1] = keyid[1];
- if( pkt->pkt.signature->sig_class == 0x1F &&
- pkt->pkt.signature->revkeys )
- revkeys = pkt->pkt.signature->revkeys;
+ else if (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY ||
+ pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
+ {
+ if (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
+ {
+ pkt->pkt.public_key->main_keyid[0] = main_keyid[0];
+ pkt->pkt.public_key->main_keyid[1] = main_keyid[1];
+ }
+ else
+ {
+ pkt->pkt.secret_key->main_keyid[0] = main_keyid[0];
+ pkt->pkt.secret_key->main_keyid[1] = main_keyid[1];
+ }
+ }
+ /* We save this for the signature */
+ _cdk_pkt_get_keyid (pkt, keyid);
+ got_key = 1;
+ }
+ else if (pkt->pkttype == CDK_PKT_USER_ID)
+ ;
+ else if (pkt->pkttype == CDK_PKT_SIGNATURE)
+ {
+ pkt->pkt.signature->key[0] = keyid[0];
+ pkt->pkt.signature->key[1] = keyid[1];
+ if (pkt->pkt.signature->sig_class == 0x1F &&
+ pkt->pkt.signature->revkeys)
+ revkeys = pkt->pkt.signature->revkeys;
}
- node = cdk_kbnode_new( pkt );
- if( !knode )
- knode = node;
- else
- _cdk_kbnode_add( knode, node );
+ node = cdk_kbnode_new (pkt);
+ if (!knode)
+ knode = node;
+ else
+ _cdk_kbnode_add (knode, node);
}
-
- if( got_key ) {
- keydb_merge_selfsig( knode, main_keyid );
- rc = keydb_parse_allsigs( knode, NULL, 0 );
- if( revkeys ) {
- node = cdk_kbnode_find( knode, CDK_PKT_PUBLIC_KEY );
- if( node )
- node->pkt->pkt.public_key->revkeys = revkeys;
+
+ if (got_key)
+ {
+ keydb_merge_selfsig (knode, main_keyid);
+ rc = keydb_parse_allsigs (knode, NULL, 0);
+ if (revkeys)
+ {
+ node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY);
+ if (node)
+ node->pkt->pkt.public_key->revkeys = revkeys;
}
}
- *r_knode = got_key ? knode : NULL;
- return rc;
-}
-
-
-cdk_error_t
-cdk_keydb_pk_cache_sigs( cdk_kbnode_t pk, cdk_keydb_hd_t hd )
-{
- if( !pk || !hd )
- return CDK_Inv_Value;
- return keydb_parse_allsigs( pk, hd, 1 );
+ else
+ cdk_kbnode_release (knode);
+ *r_knode = got_key? knode : NULL;
+ if (rc == CDK_EOF && got_key)
+ rc = 0;
+ return rc;
}
static int
-classify_data( const byte * buf, size_t len )
+classify_data (const byte *buf, size_t len)
{
- int type = 0;
- int i;
-
- if( buf[0] == '0' && (buf[1] == 'x' || buf[1] == 'X') ) { /* hex prefix */
- buf += 2;
- len -= 2;
+ int type;
+ int i;
+
+ if (buf[0] == '0' && (buf[1] == 'x' || buf[1] == 'X'))
+ { /* Skip hex prefix. */
+ buf += 2;
+ len -= 2;
}
-
- if( len == 8 || len == 16 || len == 40 ) {
- for( i = 0; i < len; i++ ) {
- if( !isxdigit( buf[i] ) )
- break;
- }
- if( i == len ) {
- switch( len ) {
- case 8: type = CDK_DBSEARCH_SHORT_KEYID; break;
- case 16: type = CDK_DBSEARCH_KEYID; break;
- case 40: type = CDK_DBSEARCH_FPR; break;
- }
- }
+
+ if (len != 8 && len != 16 && len != 40)
+ return CDK_DBSEARCH_SUBSTR;
+
+ for (i = 0; i < len; i++)
+ {
+ if (!isxdigit (buf[i]))
+ return CDK_DBSEARCH_SUBSTR;
+ }
+ if (i != len)
+ return CDK_DBSEARCH_SUBSTR;
+ switch (len)
+ {
+ case 8: type = CDK_DBSEARCH_SHORT_KEYID; break;
+ case 16: type = CDK_DBSEARCH_KEYID; break;
+ case 40: type = CDK_DBSEARCH_FPR; break;
+ default: type = CDK_DBSEARCH_SUBSTR; break;
}
- if( !type )
- type = CDK_DBSEARCH_SUBSTR;
- return type;
+
+ return type;
}
cdk_error_t
-cdk_keydb_export( cdk_keydb_hd_t hd, cdk_stream_t out, cdk_strlist_t remusr )
+cdk_keydb_export (cdk_keydb_hd_t hd, cdk_stream_t out, cdk_strlist_t remusr)
{
- cdk_kbnode_t knode, node;
- cdk_strlist_t r;
- int old_ctb = 0;
- int rc = 0;
-
- for( r = remusr; r; r = r->next ) {
- rc = cdk_keydb_search_start( hd, CDK_DBSEARCH_AUTO, r->d );
- if( !rc )
- rc = cdk_keydb_search( hd, &knode );
- if( rc )
- break;
- for( node = knode; node; node = node->next ) {
- /* those packets are not intended for the real wolrd */
- if( node->pkt->pkttype == CDK_PKT_RING_TRUST )
- continue;
- /* we never export local signed signatures */
- if( node->pkt->pkttype == CDK_PKT_SIGNATURE &&
- !node->pkt->pkt.signature->flags.exportable )
- continue;
- /* filter out invalid signatures */
- if( node->pkt->pkttype == CDK_PKT_SIGNATURE
- && !KEY_CAN_SIGN (node->pkt->pkt.signature->pubkey_algo) )
- continue;
- if( node->pkt->pkttype == CDK_PKT_PUBLIC_KEY
- && node->pkt->pkt.public_key->version == 3 )
- old_ctb = 1;
- node->pkt->old_ctb = old_ctb;
- rc = cdk_pkt_write( out, node->pkt );
- if( rc )
- break;
+ cdk_kbnode_t knode, node;
+ cdk_strlist_t r;
+ int old_ctb = 0;
+ cdk_error_t rc;
+
+ for (r = remusr; r; r = r->next)
+ {
+ rc = cdk_keydb_search_start (hd, CDK_DBSEARCH_AUTO, r->d);
+ if (rc)
+ return rc;
+ rc = cdk_keydb_search (hd, &knode);
+ if (rc)
+ return rc;
+ for (node = knode; node; node = node->next)
+ {
+ /* No specified format; skip them */
+ if (node->pkt->pkttype == CDK_PKT_RING_TRUST)
+ continue;
+ /* We never export local signed signatures */
+ if (node->pkt->pkttype == CDK_PKT_SIGNATURE &&
+ !node->pkt->pkt.signature->flags.exportable)
+ continue;
+ /* Filter out invalid signatures */
+ if (node->pkt->pkttype == CDK_PKT_SIGNATURE &&
+ !KEY_CAN_SIGN (node->pkt->pkt.signature->pubkey_algo))
+ continue;
+ if (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY
+ && node->pkt->pkt.public_key->version == 3)
+ old_ctb = 1;
+ node->pkt->old_ctb = old_ctb;
+ rc = cdk_pkt_write (out, node->pkt);
+ if (rc)
+ {
+ cdk_kbnode_release (knode);
+ return rc;
+ }
}
- cdk_kbnode_release( knode );
- knode = NULL;
+ cdk_kbnode_release (knode);
+ knode = NULL;
}
- return rc;
+ return 0;
}
static cdk_packet_t
-find_key_packet( cdk_kbnode_t knode, int * r_is_sk )
+find_key_packet (cdk_kbnode_t knode, int *r_is_sk)
{
- cdk_packet_t pkt;
-
- pkt = cdk_kbnode_find_packet( knode, CDK_PKT_PUBLIC_KEY );
- if( !pkt ) {
- pkt = cdk_kbnode_find_packet( knode, CDK_PKT_SECRET_KEY );
- if( r_is_sk )
- *r_is_sk = pkt? 1 : 0;
+ cdk_packet_t pkt;
+
+ pkt = cdk_kbnode_find_packet (knode, CDK_PKT_PUBLIC_KEY);
+ if (!pkt)
+ {
+ pkt = cdk_kbnode_find_packet (knode, CDK_PKT_SECRET_KEY);
+ if (r_is_sk)
+ *r_is_sk = pkt? 1 : 0;
}
- return pkt;
+ return pkt;
}
cdk_error_t
-cdk_keydb_import( cdk_keydb_hd_t hd, cdk_kbnode_t knode, int *result )
+cdk_keydb_import (cdk_keydb_hd_t hd, cdk_kbnode_t knode)
{
- cdk_kbnode_t node, chk = NULL;
- cdk_packet_t pkt;
- cdk_stream_t out;
- u32 keyid[2];
- int rc = 0, is_sk = 0;
-
- if( !hd || !knode )
- return CDK_Inv_Value;
-
- memset( result, 0, 4 * sizeof (int) );
- pkt = find_key_packet( knode, &is_sk );
- if( !pkt )
- return CDK_Inv_Packet;
- result[is_sk] = 1;
- _cdk_pkt_get_keyid( pkt, keyid );
- cdk_keydb_get_bykeyid( hd, keyid, &chk );
- if( chk ) { /* fixme: search for new signatures */
- cdk_kbnode_release( chk );
- return 0;
- }
+ cdk_kbnode_t node, chk = NULL;
+ cdk_packet_t pkt;
+ cdk_stream_t out;
+ u32 keyid[2];
+ int is_sk = 0;
+ cdk_error_t rc;
+
+ /* FIXME: as a feedback we might have an additional function
+ like cdk_keydb_get_import_stats () */
+ if (!hd || !knode)
+ return CDK_Inv_Value;
+
+ pkt = find_key_packet (knode, &is_sk);
+ if (!pkt)
+ return CDK_Inv_Packet;
- if( hd->buf ) {
- cdk_stream_close( hd->buf );
- hd->buf = NULL;
+ _cdk_pkt_get_keyid (pkt, keyid);
+ cdk_keydb_get_bykeyid (hd, keyid, &chk);
+ if (chk)
+ { /* FIXME: search for new signatures */
+ cdk_kbnode_release (chk);
+ return 0;
}
-
- rc = _cdk_stream_append( hd->name, &out );
- if( rc )
- return rc;
- for( node = knode; node; node = node->next ) {
- if( node->pkt->pkttype == CDK_PKT_RING_TRUST )
- continue; /* No uniformed syntax for this packet */
- rc = cdk_pkt_write( out, node->pkt );
- if( rc )
- break;
+ if (hd->buf)
+ {
+ cdk_stream_close (hd->buf);
+ hd->buf = NULL;
}
- if( !rc )
- result[is_sk? 3 : 2] = 1;
- cdk_stream_close( out );
- if( !hd->no_cache )
- cdk_keydb_idx_rebuild( hd );
+
+ rc = _cdk_stream_append (hd->name, &out);
+ if (rc)
return rc;
+
+ for (node = knode; node; node = node->next)
+ {
+ if (node->pkt->pkttype == CDK_PKT_RING_TRUST)
+ continue; /* No uniformed syntax for this packet */
+ if (node->pkt->pkttype == CDK_PKT_SIGNATURE &&
+ !node->pkt->pkt.signature->flags.exportable)
+ {
+ _cdk_log_debug ("Key import: skip local signature\n");
+ continue;
+ }
+ rc = cdk_pkt_write (out, node->pkt);
+ if (rc)
+ {
+ cdk_stream_close (out);
+ return rc;
+ }
+ }
+
+ cdk_stream_close (out);
+ if (!hd->no_cache)
+ cdk_keydb_idx_rebuild (hd);
+ return 0;
}
int
-cdk_keydb_check_sk( cdk_keydb_hd_t hd, u32 * keyid )
+_cdk_keydb_check_userid (cdk_keydb_hd_t hd, u32 * keyid, const char *id)
{
- cdk_stream_t db;
- cdk_packet_t pkt;
- u32 kid[2];
- int rc;
+ cdk_kbnode_t knode = NULL, unode = NULL;
+ int check = 0;
+ cdk_error_t rc;
- if( !hd || !keyid )
- return CDK_Inv_Value;
- if( !hd->secret )
- return CDK_Inv_Mode;
- pkt = cdk_calloc( 1, sizeof * pkt );
- if( !pkt )
- return CDK_Out_Of_Core;
- rc = cdk_keydb_open( hd, &db );
- if( rc )
- return rc;
- cdk_pkt_init( pkt );
- while( !cdk_pkt_read( db, pkt ) ) {
- if( pkt->pkttype != CDK_PKT_SECRET_KEY
- && pkt->pkttype != CDK_PKT_SECRET_SUBKEY )
- goto next;
- cdk_sk_get_keyid( pkt->pkt.secret_key, kid );
- if( KEYID_CMP( kid, keyid ) ) {
- cdk_pkt_free( pkt );
- cdk_free( pkt );
- return 0;
+ if (!hd)
+ return CDK_Inv_Value;
+
+ rc = cdk_keydb_search_start (hd, CDK_DBSEARCH_KEYID, keyid);
+ if (rc)
+ return rc;
+ rc = cdk_keydb_search (hd, &knode);
+ if (rc)
+ return rc;
+
+ rc = cdk_keydb_search_start (hd, CDK_DBSEARCH_EXACT, (char *)id);
+ if (!rc)
+ rc = cdk_keydb_search (hd, &unode);
+ if (rc)
+ {
+ cdk_kbnode_release (knode);
+ return rc;
+ }
+
+ cdk_keydb_search_start (hd, CDK_DBSEARCH_KEYID, keyid);
+ if (unode && find_by_keyid (unode, hd->dbs))
+ check++;
+ cdk_kbnode_release (unode);
+
+ cdk_keydb_search_start (hd, CDK_DBSEARCH_EXACT, (char *)id);
+ if (knode && find_by_pattern (knode, hd->dbs))
+ check++;
+ cdk_kbnode_release (knode);
+
+ return check==2 ? 1 : 0;
+}
+
+
+cdk_error_t
+cdk_keydb_check_sk (cdk_keydb_hd_t hd, u32 *keyid)
+{
+ cdk_stream_t db;
+ cdk_packet_t pkt;
+ u32 kid[2];
+ cdk_error_t rc;
+
+ if (!hd || !keyid)
+ return CDK_Inv_Value;
+ if (!hd->secret)
+ return CDK_Inv_Mode;
+
+ rc = _cdk_keydb_open (hd, &db);
+ if (rc)
+ return rc;
+ cdk_pkt_new (&pkt);
+ while (!cdk_pkt_read (db, pkt))
+ {
+ if (pkt->pkttype != CDK_PKT_SECRET_KEY &&
+ pkt->pkttype != CDK_PKT_SECRET_SUBKEY)
+ {
+ cdk_pkt_free (pkt);
+ continue;
+ }
+ cdk_sk_get_keyid (pkt->pkt.secret_key, kid);
+ if (KEYID_CMP (kid, keyid))
+ {
+ cdk_pkt_release (pkt);
+ return 0;
}
- next:
- cdk_pkt_free( pkt );
- cdk_pkt_init( pkt );
+ cdk_pkt_free (pkt);
}
- cdk_free( pkt );
- return CDK_Error_No_Key;
+ cdk_pkt_release (pkt);
+ return CDK_Error_No_Key;
}
@@ -1627,39 +1973,41 @@ cdk_keydb_check_sk( cdk_keydb_hd_t hd, u32 * keyid )
* which should be listed.
**/
cdk_error_t
-cdk_listkey_start( cdk_listkey_t * r_ctx, cdk_keydb_hd_t db,
- const char * patt, cdk_strlist_t fpatt )
+cdk_listkey_start (cdk_listkey_t * r_ctx, cdk_keydb_hd_t db,
+ const char * patt, cdk_strlist_t fpatt)
{
- cdk_listkey_t ctx;
- cdk_stream_t inp;
- int rc;
+ cdk_listkey_t ctx;
+ cdk_stream_t inp;
+ cdk_error_t rc;
- if( !r_ctx || !db )
- return CDK_Inv_Value;
- if( (patt && fpatt) || (!patt && !fpatt) )
- return CDK_Inv_Mode;
- rc = cdk_keydb_open( db, &inp );
- if( rc )
- return rc;
- ctx = cdk_calloc( 1, sizeof * ctx );
- if( !ctx )
- return CDK_Out_Of_Core;
- ctx->db = db;
- ctx->inp = inp;
- if( patt ) {
- ctx->u.patt = cdk_strdup( patt );
- if( !ctx->u.patt )
- return CDK_Out_Of_Core;
+ if (!r_ctx || !db)
+ return CDK_Inv_Value;
+ if ((patt && fpatt) || (!patt && !fpatt))
+ return CDK_Inv_Mode;
+ rc = _cdk_keydb_open (db, &inp);
+ if (rc)
+ return rc;
+ ctx = cdk_calloc (1, sizeof *ctx);
+ if (!ctx)
+ return CDK_Out_Of_Core;
+ ctx->db = db;
+ ctx->inp = inp;
+ if (patt)
+ {
+ ctx->u.patt = cdk_strdup (patt);
+ if (!ctx->u.patt)
+ return CDK_Out_Of_Core;
}
- else if( fpatt ) {
- cdk_strlist_t l;
- for( l = fpatt; l; l = l->next )
- cdk_strlist_add( &ctx->u.fpatt, l->d );
+ else if (fpatt)
+ {
+ cdk_strlist_t l;
+ for (l = fpatt; l; l = l->next)
+ cdk_strlist_add (&ctx->u.fpatt, l->d);
}
- ctx->type = patt? 1 : 0;
- ctx->init = 1;
- *r_ctx = ctx;
- return 0;
+ ctx->type = patt? 1 : 0;
+ ctx->init = 1;
+ *r_ctx = ctx;
+ return 0;
}
@@ -1670,64 +2018,68 @@ cdk_listkey_start( cdk_listkey_t * r_ctx, cdk_keydb_hd_t db,
* Free the list key context.
**/
void
-cdk_listkey_close( cdk_listkey_t ctx )
+cdk_listkey_close (cdk_listkey_t ctx)
{
- if( ctx ) {
- if( ctx->type )
- cdk_free( ctx->u.patt );
- else
- cdk_strlist_free( ctx->u.fpatt );
- cdk_free( ctx );
- }
+ if (!ctx)
+ return;
+
+ if (ctx->type)
+ cdk_free (ctx->u.patt);
+ else
+ cdk_strlist_free (ctx->u.fpatt);
+ cdk_free (ctx);
}
/**
* cdk_listkey_next:
* @ctx: list key context
- * @ret_key: the pointer to the new key node object
+ * @r_key: the pointer to the new key node object
*
* Retrieve the next key from the pattern of the key list context.
**/
cdk_error_t
-cdk_listkey_next( cdk_listkey_t ctx, cdk_kbnode_t * ret_key )
+cdk_listkey_next (cdk_listkey_t ctx, cdk_kbnode_t *ret_key)
{
- if( !ctx || !ret_key )
- return CDK_Inv_Value;
- if( !ctx->init )
- return CDK_Inv_Mode;
-
- if( ctx->type && ctx->u.patt[0] == '*' )
- return cdk_keydb_get_keyblock( ctx->inp, ret_key );
- else if( ctx->type ) {
- cdk_kbnode_t node;
- struct cdk_dbsearch_s ks;
- int rc;
-
- for( ;; ) {
- rc = cdk_keydb_get_keyblock( ctx->inp, &node );
- if( rc )
- return rc;
- memset( &ks, 0, sizeof ks );
- ks.type = CDK_DBSEARCH_SUBSTR;
- ks.u.pattern = ctx->u.patt;
- if( find_by_pattern( node, &ks ) ) {
- *ret_key = node;
- return 0;
- }
- cdk_kbnode_release( node );
- node = NULL;
+ if (!ctx || !ret_key)
+ return CDK_Inv_Value;
+ if (!ctx->init)
+ return CDK_Inv_Mode;
+
+ if (ctx->type && ctx->u.patt[0] == '*' )
+ return cdk_keydb_get_keyblock( ctx->inp, ret_key );
+ else if (ctx->type)
+ {
+ cdk_kbnode_t node;
+ struct cdk_dbsearch_s ks;
+ cdk_error_t rc;
+
+ for (;;)
+ {
+ rc = cdk_keydb_get_keyblock (ctx->inp, &node);
+ if (rc)
+ return rc;
+ memset (&ks, 0, sizeof (ks));
+ ks.type = CDK_DBSEARCH_SUBSTR;
+ ks.u.pattern = ctx->u.patt;
+ if (find_by_pattern (node, &ks))
+ {
+ *ret_key = node;
+ return 0;
+ }
+ cdk_kbnode_release (node);
+ node = NULL;
}
}
- else {
- if( !ctx->t )
- ctx->t = ctx->u.fpatt;
- else if( ctx->t->next )
- ctx->t = ctx->t->next;
- else
- return CDK_EOF;
- return cdk_keydb_get_bypattern( ctx->db, ctx->t->d, ret_key );
+ else
+ {
+ if (!ctx->t)
+ ctx->t = ctx->u.fpatt;
+ else if (ctx->t->next)
+ ctx->t = ctx->t->next;
+ else
+ return CDK_EOF;
+ return cdk_keydb_get_bypattern (ctx->db, ctx->t->d, ret_key);
}
- return CDK_General_Error;
+ return CDK_General_Error;
}
-
diff --git a/libextra/opencdk/keygen.c b/libextra/opencdk/keygen.c
deleted file mode 100644
index 18dd6730d3..0000000000
--- a/libextra/opencdk/keygen.c
+++ /dev/null
@@ -1,872 +0,0 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * keygen.c - OpenPGP key generation
- * Copyright (C) 2006 Free Software Foundation, Inc.
- * Copyright (C) 2002, 2003 Timo Schulz
- *
- * This file is part of OpenCDK.
- *
- * OpenCDK is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * OpenCDK is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include <stdio.h>
-
-#include "opencdk.h"
-#include "main.h"
-#include "packet.h"
-#include "cipher.h"
-#include "types.h"
-
-struct key_ctx_s {
- u32 expire_date;
- int algo;
- int len;
- gcry_mpi_t resarr[6];
- size_t n;
- cdk_pkt_pubkey_t pk;
- cdk_pkt_seckey_t sk;
-};
-
-
-struct cdk_keygen_ctx_s {
- char * user_id;
- cdk_pkt_userid_t id;
- byte * sym_prefs;
- size_t sym_len;
- byte * hash_prefs;
- size_t hash_len;
- byte * zip_prefs;
- size_t zip_len;
- unsigned mdc_feature:1;
- unsigned ks_no_modify:1;
- char * ks_pref_url;
- cdk_pkt_signature_t sig;
- unsigned protect:1;
- struct key_ctx_s key[2];
- char * pass;
- size_t pass_len;
-};
-
-
-/* default preferences */
-static byte def_sym_prefs[] = {CDK_CIPHER_AES, CDK_CIPHER_CAST5,
- CDK_CIPHER_TWOFISH, CDK_CIPHER_AES192,
- CDK_CIPHER_AES256, CDK_CIPHER_3DES,
- CDK_CIPHER_BLOWFISH};
-static byte def_hash_prefs[] = {CDK_MD_SHA1, CDK_MD_RMD160, CDK_MD_MD5};
-static byte def_zip_prefs[] = {CDK_COMPRESS_ZIP, CDK_COMPRESS_ZLIB};
-
-
-static int
-check_pref_array( const byte * p, size_t n, int type )
-{
- int i;
-
- if( !p )
- return 0;
-
- if( type == CDK_PREFTYPE_SYM ) {
- for( i = 0; i < n; i++ ) {
- if( cdk_cipher_test_algo( p[i] ) )
- return -1;
- }
- }
- else if( type == CDK_PREFTYPE_HASH ) {
- for( i = 0; i < n; i++ ) {
- if( cdk_md_test_algo( p[i] ) )
- return -1;
- }
- }
- else if( type == CDK_PREFTYPE_ZIP ) {
- if( n > 2 )
- return -1;
- if( p[0] > 2 || p[1] > 2 )
- return -1;
- }
- else
- return -1;
- return 0;
-}
-
-
-/**
- * cdk_keygen_set_prefs: Set the preferences for the userID
- * @hd: the keygen object
- * @type: the preference type
- * @array: one-octet array with algorithm numers
- * @n: length of @array.
- *
- **/
-cdk_error_t
-cdk_keygen_set_prefs( cdk_keygen_ctx_t hd, enum cdk_pref_type_t type,
- const byte * array, size_t n )
-{
- int rc;
-
- if( !hd )
- return CDK_Inv_Value;
-
- rc = check_pref_array( array, n, type );
- if( rc )
- return CDK_Inv_Value;
-
- switch( type) {
- case CDK_PREFTYPE_SYM:
- hd->sym_len = array? n : DIM( def_sym_prefs );
- hd->sym_prefs = cdk_calloc( 1, hd->sym_len );
- if( hd->sym_prefs )
- memcpy( hd->sym_prefs, array? array : def_sym_prefs, hd->sym_len );
- break;
-
- case CDK_PREFTYPE_HASH:
- hd->hash_len = array? n : DIM( def_hash_prefs );
- hd->hash_prefs = cdk_calloc( 1, hd->hash_len );
- if( hd->hash_prefs )
- memcpy( hd->hash_prefs, array? array : def_hash_prefs,
- hd->hash_len );
- break;
-
- case CDK_PREFTYPE_ZIP:
- hd->zip_len = array? n : DIM( def_zip_prefs );
- hd->zip_prefs = cdk_calloc( 1, hd->zip_len );
- if( hd->zip_prefs )
- memcpy( hd->zip_prefs, array? array : def_zip_prefs, hd->zip_len );
- break;
-
- default:
- return CDK_Inv_Mode;
- }
-
- return 0;
-}
-
-
-/**
- * cdk_keygen_set_name: set the userid name for the key
- * @hd: the keygen object
- * @name: name
- *
- * The name will be encoded in UTF8 to avoid problems.
- **/
-void
-cdk_keygen_set_name( cdk_keygen_ctx_t hd, const char * name )
-{
- if( hd ) {
- cdk_free( hd->user_id );
- hd->user_id = cdk_utf8_encode( name );
- }
-}
-
-
-static int
-check_bits( int bits, int algo )
-{
- if( bits < 768 )
- return 768;
- if( algo == CDK_PK_DSA && bits > 1024 )
- return 1024;
- if( bits > 4096 )
- return 4096;
- return bits;
-}
-
-
-/**
- * cdk_keygen_set_algo_info: set the length and type of the key
- * @hd: the keygen object.
- * @type: key type (primary=0, subkey=1)
- * @algo: algorithm compliant with rfc2440
- * @bits: lengt of the key in bits
- *
- **/
-cdk_error_t
-cdk_keygen_set_algo_info( cdk_keygen_ctx_t hd, int type,
- enum cdk_pk_algo_t algo, int bits )
-{
- int rc;
- int usage = type? PK_USAGE_ENCR : PK_USAGE_SIGN;
-
- if( !hd )
- return CDK_Inv_Value;
- if( type < 0 || type > 1 )
- return CDK_Inv_Value;
-
- if( bits % 128 != 0 )
- bits = bits + ( bits % 128 );
-
- rc = _cdk_pk_test_algo( algo, usage );
- if( rc )
- return rc;
-
- /* type=0 primary type=1 sub */
- hd->key[type].algo = algo;
- hd->key[type].len = check_bits( bits, algo );
-
- return 0;
-}
-
-
-/**
- * cdk_keygen_set_mdc_feature: set the mdc feature for the key
- * @hd: keygen object
- * @val: boolean( yes=1, no=0)
- *
- * if you want a RFC2440 compliant key, you've to disable this feature
- * until the rfc2440-bis8 becomes the next standard.
- **/
-void
-cdk_keygen_set_mdc_feature( cdk_keygen_ctx_t hd, int val )
-{
- if( hd )
- hd->mdc_feature = val;
-}
-
-
-
-void
-cdk_keygen_set_keyserver_flags( cdk_keygen_ctx_t hd, int no_modify,
- const char *pref_url )
-{
- if( no_modify )
- hd->ks_no_modify = 1;
- if( pref_url )
- hd->ks_pref_url = cdk_strdup( pref_url );
-} /* cdk_keygen_set_keyserver_flags */
-
-
-/**
- * cdk_keygen_set_expire_date: set the expire date of the primary key
- * @hd: keygen object
- * @type: key type( 0=primary, 1=seconardy)
- * @timestamp: the date the key should expire
- *
- **/
-void
-cdk_keygen_set_expire_date( cdk_keygen_ctx_t hd, int type, long int timestamp )
-{
- if( !hd )
- return;
- if( type < 0 || type > 1 )
- return;
- if( timestamp < 0 || timestamp < _cdk_timestamp( ) )
- timestamp = 0;
- hd->key[type].expire_date = timestamp;
-}
-
-
-void
-cdk_keygen_set_passphrase( cdk_keygen_ctx_t hd, const char * pass )
-{
- if( !hd )
- return;
- if( pass ) {
- size_t n = strlen( pass );
- _cdk_sec_free( hd->pass, hd->pass_len );
- hd->pass = cdk_salloc( n + 1, 1 );
- if( hd->pass ) {
- memcpy( hd->pass, pass, n );
- hd->pass[n] = '\0';
- hd->pass_len = n;
- hd->protect = 1;
- }
- }
-}
-
-
-static int
-read_single_mpi( gcry_sexp_t s_key, const char * val, gcry_mpi_t * r_resarr )
-{
- gcry_sexp_t list;
-
- if( !r_resarr )
- return CDK_Inv_Value;
- list = gcry_sexp_find_token( s_key, val, 0 );
- if( list )
- *r_resarr = gcry_sexp_nth_mpi( list, 1, 0 );
- gcry_sexp_release( list );
- return list? 0 : CDK_Gcry_Error;
-}
-
-
-static int
-read_dsa_key( gcry_sexp_t s_key, gcry_mpi_t * resarr )
-{
- int rc = read_single_mpi( s_key, "p", &resarr[0] );
- if( !rc )
- rc = read_single_mpi( s_key, "q", &resarr[1] );
- if( !rc )
- rc = read_single_mpi( s_key, "g", &resarr[2] );
- if( !rc )
- rc = read_single_mpi( s_key, "y", &resarr[3] );
- if( !rc )
- rc = read_single_mpi( s_key, "x", &resarr[4] );
- return rc;
-}
-
-
-static int
-read_elg_key( gcry_sexp_t s_key, gcry_mpi_t * resarr )
-{
- int rc = read_single_mpi( s_key, "p", &resarr[0] );
- if( !rc )
- rc = read_single_mpi( s_key, "g", &resarr[1] );
- if( !rc )
- rc = read_single_mpi( s_key, "y", &resarr[2] );
- if( !rc )
- rc = read_single_mpi( s_key, "x", &resarr[3] );
- return rc;
-}
-
-
-static int
-read_rsa_key( gcry_sexp_t s_key, gcry_mpi_t * resarr )
-{
- int rc = read_single_mpi( s_key, "n", &resarr[0] );
- if( !rc )
- rc =read_single_mpi( s_key, "e", &resarr[1] );
- if( !rc )
- rc = read_single_mpi( s_key, "d", &resarr[2] );
- if( !rc )
- rc = read_single_mpi( s_key, "p", &resarr[3] );
- if( !rc )
- rc = read_single_mpi( s_key, "q", &resarr[4] );
- if( !rc )
- rc = read_single_mpi( s_key, "u", &resarr[5] );
- return rc;
-}
-
-
-static int
-generate_subkey( cdk_keygen_ctx_t hd )
-{
- gcry_sexp_t s_params = NULL, s_key;
- size_t n = hd->key[1].len;
- int rc;
-
- if( !hd )
- return CDK_Inv_Value;
-
- if( is_DSA( hd->key[1].algo) )
- rc = gcry_sexp_build( &s_params, NULL, "(genkey(dsa(nbits %d)))", n );
- else if( is_ELG( hd->key[1].algo) )
- rc = gcry_sexp_build( &s_params, NULL, "(genkey(elg(nbits %d)))", n );
- else if( is_RSA( hd->key[1].algo) )
- rc = gcry_sexp_build( &s_params, NULL, "(genkey(rsa(nbits %d)))", n );
- else
- rc = CDK_Inv_Algo;
- if( !rc )
- rc = gcry_pk_genkey( &s_key, s_params );
- gcry_sexp_release( s_params );
- if( !rc ) {
- if( is_DSA( hd->key[1].algo) )
- rc = read_dsa_key( s_key, hd->key[1].resarr );
- else if( is_ELG( hd->key[1].algo) )
- rc = read_elg_key( s_key, hd->key[1].resarr );
- else if( is_RSA( hd->key[1].algo) )
- rc = read_rsa_key( s_key, hd->key[1].resarr );
- }
- hd->key[1].n = cdk_pk_get_npkey( hd->key[1].algo );
- gcry_sexp_release( s_key );
- return rc;
-}
-
-
-/**
- * cdk_keygen_start: kick off the key generation
- * @hd: the keygen object
- *
- **/
-cdk_error_t
-cdk_keygen_start( cdk_keygen_ctx_t hd )
-{
- gcry_sexp_t s_params = NULL, s_key = NULL;
- size_t n;
- int rc = 0;
-
- if( !hd || !hd->user_id )
- return CDK_Inv_Value;
- if( is_ELG( hd->key[0].algo ) )
- return CDK_Inv_Mode;
- if( !hd->key[0].len )
- hd->key[0].len = 1024;
- n = hd->key[0].len;
-
- if( !hd->sym_prefs )
- cdk_keygen_set_prefs( hd, CDK_PREFTYPE_SYM, NULL, 0 );
- if( !hd->hash_prefs )
- cdk_keygen_set_prefs( hd, CDK_PREFTYPE_HASH, NULL, 0 );
- if( !hd->zip_prefs )
- cdk_keygen_set_prefs( hd, CDK_PREFTYPE_ZIP, NULL, 0 );
-
- if( is_DSA( hd->key[0].algo ) )
- rc = gcry_sexp_build( &s_params, NULL, "(genkey(dsa(nbits %d)))", n );
- else if( is_RSA( hd->key[0].algo ) )
- rc = gcry_sexp_build( &s_params, NULL, "(genkey(rsa(nbits %d)))", n );
- else
- rc = CDK_Inv_Algo;
- if( !rc )
- rc = gcry_pk_genkey( &s_key, s_params );
- gcry_sexp_release( s_params );
- if( !rc ) {
- if( is_DSA( hd->key[0].algo ) )
- rc = read_dsa_key( s_key, hd->key[0].resarr );
- else if( is_RSA( hd->key[0].algo ) )
- rc = read_rsa_key( s_key, hd->key[0].resarr );
- hd->key[0].n = cdk_pk_get_npkey( hd->key[0].algo );
- }
- gcry_sexp_release( s_key );
- if( !rc ) {
- if( hd->key[1].algo && hd->key[1].len )
- rc = generate_subkey( hd );
- }
- return rc;
-}
-
-
-static int
-gcry_mpi_to_native( cdk_keygen_ctx_t hd, size_t nkey, int type,
- cdk_pkt_pubkey_t pk, cdk_pkt_seckey_t sk )
-{
- gcry_mpi_t * resarr;
- cdk_mpi_t a = NULL;
- size_t nbytes;
- int i = 0, j = 0, nbits;
- int rc = 0;
-
- if( !hd )
- return CDK_Inv_Value;
- if( !pk && !sk )
- return CDK_Inv_Value;
- if( type < 0 || type > 1 )
- return CDK_Inv_Value;
-
- resarr = hd->key[type].resarr;
- if( sk )
- i += cdk_pk_get_npkey( sk->pubkey_algo );
- while( j != nkey ) {
- nbits = gcry_mpi_get_nbits( resarr[i] );
- if( pk )
- a = cdk_calloc( 1, sizeof * a + (nbits + 7) / 8 + 2 + 1 );
- else if( sk )
- a = cdk_salloc( sizeof * a + (nbits + 7) / 8 + 2 + 1, 1 );
- a->bits = nbits;
- a->bytes = ( nbits + 7 ) / 8;
- nbytes = a->bytes;
- a->data[0] = nbits >> 8;
- a->data[1] = nbits;
- rc = gcry_mpi_print( GCRYMPI_FMT_USG, a->data+2, nbytes, &nbytes, resarr[i] );
- if( rc )
- break;
- if( pk )
- pk->mpi[j++] = a;
- else if( sk )
- sk->mpi[j++] = a;
- i++;
- }
- return rc;
-}
-
-
-static cdk_pkt_pubkey_t
-pk_create( cdk_keygen_ctx_t hd, int type )
-{
- cdk_pkt_pubkey_t pk;
- int rc = 0, npkey = 0;
-
- if( type < 0 || type > 1 )
- return NULL;
- pk = cdk_calloc( 1, sizeof * pk );
- if( !pk )
- return NULL;
- pk->version = 4;
- pk->pubkey_algo = hd->key[type].algo;
- pk->timestamp = _cdk_timestamp( );
- if( hd->key[type].expire_date )
- pk->expiredate = pk->timestamp + hd->key[type].expire_date;
- npkey = cdk_pk_get_npkey( pk->pubkey_algo );
- rc = gcry_mpi_to_native( hd, npkey, type, pk, NULL );
- if( rc ) {
- cdk_free( pk );
- pk = NULL;
- }
- return pk;
-}
-
-
-static cdk_pkt_seckey_t
-sk_create( cdk_keygen_ctx_t hd, int type )
-{
- cdk_pkt_seckey_t sk;
- int nskey, rc = 0;
-
- if( type < 0 || type > 1 )
- return NULL;
- sk = cdk_calloc( 1, sizeof * sk );
- if( !sk )
- return NULL;
- _cdk_copy_pubkey( &sk->pk, hd->key[type].pk );
- sk->version = 4;
- sk->pubkey_algo = hd->key[type].algo;
- sk->csum = 0;
- sk->is_protected = 0;
- nskey = cdk_pk_get_nskey( sk->pubkey_algo );
- rc = gcry_mpi_to_native( hd, nskey, type, NULL, sk );
- if( rc ) {
- cdk_free( sk );
- sk = NULL;
- }
- return sk;
-}
-
-
-static cdk_pkt_userid_t
-uid_create( cdk_keygen_ctx_t hd )
-{
- cdk_pkt_userid_t id;
-
- if( !hd->user_id )
- return NULL;
- id = cdk_calloc( 1, sizeof * id + strlen( hd->user_id ) + 1 );
- if( !id )
- return NULL;
- strcpy( id->name, hd->user_id );
- id->len = strlen( hd->user_id );
- return id;
-}
-
-
-static cdk_pkt_signature_t
-sig_subkey_create( cdk_keygen_ctx_t hd )
-{
- cdk_md_hd_t md;
- cdk_subpkt_t node;
- cdk_pkt_signature_t sig;
- cdk_pkt_pubkey_t pk = hd->key[0].pk;
- cdk_pkt_pubkey_t sub_pk = hd->key[1].pk;
- cdk_pkt_seckey_t sk = hd->key[0].sk;
- byte buf[4];
- int rc;
-
- sig = cdk_calloc( 1, sizeof * sig );
- if( !sig )
- return NULL;
- _cdk_sig_create( pk, sig );
- sig->sig_class = 0x18;
- sig->digest_algo = CDK_MD_SHA1;
-
- if( sub_pk->expiredate ) {
- _cdk_u32tobuf( sub_pk->expiredate - sub_pk->timestamp, buf );
- node = cdk_subpkt_new( 4 );
- if( node ) {
- cdk_subpkt_init( node, CDK_SIGSUBPKT_KEY_EXPIRE, buf, 4 );
- cdk_subpkt_add( sig->hashed, node );
- }
- }
-
- md = cdk_md_open( sig->digest_algo, 0 );
- if( !md ) {
- _cdk_free_signature( sig );
- return NULL;
- }
-
- _cdk_hash_pubkey( pk, md, 0 );
- _cdk_hash_pubkey( sub_pk, md, 0 );
- rc = _cdk_sig_complete( sig, sk, md );
- cdk_md_close( md );
- if( rc ) {
- _cdk_free_signature( sig );
- return NULL;
- }
- return sig;
-}
-
-
-static cdk_pkt_signature_t
-sig_self_create( cdk_keygen_ctx_t hd )
-{
- cdk_md_hd_t md;
- cdk_subpkt_t node;
- cdk_pkt_signature_t sig;
- cdk_pkt_pubkey_t pk = hd->key[0].pk;
- cdk_pkt_userid_t id = hd->id;
- cdk_pkt_seckey_t sk = hd->key[0].sk;
- u32 keyid[2];
- byte buf[8], * p;
- int rc;
-
- sig = cdk_calloc( 1, sizeof * sig );
- if( !sig )
- return NULL;
- sig->version = 4;
- sig->timestamp = _cdk_timestamp( );
- sig->sig_class = 0x13;
- sig->pubkey_algo = hd->key[0].algo;
- sig->digest_algo = CDK_MD_SHA1;
-
- _cdk_u32tobuf( sig->timestamp, buf );
- sig->hashed = node = cdk_subpkt_new( 4 );
- if( node )
- cdk_subpkt_init( node, CDK_SIGSUBPKT_SIG_CREATED, buf, 4 );
-
- p = hd->sym_prefs;
- node = cdk_subpkt_new( hd->sym_len + 1 );
- if( node ) {
- cdk_subpkt_init( node, CDK_SIGSUBPKT_PREFS_SYM, p, hd->sym_len );
- cdk_subpkt_add( sig->hashed, node );
- }
-
- p = hd->hash_prefs;
- node = cdk_subpkt_new( hd->hash_len + 1 );
- if( node ) {
- cdk_subpkt_init( node, CDK_SIGSUBPKT_PREFS_HASH, p, hd->hash_len );
- cdk_subpkt_add( sig->hashed, node );
- }
-
- p = hd->zip_prefs;
- node = cdk_subpkt_new( hd->zip_len + 1 );
- if( node ) {
- cdk_subpkt_init( node, CDK_SIGSUBPKT_PREFS_ZIP, p, hd->zip_len );
- cdk_subpkt_add( sig->hashed, node );
- }
-
- if( hd->mdc_feature ) {
- buf[0] = 0x01;
- node = cdk_subpkt_new( 1 );
- if( node ) {
- cdk_subpkt_init( node, CDK_SIGSUBPKT_FEATURES, buf, 1 );
- cdk_subpkt_add( sig->hashed, node );
- }
- }
-
- if( hd->ks_no_modify ) {
- buf[0] = 0x80;
- node = cdk_subpkt_new( 1 );
- if( node ) {
- cdk_subpkt_init( node, CDK_SIGSUBPKT_KS_FLAGS, buf, 1 );
- cdk_subpkt_add( sig->hashed, node );
- }
- }
-
- if( hd->ks_pref_url ) {
- node = cdk_subpkt_new( strlen( hd->ks_pref_url ) + 1 );
- if( node ) {
- cdk_subpkt_init( node, CDK_SIGSUBPKT_PREF_KS,
- hd->ks_pref_url, strlen( hd->ks_pref_url ) );
- cdk_subpkt_add( sig->hashed, node );
- }
- }
-
- if( pk->expiredate ) {
- node = cdk_subpkt_new( 4 );
- if( node ) {
- _cdk_u32tobuf( pk->expiredate - pk->timestamp, buf );
- cdk_subpkt_init( node, CDK_SIGSUBPKT_KEY_EXPIRE, buf, 4 );
- cdk_subpkt_add( sig->hashed, node );
- }
- }
-
- sig->unhashed = node = cdk_subpkt_new( 8 );
- if( node ) {
- cdk_pk_get_keyid( pk, keyid );
- _cdk_u32tobuf( keyid[0], buf );
- _cdk_u32tobuf( keyid[1], buf + 4 );
- cdk_subpkt_init( node, CDK_SIGSUBPKT_ISSUER, buf, 8 );
- }
-
- md = cdk_md_open( sig->digest_algo, 0 );
- if( !md ) {
- _cdk_free_signature( sig );
- return NULL;
- }
-
- _cdk_hash_pubkey( pk, md, 0 );
- _cdk_hash_userid( id, sig->version == 4, md );
- rc = _cdk_sig_complete( sig, sk, md );
- cdk_md_close( md );
- if( rc ) {
- _cdk_free_signature( sig );
- return NULL;
- }
- return sig;
-}
-
-
-/**
- * cdk_keygen_save: save the generated keys to disk
- * @hd: the keygen object
- * @pubf: name of the file to store the public key
- * @secf: name of the file to store the secret key
- *
- **/
-cdk_error_t
-cdk_keygen_save( cdk_keygen_ctx_t hd, const char * pubf, const char * secf )
-{
- cdk_stream_t out = NULL;
- CDK_PACKET pkt;
- int rc;
-
- hd->key[0].pk = pk_create( hd, 0 );
- if( !hd->key[0].pk )
- return CDK_Inv_Packet;
- hd->key[0].sk = sk_create( hd, 0 );
- if( !hd->key[0].sk )
- return CDK_Inv_Packet;
- hd->id = uid_create( hd );
- if( !hd->id )
- return CDK_Inv_Packet;
- hd->sig = sig_self_create( hd );
- if( !hd->sig )
- return CDK_Inv_Packet;
-
- rc = cdk_stream_create( pubf, &out );
- if( rc )
- return rc;
-
- cdk_pkt_init( &pkt );
- pkt.pkttype = CDK_PKT_PUBLIC_KEY;
- pkt.pkt.public_key = hd->key[0].pk;
- rc = cdk_pkt_write( out, &pkt );
- if( rc )
- goto fail;
-
- cdk_pkt_init( &pkt );
- pkt.pkttype = CDK_PKT_USER_ID;
- pkt.pkt.user_id = hd->id;
- rc = cdk_pkt_write( out, &pkt );
- if( rc )
- goto fail;
-
- cdk_pkt_init( &pkt );
- pkt.pkttype = CDK_PKT_SIGNATURE;
- pkt.pkt.signature = hd->sig;
- rc = cdk_pkt_write( out, &pkt );
- if( rc )
- goto fail;
-
- if( hd->key[1].algo ) {
- cdk_pkt_init( &pkt );
- pkt.pkttype = CDK_PKT_PUBLIC_SUBKEY;
- pkt.pkt.public_key = hd->key[1].pk = pk_create( hd, 1 );
- rc = cdk_pkt_write( out, &pkt );
- if( rc )
- goto fail;
-
- cdk_pkt_init( &pkt );
- pkt.pkttype = CDK_PKT_SIGNATURE;
- pkt.pkt.signature = sig_subkey_create( hd );
- rc = cdk_pkt_write( out, &pkt );
- cdk_pkt_free( &pkt );
- if( rc )
- goto fail;
- }
-
- cdk_stream_close( out );
- out = NULL;
-
- rc = cdk_stream_create( secf, &out );
- if( rc )
- goto fail;
-
- if( hd->protect ) {
- rc = cdk_sk_protect( hd->key[0].sk, hd->pass );
- if( rc )
- goto fail;
- }
-
- cdk_pkt_init( &pkt );
- pkt.pkttype = CDK_PKT_SECRET_KEY;
- pkt.pkt.secret_key = hd->key[0].sk;
- rc = cdk_pkt_write( out, &pkt );
- if( rc )
- goto fail;
-
- cdk_pkt_init( &pkt );
- pkt.pkttype = CDK_PKT_USER_ID;
- pkt.pkt.user_id = hd->id;
- rc = cdk_pkt_write( out, &pkt );
- if( rc )
- goto fail;
-
- cdk_pkt_init( &pkt );
- pkt.pkttype = CDK_PKT_SIGNATURE;
- pkt.pkt.signature = hd->sig;
- rc = cdk_pkt_write( out, &pkt );
- if( rc )
- goto fail;
-
- if( hd->key[1].algo ) {
- hd->key[1].sk = sk_create( hd, 1 );
- if( hd->protect && (rc = cdk_sk_protect( hd->key[1].sk, hd->pass )) )
- goto fail;
- cdk_pkt_init( &pkt );
- pkt.pkttype = CDK_PKT_SECRET_SUBKEY;
- pkt.pkt.secret_key = hd->key[1].sk;
- rc = cdk_pkt_write( out, &pkt );
- if( rc )
- goto fail;
- }
-
- fail:
- cdk_stream_close( out );
- return rc;
-}
-
-
-/**
- * cdk_keygen_free: free the keygen object
- * @hd: the keygen object
- *
- **/
-void
-cdk_keygen_free( cdk_keygen_ctx_t hd )
-{
- if( hd ) {
- _cdk_free_pubkey( hd->key[0].pk );
- _cdk_free_pubkey( hd->key[1].pk );
- _cdk_free_seckey( hd->key[0].sk );
- _cdk_free_seckey( hd->key[1].sk );
- _cdk_free_userid( hd->id );
- _cdk_free_signature( hd->sig );
- cdk_free( hd->sym_prefs );
- cdk_free( hd->hash_prefs );
- cdk_free( hd->zip_prefs );
- _cdk_sec_free( hd->pass, hd->pass_len );
- _cdk_free_mpibuf( hd->key[0].n, hd->key[0].resarr );
- _cdk_free_mpibuf( hd->key[1].n, hd->key[1].resarr );
- cdk_free( hd );
- }
-}
-
-
-/**
- * cdk_keygen_new:
- * @r_hd: the new object
- *
- **/
-cdk_error_t
-cdk_keygen_new( cdk_keygen_ctx_t * r_hd )
-{
- cdk_keygen_ctx_t hd;
-
- if( !r_hd )
- return CDK_Inv_Value;
- hd = cdk_calloc( 1, sizeof * hd );
- if( !hd )
- return CDK_Out_Of_Core;
- *r_hd = hd;
- return 0;
-}
diff --git a/libextra/opencdk/keylist.c b/libextra/opencdk/keylist.c
deleted file mode 100644
index d12f0daf9e..0000000000
--- a/libextra/opencdk/keylist.c
+++ /dev/null
@@ -1,508 +0,0 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * keylist.c - Linked key lists
- * Copyright (C) 1998-2002, 2006 Free Software Foundation, Inc.
- * Copyright (C) 2002, 2003 Timo Schulz
- *
- * This file is part of OpenCDK.
- *
- * OpenCDK is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * OpenCDK is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include <stdio.h>
-
-#include "opencdk.h"
-#include "main.h"
-#include "packet.h"
-#include "cipher.h"
-
-
-/* Here we check if *all* keys have the MDC feature. Even if one
- key doesn't support it, it is not used. */
-int
-cdk_pklist_use_mdc( cdk_keylist_t pk_list )
-{
- cdk_keylist_t pkr;
- int mdc = 0;
-
- if( !pk_list )
- return CDK_Inv_Value;
-
- for( pkr = pk_list; pkr; pkr = pkr->next ) {
- if( pkr->key.pk->uid ) /* selected by user ID */
- mdc = pkr->key.pk->uid->mdc_feature;
- if( !mdc )
- return 0;
- }
- return 1;
-}
-
-
-static int
-check_algo( int preftype, int algo )
-{
- if( preftype == CDK_PREFTYPE_SYM )
- return algo && !cdk_cipher_test_algo( algo );
- else if( preftype == CDK_PREFTYPE_HASH )
- return algo && !cdk_md_test_algo( algo );
- else if( preftype == CDK_PREFTYPE_ZIP )
- return !algo || algo == 1 || algo == 2;
- else
- return 0;
-}
-
-
-/**
- * cdk_pklist_select_algo:
- * @pkl: the keylist
- * @preftype: preference type
- *
- * Select a symmetric cipher algorithm from a list of public keys.
- * This algorithm is present in all key preferences.
- **/
-int
-cdk_pklist_select_algo( cdk_keylist_t pkl, int preftype )
-{
- const struct cdk_prefitem_s * prefs;
- cdk_keylist_t pkr;
- u32 bits[8];
- int compr_hack = 0, any = 0;
- int i = 0, j = 0;
-
- if (!pkl)
- return -1;
-
- memset (bits, ~0, 8 * sizeof *bits);
- for (pkr = pkl; pkr; pkr = pkr->next) {
- u32 mask[8];
- if (preftype == CDK_PREFTYPE_SYM) {
- memset (mask, 0, 8 * sizeof *mask);
- mask[0] |= (1 << 2); /*3DES is implicitly there for everyone else*/
- }
- if (pkr->key.pk->uid)
- prefs = pkr->key.pk->uid->prefs;
- else
- prefs = pkr->key.pk->prefs;
- any = 0;
- for (i = 0; prefs && prefs[i].type; i++) {
- if (prefs[i].type == preftype) {
- mask[prefs[i].value / 32] |= 1 << (prefs[i].value % 32);
- any = 1;
- }
- }
- if ((!prefs || !any) && preftype == CDK_PREFTYPE_ZIP) {
- mask[0] |= 3; /* asume no_compression and old pgp */
- compr_hack = 1;
- }
- for (i = 0; i < 8; i++)
- bits[i] &= mask[i];
- /* Usable algorithms are now in bits:
- We now use the last key from pkl to select the algorithm we want
- to use. There are no preferences for the last key, we select the one
- corresponding to first set bit. */
- i = -1;
- any = 0;
- for (j = 0; prefs && prefs[j].type; j++) {
- if (prefs[j].type == preftype) {
- if ((bits[prefs[j].value / 32] & (1 << (prefs[j].value % 32))))
- {
- if (check_algo (preftype, prefs[j].value)) {
- any = 1;
- i = prefs[j].value;
- break;
- }
- }
- }
- }
- if (!prefs || !any) {
- for (j = 0; j < 256; j++)
- if ((bits[j / 32] & (1 << (j % 32)))) {
- if (check_algo (preftype, j)) {
- i = j;
- break;
- }
- }
- }
- if (compr_hack && !i) {
- /* selected no compression, but we should check whether
- algorithm 1 is also available (the ordering is not relevant
- in this case). */
- if (bits[0] & (1 << 1))
- i = 1; /* yep; we can use compression algo 1 */
- }
- }
- _cdk_log_debug ("selected algo %d from prefs\n", i);
- return i;
-}
-
-
-static int
-is_duplicated_entry( cdk_strlist_t list, cdk_strlist_t item )
-{
- for( ; list && list != item; list = list->next ) {
- if( !strcmp( list->d, item->d ) )
- return 1;
- }
- return 0;
-}
-
-
-/**
- * cdk_pklist_release:
- * @pkl: the keylist
- *
- * Free the memory of the key list.
- **/
-void
-cdk_pklist_release( cdk_keylist_t pkl )
-{
- cdk_keylist_t pkr;
-
- for( ; pkl; pkl = pkr ) {
- pkr = pkl->next;
- _cdk_free_pubkey( pkl->key.pk );
- pkl->key.pk = NULL;
- cdk_free( pkl );
- }
-}
-
-
-/**
- * cdk_pklist_build:
- * @ret_pkl: the new keylist
- * @hd: the session handle
- * @remusr: the string list of the recipients
- * @use: public key usage
- *
- * Create a public key list based on the recipient names in @remusr.
- **/
-cdk_error_t
-cdk_pklist_build( cdk_keylist_t * ret_pkl, cdk_keydb_hd_t hd,
- cdk_strlist_t remusr, int use )
-{
- cdk_keylist_t pk_list = NULL, r = NULL, l;
- cdk_pkt_pubkey_t pk = NULL;
- int rc = 0;
-
- if( !hd )
- return CDK_Inv_Value;
-
- for( ; remusr; remusr = remusr->next ) {
- rc = _cdk_keydb_get_pk_byusage( hd, remusr->d, &pk, use );
- if( rc )
- break;
- else {
- for( l = pk_list; l; l = l->next ) {
- if( !_cdk_pubkey_compare( l->key.pk, pk ) ) {
- _cdk_free_pubkey( pk );
- pk = NULL;
- continue; /* key already in list so skip it */
- }
- }
- r = cdk_calloc( 1, sizeof *r );
- if( !r ) {
- rc = CDK_Out_Of_Core;
- break;
- }
- r->type = CDK_PKT_PUBLIC_KEY;
- r->key.pk = pk;
- r->next = pk_list;
- pk_list = r;
- }
- }
- if( rc ) {
- cdk_pklist_release( pk_list );
- pk_list = NULL;
- }
- *ret_pkl = pk_list;
- return rc;
-}
-
-
-/**
- * cdk_pklist_encrypt:
- * @pk_list: the keylist
- * @dek: the data encryption key
- * @outp: the stream to write in the data
- *
- * Encrypt the session key with each key of the list and wrap it
- * into a PUBKEY_ENC packet and write it to @outp.
- */
-cdk_error_t
-cdk_pklist_encrypt( cdk_keylist_t pk_list, cdk_dek_t dek, cdk_stream_t outp )
-{
- cdk_pkt_pubkey_t pk = NULL;
- cdk_pkt_pubkey_enc_t enc = NULL;
- cdk_packet_t pkt;
- cdk_sesskey_t frame = NULL;
- int nbits = 0;
- int rc = 0;
-
- if( !pk_list || !dek || !outp )
- return CDK_Inv_Value;
-
- if( pk_list->type != CDK_PKT_PUBLIC_KEY )
- return CDK_Inv_Mode;
-
- pkt = cdk_calloc( 1, sizeof * pkt );
- if( !pkt )
- return CDK_Out_Of_Core;
- for( ; pk_list; pk_list = pk_list->next ) {
- pk = pk_list->key.pk;
- cdk_free( enc );
- enc = cdk_calloc( 1, sizeof *enc );
- if( !enc )
- return CDK_Out_Of_Core;
- enc->version = 3;
- enc->pubkey_algo = pk->pubkey_algo;
- cdk_pk_get_keyid( pk, enc->keyid );
- nbits = cdk_pk_get_nbits( pk );
- rc = cdk_dek_encode_pkcs1( dek, nbits, &frame );
- if( rc )
- break;
- rc = cdk_pk_encrypt( pk, enc, frame );
- cdk_sesskey_free( frame );
- if( rc )
- break;
- else {
- cdk_pkt_init( pkt );
- pkt->old_ctb = dek->rfc1991? 1 : 0;
- pkt->pkttype = CDK_PKT_PUBKEY_ENC;
- pkt->pkt.pubkey_enc = enc;
- rc = cdk_pkt_write( outp, pkt );
- cdk_pkt_free( pkt );
- enc = NULL; /* free'd by cdk_pkt_free() */
- if( rc )
- break;
- }
- }
- cdk_free( pkt );
- cdk_free( enc );
- return rc;
-}
-
-
-/**
- * cdk_sklist_release:
- * @skl: secret keylist
- *
- * Free the memory of the secret keylist.
- **/
-void
-cdk_sklist_release( cdk_keylist_t sk_list )
-{
- cdk_keylist_t sk_rover = NULL;
-
- for( ; sk_list; sk_list = sk_rover ) {
- sk_rover = sk_list->next;
- _cdk_free_seckey( sk_list->key.sk );
- sk_list->key.sk = NULL;
- cdk_free( sk_list );
- }
-}
-
-
-cdk_error_t
-cdk_sklist_build( cdk_keylist_t * ret_skl, cdk_keydb_hd_t db, cdk_ctx_t hd,
- cdk_strlist_t locusr, int unlock, unsigned int use )
-{
- cdk_keylist_t r = NULL, sk_list = NULL;
- cdk_pkt_seckey_t sk = NULL;
- int rc = 0;
-
- if( !db || !hd || !ret_skl )
- return CDK_Inv_Value;
-
- if( !locusr ) { /* use the default one */
- rc = _cdk_keydb_get_sk_byusage( db, NULL, &sk, use );
- if( rc ) {
- _cdk_free_seckey( sk );
- return rc;
- }
- if( unlock ) {
- rc = _cdk_sk_unprotect_auto( hd, sk );
- if( rc )
- return rc;
- }
- r = cdk_calloc( 1, sizeof *r );
- if( !r )
- return CDK_Out_Of_Core;
- r->key.sk = sk;
- r->next = sk_list;
- r->type = CDK_PKT_SECRET_KEY;
- sk_list = r;
- }
- else {
- cdk_strlist_t locusr_orig = locusr;
- for( ; locusr; locusr = locusr->next ) {
- if( is_duplicated_entry( locusr_orig, locusr ) )
- continue;
- rc = _cdk_keydb_get_sk_byusage( db, locusr->d, &sk, use );
- if( rc ) {
- _cdk_free_seckey( sk );
- sk = NULL;
- }
- else {
- if( unlock && (rc = _cdk_sk_unprotect_auto( hd, sk )) )
- break;
- r = cdk_calloc( 1, sizeof *r );
- if( !r )
- return CDK_Out_Of_Core;
- r->key.sk = sk;
- r->next = sk_list;
- r->type = CDK_PKT_SECRET_KEY;
- sk_list = r;
- }
- }
- }
- if( rc ) {
- cdk_sklist_release( sk_list );
- sk_list = NULL;
- }
- *ret_skl = sk_list;
- return rc;
-}
-
-
-/**
- * cdk_sklist_write_onepass:
- * @skl: secret keylist
- * @outp: the stream to write in the data
- * @sigclass: the class of the sig to create
- * @mdalgo: the message digest algorithm
- *
- * Write a one-pass signature for each key in the list into @outp.
- **/
-cdk_error_t
-cdk_sklist_write_onepass( cdk_keylist_t skl, cdk_stream_t outp,
- int sigclass, int mdalgo )
-{
- cdk_pkt_onepass_sig_t ops;
- cdk_keylist_t r;
- cdk_packet_t pkt;
- int i, skcount = 0;
- int rc = 0;
-
- if( !skl || !outp )
- return CDK_Inv_Value;
-
- if( skl->type != CDK_PKT_SECRET_KEY )
- return CDK_Inv_Mode;
-
- pkt = cdk_calloc( 1, sizeof * pkt );
- if( !pkt )
- return CDK_Out_Of_Core;
-
- for( skcount = 0, r = skl; r; r = r->next )
- skcount++;
- for( ; skcount; skcount-- ) {
- for( i = 0, r = skl; r; r = r->next ) {
- if( ++i == skcount )
- break;
- }
- ops = cdk_calloc( 1, sizeof *ops );
- if( !ops )
- return CDK_Out_Of_Core;
- ops->version = 3;
- cdk_sk_get_keyid( r->key.sk, ops->keyid );
- ops->sig_class = sigclass;
- if( !mdalgo )
- mdalgo = _cdk_sig_hash_for( r->key.sk->pubkey_algo,
- r->key.sk->version );
- ops->digest_algo = mdalgo;
- ops->pubkey_algo = r->key.sk->pubkey_algo;
- ops->last = (skcount == 1);
-
- cdk_pkt_init( pkt );
- pkt->pkttype = CDK_PKT_ONEPASS_SIG;
- pkt->pkt.onepass_sig = ops;
- rc = cdk_pkt_write( outp, pkt );
- cdk_pkt_free( pkt );
- if( rc )
- break;
- }
- cdk_free( pkt );
- return rc;
-}
-
-
-/**
- * cdk_sklist_write:
- * @skl: secret keylist
- * @outp: the stream to write in the data
- * @hash: opaque handle for the message digest operations
- * @sigclass: the class of the sig
- * @sigver: version of the sig
- *
- * Complete the sig based on @hash and write all signatures to @outp.
- **/
-cdk_error_t
-cdk_sklist_write( cdk_keylist_t skl, cdk_stream_t outp, cdk_md_hd_t hash,
- int sigclass, int sigver )
-{
- cdk_keylist_t r = NULL;
- cdk_pkt_signature_t sig = NULL;
- cdk_packet_t pkt;
- cdk_md_hd_t md = NULL;
- byte * mdbuf;
- int rc = 0, digest_algo;
-
- if( !skl || !outp || !hash )
- return CDK_Inv_Value;
-
- if( skl->type != CDK_PKT_SECRET_KEY )
- return CDK_Inv_Mode;
-
- pkt = cdk_calloc( 1, sizeof *pkt );
- if( !pkt )
- return CDK_Out_Of_Core;
- digest_algo = cdk_md_get_algo( hash );
- for( r = skl; r; r = r->next ) {
- sig = cdk_calloc( 1, sizeof *sig );
- if( !sig )
- return CDK_Out_Of_Core;
- sig->version = sigver;
- _cdk_sig_create( r->key.sk->pk, sig );
- if( sig->digest_algo != digest_algo )
- sig->digest_algo = digest_algo;
- sig->sig_class = sigclass;
- md = cdk_md_copy( hash );
- _cdk_hash_sig_data( sig, md );
- cdk_md_final( md );
-
- mdbuf = cdk_md_read( md, sig->digest_algo );
- rc = cdk_pk_sign( r->key.sk, sig, mdbuf );
- if( rc )
- break;
- cdk_pkt_init( pkt );
- pkt->old_ctb = sig->version == 3? 1 : 0;
- pkt->pkttype = CDK_PKT_SIGNATURE;
- pkt->pkt.signature = sig;
- rc = cdk_pkt_write( outp, pkt );
- cdk_pkt_free( pkt );
- if( rc )
- break;
- cdk_md_close( md );
- md = NULL;
- }
- cdk_free( pkt );
- cdk_md_close( md );
- return rc;
-}
-
-
-
diff --git a/libextra/opencdk/keyserver.c b/libextra/opencdk/keyserver.c
deleted file mode 100644
index a4ef0349c4..0000000000
--- a/libextra/opencdk/keyserver.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * keyserver.c - Keyserver support
- * Copyright (C) 2006 Free Software Foundation, Inc.
- * Copyright (C) 2002 Timo Schulz
- *
- * This file is part of OpenCDK.
- *
- * OpenCDK is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * OpenCDK is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#ifdef HAVE_NETDB_H
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <arpa/inet.h>
-# include <netdb.h>
-# define closesocket close
-#else
-# include <windows.h>
-#endif
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#include "opencdk.h"
-#include "main.h"
-
-
-static int initialized = 0;
-
-
-static void
-init_sockets( void )
-{
-#ifdef __MINGW32__
- WSADATA wsdata;
-
- if( initialized )
- return;
- if( WSAStartup( 0x0101, &wsdata ) )
- _cdk_log_debug( "winsock init failed.\n" );
-#endif
- initialized = 1;
-}
-
-
-static int
-keyserver_hkp( const char * host, int port, u32 keyid, cdk_kbnode_t * ret_key )
-{
- const char * fmt;
- struct hostent * hp;
- struct sockaddr_in saddr;
- cdk_stream_t a;
- char * buf, buffer[256];
- int nwritten, nread, state = 0;
- int rc = 0, fd;
-
- _cdk_log_debug( "connect to `%s'\n", host );
- hp = gethostbyname( host );
- if( !hp )
- return CDK_General_Error;
-
- memset( &saddr, 0, sizeof saddr );
- memcpy( &saddr.sin_addr, hp->h_addr, hp->h_length );
- saddr.sin_family = hp->h_addrtype;
- saddr.sin_port = htons( port );
-
- fd = socket( AF_INET, SOCK_STREAM, 0 );
- if( fd == -1 )
- return CDK_General_Error;
-
- setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,( char *)1, 1 );
- if( connect( fd,( struct sockaddr *) &saddr, sizeof saddr ) == -1 ) {
- closesocket( fd );
- return CDK_General_Error;
- }
-
- fmt = "GET /pks/lookup?op=get&search=0x%08lX HTTP/1.0\r\n"
- "Host: %s:%d\r\n"
- "\r\n";
- buf = cdk_calloc( 1, 64 + strlen( host ) + strlen( fmt ) );
- if( !buf ) {
- closesocket( fd );
- return CDK_Out_Of_Core;
- }
- sprintf( buf, fmt, keyid, host, port );
- _cdk_log_debug( "%s\n", buf );
-
- nwritten = send( fd, buf, strlen( buf ), 0 );
- if( nwritten == -1 ) {
- cdk_free( buf );
- closesocket( fd );
- return CDK_File_Error;
- }
-
- a = cdk_stream_tmp( );
- if( !a ) {
- cdk_free( buf );
- closesocket( fd );
- return CDK_Out_Of_Core;
- }
-
- while( (nread = recv( fd, buffer, 255, 0 )) > 0 ) {
- buffer[nread] = '\0';
- /*_cdk_log_debug( "%s", buffer );*/
- cdk_stream_write( a, buffer, nread );
- if( strstr( buffer, "<pre>") || strstr( buffer, "</pre>" ) )
- state++;
- }
- cdk_free( buf );
-
- if( state != 2 )
- rc = CDK_Error_No_Key;
- if( !rc ) {
- cdk_stream_tmp_set_mode( a, 0 );
- cdk_stream_set_armor_flag( a, 0 );
- cdk_stream_seek( a, 0 );
- cdk_stream_read( a, NULL, 0 );
- rc = cdk_keydb_get_keyblock( a, ret_key );
- }
- if( rc == CDK_EOF && *ret_key )
- rc = 0;
- cdk_stream_close( a );
- closesocket( fd );
- return rc;
-}
-
-
-/**
- * cdk_keyserver_recv_key:
- * @host: URL or hostname of the keyserver
- * @port: The port to use for the connection
- * @keyid: KeyID of the key to retrieve
- * @kid_type: KeyID type (long, short, fingerprint)
- * @ret_key: The key that was found wrapped in a KBNODE struct
- *
- * Receive a key from a keyserver.
- **/
-cdk_error_t
-cdk_keyserver_recv_key( const char * host, int port,
- const byte * keyid, int kid_type,
- cdk_kbnode_t * ret_key )
-{
- u32 kid = 0;
-
- if( !host || !keyid || !ret_key )
- return CDK_Inv_Value;
-
- if( !initialized )
- init_sockets( );
-
- if( !port )
- port = 11371;
-
- if( !strncmp( host, "http://", 7 ) )
- host += 7;
- else if( !strncmp( host, "hkp://", 6 ) )
- host += 6;
- else if( !strncmp( host, "x-hkp://", 8 ) )
- host += 8;
-
- switch( kid_type ) {
- case CDK_DBSEARCH_SHORT_KEYID: kid = _cdk_buftou32( keyid ); break;
- case CDK_DBSEARCH_KEYID : kid = _cdk_buftou32( keyid + 4 ); break;
- case CDK_DBSEARCH_FPR : kid = _cdk_buftou32( keyid + 16 ); break;
- default : return CDK_Inv_Mode;
- }
-
- return keyserver_hkp( host, port, kid, ret_key );
-}
diff --git a/libextra/opencdk/main.c b/libextra/opencdk/main.c
index c839b377cf..51f8d8be06 100644
--- a/libextra/opencdk/main.c
+++ b/libextra/opencdk/main.c
@@ -1,6 +1,5 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * main.c
- * Copyright (C) 2001, 2002, 2003 Timo Schulz
+/* main.c
+ * Copyright (C) 2001, 2002, 2003, 2007 Timo Schulz
*
* This file is part of OpenCDK.
*
@@ -13,35 +12,35 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <errno.h>
-#ifdef HAVE_PWD_H
-# include <pwd.h>
-#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
+#ifdef _WIN32
+#include <windows.h>
+#endif
#include "opencdk.h"
#include "main.h"
#include "packet.h"
-#include "cipher.h"
-#define DEFAULT_CIPHER_ALGO CDK_CIPHER_CAST5
-#define DEFAULT_DIGEST_ALGO CDK_MD_SHA1
+/* Set a default cipher algorithm and a digest algorithm.
+ Even if AES and SHA-256 are not 'MUST' in the latest
+ OpenPGP draft, AES seems to be a good choice. */
+#define DEFAULT_CIPHER_ALGO GCRY_CIPHER_AES
+#define DEFAULT_DIGEST_ALGO GCRY_MD_SHA256
-#define SECMEM_SIZE 32768
+/* The site of the secure memory which is allocated in gcrypt. */
+#define SECMEM_SIZE 16384
+
+/* Hooks to custom memory allocation functions. */
static void *(*alloc_func) (size_t n) = gcry_xmalloc;
static void *(*alloc_secure_func) (size_t n) = gcry_malloc_secure;
static void *(*realloc_func) (void *p, size_t n) = gcry_realloc;
@@ -50,6 +49,7 @@ static void (*free_func) (void *) = gcry_free;
static int malloc_hooks = 0;
static int secmem_init = 0;
+/* Global settings for the logging. */
static cdk_log_fnc_t log_handler = NULL;
static void *log_handler_value = NULL;
static int log_level = CDK_LOG_NONE;
@@ -61,12 +61,13 @@ static int log_level = CDK_LOG_NONE;
*
* Return an error text for the given id.
**/
-const char *
+const char*
cdk_strerror (int ec)
{
- static char buf[20];
-
- switch (ec) {
+ static char buf[20];
+
+ switch (ec)
+ {
case CDK_EOF: return "End Of File";
case CDK_Success: return "No error";
case CDK_General_Error: return "General error";
@@ -75,8 +76,6 @@ cdk_strerror (int ec)
case CDK_Inv_Packet: return "Invalid packet";
case CDK_Inv_Algo: return "Invalid algorithm";
case CDK_Not_Implemented: return "This is not implemented yet";
- /* FIXME: print the actual gcrypt error */
- case CDK_Gcry_Error: return "Gcrypt error";
case CDK_Armor_Error: return "ASCII armor error";
case CDK_Armor_CRC_Error: return "ASCII armored damaged (CRC error)";
case CDK_MPI_Error: return "Invalid or missformed MPI";
@@ -88,15 +87,17 @@ cdk_strerror (int ec)
case CDK_Weak_Key: return "Weak key was detected";
case CDK_Out_Of_Core: return "Out of core!!";
case CDK_Wrong_Seckey: return "Wrong secret key";
+ case CDK_Wrong_Format: return "Data has wrong format";
case CDK_Bad_MDC: return "Manipulated MDC detected";
case CDK_Inv_Mode: return "Invalid mode";
case CDK_Error_No_Keyring: return "No keyring available";
case CDK_Inv_Packet_Ver: return "Invalid version for packet";
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";
default: sprintf (buf, "ec=%d", ec); return buf;
}
- return NULL;
+ return NULL;
}
@@ -115,7 +116,7 @@ out_of_core (size_t n)
* @new_calloc_func: calloc replacement
* @new_free_func: free replacement
*
- * Set private memory hooks for the lib.
+ * Set private memory hooks for the library.
*/
void
cdk_set_malloc_hooks (void *(*new_alloc_func) (size_t n),
@@ -145,10 +146,10 @@ cdk_malloc_hook_initialized (void)
}
-void *
+void*
cdk_malloc (size_t size)
{
- void * p = alloc_func (size);
+ void *p = alloc_func (size);
if (!p)
out_of_core (size);
return p;
@@ -164,58 +165,115 @@ cdk_calloc (size_t n, size_t m)
return p;
}
+/* Things which need to be done after the secure memory initialisation. */
+static void
+_secmem_finish (void)
+{
+ gcry_control (GCRYCTL_DROP_PRIVS);
+}
+
static void
_secmem_init (size_t size)
{
- if (!size) {
- gcry_control (GCRYCTL_DROP_PRIVS);
- return;
- }
- if (secmem_init == 1)
- return;
- if (size >= SECMEM_SIZE)
- size = SECMEM_SIZE;
- gcry_control (GCRYCTL_INIT_SECMEM, size, 0);
- gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
- gcry_control (GCRYCTL_DISABLE_SECMEM_WARN);
- secmem_init = 1;
+ if (secmem_init == 1)
+ return;
+ if (size >= SECMEM_SIZE)
+ size = SECMEM_SIZE;
+ gcry_control (GCRYCTL_INIT_SECMEM, size, 0);
+ gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
+ gcry_control (GCRYCTL_DISABLE_SECMEM_WARN);
+ secmem_init = 1;
}
-/* Not used?
+/* Things which needs to be done to deinit the secure memory. */
static void
_secmem_end (void)
{
gcry_control (GCRYCTL_TERM_SECMEM);
secmem_init = 0;
}
-*/
-void *
+
+/* The Windows system needs to startup the Winsock interface first
+ before we can use any socket related function. */
+#ifdef _WIN32
+static void
+init_sockets (void)
+{
+ static int initialized = 0;
+ WSADATA wsdata;
+
+ if (initialized)
+ return;
+ if (WSAStartup (0x202, &wsdata))
+ _cdk_log_debug ("winsock init failed.\n");
+
+ initialized = 1;
+}
+
+static void
+deinit_sockets (void)
+{
+ WSACleanup ();
+}
+#else
+void init_sockets (void) {}
+void deinit_sockets (void) {}
+#endif
+
+
+/**
+ * cdk_lib_startup:
+ *
+ * Prepare the internal structures of the library.
+ * This function should be called before any other CDK function.
+ */
+void
+cdk_lib_startup (void)
+{
+ _secmem_init (SECMEM_SIZE);
+ _secmem_finish ();
+ init_sockets ();
+}
+
+
+/**
+ * cdk_lib_shutdown:
+ *
+ * Shutdown the library and free all internal and globally used
+ * memory and structures. This function should be called in the
+ * exit handler of the calling program.
+ */
+void
+cdk_lib_shutdown (void)
+{
+ deinit_sockets ();
+ _secmem_end ();
+}
+
+/**
+ * cdk_salloc:
+ * @size: how much bytes should be allocated.
+ * @clear: shall the buffer cleared after the allocation?
+ *
+ * Allocated the requested amount of bytes in 'secure' memory.
+ */
+void*
cdk_salloc (size_t size, int clear)
{
-/* static size_t n = 0; */
- void * p;
+ void *p;
- if (!secmem_init) {
- _secmem_init (SECMEM_SIZE);
- secmem_init = 1;
- }
- if (secmem_init == 1) {
- _secmem_init (0);
- secmem_init = 2;
- }
- /*
- n += size;
- _cdk_log_debug ("\ncdk_salloc (%d)\n", n);
- */
- p = alloc_secure_func (size);
- if (!p)
- out_of_core (size);
- if (clear)
- memset (p, 0, size);
- return p;
+ if (!secmem_init)
+ _secmem_init (SECMEM_SIZE);
+
+ p = alloc_secure_func (size);
+ if (!p)
+ out_of_core (size);
+ if (clear)
+ memset (p, 0, size);
+ return p;
}
@@ -247,32 +305,19 @@ cdk_free (void * ptr)
}
-void
-_cdk_sec_free( void * ptr, size_t size )
-{
- if( ptr ) {
- memset( ptr, 0xff, size );
- memset( ptr, 0xaa, size );
- memset( ptr, 0x55, size );
- memset( ptr, 0x00, size );
- free_func( ptr );
- }
-}
-
-
static void
_cdk_logv (int level, const char *fmt, va_list arg_ptr)
{
- if (log_handler)
- log_handler (log_handler_value, level, fmt, arg_ptr);
- else {
- switch (level) {
- case CDK_LOG_INFO : break;
- case CDK_LOG_DEBUG: fputs ("DBG: ", stderr); break;
- case CDK_LOG_NONE : return;
- }
- vfprintf (stderr, fmt, arg_ptr);
+ if (log_handler)
+ log_handler (log_handler_value, level, fmt, arg_ptr);
+ else
+ {
+ if (level == CDK_LOG_NONE)
+ return;
+ if (level == CDK_LOG_DEBUG)
+ fputs ("DBG: ", stderr);
+ vfprintf (stderr, fmt, arg_ptr);
}
}
@@ -282,13 +327,13 @@ _cdk_logv (int level, const char *fmt, va_list arg_ptr)
* @logfnc: the function pointer
* @opaque: a private values for the function
*
- * set a private handler for logging.
- */
+ * Set a private handler for logging.
+ **/
void
-cdk_set_log_handler( cdk_log_fnc_t logfnc, void * opaque )
+cdk_set_log_handler (cdk_log_fnc_t logfnc, void *opaque)
{
- log_handler = logfnc;
- log_handler_value = opaque;
+ log_handler = logfnc;
+ log_handler_value = opaque;
}
@@ -296,156 +341,134 @@ cdk_set_log_handler( cdk_log_fnc_t logfnc, void * opaque )
* cdk_set_log_level:
* @lvl: the level
*
- * set the verbosity level.
+ * Set the verbosity level.
**/
void
-cdk_set_log_level (int lvl)
+cdk_set_log_level (int level)
{
- log_level = lvl;
+ log_level = level;
}
int
_cdk_get_log_level (void)
{
- return log_level;
+ return log_level;
}
void
_cdk_log_info (const char *fmt, ...)
{
- va_list arg;
-
- if (log_level == CDK_LOG_NONE)
- return;
- va_start (arg, fmt);
- _cdk_logv (CDK_LOG_INFO, fmt, arg);
- va_end (arg);
+ va_list arg;
+
+ if (log_level == CDK_LOG_NONE)
+ return;
+ va_start (arg, fmt);
+ _cdk_logv (CDK_LOG_INFO, fmt, arg);
+ va_end (arg);
}
void
_cdk_log_debug (const char *fmt, ...)
{
- va_list arg;
+ va_list arg;
- if (log_level < CDK_LOG_DEBUG)
- return;
- va_start (arg, fmt);
- _cdk_logv (CDK_LOG_DEBUG, fmt, arg);
- va_end (arg);
-}
-
-#include <getpass.h>
-
-char *
-_cdk_passphrase_get( cdk_ctx_t hd, const char * prompt )
-{
- char * p, * pass = NULL;
-
- if( hd->passphrase )
- return hd->passphrase( hd->passphrase_value, prompt );
- p = getpass( prompt );
- if( p )
- pass = cdk_strdup( p );
- return pass;
-}
-
-
-void
-_cdk_passphrase_free( char *pw, size_t size )
-{
- _cdk_sec_free( pw, size );
+ if (log_level < CDK_LOG_DEBUG)
+ return;
+ va_start (arg, fmt);
+ _cdk_logv (CDK_LOG_DEBUG, fmt, arg);
+ va_end (arg);
}
-int
-_cdk_is_idea_available (void)
+/* Use the passphrase callback in the handle HD or
+ return NULL if there is no valid callback. */
+char*
+_cdk_passphrase_get (cdk_ctx_t hd, const char *prompt)
{
- int rc = 0;
-#ifdef LIBGCRYPT_WITH_IDEA
- rc = 1;
-#endif
- return rc;
+ if (!hd || !hd->passphrase_cb)
+ return NULL;
+ return hd->passphrase_cb (hd->passphrase_cb_value, prompt);
}
static void
handle_set_cipher (cdk_ctx_t hd, int cipher)
{
- if( !hd )
- return;
- if( cdk_cipher_test_algo( cipher ) )
- cipher = DEFAULT_CIPHER_ALGO;
- hd->cipher_algo = cipher;
+ if (!hd)
+ return;
+ if (gcry_cipher_test_algo (cipher))
+ cipher = DEFAULT_CIPHER_ALGO;
+ hd->cipher_algo = cipher;
}
static void
handle_set_digest (cdk_ctx_t hd, int digest)
{
- if( !hd )
- return;
- if( cdk_md_test_algo( digest ) )
- digest = DEFAULT_DIGEST_ALGO;
- hd->digest_algo = digest;
+ if (!hd)
+ return;
+ if (gcry_md_test_algo (digest))
+ digest = DEFAULT_DIGEST_ALGO;
+ hd->digest_algo = digest;
}
static void
-handle_set_s2k( cdk_ctx_t hd, int mode, int digest, int cipher )
+handle_set_s2k (cdk_ctx_t hd, int mode, int digest, int cipher)
{
- if( !hd )
- return;
- if( cdk_cipher_test_algo( cipher ) )
- cipher = DEFAULT_CIPHER_ALGO;
- if( cdk_md_test_algo( digest ) )
- digest = DEFAULT_DIGEST_ALGO;
- if( mode != CDK_S2K_SIMPLE
- && mode != CDK_S2K_SALTED
- && mode != CDK_S2K_ITERSALTED )
- mode = CDK_S2K_ITERSALTED;
- hd->_s2k.mode = mode;
- hd->_s2k.digest_algo = digest;
- hd->_s2k.cipher_algo = cipher;
+ if (!hd)
+ return;
+ if (gcry_cipher_test_algo (cipher))
+ cipher = DEFAULT_CIPHER_ALGO;
+ if (gcry_md_test_algo (digest))
+ digest = DEFAULT_DIGEST_ALGO;
+ if (mode != CDK_S2K_SIMPLE &&
+ mode != CDK_S2K_SALTED &&
+ mode != CDK_S2K_ITERSALTED)
+ mode = CDK_S2K_ITERSALTED;
+ hd->_s2k.mode = mode;
+ hd->_s2k.digest_algo = digest;
}
static void
-handle_set_compat( cdk_ctx_t hd, int val )
+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? CDK_CIPHER_IDEA : DEFAULT_CIPHER_ALGO;
- hd->digest_algo = val == -1? CDK_MD_MD5: DEFAULT_DIGEST_ALGO;
- if( val == -1 )
- handle_set_s2k( hd, 0, hd->digest_algo, hd->cipher_algo );
+ 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 )
- return;
- if( algo < 0 || algo > 2 )
- algo = 0;
- hd->compress.algo = algo;
- if( !algo )
- hd->opt.compress = 0;
- else {
- if( level > 0 && level < 10 )
- hd->compress.level = level;
- else
- hd->compress.level = 6;
+handle_set_compress (cdk_ctx_t hd, int algo, int level)
+{
+ if (!hd)
+ return;
+ if (algo < 0 || algo > 2)
+ algo = 0;
+ hd->compress.algo = algo;
+ if (!algo)
+ hd->opt.compress = 0;
+ else
+ {
+ if (level > 0 && level < 10)
+ hd->compress.level = level;
+ else
+ hd->compress.level = 6;
}
}
@@ -459,105 +482,108 @@ handle_set_compress( cdk_ctx_t hd, int algo, int level )
* Perform various control operations for the current session.
**/
int
-cdk_handle_control( cdk_ctx_t hd, int action, int cmd, ... )
+cdk_handle_control (cdk_ctx_t hd, int action, int cmd, ...)
{
- va_list arg_ptr;
- int set = action == CDK_CTLF_SET, val = 0;
-
- if( !hd )
- return -1;
- if( action != CDK_CTLF_SET && action != CDK_CTLF_GET )
- return -1;
- va_start( arg_ptr, cmd );
- switch( cmd ) {
+ va_list arg_ptr;
+ int set = action == CDK_CTLF_SET, val = 0;
+
+ if (!hd)
+ return -1;
+
+ if (action != CDK_CTLF_SET && action != CDK_CTLF_GET)
+ return -1;
+ va_start (arg_ptr, cmd);
+ switch( cmd )
+ {
case CDK_CTL_ARMOR:
- if( set )
- hd->opt.armor = va_arg( arg_ptr, int );
- else
- val = hd->opt.armor;
- break;
+ if (set)
+ hd->opt.armor = va_arg( arg_ptr, int );
+ else
+ val = hd->opt.armor;
+ break;
case CDK_CTL_CIPHER:
- if( set )
- handle_set_cipher( hd, va_arg( arg_ptr, int ) );
- else
- val = hd->cipher_algo;
- break;
-
+ if (set)
+ handle_set_cipher (hd, va_arg (arg_ptr, int));
+ else
+ val = hd->cipher_algo;
+ break;
+
case CDK_CTL_DIGEST:
- if( set )
- handle_set_digest( hd, va_arg( arg_ptr, int ) );
- else
- val = hd->digest_algo;
- break;
-
+ 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;
-
+ 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 );
- else
- val = hd->opt.overwrite;
- break;
-
+ if (set)
+ hd->opt.overwrite = va_arg( arg_ptr, int );
+ else
+ val = hd->opt.overwrite;
+ break;
+
case CDK_CTL_COMPRESS:
- if( set ) {
- int algo = va_arg( arg_ptr, int );
- int level = va_arg( arg_ptr, int );
- handle_set_compress( hd, algo, level );
- }
- else
- val = hd->compress.algo;
- break;
-
+ if (set)
+ {
+ int algo = va_arg (arg_ptr, int);
+ int level = va_arg (arg_ptr, int);
+ handle_set_compress (hd, algo, level);
+ }
+ else
+ val = hd->compress.algo;
+ break;
+
case CDK_CTL_S2K:
- if( set ) {
- int mode = va_arg( arg_ptr, int );
- int digest = va_arg( arg_ptr, int );
- int cipher = va_arg( arg_ptr, int );
- handle_set_s2k( hd, mode, digest, cipher );
- }
- else
- val = hd->_s2k.mode;
- break;
-
+ if( set ) {
+ int mode = va_arg( arg_ptr, int );
+ int digest = va_arg( arg_ptr, int );
+ int cipher = va_arg( arg_ptr, int );
+ handle_set_s2k( hd, mode, digest, cipher );
+ }
+ else
+ 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;
-
+ if (set)
+ hd->cache.on = va_arg (arg_ptr, int);
+ else
+ val = hd->cache.on;
+ break;
+
case CDK_CTL_KEYCACHE_FREE:
- _cdk_free_seckey( hd->cache.sk );
- hd->cache.sk = NULL;
- break;
-
+ 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 );
- else
- val = hd->opt.force_digest;
- break;
-
- case CDK_CTL_TRUSTMODEL:
- if( set )
- hd->trust_model = va_arg( arg_ptr, int );
- else
- val = hd->trust_model;
- break;
-
+ if( set )
+ hd->opt.force_digest = va_arg( arg_ptr, int );
+ else
+ val = hd->opt.force_digest;
+ break;
+
+ case CDK_CTL_BLOCKMODE_ON:
+ if( set )
+ hd->opt.blockmode = va_arg( arg_ptr, int );
+ else
+ val = hd->opt.blockmode;
+ break;
+
default:
- val = -1;
- break;
+ val = -1;
+ break;
}
- va_end( arg_ptr );
- return val;
+ va_end (arg_ptr);
+ return val;
}
@@ -568,37 +594,69 @@ cdk_handle_control( cdk_ctx_t hd, int action, int cmd, ... )
*
* create a new session handle.
**/
-int
-cdk_handle_new( cdk_ctx_t * r_ctx )
+cdk_error_t
+cdk_handle_new (cdk_ctx_t *r_ctx)
{
- cdk_ctx_t c;
+ cdk_ctx_t c;
- if( !r_ctx )
- return CDK_Inv_Value;
-
- c = cdk_calloc( 1, sizeof *c );
- if( !c )
- return CDK_Out_Of_Core;
- /* default */
- c->_s2k.mode = 3;
- c->_s2k.digest_algo = DEFAULT_DIGEST_ALGO;
- c->_s2k.cipher_algo = DEFAULT_CIPHER_ALGO;
+ if (!r_ctx)
+ return CDK_Inv_Value;
+
+ c = cdk_calloc (1, sizeof *c);
+ if (!c)
+ return CDK_Out_Of_Core;
+
+ /* For S2K use the iterated and salted mode and use the
+ default digest and cipher algorithms. Because the MDC
+ feature will be used, the default cipher should use a
+ blocksize of 128 bits. */
+ c->_s2k.mode = CDK_S2K_ITERSALTED;
+ c->_s2k.digest_algo = DEFAULT_DIGEST_ALGO;
+
+ c->opt.mdc = 1;
+ c->opt.compress = 1;
+ c->opt.armor = 0;
+ c->opt.textmode = 0;
+
+ c->digest_algo = DEFAULT_DIGEST_ALGO;
+ c->cipher_algo = DEFAULT_CIPHER_ALGO;
+
+ c->compress.algo = CDK_COMPRESS_ZIP;
+ c->compress.level = 6;
- c->opt.mdc = 1;
- c->opt.compress = 1;
- c->opt.armor = 0;
- c->opt.textmode = 0;
+ *r_ctx = c;
+ return 0;
+}
- c->digest_algo = DEFAULT_DIGEST_ALGO;
- c->cipher_algo = DEFAULT_CIPHER_ALGO;
- c->compress.algo = CDK_COMPRESS_ZIP;
- c->compress.level = 6;
- *r_ctx = c;
- return 0;
+/**
+ * cdk_handle_set_keyring:
+ * @hd: session handle
+ * @type: public=0 or secret=1 keyring type
+ * @kringname: file name of the keyring which shall be used.
+ *
+ * Convenient function to set the keyring for the current session.
+ */
+cdk_error_t
+cdk_handle_set_keyring (cdk_ctx_t hd, int type, const char *kringname)
+{
+ cdk_keydb_hd_t db;
+ cdk_error_t err;
+
+ err = cdk_keydb_new_from_file (&db, type, kringname);
+ if (err)
+ return err;
+
+ if (!type)
+ hd->db.pub = db;
+ else
+ hd->db.sec = db;
+ hd->db.close_db = 1;
+ return 0;
}
+
/**
* cdk_handle_set_keydb:
* @hd: session handle
@@ -609,14 +667,14 @@ cdk_handle_new( cdk_ctx_t * r_ctx )
* secret keyring and the right handle is set.
**/
void
-cdk_handle_set_keydb( cdk_ctx_t hd, cdk_keydb_hd_t db )
+cdk_handle_set_keydb (cdk_ctx_t hd, cdk_keydb_hd_t db)
{
- if( !hd )
- return;
- if( db->secret )
- hd->db.sec = db;
- else
- hd->db.pub = db;
+ if (!hd)
+ return;
+ if (db->secret)
+ hd->db.sec = db;
+ else
+ hd->db.pub = db;
}
@@ -626,39 +684,21 @@ cdk_handle_set_keydb( cdk_ctx_t hd, cdk_keydb_hd_t db )
* @type: type of the keyring
*
* Return the keydb handle from the session handle.
+ * The caller should not free these handles.
**/
cdk_keydb_hd_t
-cdk_handle_get_keydb( cdk_ctx_t hd, int type )
-{
- if( !hd )
- return NULL;
- if( type == CDK_DBTYPE_PK_KEYRING )
- return hd->db.pub;
- else if( type == CDK_DBTYPE_SK_KEYRING )
- return hd->db.sec;
+cdk_handle_get_keydb (cdk_ctx_t hd, int type)
+{
+ if (!hd)
return NULL;
+ if (type == CDK_DBTYPE_PK_KEYRING)
+ return hd->db.pub;
+ else if (type == CDK_DBTYPE_SK_KEYRING)
+ return hd->db.sec;
+ return NULL;
}
-/**
- * cdk_handle_set_callback:
- * @hd: the handle
- * @cb: the callback function
- * @cb_value: the opaque value for the function
- *
- * set the callback for filter operations.
- **/
-void
-cdk_handle_set_callback (cdk_ctx_t hd,
- void (*cb) (void * opaque, int type, const char * s),
- void * cb_value)
-{
- if( !hd )
- return;
- hd->callback = cb;
- hd->callback_value = cb_value;
-}
-
/**
* cdk_handle_set_passphrase_cb:
@@ -668,14 +708,21 @@ cdk_handle_set_callback (cdk_ctx_t hd,
*
* set the passphrase callback.
**/
-void cdk_handle_set_passphrase_cb( cdk_ctx_t hd,
+void cdk_handle_set_passphrase_cb (cdk_ctx_t hd,
char *(*cb) (void *opa, const char *prompt),
- void * cb_value )
+ void * cb_value)
{
- if( !hd )
+ if (!hd)
return;
- hd->passphrase = cb;
- hd->passphrase_value = cb_value;
+ hd->passphrase_cb = cb;
+ hd->passphrase_cb_value = cb_value;
+}
+
+
+cdk_verify_result_t
+cdk_handle_verify_get_result (cdk_ctx_t hd)
+{
+ return hd->result.verify;
}
@@ -683,17 +730,26 @@ void cdk_handle_set_passphrase_cb( cdk_ctx_t hd,
* cdk_handle_free:
* @hd: the handle
*
- * free the main handle.
+ * Release the main handle.
**/
void
-cdk_handle_free( cdk_ctx_t hd )
-{
- if( !hd )
- return;
- _cdk_result_verify_free( hd->result.verify );
- _cdk_free_seckey( hd->cache.sk );
- cdk_free( hd->s2k );
- cdk_free( hd->dek );
- cdk_free( hd );
+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. */
+ if (hd->db.close_db)
+ {
+ if (hd->db.pub)
+ cdk_keydb_free (hd->db.pub);
+ if (hd->db.sec)
+ cdk_keydb_free (hd->db.sec);
+ hd->db.pub = hd->db.sec = NULL;
+ }
+ cdk_free (hd->dek);
+ cdk_free (hd);
}
-
diff --git a/libextra/opencdk/main.h b/libextra/opencdk/main.h
index 0ae68893ba..e84f346b44 100644
--- a/libextra/opencdk/main.h
+++ b/libextra/opencdk/main.h
@@ -1,6 +1,5 @@
/* main.h
- * Copyright (C) 2006 Free Software Foundation
- * Copyright (C) 2002, 2003, 2004 Timo Schulz
+ * Copyright (C) 2002, 2003, 2007 Timo Schulz
*
* This file is part of OpenCDK.
*
@@ -13,38 +12,47 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
#ifndef CDK_MAIN_H
#define CDK_MAIN_H
-#include <config.h>
#include <gcrypt.h>
-#include "md.h"
#include "types.h"
+
+/* The general size of a buffer for the variou modules. */
+#define BUFSIZE 8192
+
+/* This is the default block size for the partial length packet mode. */
+#define DEF_BLOCKSIZE 8192
+#define DEF_BLOCKBITS 13 /* 2^13 = 8192 */
+
+/* For now SHA-1 is used to create fingerprint for keys.
+ But if this will ever change, it is a good idea to
+ have a constant for it to avoid to change it in all files. */
+#define KEY_FPR_LEN 20
+
#include "context.h"
+/* The maximal amount of bits a multi precsion integer can have. */
#define MAX_MPI_BITS 8192
#define MAX_MPI_BYTES (MAX_MPI_BITS/8)
+
+/* Because newer DSA variants are not limited to SHA-1, we must consider
+ that SHA-512 is used and increase the buffer size of the digest. */
+#define MAX_DIGEST_LEN 64
+
#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))
-#define PK_USAGE_SIGN 1
-#define PK_USAGE_ENCR 2
-
-#define KEY_CAN_ENCRYPT(a) (_cdk_pk_algo_usage((a)) & PK_USAGE_ENCR)
-#define KEY_CAN_SIGN(a) (_cdk_pk_algo_usage((a)) & PK_USAGE_SIGN)
+#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)
-#define wipemem(_ptr,_len) \
-do \
-{ \
+/* Helper macro to make sure the buffer is overwritten. */
+#define wipemem(_ptr,_len) do { \
volatile char *_vptr = (volatile char *)(_ptr); \
size_t _vlen = (_len); \
while (_vlen) \
@@ -52,8 +60,7 @@ do \
*_vptr = 0; \
_vptr++; \
_vlen--; \
- } \
-} while (0)
+ } } while (0)
/*-- armor.c --*/
const char * _cdk_armor_get_lineend (void);
@@ -62,25 +69,27 @@ const char * _cdk_armor_get_lineend (void);
int _cdk_get_log_level (void);
void _cdk_log_info (const char * fmt, ...);
void _cdk_log_debug (const char * fmt, ...);
-char * _cdk_passphrase_get( cdk_ctx_t hd, const char * prompt );
-void _cdk_passphrase_free (char * pw, size_t size);
-int _cdk_is_idea_available (void);
-void _cdk_sec_free( void * ptr, size_t size );
+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);
-void _cdk_vasprintf_free (void * p);
-
-#ifndef HAVE_VASPRINTF
-int _cdk_vasprintf ( char **result, const char *format, va_list args);
-#else
-# define _cdk_vasprintf vasprintf
-#endif
+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 );
+cdk_error_t map_gcry_error (gcry_error_t err);
+
+/* Helper to provide case insentensive strstr version. */
+#define stristr(haystack, needle) \
+ _cdk_memistr((haystack), strlen (haystack), (needle))
+
+/*-- proc-packet.c --*/
+cdk_error_t _cdk_proc_packets (cdk_ctx_t hd, cdk_stream_t inp,
+ cdk_stream_t data,
+ const char *output, cdk_stream_t outstream,
+ gcry_md_hd_t md);
+cdk_error_t _cdk_pkt_write2 (cdk_stream_t out, int pkttype, void *pktctx);
/*-- pubkey.c --*/
u32 _cdk_pkt_get_keyid( cdk_packet_t pkt, u32 * keyid );
@@ -89,74 +98,79 @@ int _cdk_pk_algo_usage( int algo );
int _cdk_pk_test_algo( int algo, unsigned int usage );
int _cdk_sk_get_csum( cdk_pkt_seckey_t sk );
-/*-- cipher.c --*/
-int _cdk_cipher_test_algo (int algo);
-
/*-- new-packet.c --*/
byte * _cdk_subpkt_get_array (cdk_subpkt_t s, int count, size_t * r_nbytes);
cdk_error_t _cdk_subpkt_copy (cdk_subpkt_t * r_dst, cdk_subpkt_t src);
-cdk_error_t _cdk_subpkt_hash (cdk_subpkt_t hashed, size_t * r_nbytes,
- cdk_md_hd_t hd);
/*-- sig-check.c --*/
int _cdk_sig_check (cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig,
- cdk_md_hd_t digest, int * r_expired);
-void _cdk_hash_sig_data (cdk_pkt_signature_t sig, cdk_md_hd_t hd);
-void _cdk_hash_userid( cdk_pkt_userid_t uid, int sig_version, cdk_md_hd_t md);
-void _cdk_hash_pubkey (cdk_pkt_pubkey_t pk, cdk_md_hd_t md, int use_fpr);
-int _cdk_pk_check_sig(cdk_keydb_hd_t hd, cdk_kbnode_t knode,
- cdk_kbnode_t snode, int * is_selfsig);
-
+ 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);
+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,
+ cdk_kbnode_t snode, int *is_selfsig);
/*-- kbnode.c --*/
void _cdk_kbnode_add (cdk_kbnode_t root, cdk_kbnode_t node);
void _cdk_kbnode_clone (cdk_kbnode_t node);
/*-- sesskey.c --*/
-cdk_error_t _cdk_digest_encode_pkcs1( byte ** r_md, size_t * r_mdlen,
- int pk_algo, const byte * md,
- int digest_algo, unsigned nbits );
-cdk_error_t _cdk_sk_unprotect_auto( cdk_ctx_t hd, cdk_pkt_seckey_t sk );
+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 );
/*-- 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);
-char * _cdk_keydb_get_importres_as_xml( int result[4] );
+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);
-int _cdk_sig_hash_for (int pubkey_algo, int pkt_version);
-void _cdk_trim_string (char * s, int canon);
-int _cdk_sig_complete (cdk_pkt_signature_t sig, cdk_pkt_seckey_t sk,
- cdk_md_hd_t hd);
+int _cdk_sig_create( cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig );
+int _cdk_sig_hash_for (cdk_pkt_pubkey_t pk);
+void _cdk_trim_string( char * s, int canon );
+cdk_error_t _cdk_sig_complete( cdk_pkt_signature_t sig, cdk_pkt_seckey_t sk,
+ gcry_md_hd_t hd );
/*-- stream.c --*/
+void _cdk_stream_set_compress_algo (cdk_stream_t s, int algo);
+cdk_error_t _cdk_stream_open_mode (const char *file, const char *mode,
+ cdk_stream_t *ret_s);
void * _cdk_stream_get_opaque( cdk_stream_t s, int fid );
const char * _cdk_stream_get_fname( cdk_stream_t s );
FILE * _cdk_stream_get_fp( cdk_stream_t s );
int _cdk_stream_gets( cdk_stream_t s, char * buf, size_t count );
cdk_error_t _cdk_stream_append( const char * file, cdk_stream_t * ret_s );
int _cdk_stream_get_errno( cdk_stream_t s );
-int _cdk_stream_set_blockmode( cdk_stream_t s, size_t nbytes );
+cdk_error_t _cdk_stream_set_blockmode( cdk_stream_t s, size_t nbytes );
int _cdk_stream_get_blockmode( cdk_stream_t s );
int _cdk_stream_puts( cdk_stream_t s, const char * buf );
-cdk_stream_t _cdk_stream_fpopen (FILE * fp, unsigned write_mode);
+cdk_error_t _cdk_stream_fpopen (FILE * fp, unsigned write_mode,
+ cdk_stream_t *ret_out);
/*-- verify.c --*/
-void _cdk_result_verify_free (_cdk_verify_result_t res);
-_cdk_verify_result_t _cdk_result_verify_new (void);
+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 );
-int _cdk_proc_packets( cdk_ctx_t hd, cdk_stream_t inp, const char * output,
- cdk_stream_t outstream, cdk_md_hd_t md );
/*-- read-packet.c --*/
-size_t _cdk_pkt_read_len( FILE * inp, int * ret_partial );
-
-/** write-packet.c --*/
-int _cdk_pkt_write_fp( FILE * out, cdk_packet_t pkt );
+size_t _cdk_pkt_read_len (FILE * inp, size_t *ret_partial);
+
+/*-- write-packet.c --*/
+cdk_error_t _cdk_pkt_write_fp( FILE * out, cdk_packet_t pkt );
+
+/*-- dek.c --*/
+cdk_error_t cdk_dek_encode_pkcs1 (cdk_dek_t dek, size_t nbits,
+ gcry_mpi_t *r_enc);
+cdk_error_t cdk_dek_decode_pkcs1 (cdk_dek_t * ret_dek, gcry_mpi_t esk);
+cdk_error_t cdk_dek_extract (cdk_dek_t * ret_dek, cdk_ctx_t hd,
+ cdk_pkt_pubkey_enc_t enc,
+ cdk_pkt_seckey_t sk );
#endif /* CDK_MAIN_H */
diff --git a/libextra/opencdk/md.c b/libextra/opencdk/md.c
deleted file mode 100644
index 85b55701e9..0000000000
--- a/libextra/opencdk/md.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/* md.c
- * Copyright (C) 2002 Timo Schulz
- *
- * This file is part of OpenCDK.
- *
- * OpenCDK is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * OpenCDK is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#include <stdio.h>
-#include "opencdk.h"
-#include "main.h"
-#include "md.h"
-
-struct cdk_md_hd_s {
- gcry_md_hd_t hd;
- int algo;
-};
-
-inline
-static int cdk_md_to_gcry( int algo)
-{
- switch(algo) {
- case CDK_MD_MD5:
- return GCRY_MD_MD5;
- case CDK_MD_SHA1:
- return GCRY_MD_SHA1;
- case CDK_MD_RMD160:
- return GCRY_MD_RMD160;
- default:
- return -1;
- }
-
-}
-
-/* flags will be passed to gcrypt as is.
- */
-cdk_md_hd_t
-cdk_md_open( int algo, unsigned int flags )
-{
- cdk_md_hd_t hd;
- gcry_error_t err;
-
- hd = cdk_calloc( 1, sizeof * hd );
- if( !hd )
- return NULL;
- hd->algo = algo;
-
- err = gcry_md_open( &hd->hd, cdk_md_to_gcry( algo), flags);
-
- if (err) {
- cdk_free( hd );
- return NULL;
- }
-
- return hd;
-}
-
-
-void
-cdk_md_close( cdk_md_hd_t hd )
-{
- if( hd ) {
- gcry_md_close( hd->hd);
- cdk_free( hd );
- }
-}
-
-int
-cdk_md_test_algo( int algo )
-{
- return gcry_md_test_algo( cdk_md_to_gcry(algo));
-}
-
-
-void
-cdk_md_write( cdk_md_hd_t hd, const void * buf, size_t buflen )
-{
- if( hd ) {
- gcry_md_write( hd->hd, (byte *)buf, buflen );
- }
-}
-
-
-void
-cdk_md_putc( cdk_md_hd_t hd, int c )
-{
- if (hd) {
- gcry_md_putc( hd->hd, c);
- }
-}
-
-
-int
-cdk_md_final( cdk_md_hd_t hd )
-{
- if( hd ) {
- return gcry_md_final(hd->hd);
- }
- return CDK_Inv_Value;
-}
-
-
-byte *
-cdk_md_read( cdk_md_hd_t hd, int algo )
-{
-int _algo;
-
- if (algo==0) _algo = 0;
- else _algo = cdk_md_to_gcry(algo);
-
- if (hd) {
- return gcry_md_read( hd->hd, _algo);
- }
- return NULL;
-}
-
-
-cdk_md_hd_t
-cdk_md_copy( cdk_md_hd_t hd )
-{
- cdk_md_hd_t new;
- gcry_error_t err;
-
- new = cdk_calloc( 1, sizeof * hd );
- if( !new )
- return NULL;
-
- err = gcry_md_copy( &new->hd, hd->hd);
-
- if( err) {
- cdk_free( new);
- return NULL;
- }
-
- new->algo = hd->algo;
-
- return new;
-}
-
-
-int
-cdk_md_get_algo_dlen( int algo )
-{
- return gcry_md_get_algo_dlen( cdk_md_to_gcry( algo ));
-}
-
-
-int
-cdk_md_get_asnoid( int algo, byte * buf, size_t *r_asnlen )
-{
- return gcry_md_get_asnoid( cdk_md_to_gcry(algo), buf, r_asnlen);
-}
-
-
-int
-cdk_md_reset( cdk_md_hd_t hd )
-{
- if( hd ) {
- gcry_md_reset( hd->hd );
- return 0;
- }
- return CDK_Inv_Value;
-}
-
-
-int
-cdk_md_get_algo( cdk_md_hd_t hd )
-{
- if( hd )
- return hd->algo;
- return 0;
-}
diff --git a/libextra/opencdk/md.h b/libextra/opencdk/md.h
deleted file mode 100644
index 2348b48ca8..0000000000
--- a/libextra/opencdk/md.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * md.h
- * Copyright (C) 2003 Timo Schulz
- *
- * This file is part of OpenCDK.
- *
- * OpenCDK is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * OpenCDK is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#ifndef CDK_MD_H
-#define CDK_MD_H
-
-cdk_md_hd_t cdk_md_open( int algo, unsigned int flags );
-cdk_md_hd_t cdk_md_copy( cdk_md_hd_t md );
-void cdk_md_write( cdk_md_hd_t md, const void *buf, size_t n );
-void cdk_md_close( cdk_md_hd_t md );
-void cdk_md_putc( cdk_md_hd_t md, int c );
-int cdk_md_test_algo( int algo );
-unsigned char * cdk_md_read( cdk_md_hd_t md, int algo );
-int cdk_md_get_algo_dlen( int algo );
-int cdk_md_final( cdk_md_hd_t md );
-int cdk_md_get_algo( cdk_md_hd_t md );
-int cdk_md_get_asnoid( int algo, unsigned char *buf, size_t *n );
-int cdk_md_reset( cdk_md_hd_t md);
-
-#endif /*CDK_MD_H*/
-
-
diff --git a/libextra/opencdk/misc.c b/libextra/opencdk/misc.c
index b0c0e35a8b..3164bf1ca0 100644
--- a/libextra/opencdk/misc.c
+++ b/libextra/opencdk/misc.c
@@ -1,7 +1,6 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * misc.c
+/* misc.c
* Copyright (C) 2002, 2003 Timo Schulz
- * Copyright (C) 1998-2002 Free Software Foundation, Inc.
+ * Copyright (C) 1998-2002, 2007 Free Software Foundation, Inc.
*
* This file is part of OpenCDK.
*
@@ -14,17 +13,11 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
@@ -33,92 +26,92 @@
#include "main.h"
-/* return 0 if the file exists. otherwise 1 */
+/* Return 0 if the file exists. otherwise 1 */
int
-_cdk_check_file( const char * file )
+_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;
+ 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);
+ return (u32)time (NULL);
}
u32
-_cdk_buftou32 (const byte * buf)
+_cdk_buftou32 (const byte *buf)
{
- u32 u = 0;
+ u32 u;
- if (buf) {
- u = buf[0] << 24;
- u |= buf[1] << 16;
- u |= buf[2] << 8;
- u |= buf[3];
- }
- return u;
+ if (!buf)
+ return 0;
+ u = buf[0] << 24;
+ u |= buf[1] << 16;
+ u |= buf[2] << 8;
+ u |= buf[3];
+ return u;
}
void
-_cdk_u32tobuf (u32 u, byte * buf)
+_cdk_u32tobuf (u32 u, byte *buf)
{
- if (buf) {
- buf[0] = u >> 24;
- buf[1] = u >> 16;
- buf[2] = u >> 8;
- buf[3] = u ;
- }
+ if (!buf)
+ return;
+ buf[0] = u >> 24;
+ buf[1] = u >> 16;
+ buf[2] = u >> 8;
+ buf[3] = u ;
}
int
-_cdk_strcmp (const char * a, const char * b)
+_cdk_strcmp (const char *a, const char *b)
{
- int alen, blen;
+ int alen, blen;
- alen = strlen (a);
- blen = strlen (b);
- if (alen != blen)
- return alen > blen? 1 : -1;
- return strcmp (a, b);
+ 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)
+parse_version_number( const char *s, int *number )
{
- int val = 0;
-
- if (*s == '0' && isdigit(s[1]))
- return NULL;
- /* leading zeros are not allowed */
- for (; isdigit(*s); s++) {
- val *= 10;
- val += *s - '0';
- }
- *number = val;
- return val < 0? NULL : s;
+ int val = 0;
+
+ if( *s == '0' && isdigit( s[1] ) )
+ return NULL;
+ /* leading zeros are not allowed */
+ for( ; isdigit(*s); s++ ) {
+ val *= 10;
+ val += *s - '0';
+ }
+ *number = val;
+ return val < 0? NULL : s;
}
static const char *
-parse_version_string (const char * s, int * major, int * minor, int * micro)
+parse_version_string( const char * s, int * major, int * minor, int * micro )
{
- s = parse_version_number (s, major);
- if (!s || *s != '.')
+ s = parse_version_number( s, major );
+ if( !s || *s != '.' )
return NULL;
s++;
s = parse_version_number (s, minor);
@@ -226,16 +219,16 @@ _cdk_memistr (const char *buf, size_t buflen, const char *sub)
const byte *t, *s;
size_t n;
- for (t = buf, n = buflen, s = sub ; n ; 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 (*s); t++, s++, n--)
+ n && toupper (*t) == toupper ((byte)*s); t++, s++, n--)
;
if (!*s)
return buf;
- t = buf;
+ t = (byte*)buf;
n = buflen;
- s = sub ;
+ s = (byte*)sub;
}
}
@@ -289,7 +282,7 @@ cdk_utf8_decode (const char * string, size_t length, int delim)
/* 2. pass (p!=NULL): create string */
for (;;)
{
- for (slen = length, nleft = encidx = 0, n = 0, s = string; slen;
+ for (slen = length, nleft = encidx = 0, n = 0, s = (byte*)string; slen;
s++, slen--)
{
if (resync)
@@ -299,7 +292,7 @@ cdk_utf8_decode (const char * string, size_t length, int delim)
/* still invalid */
if (p)
{
- sprintf (p, "\\x%02x", *s);
+ sprintf ((char*)p, "\\x%02x", *s);
p += 4;
}
n += 4;
@@ -353,7 +346,7 @@ cdk_utf8_decode (const char * string, size_t length, int delim)
n += 3;
if (p)
{
- sprintf (p, "x%02x", *s);
+ sprintf ((char*)p, "x%02x", *s);
p += 3;
}
break;
@@ -405,7 +398,7 @@ cdk_utf8_decode (const char * string, size_t length, int delim)
{ /* invalid encoding: print as \xnn */
if (p)
{
- sprintf (p, "\\x%02x", *s);
+ sprintf ((char*)p, "\\x%02x", *s);
p += 4;
}
n += 4;
@@ -418,10 +411,10 @@ cdk_utf8_decode (const char * string, size_t length, int delim)
{
for (i = 0; i < encidx; i++)
{
- sprintf (p, "\\x%02x", encbuf[i]);
+ sprintf ((char*)p, "\\x%02x", encbuf[i]);
p += 4;
}
- sprintf (p, "\\x%02x", *s);
+ sprintf ((char*)p, "\\x%02x", *s);
p += 4;
}
n += 4 + 4 * encidx;
@@ -448,7 +441,7 @@ cdk_utf8_decode (const char * string, size_t length, int delim)
{
for (i = 0; i < encidx; i++)
{
- sprintf (p, "\\x%02x", encbuf[i]);
+ sprintf ((char*)p, "\\x%02x", encbuf[i]);
p += 4;
}
}
@@ -464,107 +457,59 @@ cdk_utf8_decode (const char * string, size_t length, int delim)
else
{
*p = 0; /* make a string */
- return buffer;
+ return (char*)buffer;
}
}
}
-#ifndef HAVE_VASPRINTF
-/*
- * Like vsprintf but provides a pointer to malloc'd storage, which
- * must be freed by the caller (gcry_free). Taken from libiberty as
- * found in gcc-2.95.2 and a little bit modernized.
- */
-int
-_cdk_vasprintf ( char **result, const char *format, va_list args)
+cdk_error_t
+map_gcry_error (gcry_error_t err)
{
- const char *p = format;
- /* Add one to make sure that it is never zero, which might cause malloc
- to return NULL. */
- int total_width = strlen (format) + 1;
- va_list ap;
-
- /* this is not really portable but works under Windows */
- memcpy ( &ap, &args, sizeof (va_list));
-
- while (*p != '\0') {
- if (*p++ == '%') {
- while (strchr ("-+ #0", *p))
- ++p;
- if (*p == '*') {
- ++p;
- total_width += abs (va_arg (ap, int));
- }
- else {
- char *endp;
- total_width += strtoul (p, &endp, 10);
- p = endp;
- }
- if (*p == '.') {
- ++p;
- if (*p == '*') {
- ++p;
- total_width += abs (va_arg (ap, int));
- }
- else {
- char *endp;
- total_width += strtoul (p, &endp, 10);
- p = endp;
- }
- }
- while (strchr ("hlL", *p))
- ++p;
- /* Should be big enough for any format specifier except %s
- and floats. */
- total_width += 30;
- switch (*p) {
- case 'd':
- case 'i':
- case 'o':
- case 'u':
- case 'x':
- case 'X':
- case 'c':
- (void) va_arg (ap, int);
- break;
- case 'f':
- case 'e':
- case 'E':
- case 'g':
- case 'G':
- (void) va_arg (ap, double);
- /* Since an ieee double can have an exponent of 307, we'll
- make the buffer wide enough to cover the gross case. */
- total_width += 307;
-
- case 's':
- total_width += strlen (va_arg (ap, char *));
- break;
- case 'p':
- case 'n':
- (void) va_arg (ap, char *);
- break;
- }
- }
+ /* FIXME: We need to catch them all. */
+ switch (gpg_err_code (err))
+ {
+ case GPG_ERR_NO_ERROR: return CDK_Success;
+ case GPG_ERR_INV_VALUE: return CDK_Inv_Value;
+ case GPG_ERR_GENERAL: return CDK_General_Error;
+ case GPG_ERR_INV_PACKET: return CDK_Inv_Packet;
+ case GPG_ERR_TOO_SHORT: return CDK_Too_Short;
+ case GPG_ERR_TOO_LARGE: return CDK_Inv_Value;
+ case GPG_ERR_NO_PUBKEY:
+ case GPG_ERR_NO_SECKEY: return CDK_Error_No_Key;
+ case GPG_ERR_BAD_SIGNATURE: return CDK_Bad_Sig;
+ case GPG_ERR_NO_DATA: return CDK_No_Data;
+ default:
+ break;
}
- *result = gcry_malloc (total_width);
- if (*result != NULL)
- return vsprintf (*result, format, args);
- else
- return 0;
+
+ return (cdk_error_t)err;
}
+
void
-_cdk_vasprintf_free (void * p)
+_cdk_trim_string (char *s, int canon)
{
- cdk_free (p);
+ while (s && *s &&
+ (s[strlen (s)-1] == '\t' ||
+ s[strlen (s)-1] == '\r' ||
+ s[strlen (s)-1] == '\n' ||
+ s[strlen (s)-1] == ' '))
+ s[strlen (s) -1] = '\0';
+ if (canon)
+ strcat (s, "\r\n");
}
-#else /*!__MINGW32__*/
-void
-_cdk_vasprintf_free (void * p)
-{
- if (p)
- free (p);
+
+
+int
+_cdk_check_args (int overwrite, const char *in, const char *out)
+{
+ if (!in || !out)
+ return CDK_Inv_Value;
+ if (!_cdk_strcmp (in, out))
+ return CDK_Inv_Mode;
+ if (!overwrite && !_cdk_check_file (out))
+ return CDK_Inv_Mode;
+ return 0;
}
-#endif
+
diff --git a/libextra/opencdk/new-packet.c b/libextra/opencdk/new-packet.c
index 2ac3ca8e05..491166e007 100644
--- a/libextra/opencdk/new-packet.c
+++ b/libextra/opencdk/new-packet.c
@@ -1,6 +1,5 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * new-packet.c - General packet handling (freeing, copying, ...)
- * Copyright (C) 2001, 2002, 2003 Timo Schulz
+/* new-packet.c - packet handling (freeing, copying, ...)
+ * Copyright (C) 2001, 2002, 2003, 2007 Timo Schulz
*
* This file is part of OpenCDK.
*
@@ -13,12 +12,7 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
@@ -32,178 +26,185 @@
void
-_cdk_free_mpibuf( size_t n, gcry_mpi_t * array )
+_cdk_free_mpibuf (size_t n, gcry_mpi_t *array)
{
- while( n-- ) {
- gcry_mpi_release( array[n] );
- array[n] = NULL;
+ while (n--)
+ {
+ gcry_mpi_release (array[n]);
+ array[n] = NULL;
}
}
cdk_error_t
-cdk_pkt_new( cdk_packet_t* r_pkt )
+cdk_pkt_new (cdk_packet_t *r_pkt)
{
- cdk_packet_t pkt;
-
- if( !r_pkt )
- return CDK_Inv_Value;
- pkt = cdk_calloc( 1, sizeof *pkt );
- if( !pkt )
- return CDK_Out_Of_Core;
- *r_pkt = pkt;
- return 0;
-}
-
-
-void
-cdk_pkt_init( cdk_packet_t pkt )
-{
- if( pkt )
- memset( pkt, 0, sizeof * pkt );
+ cdk_packet_t pkt;
+
+ if (!r_pkt)
+ return CDK_Inv_Value;
+ pkt = cdk_calloc (1, sizeof *pkt);
+ if (!pkt)
+ return CDK_Out_Of_Core;
+ *r_pkt = pkt;
+ return 0;
}
static void
free_symkey_enc (cdk_pkt_symkey_enc_t enc)
{
- if (enc) {
- cdk_free (enc->s2k);
- cdk_free (enc);
- }
+ if (!enc)
+ return;
+ cdk_free (enc->s2k);
+ cdk_free (enc);
}
static void
free_pubkey_enc (cdk_pkt_pubkey_enc_t enc)
{
- int nenc;
- if (enc) {
- nenc = cdk_pk_get_nenc (enc->pubkey_algo);
- while (enc->mpi && nenc--) {
- cdk_free (enc->mpi[nenc]);
- enc->mpi[nenc] = NULL;
- }
- cdk_free (enc);
+ size_t nenc;
+
+ if (!enc)
+ return;
+
+ nenc = cdk_pk_get_nenc (enc->pubkey_algo);
+ while (nenc--)
+ {
+ gcry_mpi_release (enc->mpi[nenc]);
+ enc->mpi[nenc] = NULL;
}
+ cdk_free (enc);
}
static void
free_literal (cdk_pkt_literal_t pt)
{
- if (pt)
- cdk_free (pt);
+ if (!pt)
+ return;
+ /* The buffer which is referenced in this packet is closed
+ elsewhere. To close it here would cause a double close. */
+ cdk_free (pt);
}
void
_cdk_free_userid (cdk_pkt_userid_t uid)
{
- if (uid) {
- cdk_free (uid->prefs);
- uid->prefs = NULL;
- cdk_free (uid->attrib_img);
- uid->attrib_img = NULL;
- cdk_free (uid);
- }
+ if (!uid)
+ return;
+
+ cdk_free (uid->prefs);
+ uid->prefs = NULL;
+ cdk_free (uid->attrib_img);
+ uid->attrib_img = NULL;
+ cdk_free (uid);
}
void
_cdk_free_signature (cdk_pkt_signature_t sig)
{
- int nsig;
- cdk_desig_revoker_t r;
-
- if (sig) {
- nsig = cdk_pk_get_nsig (sig->pubkey_algo);
- while (sig->mpi && nsig--) {
- cdk_free (sig->mpi[nsig]);
- sig->mpi[nsig] = NULL;
- }
- cdk_subpkt_free (sig->hashed);
- sig->hashed = NULL;
- cdk_subpkt_free (sig->unhashed);
- sig->unhashed = NULL;
- while( sig->revkeys ) {
- r = sig->revkeys->next;
- cdk_free( sig->revkeys );
- sig->revkeys = r;
- }
- cdk_free (sig);
+ cdk_desig_revoker_t r;
+ size_t nsig;
+
+ if (!sig)
+ return;
+
+ nsig = cdk_pk_get_nsig (sig->pubkey_algo);
+ while (nsig--)
+ {
+ gcry_mpi_release (sig->mpi[nsig]);
+ sig->mpi[nsig] = NULL;
+ }
+ cdk_subpkt_free (sig->hashed);
+ sig->hashed = NULL;
+ cdk_subpkt_free (sig->unhashed);
+ sig->unhashed = NULL;
+ while (sig->revkeys)
+ {
+ r = sig->revkeys->next;
+ cdk_free (sig->revkeys);
+ sig->revkeys = r;
}
+ cdk_free (sig);
}
void
-_cdk_free_pubkey (cdk_pkt_pubkey_t pk)
-{
- int npkey;
- if (pk) {
- npkey = cdk_pk_get_npkey (pk->pubkey_algo);
- _cdk_free_userid (pk->uid);
- pk->uid = NULL;
- cdk_free (pk->prefs);
- pk->prefs = NULL;
- while (pk->mpi && npkey--) {
- cdk_free (pk->mpi[npkey]);
- pk->mpi[npkey] = NULL;
- }
- cdk_free (pk);
+cdk_pk_release (cdk_pubkey_t pk)
+{
+ size_t npkey;
+
+ if (!pk)
+ return;
+
+ npkey = cdk_pk_get_npkey (pk->pubkey_algo);
+ _cdk_free_userid (pk->uid);
+ pk->uid = NULL;
+ cdk_free (pk->prefs);
+ pk->prefs = NULL;
+ while (npkey--)
+ {
+ gcry_mpi_release (pk->mpi[npkey]);
+ pk->mpi[npkey] = NULL;
}
+ cdk_free (pk);
}
void
-_cdk_free_seckey (cdk_pkt_seckey_t sk)
-{
- int nskey;
-
- if (sk) {
- nskey = cdk_pk_get_nskey (sk->pubkey_algo);
- while (nskey--) {
- if (sk->mpi[nskey]) {
- wipemem (sk->mpi[nskey], sk->mpi[nskey]->bytes);
- cdk_free (sk->mpi[nskey]);
- sk->mpi[nskey] = NULL;
- }
- }
- cdk_free (sk->encdata);
- sk->encdata = NULL;
- _cdk_free_pubkey (sk->pk);
- sk->pk = NULL;
- cdk_free (sk->protect.s2k);
- sk->protect.s2k = NULL;
- cdk_free (sk);
- }
+cdk_sk_release (cdk_seckey_t sk)
+{
+ size_t nskey;
+
+ if (!sk)
+ return;
+
+ nskey = cdk_pk_get_nskey (sk->pubkey_algo);
+ while (nskey--)
+ gcry_mpi_release (sk->mpi[nskey]);
+ cdk_free (sk->encdata);
+ sk->encdata = NULL;
+ cdk_pk_release (sk->pk);
+ sk->pk = NULL;
+ cdk_free (sk->protect.s2k);
+ sk->protect.s2k = NULL;
+ cdk_free (sk);
}
static void
free_encrypted (cdk_pkt_encrypted_t enc)
{
- if (enc) {
- cdk_stream_close (enc->buf);
- enc->buf = NULL;
- cdk_free (enc);
- }
+ if (!enc)
+ return;
+
+ /* This is just a reference for the filters to know where
+ the encrypted data starts and to read from the sream. It
+ us closed elsewhere and to close it here would double close it. */
+ /*cdk_stream_close (enc->buf);*/
+ enc->buf = NULL;
+ cdk_free (enc);
}
void
cdk_pkt_free (cdk_packet_t pkt)
{
- if (!pkt)
- return;
-
- switch (pkt->pkttype) {
+ if (!pkt)
+ return;
+
+ switch (pkt->pkttype)
+ {
case CDK_PKT_ATTRIBUTE :
case CDK_PKT_USER_ID : _cdk_free_userid (pkt->pkt.user_id); break;
case CDK_PKT_PUBLIC_KEY :
- case CDK_PKT_PUBLIC_SUBKEY: _cdk_free_pubkey (pkt->pkt.public_key); break;
+ case CDK_PKT_PUBLIC_SUBKEY: cdk_pk_release (pkt->pkt.public_key); break;
case CDK_PKT_SECRET_KEY :
- case CDK_PKT_SECRET_SUBKEY: _cdk_free_seckey (pkt->pkt.secret_key); break;
+ case CDK_PKT_SECRET_SUBKEY: cdk_sk_release (pkt->pkt.secret_key); break;
case CDK_PKT_SIGNATURE : _cdk_free_signature (pkt->pkt.signature);break;
case CDK_PKT_PUBKEY_ENC : free_pubkey_enc (pkt->pkt.pubkey_enc); break;
case CDK_PKT_SYMKEY_ENC : free_symkey_enc (pkt->pkt.symkey_enc); break;
@@ -215,162 +216,151 @@ cdk_pkt_free (cdk_packet_t pkt)
case CDK_PKT_COMPRESSED : cdk_free (pkt->pkt.compressed); break;
default : break;
}
+ /* Reset the packet type to avoid, when cdk_pkt_release() will be
+ used, that the second cdk_pkt_free() call will double free the data. */
+ pkt->pkttype = 0;
}
void
cdk_pkt_release (cdk_packet_t pkt)
{
- if (pkt) {
- cdk_pkt_free (pkt);
- cdk_free (pkt);
- }
+ if (!pkt)
+ return;
+ cdk_pkt_free (pkt);
+ cdk_free (pkt);
}
cdk_error_t
-cdk_pkt_alloc( cdk_packet_t* r_pkt, int pkttype )
+cdk_pkt_alloc (cdk_packet_t *r_pkt, int pkttype)
{
- cdk_packet_t pkt;
- int rc = 0;
+ cdk_packet_t pkt;
+ int rc;
- if( !r_pkt )
- return CDK_Inv_Value;
-
- rc = cdk_pkt_new( &pkt );
- if( rc )
- return rc;
+ if (!r_pkt)
+ return CDK_Inv_Value;
+
+ rc = cdk_pkt_new (&pkt);
+ if (rc)
+ return rc;
- switch (pkttype) {
+ switch (pkttype)
+ {
case CDK_PKT_USER_ID:
- pkt->pkt.user_id = cdk_calloc (1, sizeof pkt->pkt.user_id);
- if (!pkt->pkt.user_id)
- return CDK_Out_Of_Core;
- break;
-
+ pkt->pkt.user_id = cdk_calloc (1, sizeof pkt->pkt.user_id);
+ if (!pkt->pkt.user_id)
+ return CDK_Out_Of_Core;
+ break;
+
case CDK_PKT_PUBLIC_KEY:
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;
- break;
-
+ pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key);
+ if (!pkt->pkt.public_key)
+ return CDK_Out_Of_Core;
+ break;
+
case CDK_PKT_SECRET_KEY:
case CDK_PKT_SECRET_SUBKEY:
- pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key);
- pkt->pkt.secret_key->pk =
- cdk_calloc (1, sizeof *pkt->pkt.secret_key->pk);
- if (!pkt->pkt.secret_key || !pkt->pkt.secret_key->pk)
- return CDK_Out_Of_Core;
- break;
-
+ pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key);
+ pkt->pkt.secret_key->pk =
+ cdk_calloc (1, sizeof *pkt->pkt.secret_key->pk);
+ if (!pkt->pkt.secret_key || !pkt->pkt.secret_key->pk)
+ return CDK_Out_Of_Core;
+ break;
+
case CDK_PKT_SIGNATURE:
- pkt->pkt.signature = cdk_calloc (1, sizeof *pkt->pkt.signature);
- if (!pkt->pkt.signature)
- return CDK_Out_Of_Core;
- break;
-
+ pkt->pkt.signature = cdk_calloc (1, sizeof *pkt->pkt.signature);
+ if (!pkt->pkt.signature)
+ return CDK_Out_Of_Core;
+ break;
+
+ case CDK_PKT_SYMKEY_ENC:
+ pkt->pkt.symkey_enc = cdk_calloc (1, sizeof *pkt->pkt.symkey_enc);
+ if (!pkt->pkt.symkey_enc)
+ return CDK_Out_Of_Core;
+ break;
+
case CDK_PKT_PUBKEY_ENC:
- pkt->pkt.pubkey_enc = cdk_calloc (1, sizeof *pkt->pkt.pubkey_enc);
- if (!pkt->pkt.pubkey_enc)
- return CDK_Out_Of_Core;
- break;
-
+ pkt->pkt.pubkey_enc = cdk_calloc (1, sizeof *pkt->pkt.pubkey_enc);
+ if (!pkt->pkt.pubkey_enc)
+ return CDK_Out_Of_Core;
+ break;
+
case CDK_PKT_MDC:
- pkt->pkt.mdc = cdk_calloc (1, sizeof *pkt->pkt.mdc);
- if (!pkt->pkt.mdc)
- return CDK_Out_Of_Core;
- break;
-
+ pkt->pkt.mdc = cdk_calloc (1, sizeof *pkt->pkt.mdc);
+ if (!pkt->pkt.mdc)
+ return CDK_Out_Of_Core;
+ break;
+
case CDK_PKT_ENCRYPTED_MDC:
case CDK_PKT_ENCRYPTED:
- pkt->pkt.symkey_enc = cdk_calloc (1, sizeof *pkt->pkt.symkey_enc);
- if (!pkt->pkt.symkey_enc)
- return CDK_Out_Of_Core;
- break;
-
+ pkt->pkt.symkey_enc = cdk_calloc (1, sizeof *pkt->pkt.symkey_enc);
+ if (!pkt->pkt.symkey_enc)
+ return CDK_Out_Of_Core;
+ break;
+
+ case CDK_PKT_ONEPASS_SIG:
+ pkt->pkt.onepass_sig = cdk_calloc (1, sizeof *pkt->pkt.onepass_sig);
+ if (!pkt->pkt.onepass_sig)
+ return CDK_Out_Of_Core;
+ break;
+
case CDK_PKT_LITERAL:
- pkt->pkt.literal = cdk_calloc (1, sizeof *pkt->pkt.literal);
- if (!pkt->pkt.literal)
- return CDK_Out_Of_Core;
- break;
+ /* FIXME: We would need the size of the file name to allocate extra
+ bytes, otherwise the result would be useless. */
+ pkt->pkt.literal = cdk_calloc (1, sizeof *pkt->pkt.literal);
+ if (!pkt->pkt.literal)
+ return CDK_Out_Of_Core;
+ break;
}
- pkt->pkttype = pkttype;
- *r_pkt = pkt;
- return 0;
+ pkt->pkttype = pkttype;
+ *r_pkt = pkt;
+ return 0;
}
-byte *
-cdk_userid_pref_get_array( cdk_pkt_userid_t id, int type, size_t *ret_len )
+cdk_prefitem_t
+_cdk_copy_prefs (const cdk_prefitem_t prefs)
{
- cdk_prefitem_t prefs;
- byte * p;
- int i = 0, j = 0;
-
- if( !id || !id->prefs || !ret_len )
- return NULL;
-
- prefs = id->prefs;
- while( prefs[i].type ) {
- if( prefs[i].type == type )
- j++;
- i++;
- }
- if( !j )
- return 0;
- p = cdk_calloc( 1, j + 1 );
- *ret_len = j;
- i = j = 0;
- while( prefs[i].type ) {
- if( prefs[i].type == type )
- p[j++] = prefs[i].value;
- i++;
+ size_t n = 0;
+ struct cdk_prefitem_s *new_prefs;
+
+ if (!prefs)
+ return NULL;
+
+ for (n = 0; prefs[n].type; n++)
+ ;
+ new_prefs = cdk_calloc (1, sizeof *new_prefs * (n + 1));
+ if (!new_prefs)
+ return NULL;
+ for (n = 0; prefs[n].type; n++)
+ {
+ new_prefs[n].type = prefs[n].type;
+ new_prefs[n].value = prefs[n].value;
}
- p[j] = 0;
- return p;
-}
-
-
-cdk_prefitem_t
-_cdk_copy_prefs( const cdk_prefitem_t prefs )
-{
- size_t n = 0;
- struct cdk_prefitem_s *new_prefs;
-
- if (!prefs)
- return NULL;
-
- for (n = 0; prefs[n].type; n++)
- ;
- new_prefs = cdk_calloc (1, sizeof *new_prefs * (n + 1));
- if (!new_prefs)
- return NULL;
- for (n = 0; prefs[n].type; n++) {
- new_prefs[n].type = prefs[n].type;
- new_prefs[n].value = prefs[n].value;
- }
- new_prefs[n].type = CDK_PREFTYPE_NONE;
- new_prefs[n].value = 0;
-
- return new_prefs;
+ new_prefs[n].type = CDK_PREFTYPE_NONE;
+ new_prefs[n].value = 0;
+ return new_prefs;
}
cdk_error_t
-_cdk_copy_userid (cdk_pkt_userid_t* dst, cdk_pkt_userid_t src)
+_cdk_copy_userid( cdk_pkt_userid_t* dst, cdk_pkt_userid_t src )
{
cdk_pkt_userid_t u;
if (!dst || !src)
return CDK_Inv_Value;
- u = cdk_calloc (1, sizeof *u + strlen (src->name) + 1);
+ u = cdk_calloc( 1, sizeof *u + strlen( src->name ) + 1 );
if (!u)
return CDK_Out_Of_Core;
memcpy (u, src, sizeof *u);
memcpy (u->name, src->name, strlen (src->name));
u->prefs = _cdk_copy_prefs (src->prefs);
+ if( src->selfsig )
+ _cdk_copy_signature( &u->selfsig, src->selfsig );
*dst = u;
return 0;
@@ -378,7 +368,7 @@ _cdk_copy_userid (cdk_pkt_userid_t* dst, cdk_pkt_userid_t src)
cdk_error_t
-_cdk_copy_pubkey (cdk_pkt_pubkey_t* dst, cdk_pkt_pubkey_t src)
+_cdk_copy_pubkey( cdk_pkt_pubkey_t* dst, cdk_pkt_pubkey_t src )
{
cdk_pkt_pubkey_t k;
int i;
@@ -394,15 +384,8 @@ _cdk_copy_pubkey (cdk_pkt_pubkey_t* dst, cdk_pkt_pubkey_t src)
_cdk_copy_userid (&k->uid, src->uid);
if (src->prefs)
k->prefs = _cdk_copy_prefs (src->prefs);
- for (i = 0; i < cdk_pk_get_npkey (src->pubkey_algo); i++) {
- k->mpi[i] = cdk_calloc (1, sizeof **k->mpi + src->mpi[i]->bytes + 2);
- if (!k->mpi[i])
- return CDK_Out_Of_Core;
- k->mpi[i]->bits = src->mpi[i]->bits;
- k->mpi[i]->bytes = src->mpi[i]->bytes;
- /* copy 2 extra bytes (prefix) */
- memcpy (k->mpi[i]->data, src->mpi[i]->data, src->mpi[i]->bytes + 2);
- }
+ for (i = 0; i < cdk_pk_get_npkey (src->pubkey_algo); i++)
+ k->mpi[i] = gcry_mpi_copy (src->mpi[i]);
*dst = k;
return 0;
@@ -413,7 +396,6 @@ cdk_error_t
_cdk_copy_seckey (cdk_pkt_seckey_t* dst, cdk_pkt_seckey_t src)
{
cdk_pkt_seckey_t k;
- cdk_mpi_t a;
cdk_s2k_t s2k;
int i;
@@ -441,14 +423,9 @@ _cdk_copy_seckey (cdk_pkt_seckey_t* dst, cdk_pkt_seckey_t src)
s2k->count = src->protect.s2k->count;
memcpy (s2k->salt, src->protect.s2k->salt, 8);
- for (i = 0; i < cdk_pk_get_nskey (src->pubkey_algo); i++) {
- a = k->mpi[i] = cdk_calloc (1, sizeof **k->mpi + src->mpi[i]->bytes + 2);
- if (!k->mpi[i])
- return CDK_Out_Of_Core;
- a->bits = src->mpi[i]->bits;
- a->bytes = src->mpi[i]->bytes;
- /* copy 2 extra bytes (prefix) */
- memcpy (a->data, src->mpi[i]->data, src->mpi[i]->bytes + 2);
+ for (i = 0; i < cdk_pk_get_nskey (src->pubkey_algo); i++) {
+ k->mpi[i] = gcry_mpi_copy (src->mpi[i]);
+ gcry_mpi_set_flag (k->mpi[i], GCRYMPI_FLAG_SECURE);
}
*dst = k;
@@ -477,27 +454,20 @@ _cdk_copy_pk_to_sk( cdk_pkt_pubkey_t pk, cdk_pkt_seckey_t sk )
cdk_error_t
-_cdk_copy_signature (cdk_pkt_signature_t* dst, cdk_pkt_signature_t src)
+_cdk_copy_signature( cdk_pkt_signature_t * dst, cdk_pkt_signature_t src )
{
- cdk_pkt_signature_t s = NULL;
- struct cdk_subpkt_s *res = NULL;
+ cdk_pkt_signature_t s;
- if (!dst || !src)
+ if( !dst || !src )
return CDK_Inv_Value;
- s = cdk_calloc (1, sizeof *s);
- if (!s)
+ s = cdk_calloc( 1, sizeof *s );
+ if( !s )
return CDK_Out_Of_Core;
- memcpy (s, src, sizeof *src);
-
- _cdk_subpkt_copy (&res, src->hashed);
- _cdk_subpkt_copy (&s->hashed, res);
- cdk_subpkt_free (res);
- res = NULL;
- _cdk_subpkt_copy (&res, src->unhashed);
- _cdk_subpkt_copy (&s->unhashed, res);
- cdk_subpkt_free (res);
- res = NULL;
+ memcpy( s, src, sizeof *src );
+ _cdk_subpkt_copy( &s->hashed, src->hashed );
+ _cdk_subpkt_copy( &s->unhashed, src->unhashed );
+ /* FIXME: Copy MPI parts */
*dst = s;
return 0;
@@ -519,7 +489,7 @@ _cdk_pubkey_compare (cdk_pkt_pubkey_t a, cdk_pkt_pubkey_t b)
return -1;
for (i = 0; i < na; i++) {
- if (memcmp (a->mpi[i]->data, b->mpi[i]->data, a->mpi[i]->bytes))
+ if (gcry_mpi_cmp (a->mpi[i], b->mpi[i]))
return -1;
}
@@ -534,14 +504,15 @@ _cdk_pubkey_compare (cdk_pkt_pubkey_t a, cdk_pkt_pubkey_t b)
* Release the context.
**/
void
-cdk_subpkt_free( cdk_subpkt_t ctx )
+cdk_subpkt_free (cdk_subpkt_t ctx)
{
- cdk_subpkt_t s;
-
- while( ctx ) {
- s = ctx->next;
- cdk_free( ctx );
- ctx = s;
+ cdk_subpkt_t s;
+
+ while (ctx)
+ {
+ s = ctx->next;
+ cdk_free (ctx);
+ ctx = s;
}
}
@@ -555,18 +526,57 @@ cdk_subpkt_free( cdk_subpkt_t ctx )
* type was found, return null otherwise pointer to the node.
**/
cdk_subpkt_t
-cdk_subpkt_find( cdk_subpkt_t ctx, int type )
+cdk_subpkt_find (cdk_subpkt_t ctx, size_t type)
{
- cdk_subpkt_t s;
+ return cdk_subpkt_find_nth (ctx, type, 0);
+}
- /* xxx: add some code for the case there are more than one sub packet
- with the same type. */
- for( s = ctx; s; s = s->next ) {
- if( s->type == type )
- return s;
+/**
+ * cdk_subpkt_type_count:
+ * @ctx: The sub packet context
+ * @type: The sub packet type.
+ *
+ * Return the amount of sub packets with this type.
+ **/
+size_t
+cdk_subpkt_type_count (cdk_subpkt_t ctx, size_t type)
+{
+ cdk_subpkt_t s;
+ size_t count;
+
+ count = 0;
+ for (s = ctx; s; s = s->next)
+ {
+ if (s->type == type)
+ count++;
}
+
+ return count;
+}
- return NULL;
+
+/**
+ * cdk_subpkt_find_nth:
+ * @ctx: The sub packet context
+ * @type: The sub packet type
+ * @index: The nth packet to retrieve, 0 means the first
+ *
+ * Return the nth sub packet of the given type.
+ **/
+cdk_subpkt_t
+cdk_subpkt_find_nth (cdk_subpkt_t ctx, size_t type, size_t idx)
+{
+ cdk_subpkt_t s;
+ size_t pos;
+
+ pos = 0;
+ for (s = ctx; s; s = s->next)
+ {
+ if (s->type == type && pos++ == idx)
+ return s;
+ }
+
+ return NULL;
}
@@ -577,16 +587,16 @@ cdk_subpkt_find( cdk_subpkt_t ctx, int type )
* Create a new sub packet node with the size of @size.
**/
cdk_subpkt_t
-cdk_subpkt_new( size_t size )
+cdk_subpkt_new (size_t size)
{
- cdk_subpkt_t s;
-
- if( !size )
- return NULL;
- s = cdk_calloc( 1, sizeof *s + size + 1 );
- if( !s )
- return NULL;
- return s;
+ cdk_subpkt_t s;
+
+ if (!size)
+ return NULL;
+ s = cdk_calloc (1, sizeof *s + size + 1);
+ if (!s)
+ return NULL;
+ return s;
}
@@ -599,17 +609,17 @@ cdk_subpkt_new( size_t size )
* Extract the data from the given sub packet. The type is returned
* in @r_type and the size in @r_nbytes.
**/
-const byte *
-cdk_subpkt_get_data( cdk_subpkt_t ctx, int * r_type, size_t * r_nbytes )
+const byte*
+cdk_subpkt_get_data (cdk_subpkt_t ctx, size_t *r_type, size_t *r_nbytes)
{
- if( !ctx || !r_nbytes )
- return NULL;
- if( r_type )
- *r_type = ctx->type;
- *r_nbytes = ctx->size;
- return ctx->d;
+ if (!ctx || !r_nbytes)
+ return NULL;
+ if (r_type)
+ *r_type = ctx->type;
+ *r_nbytes = ctx->size;
+ return ctx->d;
}
-
+
/**
* cdk_subpkt_add:
@@ -619,116 +629,108 @@ cdk_subpkt_get_data( cdk_subpkt_t ctx, int * r_type, size_t * r_nbytes )
* Add the node in @node to the root node @root.
**/
cdk_error_t
-cdk_subpkt_add( cdk_subpkt_t root, cdk_subpkt_t node )
+cdk_subpkt_add (cdk_subpkt_t root, cdk_subpkt_t node)
{
- cdk_subpkt_t n1;
+ cdk_subpkt_t n1;
- if( !root )
- return CDK_Inv_Value;
- for( n1 = root; n1->next; n1 = n1->next )
- ;
- n1->next = node;
- return 0;
+ if (!root)
+ return CDK_Inv_Value;
+ for (n1 = root; n1->next; n1 = n1->next)
+ ;
+ n1->next = node;
+ return 0;
}
-byte *
-_cdk_subpkt_get_array( cdk_subpkt_t s, int count, size_t * r_nbytes )
+byte*
+_cdk_subpkt_get_array (cdk_subpkt_t s, int count, size_t *r_nbytes)
{
- cdk_subpkt_t list;
- byte * buf;
- int n, nbytes;
+ cdk_subpkt_t list;
+ byte *buf;
+ size_t n, nbytes;
- if( !s ) {
- if( r_nbytes )
- *r_nbytes = 0;
- return NULL;
+ if (!s)
+ {
+ if (r_nbytes)
+ *r_nbytes = 0;
+ return NULL;
}
-
- for( n=0, list = s; list; list = list->next ) {
- n += list->size + 1;
- if( list->size < 192 ) n++;
- else if( list->size < 8384 ) n += 2;
- else n += 5;
+
+ for (n = 0, list = s; list; list = list->next)
+ {
+ n++; /* type */
+ n += list->size;
+ if (list->size < 192)
+ n++;
+ else if (list->size < 8384)
+ n += 2;
+ else
+ n += 5;
}
- buf = cdk_calloc( 1, n+1 );
- if( !buf )
- return NULL;
-
- n = 0;
- for( list = s; list; list = list->next ) {
- nbytes = 1 + list->size; /* type */
- if( nbytes < 192 )
- buf[n++] = nbytes;
- else if( nbytes < 8384 ) {
- buf[n++] = nbytes / 256 + 192;
- buf[n++] = nbytes % 256;
+ buf = cdk_calloc (1, n+1);
+ if (!buf)
+ return NULL;
+
+ n = 0;
+ for (list = s; list; list = list->next)
+ {
+ nbytes = 1 + list->size; /* type */
+ if (nbytes < 192)
+ buf[n++] = nbytes;
+ else if (nbytes < 8384)
+ {
+ buf[n++] = nbytes / 256 + 192;
+ buf[n++] = nbytes % 256;
}
- else {
- buf[n++] = 0xFF;
- buf[n++] = nbytes >> 24;
- buf[n++] = nbytes >> 16;
- buf[n++] = nbytes >> 8;
- buf[n++] = nbytes;
+ else
+ {
+ buf[n++] = 0xFF;
+ buf[n++] = nbytes >> 24;
+ buf[n++] = nbytes >> 16;
+ buf[n++] = nbytes >> 8;
+ buf[n++] = nbytes;
}
- buf[n++] = list->type;
- memcpy( buf + n, list->d, list->size );
- n += list->size;
+ buf[n++] = list->type;
+ memcpy (buf + n, list->d, list->size);
+ n += list->size;
}
- if( count ) {
- cdk_free( buf );
- buf = NULL;
+
+ if (count)
+ {
+ cdk_free (buf);
+ buf = NULL;
}
- if( r_nbytes )
- *r_nbytes = n;
- return buf;
+ if (r_nbytes)
+ *r_nbytes = n;
+ return buf;
}
cdk_error_t
-_cdk_subpkt_copy( cdk_subpkt_t * r_dst, cdk_subpkt_t src )
+_cdk_subpkt_copy (cdk_subpkt_t *r_dst, cdk_subpkt_t src)
{
- cdk_subpkt_t root, p, node;
-
- if (!src || !r_dst)
- return CDK_Inv_Value;
+ cdk_subpkt_t root, p, node;
+
+ if (!src || !r_dst)
+ return CDK_Inv_Value;
- root = NULL;
- for (p = src; p; p = p->next) {
- node = cdk_subpkt_new (p->size);
- if (node) {
- memcpy (node->d, p->d, p->size);
- node->type = p->type;
- node->size = p->size;
+ root = NULL;
+ for (p = src; p; p = p->next)
+ {
+ node = cdk_subpkt_new (p->size);
+ if (node)
+ {
+ memcpy (node->d, p->d, p->size);
+ node->type = p->type;
+ node->size = p->size;
}
- if (!root)
- root = node;
- else
- cdk_subpkt_add (root, node);
+ if (!root)
+ root = node;
+ else
+ cdk_subpkt_add (root, node);
}
- *r_dst = root;
- return 0;
-}
-
-
-cdk_error_t
-_cdk_subpkt_hash( cdk_subpkt_t hashed, size_t * r_nbytes, cdk_md_hd_t hd )
-{
- byte * p, buf[2];
- size_t nbytes;
-
- p = _cdk_subpkt_get_array (hashed, 0, &nbytes);
- if (!p)
- return CDK_Out_Of_Core;
- if (nbytes > 65535)
- return CDK_Inv_Value;
- buf[0] = nbytes >> 8;
- buf[1] = nbytes;
- cdk_md_write (hd, buf, 2);
- cdk_md_write (hd, p, nbytes);
- if (r_nbytes)
- *r_nbytes = nbytes;
- return 0;
+ *r_dst = root;
+ return 0;
}
@@ -742,34 +744,65 @@ _cdk_subpkt_hash( cdk_subpkt_t hashed, size_t * r_nbytes, cdk_md_hd_t hd )
* Set the packet data of the given root and set the type of it.
**/
void
-cdk_subpkt_init( cdk_subpkt_t node, int type, const void *buf, size_t buflen )
+cdk_subpkt_init (cdk_subpkt_t node, size_t type,
+ const void *buf, size_t buflen)
{
- if( node ) {
- node->type = type;
- node->size = buflen;
- memcpy( node->d, buf, buflen );
- }
+ if (!node)
+ return;
+ node->type = type;
+ node->size = buflen;
+ memcpy (node->d, buf, buflen);
}
+/* FIXME: We need to think of a public interface for it. */
const byte*
-cdk_key_desig_revoker_walk( cdk_desig_revoker_t root,
+cdk_key_desig_revoker_walk (cdk_desig_revoker_t root,
cdk_desig_revoker_t * ctx,
- int *r_class, int *r_algid )
+ int *r_class, int *r_algid)
{
- cdk_desig_revoker_t n;
-
- if( !*ctx ) {
- *ctx = root;
- n = root;
+ cdk_desig_revoker_t n;
+
+ if (! *ctx)
+ {
+ *ctx = root;
+ n = root;
+ }
+ else
+ {
+ n = (*ctx)->next;
+ *ctx = n;
}
- else {
- n = (*ctx)->next;
- *ctx = n;
+
+ if (n && r_class && r_algid)
+ {
+ *r_class = n->r_class;
+ *r_algid = n->algid;
}
- if( n && r_class && r_algid ) {
- *r_class = n->class;
- *r_algid = n->algid;
+
+ return n? n->fpr : NULL;
+}
+
+/**
+ * cdk_subpkt_find_next:
+ * @root: the base where to begin the iteration
+ * @type: the type to find or 0 for the next node.
+ *
+ * Try to find the next node after @root with type.
+ * If type is 0, the next node will be returned.
+ **/
+cdk_subpkt_t
+cdk_subpkt_find_next (cdk_subpkt_t root, size_t type)
+{
+ cdk_subpkt_t node;
+
+ for (node = root->next; node; node = node->next)
+ {
+ if (!type)
+ return node;
+ else if (node->type == type)
+ return node;
}
- return n? n->fpr : NULL;
+
+ return NULL;
}
diff --git a/libextra/opencdk/opencdk.h b/libextra/opencdk/opencdk.h
index 5eb4afb1d7..d47f335f9c 100644
--- a/libextra/opencdk/opencdk.h
+++ b/libextra/opencdk/opencdk.h
@@ -1,6 +1,6 @@
/* opencdk.h - Open Crypto Development Kit (OpenCDK)
- * Copyright (C) 2006, 2007 Free Software Foundation, Inc.
- * Copyright (C) 2001, 2002, 2003, 2005 Timo Schulz
+ * Copyright (C) 2001, 2002, 2003, 2007 Timo Schulz
+ * Copyright (C) 2006, 2007 Free Software Foundation, Inc.
*
* This file is part of OpenCDK.
*
@@ -13,18 +13,22 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef OPENCDK_H
#define OPENCDK_H
+#include <stddef.h> /* for size_t */
#include <stdarg.h>
+#include <gcrypt.h>
+
+/* The OpenCDK version as a string. */
+#define OPENCDK_VERSION "0.6.0"
-#define OPENCDK_VERSION "0.5.11"
+/* The OpenCDK version as integer components major.minor.path */
+#define OPENCDK_VERSION_MAJOR 0
+#define OPENCDK_VERSION_MINOR 6
+#define OPENCDK_VERSION_PATCH 0
#ifdef __cplusplus
extern "C" {
@@ -34,58 +38,64 @@ extern "C" {
#endif
/* General contexts */
+
+/* 'Session' handle to support the various options and run-time
+ information. */
struct cdk_ctx_s;
typedef struct cdk_ctx_s *cdk_ctx_t;
+/* A generic context to store list of strings. */
struct cdk_strlist_s;
typedef struct cdk_strlist_s *cdk_strlist_t;
-struct cdk_sesskey_s;
-typedef struct cdk_sesskey_s *cdk_sesskey_t;
-
+/* Context used to list keys of a keyring. */
struct cdk_listkey_s;
typedef struct cdk_listkey_s *cdk_listkey_t;
-
-struct cdk_mpi_s;
-typedef struct cdk_mpi_s *cdk_mpi_t;
+/* Opaque Data Encryption Key (DEK) context. */
struct cdk_dek_s;
typedef struct cdk_dek_s *cdk_dek_t;
+/* Opaque String to Key (S2K) handle. */
struct cdk_s2k_s;
typedef struct cdk_s2k_s *cdk_s2k_t;
struct cdk_stream_s;
typedef struct cdk_stream_s *cdk_stream_t;
+/* Opaque handle for the user ID preferences. */
struct cdk_prefitem_s;
typedef struct cdk_prefitem_s *cdk_prefitem_t;
+/* Node to store a single key node packet. */
struct cdk_kbnode_s;
typedef struct cdk_kbnode_s *cdk_kbnode_t;
+/* Key database handle. */
struct cdk_keydb_hd_s;
typedef struct cdk_keydb_hd_s *cdk_keydb_hd_t;
+/* Context to store a list of recipient keys. */
struct cdk_keylist_s;
typedef struct cdk_keylist_s *cdk_keylist_t;
+/* Context to encapsulate a single sub packet of a signature. */
struct cdk_subpkt_s;
typedef struct cdk_subpkt_s *cdk_subpkt_t;
+/* Context used to generate key pairs. */
struct cdk_keygen_ctx_s;
typedef struct cdk_keygen_ctx_s *cdk_keygen_ctx_t;
+/* Handle for a single designated revoker. */
struct cdk_desig_revoker_s;
typedef struct cdk_desig_revoker_s *cdk_desig_revoker_t;
-struct cdk_md_hd_s;
-typedef struct cdk_md_hd_s *cdk_md_hd_t;
+/* Alias for backward compatibility. */
+typedef gcry_mpi_t cdk_mpi_t;
-struct cdk_cipher_hd_s;
-typedef struct cdk_cipher_hd_s *cdk_cipher_hd_t;
-
+/* All valid error constants. */
typedef enum {
CDK_EOF = -1,
CDK_Success = 0,
@@ -95,7 +105,6 @@ typedef enum {
CDK_Inv_Packet = 4,
CDK_Inv_Algo = 5,
CDK_Not_Implemented = 6,
- CDK_Gcry_Error = 7,
CDK_Armor_Error = 8,
CDK_Armor_CRC_Error = 9,
CDK_MPI_Error = 10,
@@ -113,84 +122,100 @@ typedef enum {
CDK_Wrong_Format = 22,
CDK_Inv_Packet_Ver = 23,
CDK_Too_Short = 24,
- CDK_Unusable_Key = 25
+ CDK_Unusable_Key = 25,
+ CDK_No_Data = 26
} cdk_error_t;
enum cdk_control_flags {
- CDK_CTLF_SET = 0,
- CDK_CTLF_GET = 1,
- CDK_CTL_DIGEST = 10,
- CDK_CTL_CIPHER = 11,
- CDK_CTL_ARMOR = 12,
- CDK_CTL_COMPRESS = 13,
- CDK_CTL_COMPAT = 14,
- CDK_CTL_OVERWRITE = 15,
- CDK_CTL_S2K = 16,
+ CDK_CTLF_SET = 0, /* Value to set an option */
+ CDK_CTLF_GET = 1, /* Value to get an option */
+ CDK_CTL_DIGEST = 10, /* Option to set the digest algorithm. */
+ CDK_CTL_CIPHER = 11, /* Option to set the cipher algorithm. */
+ CDK_CTL_ARMOR = 12, /* Option to enable armor output. */
+ CDK_CTL_COMPRESS = 13, /* Option to enable compression. */
+ 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,
- CDK_CTL_TRUSTMODEL = 20
+ CDK_CTL_FORCE_DIGEST = 19, /* Force the use of a digest algorithm. */
+ CDK_CTL_BLOCKMODE_ON = 20 /* Enable partial body lengths */
};
+
+/* Specifies all valid log levels. */
enum cdk_log_level_t {
- CDK_LOG_NONE = 0,
+ CDK_LOG_NONE = 0, /* No log message will be shown. */
CDK_LOG_INFO = 1,
CDK_LOG_DEBUG = 2
};
+
+/* All valid compression algorithms in OpenPGP */
enum cdk_compress_algo_t {
- CDK_COMPRESS_NONE = 0,
- CDK_COMPRESS_ZIP = 1,
- CDK_COMPRESS_ZLIB = 2
+ CDK_COMPRESS_NONE = 0,
+ CDK_COMPRESS_ZIP = 1,
+ CDK_COMPRESS_ZLIB = 2,
+ CDK_COMPRESS_BZIP2 = 3 /* Not supported in this version */
};
-enum cdk_pk_algo_t {
+
+/* All valid public key algorithms valid in OpenPGP */
+enum cdk_pubkey_algo_t {
CDK_PK_RSA = 1,
- CDK_PK_RSA_E = 2,
- CDK_PK_RSA_S = 3,
+ CDK_PK_RSA_E = 2, /* RSA-E and RSA-S are deprecated use RSA instead */
+ CDK_PK_RSA_S = 3, /* and use the key flags in the self signatures. */
CDK_PK_ELG_E = 16,
- CDK_PK_DSA = 17,
- CDK_PK_ELG = 20
+ CDK_PK_DSA = 17
};
-enum cdk_md_algo_t {
+
+/* All valid message digest algorithms in OpenPGP. */
+enum cdk_digest_algo_t {
CDK_MD_NONE = 0,
CDK_MD_MD5 = 1,
CDK_MD_SHA1 = 2,
CDK_MD_RMD160 = 3,
- CDK_MD_MD2 = 5,
- CDK_MD_TIGER = 6, /* will be removed and thus: reserved */
- CDK_MD_SHA256 = 8
+ CDK_MD_SHA256 = 8,
+ CDK_MD_SHA384 = 9,
+ CDK_MD_SHA512 = 10,
+ CDK_MD_SHA224 = 11 /* This algorithm is NOT available. */
};
+
+/* All valid symmetric cipher algorithms in OpenPGP */
enum cdk_cipher_algo_t {
CDK_CIPHER_NONE = 0,
- CDK_CIPHER_IDEA = 1,
+ CDK_CIPHER_IDEA = 1, /* This algorithm is NOT available */
CDK_CIPHER_3DES = 2,
CDK_CIPHER_CAST5 = 3,
CDK_CIPHER_BLOWFISH = 4,
- CDK_CIPHER_SAFER_SK128 = 5, /* will be removed and thus: reserved */
- CDK_CIPHER_DES_SK = 6, /* will be removed and thus: reserved */
CDK_CIPHER_AES = 7,
CDK_CIPHER_AES192 = 8,
CDK_CIPHER_AES256 = 9,
CDK_CIPHER_TWOFISH = 10
};
+
+/* The valid 'String-To-Key' modes */
enum cdk_s2k_type_t {
CDK_S2K_SIMPLE = 0,
CDK_S2K_SALTED = 1,
CDK_S2K_ITERSALTED = 3
};
+
+/* The different kind of user ID preferences. */
enum cdk_pref_type_t {
CDK_PREFTYPE_NONE = 0,
- CDK_PREFTYPE_SYM = 1,
- CDK_PREFTYPE_HASH = 2,
- CDK_PREFTYPE_ZIP = 3
+ CDK_PREFTYPE_SYM = 1, /* Symmetric ciphers */
+ CDK_PREFTYPE_HASH = 2, /* Message digests */
+ CDK_PREFTYPE_ZIP = 3 /* Compression algorithms */
};
+
+/* All valid sub packet types. */
enum cdk_sig_subpacket_t {
CDK_SIGSUBPKT_NONE = 0,
CDK_SIGSUBPKT_SIG_CREATED = 2,
@@ -217,13 +242,7 @@ enum cdk_sig_subpacket_t {
};
-enum cdk_revoc_code_t {
- CDK_REVCOD_NOREASON = 0x00,
- CDK_REVCOD_SUPERCEDED = 0x01,
- CDK_REVCOD_COMPROMISED= 0x02,
- CDK_REVCOD_NOLONGUSED = 0x03
-};
-
+/* All valid armor types. */
enum cdk_armor_type_t {
CDK_ARMOR_MESSAGE = 0,
CDK_ARMOR_PUBKEY = 1,
@@ -232,27 +251,24 @@ enum cdk_armor_type_t {
CDK_ARMOR_CLEARSIG = 4
};
-enum cdk_stream_control_t {
- CDK_STREAMCTL_DISABLE = 2,
- CDK_STREAMCTL_COMPRESSED = 3
-};
-
enum cdk_keydb_flag_t {
- /* database search modes */
- CDK_DBSEARCH_EXACT = 1,
- CDK_DBSEARCH_SUBSTR = 2, /* sub string search */
+ /* Valid database search modes */
+ CDK_DBSEARCH_EXACT = 1, /* Exact string search */
+ CDK_DBSEARCH_SUBSTR = 2, /* Sub string search */
CDK_DBSEARCH_SHORT_KEYID = 3, /* 32-bit keyid search */
CDK_DBSEARCH_KEYID = 4, /* 64-bit keyid search */
CDK_DBSEARCH_FPR = 5, /* 160-bit fingerprint search */
- CDK_DBSEARCH_NEXT = 6, /* enumerate all keys */
- CDK_DBSEARCH_AUTO = 7, /* try automagically class search */
- /* database types */
- CDK_DBTYPE_PK_KEYRING = 100,
- CDK_DBTYPE_SK_KEYRING = 101,
- CDK_DBTYPE_DATA = 102
+ CDK_DBSEARCH_NEXT = 6, /* Enumerate all keys */
+ CDK_DBSEARCH_AUTO = 7, /* Try to classify the string */
+ /* Valid database types */
+ CDK_DBTYPE_PK_KEYRING = 100, /* A file with one or more public keys */
+ CDK_DBTYPE_SK_KEYRING = 101, /* A file with one or more secret keys */
+ CDK_DBTYPE_DATA = 102, /* A buffer with at least one public key */
+ CDK_DBTYPE_STREAM = 103 /* A stream is used to read keys from */
};
+/* All valid modes for cdk_data_transform() */
enum cdk_crypto_mode_t {
CDK_CRYPTYPE_NONE = 0,
CDK_CRYPTYPE_ENCRYPT = 1,
@@ -263,14 +279,26 @@ enum cdk_crypto_mode_t {
CDK_CRYPTYPE_IMPORT = 6
};
+
+/* A list of valid public key usages. */
+enum cdk_key_usage_t {
+ CDK_KEY_USG_ENCR = 1, /* Key can be used for encryption. */
+ CDK_KEY_USG_SIGN = 2, /* Key can be used for signing and certifying. */
+ CDK_KEY_USG_AUTH = 4 /* Key can be used for authentication. */
+};
+
+
+/* Valid flags for keys. */
enum cdk_key_flag_t {
CDK_KEY_VALID = 0,
- CDK_KEY_INVALID = 1, /* missing or wrong self signature */
- CDK_KEY_EXPIRED = 2,
- CDK_KEY_REVOKED = 4,
- CDK_KEY_NOSIGNER= 8
+ CDK_KEY_INVALID = 1, /* Missing or wrong self signature */
+ CDK_KEY_EXPIRED = 2, /* Key is expired. */
+ CDK_KEY_REVOKED = 4, /* Key has been revoked. */
+ CDK_KEY_NOSIGNER = 8
};
+
+/* Trust values and flags for keys and user IDs */
enum cdk_trust_flag_t {
CDK_TRUST_UNKNOWN = 0,
CDK_TRUST_EXPIRED = 1,
@@ -286,47 +314,32 @@ enum cdk_trust_flag_t {
};
-enum cdk_signature_id_t {
- /* signature status */
+/* Signature states and the signature modes. */
+enum cdk_signature_stat_t {
+ /* Signature status */
CDK_SIGSTAT_NONE = 0,
CDK_SIGSTAT_GOOD = 1,
CDK_SIGSTAT_BAD = 2,
CDK_SIGSTAT_NOKEY = 3,
- /* signature modes */
+ CDK_SIGSTAT_VALID = 4, /* True if made with a valid key. */
+ /* FIXME: We need indicators for revoked/expires signatures. */
+
+ /* Signature modes */
CDK_SIGMODE_NORMAL = 100,
CDK_SIGMODE_DETACHED = 101,
CDK_SIGMODE_CLEAR = 102
};
-enum cdk_attribute_t {
- /* cdk attributes */
- CDK_ATTR_CREATED = 1,
- CDK_ATTR_EXPIRE = 2,
- CDK_ATTR_KEYID = 3,
- CDK_ATTR_STATUS = 4,
- CDK_ATTR_NOTATION = 5,
- CDK_ATTR_ALGO_PK = 6,
- CDK_ATTR_ALGO_MD = 7,
- CDK_ATTR_VERSION = 8,
- CDK_ATTR_LEN = 9,
- CDK_ATTR_FLAGS = 10,
- CDK_ATTR_MPI = 11,
- CDK_ATTR_NAME = 12,
- CDK_ATTR_FPR = 13,
- CDK_ATTR_URL = 14,
- /* cdk key flags */
+
+/* Key flags. */
+typedef enum {
CDK_FLAG_KEY_REVOKED = 256,
CDK_FLAG_KEY_EXPIRED = 512,
CDK_FLAG_SIG_EXPIRED = 1024
-};
-
-
-enum cdk_callback_id_t {
- CDK_CB_NONE = 0,
- CDK_CB_PUBKEY_ENC = 1
-};
+} cdk_key_flags_t;
+/* Valid OpenPGP packet types and their IDs */
typedef enum {
CDK_PKT_RESERVED = 0,
CDK_PKT_PUBKEY_ENC = 1,
@@ -349,10 +362,42 @@ typedef enum {
CDK_PKT_MDC = 19
} cdk_packet_type_t;
+
+/* Helper macro to figure out if the packet is encrypted */
#define CDK_PKT_IS_ENCRYPTED(pkttype) (\
((pkttype)==CDK_PKT_ENCRYPTED_MDC) \
- || ((pkttype)==CDK_PKT_ENCRYPTED) \
- )
+ || ((pkttype)==CDK_PKT_ENCRYPTED))
+
+
+struct cdk_pkt_signature_s {
+ unsigned char version;
+ unsigned char sig_class;
+ unsigned int timestamp;
+ unsigned int expiredate;
+ unsigned int keyid[2];
+ unsigned char pubkey_algo;
+ unsigned char digest_algo;
+ unsigned char digest_start[2];
+ unsigned short hashed_size;
+ cdk_subpkt_t hashed;
+ unsigned short unhashed_size;
+ cdk_subpkt_t unhashed;
+ gcry_mpi_t mpi[2];
+ cdk_desig_revoker_t revkeys;
+ struct {
+ unsigned exportable:1;
+ unsigned revocable:1;
+ unsigned policy_url:1;
+ unsigned notation:1;
+ unsigned expired:1;
+ unsigned checked:1;
+ unsigned valid:1;
+ unsigned missing_key:1;
+ } flags;
+ unsigned int key[2]; /* only valid for key signatures */
+};
+typedef struct cdk_pkt_signature_s *cdk_pkt_signature_t;
+
struct cdk_pkt_userid_s {
unsigned int len;
@@ -360,14 +405,15 @@ struct cdk_pkt_userid_s {
unsigned is_revoked:1;
unsigned mdc_feature:1;
cdk_prefitem_t prefs;
+ size_t prefs_size;
unsigned char * attrib_img; /* Tag 17 if not null */
size_t attrib_len;
- size_t prefs_size;
- unsigned int created;
- char name[1];
+ cdk_pkt_signature_t selfsig;
+ char name[1];
};
typedef struct cdk_pkt_userid_s *cdk_pkt_userid_t;
+
struct cdk_pkt_pubkey_s {
unsigned char version;
unsigned char pubkey_algo;
@@ -376,7 +422,7 @@ struct cdk_pkt_pubkey_s {
unsigned int main_keyid[2];
unsigned int timestamp;
unsigned int expiredate;
- cdk_mpi_t mpi[4];
+ gcry_mpi_t mpi[4];
unsigned is_revoked:1;
unsigned is_invalid:1;
unsigned has_expired:1;
@@ -388,6 +434,10 @@ struct cdk_pkt_pubkey_s {
};
typedef struct cdk_pkt_pubkey_s *cdk_pkt_pubkey_t;
+/* Alias to define a generic public key context. */
+typedef cdk_pkt_pubkey_t cdk_pubkey_t;
+
+
struct cdk_pkt_seckey_s {
cdk_pkt_pubkey_t pk;
unsigned int expiredate;
@@ -404,7 +454,7 @@ struct cdk_pkt_seckey_s {
unsigned char ivlen;
} protect;
unsigned short csum;
- cdk_mpi_t mpi[4];
+ gcry_mpi_t mpi[4];
unsigned char * encdata;
size_t enclen;
unsigned char is_protected;
@@ -414,34 +464,9 @@ struct cdk_pkt_seckey_s {
};
typedef struct cdk_pkt_seckey_s *cdk_pkt_seckey_t;
-struct cdk_pkt_signature_s {
- unsigned char version;
- unsigned char sig_class;
- unsigned int timestamp;
- unsigned int expiredate;
- unsigned int keyid[2];
- unsigned char pubkey_algo;
- unsigned char digest_algo;
- unsigned char digest_start[2];
- unsigned short hashed_size;
- cdk_subpkt_t hashed;
- unsigned short unhashed_size;
- cdk_subpkt_t unhashed;
- cdk_mpi_t mpi[2];
- cdk_desig_revoker_t revkeys;
- struct {
- unsigned exportable:1;
- unsigned revocable:1;
- unsigned policy_url:1;
- unsigned notation:1;
- unsigned expired:1;
- unsigned checked:1;
- unsigned valid:1;
- unsigned missing_key:1;
- } flags;
- unsigned int key[2]; /* only valid for key signatures */
-};
-typedef struct cdk_pkt_signature_s *cdk_pkt_signature_t;
+/* Alias to define a generic secret key context. */
+typedef cdk_pkt_seckey_t cdk_seckey_t;
+
struct cdk_pkt_onepass_sig_s {
unsigned char version;
@@ -459,7 +484,7 @@ struct cdk_pkt_pubkey_enc_s {
unsigned int keyid[2];
int throw_keyid;
unsigned char pubkey_algo;
- cdk_mpi_t mpi[2];
+ gcry_mpi_t mpi[2];
};
typedef struct cdk_pkt_pubkey_enc_s * cdk_pkt_pubkey_enc_t;
@@ -508,10 +533,11 @@ struct cdk_pkt_compressed_s {
typedef struct cdk_pkt_compressed_s *cdk_pkt_compressed_t;
+/* Structure which represents a single OpenPGP packet. */
struct cdk_packet_s {
size_t pktlen; /* real packet length */
size_t pktsize; /* length with all headers */
- int old_ctb;
+ int old_ctb; /* 1 if RFC1991 mode is used */
cdk_packet_type_t pkttype;
union {
cdk_pkt_mdc_t mdc;
@@ -527,184 +553,308 @@ struct cdk_packet_s {
cdk_pkt_onepass_sig_t onepass_sig;
} pkt;
};
-typedef struct cdk_packet_s CDK_PACKET;
typedef struct cdk_packet_s *cdk_packet_t;
/*-- main.c --*/
/* memory routines */
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);
+void cdk_set_log_handler (cdk_log_fnc_t logfnc, void *opaque);
const char* cdk_strerror (int ec);
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_realloc_func) (void *p, size_t n),
void *(*new_calloc_func) (size_t m, size_t n),
void (*new_free_func) (void *));
int cdk_malloc_hook_initialized (void);
-void * cdk_malloc (size_t size);
-void * cdk_calloc (size_t n, size_t m);
-void * cdk_realloc (void * ptr, size_t size);
-void * cdk_salloc (size_t size, int clear);
-char * cdk_strdup (const char * ptr);
+void *cdk_malloc (size_t size);
+void *cdk_calloc (size_t n, size_t m);
+void *cdk_realloc (void * ptr, size_t size);
+void *cdk_salloc (size_t size, int clear);
+char *cdk_strdup (const char * ptr);
void cdk_free (void * ptr);
+
+/* Startup routines. */
+
+/* This function has to be called before any other
+ CDK function is executed. */
+void cdk_lib_startup (void);
+
+/* This function should be called before the application exists
+ to allow the lib to cleanup its internal structures. */
+void cdk_lib_shutdown (void);
+
/* session handle routines */
-int cdk_handle_new (cdk_ctx_t * r_ctx);
-void cdk_handle_free (cdk_ctx_t hd);
+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.
+ The type of the key db handle (public or secret) decides
+ which session key db handle to use. */
void cdk_handle_set_keydb (cdk_ctx_t hd, cdk_keydb_hd_t db);
-cdk_keydb_hd_t cdk_handle_get_keydb( cdk_ctx_t hd, int type );
-int cdk_handle_control( cdk_ctx_t hd, int action, int cmd, ... );
-void cdk_handle_set_callback (cdk_ctx_t hd,
- void (*cb) (void *opa, int type, const char * s),
- void * cb_value);
-void cdk_handle_set_passphrase_cb( cdk_ctx_t hd,
+
+/* Convenient function to avoid to open a key db first.
+ The user can directly use the file name, the rest is
+ done internally. */
+cdk_error_t cdk_handle_set_keyring (cdk_ctx_t hd, int type,
+ const char *kringname);
+
+/* Return keydb handle stored in the session handle. */
+cdk_keydb_hd_t cdk_handle_get_keydb (cdk_ctx_t hd, int type);
+int cdk_handle_control (cdk_ctx_t hd, int action, int cmd, ...);
+
+/* Set a passphrase callback for the given session handle. */
+void cdk_handle_set_passphrase_cb (cdk_ctx_t hd,
char *(*cb) (void *opa, const char *prompt),
- void * cb_value );
+ void *cb_value);
/* shortcuts for some controls */
-#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 ) \
- cdk_handle_control( (a), CDK_CTLF_SET, CDK_CTL_COMPRESS, (algo), (level) )
-
-
-/*-- cipher.c --*/
-void cdk_set_progress_handler (void (*cb)(void * hd, unsigned off,
- unsigned size), void * cb_value);
-
-/*-- new-packet.c --*/
-cdk_error_t cdk_pkt_new( cdk_packet_t * r_pkt );
-void cdk_pkt_init( cdk_packet_t pkt );
-cdk_error_t cdk_pkt_alloc( cdk_packet_t * r_pkt, int pkttype );
-void cdk_pkt_free( cdk_packet_t pkt );
-void cdk_pkt_release( cdk_packet_t pkt );
-cdk_error_t cdk_pkt_read( cdk_stream_t inp, cdk_packet_t pkt );
-cdk_error_t cdk_pkt_write( cdk_stream_t out, cdk_packet_t pkt );
-/* sub packet routines */
-cdk_subpkt_t cdk_subpkt_new( size_t size );
-void cdk_subpkt_free( cdk_subpkt_t ctx );
-cdk_subpkt_t cdk_subpkt_find( cdk_subpkt_t ctx, int type );
-cdk_error_t cdk_subpkt_add( cdk_subpkt_t root, cdk_subpkt_t node );
-const unsigned char * cdk_subpkt_get_data( cdk_subpkt_t ctx,
- int * r_type, size_t * r_nbytes );
-void cdk_subpkt_init( cdk_subpkt_t node, int type,
- const void *buf, size_t buflen );
-unsigned char * cdk_userid_pref_get_array( cdk_pkt_userid_t id, int type,
- size_t *ret_len );
-const unsigned char* cdk_key_desig_revoker_walk( cdk_desig_revoker_t root,
+#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) \
+ cdk_handle_control ((a), CDK_CTLF_SET, CDK_CTL_COMPRESS, (algo), (level))
+
+#define cdk_handle_set_blockmode(a, val) \
+ cdk_handle_control ((a), CDK_CTLF_SET, CDK_CTL_BLOCKMODE_ON, (val))
+
+/* Set the symmetric cipher for encryption. */
+#define cdk_handle_set_cipher(a, val) \
+ cdk_handle_control ((a), CDK_CTLF_SET, CDK_CTL_CIPHER, (val))
+
+/* Set the digest for the PK signing operation. */
+#define cdk_handle_set_digest(a, val) \
+ cdk_handle_control ((a), CDK_CTLF_SET, CDK_CTL_DIGEST, (val))
+
+/* Set the mode and the digest for the S2K operation. */
+#define cdk_handle_set_s2k(a, val1, val2) \
+ cdk_handle_control ((a), CDK_CTLF_SET, CDK_CTL_S2K, (val1), (val2))
+
+
+/* This context holds all information of the verification process. */
+struct cdk_verify_result_s {
+ int sig_ver; /* Version of the signature. */
+ int sig_status; /* The status (GOOD, BAD) of the signature */
+ int sig_flags; /* May contain expired or revoked flags */
+ unsigned int keyid[2]; /* The issuer key ID */
+ unsigned int created; /* Timestamp when the sig was created. */
+ unsigned int expires;
+ int pubkey_algo;
+ int digest_algo;
+ char *user_id; /* NULL or user ID which issued the signature. */
+ char *policy_url; /* If set, the policy the sig was created under. */
+ size_t sig_len; /* Size of the signature data inbits. */
+ unsigned char *sig_data; /* Raw signature data. */
+};
+typedef struct cdk_verify_result_s *cdk_verify_result_t;
+
+/* Return the verify result. Do not free the data. */
+cdk_verify_result_t cdk_handle_verify_get_result (cdk_ctx_t hd);
+
+/* Raw packet routines. */
+cdk_error_t cdk_pkt_new (cdk_packet_t *r_pkt);
+cdk_error_t cdk_pkt_alloc (cdk_packet_t *r_pkt, int pkttype);
+
+/* Only release the contents of the packet but not @PKT itself. */
+void cdk_pkt_free (cdk_packet_t pkt);
+
+/* Release the packet contents and the packet structure @PKT itself. */
+void cdk_pkt_release (cdk_packet_t pkt);
+
+/* Read or write the given output from or to the stream. */
+cdk_error_t cdk_pkt_read (cdk_stream_t inp, cdk_packet_t pkt);
+cdk_error_t cdk_pkt_write (cdk_stream_t out, cdk_packet_t pkt);
+
+/* Sub packet routines */
+cdk_subpkt_t cdk_subpkt_new (size_t size);
+void cdk_subpkt_free (cdk_subpkt_t ctx);
+cdk_subpkt_t cdk_subpkt_find (cdk_subpkt_t ctx, size_t type);
+cdk_subpkt_t cdk_subpkt_find_next (cdk_subpkt_t root, size_t type);
+size_t cdk_subpkt_type_count (cdk_subpkt_t ctx, size_t type);
+cdk_subpkt_t cdk_subpkt_find_nth (cdk_subpkt_t ctx, size_t type, size_t index);
+cdk_error_t cdk_subpkt_add (cdk_subpkt_t root, cdk_subpkt_t node);
+const unsigned char * cdk_subpkt_get_data (cdk_subpkt_t ctx,
+ size_t * r_type, size_t *r_nbytes);
+void cdk_subpkt_init (cdk_subpkt_t node, size_t type,
+ const void *buf, size_t buflen);
+
+/* Designated Revoker routines */
+const unsigned char* cdk_key_desig_revoker_walk (cdk_desig_revoker_t root,
cdk_desig_revoker_t * ctx,
- int *r_class, int *r_algid );
+ int *r_class, int *r_algid);
/*-- pubkey.c --*/
#define is_RSA(a) ((a) == CDK_PK_RSA \
|| (a) == CDK_PK_RSA_E \
|| (a) == CDK_PK_RSA_S)
-#define is_ELG(a) ((a) == CDK_PK_ELG || (a) == CDK_PK_ELG_E)
+#define is_ELG(a) ((a) == CDK_PK_ELG_E)
#define is_DSA(a) ((a) == CDK_PK_DSA)
-cdk_error_t cdk_pk_encrypt (cdk_pkt_pubkey_t pk, cdk_pkt_pubkey_enc_t pke,
- cdk_sesskey_t esk);
-cdk_error_t cdk_pk_decrypt (cdk_pkt_seckey_t sk, cdk_pkt_pubkey_enc_t pke,
- cdk_sesskey_t *r_sk);
-cdk_error_t cdk_pk_sign (cdk_pkt_seckey_t sk, cdk_pkt_signature_t sig,
+cdk_error_t cdk_pk_encrypt (cdk_pubkey_t pk, cdk_pkt_pubkey_enc_t pke,
+ gcry_mpi_t esk);
+cdk_error_t cdk_pk_decrypt (cdk_seckey_t sk, cdk_pkt_pubkey_enc_t pke,
+ gcry_mpi_t *r_sk);
+cdk_error_t cdk_pk_sign (cdk_seckey_t sk, cdk_pkt_signature_t sig,
const unsigned char * md);
-cdk_error_t cdk_pk_verify (cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig,
- const unsigned char * md);
-cdk_error_t cdk_pk_get_mpi (cdk_pkt_pubkey_t pk, int idx,
- unsigned char * buf, size_t * r_count, size_t * r_nbits);
-cdk_error_t cdk_sk_get_mpi (cdk_pkt_seckey_t sk, int idx,
- unsigned char * buf, size_t * r_count, size_t * r_nbits);
-int cdk_pk_get_nbits (cdk_pkt_pubkey_t pk);
+cdk_error_t cdk_pk_verify (cdk_pubkey_t pk, cdk_pkt_signature_t sig,
+ 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. */
+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);
+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
+ for the given object. */
+int cdk_pk_get_nbits (cdk_pubkey_t pk);
int cdk_pk_get_npkey (int algo);
int cdk_pk_get_nskey (int algo);
int cdk_pk_get_nsig (int algo);
int cdk_pk_get_nenc (int algo);
-int cdk_pk_get_fingerprint (cdk_pkt_pubkey_t pk, unsigned char * fpr);
-unsigned int cdk_pk_fingerprint_get_keyid (const unsigned char * fpr,
+
+/* Fingerprint and key ID routines. */
+cdk_error_t cdk_pk_get_fingerprint (cdk_pubkey_t pk, unsigned char *fpr);
+unsigned int cdk_pk_fingerprint_get_keyid (const unsigned char *fpr,
size_t fprlen,
- unsigned int * keyid);
-unsigned int cdk_pk_get_keyid (cdk_pkt_pubkey_t pk, unsigned int * keyid);
-unsigned int cdk_sk_get_keyid (cdk_pkt_seckey_t sk, unsigned int * keyid);
+ unsigned int *keyid);
+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);
-cdk_error_t cdk_sk_unprotect( cdk_pkt_seckey_t sk, const char * pw );
-cdk_error_t cdk_sk_protect( cdk_pkt_seckey_t sk, const char * pw );
-cdk_error_t cdk_pk_from_secret_key( cdk_pkt_seckey_t sk,
- cdk_pkt_pubkey_t *ret_pk );
-cdk_error_t cdk_pubkey_to_sexp (cdk_pkt_pubkey_t pk,
- char **sexp, size_t * len);
-cdk_error_t cdk_seckey_to_sexp (cdk_pkt_seckey_t sk,
- char **sexp, size_t * len);
-
-/*-- seskey.c --*/
-cdk_error_t cdk_sesskey_new( cdk_sesskey_t * r_sk );
-void cdk_sesskey_free( cdk_sesskey_t sk );
-cdk_error_t cdk_dek_new( cdk_dek_t * r_dek );
-void cdk_dek_free( cdk_dek_t dek );
-cdk_error_t cdk_dek_set_cipher( cdk_dek_t dek, int algo );
-cdk_error_t cdk_dek_set_key( cdk_dek_t dek, const unsigned char *key,
- size_t keylen );
-cdk_error_t cdk_dek_from_passphrase( cdk_dek_t * ret_dek, int cipher_algo,
- cdk_s2k_t s2k, int mode,
- const char * pw );
-cdk_error_t cdk_dek_encode_pkcs1( cdk_dek_t dek, int nbits,
- cdk_sesskey_t * r_esk );
-cdk_error_t cdk_dek_decode_pkcs1( cdk_dek_t * ret_dek, cdk_sesskey_t esk );
-cdk_error_t cdk_dek_extract( cdk_dek_t * ret_dek, cdk_ctx_t hd,
- cdk_pkt_pubkey_enc_t enc,
- cdk_pkt_seckey_t sk );
-void cdk_dek_set_mdc_flag( cdk_dek_t dek, int val );
-/* string to key */
-cdk_error_t cdk_s2k_new (cdk_s2k_t * ret_s2k, int mode, int algo,
- const unsigned char * salt);
+
+/* Key release functions. */
+void cdk_pk_release (cdk_pubkey_t pk);
+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_pk_from_secret_key (cdk_seckey_t sk,
+ cdk_pubkey_t *ret_pk);
+
+/* Sexp conversion of keys. */
+cdk_error_t cdk_pubkey_to_sexp (cdk_pubkey_t pk,
+ char **sexp, size_t *len);
+cdk_error_t cdk_seckey_to_sexp (cdk_seckey_t sk,
+ char **sexp, size_t *len);
+
+
+/* Data Encryption Key (DEK) routines */
+cdk_error_t cdk_dek_new (cdk_dek_t *r_dek);
+void cdk_dek_free (cdk_dek_t dek);
+cdk_error_t cdk_dek_set_cipher (cdk_dek_t dek, int cipher_algo);
+cdk_error_t cdk_dek_set_key (cdk_dek_t dek, const unsigned char *key,
+ size_t keylen);
+void cdk_dek_set_mdc_flag (cdk_dek_t dek, int val);
+
+/* Transform the given passphrase into a DEK.
+ If @rndsalt is set, a random salt will be generated. */
+cdk_error_t cdk_dek_from_passphrase (cdk_dek_t *ret_dek, int cipher_algo,
+ cdk_s2k_t s2k, int rndsalt,
+ const char *passphrase);
+
+/* String to Key routines. */
+cdk_error_t cdk_s2k_new (cdk_s2k_t *ret_s2k, int mode, int digest_algo,
+ const unsigned char *salt);
void cdk_s2k_free (cdk_s2k_t s2k);
/*-- armor.c --*/
-cdk_error_t cdk_file_armor( cdk_ctx_t hd, const char * file,
- const char * output );
-cdk_error_t cdk_file_dearmor( const char * file, const char * output );
-cdk_error_t cdk_armor_filter_use (cdk_stream_t inp);
+cdk_error_t cdk_file_armor (cdk_ctx_t hd, const char *file,
+ const char *output);
+cdk_error_t cdk_file_dearmor (const char * file, const char *output);
+int cdk_armor_filter_use (cdk_stream_t inp);
+
+/* Protect the inbuf with ASCII armor of the specified type.
+ If @outbuf and @outlen are NULL, the function returns the calculated
+ size of the base64 encoded data in @nwritten. */
+cdk_error_t cdk_armor_encode_buffer (const unsigned char *inbuf, size_t inlen,
+ char *outbuf, size_t outlen,
+ size_t *nwritten, int type);
+
/*-- stream.c --*/
-int cdk_stream_control (cdk_stream_t s, int ctl, int val);
+/* This context contain user callbacks for different stream operations.
+ Some of these callbacks might be NULL to indicate that the callback
+ is not used. */
+struct cdk_stream_cbs_s
+{
+ cdk_error_t (*open)(void *);
+ cdk_error_t (*release)(void *);
+ int (*read)(void *, void *buf, size_t);
+ int (*write)(void *, const void *buf, size_t);
+ int (*seek)(void *, off_t);
+};
+typedef struct cdk_stream_cbs_s *cdk_stream_cbs_t;
+
+
+int cdk_stream_is_compressed (cdk_stream_t s);
cdk_error_t cdk_stream_open (const char * file, cdk_stream_t * ret_s);
cdk_error_t cdk_stream_new (const char * file, cdk_stream_t * ret_s);
+cdk_error_t cdk_stream_new_from_cbs (cdk_stream_cbs_t cbs, void *opa,
+ cdk_stream_t *ret_s);
cdk_error_t cdk_stream_create (const char * file, cdk_stream_t * ret_s);
-cdk_stream_t cdk_stream_tmp (void);
-cdk_stream_t cdk_stream_tmp_from_mem (const void * buf, size_t count);
+cdk_error_t cdk_stream_tmp_new (cdk_stream_t *r_out);
+cdk_error_t cdk_stream_tmp_from_mem (const void * buf, size_t buflen,
+ cdk_stream_t *r_out);
void cdk_stream_tmp_set_mode (cdk_stream_t s, int val);
cdk_error_t cdk_stream_flush (cdk_stream_t s);
-cdk_error_t cdk_stream_set_cache (cdk_stream_t s, int val);
+cdk_error_t cdk_stream_enable_cache (cdk_stream_t s, int val);
cdk_error_t cdk_stream_filter_disable (cdk_stream_t s, int type);
cdk_error_t cdk_stream_close (cdk_stream_t s);
-unsigned cdk_stream_get_length (cdk_stream_t s);
+off_t cdk_stream_get_length (cdk_stream_t s);
int cdk_stream_read (cdk_stream_t s, void * buf, size_t count);
int cdk_stream_write (cdk_stream_t s, const void * buf, size_t count);
int cdk_stream_putc (cdk_stream_t s, int c);
int cdk_stream_getc (cdk_stream_t s);
int cdk_stream_eof (cdk_stream_t s);
-long cdk_stream_tell (cdk_stream_t s);
-cdk_error_t cdk_stream_seek (cdk_stream_t s, long offset);
+off_t cdk_stream_tell (cdk_stream_t s);
+cdk_error_t cdk_stream_seek (cdk_stream_t s, off_t offset);
cdk_error_t 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_error_t 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_error_t cdk_stream_set_compress_flag (cdk_stream_t s, int algo, int level);
cdk_error_t cdk_stream_set_hash_flag (cdk_stream_t s, int algo);
cdk_error_t cdk_stream_set_text_flag (cdk_stream_t s, const char * lf);
cdk_error_t cdk_stream_kick_off (cdk_stream_t inp, cdk_stream_t out);
-cdk_error_t cdk_stream_mmap( cdk_stream_t s, unsigned char ** ret_buf,
- size_t * ret_count );
-int cdk_stream_peek( cdk_stream_t inp, unsigned char *s, size_t count );
+cdk_error_t cdk_stream_mmap (cdk_stream_t s, unsigned char **ret_buf,
+ size_t *ret_buflen);
+cdk_error_t cdk_stream_mmap_part (cdk_stream_t s, off_t off, size_t len,
+ unsigned char **ret_buf, size_t *ret_buflen);
+
+/* Read from the stream but restore the file pointer after reading
+ the requested amount of bytes. */
+int cdk_stream_peek (cdk_stream_t inp, unsigned char *buf, size_t buflen);
/*-- keydb.c --*/
-cdk_error_t cdk_keydb_new( cdk_keydb_hd_t * r_hd, int type, void * data,
+
+/* A wrapper around the various new_from_XXX functions. Because
+ the function does not support all combinations, the dedicated
+ functions should be preferred. */
+cdk_error_t cdk_keydb_new (cdk_keydb_hd_t *r_hd, int type, void *data,
size_t count);
-cdk_error_t cdk_keydb_open( cdk_keydb_hd_t hd, cdk_stream_t * ret_kr );
-int cdk_keydb_check_sk( cdk_keydb_hd_t hd, unsigned int * keyid );
-cdk_error_t cdk_keydb_search_start( cdk_keydb_hd_t db, int type, void * desc );
-cdk_error_t cdk_keydb_search( cdk_keydb_hd_t hd, cdk_kbnode_t * ret_key );
+
+cdk_error_t cdk_keydb_new_from_mem (cdk_keydb_hd_t *r_hd, int secret,
+ const void *data, size_t datlen);
+cdk_error_t cdk_keydb_new_from_file (cdk_keydb_hd_t *r_hd, int secret,
+ const char *fname);
+
+/* Uses a stream as the key db input. For searching it is important
+ that the seek function is supported on the stream. Furthermore,
+ the stream is not closed in cdk_keydb_free(). The caller must do it. */
+cdk_error_t cdk_keydb_new_from_stream (cdk_keydb_hd_t *r_hd, int secret,
+ cdk_stream_t in);
+
+/* 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);
+
+cdk_error_t cdk_keydb_search_start (cdk_keydb_hd_t hd, int type, void *desc);
+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 );
@@ -713,16 +863,15 @@ cdk_error_t cdk_keydb_get_byfpr( cdk_keydb_hd_t hd, const unsigned char * fpr,
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_pkt_pubkey_t* ret_pk );
+ cdk_pubkey_t* ret_pk );
cdk_error_t cdk_keydb_get_sk( cdk_keydb_hd_t khd, unsigned int * keyid,
- cdk_pkt_seckey_t* ret_sk );
-cdk_error_t cdk_keydb_get_keyblock( cdk_stream_t inp, cdk_kbnode_t * ret_key );
-cdk_error_t cdk_keydb_idx_rebuild( cdk_keydb_hd_t hd );
-cdk_error_t cdk_keydb_export( cdk_keydb_hd_t hd, cdk_stream_t out,
- cdk_strlist_t remusr );
-cdk_error_t cdk_keydb_import( cdk_keydb_hd_t hd, cdk_kbnode_t knode,
- int *result );
-cdk_error_t cdk_keydb_pk_cache_sigs( cdk_kbnode_t pk, cdk_keydb_hd_t hd );
+ cdk_seckey_t* ret_sk );
+cdk_error_t cdk_keydb_get_keyblock (cdk_stream_t inp, cdk_kbnode_t * ret_key);
+cdk_error_t cdk_keydb_idx_rebuild (cdk_keydb_hd_t hd);
+cdk_error_t cdk_keydb_export (cdk_keydb_hd_t hd, cdk_stream_t out,
+ cdk_strlist_t remusr);
+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,
@@ -737,79 +886,89 @@ cdk_error_t cdk_kbnode_read_from_mem (cdk_kbnode_t * ret_node,
size_t buflen);
cdk_error_t cdk_kbnode_write_to_mem (cdk_kbnode_t node,
unsigned char * buf, size_t * r_nbytes);
+cdk_error_t cdk_kbnode_write_to_mem_alloc (cdk_kbnode_t node,
+ unsigned char **r_buf,
+ size_t *r_buflen);
+
void cdk_kbnode_release (cdk_kbnode_t node);
cdk_kbnode_t cdk_kbnode_walk (cdk_kbnode_t root, cdk_kbnode_t * ctx, int all);
cdk_packet_t cdk_kbnode_find_packet (cdk_kbnode_t node, int pkttype);
cdk_packet_t cdk_kbnode_get_packet (cdk_kbnode_t node);
cdk_kbnode_t cdk_kbnode_find (cdk_kbnode_t node, int pkttype);
-cdk_kbnode_t cdk_kbnode_find_prev( cdk_kbnode_t root, cdk_kbnode_t node,
- int pkttype );
+cdk_kbnode_t cdk_kbnode_find_prev (cdk_kbnode_t root, cdk_kbnode_t node,
+ int pkttype);
cdk_kbnode_t cdk_kbnode_find_next (cdk_kbnode_t node, int pkttype);
-void * cdk_kbnode_get_attr( cdk_kbnode_t node, int pkttype, int attr );
-cdk_error_t cdk_kbnode_hash( cdk_kbnode_t node, cdk_md_hd_t md, int is_v4,
- int pkttype, int flags );
+cdk_error_t cdk_kbnode_hash (cdk_kbnode_t node, gcry_md_hd_t md, int is_v4,
+ int pkttype, int flags);
/*-- sig-check.c --*/
-cdk_error_t cdk_pk_check_sigs( cdk_kbnode_t knode, cdk_keydb_hd_t hd,
- int * r_status );
+
+/* Check each signature in the key node and return a summary of the
+ key status in @r_status. Values of cdk_key_flag_t are used. */
+cdk_error_t cdk_pk_check_sigs (cdk_kbnode_t knode, cdk_keydb_hd_t hd,
+ int *r_status);
+
+/* Check the self signature of the key to make sure it is valid. */
+cdk_error_t cdk_pk_check_self_sig (cdk_kbnode_t knode, int *r_status);
/*-- keylist.c --*/
-int cdk_pklist_select_algo( cdk_keylist_t pkl, int preftype );
+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,
- cdk_strlist_t remusr, int use );
+cdk_error_t cdk_pklist_build (cdk_keylist_t *ret_pkl, cdk_keydb_hd_t hd,
+ cdk_strlist_t remusr, int use);
void cdk_pklist_release (cdk_keylist_t pkl);
-cdk_error_t cdk_pklist_encrypt (cdk_keylist_t pk_list, cdk_dek_t dek,
- cdk_stream_t outp);
+cdk_error_t cdk_pklist_encrypt (cdk_keylist_t pkl, cdk_dek_t dek,
+ cdk_stream_t out);
+
/* secret key list */
-cdk_error_t cdk_sklist_build( cdk_keylist_t * ret_skl,
+cdk_error_t cdk_sklist_build (cdk_keylist_t * ret_skl,
cdk_keydb_hd_t db, cdk_ctx_t hd,
cdk_strlist_t locusr,
- int unlock, unsigned int use );
+ int unlock, unsigned int use);
void cdk_sklist_release (cdk_keylist_t skl);
cdk_error_t cdk_sklist_write (cdk_keylist_t skl, cdk_stream_t outp,
- cdk_md_hd_t hash,
+ gcry_md_hd_t mdctx,
int sigclass, int sigver);
-cdk_error_t cdk_sklist_write_onepass( cdk_keylist_t skl, cdk_stream_t outp,
- int sigclass, int mdalgo );
+cdk_error_t cdk_sklist_write_onepass (cdk_keylist_t skl, cdk_stream_t outp,
+ int sigclass, int mdalgo);
/*-- encrypt.c --*/
cdk_error_t cdk_stream_encrypt (cdk_ctx_t hd, cdk_strlist_t remusr,
cdk_stream_t inp, cdk_stream_t out);
-cdk_error_t cdk_stream_decrypt (cdk_ctx_t hd, cdk_stream_t inp,
+cdk_error_t cdk_stream_decrypt (cdk_ctx_t hd, cdk_stream_t inp,
cdk_stream_t out);
+
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);
-cdk_error_t cdk_data_transform( cdk_ctx_t hd, enum cdk_crypto_mode_t mode,
+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,
unsigned char ** outbuf, size_t * outsize,
- int modval );
+ int modval);
/*-- sign.c --*/
-cdk_error_t cdk_stream_sign( cdk_ctx_t hd, cdk_stream_t inp, cdk_stream_t out,
+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 );
-cdk_error_t cdk_file_sign( cdk_ctx_t hd, cdk_strlist_t locusr,
+cdk_error_t cdk_file_sign (cdk_ctx_t hd, cdk_strlist_t locusr,
cdk_strlist_t remusr,
const char * file, const char * output,
- int sigmode, int encryptflag );
+ int sigmode, int encryptflag);
/*-- verify.c --*/
-cdk_error_t cdk_stream_verify( cdk_ctx_t hd, cdk_stream_t inp,
- cdk_stream_t out );
-cdk_error_t cdk_file_verify( cdk_ctx_t hd, const char * file,
- const char * output );
-unsigned long cdk_sig_get_ulong_attr( cdk_ctx_t hd, int idx, int what );
-const void * cdk_sig_get_data_attr( cdk_ctx_t hd, int idx, int what );
+cdk_error_t cdk_stream_verify (cdk_ctx_t hd, cdk_stream_t inp,
+ cdk_stream_t data,
+ cdk_stream_t out);
+cdk_error_t cdk_file_verify (cdk_ctx_t hd, const char *file,
+ const char *data_file, const char *output);
/*-- trustdb.c --*/
-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_pkt_pubkey_t pk,
- int * r_val, int * r_flags );
+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);
/*-- misc.c --*/
void cdk_strlist_free (cdk_strlist_t sl);
@@ -817,32 +976,33 @@ 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);
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 );
+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,
+cdk_error_t cdk_keyserver_recv_key (const char * host, int port,
const unsigned char * keyid, int kid_type,
- cdk_kbnode_t * ret_key );
+ 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_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,
enum cdk_pref_type_t type,
const unsigned char * array, size_t n );
cdk_error_t cdk_keygen_set_algo_info( cdk_keygen_ctx_t hd, int type,
- enum cdk_pk_algo_t algo, int bits );
-void cdk_keygen_set_mdc_feature( cdk_keygen_ctx_t hd, int val );
-void cdk_keygen_set_keyserver_flags( cdk_keygen_ctx_t hd, int no_modify,
- const char *pref_url );
-void cdk_keygen_set_expire_date( cdk_keygen_ctx_t hd, int type,
- long int timestamp );
+ int usage, enum cdk_pubkey_algo_t algo,
+ unsigned int bits );
+int cdk_keygen_set_keyserver_flags( cdk_keygen_ctx_t hd, int no_modify,
+ const char *pref_url );
+int cdk_keygen_set_expire_date( cdk_keygen_ctx_t hd, int type,
+ long timestamp );
void cdk_keygen_set_name( cdk_keygen_ctx_t hd, const char * name );
void cdk_keygen_set_passphrase( cdk_keygen_ctx_t hd, const char * pass );
cdk_error_t cdk_keygen_start( cdk_keygen_ctx_t hd );
cdk_error_t cdk_keygen_save( cdk_keygen_ctx_t hd,
- const char * pubf, const char * secf );
+ const char * pubf,
+ const char * secf );
#ifdef __cplusplus
}
diff --git a/libextra/opencdk/packet.h b/libextra/opencdk/packet.h
index c91e293b10..03547acea0 100644
--- a/libextra/opencdk/packet.h
+++ b/libextra/opencdk/packet.h
@@ -1,7 +1,5 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * packet.h - Internal packet routines
- * Copyright (C) 2006 Free Software Foundation
- * Copyright (C) 2002, 2003 Timo Schulz
+/* packet.h
+ * Copyright (C) 2002, 2003, 2007 Timo Schulz
*
* This file is part of OpenCDK.
*
@@ -14,34 +12,29 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
#ifndef CDK_PACKET_H
#define CDK_PACKET_H
-struct cdk_kbnode_s {
- struct cdk_kbnode_s * next;
- cdk_packet_t pkt;
- int private_flag;
+struct cdk_kbnode_s
+{
+ struct cdk_kbnode_s *next;
+ cdk_packet_t pkt;
+ unsigned int is_deleted:1;
+ unsigned int is_cloned:1;
};
/*-- new-packet.c --*/
-void _cdk_free_mpibuf( size_t n, gcry_mpi_t * array );
-void _cdk_free_userid( cdk_pkt_userid_t uid );
+void _cdk_free_mpibuf (size_t n, gcry_mpi_t *array);
+void _cdk_free_userid (cdk_pkt_userid_t uid);
void _cdk_free_signature( cdk_pkt_signature_t sig );
-void _cdk_free_pubkey( cdk_pkt_pubkey_t pk );
-void _cdk_free_seckey( cdk_pkt_seckey_t sk );
cdk_prefitem_t _cdk_copy_prefs( const cdk_prefitem_t prefs );
-cdk_error_t _cdk_copy_userid( cdk_pkt_userid_t *dst, cdk_pkt_userid_t src );
-cdk_error_t _cdk_copy_pubkey( cdk_pkt_pubkey_t* dst, cdk_pkt_pubkey_t src );
-cdk_error_t _cdk_copy_seckey( cdk_pkt_seckey_t* dst, cdk_pkt_seckey_t src );
-cdk_error_t _cdk_copy_pk_to_sk( cdk_pkt_pubkey_t pk, cdk_pkt_seckey_t sk );
-cdk_error_t _cdk_copy_signature( cdk_pkt_signature_t* dst, cdk_pkt_signature_t src );
-cdk_error_t _cdk_pubkey_compare( cdk_pkt_pubkey_t a, cdk_pkt_pubkey_t b );
+int _cdk_copy_userid( cdk_pkt_userid_t *dst, cdk_pkt_userid_t src );
+int _cdk_copy_pubkey( cdk_pkt_pubkey_t* dst, cdk_pkt_pubkey_t src );
+int _cdk_copy_seckey( cdk_pkt_seckey_t* dst, cdk_pkt_seckey_t src );
+int _cdk_copy_pk_to_sk( cdk_pkt_pubkey_t pk, cdk_pkt_seckey_t sk );
+int _cdk_copy_signature( cdk_pkt_signature_t* dst, cdk_pkt_signature_t src );
+int _cdk_pubkey_compare( cdk_pkt_pubkey_t a, cdk_pkt_pubkey_t b );
#endif /* CDK_PACKET_H */
diff --git a/libextra/opencdk/plaintext.c b/libextra/opencdk/plaintext.c
deleted file mode 100644
index 097bcc2c0d..0000000000
--- a/libextra/opencdk/plaintext.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * plaintext.c - Literal packet filters
- * Copyright (C) 2002, 2003 Timo Schulz
- *
- * This file is part of OpenCDK.
- *
- * OpenCDK is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * OpenCDK is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include <stdio.h>
-
-#include "opencdk.h"
-#include "main.h"
-#include "filters.h"
-
-
-static int
-literal_decode( void * opaque, FILE * in, FILE * out )
-{
- literal_filter_t * pfx = opaque;
- cdk_stream_t si, so;
- CDK_PACKET pkt;
- cdk_pkt_literal_t pt;
- byte buf[8192];
- size_t nread;
- int rc, bufsize;
-
- _cdk_log_debug( "literal filter: decode\n" );
-
- if (!pfx || !in || !out)
- return CDK_Inv_Value;
-
- si = _cdk_stream_fpopen( in, STREAMCTL_READ );
- if (!si)
- return CDK_Out_Of_Core;
- so = _cdk_stream_fpopen( out, STREAMCTL_WRITE );
- if( !so ) {
- cdk_stream_close( si );
- return CDK_Out_Of_Core;
- }
- cdk_pkt_init( &pkt );
- rc = cdk_pkt_read( si, &pkt );
- if( pkt.pkttype != CDK_PKT_LITERAL ) {
- if( pkt.pkttype )
- cdk_pkt_free( &pkt );
- return rc;
- }
- pt = pkt.pkt.literal;
- pfx->mode = pt->mode;
- pfx->filename = cdk_strdup( pt->name? pt->name : " " );
- if( !pfx->filename ) {
- cdk_pkt_free( &pkt );
- return CDK_Out_Of_Core;
- }
- while( !feof( in ) ) {
- _cdk_log_debug( "partial on=%d size=%lu\n",
- pfx->blkmode.on, pfx->blkmode.size );
- if( pfx->blkmode.on )
- bufsize = pfx->blkmode.size;
- else
- bufsize = pt->len < sizeof buf-1? pt->len : sizeof buf-1;
- nread = cdk_stream_read( pt->buf, buf, bufsize );
- if( nread == EOF ) {
- rc = CDK_File_Error;
- break;
- }
- if( pfx->md )
- cdk_md_write (pfx->md, buf, nread);
- cdk_stream_write( so, buf, nread );
- pt->len -= nread;
- if( pfx->blkmode.on ) {
- pfx->blkmode.size = _cdk_pkt_read_len( in, &pfx->blkmode.on );
- if( pfx->blkmode.size == (size_t)EOF )
- return CDK_Inv_Packet;
- }
- if( pt->len <= 0 && !pfx->blkmode.on )
- break;
- }
- cdk_stream_close( si );
- cdk_stream_close( so );
- cdk_pkt_free( &pkt );
- return rc;
-}
-
-
-static int
-literal_encode (void * opaque, FILE * in, FILE * out)
-{
- literal_filter_t * pfx = opaque;
- cdk_pkt_literal_t pt;
- cdk_stream_t si;
- CDK_PACKET pkt;
- size_t filelen;
- int rc;
-
- _cdk_log_debug ("literal filter: encode\n");
-
- if (!pfx || !in || !out)
- return CDK_Inv_Value;
-
- if (!pfx->filename) {
- pfx->filename = cdk_strdup ("_CONSOLE");
- if( !pfx->filename )
- return CDK_Out_Of_Core;
- }
-
- si = _cdk_stream_fpopen (in, STREAMCTL_READ);
- if (!si)
- return CDK_Out_Of_Core;
-
- filelen = strlen (pfx->filename);
- pt = cdk_calloc (1, sizeof *pt + filelen - 1);
- if (!pt)
- return CDK_Out_Of_Core;
- memcpy (pt->name, pfx->filename, filelen);
- pt->namelen = filelen;
- pt->name[pt->namelen] = '\0';
- pt->timestamp = _cdk_timestamp ();
- pt->mode = pfx->mode ? 't' : 'b';
- pt->len = cdk_stream_get_length (si);
- pt->buf = si;
- cdk_pkt_init (&pkt);
- pkt.old_ctb = pfx->rfc1991? 1 : 0;
- pkt.pkttype = CDK_PKT_LITERAL;
- pkt.pkt.literal = pt;
- rc = _cdk_pkt_write_fp (out, &pkt);
-
- cdk_free (pt);
- cdk_stream_close (si);
- return rc;
-}
-
-
-int
-_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_free( pfx->filename );
- pfx->filename = NULL;
- }
- }
- return CDK_Inv_Mode;
-}
-
-
-static int
-text_encode( void * opaque, FILE * in, FILE * out )
-{
- const char * s;
- char buf[1024];
-
- if( !in || !out )
- return CDK_Inv_Value;
-
- while( !feof( in ) ) {
- s = fgets( buf, sizeof buf-1, in );
- if( !s )
- break;
- _cdk_trim_string( buf, 1 );
- fwrite( buf, 1, strlen( buf ), out );
- }
-
- return 0;
-}
-
-
-static int
-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, sizeof 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;
-}
-
-
-int
-_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;
- }
- }
- return CDK_Inv_Mode;
-}
-
-
-
diff --git a/libextra/opencdk/pubkey.c b/libextra/opencdk/pubkey.c
index 18154229df..77eec0020e 100644
--- a/libextra/opencdk/pubkey.c
+++ b/libextra/opencdk/pubkey.c
@@ -1,7 +1,6 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * pubkey.c - Public key API
+/* pubkey.c - Public key API
* Copyright (C) 2007 Free Software Foundation, Inc.
- * Copyright (C) 2002, 2003 Timo Schulz
+ * Copyright (C) 2002, 2003, 2007 Timo Schulz
*
* This file is part of OpenCDK.
*
@@ -14,344 +13,274 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
+#include <gcrypt.h>
#include "opencdk.h"
#include "main.h"
#include "packet.h"
-#include "cipher.h"
-static gcry_mpi_t *
-convert_to_gcrympi( cdk_mpi_t m[4], int ncount )
+static int
+seckey_to_sexp (gcry_sexp_t * r_skey, cdk_seckey_t sk)
{
- gcry_mpi_t * d;
- size_t nbytes = 0;
- int i = 0, rc = 0;
-
- if( !m || ncount > 4 )
- return NULL;
- d = cdk_calloc( ncount, sizeof *d );
- if( !d )
- return NULL;
- for( i = 0; i < ncount; i++ ) {
- nbytes = m[i]->bytes + 2;
- if( gcry_mpi_scan( &d[i], GCRYMPI_FMT_PGP, m[i]->data, nbytes, &nbytes ) ) {
- rc = CDK_Gcry_Error;
- break;
- }
- }
- if( rc ) {
- _cdk_free_mpibuf( i, d );
- d = NULL;
- }
- return d;
-}
+ gcry_sexp_t sexp = NULL;
+ gcry_mpi_t *mpk = NULL, * msk = NULL;
+ cdk_pubkey_t pk;
+ const char *fmt;
+ gcry_error_t err;
+ if (!r_skey || !sk || !sk->pk)
+ return CDK_Inv_Value;
-static int
-seckey_to_sexp( gcry_sexp_t * r_skey, cdk_pkt_seckey_t sk )
-{
- gcry_sexp_t sexp = NULL;
- gcry_mpi_t * mpk = NULL, * msk = NULL;
- cdk_pkt_pubkey_t pk;
- const char * fmt = NULL;
- int ncount = 0, nscount = 0;
- int rc = 0;
-
- if( !r_skey || !sk || !sk->pk )
- return CDK_Inv_Value;
-
- pk = sk->pk;
- ncount = cdk_pk_get_npkey( pk->pubkey_algo );
- mpk = convert_to_gcrympi( pk->mpi, ncount );
- if( !mpk )
- return CDK_MPI_Error;
- nscount = cdk_pk_get_nskey( sk->pubkey_algo );
- msk = convert_to_gcrympi( sk->mpi, nscount );
- if( !msk )
- rc = CDK_MPI_Error;
- if( !rc && is_RSA( sk->pubkey_algo ) ) {
- fmt = "(private-key(openpgp-rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))";
- if( gcry_sexp_build( &sexp, NULL, fmt, mpk[0], mpk[1],
- msk[0], msk[1], msk[2], msk[3] ) )
- rc = CDK_Gcry_Error;
+ pk = sk->pk;
+ mpk = pk->mpi;
+ msk = sk->mpi;
+
+ *r_skey = NULL;
+ if (is_RSA (sk->pubkey_algo))
+ {
+ fmt = "(private-key(openpgp-rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))";
+ err = gcry_sexp_build (&sexp, NULL, fmt, mpk[0], mpk[1],
+ msk[0], msk[1], msk[2], msk[3]);
}
- else if( !rc && is_ELG( sk->pubkey_algo ) ) {
- fmt = "(private-key(openpgp-elg(p%m)(g%m)(y%m)(x%m)))";
- if( gcry_sexp_build( &sexp, NULL, fmt, mpk[0], mpk[1],
- mpk[2], msk[0] ) )
- rc = CDK_Gcry_Error;
+ else if (is_ELG (sk->pubkey_algo))
+ {
+ fmt = "(private-key(openpgp-elg(p%m)(g%m)(y%m)(x%m)))";
+ err = gcry_sexp_build (&sexp, NULL, fmt, mpk[0], mpk[1],
+ mpk[2], msk[0]);
}
- else if( !rc && is_DSA( sk->pubkey_algo ) ) {
- fmt = "(private-key(openpgp-dsa(p%m)(q%m)(g%m)(y%m)(x%m)))";
- if( gcry_sexp_build( &sexp, NULL, fmt, mpk[0], mpk[1], mpk[2],
- mpk[3], msk[0] ) )
- rc = CDK_Gcry_Error;
+ else if (is_DSA (sk->pubkey_algo))
+ {
+ fmt = "(private-key(openpgp-dsa(p%m)(q%m)(g%m)(y%m)(x%m)))";
+ err = gcry_sexp_build (&sexp, NULL, fmt, mpk[0], mpk[1], mpk[2],
+ mpk[3], msk[0]);
}
- else
- rc = CDK_Inv_Algo;
-
- _cdk_free_mpibuf( ncount, mpk );
- _cdk_free_mpibuf( nscount, msk );
- *r_skey = sexp;
- return rc;
+ else
+ return CDK_Inv_Algo;
+ if (err)
+ return map_gcry_error (err);
+ *r_skey = sexp;
+ return 0;
}
-static int
-pubkey_to_sexp( gcry_sexp_t * r_key, cdk_pkt_pubkey_t pk )
+static cdk_error_t
+pubkey_to_sexp (gcry_sexp_t *r_key_sexp, cdk_pubkey_t pk)
{
- gcry_sexp_t sexp = NULL;
- gcry_mpi_t * m;
- const char * fmt = NULL;
- int ncount = 0;
- int rc = 0;
-
- if( !r_key || !pk )
- return CDK_Inv_Value;
-
- ncount = cdk_pk_get_npkey( pk->pubkey_algo );
- m = convert_to_gcrympi( pk->mpi, ncount );
- if( !m )
- return CDK_MPI_Error;
- if( is_RSA( pk->pubkey_algo ) ) {
- fmt = "(public-key(openpgp-rsa(n%m)(e%m)))";
- if( gcry_sexp_build( &sexp, NULL, fmt, m[0], m[1] ) )
- rc = CDK_Gcry_Error;
+ gcry_mpi_t *m;
+ const char *fmt = NULL;
+ int rc = 0;
+ gcry_error_t err;
+
+ if (!r_key_sexp || !pk)
+ return CDK_Inv_Value;
+
+ m = pk->mpi;
+ if (is_RSA (pk->pubkey_algo))
+ {
+ fmt = "(public-key(openpgp-rsa(n%m)(e%m)))";
+ err = gcry_sexp_build (r_key_sexp, NULL, fmt, m[0], m[1]);
+ if (err)
+ rc = map_gcry_error (err);
}
- else if( is_ELG( pk->pubkey_algo ) ) {
- fmt = "(public-key(openpgp-elg(p%m)(g%m)(y%m)))";
- if( gcry_sexp_build( &sexp, NULL, fmt, m[0], m[1], m[2] ) )
- rc = CDK_Gcry_Error;
+ else if (is_ELG (pk->pubkey_algo))
+ {
+ fmt = "(public-key(openpgp-elg(p%m)(g%m)(y%m)))";
+ err = gcry_sexp_build (r_key_sexp, NULL, fmt, m[0], m[1], m[2]);
+ if (err)
+ rc = map_gcry_error (err);
}
- else if( is_DSA( pk->pubkey_algo ) ) {
- fmt = "(public-key(openpgp-dsa(p%m)(q%m)(g%m)(y%m)))";
- if( gcry_sexp_build( &sexp, NULL, fmt, m[0], m[1], m[2], m[3] ) )
- rc = CDK_Gcry_Error;
+ else if (is_DSA (pk->pubkey_algo))
+ {
+ fmt = "(public-key(openpgp-dsa(p%m)(q%m)(g%m)(y%m)))";
+ err = gcry_sexp_build (r_key_sexp, NULL, fmt, m[0], m[1], m[2], m[3]);
+ if (err)
+ rc = map_gcry_error (err);
}
- else
- rc = CDK_Inv_Algo;
- _cdk_free_mpibuf( ncount, m );
- *r_key = sexp;
- return rc;
+ else
+ rc = CDK_Inv_Algo;
+ return rc;
}
-static int
-enckey_to_sexp( gcry_sexp_t * r_sexp, gcry_mpi_t esk )
+static cdk_error_t
+enckey_to_sexp (gcry_sexp_t *r_sexp, gcry_mpi_t esk)
{
- gcry_sexp_t sexp = NULL;
- int rc = 0;
-
- if( !r_sexp || !esk )
- return CDK_Inv_Value;
- if( gcry_sexp_build( &sexp, NULL, "%m", esk ) )
- rc = CDK_Gcry_Error;
- *r_sexp = sexp;
- return rc;
+ gcry_error_t err;
+
+ if (!r_sexp || !esk)
+ return CDK_Inv_Value;
+ err = gcry_sexp_build (r_sexp, NULL, "%m", esk);
+ if (err)
+ return map_gcry_error (err);
+ return 0;
}
-static int
-digest_to_sexp( gcry_sexp_t * r_md, int algo, const byte * md, size_t mdlen )
+static cdk_error_t
+digest_to_sexp (gcry_sexp_t *r_md_sexp, int algo, const byte *md, size_t mdlen)
{
- gcry_sexp_t sexp = NULL;
- gcry_mpi_t m = NULL;
- size_t nbytes = 0;
- int rc = 0;
-
- if( !r_md || !md )
- return CDK_Inv_Value;
- nbytes = mdlen ? mdlen : cdk_md_get_algo_dlen( algo );
- if( !nbytes )
- return CDK_Inv_Algo;
- if( gcry_mpi_scan( &m, GCRYMPI_FMT_USG, md, nbytes, &nbytes ) )
- return CDK_Gcry_Error;
- if( gcry_sexp_build( &sexp, NULL, "%m", m ) )
- rc = CDK_Gcry_Error;
- if( !rc )
- *r_md = sexp;
- gcry_mpi_release( m );
- return rc;
+ gcry_mpi_t m;
+ gcry_error_t err;
+
+ if (!r_md_sexp || !md)
+ return CDK_Inv_Value;
+
+ if (!mdlen)
+ mdlen = gcry_md_get_algo_dlen (algo);
+ if (!mdlen)
+ return CDK_Inv_Algo;
+
+ err = gcry_mpi_scan (&m, GCRYMPI_FMT_USG, md, mdlen, &mdlen);
+ if (err)
+ return map_gcry_error (err);
+
+ err = gcry_sexp_build (r_md_sexp, NULL, "%m", m);
+ gcry_mpi_release (m);
+ if (err)
+ return map_gcry_error (err);
+ return 0;
}
-static int
-sexp_to_bitmpi( gcry_sexp_t sexp, const char * val, cdk_mpi_t * ret_buf )
+static cdk_error_t
+sexp_to_mpi (gcry_sexp_t sexp, const char *val, gcry_mpi_t *ret_buf)
{
- gcry_sexp_t list = NULL;
- gcry_mpi_t m = NULL;
- cdk_mpi_t buf = NULL;
- size_t nbits = 0, nbytes = 0;
- int rc = 0;
-
- if( !sexp || !val || !ret_buf )
- return CDK_Inv_Value;
-
- list = gcry_sexp_find_token( sexp, val, 0 );
- if( !list )
- return CDK_Gcry_Error;
- m = gcry_sexp_nth_mpi( list, 1, 0 );
- if( !m ) {
- gcry_sexp_release( list );
- return CDK_Gcry_Error;
- }
- nbits = gcry_mpi_get_nbits( m );
- nbytes = (nbits + 7) / 8;
- buf = cdk_calloc( 1, sizeof *buf + nbytes );
- if( !buf ) {
- rc = CDK_Out_Of_Core;
- goto leave;
- }
- buf->data[0] = nbits >> 8;
- buf->data[1] = nbits;
- if( gcry_mpi_print( GCRYMPI_FMT_USG, NULL, nbytes, &nbytes, m ) )
- rc = CDK_Gcry_Error;
- else
- if( gcry_mpi_print( GCRYMPI_FMT_USG, buf->data + 2, nbytes, &nbytes, m ) )
- rc = CDK_Gcry_Error;
- if( !rc ) {
- buf->bytes = nbytes;
- buf->bits = nbits;
- *ret_buf = buf;
- }
-
- leave:
- gcry_mpi_release( m );
- gcry_sexp_release( list );
- return rc;
+ gcry_sexp_t list;
+
+ if (!sexp || !val || !ret_buf)
+ return CDK_Inv_Value;
+
+ list = gcry_sexp_find_token (sexp, val, 0);
+ if (!list)
+ return CDK_Inv_Value;
+
+ *ret_buf = gcry_sexp_nth_mpi (list, 1, 0);
+ gcry_sexp_release (list);
+ if (! *ret_buf)
+ return CDK_Inv_Value;
+ return 0;
}
-static int
-sexp_to_sig( cdk_pkt_signature_t sig, gcry_sexp_t sexp)
+static cdk_error_t
+sexp_to_sig (cdk_pkt_signature_t sig, gcry_sexp_t sexp)
{
- int rc = 0;
-
- if( !sig || !sexp )
- return CDK_Inv_Value;
-
- if( is_RSA( sig->pubkey_algo ) )
- return sexp_to_bitmpi( sexp, "s", &sig->mpi[0] );
- else if( is_DSA( sig->pubkey_algo) || is_ELG( sig->pubkey_algo ) ) {
- rc = sexp_to_bitmpi( sexp, "r", &sig->mpi[0] );
- if( !rc )
- rc = sexp_to_bitmpi( sexp, "s", &sig->mpi[1] );
- return rc;
+ if (!sig || !sexp)
+ return CDK_Inv_Value;
+
+ /* ElGamal signatures are not supported any longer. */
+ if (is_ELG (sig->pubkey_algo))
+ return CDK_Not_Implemented;
+
+ if (is_RSA (sig->pubkey_algo))
+ return sexp_to_mpi (sexp, "s", &sig->mpi[0]);
+ else if (is_DSA (sig->pubkey_algo))
+ {
+ cdk_error_t rc;
+
+ rc = sexp_to_mpi (sexp, "r", &sig->mpi[0]);
+ if (!rc)
+ rc = sexp_to_mpi (sexp, "s", &sig->mpi[1]);
+ return rc;
}
- return CDK_Inv_Algo;
+ return CDK_Inv_Algo;
}
-static int
-sig_to_sexp( gcry_sexp_t * r_sig, cdk_pkt_signature_t sig )
+static cdk_error_t
+sig_to_sexp (gcry_sexp_t *r_sig_sexp, cdk_pkt_signature_t sig)
{
- gcry_sexp_t sexp = NULL;
- gcry_mpi_t * m;
- const char * fmt;
- int ncount = 0;
- int rc = 0;
-
- if( !r_sig || !sig )
- return CDK_Inv_Value;
-
- ncount = cdk_pk_get_nsig( sig->pubkey_algo );
- m = convert_to_gcrympi( sig->mpi, ncount );
- if( !m )
- return CDK_MPI_Error;
- if( is_RSA( sig->pubkey_algo ) ) {
- fmt = "(sig-val(openpgp-rsa(s%m)))";
- if( gcry_sexp_build( &sexp, NULL, fmt, m[0] ) )
- rc = CDK_Gcry_Error;
- }
- else if( is_ELG( sig->pubkey_algo ) ) {
- fmt = "(sig-val(openpgp-elg(r%m)(s%m)))";
- if( gcry_sexp_build( &sexp, NULL, fmt, m[0], m[1] ) )
- rc = CDK_Gcry_Error;
+ const char *fmt;
+ gcry_error_t err;
+ cdk_error_t rc;
+
+ if (!r_sig_sexp || !sig)
+ return CDK_Inv_Value;
+ if (is_ELG (sig->pubkey_algo))
+ return CDK_Not_Implemented;
+
+ rc = 0;
+ if (is_RSA (sig->pubkey_algo))
+ {
+ fmt = "(sig-val(openpgp-rsa(s%m)))";
+ err = gcry_sexp_build (r_sig_sexp, NULL, fmt, sig->mpi[0]);
+ if (err)
+ rc = map_gcry_error (err);
}
- else if( is_DSA( sig->pubkey_algo ) ) {
- fmt = "(sig-val(openpgp-dsa(r%m)(s%m)))";
- if( gcry_sexp_build( &sexp, NULL, fmt, m[0], m[1] ) )
- rc = CDK_Gcry_Error;
+ else if (is_DSA (sig->pubkey_algo))
+ {
+ fmt = "(sig-val(openpgp-dsa(r%m)(s%m)))";
+ err = gcry_sexp_build (r_sig_sexp, NULL, fmt, sig->mpi[0], sig->mpi[1]);
+ if (err)
+ rc = map_gcry_error (err);
}
- else
- rc = CDK_Inv_Algo;
- _cdk_free_mpibuf( ncount, m );
- *r_sig = sexp;
- return rc;
+ else
+ rc = CDK_Inv_Algo;
+ return rc;
}
-static int
-sexp_to_pubenc( cdk_pkt_pubkey_enc_t enc, gcry_sexp_t sexp)
+static cdk_error_t
+sexp_to_pubenc (cdk_pkt_pubkey_enc_t enc, gcry_sexp_t sexp)
{
- int rc;
-
- if( !sexp || !enc )
- return CDK_Inv_Value;
-
- if( is_RSA( enc->pubkey_algo) )
- return sexp_to_bitmpi( sexp, "a", &enc->mpi[0] );
- else if( is_ELG( enc->pubkey_algo) ) {
- rc = sexp_to_bitmpi( sexp, "a", &enc->mpi[0] );
- if( !rc )
- rc = sexp_to_bitmpi( sexp, "b", &enc->mpi[1] );
- return rc;
+ if (!sexp || !enc)
+ return CDK_Inv_Value;
+
+ if (is_RSA (enc->pubkey_algo))
+ return sexp_to_mpi (sexp, "a", &enc->mpi[0]);
+ else if (is_ELG (enc->pubkey_algo))
+ {
+ cdk_error_t rc = sexp_to_mpi (sexp, "a", &enc->mpi[0]);
+ if (!rc)
+ rc = sexp_to_mpi (sexp, "b", &enc->mpi[1]);
+ return rc;
}
- return CDK_Inv_Algo;
+ return CDK_Inv_Algo;
}
-static int
+static cdk_error_t
pubenc_to_sexp( gcry_sexp_t * r_sexp, cdk_pkt_pubkey_enc_t enc)
{
- gcry_sexp_t sexp = NULL;
- gcry_mpi_t * m;
- const char * fmt;
- int ncount;
- int rc = 0;
-
- if( !r_sexp || !enc )
- return CDK_Inv_Value;
-
- ncount = cdk_pk_get_nenc( enc->pubkey_algo );
- m = convert_to_gcrympi( enc->mpi, ncount );
- if( !m )
- return CDK_MPI_Error;
- if( is_RSA( enc->pubkey_algo ) ) {
- fmt = "(enc-val(openpgp-rsa((a%m))))";
- if( gcry_sexp_build( &sexp, NULL, fmt, m[0] ) )
- rc = CDK_Gcry_Error;
+ gcry_sexp_t sexp = NULL;
+ const char *fmt;
+ gcry_error_t err;
+
+ if (!r_sexp || !enc)
+ return CDK_Inv_Value;
+
+ *r_sexp = NULL;
+ if (is_RSA (enc->pubkey_algo))
+ {
+ fmt = "(enc-val(openpgp-rsa((a%m))))";
+ err = gcry_sexp_build (&sexp, NULL, fmt, enc->mpi[0]);
}
- else if( is_ELG( enc->pubkey_algo ) ) {
- fmt = "(enc-val(openpgp-elg((a%m)(b%m))))";
- if( gcry_sexp_build( &sexp, NULL, fmt, m[0], m[1] ) )
- rc = CDK_Gcry_Error;
+ else if (is_ELG (enc->pubkey_algo))
+ {
+ fmt = "(enc-val(openpgp-elg((a%m)(b%m))))";
+ err = gcry_sexp_build (&sexp, NULL, fmt, enc->mpi[0], enc->mpi[1]);
}
- else
- rc = CDK_Inv_Algo;
- _cdk_free_mpibuf( ncount, m );
- *r_sexp = sexp;
- return rc;
+ else
+ return CDK_Inv_Algo;
+ if (err)
+ return map_gcry_error (err);
+ *r_sexp = sexp;
+ return 0;
}
static int
-is_unprotected( cdk_pkt_seckey_t sk )
+is_unprotected (cdk_seckey_t sk)
{
- if( sk->is_protected && !sk->mpi[0] )
- return 0;
- return 1;
+ if (sk->is_protected && !sk->mpi[0])
+ return 0;
+ return 1;
}
@@ -365,30 +294,30 @@ is_unprotected( cdk_pkt_seckey_t sk )
* into the @pke struct.
**/
cdk_error_t
-cdk_pk_encrypt( cdk_pkt_pubkey_t pk, cdk_pkt_pubkey_enc_t pke,
- cdk_sesskey_t esk )
+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;
-
- if( !pk || !esk || !pke )
- return CDK_Inv_Value;
-
- if( !KEY_CAN_ENCRYPT( pk->pubkey_algo ) )
- return CDK_Inv_Algo;
-
- rc = enckey_to_sexp( &s_data, esk->a );
- if( !rc )
- rc = pubkey_to_sexp( &s_pkey, pk );
- if( !rc )
- rc = gcry_pk_encrypt( &s_ciph, s_data, s_pkey );
- if( !rc )
- rc = sexp_to_pubenc( pke, s_ciph );
-
- gcry_sexp_release( s_data );
- gcry_sexp_release( s_pkey );
- gcry_sexp_release( s_ciph );
- return rc;
+ gcry_sexp_t s_data = NULL, s_pkey = NULL, s_ciph = NULL;
+ int rc;
+
+ if (!pk || !esk || !pke)
+ return CDK_Inv_Value;
+
+ if (!KEY_CAN_ENCRYPT (pk->pubkey_algo))
+ return CDK_Inv_Algo;
+
+ rc = enckey_to_sexp (&s_data, esk);
+ if (!rc)
+ rc = pubkey_to_sexp (&s_pkey, pk);
+ if (!rc)
+ rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
+ if (!rc)
+ rc = sexp_to_pubenc (pke, s_ciph);
+
+ gcry_sexp_release (s_data);
+ gcry_sexp_release (s_pkey);
+ gcry_sexp_release (s_ciph);
+ return rc;
}
@@ -401,33 +330,41 @@ cdk_pk_encrypt( cdk_pkt_pubkey_t pk, cdk_pkt_pubkey_enc_t pke,
* Decrypt the encrypted session key from @pke into @r_sk.
**/
cdk_error_t
-cdk_pk_decrypt( cdk_pkt_seckey_t sk, cdk_pkt_pubkey_enc_t pke,
- cdk_sesskey_t * r_sk )
+cdk_pk_decrypt (cdk_seckey_t sk, cdk_pkt_pubkey_enc_t pke,
+ gcry_mpi_t *r_sk)
{
- gcry_sexp_t s_data = NULL, s_skey = NULL, s_plain = NULL;
- int rc;
-
- if( !sk || !r_sk || !pke )
- return CDK_Inv_Value;
-
- if( !is_unprotected( sk ) )
- return CDK_Inv_Mode;
-
- rc = seckey_to_sexp( &s_skey, sk );
- if( !rc )
- rc = pubenc_to_sexp( &s_data, pke );
- if( !rc && gcry_pk_decrypt( &s_plain, s_data, s_skey ) )
- rc = CDK_Gcry_Error;
- if( !rc ) {
- rc = cdk_sesskey_new( r_sk );
- if( !rc )
- (*r_sk)->a = gcry_sexp_nth_mpi( s_plain, 0, 0 );
- }
-
- gcry_sexp_release( s_data );
- gcry_sexp_release( s_skey );
- gcry_sexp_release( s_plain );
+ gcry_sexp_t s_data = NULL, s_skey = NULL, s_plain = NULL;
+ cdk_error_t rc;
+ gcry_error_t err;
+
+ if (!sk || !r_sk || !pke)
+ return CDK_Inv_Value;
+
+ if (!is_unprotected (sk))
+ return CDK_Inv_Mode;
+
+ *r_sk = NULL;
+ rc = seckey_to_sexp (&s_skey, sk);
+ if (rc)
return rc;
+
+ rc = pubenc_to_sexp (&s_data, pke);
+ if (rc)
+ {
+ gcry_sexp_release (s_skey);
+ return rc;
+ }
+
+ err = gcry_pk_decrypt (&s_plain, s_data, s_skey);
+ if (err)
+ rc = map_gcry_error (err);
+ else
+ *r_sk = gcry_sexp_nth_mpi (s_plain, 0, 0);
+
+ gcry_sexp_release (s_data);
+ gcry_sexp_release (s_skey);
+ gcry_sexp_release (s_plain);
+ return rc;
}
@@ -440,41 +377,58 @@ cdk_pk_decrypt( cdk_pkt_seckey_t sk, cdk_pkt_pubkey_enc_t pke,
* Sign the message digest from @md and write the result into @sig.
**/
cdk_error_t
-cdk_pk_sign( cdk_pkt_seckey_t sk, cdk_pkt_signature_t sig, const byte * md )
+cdk_pk_sign (cdk_seckey_t sk, cdk_pkt_signature_t sig, const byte *md)
{
- gcry_sexp_t s_skey = NULL, s_sig = NULL, s_hash = NULL;
- byte * encmd = NULL;
- size_t enclen = 0;
- int nbits, rc;
-
- if( !sk || !sk->pk || !sig || !md )
- return CDK_Inv_Value;
-
- if( !is_unprotected( sk ) )
- return CDK_Inv_Mode;
-
- if( !KEY_CAN_SIGN( sig->pubkey_algo ) )
- return CDK_Inv_Algo;
-
- nbits = cdk_pk_get_nbits( sk->pk );
- rc = _cdk_digest_encode_pkcs1( &encmd, &enclen, sk->pk->pubkey_algo, md,
- sig->digest_algo, nbits );
- if( !rc )
- rc = seckey_to_sexp( &s_skey, sk );
- if( !rc )
- rc = digest_to_sexp( &s_hash, sig->digest_algo, encmd, enclen );
- if( !rc && gcry_pk_sign( &s_sig, s_hash, s_skey ) )
- rc = CDK_Gcry_Error;
- if( !rc )
- rc = sexp_to_sig( sig, s_sig );
- sig->digest_start[0] = md[0];
- sig->digest_start[1] = md[1];
-
- gcry_sexp_release( s_skey );
- gcry_sexp_release( s_hash );
- gcry_sexp_release( s_sig );
- cdk_free( encmd );
+ gcry_sexp_t s_skey = NULL, s_sig = NULL, s_hash = NULL;
+ byte *encmd = NULL;
+ size_t enclen = 0;
+ int nbits;
+ cdk_error_t rc;
+ gcry_error_t err;
+
+ if (!sk || !sk->pk || !sig || !md)
+ return CDK_Inv_Value;
+
+ if (!is_unprotected (sk))
+ return CDK_Inv_Mode;
+
+ if (!KEY_CAN_SIGN (sig->pubkey_algo))
+ return CDK_Inv_Algo;
+
+ nbits = cdk_pk_get_nbits (sk->pk);
+ rc = _cdk_digest_encode_pkcs1 (&encmd, &enclen, sk->pk->pubkey_algo, md,
+ sig->digest_algo, nbits);
+ if (rc)
return rc;
+
+ rc = seckey_to_sexp (&s_skey, sk);
+ if (!rc)
+ rc = digest_to_sexp (&s_hash, sig->digest_algo, encmd, enclen);
+ if (rc)
+ {
+ cdk_free (encmd);
+ gcry_sexp_release (s_skey);
+ return rc;
+ }
+
+ err = gcry_pk_sign (&s_sig, s_hash, s_skey);
+ if (err)
+ rc = map_gcry_error (err);
+ else
+ {
+ rc = sexp_to_sig (sig, s_sig);
+ if (!rc)
+ {
+ sig->digest_start[0] = md[0];
+ sig->digest_start[1] = md[1];
+ }
+ }
+
+ gcry_sexp_release (s_skey);
+ gcry_sexp_release (s_hash);
+ gcry_sexp_release (s_sig);
+ cdk_free (encmd);
+ return rc;
}
@@ -487,347 +441,413 @@ cdk_pk_sign( cdk_pkt_seckey_t sk, cdk_pkt_signature_t sig, const byte * md )
* Verify the signature in @sig and compare it with the message digest in @md.
**/
cdk_error_t
-cdk_pk_verify( cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig, const byte * md)
+cdk_pk_verify (cdk_pubkey_t pk, cdk_pkt_signature_t sig, const byte *md)
{
- gcry_sexp_t s_pkey = NULL, s_sig = NULL, s_hash = NULL;
- byte * encmd = NULL;
- size_t enclen = 0;
- int nbits, rc;
-
- if( !pk || !sig || !md )
- return CDK_Inv_Value;
-
- nbits = cdk_pk_get_nbits( pk );
- rc = pubkey_to_sexp( &s_pkey, pk );
- if( !rc )
- rc = sig_to_sexp( &s_sig, sig );
- if( !rc )
- rc = _cdk_digest_encode_pkcs1( &encmd, &enclen, pk->pubkey_algo, md,
- sig->digest_algo, nbits );
- if( !rc )
- rc = digest_to_sexp( &s_hash, sig->digest_algo, encmd, enclen );
- if( !rc && gcry_pk_verify( s_sig, s_hash, s_pkey ) )
- rc = CDK_Bad_Sig;
-
- gcry_sexp_release( s_sig );
- gcry_sexp_release( s_hash );
- gcry_sexp_release( s_pkey );
- cdk_free( encmd );
+ gcry_sexp_t s_pkey = NULL, s_sig = NULL, s_hash = NULL;
+ byte *encmd = NULL;
+ size_t enclen;
+ cdk_error_t rc;
+
+ if (!pk || !sig || !md)
+ return CDK_Inv_Value;
+
+ rc = pubkey_to_sexp (&s_pkey, pk);
+ if (rc)
return rc;
+
+ rc = sig_to_sexp (&s_sig, sig);
+ if (rc)
+ goto leave;
+
+ rc = _cdk_digest_encode_pkcs1 (&encmd, &enclen, pk->pubkey_algo, md,
+ sig->digest_algo, cdk_pk_get_nbits (pk));
+ if (rc)
+ goto leave;
+
+ rc = digest_to_sexp (&s_hash, sig->digest_algo, encmd, enclen);
+ if (rc)
+ goto leave;
+
+ if (gcry_pk_verify (s_sig, s_hash, s_pkey))
+ rc = CDK_Bad_Sig;
+
+ leave:
+ gcry_sexp_release (s_sig);
+ gcry_sexp_release (s_hash);
+ gcry_sexp_release (s_pkey);
+ cdk_free (encmd);
+ return rc;
}
int
-cdk_pk_get_nbits( cdk_pkt_pubkey_t pk )
+cdk_pk_get_nbits (cdk_pubkey_t pk)
{
- if( !pk || !pk->mpi[0] )
- return 0;
- return pk->mpi[0]->bits;
+ if (!pk || !pk->mpi[0])
+ return 0;
+ return gcry_mpi_get_nbits (pk->mpi[0]);
}
+/**
+ * cdk_pk_get_npkey:
+ * @algo: The public key algorithm.
+ *
+ * Return the number of multiprecison integer forming an public
+ * key with the given algorithm.
+ */
int
-cdk_pk_get_npkey( int algo )
+cdk_pk_get_npkey (int algo)
{
- size_t bytes;
-
- if (algo == 16)
- algo = 20; /* XXX: libgcrypt returns 0 for 16 */
- if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &bytes))
- return 0;
-
- return bytes;
+ size_t bytes;
+
+ if (algo == 16)
+ algo = 20; /* FIXME: libgcrypt returns 0 for 16 */
+ if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &bytes))
+ return 0;
+ return bytes;
}
int
-cdk_pk_get_nskey( int algo )
+cdk_pk_get_nskey (int algo)
{
-size_t bytes;
-
- if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &bytes))
- return 0;
-
- bytes -= cdk_pk_get_npkey( algo );
- return bytes;
+ size_t bytes;
+
+ if (gcry_pk_algo_info (algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &bytes))
+ return 0;
+ bytes -= cdk_pk_get_npkey (algo);
+ return bytes;
}
int
-cdk_pk_get_nsig( int algo )
+cdk_pk_get_nsig (int algo)
{
-size_t bytes;
-
- if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSIGN, NULL, &bytes))
- return 0;
- return bytes;
+ size_t bytes;
+
+ if (gcry_pk_algo_info (algo, GCRYCTL_GET_ALGO_NSIGN, NULL, &bytes))
+ return 0;
+ return bytes;
}
int
-cdk_pk_get_nenc( int algo )
+cdk_pk_get_nenc (int algo)
{
-size_t bytes;
-
- if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NENCR, NULL, &bytes))
- return 0;
- return bytes;
+ size_t bytes;
+
+ if (gcry_pk_algo_info (algo, GCRYCTL_GET_ALGO_NENCR, NULL, &bytes))
+ return 0;
+ return bytes;
}
int
-_cdk_pk_algo_usage( int algo )
+_cdk_pk_algo_usage (int algo)
{
- int usage = 0;
-
- switch( algo ) {
- case CDK_PK_RSA : usage = PK_USAGE_SIGN | PK_USAGE_ENCR; break;
- case CDK_PK_RSA_E: usage = PK_USAGE_ENCR; break;
- case CDK_PK_RSA_S: usage = PK_USAGE_SIGN; break;
- case CDK_PK_ELG : usage = PK_USAGE_SIGN | PK_USAGE_ENCR; break;
- case CDK_PK_ELG_E: usage = PK_USAGE_ENCR; break;
- case CDK_PK_DSA : usage = PK_USAGE_SIGN; break;
+ int usage;
+
+ /* The ElGamal sign+encrypt algorithm is not supported any longer. */
+ switch (algo)
+ {
+ case CDK_PK_RSA : usage = CDK_KEY_USG_SIGN | CDK_KEY_USG_ENCR; break;
+ case CDK_PK_RSA_E: usage = CDK_KEY_USG_ENCR; break;
+ case CDK_PK_RSA_S: usage = CDK_KEY_USG_SIGN; break;
+ case CDK_PK_ELG_E: usage = CDK_KEY_USG_ENCR; break;
+ case CDK_PK_DSA : usage = CDK_KEY_USG_SIGN; break;
+ default: usage = 0;
}
- return usage;
+ return usage;
}
int
-_cdk_pk_test_algo( int algo, unsigned int usage_flags )
+_cdk_pk_test_algo (int algo, unsigned int usage_flags)
{
- size_t n = usage_flags;
+ size_t n = usage_flags;
- if( algo < 0 || algo > 110 )
- return GPG_ERR_INV_PARAMETER;
- return gcry_pk_algo_info( algo, GCRYCTL_TEST_ALGO, NULL, &n );
+ if (algo < 0 || algo > 110)
+ return -1;
+ return gcry_pk_algo_info (algo, GCRYCTL_TEST_ALGO, NULL, &n);
}
-static int
-read_mpi( cdk_mpi_t a, byte * buf, size_t * r_count, size_t * r_nbits )
+static cdk_error_t
+mpi_to_buffer (gcry_mpi_t a, byte *buf, size_t buflen,
+ size_t *r_nwritten, size_t *r_nbits)
{
- if( !a || !buf || !r_count )
- return CDK_Inv_Value;
-
- if( a->bytes + 2 > *r_count )
- return CDK_General_Error;
- *r_count = a->bytes + 2;
- memcpy( buf, a->data, *r_count );
- if( r_nbits )
- *r_nbits = a->bits;
- return 0;
+ size_t nbits;
+
+ if (!a || !buf || !r_nwritten)
+ return CDK_Inv_Value;
+
+ nbits = gcry_mpi_get_nbits (a);
+ if (r_nbits)
+ *r_nbits = nbits;
+ if ((nbits+7)/8+2 > buflen)
+ return CDK_Too_Short;
+ *r_nwritten = (nbits+7)/8+2;
+ if (gcry_mpi_print (GCRYMPI_FMT_PGP, buf, buflen, r_nwritten, a))
+ return CDK_Wrong_Format;
+ return 0;
}
cdk_error_t
-cdk_pk_get_mpi( cdk_pkt_pubkey_t pk, int idx,
- byte * buf, size_t * r_count, size_t * r_nbits )
+cdk_pk_get_mpi (cdk_pkt_pubkey_t pk, size_t idx,
+ byte *buf, size_t buflen, size_t *r_nwritten, size_t *r_nbits)
{
- if( !pk || idx < 0 || !r_count )
- return CDK_Inv_Value;
- if( idx > cdk_pk_get_npkey( pk->pubkey_algo ) )
- return CDK_Inv_Value;
- return read_mpi( pk->mpi[idx], buf, r_count, r_nbits );
+ if (!pk || !r_nwritten)
+ return CDK_Inv_Value;
+ if (idx > cdk_pk_get_npkey (pk->pubkey_algo))
+ return CDK_Inv_Value;
+ return mpi_to_buffer (pk->mpi[idx], buf, buflen, r_nwritten, r_nbits);
}
cdk_error_t
-cdk_sk_get_mpi( cdk_pkt_seckey_t sk, int idx,
- byte * buf, size_t * r_count, size_t * r_nbits)
+cdk_sk_get_mpi (cdk_pkt_seckey_t sk, size_t idx,
+ byte *buf, size_t buflen, size_t *r_nwritten, size_t * r_nbits)
{
- if( !sk || idx < 0 || !r_count)
- return CDK_Inv_Value;
- if( idx > cdk_pk_get_nskey( sk->pubkey_algo ) )
- return CDK_Inv_Value;
- return read_mpi( sk->mpi[idx], buf, r_count, r_nbits );
+ if (!sk || !r_nwritten)
+ return CDK_Inv_Value;
+ if (idx > cdk_pk_get_nskey (sk->pubkey_algo))
+ return CDK_Inv_Value;
+ return mpi_to_buffer (sk->mpi[idx], buf, buflen, r_nwritten, r_nbits);
}
static u16
-checksum_mpi( cdk_mpi_t m )
+checksum_mpi (gcry_mpi_t m)
{
- int i;
- u16 chksum = 0;
-
- if( !m )
- return 0;
- for( i = 0; i < m->bytes + 2; i++)
- chksum += m->data[i];
- return chksum;
+ byte buf[MAX_MPI_BYTES+2];
+ size_t nread;
+ int i;
+ u16 chksum = 0;
+
+ if (!m)
+ return 0;
+ if (gcry_mpi_print (GCRYMPI_FMT_PGP, buf, 2048, &nread, m))
+ return 0;
+ for (i=0; i < nread; i++)
+ chksum += buf[i];
+ return chksum;
}
cdk_error_t
-cdk_sk_unprotect( cdk_pkt_seckey_t sk, const char * pw )
+cdk_sk_unprotect (cdk_pkt_seckey_t sk, const char *pw)
{
- cdk_cipher_hd_t hd;
- cdk_dek_t dek = NULL;
- cdk_mpi_t a;
- u16 chksum = 0;
- size_t ndata, nbits;
- int j, i, dlen, pos = 0, nskey;
- int rc;
- byte * data = NULL;
-
- if( !sk )
- return CDK_Inv_Value;
-
- nskey = cdk_pk_get_nskey( sk->pubkey_algo );
- if( sk->is_protected ) {
- rc = cdk_dek_from_passphrase( &dek, sk->protect.algo,
- sk->protect.s2k, 0, pw );
- if( rc )
- return rc;
- hd = cdk_cipher_open( sk->protect.algo, 1,
- dek->key, dek->keylen,
- sk->protect.iv, sk->protect.ivlen );
- if( !hd ) {
- cdk_free( dek );
- return CDK_Inv_Algo;
- }
- wipemem( dek, sizeof dek );
- cdk_dek_free( dek );
- chksum = 0;
- if( sk->version == 4 ) {
- ndata = sk->enclen;
- data = cdk_salloc( ndata, 1 );
- if( !data )
- return CDK_Out_Of_Core;
- cdk_cipher_decrypt( hd, data, sk->encdata, ndata );
- if( sk->protect.sha1chk ) {
- /* This is the new SHA1 checksum method to detect tampering
- with the key as used by the Klima/Rosa attack */
- sk->csum = 0;
- chksum = 1;
- dlen = cdk_md_get_algo_dlen( CDK_MD_SHA1 );
- if( ndata < dlen ) {
- cdk_free( data );
- return CDK_Inv_Packet;
- }
- else {
- cdk_md_hd_t md = cdk_md_open( CDK_MD_SHA1, 1 );
- if( !md )
- return CDK_Gcry_Error;
- cdk_md_write( md, data, ndata - dlen );
- cdk_md_final( md );
- if( !memcmp( cdk_md_read( md, CDK_MD_SHA1 ),
- data + ndata - dlen, dlen ) )
- chksum = 0; /* digest does match */
- cdk_md_close( md );
- }
- }
- else {
- for( i = 0; i < ndata - 2; i++)
- chksum += data[i];
- sk->csum = data[ndata - 2] << 8 | data[ndata - 1];
+ gcry_cipher_hd_t hd;
+ cdk_dek_t dek = NULL;
+ byte *data = NULL;
+ u16 chksum = 0;
+ size_t ndata, nbits, nbytes;
+ int i, dlen, pos = 0, nskey;
+ cdk_error_t rc;
+ gcry_error_t err;
+
+ if (!sk)
+ return CDK_Inv_Value;
+
+ nskey = cdk_pk_get_nskey (sk->pubkey_algo);
+ if (!sk->is_protected)
+ {
+ chksum = 0;
+ for (i = 0; i < nskey; i++)
+ chksum += checksum_mpi (sk->mpi[i]);
+ if (chksum != sk->csum)
+ return CDK_Chksum_Error;
+ }
+
+ rc = cdk_dek_from_passphrase (&dek, sk->protect.algo,
+ sk->protect.s2k, 0, pw);
+ if (rc)
+ return rc;
+ err = gcry_cipher_open (&hd, sk->protect.algo, GCRY_CIPHER_MODE_CFB,
+ GCRY_CIPHER_ENABLE_SYNC);
+ if (!err)
+ err = gcry_cipher_setiv (hd, sk->protect.iv, sk->protect.ivlen);
+ if (!err)
+ err = gcry_cipher_setkey (hd, dek->key, dek->keylen);
+ if (err)
+ {
+ cdk_free (dek);
+ return map_gcry_error (err);
+ }
+ cdk_dek_free (dek);
+ chksum = 0;
+ if (sk->version == 4)
+ {
+ ndata = sk->enclen;
+ data = cdk_salloc (ndata, 1);
+ if (!data)
+ return CDK_Out_Of_Core;
+ gcry_cipher_decrypt (hd, data, ndata, sk->encdata, ndata);
+ if (sk->protect.sha1chk)
+ {
+ /* This is the new SHA1 checksum method to detect tampering
+ with the key as used by the Klima/Rosa attack */
+ sk->csum = 0;
+ chksum = 1;
+ dlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
+ if (ndata < dlen)
+ {
+ cdk_free (data);
+ return CDK_Inv_Packet;
}
- if( sk->csum == chksum ) {
- for( i = 0; i < nskey; i++ ) {
- nbits = data[pos] << 8 | data[pos + 1];
- ndata = (nbits + 7) / 8;
- a = sk->mpi[i] = cdk_salloc( sizeof *a + ndata + 2, 1 );
- if( !a ) {
- cdk_free( data );
- return CDK_Out_Of_Core;
- }
- a->bits = nbits;
- a->bytes = ndata;
- for( j = 0; j < ndata + 2; j++ )
- a->data[j] = data[pos++];
- }
+ else
+ {
+ byte mdcheck[20];
+
+ gcry_md_hash_buffer (GCRY_MD_SHA1,
+ mdcheck, data, ndata-dlen);
+ if (!memcmp (mdcheck, data + ndata - dlen, dlen))
+ chksum = 0; /* Digest does match */
}
- wipemem( data, sk->enclen );
- cdk_free( data );
}
- else {
- chksum = 0;
- for( i = 0; i < nskey; i++ ) {
- a = sk->mpi[i];
- cdk_cipher_sync( hd );
- cdk_cipher_decrypt( hd, a->data+2, a->data+2, a->bytes );
- chksum += checksum_mpi( a );
+ else
+ {
+ for (i = 0; i < ndata - 2; i++)
+ chksum += data[i];
+ sk->csum = data[ndata - 2] << 8 | data[ndata - 1];
+ }
+ if (sk->csum == chksum)
+ {
+ for (i = 0; i < nskey; i++)
+ {
+ nbits = data[pos] << 8 | data[pos + 1];
+
+ if (gcry_mpi_scan (&sk->mpi[i], GCRYMPI_FMT_PGP, data,
+ (nbits+7)/8+2, &nbytes))
+ {
+ wipemem (data, sk->enclen);
+ cdk_free (data);
+ return CDK_Wrong_Format;
+ }
+ gcry_mpi_set_flag (sk->mpi[i], GCRYMPI_FLAG_SECURE);
+ pos += (nbits+7)/8+2;
}
}
- cdk_cipher_close( hd );
+ wipemem (data, sk->enclen);
+ cdk_free (data);
}
- else {
- chksum = 0;
- for( i = 0; i < nskey; i++ )
- chksum += checksum_mpi( sk->mpi[i] );
+ else
+ {
+ byte buf[MAX_MPI_BYTES+2];
+
+ chksum = 0;
+ for (i = 0; i < nskey; i++)
+ {
+ gcry_cipher_sync (hd);
+ gcry_mpi_print (GCRYMPI_FMT_PGP, buf, DIM (buf),
+ &nbytes, sk->mpi[i]);
+ gcry_cipher_decrypt (hd, buf+2, nbytes-2, NULL, 0);
+ gcry_mpi_release (sk->mpi[i]);
+ if (gcry_mpi_scan (&sk->mpi[i], GCRYMPI_FMT_PGP,
+ buf, nbytes, &nbytes))
+ return CDK_Wrong_Format;
+ chksum += checksum_mpi (sk->mpi[i]);
+ }
}
- if( chksum != sk->csum )
- return CDK_Chksum_Error;
- sk->is_protected = 0;
- return 0;
+ gcry_cipher_close (hd);
+ if (chksum != sk->csum)
+ return CDK_Chksum_Error;
+ sk->is_protected = 0;
+ return 0;
}
cdk_error_t
-cdk_sk_protect( cdk_pkt_seckey_t sk, const char * pass )
+cdk_sk_protect (cdk_pkt_seckey_t sk, const char *pass)
{
- cdk_cipher_hd_t hd;
- cdk_md_hd_t md;
- cdk_mpi_t a;
- cdk_dek_t dek;
- cdk_s2k_t s2k;
- byte * p;
- size_t enclen = 0, nskey, i;
- int rc;
-
- rc = cdk_s2k_new( &s2k, 3, CDK_MD_SHA1, NULL );
- if( rc )
- return rc;
- rc = cdk_dek_from_passphrase( &dek, CDK_CIPHER_3DES, s2k, 2, pass );
- if( rc )
- return rc;
-
- nskey = cdk_pk_get_nskey( sk->pubkey_algo );
- for( i = 0; i < nskey; i++ ) {
- enclen += 2;
- enclen += sk->mpi[i]->bytes;
+ gcry_cipher_hd_t hd = NULL;
+ cdk_dek_t dek = NULL;
+ cdk_s2k_t s2k;
+ byte *p = NULL, buf[MAX_MPI_BYTES+2];
+ size_t enclen = 0, nskey, i, nbytes;
+ size_t dlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
+ gcry_error_t err;
+ cdk_error_t rc;
+
+ nskey = cdk_pk_get_nskey (sk->pubkey_algo );
+ if (!nskey)
+ return CDK_Inv_Algo;
+
+ rc = cdk_s2k_new (&s2k, CDK_S2K_ITERSALTED, GCRY_MD_SHA256, NULL);
+ if (!rc)
+ rc = cdk_dek_from_passphrase (&dek, GCRY_CIPHER_AES, s2k, 1, pass);
+ if (rc)
+ {
+ cdk_s2k_free (s2k);
+ return rc;
}
- p = sk->encdata = cdk_calloc( 1, enclen + 20 + 1 );
- if( !p )
- return CDK_Out_Of_Core;
- enclen = 0;
- for( i = 0; i < nskey; i++ ) {
- a = sk->mpi[i];
- p[enclen++] = a->bits >> 8;
- p[enclen++] = a->bits;
- memcpy( p + enclen, a->data, a->bytes );
- enclen += a->bytes;
+
+ for (i = 0; i < nskey; i++)
+ {
+ enclen += 2;
+ enclen += (gcry_mpi_get_nbits (sk->mpi[i])+7)/8;
}
- enclen += 20;
- sk->enclen = enclen;
- sk->protect.s2k = s2k;
- sk->protect.algo = CDK_CIPHER_3DES;
- sk->protect.ivlen = cdk_cipher_get_algo_blklen( sk->protect.algo );
- gcry_randomize( sk->protect.iv, sk->protect.ivlen, GCRY_STRONG_RANDOM );
- hd = cdk_cipher_open( sk->protect.algo, 1,
- dek->key, dek->keylen,
- sk->protect.iv, sk->protect.ivlen );
- if( !hd ) {
- cdk_free( p );
- return CDK_Gcry_Error;
+ p = sk->encdata = cdk_calloc (1, enclen + dlen + 1);
+ if (!p)
+ {
+ cdk_s2k_free (s2k);
+ return CDK_Out_Of_Core;
}
-
- md = cdk_md_open( CDK_MD_SHA1, GCRY_CIPHER_SECURE );
- if( !md ) {
- cdk_cipher_close( hd );
- cdk_free( p );
- return CDK_Gcry_Error;
+
+ enclen = 0;
+ for (i = 0; i < nskey; i++)
+ {
+ if (gcry_mpi_print (GCRYMPI_FMT_PGP, buf,
+ DIM (buf), &nbytes, sk->mpi[i]))
+ {
+ cdk_free (p);
+ cdk_s2k_free (s2k);
+ return CDK_Wrong_Format;
+ }
+ memcpy (p + enclen, buf, nbytes);
+ enclen += nbytes;
}
- sk->protect.sha1chk = 1;
- sk->is_protected = 1;
- sk->csum = 0;
- cdk_md_write( md, p, enclen - 20 );
- cdk_md_final( md );
- memcpy( p + enclen - 20, cdk_md_read( md, 0 ), 20 );
- cdk_md_close( md );
- rc = cdk_cipher_encrypt( hd, p, p, enclen );
- cdk_cipher_close( hd );
- cdk_dek_free( dek );
- return rc;
+
+ enclen += dlen;
+ sk->enclen = enclen;
+ sk->protect.s2k = s2k;
+ sk->protect.algo = GCRY_CIPHER_AES;
+ sk->protect.ivlen = gcry_cipher_get_algo_blklen (sk->protect.algo);
+ gcry_randomize (sk->protect.iv, sk->protect.ivlen, GCRY_STRONG_RANDOM);
+ err = gcry_cipher_open (&hd, sk->protect.algo, GCRY_CIPHER_MODE_CFB,
+ GCRY_CIPHER_ENABLE_SYNC);
+ if (err)
+ {
+ cdk_dek_free (dek);
+ rc = map_gcry_error (err);
+ goto leave;
+ }
+
+ err = gcry_cipher_setkey (hd, dek->key, dek->keylen);
+ if (!err)
+ err = gcry_cipher_setiv (hd, sk->protect.iv, sk->protect.ivlen);
+ cdk_dek_free (dek);
+ if (err)
+ {
+ rc = map_gcry_error (err);
+ goto leave;
+ }
+
+ sk->protect.sha1chk = 1;
+ sk->is_protected = 1;
+ sk->csum = 0;
+
+ gcry_md_hash_buffer (GCRY_MD_SHA1, buf, p, enclen-dlen);
+ memcpy (p + enclen - dlen, buf, dlen);
+ gcry_cipher_encrypt (hd, p, enclen, NULL, 0);
+
+ /* FIXME: We should release all MPI's and set the elements to NULL. */
+
+ leave:
+ gcry_cipher_close (hd);
+ return rc;
}
@@ -839,240 +859,253 @@ 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 )
-{
- if( !sk )
- return CDK_Inv_Value;
- return _cdk_copy_pubkey( ret_pk, sk->pk );
-}
-
-
-int
-cdk_pk_revoke_import( cdk_keydb_hd_t db, const char * revcert )
+cdk_pk_from_secret_key (cdk_pkt_seckey_t sk, cdk_pkt_pubkey_t *ret_pk)
{
- /* due to the fact the keydb code can't insert or modify packets
- it is not possible to handle this step yet */
- return 0;
+ if (!sk)
+ return CDK_Inv_Value;
+ return _cdk_copy_pubkey (ret_pk, sk->pk);
}
-int
-cdk_pk_revoke_create( cdk_pkt_seckey_t sk, int code, const char * inf,
- char ** ret_revcert )
+#if 0 /* FIXME: Code is not finished yet. */
+cdk_error_t
+cdk_pk_revoke_cert_create (cdk_pkt_seckey_t sk, int code, const char *inf,
+ char **ret_revcert)
{
- cdk_md_hd_t md;
- cdk_subpkt_t node;
- cdk_pkt_signature_t sig;
- char * p = NULL, * dat;
- int n;
-
- if( !sk || !ret_revcert )
- return CDK_Inv_Value;
- if( code < 0 || code > 3 )
- return CDK_Inv_Value;
-
- sig = cdk_calloc( 1, sizeof * sig );
- if( !sig )
- return CDK_Out_Of_Core;
- _cdk_sig_create( sk->pk, sig );
- n = 1;
- if( inf ) {
- n += strlen( p );
- p = cdk_utf8_encode( inf );
- }
- dat = cdk_calloc( 1, n+1 );
- if( !dat ) {
- _cdk_free_signature( sig );
- return CDK_Out_Of_Core;
+ gcry_md_hd_t md;
+ cdk_subpkt_t node;
+ cdk_pkt_signature_t sig;
+ char *p = NULL, *dat;
+ gcry_error_t err;
+ cdk_error_t rc = 0;
+ size_t n;
+
+ if (!sk || !ret_revcert)
+ return CDK_Inv_Value;
+ if(code < 0 || code > 3)
+ return CDK_Inv_Value;
+
+ sig = cdk_calloc (1, sizeof *sig);
+ if (!sig)
+ return CDK_Out_Of_Core;
+ _cdk_sig_create (sk->pk, sig);
+ n = 1;
+ if (inf)
+ {
+ n += strlen (p);
+ p = cdk_utf8_encode (inf);
}
- dat[0] = code;
- if( inf )
- memcpy( dat+1, p, strlen( p ) );
- cdk_free( p );
-
- node = cdk_subpkt_new( n );
- if( node ) {
- cdk_subpkt_init( node, CDK_SIGSUBPKT_REVOC_REASON, dat, n );
- cdk_subpkt_add( sig->hashed, node );
+ dat = cdk_calloc (1, n+1);
+ if (!dat)
+ {
+ _cdk_free_signature (sig);
+ return CDK_Out_Of_Core;
}
- cdk_free( dat );
-
- md = cdk_md_open( CDK_MD_SHA1, 0 );
- if( !md ) {
- _cdk_free_signature( sig );
- return CDK_Gcry_Error;
+ dat[0] = code;
+ if (inf)
+ memcpy (dat+1, p, strlen (p));
+ cdk_free (p);
+
+ node = cdk_subpkt_new (n);
+ if (node)
+ {
+ cdk_subpkt_init (node, CDK_SIGSUBPKT_REVOC_REASON, dat, n);
+ cdk_subpkt_add (sig->hashed, node);
}
- _cdk_hash_pubkey( sk->pk, md, 0 );
- _cdk_free_signature( sig );
- return 0;
+ cdk_free (dat);
+
+ err = gcry_md_open (&md, GCRY_MD_SHA1, 0);
+ if (err)
+ rc = map_gcry_error (err);
+ else
+ _cdk_hash_pubkey (sk->pk, md, 0);
+ _cdk_free_signature (sig);
+
+ return rc;
}
-
+#endif
int
-_cdk_sk_get_csum( cdk_pkt_seckey_t sk )
+_cdk_sk_get_csum (cdk_pkt_seckey_t sk)
{
- u16 csum = 0, i;
-
- if( !sk )
- return 0;
- for( i = 0; i < cdk_pk_get_nskey( sk->pubkey_algo ); i++ )
- csum += checksum_mpi( sk->mpi[i] );
- return csum;
+ u16 csum = 0, i;
+
+ if (!sk)
+ return 0;
+ for (i = 0; i < cdk_pk_get_nskey (sk->pubkey_algo); i++)
+ csum += checksum_mpi (sk->mpi[i]);
+ return csum;
}
-int
-cdk_pk_get_fingerprint( cdk_pkt_pubkey_t pk, byte * fpr )
+cdk_error_t
+cdk_pk_get_fingerprint (cdk_pkt_pubkey_t pk, byte *fpr)
{
- cdk_md_hd_t hd;
- int md_algo;
- int dlen = 0;
-
- if( !pk || !fpr )
- return CDK_Inv_Value;
-
- if( pk->version < 4 && is_RSA( pk->pubkey_algo ) )
- md_algo = CDK_MD_MD5; /* special */
- else
- md_algo = pk->version < 4 ? CDK_MD_RMD160 : CDK_MD_SHA1;
- dlen = cdk_md_get_algo_dlen( md_algo );
- hd = cdk_md_open( md_algo, 0 );
- if( !hd )
- return CDK_Gcry_Error;
- _cdk_hash_pubkey( pk, hd, 1 );
- cdk_md_final( hd );
- memcpy( fpr, cdk_md_read( hd, md_algo ), dlen );
- cdk_md_close( hd );
- if( dlen == 16 )
- memset( fpr + 16, 0, 4 );
- return 0;
+ gcry_md_hd_t hd;
+ int md_algo;
+ int dlen = 0;
+ gcry_error_t err;
+
+ if (!pk || !fpr)
+ return CDK_Inv_Value;
+
+ if (pk->version < 4 && is_RSA (pk->pubkey_algo))
+ md_algo = GCRY_MD_MD5; /* special */
+ else
+ md_algo = GCRY_MD_SHA1;
+ dlen = gcry_md_get_algo_dlen (md_algo);
+ err = gcry_md_open (&hd, md_algo, 0);
+ if (err)
+ return map_gcry_error (err);
+ _cdk_hash_pubkey (pk, hd, 1);
+ gcry_md_final (hd);
+ memcpy (fpr, gcry_md_read (hd, md_algo), dlen);
+ gcry_md_close (hd);
+ if (dlen == 16)
+ memset (fpr + 16, 0, 4);
+ return 0;
}
u32
-cdk_pk_fingerprint_get_keyid( const byte * fpr, size_t fprlen, u32 * keyid )
+cdk_pk_fingerprint_get_keyid (const byte *fpr, size_t fprlen, u32 *keyid)
{
u32 lowbits = 0;
- /* in this case we say the key is a V3 RSA key and we can't
- use the fingerprint to get the keyid. */
- if( fpr && fprlen == 16 )
- return 0;
- else if( keyid && fpr ) {
- keyid[0] = _cdk_buftou32( fpr + 12 );
- keyid[1] = _cdk_buftou32( fpr + 16 );
- lowbits = keyid[1];
+ /* In this case we say the key is a V3 RSA key and we can't
+ use the fingerprint to get the keyid. */
+ if (fpr && fprlen == 16)
+ return 0;
+ else if (keyid && fpr)
+ {
+ keyid[0] = _cdk_buftou32 (fpr + 12);
+ keyid[1] = _cdk_buftou32 (fpr + 16);
+ lowbits = keyid[1];
}
- else if( fpr )
- lowbits = _cdk_buftou32( fpr + 16 );
- return lowbits;
+ else if (fpr)
+ lowbits = _cdk_buftou32 (fpr + 16);
+ return lowbits;
}
u32
-cdk_pk_get_keyid( cdk_pkt_pubkey_t pk, u32 * keyid )
+cdk_pk_get_keyid (cdk_pkt_pubkey_t pk, u32 *keyid)
{
- u32 lowbits = 0;
- byte buf[24];
-
- if( pk &&( !pk->keyid[0] || !pk->keyid[1] ) ) {
- if( pk->version < 4 && is_RSA( pk->pubkey_algo ) ) {
- size_t n = pk->mpi[0]->bytes;
- const byte * p = pk->mpi[0]->data + 2;
- pk->keyid[0] = p[n-8] << 24 | p[n-7] << 16 | p[n-6] << 8 | p[n-5];
- pk->keyid[1] = p[n-4] << 24 | p[n-3] << 16 | p[n-2] << 8 | p[n-1];
+ u32 lowbits = 0;
+ byte buf[24];
+
+ if (pk && (!pk->keyid[0] || !pk->keyid[1]))
+ {
+ if (pk->version < 4 && is_RSA (pk->pubkey_algo))
+ {
+ byte p[MAX_MPI_BYTES];
+ size_t n;
+
+ gcry_mpi_print (GCRYMPI_FMT_USG, p, MAX_MPI_BYTES, &n, pk->mpi[0]);
+ pk->keyid[0] = p[n-8] << 24 | p[n-7] << 16 | p[n-6] << 8 | p[n-5];
+ pk->keyid[1] = p[n-4] << 24 | p[n-3] << 16 | p[n-2] << 8 | p[n-1];
}
- else if( pk->version == 4 ) {
- cdk_pk_get_fingerprint( pk, buf );
- pk->keyid[0] = _cdk_buftou32( buf + 12 );
- pk->keyid[1] = _cdk_buftou32( buf + 16 );
+ else if (pk->version == 4)
+ {
+ cdk_pk_get_fingerprint (pk, buf);
+ pk->keyid[0] = _cdk_buftou32 (buf + 12);
+ pk->keyid[1] = _cdk_buftou32 (buf + 16);
}
}
- lowbits = pk ? pk->keyid[1] : 0;
- if( keyid && pk ) {
- keyid[0] = pk->keyid[0];
- keyid[1] = pk->keyid[1];
+ lowbits = pk ? pk->keyid[1] : 0;
+ if (keyid && pk)
+ {
+ keyid[0] = pk->keyid[0];
+ keyid[1] = pk->keyid[1];
}
- return lowbits;
+
+ return lowbits;
}
u32
-cdk_sk_get_keyid( cdk_pkt_seckey_t sk, u32 * keyid )
+cdk_sk_get_keyid (cdk_pkt_seckey_t sk, u32 *keyid)
{
- u32 lowbits = 0;
-
- if( sk && sk->pk ) {
- lowbits = cdk_pk_get_keyid( sk->pk, keyid );
- sk->keyid[0] = sk->pk->keyid[0];
- sk->keyid[1] = sk->pk->keyid[1];
+ u32 lowbits = 0;
+
+ if (sk && sk->pk)
+ {
+ lowbits = cdk_pk_get_keyid (sk->pk, keyid);
+ sk->keyid[0] = sk->pk->keyid[0];
+ sk->keyid[1] = sk->pk->keyid[1];
}
- return lowbits;
+
+ return lowbits;
}
u32
cdk_sig_get_keyid( cdk_pkt_signature_t sig, u32 * keyid )
{
- u32 lowbits = sig ? sig->keyid[1] : 0;
+ u32 lowbits = sig ? sig->keyid[1] : 0;
- if( keyid && sig ) {
- keyid[0] = sig->keyid[0];
- keyid[1] = sig->keyid[1];
+ if (keyid && sig)
+ {
+ keyid[0] = sig->keyid[0];
+ keyid[1] = sig->keyid[1];
}
- return lowbits;
+ return lowbits;
}
u32
-_cdk_pkt_get_keyid( cdk_packet_t pkt, u32 * keyid )
+_cdk_pkt_get_keyid (cdk_packet_t pkt, u32 *keyid)
{
- u32 lowbits;
-
- if( !pkt )
- return 0;
-
- switch( pkt->pkttype ) {
+ u32 lowbits;
+
+ if (!pkt)
+ return 0;
+
+ switch (pkt->pkttype)
+ {
case CDK_PKT_PUBLIC_KEY:
case CDK_PKT_PUBLIC_SUBKEY:
- lowbits = cdk_pk_get_keyid( pkt->pkt.public_key, keyid );
- break;
+ lowbits = cdk_pk_get_keyid (pkt->pkt.public_key, keyid);
+ break;
case CDK_PKT_SECRET_KEY:
case CDK_PKT_SECRET_SUBKEY:
- lowbits = cdk_sk_get_keyid( pkt->pkt.secret_key, keyid );
- break;
-
+ lowbits = cdk_sk_get_keyid (pkt->pkt.secret_key, keyid);
+ break;
+
case CDK_PKT_SIGNATURE:
- lowbits = cdk_sig_get_keyid( pkt->pkt.signature, keyid );
- break;
+ lowbits = cdk_sig_get_keyid (pkt->pkt.signature, keyid);
+ break;
default:
- lowbits = 0;
+ lowbits = 0;
+ break;
}
- return lowbits;
+
+ return lowbits;
}
int
-_cdk_pkt_get_fingerprint( cdk_packet_t pkt, byte * fpr )
+_cdk_pkt_get_fingerprint (cdk_packet_t pkt, byte *fpr)
{
- if( !pkt || !fpr )
- return CDK_Inv_Value;
-
- switch( pkt->pkttype ) {
+ if (!pkt || !fpr)
+ return CDK_Inv_Value;
+
+ switch (pkt->pkttype)
+ {
case CDK_PKT_PUBLIC_KEY:
case CDK_PKT_PUBLIC_SUBKEY:
- return cdk_pk_get_fingerprint( pkt->pkt.public_key, fpr );
-
+ return cdk_pk_get_fingerprint (pkt->pkt.public_key, fpr);
+
case CDK_PKT_SECRET_KEY:
case CDK_PKT_SECRET_SUBKEY:
- return cdk_pk_get_fingerprint( pkt->pkt.secret_key->pk, fpr );
-
+ return cdk_pk_get_fingerprint (pkt->pkt.secret_key->pk, fpr);
+
default:
- return CDK_Inv_Packet;
+ return CDK_Inv_Mode;
}
- return 0;
+ return 0;
}
/**
@@ -1086,14 +1119,13 @@ _cdk_pkt_get_fingerprint( cdk_packet_t pkt, byte * fpr )
* is stored in canonical format as used by libgcrypt
* (GCRYSEXP_FMT_CANON).
**/
-
cdk_error_t
cdk_pubkey_to_sexp (cdk_pkt_pubkey_t pk, char **sexp, size_t * len)
{
- int rc;
char *buf;
size_t sexp_len;
gcry_sexp_t pk_sexp;
+ cdk_error_t rc;
if (!pk || !sexp)
return CDK_Inv_Value;
@@ -1104,35 +1136,30 @@ cdk_pubkey_to_sexp (cdk_pkt_pubkey_t pk, char **sexp, size_t * len)
sexp_len = gcry_sexp_sprint (pk_sexp, GCRYSEXP_FMT_CANON, NULL, 0);
if (!sexp_len)
- {
- return CDK_Gcry_Error;
- }
+ return CDK_Wrong_Format;
- buf = (char *) cdk_malloc (sexp_len);
+ buf = (char *)cdk_malloc (sexp_len);
if (!buf)
{
gcry_sexp_release (pk_sexp);
return CDK_Out_Of_Core;
}
-
- sexp_len =
- gcry_sexp_sprint (pk_sexp, GCRYSEXP_FMT_CANON, buf, sexp_len);
-
+
+ sexp_len = gcry_sexp_sprint (pk_sexp, GCRYSEXP_FMT_CANON, buf, sexp_len);
gcry_sexp_release (pk_sexp);
-
if (!sexp_len)
{
cdk_free (buf);
- return CDK_Gcry_Error;
+ return CDK_Wrong_Format;
}
if (len)
*len = sexp_len;
*sexp = buf;
-
return CDK_Success;
}
+
/**
* cdk_seckey_to_sexp:
* @sk: the secret key
@@ -1144,27 +1171,24 @@ cdk_pubkey_to_sexp (cdk_pkt_pubkey_t pk, char **sexp, size_t * len)
* is stored in canonical format as used by libgcrypt
* (GCRYSEXP_FMT_CANON).
**/
-
cdk_error_t
cdk_seckey_to_sexp (cdk_pkt_seckey_t sk, char **sexp, size_t * len)
{
- int rc;
char *buf;
size_t sexp_len;
gcry_sexp_t sk_sexp;
+ cdk_error_t rc;
if (!sk || !sexp)
return CDK_Inv_Value;
-
+
rc = seckey_to_sexp (&sk_sexp, sk);
if (rc)
return rc;
sexp_len = gcry_sexp_sprint (sk_sexp, GCRYSEXP_FMT_CANON, NULL, 0);
if (!sexp_len)
- {
- return CDK_Gcry_Error;
- }
+ return CDK_Wrong_Format;
buf = (char *) cdk_malloc (sexp_len);
if (!buf)
@@ -1173,15 +1197,12 @@ cdk_seckey_to_sexp (cdk_pkt_seckey_t sk, char **sexp, size_t * len)
return CDK_Out_Of_Core;
}
- sexp_len =
- gcry_sexp_sprint (sk_sexp, GCRYSEXP_FMT_CANON, buf, sexp_len);
-
+ sexp_len = gcry_sexp_sprint (sk_sexp, GCRYSEXP_FMT_CANON, buf, sexp_len);
gcry_sexp_release (sk_sexp);
-
if (!sexp_len)
{
cdk_free (buf);
- return CDK_Gcry_Error;
+ return CDK_Wrong_Format;
}
if (len)
diff --git a/libextra/opencdk/read-packet.c b/libextra/opencdk/read-packet.c
index 9bdc025855..5242278251 100644
--- a/libextra/opencdk/read-packet.c
+++ b/libextra/opencdk/read-packet.c
@@ -1,5 +1,5 @@
/* read-packet.c - Read OpenPGP packets
- * Copyright (C) 2001, 2002, 2003 Timo Schulz
+ * Copyright (C) 2001, 2002, 2003, 2007 Timo Schulz
*
* This file is part of OpenCDK.
*
@@ -12,12 +12,7 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
@@ -28,892 +23,964 @@
#include "opencdk.h"
#include "main.h"
#include "packet.h"
-#include "cipher.h"
-
-
-static int
-stream_getc( cdk_stream_t s )
-{
- return cdk_stream_getc( s );
-}
+#include "types.h"
+/* The version of the MDC packet considering the lastest OpenPGP draft. */
+#define MDC_PKT_VER 1
static int
-stream_read (cdk_stream_t s, void * buf, size_t count, size_t * r_nread)
+stream_read (cdk_stream_t s, void *buf, size_t buflen, size_t *r_nread)
{
- int nread = cdk_stream_read (s, buf, count);
- if( !nread )
- return CDK_File_Error;
- if( r_nread )
- *r_nread = nread;
- return 0;
+ *r_nread = cdk_stream_read (s, buf, buflen);
+ return *r_nread > 0? 0: _cdk_stream_get_errno (s);
}
+/* Try to read 4 octets from the stream. */
static u32
-read_32 (cdk_stream_t buf)
+read_32 (cdk_stream_t s)
{
- u32 u = 0;
- int c;
-
- if( !buf )
- return (u32) -1;
-
- if( (c = stream_getc( buf )) == EOF )
- return (u32)-1;
- u |= c << 24;
- if( (c = stream_getc( buf )) == EOF )
- return (u32)-1;
- u |= c << 16;
- if( (c = stream_getc( buf )) == EOF )
- return (u32)-1;
- u |= c << 8;
- if( (c = stream_getc( buf )) == EOF )
- return (u32)-1;
- u |= c;
- return u;
+ byte buf[4];
+ size_t nread;
+
+ assert (buf != NULL);
+
+ stream_read (s, buf, 4, &nread);
+ if (nread != 4)
+ return (u32)-1;
+ return buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
}
+/* Try to read 2 octets from a stream. */
static u16
-read_16 (cdk_stream_t buf)
+read_16 (cdk_stream_t s)
{
- u16 u = 0;
- int c;
-
- if( !buf )
- return (u16)-1;
-
- if( (c = stream_getc( buf )) == EOF )
- return (u16)-1;
- u |= c << 8;
- if( (c = stream_getc( buf )) == EOF )
- return (u16)-1;
- u |= c;
- return u;
+ byte buf[2];
+ size_t nread;
+
+ assert (s != NULL);
+
+ stream_read (s, buf, 2, &nread);
+ if (nread != 2)
+ return (u16)-1;
+ return buf[0] << 8 | buf[1];
}
-#define check_s2k_mode( mode ) ( \
- (mode) == CDK_S2K_SIMPLE \
- || (mode) == CDK_S2K_SALTED \
- || (mode) == CDK_S2K_ITERSALTED \
-)
-
static int
-read_s2k( cdk_stream_t inp, cdk_s2k_t s2k )
+read_s2k (cdk_stream_t inp, cdk_s2k_t s2k)
{
- size_t nread = 0;
- int rc = 0;
-
- if( !inp || !s2k )
- return CDK_Inv_Value;
-
- if( DEBUG_PKT )
- _cdk_log_debug( "** read S2K part\n" );
-
- s2k->mode = stream_getc( inp );
- if( s2k->mode == EOF || !check_s2k_mode( s2k->mode ) )
- return CDK_Inv_Packet;
- s2k->hash_algo = stream_getc( inp );
- if( s2k->mode == CDK_S2K_SIMPLE ) {
- memset( s2k->salt, 0, sizeof s2k->salt );
- /* nothing else to do */
- }
- else if( s2k->mode == CDK_S2K_SALTED || s2k->mode == CDK_S2K_ITERSALTED ) {
- rc = stream_read( inp, s2k->salt, sizeof s2k->salt, &nread );
- if( !rc && nread != sizeof s2k->salt )
- return CDK_Inv_Packet;
- if( !rc && s2k->mode == CDK_S2K_ITERSALTED ) {
- s2k->count = stream_getc( inp );
- if( s2k->count == EOF )
- return CDK_Inv_Packet;
+ size_t nread;
+ cdk_error_t rc;
+
+ if (!inp || !s2k)
+ return CDK_Inv_Value;
+
+ if (DEBUG_PKT)
+ _cdk_log_debug ("** read S2K part\n");
+
+ rc = 0;
+ s2k->mode = cdk_stream_getc (inp);
+ if (cdk_stream_eof (inp))
+ return CDK_Inv_Packet;
+ if (s2k->mode != CDK_S2K_SIMPLE && s2k->mode != CDK_S2K_SALTED &&
+ s2k->mode != CDK_S2K_ITERSALTED)
+ return CDK_Inv_Packet;
+ s2k->hash_algo = cdk_stream_getc (inp);
+ if (s2k->mode == CDK_S2K_SIMPLE) /* No additional elements. */
+ memset (s2k->salt, 0, sizeof (s2k->salt));
+ else if (s2k->mode == CDK_S2K_SALTED ||
+ s2k->mode == CDK_S2K_ITERSALTED)
+ {
+ rc = stream_read (inp, s2k->salt, DIM (s2k->salt), &nread);
+ if (rc)
+ return CDK_Inv_Packet;
+ if (nread != DIM (s2k->salt))
+ return CDK_Too_Short;
+ if (s2k->mode == CDK_S2K_ITERSALTED)
+ {
+ s2k->count = cdk_stream_getc (inp);
+ if (cdk_stream_eof (inp))
+ return CDK_Inv_Packet;
}
}
- else
- return CDK_Inv_Mode;
- return rc;
+ else
+ return CDK_Inv_Mode;
+ return rc;
}
-static int
-read_mpi (cdk_stream_t inp, cdk_mpi_t * ret_m, int secure)
+static cdk_error_t
+read_mpi (cdk_stream_t inp, gcry_mpi_t * ret_m, int secure)
{
- cdk_mpi_t m = NULL;
- size_t nread = 0, nbits = 0, nbytes = 0;
- int rc = 0;
-
- if( !inp || !ret_m )
- return CDK_Inv_Value;
-
- if (DEBUG_PKT)
- _cdk_log_debug ("** read MPI part\n");
-
- nbits = read_16 (inp);
- nbytes = (nbits + 7) / 8;
- if( nbits > MAX_MPI_BITS || nbits == 0 )
- return CDK_MPI_Error; /* sanity check */
- m = secure ? cdk_salloc( sizeof *m + nbytes + 2, 1 ) :
- cdk_calloc( 1, sizeof *m + nbytes + 2 );
- if( !m )
- return CDK_Out_Of_Core;
- m->bytes = nbytes;
- m->bits = nbits;
-
- /* the prefix encodes the length of the MPI data */
- m->data[0] = nbits >> 8;
- m->data[1] = nbits;
- rc = stream_read( inp, m->data + 2, nbytes, &nread );
- if( !rc && nread != nbytes )
- rc = CDK_MPI_Error;
- *ret_m = m;
- return rc;
+ gcry_mpi_t m;
+ 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 */
+
+ rc = stream_read (inp, buf+2, nread, &nread);
+ if (!rc && nread != ((nbits+7)/8))
+ return CDK_MPI_Error;
+
+ buf[0] = nbits >> 8;
+ buf[1] = nbits >> 0;
+ err = gcry_mpi_scan (&m, GCRYMPI_FMT_PGP, buf, nread+2, &nread);
+ if (err)
+ return map_gcry_error (err);
+ if (secure)
+ gcry_mpi_set_flag (m, GCRYMPI_FLAG_SECURE);
+ *ret_m = m;
+ 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. */
size_t
-_cdk_pkt_read_len( FILE * inp, int * ret_partial )
+_cdk_pkt_read_len (FILE *inp, size_t *ret_partial)
{
- int c1 = 0, c2 = 0;
- size_t pktlen = 0;
-
- if( (c1 = fgetc (inp)) == EOF )
- return (size_t)EOF;
- if( c1 < 224 || c1 == 255 )
- *ret_partial = 0; /* end of partial data */
- if( c1 < 192 )
- pktlen = c1;
- else if( c1 >= 192 && c1 <= 223 ) {
- if( (c2 = fgetc( inp )) == EOF )
- return (size_t)EOF;
- pktlen = ((c1 - 192) << 8) + c2 + 192;
+ int c1, c2;
+ size_t pktlen;
+
+ c1 = fgetc (inp);
+ if (c1 == EOF)
+ return (size_t)EOF;
+ if (c1 < 224 || c1 == 255)
+ *ret_partial = 0; /* End of partial data */
+ if (c1 < 192)
+ pktlen = c1;
+ else if (c1 >= 192 && c1 <= 223)
+ {
+ c2 = fgetc (inp);
+ if (c2 == EOF)
+ return (size_t)EOF;
+ pktlen = ((c1 - 192) << 8) + c2 + 192;
}
- else if( c1 == 255 ) {
- pktlen = fgetc( inp ) << 24;
- pktlen |= fgetc( inp ) << 16;
- pktlen |= fgetc( inp ) << 8;
- pktlen |= fgetc( inp );
- if( !pktlen )
- return (size_t)EOF;
+ else if (c1 == 255)
+ {
+ pktlen = fgetc (inp) << 24;
+ pktlen |= fgetc (inp) << 16;
+ pktlen |= fgetc (inp) << 8;
+ pktlen |= fgetc (inp) << 0;
}
- else
- pktlen = 1 << (c1 & 0x1f);
- return pktlen;
+ else
+ pktlen = 1 << (c1 & 0x1f);
+ return pktlen;
}
-static int
-read_encrypted( cdk_stream_t inp, size_t pktlen, cdk_pkt_encrypted_t enc,
- int partial, int mdc )
+static cdk_error_t
+read_encrypted (cdk_stream_t inp, size_t pktlen, cdk_pkt_encrypted_t enc,
+ int partial, int is_mdc)
{
- int rc = 0, version;
-
- if( !inp || !enc )
- return CDK_Inv_Value;
-
- if( DEBUG_PKT )
- _cdk_log_debug( "** read encrypted packet %d bytes\n", pktlen );
+ if (!inp || !enc)
+ return CDK_Inv_Value;
- if( mdc ) {
- version = stream_getc( inp );
- if( version != 1 )
- return CDK_Inv_Packet;
- enc->mdc_method = CDK_MD_SHA1;
- pktlen--;
+ if (DEBUG_PKT)
+ _cdk_log_debug ("** read encrypted packet %d bytes\n", pktlen);
+
+ if (is_mdc)
+ {
+ int version = cdk_stream_getc (inp);
+ if (version != MDC_PKT_VER)
+ return CDK_Inv_Packet;
+ enc->mdc_method = CDK_MD_SHA1;
+ pktlen--;
}
- if( pktlen < 10 )
- return CDK_Inv_Packet; /* we need at least blocksize + 2 bytes */
- if( partial )
- _cdk_stream_set_blockmode( inp, pktlen );
- enc->len = pktlen;
- enc->buf = inp;
- return rc;
+ /* The packet must at least contain blocksize + 2 octets. */
+ if (pktlen < 10)
+ return CDK_Inv_Packet;
+ if (partial)
+ _cdk_stream_set_blockmode (inp, pktlen);
+ enc->len = pktlen;
+ enc->buf = inp;
+ return 0;
}
-static int
-read_symkey_enc( cdk_stream_t inp, size_t pktlen, cdk_pkt_symkey_enc_t ske )
+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 = 0, minlen = 0;
- int rc = 0;
-
- if( !inp || !ske )
- return CDK_Inv_Value;
-
- if( DEBUG_PKT )
- _cdk_log_debug( "** read symmetric key encrypted packet\n" );
-
- ske->version = stream_getc( inp );
- if( ske->version != 4 )
- return CDK_Inv_Packet;
-
- s2k = ske->s2k = cdk_calloc( 1, sizeof *ske->s2k );
- if( !ske->s2k )
- return CDK_Out_Of_Core;
-
- ske->cipher_algo = stream_getc( inp );
- s2k->mode = stream_getc( inp );
- switch( s2k->mode ) {
- case 0: minlen = 0; break;
- case 1: minlen = 8; break;
- case 3: minlen = 9; break;
+ cdk_s2k_t s2k;
+ size_t nread, minlen;
+ cdk_error_t rc;
+
+ if (!inp || !ske)
+ return CDK_Inv_Value;
+
+ if (DEBUG_PKT)
+ _cdk_log_debug ("** read symmetric key encrypted packet\n");
+
+ ske->version = cdk_stream_getc (inp);
+ if (ske->version != 4 || cdk_stream_eof (inp))
+ return CDK_Inv_Packet;
+
+ s2k = ske->s2k = cdk_calloc (1, sizeof *ske->s2k);
+ if (!ske->s2k)
+ return CDK_Out_Of_Core;
+
+ ske->cipher_algo = cdk_stream_getc (inp);
+ s2k->mode = cdk_stream_getc (inp);
+ switch (s2k->mode)
+ {
+ case CDK_S2K_SIMPLE : minlen = 0; break;
+ case CDK_S2K_SALTED : minlen = 8; break;
+ case CDK_S2K_ITERSALTED: minlen = 9; break;
+
+ default:
+ /* Invalid S2K mode. */
+ return CDK_Inv_Packet;
}
- s2k->hash_algo = stream_getc( inp );
- if( s2k->mode == 0 )
- ; /* nothing to do */
- else if( s2k->mode == 1 || s2k->mode == 3 ) {
- rc = stream_read( inp, s2k->salt, DIM (s2k->salt), &nread);
- if( !rc && nread != DIM( s2k->salt ) )
- return CDK_Inv_Packet;
- if( !rc && s2k->mode == 3 )
- s2k->count = stream_getc( inp );
+
+ 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)
+ return CDK_Inv_Packet;
+ if (nread != DIM (s2k->salt))
+ return CDK_Too_Short;
+
+ if (s2k->mode == CDK_S2K_ITERSALTED)
+ s2k->count = cdk_stream_getc (inp);
}
- else
- return CDK_Inv_Packet;
- ske->seskeylen = pktlen - 4 - minlen;
- if( ske->seskeylen > sizeof ske->seskey )
- return CDK_Inv_Packet;
- for( nread = 0; nread < ske->seskeylen; nread++ ) {
- ske->seskey[nread] = stream_getc( inp );
- if( cdk_stream_eof( inp ) )
- break;
+
+ ske->seskeylen = pktlen - 4 - minlen;
+ /* We check if there is an encrypted session key and if it fits into
+ the buffer. The maximal key length is 256-bit. */
+ if (ske->seskeylen > DIM (ske->seskey))
+ return CDK_Inv_Packet;
+ for (nread = 0; nread < ske->seskeylen; nread++)
+ {
+ ske->seskey[nread] = cdk_stream_getc (inp);
+ if (cdk_stream_eof (inp))
+ return CDK_Too_Short;
}
- return rc;
+
+ return 0;
}
-static int
-read_pubkey_enc( cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_enc_t pke )
+static cdk_error_t
+read_pubkey_enc (cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_enc_t pke)
{
- int rc = 0;
- int i, nenc = 0;
-
- if( !inp || !pke )
- return CDK_Inv_Value;
-
- if( DEBUG_PKT )
- _cdk_log_debug( "** read public key encrypted packet\n" );
-
- if( pktlen < 10 )
- return CDK_Inv_Packet;
- pke->version = stream_getc( inp );
- if( pke->version < 2 || pke->version > 3 )
- return CDK_Inv_Packet;
- pke->keyid[0] = read_32( inp );
- pke->keyid[1] = read_32( inp );
- if( !pke->keyid[0] && !pke->keyid[1] )
- pke->throw_keyid = 1; /* RFC2440 "speculative" keyID */
- pke->pubkey_algo = stream_getc( inp );
- nenc = cdk_pk_get_nenc( pke->pubkey_algo );
- if( !nenc )
- return CDK_Inv_Algo;
- for( i = 0; i < nenc; i++ ) {
- rc = read_mpi( inp, &pke->mpi[i], 0 );
- if( rc )
- break;
+ 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");
+
+ if (pktlen < 12)
+ return CDK_Inv_Packet;
+ pke->version = cdk_stream_getc (inp);
+ if (pke->version < 2 || pke->version > 3)
+ return CDK_Inv_Packet;
+ pke->keyid[0] = read_32 (inp);
+ pke->keyid[1] = read_32 (inp);
+ if (!pke->keyid[0] && !pke->keyid[1])
+ pke->throw_keyid = 1; /* RFC2440 "speculative" keyID */
+ pke->pubkey_algo = cdk_stream_getc (inp);
+ nenc = cdk_pk_get_nenc (pke->pubkey_algo);
+ if (!nenc)
+ return CDK_Inv_Algo;
+ for (i = 0; i < nenc; i++)
+ {
+ rc = read_mpi (inp, &pke->mpi[i], 0);
+ if (rc)
+ return rc;
}
- return rc;
+
+ return 0;
}
-static int
-read_mdc( cdk_stream_t inp, cdk_pkt_mdc_t mdc )
+static cdk_error_t
+read_mdc (cdk_stream_t inp, cdk_pkt_mdc_t mdc)
{
- size_t n = 0;
- int rc = 0;
-
- if( !inp || !mdc )
- return CDK_Inv_Value;
+ size_t n;
+ cdk_error_t rc;
- if (DEBUG_PKT)
- _cdk_log_debug ("** read MDC packet\n");
-
- rc = stream_read( inp, mdc->hash, 20, &n );
- if( !rc && n != 20 )
- rc = CDK_Inv_Packet;
- return rc;
+ if (!inp || !mdc)
+ return CDK_Inv_Value;
+
+ if (DEBUG_PKT)
+ _cdk_log_debug ("** read MDC packet\n");
+
+ rc = stream_read (inp, mdc->hash, 20, &n);
+ if (rc)
+ return rc;
+
+ return n != 20? CDK_Inv_Packet : 0;
}
-static int
-read_compressed( cdk_stream_t inp, size_t pktlen, cdk_pkt_compressed_t c )
+static cdk_error_t
+read_compressed (cdk_stream_t inp, size_t pktlen, cdk_pkt_compressed_t c)
{
- if (!inp || !c)
- return CDK_Inv_Value;
-
- if (DEBUG_PKT)
- _cdk_log_debug ("** read compressed packet\n");
-
- c->algorithm = stream_getc( inp );
- if( c->algorithm > 2 )
- return CDK_Inv_Packet;
-
- /* don't know the size, so we read until EOF */
- if( !pktlen ) {
- c->len = 0;
- c->buf = inp;
+ if (!inp || !c)
+ return CDK_Inv_Value;
+
+ if (DEBUG_PKT)
+ _cdk_log_debug ("** read compressed packet\n");
+
+ c->algorithm = cdk_stream_getc (inp);
+ if (c->algorithm > 3)
+ return CDK_Inv_Packet;
+
+ /* don't know the size, so we read until EOF */
+ if (!pktlen)
+ {
+ c->len = 0;
+ c->buf = inp;
}
-
- return 0;
+
+ /* FIXME: Support partial bodies. */
+ return 0;
}
-static int
-read_public_key( cdk_stream_t inp, cdk_pkt_pubkey_t pk )
+static cdk_error_t
+read_public_key (cdk_stream_t inp, cdk_pkt_pubkey_t pk)
{
- int i = 0, ndays, npkey;
- int rc = 0;
-
- if (!inp || !pk)
- return CDK_Inv_Value;
-
- if( DEBUG_PKT )
- _cdk_log_debug( "** read public key packet\n" );
-
- pk->is_invalid = 1; /* default to detect missing self signatures */
- pk->is_revoked = 0;
- pk->has_expired = 0;
-
- pk->version = stream_getc( inp );
- if( pk->version < 2 || pk->version > 4 )
- return CDK_Inv_Packet_Ver;
- pk->timestamp = read_32( inp );
- if( pk->version < 4 ) {
- ndays = read_16( inp );
- if( ndays )
- pk->expiredate = pk->timestamp + ndays * 86400L;
+ 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" );
+
+ pk->is_invalid = 1; /* default to detect missing self signatures */
+ pk->is_revoked = 0;
+ pk->has_expired = 0;
+
+ pk->version = cdk_stream_getc (inp);
+ if (pk->version < 2 || pk->version > 4)
+ return CDK_Inv_Packet_Ver;
+ pk->timestamp = read_32 (inp);
+ if (pk->version < 4)
+ {
+ ndays = read_16 (inp);
+ if (ndays)
+ pk->expiredate = pk->timestamp + ndays * 86400L;
}
- pk->pubkey_algo = stream_getc( inp );
- npkey = cdk_pk_get_npkey( pk->pubkey_algo );
- if( !npkey )
- return CDK_Inv_Algo;
- for( i = 0; i < npkey; i++ ) {
- rc = read_mpi( inp, &pk->mpi[i], 0 );
- if ( rc )
- break;
+
+ pk->pubkey_algo = cdk_stream_getc (inp);
+ npkey = cdk_pk_get_npkey (pk->pubkey_algo);
+ if (!npkey)
+ return CDK_Inv_Algo;
+ rc = 0;
+ for (i = 0; i < npkey; i++)
+ {
+ rc = read_mpi (inp, &pk->mpi[i], 0);
+ if (rc)
+ break;
}
- pk->pubkey_usage = _cdk_pk_algo_usage( pk->pubkey_algo );
- 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;
}
-static int
-read_public_subkey( cdk_stream_t inp, cdk_pkt_pubkey_t pk )
+static cdk_error_t
+read_public_subkey (cdk_stream_t inp, cdk_pkt_pubkey_t pk)
{
- if( !inp || !pk )
- return CDK_Inv_Value;
- return read_public_key( inp, pk );
+ if (!inp || !pk)
+ return CDK_Inv_Value;
+ return read_public_key (inp, pk);
}
-static int
-read_secret_key( cdk_stream_t inp, size_t pktlen, cdk_pkt_seckey_t sk )
+static cdk_error_t
+read_secret_key (cdk_stream_t inp, size_t pktlen, cdk_pkt_seckey_t sk)
{
- size_t p1 = 0, p2 = 0, nread = 0;
- int i = 0, blklen = 0, nskey = 0;
- int rc = 0;
-
- if( !inp || !sk || !sk->pk )
- return CDK_Inv_Value;
-
- if (DEBUG_PKT)
- _cdk_log_debug ("** read secret key\n");
-
- p1 = cdk_stream_tell( inp );
- rc = read_public_key( inp, sk->pk );
- if( rc )
- return rc;
-
- sk->s2k_usage = stream_getc( inp );
- sk->protect.sha1chk = 0;
- if( sk->s2k_usage == 254 || sk->s2k_usage == 255 ) {
- sk->protect.sha1chk = (sk->s2k_usage == 254);
- sk->protect.algo = stream_getc( inp );
- sk->protect.s2k = cdk_calloc( 1, sizeof *sk->protect.s2k );
- if( !sk->protect.s2k )
- return CDK_Out_Of_Core;
- rc = read_s2k( inp, sk->protect.s2k );
- if( rc )
- return rc;
- blklen = cdk_cipher_get_algo_blklen( sk->protect.algo );
- if( !blklen )
- return CDK_Inv_Packet;
- sk->protect.ivlen = blklen;
- rc = stream_read( inp, sk->protect.iv, sk->protect.ivlen, &nread );
- if( !rc && nread != sk->protect.ivlen )
- return CDK_Inv_Packet;
+ size_t p1, p2, nread;
+ int i, nskey;
+ int rc;
+
+ if (!inp || !sk || !sk->pk)
+ return CDK_Inv_Value;
+
+ if (DEBUG_PKT)
+ _cdk_log_debug ("** read secret key\n");
+
+ p1 = cdk_stream_tell (inp);
+ rc = read_public_key (inp, sk->pk);
+ if (rc)
+ return rc;
+
+ sk->s2k_usage = cdk_stream_getc (inp);
+ sk->protect.sha1chk = 0;
+ if (sk->s2k_usage == 254 || sk->s2k_usage == 255)
+ {
+ sk->protect.sha1chk = (sk->s2k_usage == 254);
+ sk->protect.algo = cdk_stream_getc (inp);
+ sk->protect.s2k = cdk_calloc (1, sizeof *sk->protect.s2k);
+ if (!sk->protect.s2k)
+ return CDK_Out_Of_Core;
+ rc = read_s2k (inp, sk->protect.s2k);
+ if (rc)
+ return rc;
+ sk->protect.ivlen = gcry_cipher_get_algo_blklen (sk->protect.algo);
+ if (!sk->protect.ivlen)
+ return CDK_Inv_Packet;
+ rc = stream_read (inp, sk->protect.iv, sk->protect.ivlen, &nread);
+ if (rc)
+ return rc;
+ if (nread != sk->protect.ivlen)
+ return CDK_Inv_Packet;
}
- else
- sk->protect.algo = sk->s2k_usage;
- if( sk->protect.algo == CDK_CIPHER_NONE ) {
- sk->csum = 0;
- nskey = cdk_pk_get_nskey( sk->pk->pubkey_algo );
- if( !nskey )
- return CDK_Inv_Algo;
- for( i = 0; i < nskey; i++ ) {
- rc = read_mpi( inp, &sk->mpi[i], 1 );
- if( rc )
- break;
- }
- if( !rc ) {
- sk->csum = read_16( inp );
- sk->is_protected = 0;
+ else
+ sk->protect.algo = sk->s2k_usage;
+ if (sk->protect.algo == GCRY_CIPHER_NONE)
+ {
+ sk->csum = 0;
+ nskey = cdk_pk_get_nskey (sk->pk->pubkey_algo);
+ if (!nskey)
+ return CDK_Inv_Algo;
+ for (i = 0; i < nskey; i++)
+ {
+ rc = read_mpi (inp, &sk->mpi[i], 1);
+ if (rc)
+ return rc;
}
+ sk->csum = read_16 (inp);
+ sk->is_protected = 0;
}
- else if( sk->pk->version < 4 ) {
- /* mpi size isn't encrypted! */
- nskey = cdk_pk_get_nskey( sk->pk->pubkey_algo );
- if( !nskey )
- return CDK_Inv_Algo;
- for( i = 0; i < nskey; i++ ) {
- rc = read_mpi( inp, &sk->mpi[i], 1 );
- if( rc )
- break;
+ else if (sk->pk->version < 4)
+ {
+ /* The length of each multiprecision integer is stored in plaintext. */
+ nskey = cdk_pk_get_nskey (sk->pk->pubkey_algo);
+ if (!nskey)
+ return CDK_Inv_Algo;
+ for (i = 0; i < nskey; i++)
+ {
+ rc = read_mpi (inp, &sk->mpi[i], 1);
+ if (rc)
+ return rc;
}
- if( !rc ) {
- sk->csum = read_16( inp );
- sk->is_protected = 1;
- }
- }
- else {
- /* we need to read the rest of the packet because we don't
- have any information how long the encrypted mpi's are */
- p2 = cdk_stream_tell( inp );
- p2 -= p1;
- sk->enclen = pktlen - p2;
- if( sk->enclen < 2 )
- return CDK_Inv_Packet; /* at least 16 bits for the checksum! */
- sk->encdata = cdk_calloc( 1, sk->enclen + 1 );
- if( !sk->encdata )
- return CDK_Out_Of_Core;
- rc = stream_read( inp, sk->encdata, sk->enclen, &nread );
- if( rc )
- return CDK_Inv_Packet;
- nskey = cdk_pk_get_nskey( sk->pk->pubkey_algo );
- if( !nskey )
- return CDK_Inv_Algo;
- for( i = 0; i < nskey; i++ )
- sk->mpi[i] = NULL;
- sk->is_protected = 1;
+ sk->csum = read_16 (inp);
+ sk->is_protected = 1;
+ }
+ else
+ {
+ /* We need to read the rest of the packet because we do not
+ have any information how long the encrypted mpi's are */
+ p2 = cdk_stream_tell (inp);
+ p2 -= p1;
+ sk->enclen = pktlen - p2;
+ if (sk->enclen < 2)
+ return CDK_Inv_Packet; /* at least 16 bits for the checksum! */
+ sk->encdata = cdk_calloc (1, sk->enclen + 1);
+ if (!sk->encdata)
+ return CDK_Out_Of_Core;
+ if (stream_read (inp, sk->encdata, sk->enclen, &nread))
+ return CDK_Inv_Packet;
+ nskey = cdk_pk_get_nskey (sk->pk->pubkey_algo);
+ if (!nskey)
+ return CDK_Inv_Algo;
+ /* We mark each MPI entry with NULL to indicate a protected key. */
+ for (i = 0; i < nskey; i++)
+ sk->mpi[i] = NULL;
+ sk->is_protected = 1;
}
- sk->is_primary = 1;
- _cdk_copy_pk_to_sk( sk->pk, sk );
- return rc;
+
+ sk->is_primary = 1;
+ _cdk_copy_pk_to_sk (sk->pk, sk);
+ return 0;
}
-static int
-read_secret_subkey( cdk_stream_t inp, size_t pktlen, cdk_pkt_seckey_t sk )
+static cdk_error_t
+read_secret_subkey (cdk_stream_t inp, size_t pktlen, cdk_pkt_seckey_t sk)
{
- int rc = 0;
-
- if( !inp || !sk || !sk->pk )
- return CDK_Inv_Value;
+ cdk_error_t rc;
- rc = read_secret_key( inp, pktlen, sk );
- sk->is_primary = 0;
- return rc;
+ if (!inp || !sk || !sk->pk)
+ return CDK_Inv_Value;
+
+ rc = read_secret_key (inp, pktlen, sk);
+ sk->is_primary = 0;
+ return rc;
}
-static int
+static cdk_error_t
read_attribute (cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t attr)
{
- size_t nread = 0;
- byte * buf;
- const byte * p;
- int len = 0;
- int rc = 0;
-
- if( !inp || !attr || !pktlen )
- return CDK_Inv_Value;
-
- strcpy( attr->name, "[attribute]" );
- attr->len = strlen( attr->name );
- buf = cdk_calloc( 1, pktlen );
- if( !buf )
- return CDK_Out_Of_Core;
- rc = stream_read( inp, buf, pktlen, &nread );
- if( rc ) {
- cdk_free( buf );
- return CDK_Inv_Packet;
+ size_t nread;
+ byte *buf;
+ const byte *p;
+ size_t len;
+ cdk_error_t rc;
+
+ if (!inp || !attr || !pktlen)
+ return CDK_Inv_Value;
+
+ strcpy (attr->name, "[attribute]");
+ attr->len = strlen (attr->name);
+ buf = cdk_calloc (1, pktlen);
+ if (!buf)
+ return CDK_Out_Of_Core;
+ rc = stream_read (inp, buf, pktlen, &nread);
+ if (rc)
+ {
+ cdk_free (buf);
+ return CDK_Inv_Packet;
}
- p = buf;
- len = *p++;
- if (len == 255) {
- len = _cdk_buftou32( p );
- p += 4;
- pktlen -= 4;
+ p = buf;
+ len = *p++;
+ if (len == 255)
+ {
+ len = _cdk_buftou32 (p);
+ p += 4;
+ pktlen -= 4;
}
- else if (len >= 192) {
- if( pktlen < 2 ) {
- cdk_free( buf );
- return CDK_Inv_Packet;
+ else if (len >= 192)
+ {
+ if (pktlen < 2)
+ {
+ cdk_free (buf);
+ return CDK_Inv_Packet;
}
- len = ((len - 192) << 8) + *p + 192;
- p++;
- pktlen--;
+ len = ((len - 192) << 8) + *p + 192;
+ p++;
+ pktlen--;
}
- if( *p != 1 ) { /* ATTRIBUTE IMAGE */
- cdk_free( buf );
- return CDK_Inv_Packet;
+ if (*p != 1)
+ { /* ATTRIBUTE IMAGE */
+ cdk_free (buf);
+ return CDK_Inv_Packet;
}
- p++;
-
- attr->attrib_img = cdk_calloc( 1, len );
- if( !attr->attrib_img )
- return CDK_Out_Of_Core;
- attr->attrib_len = len;
- memcpy( attr->attrib_img, p, len );
- cdk_free( buf );
- return rc;
+ p++;
+
+ /* There is no maximum for the attribute data length
+ but even so we dissalow images larger than 100K. */
+ if (len > 100000)
+ {
+ cdk_free (buf);
+ 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);
+ return rc;
}
-static int
-read_user_id( cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t user_id )
+static cdk_error_t
+read_user_id (cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t user_id)
{
- size_t nread = 0;
- int rc = 0;
-
- if( !inp || !user_id )
- return CDK_Inv_Value;
- if( !pktlen )
- return CDK_Inv_Packet;
-
- if (DEBUG_PKT)
- _cdk_log_debug ("** read user ID packet: ");
-
- user_id->len = pktlen;
- rc = stream_read( inp, user_id->name, pktlen, &nread );
- if( !rc && nread != pktlen )
- return CDK_Inv_Packet;
- user_id->name[nread] = '\0';
- if (DEBUG_PKT)
- _cdk_log_debug ("%s\n", user_id->name);
+ size_t nread;
+ cdk_error_t rc;
+
+ if (!inp || !user_id)
+ return CDK_Inv_Value;
+ if (!pktlen)
+ return CDK_Inv_Packet;
+
+ if (DEBUG_PKT)
+ _cdk_log_debug ("** read user ID packet\n");
+
+ user_id->len = pktlen;
+ rc = stream_read (inp, user_id->name, pktlen, &nread);
+ if (rc)
return rc;
+ if (nread != pktlen)
+ return CDK_Inv_Packet;
+ user_id->name[nread] = '\0';
+ return rc;
}
-static int
+static cdk_error_t
read_subpkt( cdk_stream_t inp, cdk_subpkt_t * r_ctx, size_t * r_nbytes )
{
- byte c, c1;
- size_t size = 0, nread, n = 0;
- cdk_subpkt_t node;
- int rc = 0;
-
- if( !inp || !r_nbytes )
- return CDK_Inv_Value;
-
- if (DEBUG_PKT)
- _cdk_log_debug ("** read sub packet");
-
- *r_nbytes = 0;
- c = stream_getc( inp );
- n++;
- if( c == 255 ) {
- size = read_32( inp );
- n += 4;
- node = cdk_subpkt_new( size );
- }
- else if( c >= 192 && c < 255 ) {
- c1 = stream_getc( inp );
- n++;
- if( c1 == 0 )
- return 0;
- size = ((c - 192) << 8) + c1 + 192;
- node = cdk_subpkt_new( size );
+ byte c, c1;
+ size_t size, nread, n;
+ cdk_subpkt_t node;
+ cdk_error_t rc;
+
+ if (!inp || !r_nbytes)
+ return CDK_Inv_Value;
+
+ if (DEBUG_PKT)
+ _cdk_log_debug ("** read sub packet");
+
+ n = 0;
+ *r_nbytes = 0;
+ c = cdk_stream_getc (inp);
+ n++;
+ if (c == 255)
+ {
+ size = read_32 (inp);
+ n += 4;
}
- else if( c < 192 ) {
- size = c;
- node = cdk_subpkt_new( size );
+ else if (c >= 192 && c < 255)
+ {
+ c1 = cdk_stream_getc (inp);
+ n++;
+ if (c1 == 0)
+ return 0;
+ size = ((c - 192) << 8) + c1 + 192;
}
- else
- return CDK_Inv_Packet;
-
- if (DEBUG_PKT)
- _cdk_log_debug (" `%d' bytes\n", size);
-
- if( !node )
- return CDK_Out_Of_Core;
- node->size = size;
- node->type = stream_getc( inp );
- n++;
- node->size--;
- rc = stream_read( inp, node->d, node->size, &nread );
- n += nread;
- if( rc )
- return rc;
- *r_nbytes = n;
- if( !*r_ctx )
- *r_ctx = node;
- else
- cdk_subpkt_add( *r_ctx, node );
+ else if (c < 192)
+ size = c;
+ else
+ 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;
+ node->size = size;
+ node->type = cdk_stream_getc (inp);
+ n++;
+ node->size--;
+ rc = stream_read (inp, node->d, node->size, &nread);
+ n += nread;
+ if (rc)
return rc;
+ *r_nbytes = n;
+ if (! *r_ctx)
+ *r_ctx = node;
+ else
+ cdk_subpkt_add (*r_ctx, node);
+ return rc;
}
-static int
-read_onepass_sig( cdk_stream_t inp, size_t pktlen, cdk_pkt_onepass_sig_t sig )
+static cdk_error_t
+read_onepass_sig (cdk_stream_t inp, size_t pktlen, cdk_pkt_onepass_sig_t sig)
{
- if( !inp || !sig )
- return CDK_Inv_Value;
-
- if (DEBUG_PKT)
- _cdk_log_debug ("** read one pass signature packet\n");
-
- if( pktlen < 13 )
- return CDK_Inv_Packet;
- sig->version = stream_getc( inp );
- if( sig->version != 3 )
- return CDK_Inv_Packet_Ver;
- sig->sig_class = stream_getc( inp );
- sig->digest_algo = stream_getc( inp );
- sig->pubkey_algo = stream_getc( inp );
- sig->keyid[0] = read_32( inp );
- sig->keyid[1] = read_32( inp );
- sig->last = stream_getc( inp );
- return 0;
+ if (!inp || !sig)
+ return CDK_Inv_Value;
+
+ if (DEBUG_PKT)
+ _cdk_log_debug ("** read one pass signature packet\n");
+
+ if (pktlen != 13)
+ return CDK_Inv_Packet;
+ sig->version = cdk_stream_getc (inp);
+ if (sig->version != 3)
+ return CDK_Inv_Packet_Ver;
+ sig->sig_class = cdk_stream_getc (inp);
+ sig->digest_algo = cdk_stream_getc (inp);
+ sig->pubkey_algo = cdk_stream_getc (inp);
+ sig->keyid[0] = read_32 (inp);
+ sig->keyid[1] = read_32 (inp);
+ sig->last = cdk_stream_getc (inp);
+ return 0;
}
-static int
-read_signature( cdk_stream_t inp, size_t pktlen, cdk_pkt_signature_t sig )
+static cdk_error_t
+parse_sig_subpackets (cdk_pkt_signature_t sig)
{
- cdk_subpkt_t node = NULL;
- size_t nbytes;
- int i, size, nsig;
- int rc = 0;
-
- if( !inp || !sig )
- return CDK_Inv_Value;
-
- if( DEBUG_PKT )
- _cdk_log_debug( "** read signature packet\n" );
-
- if( pktlen < 10 )
- return CDK_Inv_Packet;
- sig->version = stream_getc( inp );
- if( sig->version < 2 || sig->version > 4 )
- return CDK_Inv_Packet_Ver;
-
- sig->flags.exportable = 1;
- sig->flags.revocable = 1;
-
- if( sig->version < 4 ) {
- if( stream_getc( inp ) != 5 )
- return CDK_Inv_Packet;
- sig->sig_class = stream_getc( inp );
- sig->timestamp = read_32( inp );
- sig->keyid[0] = read_32( inp );
- sig->keyid[1] = read_32( inp );
- sig->pubkey_algo = stream_getc( inp );
- sig->digest_algo = stream_getc( inp );
- sig->digest_start[0] = stream_getc( inp );
- sig->digest_start[1] = stream_getc( inp );
- nsig = cdk_pk_get_nsig( sig->pubkey_algo );
- if( !nsig )
- return CDK_Inv_Algo;
- for( i = 0; i < nsig; i++ ) {
- rc = read_mpi( inp, &sig->mpi[i], 0 );
- if( rc )
- break;
+ cdk_subpkt_t node;
+
+ /* Setup the standard packet entries, so we can use V4
+ signatures similar to V3. */
+ for (node = sig->unhashed; node; node = node->next)
+ {
+ if (node->type == CDK_SIGSUBPKT_ISSUER && node->size >= 8)
+ {
+ sig->keyid[0] = _cdk_buftou32 (node->d );
+ sig->keyid[1] = _cdk_buftou32 (node->d + 4);
+ }
+ else if (node->type == CDK_SIGSUBPKT_EXPORTABLE &&
+ node->d[0] == 0)
+ {
+ /* Sometimes this packet might be placed in the unhashed area */
+ sig->flags.exportable = 0;
}
}
- else {
- sig->sig_class = stream_getc( inp );
- sig->pubkey_algo = stream_getc( inp );
- sig->digest_algo = stream_getc( inp );
- sig->hashed_size = read_16( inp );
- size = sig->hashed_size;
- sig->hashed = NULL;
- while( size > 0 ) {
- rc = read_subpkt( inp, &sig->hashed, &nbytes );
- if( rc )
- break;
- size -= nbytes;
- }
- sig->unhashed_size = read_16( inp );
- size = sig->unhashed_size;
- sig->unhashed = NULL;
- while( size > 0 ) {
- rc = read_subpkt( inp, &sig->unhashed, &nbytes );
- if( rc )
- break;
- size -= nbytes;
+ for (node = sig->hashed; node; node = node->next)
+ {
+ if (node->type == CDK_SIGSUBPKT_SIG_CREATED && node->size >= 4)
+ sig->timestamp = _cdk_buftou32 (node->d);
+ else if (node->type == CDK_SIGSUBPKT_SIG_EXPIRE && node->size >= 4)
+ {
+ sig->expiredate = _cdk_buftou32 (node->d);
+ if (sig->expiredate > 0 &&
+ sig->expiredate < _cdk_timestamp ())
+ sig->flags.expired = 1;
}
-
- /* Setup the standard packet entries, so we can use V4
- signatures similar to V3. */
- for( node = sig->unhashed; node; node = node->next ) {
- if( node->type == CDK_SIGSUBPKT_ISSUER ) {
- sig->keyid[0] = _cdk_buftou32( node->d );
- sig->keyid[1] = _cdk_buftou32( node->d + 4 );
- }
- else if( node->type == CDK_SIGSUBPKT_EXPORTABLE
- && node->d[0] == 0 ) {
- /* this packet might be also placed in the unhashed area */
- sig->flags.exportable = 0;
+ else if (node->type == CDK_SIGSUBPKT_POLICY)
+ sig->flags.policy_url = 1;
+ else if (node->type == CDK_SIGSUBPKT_NOTATION)
+ sig->flags.notation = 1;
+ else if (node->type == CDK_SIGSUBPKT_REVOCABLE && node->d[0] == 0)
+ sig->flags.revocable = 0;
+ else if (node->type == CDK_SIGSUBPKT_EXPORTABLE && node->d[0]== 0)
+ sig->flags.exportable = 0;
+ }
+ 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)
+ {
+ if (node->size < 22)
+ continue;
+ rnode = cdk_calloc (1, sizeof *rnode);
+ if (!rnode)
+ return CDK_Out_Of_Core;
+ rnode->r_class = node->d[0];
+ rnode->algid = node->d[1];
+ memcpy (rnode->fpr, node->d+2, KEY_FPR_LEN);
+ if (!sig->revkeys)
+ sig->revkeys = rnode;
+ else
+ {
+ for (r = sig->revkeys; r->next; r = r->next)
+ ;
+ r->next = rnode;
+ }
}
}
- for( node = sig->hashed; node; node = node->next ) {
- if( node->type == CDK_SIGSUBPKT_SIG_CREATED )
- sig->timestamp = _cdk_buftou32( node->d );
- else if( node->type == CDK_SIGSUBPKT_SIG_EXPIRE ) {
- sig->expiredate = _cdk_buftou32( node->d );
- if( sig->expiredate > 0
- && sig->expiredate < _cdk_timestamp() )
- sig->flags.expired = 1;
- }
- else if( node->type == CDK_SIGSUBPKT_POLICY )
- sig->flags.policy_url = 1;
- else if( node->type == CDK_SIGSUBPKT_NOTATION )
- sig->flags.notation = 1;
- else if( node->type == CDK_SIGSUBPKT_REVOCABLE && node->d[0] == 0 )
- sig->flags.revocable = 0;
- else if( node->type == CDK_SIGSUBPKT_EXPORTABLE
- && node->d[0] == 0 )
- sig->flags.exportable = 0;
+ }
+
+ return 0;
+}
+
+static cdk_error_t
+read_signature (cdk_stream_t inp, size_t pktlen, cdk_pkt_signature_t sig)
+{
+ size_t nbytes;
+ size_t i, size, nsig;
+ cdk_error_t rc;
+
+ if (!inp || !sig)
+ return CDK_Inv_Value;
+
+ if (DEBUG_PKT)
+ _cdk_log_debug( "** read signature packet\n" );
+
+ if (pktlen < 10)
+ return CDK_Inv_Packet;
+ sig->version = cdk_stream_getc (inp);
+ if (sig->version < 2 || sig->version > 4)
+ return CDK_Inv_Packet_Ver;
+
+ sig->flags.exportable = 1;
+ sig->flags.revocable = 1;
+
+ if (sig->version < 4)
+ {
+ if (cdk_stream_getc (inp) != 5)
+ return CDK_Inv_Packet;
+ sig->sig_class = cdk_stream_getc (inp);
+ sig->timestamp = read_32 (inp);
+ sig->keyid[0] = read_32 (inp);
+ sig->keyid[1] = read_32 (inp);
+ sig->pubkey_algo = cdk_stream_getc (inp);
+ sig->digest_algo = cdk_stream_getc (inp);
+ sig->digest_start[0] = cdk_stream_getc (inp);
+ sig->digest_start[1] = cdk_stream_getc (inp);
+ nsig = cdk_pk_get_nsig (sig->pubkey_algo);
+ if (!nsig)
+ return CDK_Inv_Algo;
+ for (i = 0; i < nsig; i++)
+ {
+ rc = read_mpi (inp, &sig->mpi[i], 0);
+ if (rc)
+ return rc;
}
- 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 ) {
- rnode = cdk_calloc( 1, sizeof * rnode );
- if( !rnode )
- return CDK_Out_Of_Core;
- rnode->class = node->d[0];
- rnode->algid = node->d[1];
- memcpy( rnode->fpr, node->d+2, 20 );
- if( !sig->revkeys )
- sig->revkeys = rnode;
- else {
- for( r = sig->revkeys; r->next; r = r->next )
- ;
- r->next = rnode;
- }
- }
- }
+ }
+ else
+ {
+ sig->sig_class = cdk_stream_getc (inp);
+ sig->pubkey_algo = cdk_stream_getc (inp);
+ sig->digest_algo = cdk_stream_getc (inp);
+ sig->hashed_size = read_16 (inp);
+ size = sig->hashed_size;
+ sig->hashed = NULL;
+ while (size > 0)
+ {
+ rc = read_subpkt (inp, &sig->hashed, &nbytes);
+ if (rc)
+ return rc;
+ size -= nbytes;
}
- sig->digest_start[0] = stream_getc( inp );
- sig->digest_start[1] = stream_getc( inp );
- nsig = cdk_pk_get_nsig( sig->pubkey_algo );
- if( !nsig )
- return CDK_Inv_Algo;
- for( i = 0; i < nsig; i++ ) {
- rc = read_mpi( inp, &sig->mpi[i], 0 );
- if( rc )
- break;
+ sig->unhashed_size = read_16 (inp);
+ size = sig->unhashed_size;
+ sig->unhashed = NULL;
+ while (size > 0)
+ {
+ rc = read_subpkt (inp, &sig->unhashed, &nbytes);
+ if (rc)
+ return rc;
+ size -= nbytes;
+ }
+
+ rc = parse_sig_subpackets (sig);
+ if (rc)
+ return rc;
+
+ sig->digest_start[0] = cdk_stream_getc (inp);
+ sig->digest_start[1] = cdk_stream_getc (inp);
+ nsig = cdk_pk_get_nsig (sig->pubkey_algo);
+ if (!nsig)
+ return CDK_Inv_Algo;
+ for (i = 0; i < nsig; i++)
+ {
+ rc = read_mpi (inp, &sig->mpi[i], 0);
+ if (rc)
+ return rc;
}
}
- return rc;
+
+ return 0;
}
-static int
-read_literal( cdk_stream_t inp, size_t pktlen, cdk_pkt_literal_t * ret_pt,
- int partial )
+static cdk_error_t
+read_literal (cdk_stream_t inp, size_t pktlen, cdk_pkt_literal_t *ret_pt,
+ int partial)
{
- cdk_pkt_literal_t pt = *ret_pt;
- size_t nread = 0;
- int rc = 0;
-
- if( !inp || !pt )
- return CDK_Inv_Value;
-
- if( DEBUG_PKT )
- _cdk_log_debug( "** read literal packet\n" );
-
- pt->mode = stream_getc( inp );
- if( pt->mode != 0x62 && pt->mode != 0x74 )
- return CDK_Inv_Packet;
- pt->namelen = stream_getc( inp );
- if( pt->namelen ) {
- *ret_pt = pt = cdk_realloc( pt, sizeof * pt + pt->namelen + 1 );
- if( !pt )
- return CDK_Out_Of_Core;
- rc = stream_read( inp, pt->name, pt->namelen, &nread );
- if( !rc && nread != pt->namelen )
- return CDK_Inv_Packet;
- pt->name[pt->namelen] = '\0';
+ cdk_pkt_literal_t pt = *ret_pt;
+ size_t nread ;
+ cdk_error_t rc;
+
+ if (!inp || !pt)
+ return CDK_Inv_Value;
+
+ if (DEBUG_PKT)
+ _cdk_log_debug ("** read literal packet\n");
+
+ pt->mode = cdk_stream_getc (inp);
+ if (pt->mode != 0x62 && pt->mode != 0x74)
+ return CDK_Inv_Packet;
+ if (cdk_stream_eof (inp))
+ return CDK_Inv_Packet;
+
+ pt->namelen = cdk_stream_getc (inp);
+ if (pt->namelen)
+ {
+ *ret_pt = pt = cdk_realloc (pt, sizeof * pt + pt->namelen + 1);
+ if (!pt)
+ return CDK_Out_Of_Core;
+ rc = stream_read (inp, pt->name, pt->namelen, &nread);
+ if (rc)
+ return rc;
+ if (nread != pt->namelen)
+ return CDK_Inv_Packet;
+ pt->name[pt->namelen] = '\0';
}
- pt->timestamp = read_32( inp );
- pktlen = pktlen - 6 - pt->namelen;
- if( partial )
- _cdk_stream_set_blockmode( inp, pktlen );
- pt->buf = inp;
- pt->len = pktlen;
- return rc;
+ pt->timestamp = read_32 (inp);
+ pktlen = pktlen - 6 - pt->namelen;
+ if (partial)
+ _cdk_stream_set_blockmode (inp, pktlen);
+ pt->buf = inp;
+ pt->len = pktlen;
+ return 0;
}
+/* Read an old packet CTB and return the length of the body. */
static void
-read_old_length( cdk_stream_t inp, int ctb, size_t *r_len, size_t *r_size )
+read_old_length (cdk_stream_t inp, int ctb, size_t *r_len, size_t *r_size)
{
- int llen = ctb & 0x03;
-
- if( llen == 0 ) {
- *r_len = stream_getc( inp );
- (*r_size)++;
+ int llen = ctb & 0x03;
+
+ if (llen == 0)
+ {
+ *r_len = cdk_stream_getc (inp);
+ (*r_size)++;
}
- else if( llen == 1 ) {
- *r_len = read_16( inp );
- (*r_size) += 2;
+ else if (llen == 1)
+ {
+ *r_len = read_16 (inp);
+ (*r_size) += 2;
}
- else if( llen == 2 ) {
- *r_len = read_32( inp );
- (*r_size) += 4;
+ else if (llen == 2)
+ {
+ *r_len = read_32 (inp);
+ (*r_size) += 4;
}
- else {
- *r_len = 0;
- *r_size = 0;
+ else
+ {
+ *r_len = 0;
+ *r_size = 0;
}
}
+/* Read a new CTB and decode the body length. */
static void
-read_new_length( cdk_stream_t inp,
- size_t *r_len, size_t *r_size, size_t *r_partial )
+read_new_length (cdk_stream_t inp,
+ size_t *r_len, size_t *r_size, size_t *r_partial)
{
- int c, c1;
-
- c = stream_getc( inp );
- (*r_size)++;
- if( c < 192 )
- *r_len = c;
- else if( c >= 192 && c <= 223 ) {
- c1 = stream_getc( inp );
- (*r_size)++;
- *r_len = ((c - 192) << 8) + c1 + 192;
+ int c, c1;
+
+ c = cdk_stream_getc (inp);
+ (*r_size)++;
+ if (c < 192)
+ *r_len = c;
+ else if (c >= 192 && c <= 223)
+ {
+ c1 = cdk_stream_getc (inp);
+ (*r_size)++;
+ *r_len = ((c - 192) << 8) + c1 + 192;
}
- else if( c == 255 ) {
- *r_len = read_32( inp );
- (*r_size) += 4;
+ else if (c == 255)
+ {
+ *r_len = read_32( inp );
+ (*r_size) += 4;
}
- else {
- *r_len = 1 << (c & 0x1f);
- *r_partial = 1;
+ else
+ {
+ *r_len = 1 << (c & 0x1f);
+ *r_partial = 1;
}
}
-/* we use a buffer to make it faster to skip larger unknown packets. */
+/* Skip an unwanted packet. Use a large buffer to speed up the read process. */
static void
-skip_packet( cdk_stream_t inp, size_t pktlen )
+skip_packet (cdk_stream_t inp, size_t pktlen)
{
- byte buf[4096];
- size_t nread;
+ byte buf[BUFSIZE];
+ size_t nread, buflen = DIM (buf);
- while( pktlen > 4095 ) {
- stream_read( inp, buf, sizeof buf-1, &nread );
- pktlen -= nread;
+ while (pktlen > 0)
+ {
+ stream_read (inp, buf, pktlen > buflen? buflen : pktlen, &nread);
+ pktlen -= nread;
}
- stream_read( inp, buf, pktlen, &nread );
- pktlen -= nread;
- assert( pktlen == 0 );
+
+ assert (pktlen == 0);
}
@@ -925,168 +992,179 @@ skip_packet( cdk_stream_t inp, size_t pktlen )
* Parse the next packet on the @inp stream and return its contents in @pkt.
**/
cdk_error_t
-cdk_pkt_read( cdk_stream_t inp, cdk_packet_t pkt )
+cdk_pkt_read (cdk_stream_t inp, cdk_packet_t pkt)
{
- int use_mdc = 0;
- int ctb = 0, is_newctb = 0, is_partial = 0;
- int rc = 0, pkttype = 0;
- size_t pktlen = 0, pktsize = 0;
-
- if( !inp || !pkt )
- return CDK_Inv_Value;
-
- ctb = stream_getc( inp );
- if( cdk_stream_eof( inp ) || ctb == EOF )
- return CDK_EOF;
- else if( !ctb )
- return CDK_Inv_Packet;
-
- pktsize++;
- if( !(ctb & 0x80) ) {
- _cdk_log_info ("no valid openpgp data found. "
- "(ctb=%02X; fpos=%02X)\n",ctb, cdk_stream_tell( inp ) );
- return CDK_Inv_Packet;
- }
- if( ctb & 0x40 ) { /* RFC2440 */
- pkttype = ctb & 0x3f;
- is_newctb = 1;
+ int use_mdc = 0;
+ int ctb, is_newctb;
+ int pkttype;
+ size_t pktlen = 0, pktsize = 0, is_partial = 0;
+ cdk_error_t rc;
+
+ if (!inp || !pkt)
+ return CDK_Inv_Value;
+
+ ctb = cdk_stream_getc (inp);
+ if (cdk_stream_eof (inp) || ctb == EOF)
+ return CDK_EOF;
+ else if (!ctb)
+ return CDK_Inv_Packet;
+
+ pktsize++;
+ if (!(ctb & 0x80))
+ {
+ _cdk_log_info ("no valid openpgp data found. "
+ "(ctb=%02X; fpos=%02X)\n",ctb, cdk_stream_tell (inp));
+ return CDK_Inv_Packet;
+ }
+
+ if (ctb & 0x40)
+ { /* RFC2440 */
+ pkttype = ctb & 0x3f;
+ is_newctb = 1;
}
- else { /* RFC1991 */
- pkttype = ctb & 0x3f;
- pkttype >>= 2;
+ else
+ { /* RFC1991 */
+ pkttype = ctb & 0x3f;
+ pkttype >>= 2;
+ is_newctb = 0;
}
- if( pkttype > 63 ) {
- _cdk_log_info ("unknown packet type (%d)\n", pkttype);
- return CDK_Inv_Packet;
+
+ if (pkttype > 63)
+ {
+ _cdk_log_info ("unknown packet type (%d)\n", pkttype);
+ return CDK_Inv_Packet;
}
- if( is_newctb )
- read_new_length( inp, &pktlen, &pktsize, &is_partial );
- else
- read_old_length( inp, ctb, &pktlen, &pktsize );
-
- pkt->pkttype = pkttype;
- pkt->pktlen = pktlen;
- pkt->pktsize = pktsize + pktlen;
- pkt->old_ctb = is_newctb? 0 : 1;
-
- switch( pkt->pkttype ) {
+
+ if (is_newctb)
+ read_new_length (inp, &pktlen, &pktsize, &is_partial);
+ else
+ read_old_length (inp, ctb, &pktlen, &pktsize);
+
+ pkt->pkttype = pkttype;
+ pkt->pktlen = pktlen;
+ pkt->pktsize = pktsize + pktlen;
+ pkt->old_ctb = is_newctb? 0 : 1;
+
+ rc = 0;
+ switch (pkt->pkttype)
+ {
case CDK_PKT_ATTRIBUTE:
- pkt->pkt.user_id = cdk_calloc (1,
- sizeof *pkt->pkt.user_id + pkt->pktlen);
- 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 */
- break;
-
+ pkt->pkt.user_id = cdk_calloc (1, sizeof *pkt->pkt.user_id
+ + pkt->pktlen);
+ 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 (??) */
+ break;
+
case CDK_PKT_USER_ID:
- pkt->pkt.user_id = cdk_calloc (1,
- sizeof *pkt->pkt.user_id + pkt->pktlen);
- if (!pkt->pkt.user_id)
- return CDK_Out_Of_Core;
- rc = read_user_id (inp, pktlen, pkt->pkt.user_id);
- break;
-
+ pkt->pkt.user_id = cdk_calloc (1, sizeof *pkt->pkt.user_id
+ + pkt->pktlen);
+ if (!pkt->pkt.user_id)
+ return CDK_Out_Of_Core;
+ rc = read_user_id (inp, pktlen, pkt->pkt.user_id);
+ break;
+
case CDK_PKT_PUBLIC_KEY:
- 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);
- break;
-
+ 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);
+ 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);
- break;
-
+ 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);
+ break;
+
case CDK_PKT_SECRET_KEY:
- pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key);
- if (!pkt->pkt.secret_key)
- return CDK_Out_Of_Core;
- pkt->pkt.secret_key->pk =cdk_calloc (1,
- sizeof *pkt->pkt.secret_key->pk);
- if (!pkt->pkt.secret_key->pk)
- return CDK_Out_Of_Core;
- rc = read_secret_key (inp, pktlen, pkt->pkt.secret_key);
- break;
-
+ pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key);
+ if (!pkt->pkt.secret_key)
+ return CDK_Out_Of_Core;
+ pkt->pkt.secret_key->pk =cdk_calloc (1,
+ sizeof *pkt->pkt.secret_key->pk);
+ if (!pkt->pkt.secret_key->pk)
+ return CDK_Out_Of_Core;
+ rc = read_secret_key (inp, pktlen, pkt->pkt.secret_key);
+ break;
+
case CDK_PKT_SECRET_SUBKEY:
- pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key);
- if (!pkt->pkt.secret_key)
- return CDK_Out_Of_Core;
- pkt->pkt.secret_key->pk =
- cdk_calloc (1, sizeof *pkt->pkt.secret_key->pk);
- if (!pkt->pkt.secret_key->pk)
- return CDK_Out_Of_Core;
- rc = read_secret_subkey (inp, pktlen, pkt->pkt.secret_key);
- break;
-
+ pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key);
+ if (!pkt->pkt.secret_key)
+ return CDK_Out_Of_Core;
+ pkt->pkt.secret_key->pk = cdk_calloc (1,
+ sizeof *pkt->pkt.secret_key->pk);
+ if (!pkt->pkt.secret_key->pk)
+ return CDK_Out_Of_Core;
+ rc = read_secret_subkey (inp, pktlen, pkt->pkt.secret_key);
+ break;
+
case CDK_PKT_LITERAL:
- pkt->pkt.literal = cdk_calloc( 1, sizeof *pkt->pkt.literal );
- if (!pkt->pkt.literal)
- return CDK_Out_Of_Core;
- rc = read_literal( inp, pktlen, &pkt->pkt.literal, is_partial);
- break;
-
+ pkt->pkt.literal = cdk_calloc (1, sizeof *pkt->pkt.literal);
+ if (!pkt->pkt.literal)
+ return CDK_Out_Of_Core;
+ rc = read_literal (inp, pktlen, &pkt->pkt.literal, is_partial);
+ break;
+
case CDK_PKT_ONEPASS_SIG:
- pkt->pkt.onepass_sig = cdk_calloc (1, sizeof *pkt->pkt.onepass_sig);
- if (!pkt->pkt.onepass_sig)
- return CDK_Out_Of_Core;
- rc = read_onepass_sig (inp, pktlen, pkt->pkt.onepass_sig);
- break;
-
+ pkt->pkt.onepass_sig = cdk_calloc (1, sizeof *pkt->pkt.onepass_sig);
+ if (!pkt->pkt.onepass_sig)
+ return CDK_Out_Of_Core;
+ rc = read_onepass_sig (inp, pktlen, pkt->pkt.onepass_sig);
+ break;
+
case CDK_PKT_SIGNATURE:
- pkt->pkt.signature = cdk_calloc (1, sizeof *pkt->pkt.signature);
- if (!pkt->pkt.signature)
- return CDK_Out_Of_Core;
- rc = read_signature (inp, pktlen, pkt->pkt.signature);
- break;
-
+ pkt->pkt.signature = cdk_calloc (1, sizeof *pkt->pkt.signature);
+ if (!pkt->pkt.signature)
+ return CDK_Out_Of_Core;
+ rc = read_signature (inp, pktlen, pkt->pkt.signature);
+ break;
+
case CDK_PKT_ENCRYPTED_MDC:
case CDK_PKT_ENCRYPTED:
- pkt->pkt.encrypted = cdk_calloc (1, sizeof *pkt->pkt.encrypted);
- if (!pkt->pkt.encrypted)
- return CDK_Out_Of_Core;
- use_mdc = (pkt->pkttype == CDK_PKT_ENCRYPTED_MDC) ? 1 : 0;
- rc = read_encrypted( inp, pktlen, pkt->pkt.encrypted,
- is_partial, use_mdc );
- break;
-
+ pkt->pkt.encrypted = cdk_calloc (1, sizeof *pkt->pkt.encrypted);
+ if (!pkt->pkt.encrypted)
+ return CDK_Out_Of_Core;
+ use_mdc = (pkt->pkttype == CDK_PKT_ENCRYPTED_MDC) ? 1 : 0;
+ rc = read_encrypted (inp, pktlen, pkt->pkt.encrypted,
+ is_partial, use_mdc);
+ break;
+
case CDK_PKT_SYMKEY_ENC:
- pkt->pkt.symkey_enc = cdk_calloc (1, sizeof *pkt->pkt.symkey_enc);
- if (!pkt->pkt.symkey_enc)
- return CDK_Out_Of_Core;
- rc = read_symkey_enc (inp, pktlen, pkt->pkt.symkey_enc);
- break;
-
+ pkt->pkt.symkey_enc = cdk_calloc (1, sizeof *pkt->pkt.symkey_enc);
+ if (!pkt->pkt.symkey_enc)
+ return CDK_Out_Of_Core;
+ rc = read_symkey_enc (inp, pktlen, pkt->pkt.symkey_enc);
+ break;
+
case CDK_PKT_PUBKEY_ENC:
- pkt->pkt.pubkey_enc = cdk_calloc (1, sizeof *pkt->pkt.pubkey_enc);
- if (!pkt->pkt.pubkey_enc)
- return CDK_Out_Of_Core;
- rc = read_pubkey_enc (inp, pktlen, pkt->pkt.pubkey_enc);
- break;
-
+ pkt->pkt.pubkey_enc = cdk_calloc (1, sizeof *pkt->pkt.pubkey_enc);
+ if (!pkt->pkt.pubkey_enc)
+ return CDK_Out_Of_Core;
+ rc = read_pubkey_enc (inp, pktlen, pkt->pkt.pubkey_enc);
+ break;
+
case CDK_PKT_COMPRESSED:
- pkt->pkt.compressed = cdk_calloc (1, sizeof *pkt->pkt.compressed);
- if (!pkt->pkt.compressed)
- return CDK_Out_Of_Core;
- rc = read_compressed (inp, pktlen, pkt->pkt.compressed);
- break;
-
+ pkt->pkt.compressed = cdk_calloc (1, sizeof *pkt->pkt.compressed);
+ if (!pkt->pkt.compressed)
+ return CDK_Out_Of_Core;
+ rc = read_compressed (inp, pktlen, pkt->pkt.compressed);
+ break;
+
case CDK_PKT_MDC:
- pkt->pkt.mdc = cdk_calloc (1, sizeof *pkt->pkt.mdc);
- if (!pkt->pkt.mdc)
- return CDK_Out_Of_Core;
- rc = read_mdc (inp, pkt->pkt.mdc);
- break;
-
+ pkt->pkt.mdc = cdk_calloc (1, sizeof *pkt->pkt.mdc);
+ if (!pkt->pkt.mdc)
+ return CDK_Out_Of_Core;
+ rc = read_mdc (inp, pkt->pkt.mdc);
+ break;
+
default:
- /* skip all packets we don't understand */
- skip_packet( inp, pktlen );
- break;
+ /* Skip all packets we don't understand */
+ skip_packet (inp, pktlen);
+ break;
}
-
- return rc;
+
+ return rc;
}
diff --git a/libextra/opencdk/seskey.c b/libextra/opencdk/seskey.c
index 3b1e376a0f..6c3a0d241b 100644
--- a/libextra/opencdk/seskey.c
+++ b/libextra/opencdk/seskey.c
@@ -1,7 +1,6 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * seskey.c - Session key routines
- * Copyright (C) 2002, 2003 Timo Schulz
- * Copyright (C) 1998-2002 Free Software Foundation, Inc.
+/* seskey.c - Session key routines
+ * Copyright (C) 2002, 2003, 2007 Timo Schulz
+ * Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
*
* This file is part of OpenCDK.
*
@@ -14,22 +13,17 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <assert.h>
#include <stdio.h>
+#include <gcrypt.h>
#include "opencdk.h"
#include "main.h"
#include "packet.h"
-#include "cipher.h"
/* We encode the MD in this way:
@@ -38,47 +32,51 @@
*
* PAD consists of FF bytes.
*/
-static int
-do_encode_md (byte ** r_frame, size_t * r_flen, const byte * md, int algo,
- size_t len, unsigned nbits, const byte * asn, size_t asnlen)
+static cdk_error_t
+do_encode_md (byte **r_frame, size_t *r_flen, const byte *md, int algo,
+ size_t len, unsigned nbits, const byte *asn, size_t asnlen)
{
- byte * frame = NULL;
- size_t n = 0;
- int i, nframe = (nbits + 7) / 8;
-
- if( !asn || !md || !r_frame || !r_flen )
- return CDK_Inv_Value;
-
- if (len + asnlen + 4 > nframe)
- return CDK_General_Error;
-
- frame = cdk_calloc (1, nframe);
- if (!frame)
- return CDK_Out_Of_Core;
- frame[n++] = 0;
- frame[n++] = 1;
- i = nframe - len - asnlen - 3;
- if (i < 0) {
- cdk_free (frame);
- return CDK_Inv_Value;
+ byte *frame = NULL;
+ size_t n = 0;
+ size_t nframe = (nbits + 7) / 8;
+ size_t i;
+
+ if (!asn || !md || !r_frame || !r_flen)
+ return CDK_Inv_Value;
+
+ if (len + asnlen + 4 > nframe)
+ return CDK_General_Error;
+
+ frame = cdk_calloc (1, nframe);
+ if (!frame)
+ return CDK_Out_Of_Core;
+ frame[n++] = 0;
+ frame[n++] = 1;
+ i = nframe - len - asnlen - 3;
+ if (i < 0)
+ {
+ cdk_free (frame);
+ return CDK_Inv_Value;
}
- memset (frame + n, 0xff, i);
- n += i;
- frame[n++] = 0;
- memcpy (frame + n, asn, asnlen);
- n += asnlen;
- memcpy (frame + n, md, len);
- n += len;
- if( n != nframe ) {
- cdk_free( frame );
- return CDK_Inv_Value;
+ memset (frame + n, 0xFF, i);
+ n += i;
+ frame[n++] = 0;
+ memcpy (frame + n, asn, asnlen);
+ n += asnlen;
+ memcpy (frame + n, md, len);
+ n += len;
+ if (n != nframe)
+ {
+ cdk_free (frame);
+ return CDK_Inv_Value;
}
- *r_frame = frame;
- *r_flen = n;
- return 0;
+ *r_frame = frame;
+ *r_flen = n;
+ return 0;
}
+
/* RFC2437 format:
*
* 0 2 RND(n bytes) 0 [A DEK(k bytes) CSUM(2 bytes)]
@@ -89,474 +87,505 @@ do_encode_md (byte ** r_frame, size_t * r_flen, const byte * md, int algo,
* CKSUM - algebraic checksum of the DEK.
*/
cdk_error_t
-cdk_dek_encode_pkcs1( cdk_dek_t dek, int nbits, cdk_sesskey_t * r_esk )
+cdk_dek_encode_pkcs1 (cdk_dek_t dek, size_t nbits, gcry_mpi_t *r_enc)
{
- gcry_mpi_t a = NULL;
- byte * p, * frame;
- size_t n = 0;
- u16 chksum = 0;
- int i = 0, nframe = 0;
- int rc = 0;
-
- if( !r_esk || !dek )
- return CDK_Inv_Value;
-
- for (i = 0; i < dek->keylen; i++)
- chksum += dek->key[i];
- nframe = (nbits + 7) / 8;
- frame = cdk_salloc (nframe + 1, 1);
- if (!frame)
- return CDK_Out_Of_Core;
- n = 0;
- frame[n++] = 0x00;
- frame[n++] = 0x02;
- i = nframe - 6 - dek->keylen;
- p = gcry_random_bytes (i, GCRY_STRONG_RANDOM);
- /* replace zero bytes by new values */
- for (;;) {
- int j, k;
- byte * pp;
-
- /* count the zero bytes */
- for (j = k = 0; j < i; j++) {
- if (!p[j])
- k++;
+ gcry_mpi_t a = NULL;
+ gcry_error_t err;
+ byte *p, *frame;
+ size_t n = 0;
+ size_t nframe = 0;
+ u16 chksum = 0;
+ size_t i;
+
+ if (!r_enc || !dek)
+ return CDK_Inv_Value;
+
+ *r_enc = NULL;
+ for (i = 0; i < dek->keylen; i++)
+ chksum += dek->key[i];
+ nframe = (nbits + 7) / 8;
+ frame = cdk_salloc (nframe + 1, 1);
+ if (!frame)
+ return CDK_Out_Of_Core;
+ n = 0;
+ frame[n++] = 0x00;
+ frame[n++] = 0x02;
+ i = nframe - 6 - dek->keylen;
+ p = gcry_random_bytes (i, GCRY_STRONG_RANDOM);
+ /* Replace zero bytes by new values */
+ for (;;)
+ {
+ size_t j, k;
+ byte *pp;
+
+ /* count the zero bytes */
+ for (j = k = 0; j < i; j++)
+ {
+ if (!p[j])
+ k++;
}
- if (!k)
- break; /* okay: no zero bytes */
- k += k / 128; /* better get some more */
- pp = gcry_random_bytes (k, GCRY_STRONG_RANDOM);
- for (j = 0; j < i && k; j++) {
- if (!p[j])
- p[j] = pp[--k];
+ if (!k)
+ break; /* No zeroes remain. */
+ k += k / 128; /* better get some more */
+ pp = gcry_random_bytes (k, GCRY_STRONG_RANDOM);
+ for (j = 0; j < i && k; j++)
+ {
+ if (!p[j])
+ p[j] = pp[--k];
}
- cdk_free (pp);
- }
- memcpy (frame + n, p, i);
- cdk_free (p);
- n += i;
- frame[n++] = 0;
- frame[n++] = dek->algo;
- memcpy (frame + n, dek->key, dek->keylen);
- n += dek->keylen;
- frame[n++] = chksum >> 8;
- frame[n++] = chksum;
- rc = gcry_mpi_scan (&a, GCRYMPI_FMT_USG, frame, nframe, &nframe);
- if (rc)
- rc = CDK_Gcry_Error;
- cdk_free (frame);
- if( !rc ) {
- rc = cdk_sesskey_new( r_esk );
- if( rc ) {
- gcry_mpi_release( a );
- return rc;
- }
- (*r_esk)->a = a;
+ cdk_free (pp);
}
- return rc;
+ memcpy (frame + n, p, i);
+ cdk_free (p);
+ n += i;
+ frame[n++] = 0;
+ frame[n++] = dek->algo;
+ memcpy (frame + n, dek->key, dek->keylen);
+ n += dek->keylen;
+ frame[n++] = chksum >> 8;
+ frame[n++] = chksum;
+ err = gcry_mpi_scan (&a, GCRYMPI_FMT_USG, frame, nframe, &nframe);
+ cdk_free (frame);
+ if (err)
+ return map_gcry_error (err);
+ else
+ *r_enc = a;
+ return 0;
}
cdk_error_t
-cdk_dek_decode_pkcs1( cdk_dek_t *ret_dek, cdk_sesskey_t esk )
+cdk_dek_decode_pkcs1 (cdk_dek_t *ret_dek, gcry_mpi_t esk)
{
- cdk_dek_t dek;
- byte frame[4096];
- size_t nframe, n;
- u16 csum = 0, csum2 = 0;
- int rc;
-
- if( !ret_dek || !esk )
- return CDK_Inv_Value;
-
- nframe = sizeof frame-1;
- rc = gcry_mpi_print (GCRYMPI_FMT_USG, frame, nframe, &nframe, esk->a);
- if( rc )
- return CDK_Gcry_Error;
- dek = cdk_salloc( sizeof *dek, 1 );
- if( !dek )
- return CDK_Out_Of_Core;
-
- /* Now get the DEK (data encryption key) from the frame
- *
- * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes)
- *
- * (gcry_mpi_print already removed the leading zero).
- *
- * RND are non-zero randow bytes.
- * A is the cipher algorithm
- * DEK is the encryption key (session key) with length k
- * CSUM
- */
- n = 0;
- if( frame[n] != 2 ) {
- cdk_free (dek);
- return CDK_Inv_Mode;
+ cdk_dek_t dek;
+ byte frame[MAX_MPI_BYTES+2+1];
+ size_t nframe, n;
+ u16 csum = 0, csum2 = 0;
+ gcry_error_t err;
+
+ if (!ret_dek || !esk)
+ return CDK_Inv_Value;
+
+ nframe = DIM (frame)-1;
+ err = gcry_mpi_print (GCRYMPI_FMT_USG, frame, nframe, &nframe, esk);
+ if (err)
+ return map_gcry_error (err);
+ dek = cdk_salloc (sizeof *dek, 1);
+ if (!dek)
+ return CDK_Out_Of_Core;
+
+ /* Now get the DEK (data encryption key) from the frame
+ *
+ * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes)
+ *
+ * (gcry_mpi_print already removed the leading zero).
+ *
+ * RND are non-zero randow bytes.
+ * A is the cipher algorithm
+ * DEK is the encryption key (session key) with length k
+ * CSUM
+ */
+ n = 0;
+ if (frame[n] != 2)
+ {
+ cdk_free (dek);
+ return CDK_Inv_Mode;
}
- for( n++; n < nframe && frame[n]; n++ )
- ;
- n++;
- dek->keylen = nframe - (n + 1) - 2;
- dek->algo = frame[n++];
- if( dek->keylen != cdk_cipher_get_algo_keylen( dek->algo ) ) {
- cdk_free( dek );
- return CDK_Inv_Algo;
+ for (n++; n < nframe && frame[n]; n++)
+ ;
+ n++;
+ dek->keylen = nframe - (n + 1) - 2;
+ dek->algo = frame[n++];
+ if (dek->keylen != gcry_cipher_get_algo_keylen (dek->algo))
+ {
+ cdk_free (dek);
+ return CDK_Inv_Algo;
}
- csum = frame[nframe-2] << 8;
- csum |= frame[nframe-1];
- memcpy( dek->key, frame + n, dek->keylen );
- for( n = 0; n < dek->keylen; n++ )
- csum2 += dek->key[n];
- if( csum != csum2 ) {
- cdk_free( dek );
- return CDK_Chksum_Error;
+ csum = frame[nframe-2] << 8;
+ csum |= frame[nframe-1];
+ memcpy (dek->key, frame + n, dek->keylen);
+ for (n = 0; n < dek->keylen; n++)
+ csum2 += dek->key[n];
+ if (csum != csum2)
+ {
+ cdk_free (dek);
+ return CDK_Chksum_Error;
}
- *ret_dek = dek;
- return 0;
+ *ret_dek = dek;
+ return 0;
}
/* Do some tests before it calls do_encode_md that depends on the
public key algorithm that is used. */
cdk_error_t
-_cdk_digest_encode_pkcs1( byte ** r_md, size_t * r_mdlen, int pk_algo,
- const byte * md, int digest_algo, unsigned nbits )
+_cdk_digest_encode_pkcs1 (byte **r_md, size_t *r_mdlen, int pk_algo,
+ const byte *md, int digest_algo, unsigned nbits)
{
- int rc = 0;
- int dlen = cdk_md_get_algo_dlen( digest_algo );
- byte * p;
-
- if( !md || !r_md || !r_mdlen )
- return CDK_Inv_Value;
-
- if( !dlen )
- return CDK_Inv_Algo;
- if( is_DSA( pk_algo ) ) {
- *r_md = p = cdk_malloc( dlen + 1 );
- if( !p )
- return CDK_Out_Of_Core;
- *r_mdlen = dlen;
- memcpy( p, md, dlen );
- return 0;
+ gcry_error_t err;
+ int dlen;
+
+ if (!md || !r_md || !r_mdlen)
+ return CDK_Inv_Value;
+
+ dlen = gcry_md_get_algo_dlen (digest_algo);
+ if (!dlen)
+ return CDK_Inv_Algo;
+ if (is_DSA (pk_algo))
+ {
+ *r_md = cdk_malloc (dlen + 1);
+ if (!*r_md)
+ return CDK_Out_Of_Core;
+ *r_mdlen = dlen;
+ memcpy (*r_md, md, dlen);
+ return 0;
}
- else {
- byte * asn = NULL;
- size_t asnlen = 0;
-
- rc = cdk_md_get_asnoid( digest_algo, NULL, &asnlen );
- if( !rc ) {
- asn = cdk_malloc( asnlen + 1 );
- if( !asn )
- return CDK_Out_Of_Core;
- }
- if( !rc )
- rc = cdk_md_get_asnoid( digest_algo, asn, &asnlen );
- if( !rc )
- rc = do_encode_md( r_md, r_mdlen, md, digest_algo, dlen,
- nbits, asn, asnlen );
- cdk_free( asn );
- return rc;
+ else
+ {
+ byte *asn;
+ size_t asnlen;
+ cdk_error_t rc;
+
+ err = gcry_md_get_asnoid (digest_algo, NULL, &asnlen);
+ if (err)
+ return map_gcry_error (err);
+ asn = cdk_malloc (asnlen + 1);
+ if (!asn)
+ return CDK_Out_Of_Core;
+ err = gcry_md_get_asnoid (digest_algo, asn, &asnlen);
+ if (err)
+ {
+ cdk_free (asn);
+ return map_gcry_error (err);
+ }
+ rc = do_encode_md (r_md, r_mdlen, md, digest_algo, dlen,
+ nbits, asn, asnlen);
+ cdk_free (asn);
+ return rc;
}
- return 0;
+ return 0;
}
-static char *
+static char*
passphrase_prompt (cdk_pkt_seckey_t sk)
{
- u32 keyid = cdk_pk_get_keyid (sk->pk, NULL);
- int bits = cdk_pk_get_nbits (sk->pk), pk_algo = sk->pubkey_algo;
- const char * algo = "???", * fmt;
- char * p;
+ u32 keyid = cdk_pk_get_keyid (sk->pk, NULL);
+ int bits = cdk_pk_get_nbits (sk->pk), pk_algo = sk->pubkey_algo;
+ const char *algo = "???", *fmt;
+ char *p;
- if (is_RSA (pk_algo))
- algo = "RSA";
- else if (is_ELG (pk_algo))
- algo = "ELG";
- else if (is_DSA (pk_algo))
- algo = "DSA";
-
- fmt = "%d-bit %s key, ID %08lX\nEnter Passphrase: ";
- p = cdk_calloc( 1, 64 + strlen( fmt ) + 1 );
- if( !p )
- return NULL;
- sprintf( p, fmt, bits, algo, keyid );
- return p;
+ if (is_RSA (pk_algo))
+ algo = "RSA";
+ else if (is_ELG (pk_algo))
+ algo = "ELG";
+ else if (is_DSA (pk_algo))
+ algo = "DSA";
+
+ fmt = "%d-bit %s key, ID %08lX\nEnter Passphrase: ";
+ p = cdk_calloc (1, 64 + strlen (fmt) + strlen (algo) + 1);
+ if (!p)
+ return NULL;
+ sprintf (p, fmt, bits, algo, keyid);
+ return p;
}
+/* Try to unprotect the secret key, if needed, automatically.
+ The passphrase callback is used to get the passphrase directly
+ from the user. */
cdk_error_t
-_cdk_sk_unprotect_auto( cdk_ctx_t hd, cdk_pkt_seckey_t sk )
+_cdk_sk_unprotect_auto (cdk_ctx_t hd, cdk_pkt_seckey_t sk)
{
- char * pw = NULL, * p = NULL;
- int rc = 0;
+ char *pw, *p;
+ cdk_error_t rc;
- if( sk->is_protected ) {
- p = passphrase_prompt( sk );
- pw = _cdk_passphrase_get( hd, p );
- if( pw )
- rc = cdk_sk_unprotect( sk, pw );
- _cdk_passphrase_free( pw, pw? strlen( pw ) : 0 );
- cdk_free( p );
+ rc = 0;
+ if (sk->is_protected)
+ {
+ p = passphrase_prompt (sk);
+ pw = _cdk_passphrase_get (hd, p);
+ if (pw)
+ rc = cdk_sk_unprotect (sk, pw);
+ if (pw)
+ {
+ wipemem (pw, strlen (pw));
+ cdk_free (pw);
+ }
+ cdk_free (p);
}
- return rc;
+ return rc;
}
+/* Try to extract the DEK from the public key encrypted packet. */
cdk_error_t
-cdk_dek_extract( cdk_dek_t * ret_dek, cdk_ctx_t hd,
- cdk_pkt_pubkey_enc_t enc, cdk_pkt_seckey_t sk )
+cdk_dek_extract (cdk_dek_t *ret_dek, cdk_ctx_t hd,
+ cdk_pkt_pubkey_enc_t enc, cdk_pkt_seckey_t sk)
{
- cdk_dek_t dek = NULL;
- cdk_sesskey_t skey = NULL;
- int rc = 0;
+ cdk_dek_t dek = NULL;
+ gcry_mpi_t skey =NULL;
+ cdk_error_t rc;
- if( !enc || !sk || !ret_dek )
- return CDK_Inv_Value;
+ if (!enc || !sk || !ret_dek)
+ return CDK_Inv_Value;
- if( sk->is_protected )
- rc = _cdk_sk_unprotect_auto( hd, sk );
- if( !rc )
- rc = cdk_pk_decrypt( sk, enc, &skey );
- if( !rc )
- rc = cdk_dek_decode_pkcs1( &dek, skey );
- cdk_sesskey_free( skey );
- if( rc ) {
- cdk_dek_free( dek );
- dek = NULL;
- }
- *ret_dek = dek;
+ if (sk->is_protected)
+ {
+ rc = _cdk_sk_unprotect_auto (hd, sk);
+ if (rc)
+ return rc;
+ }
+
+ rc = cdk_pk_decrypt (sk, enc, &skey);
+ if (rc)
return rc;
-}
-
-
-cdk_error_t
-cdk_sesskey_new( cdk_sesskey_t * r_sk )
-{
- cdk_sesskey_t sk;
-
- if( !r_sk )
- return CDK_Inv_Value;
- sk = cdk_calloc( 1, sizeof **r_sk );
- if( !sk )
- return CDK_Out_Of_Core;
- *r_sk = sk;
- return 0;
-}
-
-
-void
-cdk_sesskey_free( cdk_sesskey_t sk )
-{
- if( sk ) {
- gcry_mpi_release( sk->a );
- cdk_free( sk );
+
+ rc = cdk_dek_decode_pkcs1 (&dek, skey);
+ gcry_mpi_release (skey);
+ if (rc)
+ {
+ cdk_dek_free (dek);
+ dek = NULL;
}
+ *ret_dek = dek;
+ return rc;
}
cdk_error_t
-cdk_dek_new( cdk_dek_t * r_dek )
+cdk_dek_new (cdk_dek_t *r_dek)
{
- cdk_dek_t dek;
-
- if( !r_dek )
- return CDK_Inv_Value;
- *r_dek = NULL;
- dek = cdk_salloc( sizeof *dek, 1 );
- if( !dek )
- return CDK_Out_Of_Core;
- *r_dek = dek;
- return 0;
+ cdk_dek_t dek;
+
+ if (!r_dek)
+ return CDK_Inv_Value;
+ *r_dek = NULL;
+ dek = cdk_salloc (sizeof *dek, 1);
+ if (!dek)
+ return CDK_Out_Of_Core;
+ *r_dek = dek;
+ return 0;
}
cdk_error_t
-cdk_dek_set_cipher( cdk_dek_t dek, int algo )
+cdk_dek_set_cipher (cdk_dek_t dek, int algo)
{
- if( !dek )
- return CDK_Inv_Value;
- if( !algo )
- algo = CDK_CIPHER_CAST5;
- if( cdk_cipher_test_algo( algo ) )
- return CDK_Inv_Algo;
- dek->algo = algo;
- dek->keylen = cdk_cipher_get_algo_keylen( dek->algo );
- return 0;
+ if (!dek)
+ return CDK_Inv_Value;
+
+ if (!algo)
+ algo = GCRY_CIPHER_AES128;
+ if (gcry_cipher_test_algo (algo))
+ return CDK_Inv_Algo;
+ dek->algo = algo;
+ dek->keylen = gcry_cipher_get_algo_keylen (dek->algo);
+ return 0;
}
cdk_error_t
-cdk_dek_set_key( cdk_dek_t dek, const byte * key, size_t keylen )
+cdk_dek_set_key (cdk_dek_t dek, const byte *key, size_t keylen)
{
- cdk_cipher_hd_t hd;
- int i;
-
- if( !dek )
- return CDK_Inv_Value;
- if( keylen > 0 && keylen != dek->keylen )
- return CDK_Inv_Mode;
-
- if( !key && !keylen ) {
- hd = cdk_cipher_new( dek->algo, 1 );
- if( !hd )
- return CDK_Inv_Algo;
- gcry_randomize( dek->key, dek->keylen, GCRY_STRONG_RANDOM );
- for( i = 0; i < 8; i++ ) {
- if( !cdk_cipher_setkey( hd, dek->key, dek->keylen ) ) {
- cdk_cipher_close( hd );
- return 0;
- }
- gcry_randomize( dek->key, dek->keylen, GCRY_STRONG_RANDOM );
- }
- return CDK_Weak_Key;
+ gcry_cipher_hd_t hd;
+ size_t i;
+
+ if (!dek)
+ return CDK_Inv_Value;
+
+ if (keylen > 0 && keylen != dek->keylen)
+ return CDK_Inv_Mode;
+
+ if (!key && !keylen)
+ {
+ gcry_error_t err;
+
+ /* Used to generate a random session key. The extra code is used
+ to detect weak keys, if they are possible at all. */
+ err = gcry_cipher_open (&hd, dek->algo, GCRY_CIPHER_MODE_CFB,
+ GCRY_CIPHER_ENABLE_SYNC);
+ if (err)
+ return map_gcry_error (err);
+ gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM);
+ for (i = 0; i < 8; i++)
+ {
+ if (!gcry_cipher_setkey (hd, dek->key, dek->keylen))
+ {
+ gcry_cipher_close (hd);
+ return 0;
+ }
+ gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM);
+ }
+ return CDK_Weak_Key;
}
- memcpy( dek->key, key, dek->keylen );
- return 0;
+
+ memcpy (dek->key, key, dek->keylen);
+ return 0;
}
void
-cdk_dek_set_mdc_flag( cdk_dek_t dek, int val )
+cdk_dek_set_mdc_flag (cdk_dek_t dek, int val)
{
- if( dek )
- dek->use_mdc = val;
+ if (dek)
+ dek->use_mdc = val;
}
void
-cdk_dek_free( cdk_dek_t dek )
+cdk_dek_free (cdk_dek_t dek)
{
- cdk_free( dek );
+ if (!dek)
+ return;
+ wipemem (dek->key, sizeof (dek->key));
+ cdk_free (dek);
}
+/* Hash the passphrase to produce the a DEK.
+ If create is set, a random salt will be generated. */
static int
-hash_passphrase( cdk_dek_t dek, const char * pw, cdk_s2k_t s2k, int create )
+hash_passphrase (cdk_dek_t dek, const char *pw, cdk_s2k_t s2k, int create)
{
- cdk_md_hd_t md;
- int pass, i;
- int used = 0, pwlen = 0;
-
- if (!dek || !pw || !s2k)
- return CDK_Inv_Value;
-
- if (!s2k->hash_algo)
- s2k->hash_algo = CDK_MD_SHA1;
- pwlen = strlen (pw);
-
- dek->keylen = cdk_cipher_get_algo_keylen (dek->algo);
- md = cdk_md_open( s2k->hash_algo, GCRY_MD_FLAG_SECURE );
- if (!md)
- return CDK_Inv_Algo;
-
- for (pass = 0; used < dek->keylen; pass++) {
- if (pass) {
- cdk_md_reset (md);
- for (i = 0; i < pass; i++) /* preset the hash context */
- cdk_md_putc (md, 0);
+ gcry_md_hd_t md;
+ byte zero[1] = {0x00};
+ int pass, i;
+ int used = 0, pwlen = 0;
+ gcry_error_t err;
+
+ if (!dek || !pw || !s2k)
+ return CDK_Inv_Value;
+
+ if (!s2k->hash_algo)
+ s2k->hash_algo = GCRY_MD_SHA1;
+ pwlen = strlen (pw);
+
+ dek->keylen = gcry_cipher_get_algo_keylen (dek->algo);
+ err = gcry_md_open (&md, s2k->hash_algo, 0);
+ if (err)
+ return map_gcry_error (err);
+
+ for (pass = 0; used < dek->keylen; pass++)
+ {
+ if (pass)
+ {
+ gcry_md_reset (md);
+ for (i = 0; i < pass; i++) /* preset the hash context */
+ gcry_md_write (md, zero, 1);
}
- if (s2k->mode == 1 || s2k->mode == 3) {
- int len2 = pwlen + 8;
- u32 count = len2;
- if (create && !pass) {
- gcry_randomize (s2k->salt, 8, 1);
- if (s2k->mode == 3)
- s2k->count = 96; /* 65536 iterations */
+ if (s2k->mode == CDK_S2K_SALTED || s2k->mode == CDK_S2K_ITERSALTED)
+ {
+ int len2 = pwlen + 8;
+ u32 count = len2;
+ if (create && !pass)
+ {
+ gcry_randomize (s2k->salt, 8, GCRY_STRONG_RANDOM);
+ if (s2k->mode == 3)
+ s2k->count = 96; /* 65536 iterations */
}
- if (s2k->mode == 3) {
- count = (16ul + (s2k->count & 15)) << ((s2k->count >> 4) + 6);
- if (count < len2)
- count = len2;
+ if (s2k->mode == 3)
+ {
+ count = (16ul + (s2k->count & 15)) << ((s2k->count >> 4) + 6);
+ if( count < len2 )
+ count = len2;
}
- /* a little bit complicated because we need a ulong for count */
- while (count > len2) { /* maybe iterated+salted */
- cdk_md_write (md, s2k->salt, 8);
- cdk_md_write (md, pw, pwlen);
- count -= len2;
+ /* a little bit complicated because we need a ulong for count */
+ while (count > len2)
+ { /* maybe iterated+salted */
+ gcry_md_write (md, s2k->salt, 8);
+ gcry_md_write (md, pw, pwlen);
+ count -= len2;
}
- if (count < 8)
- cdk_md_write (md, s2k->salt, count);
- else {
- cdk_md_write (md, s2k->salt, 8);
- count -= 8;
- cdk_md_write (md, pw, count);
+ if (count < 8)
+ gcry_md_write (md, s2k->salt, count);
+ else
+ {
+ gcry_md_write (md, s2k->salt, 8);
+ count -= 8;
+ gcry_md_write (md, pw, count);
}
}
- else
- cdk_md_write (md, pw, pwlen);
- cdk_md_final (md);
- i = cdk_md_get_algo_dlen (s2k->hash_algo);
- if (i > dek->keylen - used)
- i = dek->keylen - used;
- memcpy (dek->key + used, cdk_md_read (md, s2k->hash_algo), i);
- used += i;
+ else
+ gcry_md_write (md, pw, pwlen);
+ gcry_md_final (md);
+ i = gcry_md_get_algo_dlen (s2k->hash_algo);
+ if (i > dek->keylen - used)
+ i = dek->keylen - used;
+ memcpy (dek->key + used, gcry_md_read (md, s2k->hash_algo), i);
+ used += i;
}
- cdk_md_close (md);
- return 0;
+ gcry_md_close (md);
+ return 0;
}
+/**
+ * cdk_dek_from_passphrase:
+ * @ret_dek: the new DEK.
+ * @cipher_algo: symmetric key algorithm to use
+ * @s2k: the S2K to use
+ * @rndsalt: 1=create random salt
+ * @pw: the passphrase.
+ *
+ * Transform a passphrase into a DEK object.
+ */
cdk_error_t
-cdk_dek_from_passphrase( cdk_dek_t * ret_dek, int cipher_algo, cdk_s2k_t s2k,
- int mode, const char * pw )
+cdk_dek_from_passphrase (cdk_dek_t *ret_dek, int cipher_algo, cdk_s2k_t s2k,
+ int rndsalt, const char *pw)
{
- cdk_dek_t dek;
- int rc;
-
- if( !ret_dek )
- return CDK_Inv_Value;
- rc = cdk_dek_new( &dek );
- if( !rc )
- rc = cdk_dek_set_cipher( dek, cipher_algo );
- if( rc ) {
- cdk_dek_free( dek );
- return rc;
+ cdk_dek_t dek;
+ cdk_error_t rc;
+
+ if (!ret_dek)
+ return CDK_Inv_Value;
+
+ *ret_dek = NULL;
+ rc = cdk_dek_new (&dek);
+ if (rc)
+ return rc;
+ rc = cdk_dek_set_cipher (dek, cipher_algo);
+ if (rc)
+ {
+ cdk_dek_free (dek);
+ return rc;
}
- if( !*pw && mode == 2 )
- dek->keylen = 0;
- else
- hash_passphrase( dek, pw, s2k, mode == 2 );
- *ret_dek = dek;
- return 0;
+
+ hash_passphrase (dek, pw, s2k, rndsalt);
+
+ *ret_dek = dek;
+ return 0;
}
cdk_error_t
-cdk_s2k_new( cdk_s2k_t * ret_s2k, int mode, int algo, const byte * salt )
+cdk_s2k_new (cdk_s2k_t *ret_s2k, int mode, int algo, const byte *salt)
{
- cdk_s2k_t s2k;
- int rc;
-
- if( !ret_s2k )
- return CDK_Inv_Value;
- if( mode != 0x00 && mode != 0x01 && mode != 0x03 )
- return CDK_Inv_Mode;
-
- rc = cdk_md_test_algo( algo );
- if( rc )
- return rc;
- s2k = cdk_calloc( 1, sizeof *s2k );
- if( !s2k )
- return CDK_Out_Of_Core;
- s2k->mode = mode;
- s2k->hash_algo = algo;
- if( salt )
- memcpy( s2k->salt, salt, 8 );
- *ret_s2k = s2k;
- return 0;
+ cdk_s2k_t s2k;
+
+ if (!ret_s2k)
+ return CDK_Inv_Value;
+
+ if (mode != 0x00 && mode != 0x01 && mode != 0x03)
+ return CDK_Inv_Mode;
+
+ if (gcry_md_test_algo (algo))
+ return CDK_Inv_Algo;
+
+ s2k = cdk_calloc (1, sizeof *s2k);
+ if (!s2k)
+ return CDK_Out_Of_Core;
+ s2k->mode = mode;
+ s2k->hash_algo = algo;
+ if (salt)
+ memcpy (s2k->salt, salt, 8);
+ *ret_s2k = s2k;
+ return 0;
}
void
-cdk_s2k_free( cdk_s2k_t s2k )
+cdk_s2k_free (cdk_s2k_t s2k)
{
- cdk_free( s2k );
+ cdk_free (s2k);
}
-
-
-
-
-
-
-
diff --git a/libextra/opencdk/sig-check.c b/libextra/opencdk/sig-check.c
index f882c77967..219891e1aa 100644
--- a/libextra/opencdk/sig-check.c
+++ b/libextra/opencdk/sig-check.c
@@ -1,6 +1,6 @@
/* sig-check.c - Check signatures
- * Copyright (C) 2001, 2002, 2003, 2004 Timo Schulz
- * Copyright (C) 1998,1999,2000,2001,2002 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002, 2003, 2007 Timo Schulz
+ * Copyright (C) 1998-2002 Free Software Foundation, Inc.
*
* This file is part of OpenCDK.
*
@@ -13,304 +13,329 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <time.h>
+#include <gcrypt.h>
+#include <assert.h>
#include "opencdk.h"
#include "main.h"
#include "packet.h"
-static void
-hash_mpibuf( cdk_pkt_pubkey_t pk, cdk_md_hd_t md )
+/* Hash all multiprecision 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)
{
- cdk_mpi_t a;
- int i, npkey;
-
- npkey = cdk_pk_get_npkey( pk->pubkey_algo );
- for( i = 0; i < npkey; i++ ) {
- a = pk->mpi[i];
- if( pk->version == 4 ) {
- cdk_md_putc( md, a->bits >> 8 );
- cdk_md_putc( md, a->bits );
- }
- cdk_md_write( md, a->data + 2, a->bytes );
+ byte buf[MAX_MPI_BYTES];
+ size_t nbytes;
+ int i, npkey;
+ gcry_error_t err;
+
+ /* We have to differ between two modes for v3 keys. To form the
+ fingerprint, we hash the MPI values without the length prefix.
+ But if we calculate the hash for verifying/signing we use all data. */
+ npkey = cdk_pk_get_npkey (pk->pubkey_algo);
+ for (i = 0; i < npkey; i++)
+ {
+ err = gcry_mpi_print (GCRYMPI_FMT_PGP, buf, MAX_MPI_BYTES,
+ &nbytes, pk->mpi[i]);
+ if (err)
+ return map_gcry_error (err);
+ if (!usefpr || pk->version == 4)
+ gcry_md_write (md, buf, nbytes);
+ else /* without the prefix. */
+ gcry_md_write (md, buf + 2, nbytes - 2);
}
+ return 0;
}
-void
-_cdk_hash_pubkey( cdk_pkt_pubkey_t pk, cdk_md_hd_t md, int usefpr )
+/* Hash an entire public key PK with the given message digest context
+ 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)
{
- byte buf[4];
- u16 n;
- int i, npkey;
-
- if( !pk || !md )
- return;
-
- npkey = cdk_pk_get_npkey( pk->pubkey_algo );
- if( usefpr && pk->version < 4 && is_RSA( pk->pubkey_algo ) ) {
- hash_mpibuf( pk, md );
- return;
- }
- n = pk->version < 4 ? 8 : 6;
- for( i = 0; i < npkey; i++ ) {
- n += pk->mpi[i]->bytes;
- n += 2;
- }
+ byte buf[12];
+ u16 n;
+ int i, npkey;
- cdk_md_putc( md, 0x99 );
- cdk_md_putc( md, n >> 8 );
- cdk_md_putc( md, n );
- cdk_md_putc( md, pk->version );
+ if (!pk || !md)
+ return CDK_Inv_Value;
- buf[0] = pk->timestamp >> 24;
- buf[1] = pk->timestamp >> 16;
- buf[2] = pk->timestamp >> 8;
- buf[3] = pk->timestamp;
- cdk_md_write( md, buf, 4 );
-
- if( pk->version < 4 ) {
- u16 a = 0;
- if( pk->expiredate )
- a = (u16)((pk->expiredate - pk->timestamp) / 86400L);
- cdk_md_putc( md, a >> 8 );
- cdk_md_putc( md, a );
+ if (usefpr && pk->version < 4 && is_RSA (pk->pubkey_algo))
+ return hash_mpibuf (pk, md, 1);
+
+ n = pk->version < 4? 8 : 6; /* v4: without the expire 'date' */
+ npkey = cdk_pk_get_npkey (pk->pubkey_algo);
+ for (i = 0; i < npkey; i++)
+ n = n + (gcry_mpi_get_nbits (pk->mpi[i])+7)/8 + 2;
+
+ i = 0;
+ buf[i++] = 0x99;
+ buf[i++] = n >> 8;
+ buf[i++] = n >> 0;
+ buf[i++] = pk->version;
+ buf[i++] = pk->timestamp >> 24;
+ buf[i++] = pk->timestamp >> 16;
+ buf[i++] = pk->timestamp >> 8;
+ buf[i++] = pk->timestamp >> 0;
+
+ if (pk->version < 4)
+ {
+ u16 a = 0;
+
+ if (pk->expiredate)
+ a = (u16)((pk->expiredate - pk->timestamp) / 86400L);
+ buf[i++] = a >> 8;
+ buf[i++] = a;
}
- cdk_md_putc( md, pk->pubkey_algo );
- hash_mpibuf( pk, md );
+ buf[i++] = pk->pubkey_algo;
+ gcry_md_write (md, buf, i);
+ return hash_mpibuf (pk, md, 0);
}
void
-_cdk_hash_userid( cdk_pkt_userid_t uid, int is_v4, cdk_md_hd_t md )
+_cdk_hash_userid (cdk_pkt_userid_t uid, int is_v4, gcry_md_hd_t md)
{
- const byte * data;
- byte buf[5];
- u32 dlen;
-
- if( !uid || !md )
- return;
+ const byte *data;
+ byte buf[5];
+ u32 dlen;
+
+ if (!uid || !md)
+ return;
- if( is_v4 ) {
- if( uid->attrib_img ) {
- buf[0] = 0xD1;
- buf[1] = uid->attrib_len >> 24;
- buf[2] = uid->attrib_len >> 16;
- buf[3] = uid->attrib_len >> 8;
- buf[4] = uid->attrib_len;
- }
- else {
- buf[0] = 0xB4;
- buf[1] = uid->len >> 24;
- buf[2] = uid->len >> 16;
- buf[3] = uid->len >> 8;
- buf[4] = uid->len;
- }
- cdk_md_write( md, buf, 5 );
+ if (!is_v4)
+ {
+ gcry_md_write (md, (byte*)uid->name, uid->len);
+ return;
}
- data = uid->attrib_img ? uid->attrib_img : (byte *) uid->name;
- dlen = uid->attrib_img ? uid->attrib_len : uid->len;
- cdk_md_write( md, data, dlen );
+
+ dlen = uid->attrib_img? uid->attrib_len : uid->len;
+ data = uid->attrib_img? uid->attrib_img : (byte*)uid->name;
+ buf[0] = uid->attrib_img? 0xD1 : 0xB4;
+ buf[1] = dlen >> 24;
+ buf[2] = dlen >> 16;
+ buf[3] = dlen >> 8;
+ buf[4] = dlen >> 0;
+ gcry_md_write (md, buf, 5);
+ gcry_md_write (md, data, dlen);
}
-void
-_cdk_hash_sig_data( cdk_pkt_signature_t sig, cdk_md_hd_t md )
+cdk_error_t
+_cdk_hash_sig_data (cdk_pkt_signature_t sig, gcry_md_hd_t md)
{
- byte buf[4];
- size_t n = 0;
-
- if( !sig || !md )
- return;
-
- if( sig->version == 4 )
- cdk_md_putc( md, sig->version );
- cdk_md_putc( md, sig->sig_class );
- if( sig->version < 4 ) {
- buf[0] = sig->timestamp >> 24;
- buf[1] = sig->timestamp >> 16;
- buf[2] = sig->timestamp >> 8;
- buf[3] = sig->timestamp;
- cdk_md_write( md, buf, 4 );
+ byte buf[4];
+
+ if (!sig || !md)
+ return CDK_Inv_Value;
+
+ if (sig->version == 4)
+ gcry_md_putc (md, sig->version);
+ gcry_md_putc (md, sig->sig_class);
+ if (sig->version < 4)
+ {
+ buf[0] = sig->timestamp >> 24;
+ buf[1] = sig->timestamp >> 16;
+ buf[2] = sig->timestamp >> 8;
+ buf[3] = sig->timestamp >> 0;
+ gcry_md_write (md, buf, 4);
}
- else {
- cdk_md_putc( md, sig->pubkey_algo );
- cdk_md_putc( md, sig->digest_algo );
- if( sig->hashed ) {
- _cdk_subpkt_hash( sig->hashed, &n, md );
- sig->hashed_size = n;
- n = sig->hashed_size + 6;
+ else
+ {
+ size_t n;
+
+ gcry_md_putc (md, sig->pubkey_algo);
+ gcry_md_putc (md, sig->digest_algo);
+ if (sig->hashed != NULL)
+ {
+ byte *p = _cdk_subpkt_get_array (sig->hashed, 0, &n);
+ assert (p != NULL);
+ buf[0] = n >> 8;
+ buf[1] = n >> 0;
+ gcry_md_write (md, buf, 2);
+ gcry_md_write (md, p, n);
+ cdk_free (p);
+ sig->hashed_size = n;
+ n = sig->hashed_size + 6;
}
- else {
- cdk_md_putc( md, 0 );
- cdk_md_putc( md, 0 );
- n = 6;
+ else
+ {
+ gcry_md_putc (md, 0x00);
+ gcry_md_putc (md, 0x00);
+ n = 6;
}
- cdk_md_putc( md, sig->version );
- cdk_md_putc( md, 0xff );
- buf[0] = n >> 24;
- buf[1] = n >> 16;
- buf[2] = n >> 8;
- buf[3] = n;
- cdk_md_write( md, buf, 4 );
+ gcry_md_putc (md, sig->version);
+ gcry_md_putc (md, 0xFF);
+ buf[0] = n >> 24;
+ buf[1] = n >> 16;
+ buf[2] = n >> 8;
+ buf[3] = n >> 0;
+ gcry_md_write (md, buf, 4);
}
+ return 0;
}
static void
-cache_sig_result( cdk_pkt_signature_t sig, int res )
+cache_sig_result (cdk_pkt_signature_t sig, int res)
{
- if( !res ) {
+ sig->flags.checked = 0;
+ sig->flags.valid = 0;
+ if (!res) {
sig->flags.checked = 1;
sig->flags.valid = 1;
}
- else if( res == CDK_Bad_Sig ) {
+ else if (res == CDK_Bad_Sig) {
sig->flags.checked = 1;
sig->flags.valid = 0;
}
- else {
- sig->flags.checked = 0;
- sig->flags.valid = 0;
- }
}
-int
-_cdk_sig_check( cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig,
- cdk_md_hd_t digest, int * r_expired )
+cdk_error_t
+_cdk_sig_check (cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig,
+ gcry_md_hd_t digest, int *r_expired)
{
- byte md[24];
- time_t cur_time = _cdk_timestamp( );
- int digest_algo;
- int rc;
-
- if( !pk || !sig || !digest )
- return CDK_Inv_Value;
-
- if( sig->flags.checked )
- return sig->flags.valid ? 0 : CDK_Bad_Sig;
+ byte md[MAX_DIGEST_LEN];
+ time_t cur_time = _cdk_timestamp ();
+ int rc;
- if( !KEY_CAN_SIGN( pk->pubkey_algo ) ) {
- _cdk_log_debug ("pk algo `%d´ is not useable for signing.\n", pk->pubkey_algo);
- return CDK_Inv_Algo;
- }
- if( pk->timestamp > sig->timestamp || pk->timestamp > cur_time )
- return CDK_Time_Conflict;
-
- digest_algo = sig->digest_algo;
- if( r_expired && pk->expiredate
- && (pk->expiredate + pk->timestamp) > cur_time )
- *r_expired = 1;
-
- _cdk_hash_sig_data( sig, digest );
- cdk_md_final( digest );
- memcpy( md, cdk_md_read (digest, sig->digest_algo ),
- cdk_md_get_algo_dlen( sig->digest_algo ) );
- if( md[0] != sig->digest_start[0] || md[1] != sig->digest_start[1] )
- return CDK_Bad_Sig;
+ if (!pk || !sig || !digest)
+ return CDK_Inv_Value;
+
+ if (sig->flags.checked)
+ return sig->flags.valid ?0 : CDK_Bad_Sig;
+ if (!KEY_CAN_SIGN (pk->pubkey_algo))
+ return CDK_Inv_Algo;
+ if (pk->timestamp > sig->timestamp || pk->timestamp > cur_time)
+ return CDK_Time_Conflict;
+
+ if (r_expired && pk->expiredate
+ && (pk->expiredate + pk->timestamp) > cur_time)
+ *r_expired = 1;
+
+ _cdk_hash_sig_data (sig, digest);
+ gcry_md_final (digest);
+ memcpy (md, gcry_md_read (digest, sig->digest_algo),
+ gcry_md_get_algo_dlen (sig->digest_algo));
+
+ if (md[0] != sig->digest_start[0] ||
+ md[1] != sig->digest_start[1])
+ return CDK_Chksum_Error;
- rc = cdk_pk_verify( pk, sig, md );
- cache_sig_result( sig, rc );
- return rc;
+ rc = cdk_pk_verify (pk, sig, md);
+ cache_sig_result (sig, rc);
+ return rc;
}
-int
-_cdk_pk_check_sig (cdk_keydb_hd_t hd, cdk_kbnode_t knode, cdk_kbnode_t snode,
- int * is_selfsig)
+cdk_error_t
+_cdk_pk_check_sig (cdk_keydb_hd_t keydb,
+ cdk_kbnode_t knode, cdk_kbnode_t snode, int *is_selfsig)
{
- cdk_md_hd_t md;
- cdk_pkt_pubkey_t pk = NULL, sig_pk = NULL;
- cdk_pkt_signature_t sig = NULL;
- cdk_kbnode_t node;
- int digest_algo, is_expired = 0;
- int rc = 0;
-
- if( !knode || !snode )
- return CDK_Inv_Value;
-
- if (is_selfsig)
- *is_selfsig = 0;
- if( knode->pkt->pkttype != CDK_PKT_PUBLIC_KEY
- || snode->pkt->pkttype != CDK_PKT_SIGNATURE )
- return CDK_Inv_Value;
- pk = knode->pkt->pkt.public_key;
- sig = snode->pkt->pkt.signature;
- digest_algo = sig->digest_algo;
-
- md = cdk_md_open( digest_algo, 0 );
- if( !md )
- return CDK_Out_Of_Core;
-
- if( sig->sig_class == 0x20 ) { /* key revocation */
- cdk_kbnode_hash( knode, md, 0, 0, 0 );
- rc = _cdk_sig_check( pk, sig, md, &is_expired );
+ gcry_md_hd_t md;
+ cdk_pkt_pubkey_t pk;
+ cdk_pkt_signature_t sig;
+ cdk_kbnode_t node;
+ int is_expired;
+ gcry_error_t err;
+ cdk_error_t rc = 0;
+
+ if (!knode || !snode)
+ return CDK_Inv_Value;
+
+ if (is_selfsig)
+ *is_selfsig = 0;
+ if (knode->pkt->pkttype != CDK_PKT_PUBLIC_KEY ||
+ snode->pkt->pkttype != CDK_PKT_SIGNATURE)
+ return CDK_Inv_Value;
+ pk = knode->pkt->pkt.public_key;
+ sig = snode->pkt->pkt.signature;
+
+ err = gcry_md_open (&md, sig->digest_algo, 0);
+ if (err)
+ return map_gcry_error (err);
+
+ is_expired = 0;
+ if (sig->sig_class == 0x20)
+ { /* key revocation */
+ cdk_kbnode_hash (knode, md, 0, 0, 0);
+ rc = _cdk_sig_check (pk, sig, md, &is_expired);
}
- else if( sig->sig_class == 0x28 ) { /* subkey revocation */
- node = cdk_kbnode_find_prev( knode, snode, CDK_PKT_PUBLIC_SUBKEY );
- if( !node ) { /* no subkey for subkey revocation packet */
- rc = CDK_Error_No_Key;
- goto fail;
- }
- cdk_kbnode_hash( knode, md, 0, 0, 0 );
- cdk_kbnode_hash( node, md, 0, 0, 0 );
- rc = _cdk_sig_check( pk, sig, md, &is_expired );
+ else if (sig->sig_class == 0x28)
+ { /* subkey revocation */
+ node = cdk_kbnode_find_prev (knode, snode, CDK_PKT_PUBLIC_SUBKEY);
+ if (!node)
+ { /* no subkey for subkey revocation packet */
+ rc = CDK_Error_No_Key;
+ goto fail;
+ }
+ cdk_kbnode_hash (knode, md, 0, 0, 0);
+ cdk_kbnode_hash (node, md, 0, 0, 0);
+ rc = _cdk_sig_check (pk, sig, md, &is_expired);
}
- else if( sig->sig_class == 0x18 ) { /* key binding */
- node = cdk_kbnode_find_prev( knode, snode, CDK_PKT_PUBLIC_SUBKEY );
- if( !node ) { /* no subkey for subkey binding packet */
- rc = CDK_Error_No_Key;
- goto fail;
- }
- cdk_kbnode_hash( knode, md, 0, 0, 0 );
- cdk_kbnode_hash( node, md, 0, 0, 0 );
- rc = _cdk_sig_check( pk, sig, md, &is_expired );
+ else if (sig->sig_class == 0x18 || sig->sig_class == 0x19)
+ { /* primary/secondary key binding */
+ node = cdk_kbnode_find_prev (knode, snode, CDK_PKT_PUBLIC_SUBKEY);
+ if (!node)
+ { /* no subkey for subkey binding packet */
+ rc = CDK_Error_No_Key;
+ goto fail;
+ }
+ cdk_kbnode_hash (knode, md, 0, 0, 0);
+ cdk_kbnode_hash (node, md, 0, 0, 0);
+ rc = _cdk_sig_check (pk, sig, md, &is_expired);
}
- else if( sig->sig_class == 0x1f ) { /* direct key signature */
- cdk_kbnode_hash( knode, md, 0, 0, 0 );
- rc = _cdk_sig_check( pk, sig, md, &is_expired );
+ else if (sig->sig_class == 0x1F)
+ { /* direct key signature */
+ cdk_kbnode_hash (knode, md, 0, 0, 0);
+ rc = _cdk_sig_check (pk, sig, md, &is_expired);
}
- else { /* all other classes */
- node = cdk_kbnode_find_prev( knode, snode, CDK_PKT_USER_ID );
- if( !node ) { /* no user ID for key signature packet */
- rc = CDK_Error_No_Key;
- goto fail;
- }
- cdk_kbnode_hash( knode, md, 0, 0, 0 );
- cdk_kbnode_hash( node, md, sig->version == 4, 0, 0 );
- if (pk->keyid[0] == sig->keyid[0] && pk->keyid[1] == sig->keyid[1]) {
- rc = _cdk_sig_check (pk, sig, md, &is_expired);
- if (is_selfsig)
- *is_selfsig = 1;
- }
- else if (hd) {
- rc = cdk_keydb_get_pk (hd, sig->keyid, &sig_pk);
- if( !rc )
- rc = _cdk_sig_check (sig_pk, sig, md, &is_expired);
- _cdk_free_pubkey (sig_pk);
+ else
+ { /* all other classes */
+ node = cdk_kbnode_find_prev (knode, snode, CDK_PKT_USER_ID);
+ if (!node)
+ { /* no user ID for key signature packet */
+ rc = CDK_Error_No_Key;
+ goto fail;
+ }
+ cdk_kbnode_hash (knode, md, 0, 0, 0);
+ cdk_kbnode_hash (node, md, sig->version==4, 0, 0);
+ if (pk->keyid[0] == sig->keyid[0] && pk->keyid[1] == sig->keyid[1])
+ {
+ rc = _cdk_sig_check (pk, sig, md, &is_expired);
+ if (is_selfsig)
+ *is_selfsig = 1;
+ }
+ else if (keydb != NULL)
+ {
+ cdk_pkt_pubkey_t sig_pk;
+
+ rc = cdk_keydb_get_pk (keydb, sig->keyid, &sig_pk);
+ if (!rc)
+ rc = _cdk_sig_check (sig_pk, sig, md, &is_expired);
+ cdk_pk_release (sig_pk);
}
}
- fail:
- cdk_md_close (md);
- return rc;
+ fail:
+ gcry_md_close (md);
+ return rc;
}
/**
* cdk_pk_check_sigs:
* @knode: the key node
- * @hd: the session handle
+ * @hd: an optinal key database handle
* @r_status: variable to store the status of the key
*
* Check all signatures. When no key is available for checking, the
@@ -318,57 +343,126 @@ _cdk_pk_check_sig (cdk_keydb_hd_t hd, cdk_kbnode_t knode, cdk_kbnode_t snode,
* which are or-ed or zero when there are no flags.
**/
cdk_error_t
-cdk_pk_check_sigs( cdk_kbnode_t knode, cdk_keydb_hd_t hd, int * r_status )
+cdk_pk_check_sigs (cdk_kbnode_t knode, cdk_keydb_hd_t keydb, int *r_status)
{
- cdk_pkt_signature_t sig = NULL;
- cdk_kbnode_t k;
- u32 keyid = 0;
- int key_status = 0, is_selfsig = 0;
- int no_signer = 0, n_sigs = 0;
- int rc = 0;
-
- if( !knode || !r_status )
- return CDK_Inv_Value;
-
- k = cdk_kbnode_find( knode, CDK_PKT_PUBLIC_KEY );
- if( !k )
- return CDK_Error_No_Key;
- if( k->pkt->pkt.public_key->is_revoked )
- key_status |= CDK_KEY_REVOKED;
- if( k->pkt->pkt.public_key->has_expired )
- key_status |= CDK_KEY_EXPIRED;
- if( key_status ) {
- *r_status = key_status;
- return CDK_General_Error;
+ cdk_pkt_signature_t sig;
+ cdk_kbnode_t node;
+ u32 keyid;
+ int key_status, is_selfsig = 0;
+ int no_signer = 0, n_sigs = 0;
+ cdk_error_t rc;
+
+ if (!knode || !r_status)
+ return CDK_Inv_Value;
+
+ *r_status = 0;
+ node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY);
+ if (!node)
+ return CDK_Error_No_Key;
+
+ key_status = 0;
+ if (node->pkt->pkt.public_key->is_revoked)
+ key_status |= CDK_KEY_REVOKED;
+ if (node->pkt->pkt.public_key->has_expired)
+ key_status |= CDK_KEY_EXPIRED;
+ if (key_status)
+ {
+ *r_status = key_status;
+ return CDK_General_Error;
}
- keyid = cdk_pk_get_keyid( k->pkt->pkt.public_key, NULL );
-
- for( k = knode; k && k->pkt->pkttype; k = k->next ) {
- if( k->pkt->pkttype != CDK_PKT_SIGNATURE )
- continue;
- sig = k->pkt->pkt.signature;
- rc = _cdk_pk_check_sig (hd, knode, k, &is_selfsig);
- if (IS_UID_SIG (sig)) {
- if (is_selfsig == 0)
- n_sigs++;
- if (rc && rc == CDK_Error_No_Key) {
- sig->flags.missing_key = 1;
- no_signer++;
- continue;
- }
+ rc = 0;
+ keyid = cdk_pk_get_keyid (node->pkt->pkt.public_key, NULL);
+ for (node = knode; node; node = node->next)
+ {
+ if (node->pkt->pkttype != CDK_PKT_SIGNATURE)
+ continue;
+ sig = node->pkt->pkt.signature;
+ rc = _cdk_pk_check_sig (keydb, knode, node, &is_selfsig);
+ if (IS_UID_SIG (sig))
+ {
+ if (is_selfsig == 0)
+ n_sigs++;
+ }
+ if (rc && IS_UID_SIG (sig) && rc == CDK_Error_No_Key)
+ {
+ sig->flags.missing_key = 1;
+ no_signer++;
+ continue;
}
- else if (rc && rc != CDK_Error_No_Key) {
- *r_status = CDK_KEY_INVALID;
- rc = 0;
- break; /* invalid self signature or key signature */
+ else if (rc && rc != CDK_Error_No_Key)
+ {
+ /* If there was an error during the verify process and
+ we checked the self signature, we immediately bail out. */
+ *r_status = CDK_KEY_INVALID;
+ if (is_selfsig)
+ return rc;
+ break;
}
- _cdk_log_debug( "signature %s: signer %08lX keyid %08lX\n",
- rc==CDK_Bad_Sig? "BAD" : "good", sig->keyid[1],
- keyid );
+ _cdk_log_debug ("signature %s: signer %08lX keyid %08lX\n",
+ rc==CDK_Bad_Sig? "BAD" : "good", sig->keyid[1],
+ keyid);
+ }
+ if (n_sigs == no_signer)
+ *r_status |= CDK_KEY_NOSIGNER;
+ if (!rc || rc == CDK_Error_No_Key)
+ *r_status = CDK_KEY_VALID;
+ return rc;
+}
+
+
+/**
+ * cdk_pk_check_self_sig:
+ * @knode: the key node
+ * @keydb: an optional handle to the key database
+ * @r_status: output the status of the key.
+ *
+ * A convenient function to make sure the key is valid.
+ * Valid means the self signature is ok.
+ **/
+cdk_error_t
+cdk_pk_check_self_sig (cdk_kbnode_t knode, int *r_status)
+{
+ cdk_pkt_signature_t sig;
+ cdk_kbnode_t node;
+ u32 keyid[2], sigid[2];
+ cdk_error_t rc;
+ int is_selfsig, sig_ok;
+
+ if (!knode || !r_status)
+ return CDK_Inv_Value;
+
+ node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY);
+ if (!node)
+ return CDK_Error_No_Key;
+ cdk_pk_get_keyid (knode->pkt->pkt.public_key, keyid);
+ sig_ok = 0;
+ for (node = knode; node; node = node->next)
+ {
+ if (node->pkt->pkttype != CDK_PKT_SIGNATURE)
+ continue;
+ sig = node->pkt->pkt.signature;
+ if (!IS_UID_SIG (sig))
+ continue;
+ cdk_sig_get_keyid (sig, sigid);
+ if (sigid[0] != keyid[0] || sigid[1] != keyid[1])
+ continue;
+ /* FIXME: Now we check all self signatures. */
+ rc = _cdk_pk_check_sig (NULL, knode, node, &is_selfsig);
+ if (rc)
+ {
+ *r_status = CDK_KEY_INVALID;
+ return rc;
+ }
+ else /* For each valid self sig we increase this counter. */
+ sig_ok++;
}
- if (n_sigs == no_signer)
- *r_status |= CDK_KEY_NOSIGNER;
- if( !rc || rc == CDK_Error_No_Key )
- *r_status |= CDK_KEY_VALID;
- return rc;
+
+ /* A key without a self signature is not valid. */
+ if (!sig_ok)
+ {
+ *r_status = CDK_KEY_INVALID;
+ return CDK_General_Error;
+ }
+ *r_status = CDK_KEY_VALID;
+ return 0;
}
diff --git a/libextra/opencdk/sign.c b/libextra/opencdk/sign.c
deleted file mode 100644
index 46e1a90509..0000000000
--- a/libextra/opencdk/sign.c
+++ /dev/null
@@ -1,494 +0,0 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * sign.c - Signing routines
- * Copyright (C) 2006 Free Software Foundation, Inc.
- * Copyright (C) 2002, 2003 Timo Schulz
- *
- * This file is part of OpenCDK.
- *
- * OpenCDK is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * OpenCDK is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include <stdio.h>
-#include <time.h>
-#include <string.h>
-
-#include "opencdk.h"
-#include "main.h"
-#include "packet.h"
-#include "filters.h"
-#include "stream.h"
-
-
-static int file_clearsign( cdk_ctx_t, cdk_strlist_t,
- const char *, const char * );
-static int stream_clearsign( cdk_ctx_t, cdk_stream_t,
- cdk_stream_t, cdk_strlist_t );
-
-
-static void
-calc_subpkt_size( cdk_pkt_signature_t sig )
-{
- size_t nbytes;
-
- if( sig->hashed ) {
- _cdk_subpkt_get_array( sig->hashed, 1, &nbytes );
- sig->hashed_size = nbytes;
- }
- if( sig->unhashed ) {
- _cdk_subpkt_get_array( sig->unhashed, 1, &nbytes );
- sig->unhashed_size = nbytes;
- }
-}
-
-
-int
-_cdk_sig_hash_for( int pkalgo, int pktver )
-{
- if( is_DSA( pkalgo ) )
- return CDK_MD_SHA1;
- else if( is_RSA( pkalgo ) && pktver < 4 )
- return CDK_MD_MD5;
- return CDK_MD_SHA1; /* default message digest */
-}
-
-
-int
-_cdk_sig_create( cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig )
-{
- cdk_subpkt_t node;
- byte buf[8];
-
- if( !sig )
- return CDK_Inv_Value;
-
- if( pk ) {
- if( !sig->version )
- sig->version = pk->version;
- sig->pubkey_algo = pk->pubkey_algo;
- sig->digest_algo = _cdk_sig_hash_for( pk->pubkey_algo, pk->version );
- cdk_pk_get_keyid( pk, sig->keyid );
- }
- sig->timestamp = _cdk_timestamp( );
- if( sig->version == 3 )
- return 0;
-
- sig->hashed = sig->unhashed = NULL;
-
- _cdk_u32tobuf( sig->keyid[0], buf );
- _cdk_u32tobuf( sig->keyid[1], buf + 4 );
- node = cdk_subpkt_new( 8 );
- if( node )
- cdk_subpkt_init( node, CDK_SIGSUBPKT_ISSUER, buf, 8 );
- sig->unhashed = node;
-
- _cdk_u32tobuf( sig->timestamp, buf );
- node = cdk_subpkt_new( 4 );
- if( node ) {
- cdk_subpkt_init( node, CDK_SIGSUBPKT_SIG_CREATED, buf, 4 );
- sig->hashed = node;
- }
-
- if( sig->expiredate ) {
- u32 u = sig->expiredate - sig->timestamp;
- _cdk_u32tobuf( u, buf );
- node = cdk_subpkt_new( 4 );
- if( node ) {
- cdk_subpkt_init( node, CDK_SIGSUBPKT_SIG_EXPIRE, buf, 4 );
- cdk_subpkt_add( sig->hashed, node );
- }
- }
- calc_subpkt_size( sig );
- return 0;
-}
-
-
-int
-_cdk_sig_complete( cdk_pkt_signature_t sig, cdk_pkt_seckey_t sk,
- cdk_md_hd_t md )
-{
- byte digest[24];
-
- if( !sig || !sk || !md )
- return CDK_Inv_Value;
-
- calc_subpkt_size( sig );
- _cdk_hash_sig_data( sig, md );
- cdk_md_final( md );
- memcpy( digest, cdk_md_read( md, sig->digest_algo),
- cdk_md_get_algo_dlen( sig->digest_algo ) );
- return cdk_pk_sign( sk, sig, digest );
-}
-
-
-static int
-write_literal( cdk_stream_t inp, cdk_stream_t out )
-{
- cdk_packet_t pkt;
- cdk_pkt_literal_t pt;
- const char * s = _cdk_stream_get_fname( inp );
- int rc;
-
- if( !inp || !out )
- return CDK_Inv_Value;
-
- pkt = cdk_calloc( 1, sizeof *pkt );
- if( !pkt )
- return CDK_Out_Of_Core;
- cdk_stream_seek( inp, 0 );
- if( !s )
- s = "_CONSOLE";
- pt = cdk_calloc( 1, sizeof *pt + strlen( s ) + 1 );
- if( !pt )
- return CDK_Out_Of_Core;
- pt->len = cdk_stream_get_length( inp );
- pt->mode = 'b';
- pt->timestamp = _cdk_timestamp( );
- pt->namelen = strlen( s );
- pt->buf = inp;
- strcpy( pt->name, s );
- pkt->pkttype = CDK_PKT_LITERAL;
- pkt->pkt.literal = pt;
- rc = cdk_pkt_write( out, pkt );
- cdk_free( pt );
- cdk_free( pkt );
- return rc;
-}
-
-
-static int
-write_pubkey_enc_list( cdk_ctx_t hd, cdk_stream_t out, cdk_strlist_t remusr )
-{
- cdk_keylist_t pkl;
- int rc;
-
- if( !hd || !out )
- return CDK_Inv_Value;
-
- rc = cdk_pklist_build( &pkl, hd->db.pub, remusr, PK_USAGE_ENCR );
- if( rc )
- return rc;
-
- cdk_dek_free( hd->dek );
- rc = cdk_dek_new( &hd->dek );
- if( !rc )
- rc = cdk_dek_set_cipher( hd->dek, cdk_pklist_select_algo( pkl, 1 ) );
- if( !rc )
- rc = cdk_dek_set_key( hd->dek, NULL, 0 );
- if( !rc ) {
- cdk_dek_set_mdc_flag( hd->dek, cdk_pklist_use_mdc( pkl ) );
- rc = cdk_pklist_encrypt( pkl, hd->dek, out );
- }
- cdk_pklist_release( pkl );
- return rc;
-}
-
-
-static int
-sig_get_version( cdk_ctx_t hd, cdk_keylist_t kl )
-{
- cdk_keylist_t l;
-
- if( hd && hd->opt.compat )
- return 3;
-
- for( l = kl; l; l = l->next ) {
- if( (l->type == CDK_PKT_PUBLIC_KEY && l->key.pk->version == 3)
- || (l->type == CDK_PKT_SECRET_KEY && l->key.sk->version == 3))
- return 3;
- }
- return 4;
-}
-
-
-/**
- * cdk_stream_sign:
- * @hd: session handle
- * @inp: input stream
- * @out: output stream
- * @locusr: local user list for signing
- * @remusr: remote user list for encrypting
- * @encryptflag: shall the output be encrypted? (1/0)
- * @sigmode: signature mode
- *
- * Sign the data from the STREAM @inp.
- **/
-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 )
-{
- cdk_keylist_t list;
- cdk_pkt_seckey_t sk;
- md_filter_t * mfx;
- int sigver, digest_algo;
- int rc, detached = sigmode == CDK_SIGMODE_DETACHED;
-
- if( !hd )
- return CDK_Inv_Value;
- if( detached && encryptflag )
- return CDK_Inv_Mode;
-
- if( sigmode == CDK_SIGMODE_CLEAR )
- return stream_clearsign( hd, inp, out, locusr );
-
- rc = cdk_sklist_build( &list, hd->db.sec, hd, locusr, 1, PK_USAGE_SIGN );
- if( rc )
- return rc;
-
- sk = list->key.sk;
- digest_algo = _cdk_sig_hash_for( sk->pubkey_algo, sk->version );
- if( cdk_handle_control( hd, CDK_CTLF_GET, CDK_CTL_FORCE_DIGEST ) )
- digest_algo = hd->digest_algo;
-
- if( hd->opt.armor )
- cdk_stream_set_armor_flag( out, detached? CDK_ARMOR_SIGNATURE : 0 );
-
- if( encryptflag ) {
- cdk_stream_set_cache( out, 1 );
- rc = write_pubkey_enc_list( hd, out, remusr );
- if( rc ) {
- cdk_sklist_release( list );
- return rc;
- }
- cdk_stream_set_cipher_flag( out, hd->dek, hd->dek->use_mdc );
- cdk_stream_set_cache( out, 0 );
- }
-
- cdk_stream_set_hash_flag( inp, digest_algo );
- /* kick off the filter */
- sigver = sig_get_version( hd, list );
- cdk_stream_read( inp, NULL, 0 );
- mfx = _cdk_stream_get_opaque( inp, fHASH );
- if( mfx && mfx->md ) {
- if( sigver == 3 ) {
- rc = cdk_sklist_write( list, out, mfx->md, 0x00, 0x03 );
- if( !rc && !detached )
- rc = write_literal( inp, out );
- }
- else {
- if( !detached ) {
- rc = cdk_sklist_write_onepass( list, out, 0x00, digest_algo );
- if( !rc )
- rc = write_literal( inp, out );
- }
- if( !rc )
- rc = cdk_sklist_write( list, out, mfx->md, 0x00, 0x04 );
- }
- }
- cdk_sklist_release( list );
- return rc;
-}
-
-
-/**
- * cdk_file_sign:
- * @locusr: List of userid which should be used for signing
- * @remusr: If encrypt is valid, the list of recipients
- * @file: Name of the input file
- * @output: Name of the output file
- * @sigmode: Signature mode
- * @encryptflag: enable sign and encrypt
- *
- * Sign a file.
- **/
-cdk_error_t
-cdk_file_sign( cdk_ctx_t hd, cdk_strlist_t locusr, cdk_strlist_t remusr,
- const char * file, const char * output,
- int sigmode, int encryptflag )
-{
- cdk_stream_t inp = NULL, out = NULL;
- int rc = 0;
-
- if( !file || !output )
- return CDK_Inv_Value;
- if( encryptflag && !remusr )
- return CDK_Inv_Value;
- if( (sigmode != CDK_SIGMODE_NORMAL) && encryptflag )
- return CDK_Inv_Mode;
- if( !remusr && !locusr )
- return CDK_Inv_Value;
- if( sigmode == CDK_SIGMODE_CLEAR )
- return file_clearsign( hd, locusr, file, output );
-
- rc = cdk_stream_open( file, &inp );
- if( rc )
- return rc;
-
- if( hd->opt.armor || encryptflag )
- rc = cdk_stream_new( output, &out );
- else
- rc = cdk_stream_create( output, &out );
- if( rc ) {
- cdk_stream_close( inp );
- return rc;
- }
- rc = cdk_stream_sign( hd, inp, out, locusr, remusr, encryptflag, sigmode );
-
- cdk_stream_close( inp );
- cdk_stream_close( out );
- return rc;
-}
-
-
-static void
-put_hash_line( cdk_stream_t out, int digest_algo, int is_v4 )
-{
- const char * s = NULL;
-
- if( !is_v4 ) {
- cdk_stream_putc( out, '\n' );
- return;
- }
-
- switch( digest_algo ) {
- case CDK_MD_MD2 : s = "Hash: MD2\n\n"; break;
- case CDK_MD_MD5 : s = "Hash: MD5\n\n"; break;
- case CDK_MD_SHA1 : s = "Hash: SHA1\n\n"; break;
- case CDK_MD_RMD160 : s = "Hash: RIPEMD160\n\n"; break;
- case CDK_MD_SHA256 : s = "Hash: SHA256\n\n"; break;
- default : s = "Hash: SHA1\n\n"; break;
- }
- _cdk_stream_puts( out, s );
-}
-
-
-void
-_cdk_trim_string( char * s, int canon )
-{
- while( s && *s &&( s[strlen( s )-1] == '\t'
- || s[strlen( s )-1] == '\r'
- || s[strlen( s )-1] == '\n'
- || s[strlen( s )-1] == ' '))
- s[strlen( s ) -1] = '\0';
- if( canon )
- strcat( s, "\r\n" );
-}
-
-
-static int
-stream_clearsign( cdk_ctx_t hd, cdk_stream_t inp, cdk_stream_t out,
- cdk_strlist_t locusr )
-{
- cdk_md_hd_t md = NULL;
- cdk_keylist_t list;
- cdk_stream_t tmp;
- cdk_pkt_seckey_t sk;
- const char * s;
- char buf[1024+2];
- int digest_algo, sigver;
- int rc, nread;
-
- rc = cdk_sklist_build( &list, hd->db.sec, hd, locusr, 1, PK_USAGE_SIGN );
- if( rc )
- return rc;
-
- sk = list->key.sk;
- digest_algo = _cdk_sig_hash_for( sk->pubkey_algo, sk->version );
- md = cdk_md_open( digest_algo, 0 );
- if( !md ) {
- cdk_sklist_release( list );
- return CDK_Gcry_Error;
- }
-
- s = _cdk_armor_get_lineend( );
- strcpy( buf, "-----BEGIN PGP SIGNED MESSAGE-----" );
- strcat( buf, s );
- _cdk_stream_puts( out, buf );
- put_hash_line( out, digest_algo, sk->version == 4 );
-
- while( !cdk_stream_eof( inp ) ) {
- nread = _cdk_stream_gets( inp, buf, sizeof buf-1 );
- if( !nread )
- break;
- _cdk_trim_string( buf, 1 );
- cdk_md_write( md, buf, strlen( buf ) );
- if( buf[0] == '-' ) {
- memmove( &buf[2], buf, nread + 1 );
- buf[1] = ' ';
- }
- if( strlen( s ) == 1 ) {
- buf[strlen( buf ) - 1] = '\0';
- buf[strlen( buf ) - 1] = '\n';
- }
- _cdk_stream_puts( out, buf );
- }
- _cdk_stream_puts( out, s );
- tmp = cdk_stream_tmp( );
- if( !tmp ) {
- rc = CDK_Out_Of_Core;
- goto leave;
- }
- cdk_stream_tmp_set_mode( tmp, 1 );
- cdk_stream_set_armor_flag( tmp, CDK_ARMOR_SIGNATURE );
-
- sigver = sig_get_version( hd, list );
- rc = cdk_sklist_write( list, tmp, md, 0x01, sigver );
- if( rc ) {
- cdk_stream_close( tmp );
- goto leave;
- }
-
- rc = cdk_stream_flush( tmp );
- if( rc )
- goto leave;
-
- while( !cdk_stream_eof( tmp ) ) {
- nread = cdk_stream_read( tmp, buf, sizeof buf-1 );
- if( !nread )
- break;
- cdk_stream_write( out, buf, nread );
- }
- cdk_stream_close( tmp );
-
- leave:
- cdk_md_close( md );
- cdk_sklist_release( list );
- return rc;
-}
-
-
-static int
-file_clearsign( cdk_ctx_t hd, cdk_strlist_t locusr,
- const char * file, const char * output )
-{
- cdk_stream_t inp = NULL, out = NULL;
- int rc;
-
- if( !locusr || !file || !output )
- return CDK_Inv_Value;
- if( !hd->opt.overwrite && _cdk_check_file( output ) )
- return CDK_Inv_Mode;
-
- rc = cdk_stream_open( file, &inp );
- if( rc )
- return rc;
-
- rc = cdk_stream_create( output, &out );
- if( rc ) {
- cdk_stream_close( inp );
- return rc;
- }
-
- rc = stream_clearsign( hd, inp, out, locusr );
-
- cdk_stream_close( inp );
- cdk_stream_close( out );
-
- return rc;
-}
-
diff --git a/libextra/opencdk/stream.c b/libextra/opencdk/stream.c
index c158efe8d4..bfc0c5978b 100644
--- a/libextra/opencdk/stream.c
+++ b/libextra/opencdk/stream.c
@@ -1,6 +1,5 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * stream.c - provides a STREAM object
- * Copyright (C) 2002, 2003 Timo Schulz
+/* stream.c - The stream implementation
+ * Copyright (C) 2002, 2003, 2007 Timo Schulz
*
* This file is part of OpenCDK.
*
@@ -13,14 +12,9 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
#ifdef HAVE_CONFIG_H
-# include <config.h>
+#include <config.h>
#endif
#include <assert.h>
#include <stdio.h>
@@ -38,44 +32,99 @@
#include "stream.h"
#include "types.h"
+/* This is the maximal amount of bytes we map. */
+#define MAX_MAP_SIZE 16777216
-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 );
+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);
/**
- * cdk_stream_open: create a new stream based on an existing file.
+ * cdk_stream_open:
* @file: The file to open
* @ret_s: The new STREAM object
+ *
+ * Create a new stream based on an existing file. The stream is
+ * opened in read-only mode.
**/
cdk_error_t
-cdk_stream_open( const char * file, cdk_stream_t * ret_s )
+cdk_stream_open (const char *file, cdk_stream_t *ret_s)
{
- cdk_stream_t s;
+ return _cdk_stream_open_mode (file, "rb", ret_s);
+}
- if( !file || !ret_s )
- return CDK_Inv_Value;
- _cdk_log_debug( "open stream `%s'\n", file );
- *ret_s = NULL;
- s = cdk_calloc( 1, sizeof *s );
- if( !s )
- return CDK_Out_Of_Core;
- s->fname = cdk_strdup( file );
- if( !s->fname ) {
- cdk_free( s );
- return CDK_Out_Of_Core;
+/* Helper function to allow to open a stream in different modes. */
+cdk_error_t
+_cdk_stream_open_mode (const char *file, const char *mode, cdk_stream_t *ret_s)
+{
+ cdk_stream_t s;
+
+ if (!file || !ret_s)
+ return CDK_Inv_Value;
+
+ _cdk_log_debug ("open stream `%s'\n", file);
+ *ret_s = NULL;
+ s = cdk_calloc (1, sizeof *s);
+ if (!s)
+ return CDK_Out_Of_Core;
+ s->fname = cdk_strdup (file);
+ if (!s->fname)
+ {
+ cdk_free (s);
+ return CDK_Out_Of_Core;
}
- s->fp = fopen( file, "rb" );
- if( !s->fp ) {
- cdk_free( s->fname );
- cdk_free( s );
- return CDK_File_Error;
+ s->fp = fopen (file, mode);
+ if (!s->fp)
+ {
+ cdk_free (s->fname);
+ cdk_free (s);
+ return CDK_File_Error;
}
- s->flags.write = 0;
- *ret_s = s;
- return 0;
+ _cdk_log_debug ("open stream fd=%d\n", fileno (s->fp));
+ s->flags.write = 0;
+ *ret_s = s;
+ return 0;
+}
+
+
+/**
+ * cdk_stream_new_from_cbs:
+ * @cbs: the callback context with all user callback functions
+ * @opa: opaque handle which is passed to all callbacks.
+ * @ret_s: the allocated stream
+ *
+ * This function creates a stream which uses user callback
+ * for the core operations (open, close, read, write, seek).
+ */
+cdk_error_t
+cdk_stream_new_from_cbs (cdk_stream_cbs_t cbs, void *opa,
+ cdk_stream_t *ret_s)
+{
+ cdk_stream_t s;
+
+ if (!opa)
+ return CDK_Inv_Value;
+
+ *ret_s = NULL;
+ s = cdk_calloc (1, sizeof *s);
+ if (!s)
+ return CDK_Out_Of_Core;
+
+ s->cbs.read = cbs->read;
+ s->cbs.write = cbs->write;
+ s->cbs.seek = cbs->seek;
+ s->cbs.release = cbs->release;
+ s->cbs.open = cbs->open;
+ s->cbs_hd = opa;
+ *ret_s = s;
+
+ /* If there is a user callback for open, we need to call it
+ here because read/write expects an open stream. */
+ if (s->cbs.open)
+ return s->cbs.open (s->cbs_hd);
+ return 0;
}
@@ -85,36 +134,40 @@ cdk_stream_open( const char * file, cdk_stream_t * ret_s )
* @ret_s: The new STREAM object
**/
cdk_error_t
-cdk_stream_new( const char * file, cdk_stream_t * ret_s )
+cdk_stream_new (const char *file, cdk_stream_t *ret_s)
{
- cdk_stream_t s;
-
- if( !ret_s )
- return CDK_Inv_Value;
-
- _cdk_log_debug( "new stream `%s'\n", file? file : "[temp]" );
- *ret_s = NULL;
- s = cdk_calloc( 1, sizeof *s );
- if( !s )
- return CDK_Out_Of_Core;
- s->flags.write = 1;
- if( !file )
- s->flags.temp = 1;
- else {
- s->fname = cdk_strdup( file );
- if( !s->fname ) {
- cdk_free( s );
- return CDK_Out_Of_Core;
- }
+ cdk_stream_t s;
+
+ if (!ret_s)
+ return CDK_Inv_Value;
+
+ _cdk_log_debug ("new stream `%s'\n", file? file : "[temp]");
+ *ret_s = NULL;
+ s = cdk_calloc (1, sizeof *s);
+ if (!s)
+ return CDK_Out_Of_Core;
+ s->flags.write = 1;
+ if (!file)
+ s->flags.temp = 1;
+ else
+ {
+ s->fname = cdk_strdup (file);
+ if (!s->fname)
+ {
+ cdk_free (s);
+ return CDK_Out_Of_Core;
+ }
}
- s->fp = tmpfile( );
- if( !s->fp ) {
- cdk_free( s->fname );
- cdk_free( s );
- return CDK_File_Error;
+ s->fp = tmpfile ();
+ if (!s->fp)
+ {
+ cdk_free (s->fname);
+ cdk_free (s);
+ return CDK_File_Error;
}
- *ret_s = s;
- return 0;
+ _cdk_log_debug ("new stream fd=%d\n", fileno (s->fp));
+ *ret_s = s;
+ return 0;
}
@@ -127,161 +180,192 @@ cdk_stream_new( const char * file, cdk_stream_t * ret_s )
* this kind of stream and everything is written directly to the stream.
**/
cdk_error_t
-cdk_stream_create( const char * file, cdk_stream_t * ret_s )
+cdk_stream_create (const char *file, cdk_stream_t *ret_s)
{
- cdk_stream_t s;
-
- if( !file || !ret_s )
- return CDK_Inv_Value;
+ cdk_stream_t s;
+
+ if (!file || !ret_s)
+ return CDK_Inv_Value;
- _cdk_log_debug( "create stream `%s'\n", file );
- *ret_s = NULL;
- s = cdk_calloc( 1, sizeof * s );
- if( !s )
- return CDK_Out_Of_Core;
- s->flags.write = 1;
- s->flags.filtrated = 1;
- s->fname = cdk_strdup( file );
- if( !s->fname ) {
- cdk_free( s );
- return CDK_Out_Of_Core;
+ _cdk_log_debug ("create stream `%s'\n", file);
+ *ret_s = NULL;
+ s = cdk_calloc (1, sizeof *s);
+ if (!s)
+ return CDK_Out_Of_Core;
+ s->flags.write = 1;
+ s->flags.filtrated = 1;
+ s->fname = cdk_strdup (file);
+ if (!s->fname)
+ {
+ cdk_free (s);
+ return CDK_Out_Of_Core;
}
- s->fp = fopen( file, "w+b" );
- if( !s->fp ) {
- cdk_free( s->fname );
- cdk_free( s );
- return CDK_Out_Of_Core;
+ s->fp = fopen (file, "w+b");
+ if (!s->fp)
+ {
+ cdk_free (s->fname);
+ cdk_free (s);
+ return CDK_File_Error;
}
- *ret_s = s;
- return 0;
+ _cdk_log_debug ("stream create fd=%d\n", fileno (s->fp));
+ *ret_s = s;
+ return 0;
}
-cdk_stream_t
-cdk_stream_tmp( void )
+/**
+ * cdk_stream_tmp_new:
+ * @r_out: the new temp stream.
+ *
+ * Allocate a new tempory stream which is not associated with a file.
+ */
+cdk_error_t
+cdk_stream_tmp_new (cdk_stream_t *r_out)
{
- cdk_stream_t s;
- int rc = cdk_stream_new( NULL, &s );
- if( !rc )
- return s;
- return NULL;
+ return cdk_stream_new (NULL, r_out);
}
-cdk_stream_t
-cdk_stream_tmp_from_mem( const void * buf, size_t count )
-{
- cdk_stream_t s;
- int nwritten;
- s = cdk_stream_tmp( );
- if( !s )
- return NULL;
+/**
+ * cdk_stream_tmp_from_mem:
+ * @buf: the buffer which shall be written to the temp stream.
+ * @buflen: how large the buffer is
+ * @r_out: the new stream with the given contents.
+ *
+ * Create a new tempory stream with the given contests.
+ */
+cdk_error_t
+cdk_stream_tmp_from_mem (const void *buf, size_t buflen, cdk_stream_t *r_out)
+{
+ cdk_stream_t s;
+ cdk_error_t rc;
+ int nwritten;
+
+ *r_out = NULL;
+ rc = cdk_stream_tmp_new (&s);
+ if (rc)
+ return rc;
- nwritten = cdk_stream_write( s, buf, count );
- if( nwritten == EOF ) {
- cdk_stream_close( s );
- return NULL;
+ nwritten = cdk_stream_write (s, buf, buflen);
+ if (nwritten == EOF)
+ {
+ cdk_stream_close (s);
+ return CDK_File_Error;
}
- cdk_stream_seek( s, 0 );
- return s;
+ cdk_stream_seek (s, 0);
+ *r_out = s;
+ return 0;
}
-
-cdk_stream_t
-_cdk_stream_fpopen( FILE * fp, unsigned write_mode )
+cdk_error_t
+_cdk_stream_fpopen (FILE *fp, unsigned write_mode, cdk_stream_t *ret_out)
{
cdk_stream_t s;
- s = cdk_calloc( 1, sizeof *s );
- if( !s )
- return NULL;
+ *ret_out = NULL;
+ s = cdk_calloc (1, sizeof *s);
+ if (!s)
+ return CDK_Out_Of_Core;
+ _cdk_log_debug ("stream ref fd=%d\n", fileno (fp));
s->fp = fp;
+ s->fp_ref = 1;
s->flags.filtrated = 1;
s->flags.write = write_mode;
-
- return s;
+
+ *ret_out = s;
+ return 0;
}
cdk_error_t
-_cdk_stream_append( const char * file, cdk_stream_t * ret_s )
+_cdk_stream_append (const char *file, cdk_stream_t *ret_s)
{
- cdk_stream_t s;
- FILE * fp;
- int rc;
+ cdk_stream_t s;
+ cdk_error_t rc;
- if( !ret_s )
- return CDK_Inv_Value;
- rc = cdk_stream_open( file, &s );
- if( rc )
- return rc;
- fp = fopen( file, "a+b" );
- if( !fp ) {
- cdk_stream_close( s );
- return CDK_File_Error;
- }
- fclose( s->fp );
- s->fp = fp;
- s->flags.write = 1;
- *ret_s = s;
- return 0;
+ if (!ret_s)
+ return CDK_Inv_Value;
+ *ret_s = NULL;
+
+ rc = _cdk_stream_open_mode (file, "a+b", &s);
+ if (rc)
+ return rc;
+
+ /* In the append mode, we need to write to the flag. */
+ s->flags.write = 1;
+ *ret_s = s;
+ return 0;
}
-
+
+/**
+ * cdk_stream_is_compressed:
+ * @s: the stream
+ *
+ * Return 0 if the stream is uncompressed, otherwise the
+ * compression algorithm.
+ */
int
-cdk_stream_control( cdk_stream_t s, int ctl, int val )
+cdk_stream_is_compressed (cdk_stream_t s)
{
- if( !s )
- return CDK_Inv_Value;
-
- if( val == -1 ) {
- switch( ctl ) {
- case CDK_STREAMCTL_COMPRESSED: return s->flags.compressed;
- }
- return 0;
- }
- switch( ctl ) {
- case CDK_STREAMCTL_DISABLE: s->flags.no_filter = val; break;
- case CDK_STREAMCTL_COMPRESSED: s->flags.compressed = val; break;
- default : return CDK_Inv_Mode;
- }
+ if (!s)
return 0;
+ return s->flags.compressed;
+}
+
+void
+_cdk_stream_set_compress_algo (cdk_stream_t s, int algo)
+{
+ if (!s)
+ return;
+ s->flags.compressed = algo;
}
cdk_error_t
-cdk_stream_flush( cdk_stream_t s )
+cdk_stream_flush (cdk_stream_t s)
{
- int rc = 0;
+ cdk_error_t rc;
- if( !s )
- return CDK_Inv_Value;
-
- if( !s->flags.filtrated ) {
- if( !cdk_stream_get_length( s ) )
- return 0;
- rc = cdk_stream_seek( s, 0 );
- if( !rc )
- rc = stream_flush( s );
- if( !rc ) {
- rc = stream_filter_write( s );
- if( rc )
- s->error = rc;
- }
- s->flags.filtrated = 1;
+ if (!s)
+ return CDK_Inv_Value;
+
+ /* The user callback does not support flush */
+ if (s->cbs_hd)
+ return 0;
+
+ /* For read-only streams, no flush is needed. */
+ if (!s->flags.write)
+ return 0;
+
+ if (!s->flags.filtrated)
+ {
+ if (!cdk_stream_get_length (s))
+ return 0;
+ rc = cdk_stream_seek (s, 0);
+ if (!rc)
+ rc = stream_flush (s);
+ if (!rc)
+ rc = stream_filter_write (s);
+ s->flags.filtrated = 1;
+ if (rc)
+ {
+ s->error = rc;
+ return rc;
+ }
}
- return rc;
+ return 0;
}
void
-cdk_stream_tmp_set_mode( cdk_stream_t s, int val )
+cdk_stream_tmp_set_mode (cdk_stream_t s, int val)
{
- if( s && s->flags.temp )
- s->fmode = val;
+ if (s && s->flags.temp)
+ s->fmode = val;
}
@@ -296,38 +380,64 @@ cdk_stream_tmp_set_mode( cdk_stream_t s, int val )
* filters now. The file is closed in the filter function and not here.
**/
cdk_error_t
-cdk_stream_close( cdk_stream_t s )
+cdk_stream_close (cdk_stream_t s)
{
- struct stream_filter_s * f, * f2;
- int rc = 0;
-
- if( !s )
- return CDK_Inv_Value;
-
- _cdk_log_debug( "close stream `%s'\n", s->fname? s->fname : "[temp]" );
+ struct stream_filter_s *f, *f2;
+ cdk_error_t rc;
+
+ if (!s)
+ return CDK_Inv_Value;
+
+ _cdk_log_debug ("close stream ref=%d `%s'\n",
+ s->fp_ref, s->fname? s->fname : "[temp]");
+
+ /* In the user callback mode, we call the release cb if possible
+ and just free the stream. */
+ if (s->cbs_hd)
+ {
+ if (s->cbs.release)
+ rc = s->cbs.release (s->cbs_hd);
+ else
+ rc = 0;
+ cdk_free (s);
+ return rc;
+ }
- if( !s->flags.filtrated && !s->error )
- rc = cdk_stream_flush( s );
- if( s->fname || s->flags.temp ) {
- rc = fclose( s->fp );
- s->fp = NULL;
- if( rc )
- rc = CDK_File_Error;
+
+ rc = 0;
+ if (!s->flags.filtrated && !s->error)
+ rc = cdk_stream_flush (s);
+ if (!s->fp_ref && (s->fname || s->flags.temp))
+ {
+ int err;
+
+ _cdk_log_debug ("close stream fd=%d\n", fileno (s->fp));
+ err = fclose (s->fp);
+ s->fp = NULL;
+ if (err)
+ rc = CDK_File_Error;
}
- f = s->filters;
- while( f ) {
- f2 = f->next;
- if( f->fnct )
- f->fnct( f->opaque, STREAMCTL_FREE, NULL, NULL );
- cdk_free( f );
- f = f2;
+
+ /* Iterate over the filter list and use the cleanup flag to
+ free the allocated internal structures. */
+ f = s->filters;
+ while (f)
+ {
+ f2 = f->next;
+ if (f->fnct)
+ f->fnct (f->opaque, STREAMCTL_FREE, NULL, NULL);
+ cdk_free (f);
+ f = f2;
}
- if( s->fname ) {
- cdk_free( s->fname );
- s->fname = NULL;
+
+ if (s->fname)
+ {
+ cdk_free (s->fname);
+ s->fname = NULL;
}
- cdk_free( s );
- return rc;
+
+ cdk_free (s);
+ return rc;
}
@@ -338,30 +448,32 @@ cdk_stream_close( cdk_stream_t s )
* This function will only work with read streams.
**/
int
-cdk_stream_eof( cdk_stream_t s )
+cdk_stream_eof (cdk_stream_t s)
{
- return s? s->flags.eof : -1;
+ return s? s->flags.eof : -1;
}
-const char *
-_cdk_stream_get_fname( cdk_stream_t s )
+const char*
+_cdk_stream_get_fname (cdk_stream_t s)
{
- return s? s->fname : NULL;
+ return s? s->fname : NULL;
}
-FILE *
-_cdk_stream_get_fp( cdk_stream_t s )
+/* Return the underlying FP of the stream.
+ WARNING: This handle should not be closed. */
+FILE*
+_cdk_stream_get_fp (cdk_stream_t s)
{
- return s? s->fp : NULL;
+ return s? s->fp : NULL;
}
int
-_cdk_stream_get_errno( cdk_stream_t s )
+_cdk_stream_get_errno (cdk_stream_t s)
{
- return s? s->error : CDK_Inv_Value;
+ return s? s->error : CDK_Inv_Value;
}
@@ -369,114 +481,127 @@ _cdk_stream_get_errno( cdk_stream_t s )
* cdk_stream_get_length: Return the length of the associated file handle.
* @s: The STREAM object.
*
- * This file only works for read stream because it's likely that the
- * write stream is not flushed or even no data was inserted.
+ * This function should work for both read and write streams. For write
+ * streams an additional flush is used to write possible pending data.
**/
-unsigned
-cdk_stream_get_length( cdk_stream_t s )
+off_t
+cdk_stream_get_length (cdk_stream_t s)
{
- struct stat statbuf;
- int rc;
-
- if( !s )
- return (unsigned)-1;
-
- rc = stream_flush( s );
- if( rc ) {
- s->error = CDK_File_Error;
- return (unsigned)-1;
+ struct stat statbuf;
+ cdk_error_t rc;
+
+ if (!s)
+ return (off_t)-1;
+
+ /* The user callback does not support stat. */
+ if (s->cbs_hd)
+ return 0;
+
+ rc = stream_flush (s);
+ if (rc)
+ {
+ s->error = rc;
+ return (off_t)-1;
}
- if( fstat( fileno( s->fp ), &statbuf ) ) {
- s->error = CDK_File_Error;
- return (unsigned)-1;
+
+ if (fstat (fileno (s->fp), &statbuf))
+ {
+ s->error = CDK_File_Error;
+ return (off_t)-1;
}
- return statbuf.st_size;
+
+ return statbuf.st_size;
}
-static struct stream_filter_s *
-filter_add2( cdk_stream_t s )
+static struct stream_filter_s*
+filter_add2 (cdk_stream_t s)
{
- struct stream_filter_s * f;
-
- assert( s );
-
- f = cdk_calloc( 1, sizeof *f );
- if( !f )
- return NULL;
- f->next = s->filters;
- s->filters = f;
- return f;
+ struct stream_filter_s *f;
+
+ assert (s);
+
+ f = cdk_calloc (1, sizeof *f);
+ if (!f)
+ return NULL;
+ f->next = s->filters;
+ s->filters = f;
+ return f;
}
static struct stream_filter_s *
-filter_search( cdk_stream_t s, filter_fnct_t fnc )
+filter_search (cdk_stream_t s, filter_fnct_t fnc)
{
- struct stream_filter_s * f;
-
- assert( s );
-
- for( f = s->filters; f; f = f->next ) {
- if( f->fnct == fnc )
- return f;
+ struct stream_filter_s * f;
+
+ assert (s);
+
+ for( f = s->filters; f; f = f->next )
+ {
+ if (f->fnct == fnc)
+ return f;
}
- return NULL;
+
+ return NULL;
}
-struct stream_filter_s *
-filter_add( cdk_stream_t s, filter_fnct_t fnc, int type )
+struct stream_filter_s*
+filter_add (cdk_stream_t s, filter_fnct_t fnc, int type)
{
- struct stream_filter_s * f;
-
- assert( s );
+ struct stream_filter_s *f;
+
+ assert (s);
- s->flags.filtrated = 0;
- f = filter_search( s, fnc );
- if( f )
- return f;
- f = filter_add2( s );
- if( !f )
- return NULL;
- f->fnct = fnc;
- f->flags.enabled = 1;
- f->tmp = NULL;
- f->type = type;
- switch( type ) {
- case fARMOR : f->opaque = &f->u.afx; break;
- case fCIPHER : f->opaque = &f->u.cfx; break;
- case fLITERAL: f->opaque = &f->u.pfx; break;
- case fCOMPRESS : f->opaque = &f->u.zfx; break;
- case fHASH : f->opaque = &f->u.mfx; break;
- case fTEXT : f->opaque = &f->u.tfx; break;
- default : f->opaque = NULL;
- }
+ s->flags.filtrated = 0;
+ f = filter_search (s, fnc);
+ if (f)
return f;
+ f = filter_add2 (s);
+ if (!f)
+ return NULL;
+ f->fnct = fnc;
+ f->flags.enabled = 1;
+ f->tmp = NULL;
+ f->type = type;
+ switch (type)
+ {
+ case fARMOR : f->opaque = &f->u.afx; break;
+ case fCIPHER : f->opaque = &f->u.cfx; break;
+ case fLITERAL : f->opaque = &f->u.pfx; break;
+ case fCOMPRESS: f->opaque = &f->u.zfx; break;
+ case fHASH : f->opaque = &f->u.mfx; break;
+ case fTEXT : f->opaque = &f->u.tfx; break;
+ default : f->opaque = NULL;
+ }
+
+ return f;
}
static int
-stream_get_mode( cdk_stream_t s )
+stream_get_mode (cdk_stream_t s)
{
- assert( s );
-
- if( s->flags.temp )
- return s->fmode;
- return s->flags.write;
+ assert (s);
+
+ if (s->flags.temp)
+ return s->fmode;
+ return s->flags.write;
}
static filter_fnct_t
-stream_id_to_filter( int type )
+stream_id_to_filter (int type)
{
- switch( type ) {
- case fARMOR : return _cdk_filter_armor;
- case fLITERAL: return _cdk_filter_literal;
- case fTEXT : return _cdk_filter_text;
- case fCIPHER : return _cdk_filter_cipher;
- case fCOMPRESS : return _cdk_filter_compress;
- default : return NULL;
+ switch (type)
+ {
+ case fARMOR : return _cdk_filter_armor;
+ case fLITERAL : return _cdk_filter_literal;
+ case fTEXT : return _cdk_filter_text;
+ case fCIPHER : return _cdk_filter_cipher;
+ case fCOMPRESS: return _cdk_filter_compress;
+ default : return NULL;
}
}
@@ -488,47 +613,53 @@ stream_id_to_filter( int type )
*
**/
cdk_error_t
-cdk_stream_filter_disable( cdk_stream_t s, int type )
+cdk_stream_filter_disable (cdk_stream_t s, int type)
{
- struct stream_filter_s * f;
- filter_fnct_t fnc;
-
- if( !s )
- return CDK_Inv_Value;
- fnc = stream_id_to_filter( type );
- f = filter_search( s, fnc );
- if( f )
- f->flags.enabled = 0;
- return 0;
+ struct stream_filter_s *f;
+ filter_fnct_t fnc;
+
+ if (!s)
+ return CDK_Inv_Value;
+
+ fnc = stream_id_to_filter (type);
+ if (!fnc)
+ return CDK_Inv_Value;
+ f = filter_search (s, fnc);
+ if (f)
+ f->flags.enabled = 0;
+ return 0;
}
-static int
-stream_fp_replace( cdk_stream_t s, FILE ** tmp )
+/* WARNING: tmp should not be closed by the caller. */
+static cdk_error_t
+stream_fp_replace (cdk_stream_t s, FILE **tmp)
{
- int rc;
-
- assert( s );
+ int rc;
- rc = fclose( s->fp );
- if( rc )
- return CDK_File_Error;
- s->fp = *tmp;
- *tmp = NULL;
- return 0;
+ assert (s);
+
+ _cdk_log_debug ("replace stream fd=%d with fd=%d\n",
+ fileno (s->fp), fileno (*tmp));
+ rc = fclose (s->fp);
+ if (rc)
+ return CDK_File_Error;
+ s->fp = *tmp;
+ *tmp = NULL;
+ return 0;
}
/* This function is exactly like filter_read, except the fact that we can't
use tmpfile () all the time. That's why we open the real file when there
is no last filter. */
-static int
-stream_filter_write( cdk_stream_t s )
+static cdk_error_t
+stream_filter_write (cdk_stream_t s)
{
struct stream_filter_s * f;
- int rc = 0;
+ cdk_error_t rc = 0;
- assert( s );
+ assert (s);
if( s->flags.filtrated )
return CDK_Inv_Value;
@@ -556,12 +687,13 @@ stream_filter_write( cdk_stream_t s )
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 );
+ _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;
}
@@ -575,69 +707,86 @@ stream_filter_write( cdk_stream_t s )
Create a tempfile and use it for the output of the filter. Then the
original file handle will be closed and replace with the temp handle.
The file pointer will be set to the begin and the game starts again. */
-static int
-stream_filter_read( cdk_stream_t s )
+static cdk_error_t
+stream_filter_read (cdk_stream_t s)
{
- struct stream_filter_s * f;
- int rc = 0;
+ struct stream_filter_s *f;
+ cdk_error_t rc = 0;
- assert( s );
-
- if( s->flags.filtrated )
- return 0;
-
- for( f = s->filters; f; f = f->next ) {
- if( !f->flags.enabled )
- continue;
- f->tmp = tmpfile( );
- if( !f->tmp ) {
- rc = CDK_File_Error;
- break;
+ assert (s);
+
+ if (s->flags.filtrated)
+ return 0;
+
+ for (f = s->filters; f; f = f->next)
+ {
+ if (!f->flags.enabled)
+ continue;
+ if (f->flags.error)
+ {
+ _cdk_log_debug ("filter %s [read]: has the error flag; skipped\n",
+ s->fname? s->fname: "[temp]");
+ continue;
+ }
+
+ f->tmp = tmpfile ();
+ if (!f->tmp)
+ {
+ rc = CDK_File_Error;
+ break;
}
- rc = f->fnct( f->opaque, f->ctl, s->fp, f->tmp );
- _cdk_log_debug( "filter %s [read]: type=%d rc=%d\n",
- s->fname? s->fname : "[temp]", f->type, rc );
- if( rc )
- break;
+ rc = f->fnct (f->opaque, f->ctl, s->fp, f->tmp);
+ _cdk_log_debug ("filter %s [read]: type=%d rc=%d\n",
+ s->fname? s->fname : "[temp]", f->type, rc);
+ if (rc)
+ {
+ f->flags.error = 1;
+ break;
+ }
- /* if the filter is read-only, do not replace the FP because
- the contents were not altered in any way. */
- if( !f->flags.rdonly ) {
- rc = stream_fp_replace( s, &f->tmp );
- if( rc )
- break;
+ f->flags.error = 0;
+ /* If the filter is read-only, do not replace the FP because
+ the contents were not altered in any way. */
+ if (!f->flags.rdonly)
+ {
+ rc = stream_fp_replace (s, &f->tmp);
+ if (rc)
+ break;
}
- else {
- fclose( f->tmp );
- f->tmp = NULL;
+ else
+ {
+ fclose (f->tmp);
+ f->tmp = NULL;
}
- rc = cdk_stream_seek( s, 0 );
- if( rc )
- break;
- /* Disable the filter after it was successfully used. The idea
- is the following: let's say the armor filter was pushed and
- later more filters were added. The second time the filter code
- will be executed, only the new filter should be started but
- not the old because we already used it. */
- f->flags.enabled = 0;
+ rc = cdk_stream_seek (s, 0);
+ if (rc)
+ break;
+ /* Disable the filter after it was successfully used. The idea
+ is the following: let's say the armor filter was pushed and
+ later more filters were added. The second time the filter code
+ will be executed, only the new filter should be started but
+ not the old because we already used it. */
+ f->flags.enabled = 0;
}
- return rc;
+
+ return rc;
}
-void *
-_cdk_stream_get_opaque( cdk_stream_t s, int fid )
+void*
+_cdk_stream_get_opaque (cdk_stream_t s, int fid)
{
- struct stream_filter_s * f;
-
- if( !s )
- return NULL;
-
- for( f = s->filters; f; f = f->next ) {
- if( f->type == fid )
- return f->opaque;
- }
+ struct stream_filter_s * f;
+
+ if (!s)
return NULL;
+
+ for (f = s->filters; f; f = f->next)
+ {
+ if (f->type == fid)
+ return f->opaque;
+ }
+ return NULL;
}
@@ -652,51 +801,62 @@ _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 count)
{
- int nread;
- int rc;
-
- if( !s )
- return EOF;
+ int nread;
+ int rc;
+
+ if (!s)
+ return EOF;
+
+ if (s->cbs_hd)
+ {
+ if (s->cbs.read)
+ return s->cbs.read (s->cbs_hd, buf, count);
+ return 0;
+ }
- if( s->flags.write && !s->flags.temp )
- return EOF; /* this is a write stream */
+ if (s->flags.write && !s->flags.temp)
+ return EOF; /* this is a write stream */
- if( !s->flags.no_filter && !s->cache.on && !s->flags.filtrated ) {
- rc = stream_filter_read( s );
- if( rc ) {
- s->error = rc;
- return EOF;
- }
- s->flags.filtrated = 1;
+ if (!s->flags.no_filter && !s->cache.on && !s->flags.filtrated)
+ {
+ rc = stream_filter_read (s);
+ if (rc)
+ {
+ s->error = rc;
+ if (feof (s->fp))
+ s->flags.eof = 1;
+ return EOF;
+ }
+ s->flags.filtrated = 1;
}
- if( !buf && !count )
- return 0;
- nread = fread( buf, 1, count, s->fp );
- if( !nread )
- nread = EOF;
- if( feof( s->fp ) )
- s->flags.eof = 1;
- return nread;
+ if (!buf && !count)
+ return 0;
+ nread = fread (buf, 1, count, s->fp);
+ if (!nread)
+ nread = EOF;
+ if (feof (s->fp))
+ s->flags.eof = 1;
+ return nread;
}
int
-cdk_stream_getc( cdk_stream_t s )
+cdk_stream_getc (cdk_stream_t s)
{
- unsigned char buf[2];
- int nread;
-
- if( !s )
- return EOF;
-
- nread = cdk_stream_read( s, buf, 1 );
- if( nread == EOF ) {
- s->error = CDK_File_Error;
- return EOF;
+ unsigned char buf[2];
+ int nread;
+
+ if (!s)
+ return EOF;
+ nread = cdk_stream_read (s, buf, 1);
+ if (nread == EOF)
+ {
+ s->error = CDK_File_Error;
+ return EOF;
}
- return buf[0];
+ return buf[0];
}
@@ -711,293 +871,347 @@ cdk_stream_getc( cdk_stream_t s )
* partial flushing.
**/
int
-cdk_stream_write( cdk_stream_t s, const void * buf, size_t count )
+cdk_stream_write (cdk_stream_t s, const void * buf, size_t count)
{
- int nwritten;
+ int nwritten;
- if( !s )
- return CDK_Inv_Value;
-
- if( !s->flags.write )
- return CDK_Inv_Mode; /* this is a read stream */
-
- if( !buf && !count )
- return stream_flush( s );
-
- if( s->cache.on ) {
- if( s->cache.size + count > sizeof( s->cache.buf ) )
- return CDK_EOF;
- memcpy( s->cache.buf + s->cache.size, buf, count );
- s->cache.size += count;
- return 0;
+ if (!s)
+ return EOF;
+
+ if (s->cbs_hd)
+ {
+ if (s->cbs.write)
+ return s->cbs.write (s->cbs_hd, buf, count);
+ return 0;
+ }
+
+ if (!s->flags.write)
+ {
+ s->error = CDK_Inv_Mode; /* this is a read stream */
+ return EOF;
+ }
+
+ if (!buf && !count)
+ return stream_flush (s);
+
+ if (s->cache.on)
+ {
+ if (s->cache.size + count > DIM (s->cache.buf))
+ return EOF;
+ memcpy (s->cache.buf + s->cache.size, buf, count);
+ s->cache.size += count;
+ return count;
}
- nwritten = fwrite( buf, 1, count, s->fp );
- if( !nwritten )
- nwritten = EOF;
- return nwritten;
+ nwritten = fwrite (buf, 1, count, s->fp);
+ if (!nwritten)
+ nwritten = EOF;
+ return nwritten;
}
int
-cdk_stream_putc( cdk_stream_t s, int c )
+cdk_stream_putc (cdk_stream_t s, int c)
{
- unsigned char buf[2];
- int nwritten;
-
- if( !s )
- return EOF;
- buf[0] = c;
- nwritten = cdk_stream_write( s, buf, 1 );
- if( nwritten == EOF ) {
- s->error = CDK_File_Error;
- return EOF;
- }
- return 0;
+ byte buf[2];
+ int nwritten;
+
+ if (!s)
+ return EOF;
+ buf[0] = c;
+ nwritten = cdk_stream_write (s, buf, 1);
+ if (nwritten == EOF)
+ return EOF;
+ return 0;
}
-long
-cdk_stream_tell( cdk_stream_t s )
-{
- return s? ftell( s->fp ): (long)-1;
+off_t
+cdk_stream_tell (cdk_stream_t s)
+{
+ return s? ftell (s->fp): (off_t)-1;
}
cdk_error_t
-cdk_stream_seek( cdk_stream_t s, long offset )
+cdk_stream_seek (cdk_stream_t s, off_t offset)
{
- int rc;
-
- if( !s )
- return CDK_Inv_Value;
- if( offset < cdk_stream_get_length( s ) )
- s->flags.eof = 0;
- rc = fseek( s->fp, offset, SEEK_SET );
- if( rc )
- rc = CDK_File_Error;
- return rc;
+ cdk_error_t rc;
+
+ if (!s)
+ return CDK_Inv_Value;
+
+ if (s->cbs_hd)
+ {
+ if (s->cbs.seek)
+ return s->cbs.seek (s->cbs_hd, offset);
+ return 0;
+ }
+
+ if (offset < cdk_stream_get_length (s))
+ s->flags.eof = 0;
+ rc = fseek (s->fp, offset, SEEK_SET);
+ if (rc)
+ rc = CDK_File_Error;
+ return rc;
}
-static int
-stream_flush( cdk_stream_t s )
+static cdk_error_t
+stream_flush (cdk_stream_t s)
{
- int rc;
-
- assert( s );
-
- rc = fflush( s->fp );
- if( rc )
- rc = CDK_File_Error;
- return rc;
+ assert (s);
+
+ if (fflush (s->fp))
+ return CDK_File_Error;
+ return 0;
}
cdk_error_t
-cdk_stream_set_armor_flag( cdk_stream_t s, int type )
+cdk_stream_set_armor_flag (cdk_stream_t s, int type)
{
- struct stream_filter_s * f;
-
- if( !s )
- return CDK_Inv_Value;
- f = filter_add( s, _cdk_filter_armor, fARMOR );
- if( !f )
- return CDK_Out_Of_Core;
- f->u.afx.idx = f->u.afx.idx2 = type;
- f->ctl = stream_get_mode( s );
- return 0;
+ struct stream_filter_s *f;
+
+ if (!s)
+ return CDK_Inv_Value;
+ f = filter_add (s, _cdk_filter_armor, fARMOR);
+ if (!f)
+ return CDK_Out_Of_Core;
+ f->u.afx.idx = f->u.afx.idx2 = type;
+ f->ctl = stream_get_mode (s);
+ return 0;
}
cdk_error_t
cdk_stream_set_literal_flag( cdk_stream_t s, int mode, const char * fname )
{
- struct stream_filter_s * f;
-
- if( !s )
- return CDK_Inv_Value;
- 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->ctl = stream_get_mode( s );
- if( s->blkmode ) {
- f->u.pfx.blkmode.on = 1;
- f->u.pfx.blkmode.size = s->blkmode;
+ struct stream_filter_s * f;
+
+ if (!s)
+ return CDK_Inv_Value;
+ 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->ctl = stream_get_mode (s);
+ if (s->blkmode)
+ {
+ f->u.pfx.blkmode.on = 1;
+ f->u.pfx.blkmode.size = s->blkmode;
}
- return 0;
+ return 0;
}
cdk_error_t
cdk_stream_set_cipher_flag( cdk_stream_t s, cdk_dek_t dek, int use_mdc )
{
- struct stream_filter_s * f;
-
- if( !s )
- return CDK_Inv_Value;
- f = filter_add( s, _cdk_filter_cipher, fCIPHER );
- 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 ) {
- f->u.cfx.blkmode.on = 1;
- f->u.cfx.blkmode.size = s->blkmode;
+ struct stream_filter_s * f;
+
+ if (!s)
+ return CDK_Inv_Value;
+ f = filter_add (s, _cdk_filter_cipher, fCIPHER);
+ 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)
+ {
+ f->u.cfx.blkmode.on = 1;
+ f->u.cfx.blkmode.size = s->blkmode;
}
- return 0;
+ return 0;
}
cdk_error_t
-cdk_stream_set_compress_flag( cdk_stream_t s, int algo, int level )
+cdk_stream_set_compress_flag (cdk_stream_t s, int algo, int level)
{
- struct stream_filter_s * f;
-
- if( !s )
- return CDK_Inv_Value;
- f = filter_add( s, _cdk_filter_compress, fCOMPRESS );
- if( !f )
- return CDK_Out_Of_Core;
- f->ctl = stream_get_mode( s );
- f->u.zfx.algo = algo;
- f->u.zfx.level = level;
- return 0;
+ struct stream_filter_s *f;
+
+ if (!s)
+ return CDK_Inv_Value;
+ f = filter_add (s, _cdk_filter_compress, fCOMPRESS);
+ if (!f)
+ return CDK_Out_Of_Core;
+ f->ctl = stream_get_mode (s);
+ f->u.zfx.algo = algo;
+ f->u.zfx.level = level;
+ return 0;
}
cdk_error_t
-cdk_stream_set_text_flag( cdk_stream_t s, const char * lf )
+cdk_stream_set_text_flag (cdk_stream_t s, const char *lf)
{
- struct stream_filter_s * f;
-
- if( !s )
- return CDK_Inv_Value;
- f = filter_add( s, _cdk_filter_text, fTEXT );
- if( !f )
- return CDK_Out_Of_Core;
- f->ctl = stream_get_mode( s );
- f->u.tfx.lf = lf;
- return 0;
+ struct stream_filter_s *f;
+
+ if (!s)
+ return CDK_Inv_Value;
+ f = filter_add (s, _cdk_filter_text, fTEXT);
+ if (!f)
+ return CDK_Out_Of_Core;
+ 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 algo)
{
- struct stream_filter_s * f;
-
- if( !s )
- return CDK_Inv_Value;
- if( stream_get_mode( s ) )
- return CDK_Inv_Mode;
- f = filter_add( s, _cdk_filter_hash, fHASH );
- if( !f )
- return CDK_Out_Of_Core;
- f->ctl = stream_get_mode( s );
- f->u.mfx.digest_algo = algo;
- f->flags.rdonly = 1;
- return 0;
+ struct stream_filter_s * f;
+
+ if (!s)
+ return CDK_Inv_Value;
+ if (stream_get_mode (s))
+ return CDK_Inv_Mode;
+ f = filter_add (s, _cdk_filter_hash, fHASH);
+ if (!f)
+ return CDK_Out_Of_Core;
+ f->ctl = stream_get_mode (s);
+ f->u.mfx.digest_algo = algo;
+ f->flags.rdonly = 1;
+ return 0;
}
+/**
+ * cdk_stream_enable_cache:
+ * @s: the stream object
+ * @val: 1=on, 0=off
+ *
+ * Enable or disable the cache section of a stream object.
+ **/
cdk_error_t
-cdk_stream_set_cache( cdk_stream_t s, int val )
+cdk_stream_enable_cache (cdk_stream_t s, int val)
{
- if( !s )
- return CDK_Inv_Value;
- if( !s->flags.write )
- return CDK_Inv_Mode;
- s->cache.on = val;
- return 0;
+ if (!s)
+ return CDK_Inv_Value;
+ if (!s->flags.write)
+ return CDK_Inv_Mode;
+ s->cache.on = val;
+ return 0;
}
static int
-stream_cache_flush( cdk_stream_t s, FILE * fp )
+stream_cache_flush (cdk_stream_t s, FILE * fp)
{
- int nwritten;
-
- assert( s );
-
- if( s->cache.size > 0 ) {
- nwritten = fwrite( s->cache.buf, 1, s->cache.size, fp );
- if( !nwritten )
- return CDK_File_Error;
- s->cache.size = 0;
- s->cache.on = 0;
- memset( s->cache.buf, 0, sizeof s->cache.buf );
+ int nwritten;
+
+ assert (s);
+
+ /* FIXME: We should find a way to use cdk_stream_write here. */
+ if (s->cache.size > 0)
+ {
+ nwritten = fwrite (s->cache.buf, 1, s->cache.size, fp);
+ if (!nwritten)
+ return CDK_File_Error;
+ s->cache.size = 0;
+ s->cache.on = 0;
+ wipemem (s->cache.buf, sizeof s->cache.buf);
}
- return 0;
+ return 0;
}
+/**
+ * cdk_stream_kick_off:
+ * @inp: the input stream
+ * @out: the output stream.
+ *
+ * Passes the entire data from @inp into the output stream @out
+ * with all the activated filters.
+ */
cdk_error_t
-cdk_stream_kick_off( cdk_stream_t inp, cdk_stream_t out )
+cdk_stream_kick_off (cdk_stream_t inp, cdk_stream_t out)
{
- byte buf[8192];
- int nread, nwritten;
- int rc = 0;
-
- if( !inp || !out )
- return CDK_Inv_Value;
- while( !cdk_stream_eof( inp ) ) {
- nread = cdk_stream_read( inp, buf, sizeof buf-1 );
- if( nread == EOF )
- break;
- nwritten = cdk_stream_write( out, buf, nread );
- if( nwritten == EOF )
- rc = CDK_File_Error;
+ byte buf[BUFSIZE];
+ int nread, nwritten;
+ cdk_error_t rc;
+
+ if (!inp || !out)
+ return CDK_Inv_Value;
+ rc = CDK_Success;
+ while (!cdk_stream_eof (inp))
+ {
+ nread = cdk_stream_read (inp, buf, DIM (buf));
+ if (!nread || nread == EOF)
+ break;
+ nwritten = cdk_stream_write (out, buf, nread);
+ if (!nwritten || nwritten == EOF)
+ { /* In case of errors, we leave the loop. */
+ rc = inp->error;
+ break;
+ }
}
- wipemem( buf, sizeof buf );
- return rc;
+
+ wipemem (buf, sizeof (buf));
+ return rc;
}
/**
- * cdk_stream_mmap:
+ * cdk_stream_mmap_part:
* @s: the stream
+ * @off: the offset where to start
+ * @len: how much bytes shall be mapped
* @ret_buf: the buffer to store the content
- * @ret_count: length of the buffer
+ * @ret_buflen: length of the buffer
*
* Map the data of the given stream into a memory section. @ret_count
* contains the length of the buffer.
**/
cdk_error_t
-cdk_stream_mmap( cdk_stream_t s, byte ** ret_buf, size_t * ret_count )
+cdk_stream_mmap_part (cdk_stream_t s, off_t off, size_t len,
+ byte **ret_buf, size_t *ret_buflen)
{
- const u32 max_filesize = 16777216;
- u32 len, oldpos;
- int n, rc;
- char * p;
+ off_t oldpos;
+ int n;
+ cdk_error_t rc;
+
+ if (!s || !ret_buf || !ret_buflen)
+ return CDK_Inv_Value;
+ if (s->cbs_hd)
+ return CDK_Inv_Mode;
+
+ *ret_buflen = 0;
+ *ret_buf = NULL;
+ oldpos = cdk_stream_tell (s);
+ rc = cdk_stream_flush (s);
+ if (!rc)
+ rc = cdk_stream_seek (s, off);
+ if (rc)
+ return rc;
+ if (!len)
+ len = cdk_stream_get_length (s);
+ if (!len || len > MAX_MAP_SIZE)
+ return 0;
+ *ret_buf = cdk_calloc (1, len+1);
+ *ret_buflen = len;
+ n = cdk_stream_read (s, *ret_buf, len);
+ if (n != len)
+ *ret_buflen = n;
+ rc = cdk_stream_seek (s, oldpos);
+ return rc;
+}
- if( !s || !ret_buf || !ret_count )
- return CDK_Inv_Value;
- *ret_count = 0;
- *ret_buf = NULL;
- oldpos = cdk_stream_tell( s );
- rc = cdk_stream_flush( s );
- if( !rc )
- rc = cdk_stream_seek( s, 0 );
- if( rc )
- return rc;
- len = cdk_stream_get_length( s );
- if( !len || len > max_filesize )
- return 0;
- p = *ret_buf = cdk_calloc( 1, len+1 );
- if( !p )
- return 0;
- *ret_count = len;
- n = cdk_stream_read( s, p, len );
- if( n != len )
- *ret_count = n;
- rc = cdk_stream_seek( s, oldpos );
- return rc;
+cdk_error_t
+cdk_stream_mmap (cdk_stream_t inp, byte **buf, size_t *buflen)
+{
+ off_t len;
+
+ /* We need to make sure all data is flushed before we retrieve the size. */
+ cdk_stream_flush (inp);
+ len = cdk_stream_get_length (inp);
+ return cdk_stream_mmap_part (inp, 0, len, buf, buflen);
}
@@ -1011,63 +1225,73 @@ cdk_stream_mmap( cdk_stream_t s, byte ** ret_buf, size_t * ret_count )
* 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 *s, size_t count)
{
- unsigned off;
- int nbytes, rc;
-
- if( !inp || !s )
- return CDK_Inv_Value;
- off = cdk_stream_tell( inp );
- nbytes = _cdk_stream_gets( inp, s, count );
- rc = cdk_stream_seek( inp, off );
- if( rc )
- return 0;
- return nbytes;
+ off_t off;
+ int nbytes;
+
+ if (!inp || !s)
+ return 0;
+ if (inp->cbs_hd)
+ return 0;
+
+ off = cdk_stream_tell (inp);
+ nbytes = _cdk_stream_gets (inp, (char*)s, count);
+ if (nbytes == -1)
+ return 0;
+ if (cdk_stream_seek (inp, off))
+ return 0;
+ return nbytes;
}
+/* Try to read a line from the given stream. */
int
-_cdk_stream_gets( cdk_stream_t s, char * buf, size_t count )
+_cdk_stream_gets (cdk_stream_t s, char * buf, size_t count)
{
- int c, i = 0;
-
- if( !s )
- return CDK_Inv_Value;
- while( !cdk_stream_eof( s ) && count > 0 ) {
- c = cdk_stream_getc( s );
- if( c == EOF || c == '\r' || c == '\n' ) {
- buf[i++] = '\0';
- break;
- }
- buf[i++] = c;
- count--;
+ int c, i;
+
+ assert (s);
+
+ i = 0;
+ while (!cdk_stream_eof (s) && count > 0)
+ {
+ c = cdk_stream_getc (s);
+ if (c == EOF || c == '\r' || c == '\n' )
+ {
+ buf[i++] = '\0';
+ break;
+ }
+ buf[i++] = c;
+ count--;
}
- return i;
+ return i;
}
+/* Try to write string into the stream @s. */
int
-_cdk_stream_puts( cdk_stream_t s, const char * buf )
+_cdk_stream_puts (cdk_stream_t s, const char *buf)
{
- return cdk_stream_write( s, buf, strlen( buf ) );
+ return cdk_stream_write (s, buf, strlen (buf));
}
-int
-_cdk_stream_set_blockmode( cdk_stream_t s, size_t nbytes )
+/* Activate the block mode for the given stream. */
+cdk_error_t
+_cdk_stream_set_blockmode (cdk_stream_t s, size_t nbytes)
{
- if( !s )
- return CDK_Inv_Value;
- _cdk_log_debug( "set block mode for stream (size=%d)\n", nbytes );
- s->blkmode = nbytes;
- return 0;
+ assert (s);
+
+ _cdk_log_debug ("set block mode for stream; blocksize %d\n", nbytes);
+ s->blkmode = nbytes;
+ return 0;
}
+/* Return the block mode state of the given stream. */
int
-_cdk_stream_get_blockmode( cdk_stream_t s )
+_cdk_stream_get_blockmode (cdk_stream_t s)
{
- return s? s->blkmode : 0;
+ return s? s->blkmode : 0;
}
-
diff --git a/libextra/opencdk/stream.h b/libextra/opencdk/stream.h
index 1a485f2b34..ef1d1c725b 100644
--- a/libextra/opencdk/stream.h
+++ b/libextra/opencdk/stream.h
@@ -1,6 +1,5 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * stream.h - internal definiton for the STREAM object
- * Copyright (C) 2002, 2003 Timo Schulz
+/* stream.h - internal definiton for the STREAM object
+ * Copyright (C) 2002, 2003, 2007 Timo Schulz
*
* This file is part of OpenCDK.
*
@@ -13,70 +12,76 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
#ifndef CDK_STREAM_H
#define CDK_STREAM_H
+/* The default buffer size for the stream. */
+#define STREAM_BUFSIZE 8192
+
enum {
- fDUMMY = 0,
- fARMOR = 1,
- fCIPHER = 2,
+ fDUMMY = 0,
+ fARMOR = 1,
+ fCIPHER = 2,
fLITERAL = 3,
fCOMPRESS= 4,
fHASH = 5,
fTEXT = 6
};
+/* Type definition for the filter function. */
typedef int (*filter_fnct_t) (void * opaque, int ctl, FILE * in, FILE * out);
-struct stream_filter_s {
- struct stream_filter_s * next;
- filter_fnct_t fnct;
- void * opaque;
- FILE * tmp;
- union {
- armor_filter_t afx;
- cipher_filter_t cfx;
- literal_filter_t pfx;
- compress_filter_t zfx;
- text_filter_t tfx;
- md_filter_t mfx;
- } u;
- struct {
- unsigned enabled:1;
- unsigned rdonly:1;
- } flags;
- unsigned type;
- unsigned ctl;
+/* The stream filter context structure. */
+struct stream_filter_s
+{
+ struct stream_filter_s *next;
+ filter_fnct_t fnct;
+ void *opaque;
+ FILE *tmp;
+ union {
+ armor_filter_t afx;
+ cipher_filter_t cfx;
+ literal_filter_t pfx;
+ compress_filter_t zfx;
+ text_filter_t tfx;
+ md_filter_t mfx;
+ } u;
+ struct {
+ unsigned enabled:1;
+ unsigned rdonly:1;
+ unsigned error:1;
+ } flags;
+ unsigned type;
+ unsigned ctl;
};
+/* The stream context structure. */
struct cdk_stream_s {
- struct stream_filter_s * filters;
- int fmode;
- int error;
- size_t blkmode;
- struct {
- unsigned filtrated:1;
- unsigned eof:1;
- unsigned write:1;
- unsigned temp:1;
- unsigned reset:1;
- unsigned no_filter:1;
- unsigned compressed:3;
- } flags;
- struct {
- unsigned char buf[8192];
- unsigned on:1;
- size_t size;
- } cache;
- char * fname;
- FILE * fp;
+ struct stream_filter_s *filters;
+ int fmode;
+ int error;
+ size_t blkmode;
+ struct {
+ unsigned filtrated:1;
+ unsigned eof:1;
+ unsigned write:1;
+ unsigned temp:1;
+ unsigned reset:1;
+ unsigned no_filter:1;
+ unsigned compressed:3;
+ } flags;
+ struct {
+ unsigned char buf[STREAM_BUFSIZE];
+ unsigned on:1;
+ off_t size;
+ } cache;
+ char *fname;
+ FILE *fp;
+ unsigned int fp_ref:1;
+ struct cdk_stream_cbs_s cbs;
+ void *cbs_hd;
};
#endif /* CDK_STREAM_H */
diff --git a/libextra/opencdk/sym-cipher.c b/libextra/opencdk/sym-cipher.c
deleted file mode 100644
index 5405b89a16..0000000000
--- a/libextra/opencdk/sym-cipher.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * sym-cipher.c
- * Copyright (C) 2003 Timo Schulz
- *
- * This file is part of OpenCDK.
- *
- * OpenCDK is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * OpenCDK is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-
-#include <stdio.h>
-#include <string.h>
-#include "opencdk.h"
-#include "main.h"
-#include "cipher.h"
-
-
-struct cdk_cipher_hd_s {
- gcry_cipher_hd_t hd;
- int algo;
-};
-
-inline
-static int cdk_cipher_to_gcry( int algo)
-{
- switch( algo ) {
- case CDK_CIPHER_BLOWFISH: return GCRY_CIPHER_BLOWFISH;
- case CDK_CIPHER_TWOFISH: return GCRY_CIPHER_TWOFISH;
- case CDK_CIPHER_3DES: return GCRY_CIPHER_3DES;
- case CDK_CIPHER_CAST5: return GCRY_CIPHER_CAST5;
- case CDK_CIPHER_AES: return GCRY_CIPHER_AES;
- case CDK_CIPHER_AES192: return GCRY_CIPHER_AES192;
- case CDK_CIPHER_AES256: return GCRY_CIPHER_AES256;
- default: return -1;
- }
-}
-
-cdk_cipher_hd_t
-cdk_cipher_new( int algo, int pgp_sync )
-{
- cdk_cipher_hd_t hd;
- unsigned int flags = 0;
- gcry_error_t err;
-
- if( cdk_cipher_test_algo( algo ) )
- return NULL;
- hd = cdk_calloc( 1, sizeof * hd );
- if( !hd )
- return NULL;
-
- if( pgp_sync )
- flags = GCRY_CIPHER_ENABLE_SYNC;
-
- hd->algo = algo;
-
- err = gcry_cipher_open( &hd->hd, cdk_cipher_to_gcry(algo),
- GCRY_CIPHER_MODE_CFB, flags);
- if( err ) {
- cdk_free( hd );
- return NULL;
- }
- return hd;
-}
-
-
-cdk_cipher_hd_t
-cdk_cipher_open( int algo, int pgp_sync,
- const byte * key, size_t keylen,
- const byte * ivbuf, size_t ivlen )
-{
- cdk_cipher_hd_t hd;
- gcry_error_t err;
-
- hd = cdk_cipher_new( algo, pgp_sync );
- if( hd ) {
- err = gcry_cipher_setkey( hd->hd, key, keylen );
- if( !err)
- err = gcry_cipher_setiv( hd->hd, ivbuf, ivlen );
- if( err) {
- cdk_cipher_close( hd );
- hd = NULL;
- }
- }
- return hd;
-}
-
-
-void
-cdk_cipher_close( cdk_cipher_hd_t hd )
-{
- if( !hd )
- return;
- gcry_cipher_close( hd->hd);
- cdk_free( hd );
-}
-
-
-int
-cdk_cipher_decrypt( cdk_cipher_hd_t hd, byte * outbuf, const byte *inbuf,
- size_t nbytes )
-{
-gcry_error_t err;
-
- if( !hd )
- return CDK_Inv_Value;
- err = gcry_cipher_decrypt( hd->hd, outbuf, nbytes, inbuf, nbytes);
-
- if (err) return CDK_Gcry_Error;
- else return 0;
-}
-
-
-int
-cdk_cipher_encrypt( cdk_cipher_hd_t hd, byte * outbuf, const byte *inbuf,
- size_t nbytes )
-{
-gcry_error_t err;
-
- if( !hd )
- return CDK_Inv_Value;
- err = gcry_cipher_encrypt( hd->hd, outbuf, nbytes, inbuf, nbytes);
-
- if (err) return CDK_Gcry_Error;
- else return 0;
-}
-
-
-void
-cdk_cipher_sync( cdk_cipher_hd_t hd )
-{
- gcry_cipher_sync( hd->hd);
-}
-
-
-int
-cdk_cipher_setiv( cdk_cipher_hd_t hd, const byte *ivbuf, size_t ivlen )
-{
- if( !hd )
- return CDK_Inv_Value;
-
- gcry_cipher_setiv( hd->hd, ivbuf, ivlen);
- return 0;
-}
-
-
-int
-cdk_cipher_setkey( cdk_cipher_hd_t hd, const byte *keybuf, size_t keylen )
-{
- if( !hd )
- return CDK_Inv_Value;
-
- gcry_cipher_setkey( hd->hd, keybuf, keylen);
- return 0;
-}
-
-
-int
-cdk_cipher_get_algo_blklen( int algo )
-{
- return gcry_cipher_get_algo_blklen( cdk_cipher_to_gcry( algo));
-}
-
-
-int
-cdk_cipher_get_algo_keylen( int algo )
-{
- return gcry_cipher_get_algo_keylen( cdk_cipher_to_gcry( algo));
-}
-
-
-int
-cdk_cipher_test_algo( int algo )
-{
- return gcry_cipher_test_algo( cdk_cipher_to_gcry( algo));
-}
diff --git a/libextra/opencdk/trustdb.c b/libextra/opencdk/trustdb.c
deleted file mode 100644
index 36d89e7a56..0000000000
--- a/libextra/opencdk/trustdb.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/* -*- Mode: C; c-file-style: "bsd" -*- */
-/* trustdb.c - High level interface for ownertrust handling
- * Copyright (C) 2001, 2002, 2003 Timo Schulz
- *
- * This file is part of OpenCDK.
- *
- * OpenCDK is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * OpenCDK is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include <stdio.h>
-
-#include "opencdk.h"
-#include "main.h"
-
-#define TRUST_MASK 15
-#define RECORD_SIZE 40
-#define MIN_TRUSTDB_VER 3
-
-
-enum {
- TDB_RECORD_TRUST = 12,
- TDB_RECORD_VALID = 13,
-};
-
-struct tdb_record_s {
- int recno;
- union {
- struct {
- byte reserved;
- byte fpr[20];
- int ownertrust;
- byte depth;
- u32 validlist;
- } trust;
- struct {
- byte reserved;
- byte fpr[20];
- u32 next;
- int valid;
- } valid;
- } u;
-};
-typedef struct tdb_record_s *tdb_record_t;
-
-
-static void
-trustdb_rec_release( tdb_record_t rec )
-{
- if( rec ) {
- rec->recno = 0;
- cdk_free( rec );
- }
-}
-
-
-static tdb_record_t
-trustdb_rec_new( void )
-{
- tdb_record_t rec;
-
- rec = cdk_calloc( 1, sizeof *rec );
- if( !rec )
- return NULL;
- return rec;
-}
-
-
-static int
-trustdb_check( cdk_stream_t a, int req_ver )
-{
- int rc = 0;
- int c = 0, nread;
- byte magic[3];
-
- cdk_stream_seek( a, 0 );
- c = cdk_stream_getc( a );
- if( c == EOF || c != 1 )
- return CDK_General_Error;
- nread = cdk_stream_read( a, magic, 3 );
- if( nread == EOF )
- return CDK_File_Error;
- c = cdk_stream_getc( a );
- if( c == EOF )
- rc = CDK_General_Error;
- else if( c < req_ver )
- rc = CDK_Wrong_Format;
- return rc;
-}
-
-
-static int
-trustdb_rec_parse( cdk_stream_t buf, tdb_record_t r )
-{
- size_t n;
- int recno;
-
- if( !buf || !r )
- return CDK_Inv_Value;
-
- recno = cdk_stream_getc( buf );
- if( recno == EOF )
- return EOF;
-
- switch( recno ) {
- case TDB_RECORD_TRUST: /* trust record: new */
- r->recno = 12;
- r->u.trust.reserved = cdk_stream_getc (buf);
- n = cdk_stream_read (buf, r->u.trust.fpr, 20);
- r->u.trust.ownertrust = cdk_stream_getc (buf);
- r->u.trust.depth = cdk_stream_getc (buf);
- r->u.trust.validlist = 0;
- n = 4;
- while (n--)
- cdk_stream_getc (buf);
- n = RECORD_SIZE - 28;
- while (n--)
- cdk_stream_getc (buf);
- if (r->u.trust.ownertrust == EOF)
- return CDK_EOF;
- break;
-
- case TDB_RECORD_VALID: /* valid record: new */
- r->recno = 13;
- r->u.valid.reserved = cdk_stream_getc (buf);
- n = cdk_stream_read (buf, r->u.valid.fpr, 20);
- r->u.valid.valid = cdk_stream_getc (buf);
- r->u.valid.next = 0;
- n = 4;
- while (n--)
- cdk_stream_getc (buf);
- n = RECORD_SIZE - 27;
- while (n--)
- cdk_stream_getc (buf);
- if (r->u.valid.valid == EOF)
- return CDK_EOF;
- break;
-
- default:
- n = RECORD_SIZE - 1;
- while (n--)
- cdk_stream_getc (buf);
- break;
- }
- r->recno = recno;
- return 0;
-}
-
-
-tdb_record_t
-trustdb_rec_byfpr( cdk_stream_t buf, int type,
- const byte * fpr, size_t fprlen )
-{
- tdb_record_t rec;
-
- if (!fpr || !buf)
- return NULL;
-
- rec = trustdb_rec_new ();
- if( !rec )
- return NULL;
-
- while( trustdb_rec_parse( buf, rec ) != EOF ) {
- if( rec->recno != type )
- continue;
- switch( type ) {
- case TDB_RECORD_VALID:
- if( !memcmp( fpr, rec->u.valid.fpr, fprlen ) )
- return rec;
- break;
-
- case TDB_RECORD_TRUST:
- if( !memcmp( rec->u.trust.fpr, fpr, fprlen ) )
- return rec;
- break;
- }
- }
- trustdb_rec_release ( rec );
- rec = NULL;
- return rec;
-}
-
-
-int
-cdk_trustdb_get_ownertrust( cdk_stream_t inp, cdk_pkt_pubkey_t pk,
- int *r_val, int *r_flags )
-{
- tdb_record_t rec = NULL;
- byte fpr[20];
- int flags = 0;
- int rc;
-
- if( !inp || !r_val || !r_flags || !pk )
- return CDK_Inv_Value;
-
- rc = trustdb_check( inp, MIN_TRUSTDB_VER );
- if( rc )
- return rc;
-
- *r_val = CDK_TRUST_UNKNOWN;
- cdk_pk_get_fingerprint( pk, fpr );
- cdk_stream_seek( inp, 0 );
-
- rec = trustdb_rec_byfpr( inp, TDB_RECORD_TRUST, fpr, 20 );
- if( rec ) {
- *r_val = rec->u.trust.ownertrust & TRUST_MASK;
- if( *r_val & CDK_TFLAG_REVOKED )
- flags |= CDK_TFLAG_REVOKED;
- if( *r_val & CDK_TFLAG_SUB_REVOKED )
- flags |= CDK_TFLAG_SUB_REVOKED;
- if( *r_val & CDK_TFLAG_DISABLED )
- flags |= CDK_TFLAG_DISABLED;
- *r_flags = flags;
- rc = 0;
- }
- trustdb_rec_release( rec );
- return rc;
-}
-
-
-int
-cdk_trustdb_get_validity( cdk_stream_t inp, cdk_pkt_userid_t id, int *r_val )
-{
- cdk_md_hd_t rmd;
- tdb_record_t rec;
- byte * fpr;
- int rc;
-
- if( !inp || !r_val || !id )
- return CDK_Inv_Value;
-
- rc = trustdb_check( inp, MIN_TRUSTDB_VER );
- if( rc )
- return rc;
-
- *r_val = CDK_TRUST_UNKNOWN;
- rmd = cdk_md_open( CDK_MD_RMD160, 0 );
- if( !rmd )
- return CDK_Gcry_Error;
-
- cdk_md_write( rmd, id->name, id->len );
- cdk_md_final( rmd );
- fpr = cdk_md_read( rmd, CDK_MD_RMD160 );
-
- cdk_stream_seek( inp, 0 );
- rec = trustdb_rec_byfpr( inp, TDB_RECORD_VALID, fpr, 20 );
- if( rec ) {
- *r_val = rec->u.valid.valid;
- rc = 0;
- }
-
- trustdb_rec_release( rec );
- cdk_md_close( rmd );
- return rc;
-}
diff --git a/libextra/opencdk/types.h b/libextra/opencdk/types.h
index 6b313b71a7..c53a0850ae 100644
--- a/libextra/opencdk/types.h
+++ b/libextra/opencdk/types.h
@@ -1,5 +1,5 @@
/* types.h - Some type definitions
- * Copyright (C) 2002 Timo Schulz
+ * Copyright (C) 2002, 2003, 2007 Timo Schulz
*
* This file is part of OpenCDK.
*
@@ -12,16 +12,11 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
#ifndef CDK_TYPES_H
#define CDK_TYPES_H
-#include <gcrypt.h> /*FIXME!*/
+#include <gcrypt.h>
#ifndef HAVE_BYTE_TYPEDEF
# undef byte
@@ -46,8 +41,4 @@
# define DIMof(type, member) DIM(((type *)0)->member)
#endif
-
-struct cdk_verify_result_s;
-typedef struct cdk_verify_result_s *_cdk_verify_result_t;
-
#endif /* CDK_TYPES_H */
diff --git a/libextra/opencdk/verify.c b/libextra/opencdk/verify.c
index 600b781ab5..3debeab879 100644
--- a/libextra/opencdk/verify.c
+++ b/libextra/opencdk/verify.c
@@ -1,6 +1,5 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * verify.c - Verify signatures
- * Copyright (C) 2001, 2002, 2003 Timo Schulz
+/* verify.c - Verify signatures
+ * Copyright (C) 2001, 2002, 2003, 2007 Timo Schulz
*
* This file is part of OpenCDK.
*
@@ -13,12 +12,7 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
@@ -32,279 +26,268 @@
#include "packet.h"
+/* Table of all supported digest algorithms and their names. */
struct {
const char *name;
int algo;
} digest_table[] = {
- {"MD5", CDK_MD_MD5},
- {"SHA1", CDK_MD_SHA1},
- {"RIPEMD160", CDK_MD_RMD160},
- {"MD2", CDK_MD_MD2},
- {"SHA256", CDK_MD_SHA256},
+ {"MD5", GCRY_MD_MD5},
+ {"SHA1", GCRY_MD_SHA1},
+ {"RIPEMD160", GCRY_MD_RMD160},
+ {"SHA256", GCRY_MD_SHA256},
+ {"SHA384", GCRY_MD_SHA384},
+ {"SHA512", GCRY_MD_SHA512},
{NULL, 0}
};
-static int file_verify_clearsign( cdk_ctx_t, const char *, const char * );
+static int file_verify_clearsign (cdk_ctx_t, const char *, const char *);
+/**
+ * cdk_stream_verify:
+ * @hd: session handle
+ * @inp: the input stream
+ * @data: for detached signatures, this is the data stream @inp is the sig
+ * @out: where the output shall be written.
+ */
cdk_error_t
-cdk_stream_verify( cdk_ctx_t hd, cdk_stream_t inp, cdk_stream_t out )
+cdk_stream_verify (cdk_ctx_t hd, cdk_stream_t inp, cdk_stream_t data,
+ cdk_stream_t out)
{
- if( cdk_armor_filter_use( inp ) )
- cdk_stream_set_armor_flag( inp, 0 );
- return _cdk_proc_packets( hd, inp, NULL, NULL, NULL );
+ /* FIXME: out is not currently used. */
+ if (cdk_armor_filter_use (inp))
+ cdk_stream_set_armor_flag (inp, 0);
+ return _cdk_proc_packets (hd, inp, data, NULL, NULL, NULL);
}
-
+
/**
* cdk_file_verify:
* @hd: the session handle
* @file: the input file
+ * @data_file: for detached signature this is the data file and @file is the sig.
* @output: the output file
*
* Verify a signature.
**/
cdk_error_t
-cdk_file_verify( cdk_ctx_t hd, const char * file, const char * output )
+cdk_file_verify (cdk_ctx_t hd, const char *file, const char *data_file,
+ const char *output)
{
- cdk_stream_t inp;
- char buf[2048];
- int rc, n;
-
- if( !hd || !file )
- return CDK_Inv_Value;
- if( output && !hd->opt.overwrite && _cdk_check_file( output ) )
- return CDK_Inv_Mode;
+ cdk_stream_t inp, data;
+ char buf[4096];
+ int n;
+ cdk_error_t rc;
- rc = cdk_stream_open ( file, &inp );
- if( rc )
- return rc;
- if( cdk_armor_filter_use( inp ) ) {
- n = cdk_stream_peek( inp, buf, sizeof buf-1 );
- if( !n )
- return CDK_EOF;
- buf[n] = '\0';
- if( strstr( buf, "BEGIN PGP SIGNED MESSAGE" ) ) {
- cdk_stream_close( inp );
- return file_verify_clearsign( hd, file, output );
- }
- cdk_stream_set_armor_flag( inp, 0 );
- }
- rc = _cdk_proc_packets( hd, inp, NULL, NULL, NULL );
- cdk_stream_close( inp );
+ if (!hd || !file)
+ return CDK_Inv_Value;
+ if (output && !hd->opt.overwrite && !_cdk_check_file (output))
+ return CDK_Inv_Mode;
+
+ rc = cdk_stream_open (file, &inp);
+ if (rc)
return rc;
-}
-
-
-void
-_cdk_result_verify_free( _cdk_verify_result_t res )
-{
- if( res ) {
- cdk_free( res->sig_data );
- cdk_free( res->notation );
- cdk_free( res );
+ if (cdk_armor_filter_use (inp))
+ {
+ n = cdk_stream_peek (inp, (byte*) buf, DIM (buf)-1);
+ if (!n || n == -1)
+ return CDK_EOF;
+ buf[n] = '\0';
+ if (strstr (buf, "BEGIN PGP SIGNED MESSAGE"))
+ {
+ cdk_stream_close (inp);
+ return file_verify_clearsign (hd, file, output);
+ }
+ cdk_stream_set_armor_flag (inp, 0);
}
+
+ if (data_file)
+ {
+ rc = cdk_stream_open (data_file, &data);
+ if (rc)
+ {
+ cdk_stream_close (inp);
+ return rc;
+ }
+ }
+ else
+ data = NULL;
+
+ rc = _cdk_proc_packets (hd, inp, data, NULL, NULL, NULL);
+
+ if (data != NULL)
+ cdk_stream_close (data);
+ cdk_stream_close (inp);
+ return rc;
}
-_cdk_verify_result_t
-_cdk_result_verify_new( void )
+void
+_cdk_result_verify_free (cdk_verify_result_t res)
{
- _cdk_verify_result_t res;
-
- res = cdk_calloc( 1, sizeof *res );
- if( !res )
- return NULL;
- return res;
+ if (!res)
+ return;
+ cdk_free (res->policy_url);
+ cdk_free (res->sig_data);
+ cdk_free (res);
}
-/**
- * cdk_sig_get_ulong_attr:
- * @hd: session handle
- * @idx: index of the signature
- * @what: attribute id
- *
- * Extract the requested attribute of the signature. The returned value
- * is always an integer (max. 32-bit).
- **/
-unsigned long
-cdk_sig_get_ulong_attr( cdk_ctx_t hd, int idx, int what )
+cdk_verify_result_t
+_cdk_result_verify_new (void)
{
- _cdk_verify_result_t res;
- u32 val = 0;
+ cdk_verify_result_t res;
- if( !hd || !hd->result.verify )
- return 0;
-
- assert( idx == 0 );
- res = hd->result.verify;
- switch( what ) {
- case CDK_ATTR_CREATED: val = res->created; break;
- case CDK_ATTR_EXPIRE : val = res->expires; break;
- case CDK_ATTR_KEYID : val = res->keyid[1]; break;
- case CDK_ATTR_STATUS : val = res->sig_status; break;
- case CDK_ATTR_ALGO_PK: val = res->pubkey_algo; break;
- case CDK_ATTR_ALGO_MD: val = res->digest_algo; break;
- case CDK_ATTR_VERSION: val = res->sig_ver; break;
- case CDK_ATTR_LEN : val = res->sig_len; break;
- case CDK_ATTR_FLAGS : val = res->sig_flags; break;
- default : val = 0; break;
- }
-
- return val;
+ res = cdk_calloc (1, sizeof *res);
+ if (!res)
+ return NULL;
+ return res;
}
-/**
- * cdk_sig_get_data_attr:
- * @hd: session handle
- * @idx: index of the signature
- * @what: attribute id.
- *
- * Extract the requested attribute of the signature. The returned value
- * is always a constant object to the data.
- **/
-const void *
-cdk_sig_get_data_attr( cdk_ctx_t hd, int idx, int what )
+static cdk_error_t
+file_verify_clearsign (cdk_ctx_t hd, const char *file, const char *output)
{
- _cdk_verify_result_t res;
- const void * val;
+ cdk_stream_t inp = NULL, out = NULL, tmp = NULL;
+ gcry_md_hd_t md = NULL;
+ char buf[512], chk[512];
+ const char *s;
+ int i, is_signed = 0, nbytes;
+ int digest_algo = 0;
+ gcry_error_t err;
+ cdk_error_t rc;
- if( !hd || !hd->result.verify )
- return NULL;
-
- assert( idx == 0 );
- res = hd->result.verify;
- switch( what ) {
- case CDK_ATTR_KEYID : val = res->keyid; break;
- case CDK_ATTR_NOTATION: val = res->notation; break;
- case CDK_ATTR_MPI : val = res->sig_data; break;
- default : val = NULL;
- }
-
- return val;
-}
-
-
-static int
-file_verify_clearsign( cdk_ctx_t hd, const char * file, const char * output )
-{
- cdk_stream_t inp = NULL, out = NULL, tmp = NULL;
- cdk_md_hd_t md = NULL;
- char buf[512], chk[512];
- const char * s;
- int rc = 0;
- int i, is_signed = 0, nbytes;
- int digest_algo = 0;
-
- if( output ) {
- rc = cdk_stream_create( output, &out );
- if( rc )
- return rc;
+ if (output)
+ {
+ rc = cdk_stream_create (output, &out);
+ if (rc)
+ return rc;
}
- rc = cdk_stream_open( file, &inp );
- if( rc )
- return rc;
-
- s = "-----BEGIN PGP SIGNED MESSAGE-----";
- while( !cdk_stream_eof( inp ) ) {
- nbytes = _cdk_stream_gets( inp, buf, sizeof buf-1 );
- if( !nbytes )
- break;
- if( !strncmp( buf, s, strlen( s ) ) ) {
- is_signed = 1;
- break;
- }
+ rc = cdk_stream_open (file, &inp);
+ if (rc)
+ {
+ if (output)
+ cdk_stream_close (out);
+ return rc;
+ }
+
+ s = "-----BEGIN PGP SIGNED MESSAGE-----";
+ while (!cdk_stream_eof (inp))
+ {
+ nbytes = _cdk_stream_gets (inp, buf, DIM (buf)-1);
+ if (!nbytes || nbytes == -1)
+ break;
+ if (!strncmp (buf, s, strlen (s)))
+ {
+ is_signed = 1;
+ break;
+ }
}
- if( cdk_stream_eof( inp ) && !is_signed ) {
- rc = CDK_Armor_Error;
- goto leave;
+
+ if (cdk_stream_eof (inp) && !is_signed)
+ {
+ rc = CDK_Armor_Error;
+ goto leave;
}
- while( !cdk_stream_eof( inp ) ) {
- nbytes = _cdk_stream_gets( inp, buf, sizeof buf-1 );
- if( !nbytes )
- break;
- if( nbytes == 1 ) /* empty line */
- break;
- else if( !strncmp( buf, "Hash: ", 6 ) ) {
- for( i = 0; (s = digest_table[i].name); i++ ) {
- if( !strcmp( buf + 6, s ) ) {
- digest_algo = digest_table[i].algo;
- break;
- }
- }
+ while (!cdk_stream_eof (inp))
+ {
+ nbytes = _cdk_stream_gets (inp, buf, DIM (buf)-1);
+ if (!nbytes || nbytes == -1)
+ break;
+ if (nbytes == 1) /* Empty line */
+ break;
+ else if (!strncmp (buf, "Hash: ", 6))
+ {
+ for (i = 0; digest_table[i].name; i++)
+ {
+ if (!strcmp (buf + 6, digest_table[i].name))
+ {
+ digest_algo = digest_table[i].algo;
+ break;
+ }
+ }
}
}
-
- if( digest_algo && cdk_md_test_algo( digest_algo ) ) {
- rc = CDK_Inv_Algo;
- goto leave;
- }
- if( !digest_algo )
- digest_algo = CDK_MD_MD5;
- md = cdk_md_open( digest_algo, 0 );
- if( !md ) {
- rc = CDK_Inv_Algo;
- goto leave;
+
+ if (digest_algo && gcry_md_test_algo (digest_algo))
+ {
+ rc = CDK_Inv_Algo;
+ goto leave;
}
-
- s = "-----BEGIN PGP SIGNATURE-----";
- while( !cdk_stream_eof( inp ) ) {
- nbytes = _cdk_stream_gets( inp, buf, sizeof buf-1 );
- if( !nbytes )
- break;
- if( !strncmp( buf, s, strlen( s ) ) )
- break;
- else {
- cdk_stream_peek( inp, chk, sizeof chk-1 );
- i = strncmp( chk, s, strlen( s ) );
- if( strlen( buf ) == 0 && i == 0 )
- continue; /* skip last '\n' */
- _cdk_trim_string( buf, i == 0? 0 : 1 );
- cdk_md_write( md, buf, strlen( buf ) );
+
+ if (!digest_algo)
+ digest_algo = GCRY_MD_MD5;
+
+ err = gcry_md_open (&md, digest_algo, 0);
+ if (err)
+ {
+ rc = map_gcry_error (err);
+ goto leave;
+ }
+
+ s = "-----BEGIN PGP SIGNATURE-----";
+ while (!cdk_stream_eof (inp))
+ {
+ nbytes = _cdk_stream_gets (inp, buf, DIM (buf)-1);
+ if (!nbytes || nbytes == -1)
+ break;
+ if (!strncmp (buf, s, strlen (s)))
+ break;
+ else
+ {
+ cdk_stream_peek (inp, (byte*)chk, DIM (chk)-1);
+ i = strncmp (chk, s, strlen (s));
+ if (strlen (buf) == 0 && i == 0)
+ continue; /* skip last '\n' */
+ _cdk_trim_string (buf, i == 0? 0 : 1);
+ gcry_md_write (md, buf, strlen (buf));
}
- if( !strncmp( buf, "- ", 2 ) )
- memmove( buf, buf + 2, nbytes - 2 );
- if( out ) {
- buf[strlen( buf ) - 1] = 0;
- buf[strlen( buf ) - 1] = '\n';
- cdk_stream_write( out, buf, strlen( buf ) );
+ if (!strncmp (buf, "- ", 2)) /* FIXME: handle it recursive. */
+ memmove (buf, buf + 2, nbytes - 2);
+ if (out)
+ {
+ if (strstr (buf, "\r\n"))
+ buf[strlen (buf)-2] = '\0';
+ cdk_stream_write (out, buf, strlen (buf));
+ _cdk_stream_puts (out, _cdk_armor_get_lineend ());
}
}
- tmp = cdk_stream_tmp( );
- if( !tmp ) {
- rc = CDK_Out_Of_Core;
- goto leave;
+ /* We create a temporary stream object to store the
+ signature data in there. */
+ rc = cdk_stream_tmp_new (&tmp);
+ if (rc)
+ goto leave;
+
+ s = "-----BEGIN PGP SIGNATURE-----\n";
+ _cdk_stream_puts (tmp, s);
+ while (!cdk_stream_eof (inp))
+ {
+ nbytes = _cdk_stream_gets (inp, buf, DIM (buf)-1);
+ if (!nbytes || nbytes == -1)
+ break;
+ if (nbytes < (DIM (buf) -3))
+ {
+ buf[nbytes-1] = '\n';
+ buf[nbytes] = '\0';
+ }
+ cdk_stream_write (tmp, buf, nbytes);
}
- /* xxx revamp this part of the function */
- s = "-----BEGIN PGP SIGNATURE-----\n";
- _cdk_stream_puts( tmp, s );
- while( !cdk_stream_eof( inp ) ) {
- nbytes = _cdk_stream_gets( inp, buf, sizeof buf-1 );
- if( !nbytes )
- break;
- if( nbytes < (sizeof buf -3) ) {
- buf[nbytes-1] = '\n';
- buf[nbytes] = '\0';
- }
- cdk_stream_write( tmp, buf, nbytes );
- }
- cdk_stream_tmp_set_mode( tmp, STREAMCTL_READ );
- cdk_stream_seek( tmp, 0 );
- cdk_stream_set_armor_flag( tmp, 0 );
- cdk_stream_read( tmp, NULL, 0 );
-
- rc = _cdk_proc_packets( hd, tmp, NULL, NULL, md );
-
- leave:
- cdk_stream_close( out );
- cdk_stream_close( tmp );
- cdk_stream_close( inp );
- return rc;
+ /* FIXME: This code is not very elegant. */
+ cdk_stream_tmp_set_mode (tmp, STREAMCTL_READ);
+ cdk_stream_seek (tmp, 0);
+ cdk_stream_set_armor_flag (tmp, 0);
+ cdk_stream_read (tmp, NULL, 0);
+
+ rc = _cdk_proc_packets (hd, tmp, NULL, NULL, NULL, md);
+
+ leave:
+ cdk_stream_close (out);
+ cdk_stream_close (tmp);
+ cdk_stream_close (inp);
+ return rc;
}
diff --git a/libextra/opencdk/write-packet.c b/libextra/opencdk/write-packet.c
index 537a2f3234..12488bd422 100644
--- a/libextra/opencdk/write-packet.c
+++ b/libextra/opencdk/write-packet.c
@@ -1,6 +1,5 @@
-/* -*- Mode: C; c-file-style: "bsd" -*-
- * write-packet.c - Write OpenPGP packets
- * Copyright (C) 2001, 2002, 2003 Timo Schulz
+/* write-packet.c - Write OpenPGP packets
+ * Copyright (C) 2001, 2002, 2003, 2007 Timo Schulz
*
* This file is part of OpenCDK.
*
@@ -13,12 +12,7 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with OpenCDK; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
@@ -30,436 +24,463 @@
static int
-stream_write( cdk_stream_t s, const void * buf, size_t count )
+stream_write (cdk_stream_t s, const void *buf, size_t buflen)
{
- int nwritten = cdk_stream_write( s, buf, count );
- if( nwritten == EOF )
- return CDK_File_Error;
- return 0;
+ int nwritten;
+
+ nwritten = cdk_stream_write (s, buf, buflen);
+ if (nwritten == EOF)
+ return _cdk_stream_get_errno (s);
+ return 0;
}
static int
-stream_read( cdk_stream_t s, void * buf, size_t count, size_t * r_nread )
+stream_read (cdk_stream_t s, void *buf, size_t buflen, size_t *r_nread)
{
- int nread;
-
- if( !r_nread )
- return CDK_Inv_Value;
- nread = cdk_stream_read( s, buf, count );
- if( nread == EOF )
- return CDK_File_Error;
- *r_nread = nread;
- return 0;
+ int nread;
+
+ if (!r_nread)
+ return CDK_Inv_Value;
+ nread = cdk_stream_read (s, buf, buflen);
+ if (nread == EOF)
+ return CDK_File_Error;
+ *r_nread = nread;
+ return 0;
}
static int
-stream_putc( cdk_stream_t s, int c )
+stream_putc (cdk_stream_t s, int c)
{
- int nwritten = cdk_stream_putc( s, c );
- if( nwritten == EOF )
- return CDK_File_Error;
- return 0;
+ int nwritten = cdk_stream_putc (s, c);
+ if (nwritten == EOF)
+ return CDK_File_Error;
+ return 0;
}
static int
-write_32( cdk_stream_t out, u32 u )
+write_32 (cdk_stream_t out, u32 u)
{
- byte buf[4];
- buf[0] = u >> 24;
- buf[1] = u >> 16;
- buf[2] = u >> 8;
- buf[3] = u;
- return stream_write( out, buf, 4 );
+ byte buf[4];
+
+ buf[0] = u >> 24;
+ buf[1] = u >> 16;
+ buf[2] = u >> 8;
+ buf[3] = u;
+ return stream_write (out, buf, 4);
}
static int
-write_16( cdk_stream_t out, u16 u )
+write_16 (cdk_stream_t out, u16 u)
{
- byte buf[2];
- buf[0] = u >> 8;
- buf[1] = u;
- return stream_write( out, buf, 2 );
+ byte buf[2];
+
+ buf[0] = u >> 8;
+ buf[1] = u;
+ return stream_write (out, buf, 2);
}
static size_t
-calc_mpisize( cdk_mpi_t mpi[4], int ncount )
+calc_mpisize (gcry_mpi_t mpi[4], size_t ncount)
{
- size_t nbytes, size = 0;
- int i;
-
- for( i = 0; i < ncount; i++ ) {
- nbytes = (mpi[i]->bits + 7) / 8 + 2;
- size += nbytes;
- }
- return size;
+ size_t size, i;
+
+ size=0;
+ for (i = 0; i < ncount; i++)
+ size += (gcry_mpi_get_nbits (mpi[i])+7)/8 + 2;
+ return size;
}
static int
-write_mpi( cdk_stream_t out, cdk_mpi_t m )
+write_mpi (cdk_stream_t out, gcry_mpi_t m)
{
- if( !out || !m )
- return CDK_Inv_Value;
- if( m->bits > MAX_MPI_BITS || !m->bits )
- return CDK_MPI_Error;
- if( !m->bytes )
- m->bytes = (m->bits + 7) / 8;
- return stream_write( out, m->data, m->bytes + 2 );
+ byte buf[MAX_MPI_BYTES+2];
+ size_t nbits, nread;
+ gcry_error_t err;
+
+ if (!out || !m)
+ return CDK_Inv_Value;
+ nbits = gcry_mpi_get_nbits (m);
+ if (nbits > MAX_MPI_BITS || nbits < 1)
+ return CDK_MPI_Error;
+ err = gcry_mpi_print (GCRYMPI_FMT_PGP, buf, MAX_MPI_BYTES+2, &nread, m);
+ if (err)
+ return map_gcry_error (err);
+ return stream_write (out, buf, nread);
}
-static int
-write_mpibuf( cdk_stream_t out, cdk_mpi_t mpi[4], int count )
+static cdk_error_t
+write_mpibuf (cdk_stream_t out, gcry_mpi_t mpi[4], size_t count)
{
- int i, rc = 0;
+ size_t i;
+ cdk_error_t rc;
- for( i = 0; i < count; i++ ) {
- rc = write_mpi( out, mpi[i] );
- if( rc )
- break;
+ for (i = 0; i < count; i++)
+ {
+ rc = write_mpi (out, mpi[i]);
+ if (rc)
+ return rc;
}
- return rc;
+ return 0;
}
-static int
-pkt_encode_len( cdk_stream_t out, size_t pktlen )
+static cdk_error_t
+pkt_encode_len (cdk_stream_t out, size_t pktlen)
{
- int rc = 0;
-
- if( !out )
- return CDK_Inv_Value;
- if( !pktlen )
- return 0;
- else if( pktlen < 192 )
- rc = stream_putc( out, pktlen );
- else if( pktlen < 8384 ) {
- pktlen -= 192;
- rc = stream_putc( out, (pktlen / 256) + 192 );
- if( !rc )
- rc = stream_putc( out, (pktlen % 256) );
+ cdk_error_t rc;
+
+ if (!out)
+ return CDK_Inv_Value;
+ rc = 0;
+ if (!pktlen)
+ {
+ /* Block mode, partial bodies, with 'DEF_BLOCKSIZE' from main.h */
+ rc = stream_putc( out, (0xE0|DEF_BLOCKBITS) );
}
- else {
- rc = stream_putc( out, 255 );
- if( !rc )
- rc = write_32( out, pktlen );
+ else if (pktlen < 192)
+ rc = stream_putc (out, pktlen);
+ else if (pktlen < 8384)
+ {
+ pktlen -= 192;
+ rc = stream_putc (out, (pktlen / 256) + 192);
+ if (!rc)
+ rc = stream_putc (out, (pktlen % 256));
}
- return rc;
+ else
+ {
+ rc = stream_putc (out, 255);
+ if (!rc)
+ rc = write_32 (out, pktlen);
+ }
+
+ return rc;
}
-static int
-write_head_new( cdk_stream_t out, size_t size, int type )
+static cdk_error_t
+write_head_new (cdk_stream_t out, size_t size, int type)
{
- int rc = 0;
-
- if( !out )
- return CDK_Inv_Value;
- if( type < 0 || type > 63 )
- return CDK_Inv_Packet;
- rc = stream_putc( out, (0xC0 | type) );
- if( !rc )
- rc = pkt_encode_len( out, size );
- return rc;
+ cdk_error_t rc;
+
+ if (!out)
+ return CDK_Inv_Value;
+ if (type < 0 || type > 63)
+ return CDK_Inv_Packet;
+ rc = stream_putc (out, (0xC0 | type));
+ if (!rc)
+ rc = pkt_encode_len (out, size);
+ return rc;
}
-static int
-write_head_old( cdk_stream_t out, size_t size, int type )
+static cdk_error_t
+write_head_old (cdk_stream_t out, size_t size, int type)
{
- int ctb;
- int rc;
-
- if( !out )
- return CDK_Inv_Value;
- if( type < 0 || type > 16 )
- return CDK_Inv_Packet;
- ctb = 0x80 | (type << 2);
- if( !size )
- ctb |= 3;
- else if( size < 256 )
- ;
- else if( size < 65536 )
- ctb |= 1;
- else
- ctb |= 2;
- rc = stream_putc( out, ctb );
- if( !size )
- return rc;
- if( !rc ) {
- if( size < 256 )
- rc = stream_putc( out, size );
- else if( size < 65536 )
- rc = write_16( out, size );
- else
- rc = write_32( out, size );
- }
+ cdk_error_t rc;
+ int ctb;
+
+ if (!out)
+ return CDK_Inv_Value;
+ if (type < 0 || type > 16)
+ return CDK_Inv_Packet;
+ ctb = 0x80 | (type << 2);
+ if (!size)
+ ctb |= 3;
+ else if (size < 256)
+ ;
+ else if (size < 65536)
+ ctb |= 1;
+ else
+ ctb |= 2;
+ rc = stream_putc (out, ctb);
+ if (!size)
return rc;
+ if (!rc)
+ {
+ if (size < 256)
+ rc = stream_putc (out, size);
+ else if (size < 65536)
+ rc = write_16 (out, size);
+ else
+ rc = write_32 (out, size);
+ }
+
+ return rc;
}
/* write special PGP2 packet header. PGP2 (wrongly) uses two byte header
length for signatures and keys even if the size is < 256. */
-static int
-pkt_write_head2( cdk_stream_t out, size_t size, int type )
+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 );
- if( !rc )
- rc = cdk_stream_putc( out, size >> 8 );
- if( !rc )
- rc = cdk_stream_putc( out, size & 0xff );
- return rc;
+ int rc = cdk_stream_putc (out, 0x80 | (type << 2) | 1);
+ if (!rc)
+ rc = cdk_stream_putc (out, size >> 8);
+ if (!rc)
+ rc = cdk_stream_putc (out, size & 0xff);
+ return rc;
}
static int
-pkt_write_head( cdk_stream_t out, int old_ctb, size_t size, int type )
+pkt_write_head (cdk_stream_t out, int old_ctb, size_t size, int type)
{
- return old_ctb?
- write_head_old( out, size, type ) :
- write_head_new( out, size, type );
+ if (old_ctb)
+ return write_head_old (out, size, type);
+ return write_head_new (out, size, type);
}
-static int
-write_encrypted( cdk_stream_t out, cdk_pkt_encrypted_t enc, int old_ctb )
+static cdk_error_t
+write_encrypted (cdk_stream_t out, cdk_pkt_encrypted_t enc, int old_ctb)
{
- size_t nbytes;
- int rc = 0;
-
- if( !out || !enc )
- return CDK_Inv_Value;
-
- if( DEBUG_PKT )
- _cdk_log_debug ("** write encrypted packet %lu bytes\n", enc->len);
+ size_t nbytes;
+ cdk_error_t rc;
- nbytes = enc->len ? (enc->len + enc->extralen) : 0;
- rc = pkt_write_head( out, old_ctb, nbytes, CDK_PKT_ENCRYPTED );
- /* rest of the packet is ciphertext */
- return rc;
+ if (!out || !enc)
+ return CDK_Inv_Value;
+
+ if (DEBUG_PKT)
+ _cdk_log_debug ("** write encrypted packet %lu bytes\n", enc->len);
+
+ nbytes = enc->len ? (enc->len + enc->extralen) : 0;
+ rc = pkt_write_head (out, old_ctb, nbytes, CDK_PKT_ENCRYPTED);
+ /* The rest of the packet is ciphertext */
+ return rc;
}
static int
-write_encrypted_mdc( cdk_stream_t out, cdk_pkt_encrypted_t enc )
+write_encrypted_mdc (cdk_stream_t out, cdk_pkt_encrypted_t enc)
{
- size_t nbytes;
- int rc = 0;
-
- if( !out || !enc )
- return CDK_Inv_Value;
- if( !enc->mdc_method )
- return CDK_Inv_Packet;
+ size_t nbytes;
+ cdk_error_t rc;
- if( DEBUG_PKT )
- _cdk_log_debug ("** write encrypted mdc packet %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 );
- if( !rc )
- rc = stream_putc( out, 1 ); /* version */
- /* rest of the packet is ciphertext */
- return rc;
+ if (!out || !enc)
+ return CDK_Inv_Value;
+ if (!enc->mdc_method)
+ return CDK_Inv_Packet;
+
+ if (DEBUG_PKT)
+ _cdk_log_debug ("** write encrypted mdc packet %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);
+ if (!rc)
+ rc = stream_putc (out, 1); /* version */
+ /* The rest of the packet is ciphertext */
+ return rc;
}
-static int
-write_symkey_enc( cdk_stream_t out, cdk_pkt_symkey_enc_t ske )
+static cdk_error_t
+write_symkey_enc (cdk_stream_t out, cdk_pkt_symkey_enc_t ske)
{
- cdk_s2k_t s2k;
- size_t size = 0, s2k_size = 0;
- int rc = 0;
-
- if( !out || !ske )
- return CDK_Inv_Value;
- if( ske->version != 4 )
- return CDK_Inv_Packet;
-
- if( DEBUG_PKT )
- _cdk_log_debug ("** write symmetric key encrypted packet\n");
-
- s2k = ske->s2k;
- if( s2k->mode == 1 || s2k->mode == 3 )
- s2k_size = 8;
- if( s2k->mode == 3 )
- s2k_size++;
- size = 4 + s2k_size + ske->seskeylen;
- rc = pkt_write_head( out, 0, size, CDK_PKT_SYMKEY_ENC );
- if( !rc )
- rc = stream_putc( out, ske->version );
- if( !rc )
- rc = stream_putc( out, ske->cipher_algo );
- if( !rc )
- rc = stream_putc( out, s2k->mode );
- if( !rc )
- rc = stream_putc( out, s2k->hash_algo );
- if( s2k->mode == 1 || s2k->mode == 3 ) {
- rc = stream_write( out, s2k->salt, 8 );
- if( !rc && s2k->mode == 3 )
- rc = stream_putc( out, s2k->count );
+ cdk_s2k_t s2k;
+ size_t size = 0, s2k_size = 0;
+ cdk_error_t rc;
+
+ if (!out || !ske)
+ return CDK_Inv_Value;
+ if (ske->version != 4)
+ return CDK_Inv_Packet;
+
+ if (DEBUG_PKT)
+ _cdk_log_debug ("** write symmetric key encrypted packet\n");
+
+ s2k = ske->s2k;
+ if (s2k->mode == CDK_S2K_SALTED || s2k->mode == CDK_S2K_ITERSALTED)
+ s2k_size = 8;
+ if (s2k->mode == CDK_S2K_ITERSALTED)
+ s2k_size++;
+ size = 4 + s2k_size + ske->seskeylen;
+ rc = pkt_write_head (out, 0, size, CDK_PKT_SYMKEY_ENC);
+ if (!rc)
+ rc = stream_putc (out, ske->version);
+ if (!rc)
+ rc = stream_putc (out, ske->cipher_algo);
+ if (!rc)
+ rc = stream_putc (out, s2k->mode);
+ if (!rc)
+ rc = stream_putc (out, s2k->hash_algo);
+ if (s2k->mode == CDK_S2K_SALTED || s2k->mode == CDK_S2K_ITERSALTED)
+ {
+ rc = stream_write (out, s2k->salt, 8);
+ if (!rc)
+ {
+ if (s2k->mode == CDK_S2K_ITERSALTED)
+ rc = stream_putc (out, s2k->count);
+ }
}
- return rc;
+ return rc;
}
static int
-write_pubkey_enc( cdk_stream_t out, cdk_pkt_pubkey_enc_t pke, int old_ctb )
+write_pubkey_enc (cdk_stream_t out, cdk_pkt_pubkey_enc_t pke, int old_ctb)
{
- size_t size;
- int rc = 0, nenc = 0;
-
- if( !out || !pke )
- return CDK_Inv_Value;
- 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");
+ size_t size;
+ int rc, nenc;
+
+ if (!out || !pke)
+ return CDK_Inv_Value;
+ 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");
- nenc = cdk_pk_get_nenc( pke->pubkey_algo );
- size = 10 + calc_mpisize( pke->mpi, nenc );
- rc = pkt_write_head( out, old_ctb, size, CDK_PKT_PUBKEY_ENC );
- if( !rc )
- rc = stream_putc( out, pke->version );
- if( !rc )
- rc = write_32( out, pke->keyid[0] );
- if( !rc )
- rc = write_32( out, pke->keyid[1] );
- if( !rc )
- rc = stream_putc( out, pke->pubkey_algo );
- if( !rc )
- rc = write_mpibuf( out, pke->mpi, nenc );
+ nenc = cdk_pk_get_nenc (pke->pubkey_algo);
+ size = 10 + calc_mpisize (pke->mpi, nenc);
+ rc = pkt_write_head (out, old_ctb, size, CDK_PKT_PUBKEY_ENC);
+ if (rc)
return rc;
+
+ rc = stream_putc (out, pke->version);
+ if (!rc)
+ rc = write_32 (out, pke->keyid[0]);
+ if (!rc)
+ rc = write_32 (out, pke->keyid[1]);
+ if (!rc)
+ rc = stream_putc (out, pke->pubkey_algo);
+ if (!rc)
+ rc = write_mpibuf (out, pke->mpi, nenc);
+ return rc;
}
-static int
-write_mdc( cdk_stream_t out, cdk_pkt_mdc_t mdc )
+static cdk_error_t
+write_mdc (cdk_stream_t out, cdk_pkt_mdc_t mdc)
{
- int rc = 0;
+ cdk_error_t rc;
- if( !out || !mdc )
- return CDK_Inv_Value;
-
- if( DEBUG_PKT )
- _cdk_log_debug ("** write_mdc\n");
-
- /* This packet requires a fixed header encoding */
- rc = stream_putc (out, 0xD3); /* packet ID and 1 byte length */
- if( !rc )
- rc = stream_putc( out, 0x14 );
- if( !rc )
- rc = stream_write( out, mdc->hash, sizeof mdc->hash );
- return rc;
+ if (!out || !mdc)
+ return CDK_Inv_Value;
+
+ if (DEBUG_PKT)
+ _cdk_log_debug ("** write_mdc packet\n");
+
+ /* This packet requires a fixed header encoding */
+ rc = stream_putc (out, 0xD3); /* packet ID and 1 byte length */
+ if (!rc)
+ rc = stream_putc (out, 0x14);
+ if (!rc)
+ rc = stream_write (out, mdc->hash, DIM (mdc->hash));
+ return rc;
}
static size_t
-calc_subpktsize( cdk_subpkt_t s )
+calc_subpktsize (cdk_subpkt_t s)
{
- size_t nbytes;
-
- if( !s )
- return 0;
- _cdk_subpkt_get_array( s, 1, &nbytes );
- return nbytes;
+ size_t nbytes;
+
+ /* In the count mode, no buffer is returned. */
+ _cdk_subpkt_get_array (s, 1, &nbytes);
+ return nbytes;
}
-static int
-write_signature( cdk_stream_t out, cdk_pkt_signature_t sig, int old_ctb )
+static cdk_error_t
+write_signature (cdk_stream_t out, cdk_pkt_signature_t sig, int old_ctb)
{
- byte * buf;
- size_t nbytes, size;
- int nsig = 0, rc = 0;
-
- if( !out || !sig )
- return CDK_Inv_Value;
-
- if( !KEY_CAN_SIGN( sig->pubkey_algo ) )
- return CDK_Inv_Algo;
- if( sig->version < 3 || sig->version > 4 )
- return CDK_Inv_Packet;
+ byte *buf;
+ size_t nbytes, size, nsig;
+ cdk_error_t rc;
- if (DEBUG_PKT)
- _cdk_log_debug ("** write signature packet\n");
+ if (!out || !sig)
+ return CDK_Inv_Value;
+
+ if (!KEY_CAN_SIGN( sig->pubkey_algo))
+ return CDK_Inv_Algo;
+ if (sig->version < 2 || sig->version > 4)
+ return CDK_Inv_Packet;
- nsig = cdk_pk_get_nsig( sig->pubkey_algo );
- if( !nsig )
- return CDK_Inv_Algo;
- if( sig->version < 4 ) {
- 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] );
+ if (DEBUG_PKT)
+ _cdk_log_debug ("** write signature packet\n");
+
+ nsig = cdk_pk_get_nsig (sig->pubkey_algo);
+ if (!nsig)
+ return CDK_Inv_Algo;
+ if (sig->version < 4)
+ {
+ 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]);
}
- else {
- 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 );
+ else
+ {
+ 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 = 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] );
+ 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]);
}
- if( !rc )
- rc = write_mpibuf( out, sig->mpi, nsig );
- return rc;
+ if (!rc)
+ rc = write_mpibuf (out, sig->mpi, nsig);
+ return rc;
}
@@ -481,6 +502,8 @@ write_public_key( cdk_stream_t out, cdk_pkt_pubkey_t pk,
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 )
@@ -511,15 +534,13 @@ static int
calc_s2ksize( cdk_pkt_seckey_t sk )
{
size_t nbytes = 0;
- cdk_s2k_t s2k;
if( !sk->is_protected )
return 0;
- s2k = sk->protect.s2k;
- switch( s2k->mode ) {
- case 0: nbytes = 2; break;
- case 1: nbytes = 10; break;
- case 3: nbytes = 11; break;
+ 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 */
@@ -552,10 +573,12 @@ write_secret_key( cdk_stream_t out, cdk_pkt_seckey_t sk,
return CDK_Inv_Algo;
if( pk->version < 4 )
size += 2;
- /* if the key is unprotected, the 3 extra bytes are:
+ /* if the key is unprotected, the 1 extra byte:
1 octet - cipher algorithm byte (0x00)
- 2 octets - simple checksum */
- size = !sk->is_protected? size + 3 : size + 1 + calc_s2ksize( sk );
+ 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 ) {
@@ -645,91 +668,105 @@ write_compressed( cdk_stream_t out, cdk_pkt_compressed_t cd )
}
-static int
-write_literal( cdk_stream_t out, cdk_pkt_literal_t pt, int old_ctb )
+static cdk_error_t
+write_literal (cdk_stream_t out, cdk_pkt_literal_t pt, int old_ctb)
{
- byte buf[8192];
- size_t size;
- int rc;
-
- if( !out || !pt )
- return CDK_Inv_Value;
+ byte buf[BUFSIZE];
+ size_t size;
+ cdk_error_t rc;
+
+ if (!out || !pt)
+ return CDK_Inv_Value;
+ /* 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");
- if (DEBUG_PKT)
- _cdk_log_debug ("** write literal packet\n");
+ size = 6 + pt->namelen + pt->len;
+ rc = pkt_write_head (out, old_ctb, size, CDK_PKT_LITERAL);
+ if (rc)
+ return rc;
- size = 6 + pt->namelen + pt->len;
- rc = pkt_write_head( out, old_ctb, size, CDK_PKT_LITERAL );
- if( !rc )
- rc = stream_putc( out, pt->mode );
- if( !rc )
- rc = stream_putc( out, pt->namelen );
- if( !rc && pt->namelen )
- rc = stream_write( out, pt->name, pt->namelen );
- if( !rc )
- rc = write_32( out, pt->timestamp );
- if( !rc ) {
- while( pt->len && !cdk_stream_eof( pt->buf ) && !rc ) {
- rc = stream_read( pt->buf, buf, sizeof buf-1, &size );
- if( !rc )
- rc = stream_write( out, buf, size );
- }
- wipemem( buf, sizeof buf );
- }
+ rc = stream_putc (out, pt->mode);
+ if (rc)
+ return rc;
+ rc = stream_putc (out, pt->namelen);
+ if (rc)
return rc;
+
+ if (pt->namelen > 0)
+ rc = stream_write (out, pt->name, pt->namelen);
+ if (!rc)
+ rc = write_32 (out, pt->timestamp);
+ if (rc)
+ return rc;
+
+ while (!cdk_stream_eof (pt->buf) && !rc)
+ {
+ rc = stream_read (pt->buf, buf, DIM (buf), &size);
+ if (!rc)
+ rc = stream_write (out, buf, size);
+ }
+
+ wipemem (buf, sizeof (buf));
+ return rc;
}
-static int
-write_onepass_sig( cdk_stream_t out, cdk_pkt_onepass_sig_t sig )
+static cdk_error_t
+write_onepass_sig (cdk_stream_t out, cdk_pkt_onepass_sig_t sig)
{
- size_t size = 0;
- int rc = 0;
-
- if( !out || !sig )
- return CDK_Inv_Value;
- if( sig->version != 3 )
- return CDK_Inv_Packet;
-
- if (DEBUG_PKT)
- _cdk_log_debug ("** write one pass signature packet\n");
+ cdk_error_t rc;
+
+ if (!out || !sig)
+ return CDK_Inv_Value;
+ if (sig->version != 3)
+ return CDK_Inv_Packet;
- size = 13;
- rc = pkt_write_head( out, 0, size, CDK_PKT_ONEPASS_SIG );
- if( !rc )
- rc = stream_putc( out, sig->version );
- if( !rc )
- rc = stream_putc( out, sig->sig_class );
- if( !rc )
- rc = stream_putc( out, sig->digest_algo );
- if (!rc)
- rc = stream_putc( out, sig->pubkey_algo );
- 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->last );
- return rc;
+ if (DEBUG_PKT)
+ _cdk_log_debug ("** write one pass signature packet\n");
+
+ rc = pkt_write_head (out, 0, 13, CDK_PKT_ONEPASS_SIG);
+ if (!rc)
+ rc = stream_putc (out, sig->version);
+ if (!rc)
+ rc = stream_putc (out, sig->sig_class);
+ if (!rc)
+ rc = stream_putc (out, sig->digest_algo);
+ if (!rc)
+ rc = stream_putc (out, sig->pubkey_algo);
+ 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->last);
+ return rc;
}
-static int
-write_user_id( cdk_stream_t out, cdk_pkt_userid_t id, int old_ctb )
+static cdk_error_t
+write_user_id (cdk_stream_t out, cdk_pkt_userid_t id, int old_ctb)
{
- int rc = 0;
-
- if( !out || !id || !id->name )
- return CDK_Inv_Value;
+ cdk_error_t rc;
- if( id->attrib_img )
- ;/* todo */
- else {
- rc = pkt_write_head( out, old_ctb, id->len, CDK_PKT_USER_ID );
- if( !rc )
- rc = stream_write( out, id->name, id->len );
+ if (!out || !id || !id->name)
+ return CDK_Inv_Value;
+
+ if (id->attrib_img)
+ ; /* FIXME: Implement to store attribute packets. */
+ else
+ {
+ 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;
}
- return rc;
+
+ return CDK_Not_Implemented;
}
@@ -739,76 +776,117 @@ write_user_id( cdk_stream_t out, cdk_pkt_userid_t id, int old_ctb )
* @pkt: the packet itself
*
* Write the contents of @pkt into the @out stream.
+ * Return 0 on success.
**/
cdk_error_t
-cdk_pkt_write( cdk_stream_t out, cdk_packet_t pkt )
+cdk_pkt_write (cdk_stream_t out, cdk_packet_t pkt)
{
- int rc;
+ cdk_error_t rc;
- if( !out || !pkt )
- return CDK_Inv_Value;
-
- switch( pkt->pkttype ) {
+ if (!out || !pkt)
+ return CDK_Inv_Value;
+
+ _cdk_log_debug ("write packet pkttype=%d\n", pkt->pkttype);
+ switch (pkt->pkttype)
+ {
case CDK_PKT_LITERAL:
- rc = write_literal( out, pkt->pkt.literal, pkt->old_ctb );
- break;
+ rc = write_literal (out, pkt->pkt.literal, pkt->old_ctb);
+ break;
case CDK_PKT_ONEPASS_SIG:
- rc = write_onepass_sig( out, pkt->pkt.onepass_sig );
- break;
+ rc = write_onepass_sig (out, pkt->pkt.onepass_sig);
+ break;
case CDK_PKT_MDC:
- rc = write_mdc( out, pkt->pkt.mdc );
- break;
+ rc = write_mdc (out, pkt->pkt.mdc);
+ break;
case CDK_PKT_SYMKEY_ENC:
- rc = write_symkey_enc( out, pkt->pkt.symkey_enc );
- break;
+ rc = write_symkey_enc (out, pkt->pkt.symkey_enc);
+ break;
case CDK_PKT_ENCRYPTED:
- rc = write_encrypted( out, pkt->pkt.encrypted, pkt->old_ctb );
- break;
+ rc = write_encrypted (out, pkt->pkt.encrypted, pkt->old_ctb);
+ break;
case CDK_PKT_ENCRYPTED_MDC:
- rc = write_encrypted_mdc( out, pkt->pkt.encrypted );
- break;
+ rc = write_encrypted_mdc (out, pkt->pkt.encrypted);
+ break;
case CDK_PKT_PUBKEY_ENC:
- rc = write_pubkey_enc( out, pkt->pkt.pubkey_enc, pkt->old_ctb );
- break;
+ rc = write_pubkey_enc (out, pkt->pkt.pubkey_enc, pkt->old_ctb);
+ break;
case CDK_PKT_SIGNATURE:
- rc = write_signature( out, pkt->pkt.signature, pkt->old_ctb );
- break;
+ rc = write_signature (out, pkt->pkt.signature, pkt->old_ctb);
+ break;
case CDK_PKT_PUBLIC_KEY:
- rc = write_public_key( out, pkt->pkt.public_key, 0, pkt->old_ctb );
- break;
+ rc = write_public_key (out, pkt->pkt.public_key, 0, pkt->old_ctb);
+ break;
case CDK_PKT_PUBLIC_SUBKEY:
- rc = write_public_key( out, pkt->pkt.public_key, 1, pkt->old_ctb );
- break;
+ rc = write_public_key (out, pkt->pkt.public_key, 1, pkt->old_ctb);
+ break;
case CDK_PKT_COMPRESSED:
- rc = write_compressed( out, pkt->pkt.compressed );
- break;
+ rc = write_compressed (out, pkt->pkt.compressed);
+ break;
case CDK_PKT_SECRET_KEY:
- rc = write_secret_key( out, pkt->pkt.secret_key, 0, pkt->old_ctb );
- break;
+ rc = write_secret_key (out, pkt->pkt.secret_key, 0, pkt->old_ctb);
+ break;
case CDK_PKT_SECRET_SUBKEY:
- rc = write_secret_key( out, pkt->pkt.secret_key, 1, pkt->old_ctb );
- break;
+ 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 );
- break;
+ rc = write_user_id (out, pkt->pkt.user_id, pkt->old_ctb);
+ break;
default:
- rc = CDK_Inv_Packet;
- break;
+ rc = CDK_Inv_Packet;
+ break;
}
- return rc;
+
+ return rc;
}
-int
-_cdk_pkt_write_fp( FILE * out, cdk_packet_t pkt )
+cdk_error_t
+_cdk_pkt_write2 (cdk_stream_t out, int pkttype, void *pktctx)
{
- cdk_stream_t so;
- int rc;
+ cdk_packet_t pkt;
+ cdk_error_t rc;
+
+ rc = cdk_pkt_new (&pkt);
+ if (rc)
+ return rc;
- so = _cdk_stream_fpopen( out, 1 );
- rc = cdk_pkt_write( so, pkt );
- cdk_stream_close( so );
+ switch (pkttype)
+ {
+ case CDK_PKT_PUBLIC_KEY:
+ case CDK_PKT_PUBLIC_SUBKEY:
+ pkt->pkt.public_key = pktctx;
+ break;
+ case CDK_PKT_SIGNATURE:
+ pkt->pkt.signature = pktctx;
+ break;
+ case CDK_PKT_SECRET_KEY:
+ case CDK_PKT_SECRET_SUBKEY:
+ pkt->pkt.secret_key = pktctx;
+ break;
+
+ case CDK_PKT_USER_ID:
+ pkt->pkt.user_id = pktctx;
+ break;
+ }
+ pkt->pkttype = pkttype;
+ rc = cdk_pkt_write (out, pkt);
+ cdk_free (pkt);
+ return rc;
+}
+
+
+cdk_error_t
+_cdk_pkt_write_fp (FILE *out, cdk_packet_t pkt)
+{
+ cdk_stream_t so;
+ cdk_error_t rc;
+
+ rc = _cdk_stream_fpopen (out, 1, &so);
+ if (rc)
return rc;
+ rc = cdk_pkt_write (so, pkt);
+ cdk_stream_close (so);
+ return rc;
}