summaryrefslogtreecommitdiff
path: root/libextra
diff options
context:
space:
mode:
authorSimon Josefsson <simon@josefsson.org>2007-06-11 10:49:25 +0200
committerSimon Josefsson <simon@josefsson.org>2007-06-11 10:49:25 +0200
commitc86c105e35466f58203a41b2bd9cd94c9967602d (patch)
treee6165e2471d091e3ec68701a8f34e203593d584d /libextra
parent37ceaa4697db3397be0191524e89427e42f023f5 (diff)
downloadgnutls-c86c105e35466f58203a41b2bd9cd94c9967602d.tar.gz
Update to OpenCDK 0.6.3.
Diffstat (limited to 'libextra')
-rw-r--r--libextra/opencdk/armor.c214
-rw-r--r--libextra/opencdk/cipher.c73
-rw-r--r--libextra/opencdk/compress.c2
-rw-r--r--libextra/opencdk/context.h39
-rw-r--r--libextra/opencdk/filters.h2
-rw-r--r--libextra/opencdk/kbnode.c2
-rw-r--r--libextra/opencdk/keydb.c176
-rw-r--r--libextra/opencdk/literal.c27
-rw-r--r--libextra/opencdk/main.c94
-rw-r--r--libextra/opencdk/main.h16
-rw-r--r--libextra/opencdk/misc.c119
-rw-r--r--libextra/opencdk/new-packet.c281
-rw-r--r--libextra/opencdk/opencdk.h125
-rw-r--r--libextra/opencdk/pubkey.c212
-rw-r--r--libextra/opencdk/read-packet.c6
-rw-r--r--libextra/opencdk/seskey.c189
-rw-r--r--libextra/opencdk/sig-check.c9
-rw-r--r--libextra/opencdk/stream.c95
-rw-r--r--libextra/opencdk/stream.h5
-rw-r--r--libextra/opencdk/verify.c2
20 files changed, 1130 insertions, 558 deletions
diff --git a/libextra/opencdk/armor.c b/libextra/opencdk/armor.c
index 07d3b39134..5195d41f72 100644
--- a/libextra/opencdk/armor.c
+++ b/libextra/opencdk/armor.c
@@ -244,18 +244,18 @@ check_armor (cdk_stream_t inp, int *r_zipalgo)
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"))
+ if (strstr (buf, "-----BEGIN PGP"))
{
compress_get_algo (inp, r_zipalgo);
check = 1;
}
- cdk_stream_seek (inp, 0);
+ cdk_stream_seek (inp, 0);
}
return check;
}
@@ -305,60 +305,56 @@ update_crc (u32 crc, const byte *buf, size_t buflen)
static cdk_error_t
armor_encode (void *opaque, FILE *in, FILE *out)
{
- armor_filter_t * afx = opaque;
- struct stat statbuf;
- char crcbuf[5], buf[128], raw[49];
- byte crcbuf2[3];
- size_t nread = 0;
- const char * lf;
- cdk_error_t rc = 0;
-
- if( !afx )
- return CDK_Inv_Value;
- if( afx->idx < 0 || afx->idx > DIM (armor_begin)
- || afx->idx2 < 0 || afx->idx2 > DIM (armor_end) )
+ armor_filter_t * afx = opaque;
+ struct stat statbuf;
+ char crcbuf[5], buf[128], raw[49];
+ byte crcbuf2[3];
+ size_t nread = 0;
+ const char * lf;
+
+ if (!afx)
+ return CDK_Inv_Value;
+ 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");
-
- 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 );
- fprintf( out, "%s", lf );
-
- if( fstat( fileno( in ), &statbuf ) )
- return CDK_General_Error;
-
- while( !feof( 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, (byte*)raw, nread);
- base64_encode (buf, (byte*)raw, nread, DIM (buf)-1);
- fprintf( out, "%s%s", buf, lf );
- }
+ _cdk_log_debug ("armor filter: encode\n");
+
+ 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);
+ fprintf (out, "%s", lf);
+
+ if (fstat (fileno (in), &statbuf))
+ return CDK_General_Error;
- if( !rc ) {
- crcbuf2[0] = afx->crc >> 16;
- crcbuf2[1] = afx->crc >> 8;
- crcbuf2[2] = afx->crc;
- crcbuf[0] = b64chars[crcbuf2[0] >> 2];
- crcbuf[1] = b64chars[((crcbuf2[0] << 4) & 0x30) |( crcbuf2[1] >> 4)];
- crcbuf[2] = b64chars[((crcbuf2[1] << 2) & 0x3c) |( crcbuf2[2] >> 6)];
- crcbuf[3] = b64chars[crcbuf2[2] & 0x3f];
- fprintf( out, "=%s%s", crcbuf, lf );
- fprintf( out, "-----%s-----%s", armor_end[afx->idx2], lf );
+ while (!feof (in))
+ {
+ nread = fread (raw, 1, DIM (raw)-1, in);
+ if (!nread)
+ break;
+ if (ferror (in))
+ return CDK_File_Error;
+ afx->crc = update_crc (afx->crc, (byte*)raw, nread);
+ base64_encode (buf, (byte*)raw, nread, DIM (buf)-1);
+ fprintf (out, "%s%s", buf, lf);
}
- return rc;
+ crcbuf2[0] = afx->crc >> 16;
+ crcbuf2[1] = afx->crc >> 8;
+ crcbuf2[2] = afx->crc;
+ crcbuf[0] = b64chars[crcbuf2[0] >> 2];
+ crcbuf[1] = b64chars[((crcbuf2[0] << 4) & 0x30) |(crcbuf2[1] >> 4)];
+ crcbuf[2] = b64chars[((crcbuf2[1] << 2) & 0x3c) |(crcbuf2[2] >> 6)];
+ crcbuf[3] = b64chars[crcbuf2[2] & 0x3f];
+ fprintf (out, "=%s%s", crcbuf, lf);
+ fprintf (out, "-----%s-----%s", armor_end[afx->idx2], lf);
+
+ return 0;
}
@@ -393,23 +389,24 @@ cdk_armor_filter_use (cdk_stream_t inp)
static int
search_header (const char *buf, const char **array)
{
- const char *s;
- int i;
-
- if( strlen( buf ) < 5 || strncmp( buf, "-----", 5 ) )
- return -1;
- for( i = 0; (s = array[i]); i++ ) {
- if( !strncmp( s, buf + 5, strlen( s ) ) )
- return i;
+ const char *s;
+ int i;
+
+ if (strlen (buf) < 5 || strncmp (buf, "-----", 5))
+ return -1;
+ for (i = 0; (s = array[i]); i++)
+ {
+ if (!strncmp (s, buf + 5, strlen (s)))
+ return i;
}
- return -1;
+ return -1;
}
-const char *
+const char*
_cdk_armor_get_lineend( void )
{
- return LF;
+ return LF;
}
@@ -583,58 +580,64 @@ 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_stream_t inp, out;
- int rc = 0, zipalgo;
-
- rc = _cdk_check_args( 1, 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;
+ int zipalgo;
- rc = cdk_stream_create( output, &out );
- if( rc ) {
- cdk_stream_close( inp );
- return rc;
+ rc = _cdk_check_args (1, file, output);
+ if (rc)
+ return rc;
+
+ rc = cdk_stream_open (file, &inp);
+ if (rc)
+ return rc;
+
+ rc = cdk_stream_create (output, &out);
+ if (rc)
+ {
+ cdk_stream_close( inp );
+ return rc;
}
-
- if( cdk_armor_filter_use( inp ) ) {
- rc = cdk_stream_set_literal_flag( inp, 0, NULL );
- zipalgo = cdk_stream_is_compressed (inp);
- if( zipalgo )
- rc = cdk_stream_set_compress_flag( inp, zipalgo, 0 );
- if( !rc )
- rc = cdk_stream_set_armor_flag( inp, 0 );
- if( !rc )
- rc = cdk_stream_kick_off( inp, out );
- if( !rc )
- rc = _cdk_stream_get_errno( inp );
+
+ if (cdk_armor_filter_use (inp))
+ {
+ rc = cdk_stream_set_literal_flag (inp, 0, NULL);
+ zipalgo = cdk_stream_is_compressed (inp);
+ if (zipalgo)
+ rc = cdk_stream_set_compress_flag (inp, zipalgo, 0);
+ if (!rc)
+ rc = cdk_stream_set_armor_flag (inp, 0);
+ if (!rc)
+ rc = cdk_stream_kick_off (inp, out);
+ if (!rc)
+ rc = _cdk_stream_get_errno (inp);
}
-
- cdk_stream_close( inp );
- cdk_stream_close( out );
- return rc;
+
+ cdk_stream_close (inp);
+ cdk_stream_close (out);
+ return rc;
}
int
_cdk_filter_armor (void *opaque, int ctl, FILE * in, FILE *out)
{
- if( ctl == STREAMCTL_READ )
- return armor_decode( opaque, in, out );
- else if( ctl == STREAMCTL_WRITE )
- return armor_encode( opaque, in, out );
- else if( ctl == STREAMCTL_FREE ) {
- armor_filter_t * afx = opaque;
- if( afx ) {
- _cdk_log_debug( "free armor filter\n" );
- afx->idx = afx->idx2 = 0;
- afx->crc = afx->crc_okay = 0;
- }
+ if (ctl == STREAMCTL_READ)
+ return armor_decode (opaque, in, out);
+ else if (ctl == STREAMCTL_WRITE)
+ return armor_encode (opaque, in, out);
+ else if (ctl == STREAMCTL_FREE)
+ {
+ armor_filter_t * afx = opaque;
+ if (afx)
+ {
+ _cdk_log_debug ("free armor filter\n");
+ afx->idx = afx->idx2 = 0;
+ afx->crc = afx->crc_okay = 0;
+ return 0;
+ }
}
- return CDK_Inv_Mode;
+ return CDK_Inv_Mode;
}
@@ -709,7 +712,6 @@ cdk_armor_encode_buffer (const byte *inbuf, size_t inlen,
memcpy (outbuf+pos, le, strlen (le)); pos += strlen (le);
}
- /* FIXME: We do not generate a CRC for the data, which is legal. */
memcpy (outbuf+pos, "-----", 5); pos += 5;
memcpy (outbuf+pos, tail, strlen (tail)); pos += strlen (tail);
memcpy (outbuf+pos, "-----", 5); pos += 5;
diff --git a/libextra/opencdk/cipher.c b/libextra/opencdk/cipher.c
index 3fb7f94e55..900fb7a21b 100644
--- a/libextra/opencdk/cipher.c
+++ b/libextra/opencdk/cipher.c
@@ -40,7 +40,7 @@ fp_get_length (FILE *fp)
static cdk_error_t
hash_encode (void *opaque, FILE *in, FILE *out)
{
- md_filter_t * mfx = opaque;
+ md_filter_t *mfx = opaque;
byte buf[BUFSIZE];
gcry_error_t err;
int nread;
@@ -48,7 +48,7 @@ hash_encode (void *opaque, FILE *in, FILE *out)
if (!mfx)
return CDK_Inv_Value;
- _cdk_log_debug ("hash filter: encode (algo=%d)\n", mfx->digest_algo);
+ _cdk_log_debug ("hash filter: encode algo=%d\n", mfx->digest_algo);
if (!mfx->md)
{
@@ -86,7 +86,7 @@ _cdk_filter_hash (void *opaque, int ctl, FILE *in, FILE *out)
return 0;
}
}
- return CDK_Inv_Mode;
+ return CDK_Inv_Mode;
}
@@ -110,8 +110,10 @@ write_header (cipher_filter_t *cfx, FILE *out)
output and thus we offer to supress the MDC packet. */
use_mdc = dek->use_mdc;
if (blocksize == 8)
- use_mdc = 0; /* Enabled by default for all 128-bit block cipher */
+ use_mdc = 0;
+ /* We need to increase the data length because the MDC packet will
+ be also included. It has a fixed length of 22 octets. */
if (use_mdc && cfx->datalen)
cfx->datalen += 22;
@@ -213,10 +215,10 @@ static cdk_error_t
write_partial_block (FILE *in, FILE *out, off_t *r_len,
cipher_filter_t *cfx)
{
+ gcry_error_t err;
byte buf[DEF_BLOCKSIZE];
size_t n;
int nread;
- gcry_error_t err;
if (!out || !cfx)
return CDK_Inv_Value;
@@ -424,8 +426,8 @@ cipher_decode_file (void *opaque, FILE *in, FILE *out)
while (!feof (in))
{
- _cdk_log_debug ("partial on=%d size=%lu\n",
- cfx->blkmode.on, cfx->blkmode.size);
+ /*_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)
@@ -460,22 +462,22 @@ cipher_decode_file (void *opaque, FILE *in, FILE *out)
static cdk_error_t
-cipher_decode( void * opaque, FILE * in, FILE * out )
+cipher_decode (void * opaque, FILE * in, FILE * out)
{
- cipher_filter_t * cfx = opaque;
- cdk_error_t rc;
-
- _cdk_log_debug ("cipher filter: decode\n");
+ cipher_filter_t * cfx = opaque;
+ cdk_error_t rc;
- if( !cfx || !in || !out )
- return CDK_Inv_Value;
+ _cdk_log_debug ("cipher filter: decode\n");
- rc = read_header( cfx, in );
- if( !rc )
- rc = cipher_decode_file( cfx, in, out );
- return rc;
+ if (!cfx || !in || !out)
+ return CDK_Inv_Value;
+
+ rc = read_header (cfx, in);
+ if (!rc)
+ rc = cipher_decode_file (cfx, in, out);
+ return rc;
}
-
+
static cdk_error_t
cipher_encode (void *opaque, FILE *in, FILE *out)
@@ -499,22 +501,25 @@ cipher_encode (void *opaque, FILE *in, FILE *out)
cdk_error_t
-_cdk_filter_cipher( void * opaque, int ctl, FILE * in, FILE * out )
+_cdk_filter_cipher (void * opaque, int ctl, FILE * in, FILE * out)
{
- if( ctl == STREAMCTL_READ )
- return cipher_decode( opaque, in, out );
- else if( ctl == STREAMCTL_WRITE )
- return cipher_encode( opaque, in, out );
- else if( ctl == STREAMCTL_FREE ) {
- cipher_filter_t * cfx = opaque;
- if( cfx ) {
- _cdk_log_debug( "free cipher filter\n" );
- gcry_md_close( cfx->mdc );
- cfx->mdc = NULL;
- gcry_cipher_close( cfx->hd );
- cfx->hd = NULL;
- }
+ if (ctl == STREAMCTL_READ)
+ return cipher_decode (opaque, in, out);
+ else if (ctl == STREAMCTL_WRITE)
+ return cipher_encode( opaque, in, out );
+ else if (ctl == STREAMCTL_FREE)
+ {
+ cipher_filter_t * cfx = opaque;
+ if (cfx)
+ {
+ _cdk_log_debug( "free cipher filter\n" );
+ gcry_md_close( cfx->mdc );
+ cfx->mdc = NULL;
+ gcry_cipher_close( cfx->hd );
+ cfx->hd = NULL;
+ return 0;
+ }
}
- return CDK_Inv_Mode;
+ return CDK_Inv_Mode;
}
diff --git a/libextra/opencdk/compress.c b/libextra/opencdk/compress.c
index b67bffdd43..f9dd0ca2a7 100644
--- a/libextra/opencdk/compress.c
+++ b/libextra/opencdk/compress.c
@@ -222,8 +222,8 @@ _cdk_filter_compress (void *opaque, int ctl, FILE *in, FILE *out)
_cdk_log_debug ("free compress filter\n");
zfx->level = 0;
zfx->algo = 0;
+ return 0;
}
- return 0;
}
return CDK_Inv_Mode;
}
diff --git a/libextra/opencdk/context.h b/libextra/opencdk/context.h
index 7ff2a9c401..e656952302 100644
--- a/libextra/opencdk/context.h
+++ b/libextra/opencdk/context.h
@@ -30,6 +30,7 @@ struct cdk_listkey_s {
cdk_strlist_t t;
};
+
struct cdk_s2k_s {
int mode;
byte hash_algo;
@@ -37,6 +38,7 @@ struct cdk_s2k_s {
u32 count;
};
+
struct cdk_ctx_s {
int cipher_algo;
int digest_algo;
@@ -93,43 +95,6 @@ struct cdk_subpkt_s {
byte d[1];
};
-
-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;
- off_t offset;
- cdk_dbsearch_t desc;
-};
-
-
-
-struct cdk_keydb_hd_s {
- 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 {
diff --git a/libextra/opencdk/filters.h b/libextra/opencdk/filters.h
index 2c1b2014e0..a60881edb8 100644
--- a/libextra/opencdk/filters.h
+++ b/libextra/opencdk/filters.h
@@ -50,7 +50,7 @@ typedef struct {
} armor_filter_t;
typedef struct {
- int mode;
+ cdk_lit_format_t mode;
char *orig_filename; /* This original name of the input file. */
char *filename;
gcry_md_hd_t md;
diff --git a/libextra/opencdk/kbnode.c b/libextra/opencdk/kbnode.c
index 4595f18b2b..848a34214b 100644
--- a/libextra/opencdk/kbnode.c
+++ b/libextra/opencdk/kbnode.c
@@ -1,5 +1,5 @@
/* kbnode.c - keyblock node utility functions
- * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ * Copyright (C) 1998-2001 Free Software Foundation, Inc.
* Copyright (C) 2002, 2003, 2007 Timo Schulz
*
* This file is part of OpenCDK.
diff --git a/libextra/opencdk/keydb.c b/libextra/opencdk/keydb.c
index 26bc6dd1a7..311565e27f 100644
--- a/libextra/opencdk/keydb.c
+++ b/libextra/opencdk/keydb.c
@@ -33,8 +33,8 @@
#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;
+/* Internal key index structure. */
struct key_idx_s
{
off_t offset;
@@ -44,6 +44,45 @@ struct key_idx_s
typedef struct key_idx_s *key_idx_t;
+/* Internal handle for the search operation. */
+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;
+
+/* Internal key cache to associate a key with an file offset. */
+struct key_table_s
+{
+ struct key_table_s * next;
+ off_t offset;
+ cdk_dbsearch_t desc;
+};
+typedef struct key_table_s *key_table_t;
+
+/* Internal key database handle. */
+struct cdk_keydb_hd_s
+{
+ 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;
+};
+
+
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);
@@ -145,19 +184,19 @@ 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 db)
{
struct stat stbuf;
char *tmp_idx_name;
cdk_error_t rc;
int err;
- if (!hd || !hd->name)
+ if (!db || !db->name)
return CDK_Inv_Value;
- if (hd->secret)
+ if (db->secret)
return 0;
- tmp_idx_name = keydb_idx_mkname (hd->name);
+ tmp_idx_name = keydb_idx_mkname (db->name);
if (!tmp_idx_name)
return CDK_Out_Of_Core;
err = stat (tmp_idx_name, &stbuf);
@@ -167,22 +206,22 @@ cdk_keydb_idx_rebuild (cdk_keydb_hd_t hd)
if (err)
return 0;
- cdk_stream_close (hd->idx);
- hd->idx = NULL;
- if (!hd->idx_name)
+ cdk_stream_close (db->idx);
+ db->idx = NULL;
+ if (!db->idx_name)
{
- hd->idx_name = keydb_idx_mkname (hd->name);
- if (!hd->idx_name)
+ db->idx_name = keydb_idx_mkname (db->name);
+ if (!db->idx_name)
return CDK_Out_Of_Core;
}
- rc = keydb_idx_build (hd->name);
+ rc = keydb_idx_build (db->name);
if (!rc)
- rc = cdk_stream_open (hd->idx_name, &hd->idx);
+ rc = cdk_stream_open (db->idx_name, &db->idx);
return rc;
}
-static int
+static cdk_error_t
keydb_idx_parse (cdk_stream_t inp, key_idx_t *r_idx)
{
key_idx_t idx;
@@ -212,7 +251,7 @@ keydb_idx_parse (cdk_stream_t inp, key_idx_t *r_idx)
}
-static int
+static cdk_error_t
keydb_idx_search (cdk_stream_t inp, u32 *keyid, const byte *fpr, off_t *r_off)
{
key_idx_t idx;
@@ -256,27 +295,27 @@ keydb_idx_search (cdk_stream_t inp, u32 *keyid, const byte *fpr, off_t *r_off)
* 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,
+cdk_keydb_new_from_mem (cdk_keydb_hd_t *r_db, int secret,
const void *data, size_t datlen)
{
- cdk_keydb_hd_t hd;
+ cdk_keydb_hd_t db;
cdk_error_t rc;
- if (!r_hd)
+ if (!r_db)
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)
+ *r_db = NULL;
+ db = calloc (1, sizeof *db);
+ rc = cdk_stream_tmp_from_mem (data, datlen, &db->buf);
+ if (!db->buf)
{
- cdk_free (hd);
+ cdk_free (db);
return rc;
}
- 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;
+ if (cdk_armor_filter_use (db->buf))
+ cdk_stream_set_armor_flag (db->buf, 0);
+ db->type = CDK_DBTYPE_DATA;
+ db->secret = secret;
+ *r_db = db;
return 0;
}
@@ -661,7 +700,7 @@ keydb_cache_find (key_table_t cache, cdk_dbsearch_t desc)
}
-static int
+static cdk_error_t
keydb_cache_add (cdk_keydb_hd_t hd, cdk_dbsearch_t dbs, off_t offset)
{
key_table_t k;
@@ -679,7 +718,7 @@ keydb_cache_add (cdk_keydb_hd_t hd, cdk_dbsearch_t dbs, off_t offset)
k->next = hd->cache;
hd->cache = k;
hd->ncache++;
- _cdk_log_debug ("cache: add entry [o=%d t=%d]\n", offset, dbs->type);
+ _cdk_log_debug ("cache: add entry off=%d type=%d\n", offset, dbs->type);
return 0;
}
@@ -692,6 +731,7 @@ keydb_search_copy (cdk_dbsearch_t *r_dst, cdk_dbsearch_t src)
if (!r_dst || !src)
return CDK_Inv_Value;
+ *r_dst = NULL;
dst = cdk_calloc (1, sizeof *dst);
if (!dst)
return CDK_Out_Of_Core;
@@ -843,7 +883,7 @@ cdk_keydb_search_start (cdk_keydb_hd_t db, int type, void *desc)
}
-static int
+static cdk_error_t
keydb_pos_from_cache (cdk_keydb_hd_t hd, cdk_dbsearch_t ks,
int *r_cache_hit, off_t *r_off)
{
@@ -859,7 +899,7 @@ keydb_pos_from_cache (cdk_keydb_hd_t hd, cdk_dbsearch_t ks,
c = keydb_cache_find (hd->cache, ks);
if (c != NULL)
{
- _cdk_log_debug ("Cache: found entry in cache.\n");
+ _cdk_log_debug ("cache: found entry in cache.\n");
*r_cache_hit = 1;
*r_off = c->offset;
return 0;
@@ -875,14 +915,14 @@ keydb_pos_from_cache (cdk_keydb_hd_t hd, cdk_dbsearch_t ks,
{
if (keydb_idx_search (hd->idx, ks->u.keyid, NULL, r_off))
return CDK_Error_No_Key;
- _cdk_log_debug ("Cache: found keyid entry in idx table.\n");
+ _cdk_log_debug ("cache: found keyid entry in idx table.\n");
*r_cache_hit = 1;
}
else if (ks->type == CDK_DBSEARCH_FPR)
{
if (keydb_idx_search (hd->idx, NULL, ks->u.fpr, r_off))
return CDK_Error_No_Key;
- _cdk_log_debug ("Cache: found fpr entry in idx table.\n");
+ _cdk_log_debug ("cache: found fpr entry in idx table.\n");
*r_cache_hit = 1;
}
}
@@ -1138,14 +1178,16 @@ keydb_find_bykeyid (cdk_kbnode_t root, const u32 *keyid, int search_mode)
}
-int
+cdk_error_t
_cdk_keydb_get_sk_byusage (cdk_keydb_hd_t hd, const char *name,
- cdk_pkt_seckey_t* ret_sk, int usage)
+ cdk_seckey_t* ret_sk, int usage)
{
- cdk_kbnode_t knode = NULL, node;
+ cdk_kbnode_t knode = NULL;
+ cdk_kbnode_t node, sk_node;
cdk_pkt_seckey_t sk;
- const char *s;
cdk_error_t rc;
+ const char *s;
+ int pkttype;
if (!ret_sk || !usage)
return CDK_Inv_Value;
@@ -1161,16 +1203,17 @@ _cdk_keydb_get_sk_byusage (cdk_keydb_hd_t hd, const char *name,
if (rc)
return rc;
- node = keydb_find_byusage (knode, usage, 0);
- if (!node)
+ sk_node = keydb_find_byusage (knode, usage, 0);
+ if (!sk_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;
+ /* We clone the node with the secret key to avoid that the
+ packet will be released. */
+ _cdk_kbnode_clone (sk_node);
+ sk = sk_node->pkt->pkt.secret_key;
for (node = knode; node; node = node->next)
{
@@ -1189,15 +1232,17 @@ _cdk_keydb_get_sk_byusage (cdk_keydb_hd_t hd, const char *name,
if (sk->pk->uid && node)
_cdk_copy_signature (&sk->pk->uid->selfsig, node->pkt->pkt.signature);
+ /* We release the outer packet. */
+ _cdk_pkt_detach_free (sk_node->pkt, &pkttype, (void*)&sk);
cdk_kbnode_release (knode);
*ret_sk = sk;
return rc;
}
-int
+cdk_error_t
_cdk_keydb_get_pk_byusage (cdk_keydb_hd_t hd, const char *name,
- cdk_pkt_pubkey_t *ret_pk, int usage)
+ cdk_pubkey_t *ret_pk, int usage)
{
cdk_kbnode_t knode, node = NULL;
cdk_pkt_pubkey_t pk = NULL;
@@ -1248,12 +1293,13 @@ _cdk_keydb_get_pk_byusage (cdk_keydb_hd_t hd, const char *name,
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_pubkey_t *r_pk)
{
cdk_kbnode_t knode = NULL, node;
- cdk_pkt_pubkey_t pk;
+ cdk_pubkey_t pk;
+ cdk_error_t rc;
size_t s_type;
- int rc;
+ int pkttype;
if (!keyid || !r_pk)
return CDK_Inv_Value;
@@ -1275,12 +1321,13 @@ cdk_keydb_get_pk (cdk_keydb_hd_t hd, u32 *keyid, cdk_pkt_pubkey_t *r_pk)
cdk_kbnode_release (knode);
return CDK_Error_No_Key;
}
-
- pk = node->pkt->pkt.public_key;
+
+ /* See comment in cdk_keydb_get_sk() */
+ _cdk_pkt_detach_free (node->pkt, &pkttype, (void*)&pk);
+ *r_pk = pk;
_cdk_kbnode_clone (node);
cdk_kbnode_release (knode);
- *r_pk = pk;
return rc;
}
@@ -1291,6 +1338,7 @@ cdk_keydb_get_sk (cdk_keydb_hd_t hd, u32 *keyid, cdk_seckey_t *ret_sk)
cdk_kbnode_t snode, node;
cdk_seckey_t sk;
cdk_error_t rc;
+ int pkttype;
if (!keyid || !ret_sk)
return CDK_Inv_Value;
@@ -1309,7 +1357,9 @@ cdk_keydb_get_sk (cdk_keydb_hd_t hd, u32 *keyid, cdk_seckey_t *ret_sk)
return CDK_Error_No_Key;
}
- sk = node->pkt->pkt.secret_key;
+ /* We need to release the packet itself but not its contents
+ and thus we detach the openpgp packet and release the structure. */
+ _cdk_pkt_detach_free (node->pkt, &pkttype, (void*)&sk);
_cdk_kbnode_clone (node);
cdk_kbnode_release (snode);
@@ -1351,7 +1401,7 @@ find_selfsig_node (cdk_kbnode_t key, cdk_pkt_pubkey_t pk)
-static int
+static cdk_error_t
keydb_merge_selfsig (cdk_kbnode_t key, u32 *keyid)
{
cdk_kbnode_t node, kbnode, unode;
@@ -1662,7 +1712,11 @@ cdk_keydb_get_keyblock (cdk_stream_t inp, cdk_kbnode_t *r_knode)
if (rc == CDK_EOF)
break;
else
- return rc;
+ { /* Release all packets we reached so far. */
+ _cdk_log_debug ("keydb_get_keyblock: error %d\n", rc);
+ cdk_kbnode_release (knode);
+ return rc;
+ }
}
if (pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY ||
@@ -1701,7 +1755,7 @@ cdk_keydb_get_keyblock (cdk_stream_t inp, cdk_kbnode_t *r_knode)
/* 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)
@@ -1733,6 +1787,10 @@ cdk_keydb_get_keyblock (cdk_stream_t inp, cdk_kbnode_t *r_knode)
else
cdk_kbnode_release (knode);
*r_knode = got_key? knode : NULL;
+
+ /* It is possible that we are in an EOF condition after we
+ successfully read a keyblock. For example if the requested
+ key is the last in the file. */
if (rc == CDK_EOF && got_key)
rc = 0;
return rc;
@@ -1898,7 +1956,7 @@ cdk_keydb_import (cdk_keydb_hd_t hd, cdk_kbnode_t knode)
}
-int
+cdk_error_t
_cdk_keydb_check_userid (cdk_keydb_hd_t hd, u32 * keyid, const char *id)
{
cdk_kbnode_t knode = NULL, unode = NULL;
@@ -1934,7 +1992,7 @@ _cdk_keydb_check_userid (cdk_keydb_hd_t hd, u32 * keyid, const char *id)
check++;
cdk_kbnode_release (knode);
- return check==2 ? 1 : 0;
+ return check==2 ? 0 : CDK_Inv_Value;
}
@@ -2099,3 +2157,9 @@ cdk_listkey_next (cdk_listkey_t ctx, cdk_kbnode_t *ret_key)
}
return CDK_General_Error;
}
+
+int
+_cdk_keydb_is_secret (cdk_keydb_hd_t db)
+{
+ return db->secret;
+}
diff --git a/libextra/opencdk/literal.c b/libextra/opencdk/literal.c
index 5fae806f02..e38e564bbf 100644
--- a/libextra/opencdk/literal.c
+++ b/libextra/opencdk/literal.c
@@ -63,16 +63,11 @@ literal_decode (void *opaque, FILE *in, FILE *out)
cdk_pkt_new (&pkt);
rc = cdk_pkt_read (si, pkt);
- if (rc)
- {
- cdk_stream_close (si);
- return rc;
- }
- if (pkt->pkttype != CDK_PKT_LITERAL)
+ if (rc || pkt->pkttype != CDK_PKT_LITERAL)
{
cdk_pkt_release (pkt);
cdk_stream_close (si);
- return CDK_Inv_Packet;
+ return !rc? CDK_Inv_Packet: rc;
}
rc = _cdk_stream_fpopen (out, STREAMCTL_WRITE, &so);
@@ -149,6 +144,21 @@ literal_decode (void *opaque, FILE *in, FILE *out)
}
+static char
+intmode_to_char (int mode)
+{
+ switch (mode)
+ {
+ case CDK_LITFMT_BINARY: return 'b';
+ case CDK_LITFMT_TEXT: return 't';
+ case CDK_LITFMT_UNICODE:return 'u';
+ default: return 'b';
+ }
+
+ return 'b';
+}
+
+
static cdk_error_t
literal_encode (void *opaque, FILE *in, FILE *out)
{
@@ -187,7 +197,7 @@ literal_encode (void *opaque, FILE *in, FILE *out)
pt->namelen = filelen;
pt->name[pt->namelen] = '\0';
pt->timestamp = (u32)time (NULL);
- pt->mode = pfx->mode ? 't' : 'b';
+ pt->mode = intmode_to_char (pfx->mode);
pt->len = cdk_stream_get_length (si);
pt->buf = si;
pkt->old_ctb = 1;
@@ -218,6 +228,7 @@ _cdk_filter_literal (void * opaque, int ctl, FILE * in, FILE * out)
pfx->filename = NULL;
cdk_free (pfx->orig_filename);
pfx->orig_filename = NULL;
+ return 0;
}
}
return CDK_Inv_Mode;
diff --git a/libextra/opencdk/main.c b/libextra/opencdk/main.c
index 3f863b6cec..2d3648ef3a 100644
--- a/libextra/opencdk/main.c
+++ b/libextra/opencdk/main.c
@@ -96,6 +96,7 @@ cdk_strerror (int ec)
case CDK_Unusable_Key: return "Unusable public key";
case CDK_No_Data: return "No data";
case CDK_No_Passphrase: return "No passphrase supplied";
+ case CDK_Network_Error: return "A network error occurred";
default: sprintf (buf, "ec=%d", ec); return buf;
}
return NULL;
@@ -105,7 +106,7 @@ cdk_strerror (int ec)
static void
out_of_core (size_t n)
{
- fprintf (stderr, "\n ** fatal error: out of memory (%d bytes) **\n", n);
+ fprintf (stderr, "\n ** fatal error: out of memory (%d bytes) **\n", n);
}
@@ -126,12 +127,12 @@ cdk_set_malloc_hooks (void *(*new_alloc_func) (size_t n),
void *(*new_calloc_func) (size_t m, size_t n),
void (*new_free_func) (void *))
{
- alloc_func = new_alloc_func;
- alloc_secure_func = new_alloc_secure_func;
- realloc_func = new_realloc_func;
- calloc_func = new_calloc_func;
- free_func = new_free_func;
- malloc_hooks = 1;
+ alloc_func = new_alloc_func;
+ alloc_secure_func = new_alloc_secure_func;
+ realloc_func = new_realloc_func;
+ calloc_func = new_calloc_func;
+ free_func = new_free_func;
+ malloc_hooks = 1;
}
@@ -143,29 +144,37 @@ cdk_set_malloc_hooks (void *(*new_alloc_func) (size_t n),
int
cdk_malloc_hook_initialized (void)
{
- return malloc_hooks;
+ return malloc_hooks;
}
void*
cdk_malloc (size_t size)
{
- void *p = alloc_func (size);
- if (!p)
- out_of_core (size);
- return p;
+ void *p = alloc_func (size);
+ if (!p)
+ out_of_core (size);
+ return p;
}
-void *
+/**
+ * cdk_calloc:
+ * @n: amount of elements
+ * @m: size of one element
+ *
+ * Safe wrapper around the c-function calloc.
+ **/
+void*
cdk_calloc (size_t n, size_t m)
{
- void * p = calloc_func (n, m);
- if (!p)
- out_of_core (m);
- return p;
+ void * p = calloc_func (n, m);
+ if (!p)
+ out_of_core (m);
+ return p;
}
+
/* Things which need to be done after the secure memory initialisation. */
static void
_secmem_finish (void)
@@ -174,6 +183,7 @@ _secmem_finish (void)
}
+/* Initialize the secure memory. */
static void
_secmem_init (size_t size)
{
@@ -181,10 +191,17 @@ _secmem_init (size_t size)
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;
+
+ /* Check if no other library has already initialized gcrypt. */
+ if (!gcry_control (GCRYCTL_ANY_INITIALIZATION_P))
+ {
+ _cdk_log_debug ("init: libgcrypt initialize.\n");
+ gcry_control (GCRYCTL_INIT_SECMEM, size, 0);
+ gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
+ gcry_control (GCRYCTL_DISABLE_SECMEM_WARN);
+ gcry_control (GCRYCTL_INITIALIZATION_FINISHED, NULL, 0);
+ secmem_init = 1;
+ }
}
@@ -281,31 +298,32 @@ cdk_salloc (size_t size, int clear)
void *
cdk_realloc (void *ptr, size_t size)
{
- void * p = realloc_func (ptr, size);
- if (!p)
- out_of_core (size);
- return p;
+ void * p = realloc_func (ptr, size);
+ if (!p)
+ out_of_core (size);
+ return p;
}
char *
cdk_strdup (const char * ptr)
{
- char * p = cdk_malloc (strlen (ptr) + 1);
- if (p)
- strcpy (p, ptr);
- return p;
+ char * p = cdk_malloc (strlen (ptr) + 1);
+ if (p)
+ strcpy (p, ptr);
+ return p;
}
void
cdk_free (void * ptr)
{
- if (ptr)
- free_func (ptr);
+ if (ptr)
+ free_func (ptr);
}
+/* Internal logging routine. */
static void
_cdk_logv (int level, const char *fmt, va_list arg_ptr)
{
@@ -328,7 +346,7 @@ _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 custom handler for logging.
**/
void
cdk_set_log_handler (cdk_log_fnc_t logfnc, void *opaque)
@@ -351,6 +369,7 @@ cdk_set_log_level (int level)
}
+/* Return the current log level of the lib. */
int
_cdk_get_log_level (void)
{
@@ -618,7 +637,6 @@ cdk_handle_set_keyring (cdk_ctx_t hd, int type, const char *kringname)
return 0;
}
-
/**
* cdk_handle_set_keydb:
@@ -634,7 +652,7 @@ cdk_handle_set_keydb (cdk_ctx_t hd, cdk_keydb_hd_t db)
{
if (!hd)
return;
- if (db->secret)
+ if (_cdk_keydb_is_secret (db))
hd->db.sec = db;
else
hd->db.pub = db;
@@ -662,7 +680,6 @@ cdk_handle_get_keydb (cdk_ctx_t hd, int type)
}
-
/**
* cdk_handle_set_passphrase_cb:
* @hd: session handle
@@ -682,6 +699,13 @@ void cdk_handle_set_passphrase_cb (cdk_ctx_t hd,
}
+/**
+ * cdk_handle_verify_get_result:
+ * @hd: the session handle
+ *
+ * Return the verify result for the current session.
+ * Do not free the pointer.
+ **/
cdk_verify_result_t
cdk_handle_verify_get_result (cdk_ctx_t hd)
{
diff --git a/libextra/opencdk/main.h b/libextra/opencdk/main.h
index 10ef55711a..73c4b8d3a4 100644
--- a/libextra/opencdk/main.h
+++ b/libextra/opencdk/main.h
@@ -79,7 +79,8 @@ int _cdk_check_args( int overwrite, const char * in, const char * out );
u32 _cdk_buftou32 (const byte * buf);
void _cdk_u32tobuf (u32 u, byte * buf);
const char *_cdk_memistr (const char * buf, size_t buflen, const char * sub);
-cdk_error_t map_gcry_error (gcry_error_t err);
+cdk_error_t _cdk_map_gcry_error (gcry_error_t err);
+#define map_gcry_error(err) _cdk_map_gcry_error (err)
/* Helper to provide case insentensive strstr version. */
#define stristr(haystack, needle) \
@@ -102,6 +103,7 @@ int _cdk_sk_get_csum( cdk_pkt_seckey_t sk );
/*-- 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);
+void _cdk_pkt_detach_free (cdk_packet_t pkt, int *r_pkttype, void **ctx);
/*-- sig-check.c --*/
int _cdk_sig_check (cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig,
@@ -124,11 +126,13 @@ int _cdk_digest_encode_pkcs1 (byte ** r_md, size_t * r_mdlen, int pk_algo,
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,
+int _cdk_keydb_is_secret (cdk_keydb_hd_t db);
+cdk_error_t _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_error_t _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);
+cdk_error_t _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 );
@@ -164,7 +168,9 @@ 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 --*/
+/*-- seskey.c --*/
+cdk_error_t _cdk_s2k_copy (cdk_s2k_t *r_dst, cdk_s2k_t src);
+
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);
diff --git a/libextra/opencdk/misc.c b/libextra/opencdk/misc.c
index 85a567fef0..be6b6b68d0 100644
--- a/libextra/opencdk/misc.c
+++ b/libextra/opencdk/misc.c
@@ -54,42 +54,43 @@ _cdk_u32tobuf (u32 u, byte *buf)
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] ) )
+ if (*s == '0' && isdigit (s[1]))
return NULL;
/* leading zeros are not allowed */
- for( ; isdigit(*s); s++ ) {
- val *= 10;
- val += *s - '0';
- }
+ 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 != '.' )
- return NULL;
- s++;
- s = parse_version_number (s, minor);
- if (!s || *s != '.')
- return NULL;
- s++;
- s = parse_version_number(s, micro);
- if (!s)
- return NULL;
- return s; /* patchlevel */
+ s = parse_version_number( s, major );
+ if( !s || *s != '.' )
+ return NULL;
+ s++;
+ s = parse_version_number (s, minor);
+ if (!s || *s != '.')
+ return NULL;
+ s++;
+ s = parse_version_number(s, micro);
+ if (!s)
+ return NULL;
+ return s; /* patchlevel */
}
/**
- * cdk_check_version - Version control handling.
+ * cdk_check_version:
* @req_version: The requested version
*
* Check that the the version of the library is at minimum the requested
@@ -100,40 +101,45 @@ parse_version_string( const char * s, int * major, int * minor, int * micro )
const char *
cdk_check_version (const char *req_version)
{
- const char *ver = VERSION;
- int my_major, my_minor, my_micro;
- int rq_major, rq_minor, rq_micro;
- const char *my_plvl, *rq_plvl;
+ const char *ver = VERSION;
+ int my_major, my_minor, my_micro;
+ int rq_major, rq_minor, rq_micro;
+ const char *my_plvl, *rq_plvl;
- if (!req_version)
- return ver;
- my_plvl = parse_version_string (ver, &my_major, &my_minor, &my_micro);
- if (!my_plvl)
- return NULL;
- /* very strange our own version is bogus */
- rq_plvl = parse_version_string (req_version, &rq_major, &rq_minor,
- &rq_micro);
- if (!rq_plvl)
- return NULL; /* req version string is invalid */
- if (my_major > rq_major
- || (my_major == rq_major && my_minor > rq_minor)
- || (my_major == rq_major && my_minor == rq_minor
- && my_micro > rq_micro)
- || (my_major == rq_major && my_minor == rq_minor
- && my_micro == rq_micro
- && strcmp (my_plvl, rq_plvl) >= 0)) {
- return ver;
- }
+ if (!req_version)
+ return ver;
+ my_plvl = parse_version_string (ver, &my_major, &my_minor, &my_micro);
+ if (!my_plvl)
return NULL;
+ /* very strange our own version is bogus */
+ rq_plvl = parse_version_string (req_version, &rq_major, &rq_minor,
+ &rq_micro);
+ if (!rq_plvl)
+ return NULL; /* req version string is invalid */
+ if (my_major > rq_major
+ || (my_major == rq_major && my_minor > rq_minor)
+ || (my_major == rq_major && my_minor == rq_minor
+ && my_micro > rq_micro)
+ || (my_major == rq_major && my_minor == rq_minor
+ && my_micro == rq_micro
+ && strcmp (my_plvl, rq_plvl) >= 0))
+ return ver;
+ return NULL;
}
+/**
+ * cdk_strlist_free:
+ * @sl: the string list
+ *
+ * Release the string list object.
+ **/
void
cdk_strlist_free (cdk_strlist_t sl)
{
cdk_strlist_t sl2;
- for(; sl; sl = sl2 )
+ for(; sl; sl = sl2)
{
sl2 = sl->next;
cdk_free (sl);
@@ -141,6 +147,13 @@ cdk_strlist_free (cdk_strlist_t sl)
}
+/**
+ * cdk_strlist_add:
+ * @list: destination string list
+ * @string: the string to add
+ *
+ * Add the given list to the string list.
+ **/
cdk_strlist_t
cdk_strlist_add (cdk_strlist_t *list, const char *string)
{
@@ -206,6 +219,12 @@ _cdk_memistr (const char *buf, size_t buflen, const char *sub)
}
+/**
+ * cdk_utf8_encode:
+ * @string:
+ *
+ * Encode the given string in utf8 and return it.
+ **/
char*
cdk_utf8_encode (const char *string)
{
@@ -238,6 +257,14 @@ cdk_utf8_encode (const char *string)
}
+/**
+ * cdk_utf8_decode:
+ * @string: the string to decode
+ * @length: the length of the string
+ * @delim: the delimiter
+ *
+ * Decode the given utf8 string and return the native representation.
+ **/
char *
cdk_utf8_decode (const char * string, size_t length, int delim)
{
@@ -437,8 +464,9 @@ cdk_utf8_decode (const char * string, size_t length, int delim)
}
+/* Map the gcrypt error to a valid opencdk error constant. */
cdk_error_t
-map_gcry_error (gcry_error_t err)
+_cdk_map_gcry_error (gcry_error_t err)
{
/* FIXME: We need to catch them all. */
switch (gpg_err_code (err))
@@ -461,6 +489,7 @@ map_gcry_error (gcry_error_t err)
}
+/* Remove all trailing white spaces from the string. */
void
_cdk_trim_string (char *s, int canon)
{
diff --git a/libextra/opencdk/new-packet.c b/libextra/opencdk/new-packet.c
index 491166e007..865997f691 100644
--- a/libextra/opencdk/new-packet.c
+++ b/libextra/opencdk/new-packet.c
@@ -56,7 +56,7 @@ free_symkey_enc (cdk_pkt_symkey_enc_t enc)
{
if (!enc)
return;
- cdk_free (enc->s2k);
+ cdk_s2k_free (enc->s2k);
cdk_free (enc);
}
@@ -170,7 +170,7 @@ cdk_sk_release (cdk_seckey_t sk)
sk->encdata = NULL;
cdk_pk_release (sk->pk);
sk->pk = NULL;
- cdk_free (sk->protect.s2k);
+ cdk_s2k_free (sk->protect.s2k);
sk->protect.s2k = NULL;
cdk_free (sk);
}
@@ -191,6 +191,38 @@ free_encrypted (cdk_pkt_encrypted_t enc)
}
+/* Detach the openpgp packet from the packet structure
+ and release the packet structure itself. */
+void
+_cdk_pkt_detach_free (cdk_packet_t pkt, int *r_pkttype, void **ctx)
+{
+ /* For now we just allow this for keys. */
+ switch (pkt->pkttype)
+ {
+ case CDK_PKT_PUBLIC_KEY:
+ case CDK_PKT_PUBLIC_SUBKEY:
+ *ctx = pkt->pkt.public_key;
+ break;
+
+ case CDK_PKT_SECRET_KEY:
+ case CDK_PKT_SECRET_SUBKEY:
+ *ctx = pkt->pkt.secret_key;
+ break;
+
+ default:
+ *r_pkttype = 0;
+ return;
+ }
+
+ /* The caller might expect a specific packet type and
+ is not interested to store it for later use. */
+ if (r_pkttype)
+ *r_pkttype = pkt->pkttype;
+
+ cdk_free (pkt);
+}
+
+
void
cdk_pkt_free (cdk_packet_t pkt)
{
@@ -222,6 +254,13 @@ cdk_pkt_free (cdk_packet_t pkt)
}
+/**
+ * cdk_pkt_release:
+ * @pkt: the packet
+ *
+ * Free the contents of the given package and
+ * release the memory of the structure.
+ **/
void
cdk_pkt_release (cdk_packet_t pkt)
{
@@ -232,6 +271,13 @@ cdk_pkt_release (cdk_packet_t pkt)
}
+/**
+ * cdk_pkt_alloc:
+ * @r_pkt: output is the new packet
+ * @pkttype: the requested packet type
+ *
+ * Allocate a new packet structure with the given packet type.
+ **/
cdk_error_t
cdk_pkt_alloc (cdk_packet_t *r_pkt, int pkttype)
{
@@ -346,154 +392,154 @@ _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_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 );
- 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;
+ cdk_pkt_userid_t u;
+
+ if (!dst || !src)
+ return CDK_Inv_Value;
+
+ *dst = NULL;
+ 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;
}
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;
-
- if (!dst || !src)
- return CDK_Inv_Value;
-
- k = cdk_calloc (1, sizeof *k);
- if (!k)
- return CDK_Out_Of_Core;
- memcpy (k, src, sizeof *k);
- if (src->uid)
- _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] = gcry_mpi_copy (src->mpi[i]);
- *dst = k;
-
- return 0;
+ cdk_pkt_pubkey_t k;
+ int i;
+
+ if (!dst || !src)
+ return CDK_Inv_Value;
+
+ *dst = NULL;
+ k = cdk_calloc (1, sizeof *k);
+ if (!k)
+ return CDK_Out_Of_Core;
+ memcpy (k, src, sizeof *k);
+ if (src->uid)
+ _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] = gcry_mpi_copy (src->mpi[i]);
+ *dst = k;
+
+ return 0;
}
cdk_error_t
_cdk_copy_seckey (cdk_pkt_seckey_t* dst, cdk_pkt_seckey_t src)
{
- cdk_pkt_seckey_t k;
- cdk_s2k_t s2k;
- int i;
-
- if (!dst || !src)
- return CDK_Inv_Value;
-
- k = cdk_calloc (1, sizeof *k);
- if (!k)
- return CDK_Out_Of_Core;
- memcpy (k, src, sizeof *k);
- _cdk_copy_pubkey (&k->pk, src->pk);
-
- if (src->encdata) {
- k->encdata = cdk_calloc (1, src->enclen + 1);
- if (!k->encdata)
- return CDK_Out_Of_Core;
- memcpy (k->encdata, src->encdata, src->enclen);
+ cdk_pkt_seckey_t k;
+ int i;
+
+ if (!dst || !src)
+ return CDK_Inv_Value;
+
+ *dst = NULL;
+ k = cdk_calloc (1, sizeof *k);
+ if (!k)
+ return CDK_Out_Of_Core;
+ memcpy (k, src, sizeof *k);
+ _cdk_copy_pubkey (&k->pk, src->pk);
+
+ if (src->encdata)
+ {
+ k->encdata = cdk_calloc (1, src->enclen + 1);
+ if (!k->encdata)
+ return CDK_Out_Of_Core;
+ memcpy (k->encdata, src->encdata, src->enclen);
}
-
- s2k = k->protect.s2k = cdk_calloc (1, sizeof *k->protect.s2k);
- if (!k->protect.s2k)
- return CDK_Out_Of_Core;
- s2k->mode = src->protect.s2k->mode;
- s2k->hash_algo = src->protect.s2k->hash_algo;
- 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++) {
- k->mpi[i] = gcry_mpi_copy (src->mpi[i]);
- gcry_mpi_set_flag (k->mpi[i], GCRYMPI_FLAG_SECURE);
+
+ _cdk_s2k_copy (&k->protect.s2k, src->protect.s2k);
+
+ 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;
-
- return 0;
+
+ *dst = k;
+ return 0;
}
cdk_error_t
-_cdk_copy_pk_to_sk( cdk_pkt_pubkey_t pk, cdk_pkt_seckey_t sk )
+_cdk_copy_pk_to_sk (cdk_pkt_pubkey_t pk, cdk_pkt_seckey_t sk)
{
- if( !pk || !sk )
- return CDK_Inv_Value;
-
- sk->version = pk->version;
- sk->expiredate = pk->expiredate;
- sk->pubkey_algo = pk->pubkey_algo;
- sk->has_expired = pk->has_expired;
- sk->is_revoked = pk->is_revoked;
- sk->main_keyid[0] = pk->main_keyid[0];
- sk->main_keyid[1] = pk->main_keyid[1];
- sk->keyid[0] = pk->keyid[0];
- sk->keyid[1] = pk->keyid[1];
-
- return 0;
+ if (!pk || !sk)
+ return CDK_Inv_Value;
+
+ sk->version = pk->version;
+ sk->expiredate = pk->expiredate;
+ sk->pubkey_algo = pk->pubkey_algo;
+ sk->has_expired = pk->has_expired;
+ sk->is_revoked = pk->is_revoked;
+ sk->main_keyid[0] = pk->main_keyid[0];
+ sk->main_keyid[1] = pk->main_keyid[1];
+ sk->keyid[0] = pk->keyid[0];
+ sk->keyid[1] = pk->keyid[1];
+
+ return 0;
}
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;
-
- if( !dst || !src )
- return CDK_Inv_Value;
-
- s = cdk_calloc( 1, sizeof *s );
- if( !s )
- return CDK_Out_Of_Core;
- 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;
+ cdk_pkt_signature_t s;
+
+ if (!dst || !src)
+ return CDK_Inv_Value;
- return 0;
+ *dst = NULL;
+ s = cdk_calloc (1, sizeof *s);
+ if (!s)
+ return CDK_Out_Of_Core;
+ 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;
}
cdk_error_t
_cdk_pubkey_compare (cdk_pkt_pubkey_t a, cdk_pkt_pubkey_t b)
{
- int na, nb, i;
-
- if (a->timestamp != b->timestamp || a->pubkey_algo != b->pubkey_algo)
- return -1;
- if (a->version < 4 && a->expiredate != b->expiredate)
- return -1;
- na = cdk_pk_get_npkey (a->pubkey_algo);
- nb = cdk_pk_get_npkey (b->pubkey_algo);
- if (na != nb)
- return -1;
+ int na, nb, i;
+
+ if (a->timestamp != b->timestamp || a->pubkey_algo != b->pubkey_algo)
+ return -1;
+ if (a->version < 4 && a->expiredate != b->expiredate)
+ return -1;
+ na = cdk_pk_get_npkey (a->pubkey_algo);
+ nb = cdk_pk_get_npkey (b->pubkey_algo);
+ if (na != nb)
+ return -1;
- for (i = 0; i < na; i++) {
- if (gcry_mpi_cmp (a->mpi[i], b->mpi[i]))
- return -1;
+ for (i = 0; i < na; i++)
+ {
+ if (gcry_mpi_cmp (a->mpi[i], b->mpi[i]))
+ return -1;
}
-
- return 0;
+
+ return 0;
}
@@ -783,6 +829,7 @@ cdk_key_desig_revoker_walk (cdk_desig_revoker_t root,
return n? n->fpr : NULL;
}
+
/**
* cdk_subpkt_find_next:
* @root: the base where to begin the iteration
diff --git a/libextra/opencdk/opencdk.h b/libextra/opencdk/opencdk.h
index d7ff7bbb27..f8a9609ece 100644
--- a/libextra/opencdk/opencdk.h
+++ b/libextra/opencdk/opencdk.h
@@ -23,12 +23,12 @@
#include <gcrypt.h>
/* The OpenCDK version as a string. */
-#define OPENCDK_VERSION "0.6.1"
+#define OPENCDK_VERSION "0.6.3"
/* The OpenCDK version as integer components major.minor.path */
#define OPENCDK_VERSION_MAJOR 0
#define OPENCDK_VERSION_MINOR 6
-#define OPENCDK_VERSION_PATCH 1
+#define OPENCDK_VERSION_PATCH 3
#ifdef __cplusplus
extern "C" {
@@ -60,6 +60,7 @@ typedef struct cdk_dek_s *cdk_dek_t;
struct cdk_s2k_s;
typedef struct cdk_s2k_s *cdk_s2k_t;
+/* Abstract I/O object, a stream, which is used for most operations. */
struct cdk_stream_s;
typedef struct cdk_stream_s *cdk_stream_t;
@@ -124,7 +125,8 @@ typedef enum {
CDK_Too_Short = 24,
CDK_Unusable_Key = 25,
CDK_No_Data = 26,
- CDK_No_Passphrase = 27
+ CDK_No_Passphrase = 27,
+ CDK_Network_Error = 28
} cdk_error_t;
@@ -338,6 +340,13 @@ typedef enum {
} cdk_key_flags_t;
+/* Possible format for the literal data. */
+typedef enum {
+ CDK_LITFMT_BINARY = 0,
+ CDK_LITFMT_TEXT = 1,
+ CDK_LITFMT_UNICODE= 2
+} cdk_lit_format_t;
+
/* Valid OpenPGP packet types and their IDs */
typedef enum {
CDK_PKT_RESERVED = 0,
@@ -562,11 +571,16 @@ struct cdk_packet_s {
};
typedef struct cdk_packet_s *cdk_packet_t;
-/*-- main.c --*/
/* memory routines */
typedef void (*cdk_log_fnc_t) (void *, int, const char *, va_list);
+
+/* Set the log level. */
void cdk_set_log_level (int lvl);
+
+/* Set a custom log handler which is used for logging. */
void cdk_set_log_handler (cdk_log_fnc_t logfnc, void *opaque);
+
+/* Return a human readable error description of the given error coe. */
const char* cdk_strerror (int ec);
/* Allow the user to set custom hooks for memory allocation.
@@ -707,7 +721,6 @@ const unsigned char* cdk_key_desig_revoker_walk (cdk_desig_revoker_t root,
cdk_desig_revoker_t * ctx,
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)
@@ -758,10 +771,23 @@ int cdk_pk_get_nsig (int algo);
int cdk_pk_get_nenc (int algo);
/* Fingerprint and key ID routines. */
+
+/* Calculate the fingerprint of the given public key.
+ the FPR parameter must be at least 20 octets to hold the SHA1 hash. */
cdk_error_t cdk_pk_get_fingerprint (cdk_pubkey_t pk, unsigned char *fpr);
+
+/* Same as above, but with additional sanity checks of the buffer size. */
+cdk_error_t cdk_pk_to_fingerprint (cdk_pubkey_t pk,
+ unsigned char *fpr, size_t fprlen,
+ size_t *r_nout);
+
+/* Derive the keyid from the fingerprint. This is only possible for
+ modern, version 4 keys. */
unsigned int cdk_pk_fingerprint_get_keyid (const unsigned char *fpr,
- size_t fprlen,
- unsigned int *keyid);
+ size_t fprlen,
+ unsigned int *keyid);
+
+/* Various functions to get the keyid from the specific packet type. */
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,
@@ -789,10 +815,26 @@ cdk_error_t cdk_seckey_to_sexp (cdk_seckey_t sk,
/* Data Encryption Key (DEK) routines */
cdk_error_t cdk_dek_new (cdk_dek_t *r_dek);
void cdk_dek_free (cdk_dek_t dek);
+
+/* Set the symmetric cipher algorithm which shall be used for this
+ DEK object. */
cdk_error_t cdk_dek_set_cipher (cdk_dek_t dek, int cipher_algo);
+
+/* Return the symmetric cipher which is used for this DEK object. */
+cdk_error_t cdk_dek_get_cipher (cdk_dek_t dek, int *r_cipher_algo);
+
+
+/* Set the session key for the given DEK object.
+ If @KEY and @KEYLEN are both NULL/0, a random key will be generated
+ and stored in the DEK object. */
cdk_error_t cdk_dek_set_key (cdk_dek_t dek, const unsigned char *key,
size_t keylen);
+
+/* Enable the MDC feature for the current DEK object. */
void cdk_dek_set_mdc_flag (cdk_dek_t dek, int val);
+
+/* Return if the MDC feature is enabled for the current DEK object.*/
+int cdk_dek_get_mdc_flag (cdk_dek_t dek);
/* Transform the given passphrase into a DEK.
If @rndsalt is set, a random salt will be generated. */
@@ -805,7 +847,6 @@ 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);
@@ -819,7 +860,6 @@ cdk_error_t cdk_armor_encode_buffer (const unsigned char *inbuf, size_t inlen,
size_t *nwritten, int type);
-/*-- stream.c --*/
/* This context contain user callbacks for different stream operations.
Some of these callbacks might be NULL to indicate that the callback
is not used. */
@@ -835,8 +875,20 @@ typedef struct cdk_stream_cbs_s *cdk_stream_cbs_t;
int cdk_stream_is_compressed (cdk_stream_t s);
+
+/* Return a stream object which is associated to a socket. */
+cdk_error_t cdk_stream_sockopen (const char *host, unsigned short port,
+ cdk_stream_t *ret_out);
+
+/* Return a stream object which is associated to an existing file. */
cdk_error_t cdk_stream_open (const char * file, cdk_stream_t * ret_s);
+
+/* Return a stream object which is associated to a file which will
+ be created when the stream is closed. */
cdk_error_t cdk_stream_new (const char * file, cdk_stream_t * ret_s);
+
+/* Return a stream object with custom callback functions for the
+ various core operations. */
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);
@@ -857,8 +909,12 @@ int cdk_stream_eof (cdk_stream_t s);
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,
+
+/* Push the literal filter for the given stream. */
+cdk_error_t cdk_stream_set_literal_flag (cdk_stream_t s,
+ cdk_lit_format_t 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);
@@ -874,8 +930,6 @@ cdk_error_t cdk_stream_mmap_part (cdk_stream_t s, off_t off, size_t len,
the requested amount of bytes. */
int cdk_stream_peek (cdk_stream_t inp, unsigned char *buf, size_t buflen);
-/*-- keydb.c --*/
-
/* A wrapper around the various new_from_XXX functions. Because
the function does not support all combinations, the dedicated
functions should be preferred. */
@@ -954,7 +1008,6 @@ void cdk_listkey_close (cdk_listkey_t ctx);
/* Return the next key which matches the pattern. */
cdk_error_t cdk_listkey_next (cdk_listkey_t ctx, cdk_kbnode_t *ret_key);
-/*-- kbnode.c --*/
cdk_kbnode_t cdk_kbnode_new (cdk_packet_t pkt);
cdk_error_t cdk_kbnode_read_from_mem (cdk_kbnode_t * ret_node,
const unsigned char * buf,
@@ -976,8 +1029,6 @@ cdk_kbnode_t cdk_kbnode_find_next (cdk_kbnode_t node, int pkttype);
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 --*/
-
/* 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,
@@ -986,14 +1037,19 @@ cdk_error_t cdk_pk_check_sigs (cdk_kbnode_t knode, cdk_keydb_hd_t hd,
/* 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 --*/
/* Return a matching algorithm from the given public key list.
@PREFTYPE can be either sym-cipher/compress/digest. */
int cdk_pklist_select_algo (cdk_keylist_t pkl, int preftype);
+
+/* Return 0 or 1 if the given key list is able to understand the
+ MDC feature. */
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);
void cdk_pklist_release (cdk_keylist_t pkl);
+
+/* Encrypt the given DEK key with the list of public keys given
+ in @PKL. The result will be written to the stream output @OUT. */
cdk_error_t cdk_pklist_encrypt (cdk_keylist_t pkl, cdk_dek_t dek,
cdk_stream_t out);
@@ -1009,8 +1065,6 @@ cdk_error_t cdk_sklist_write (cdk_keylist_t skl, cdk_stream_t outp,
cdk_error_t cdk_sklist_write_onepass (cdk_keylist_t skl, cdk_stream_t outp,
int sigclass, int mdalgo);
-/*-- encrypt.c --*/
-
/* Encrypt the given stream @INP with the recipients given in @REMUSR.
If @REMUSR is NULL, symmetric encryption will be used. The output
will be written to @OUT. */
@@ -1037,7 +1091,6 @@ cdk_error_t cdk_data_transform (cdk_ctx_t hd, enum cdk_crypto_mode_t mode,
unsigned char ** outbuf, size_t * outsize,
int modval);
-/*-- sign.c --*/
/* Sign the stream @INP. Optionally, the output will be encrypted
if @REMUSR is not NULL and the @ENCRYPTFLAG is set.
The output will be written to @OUT.
@@ -1052,7 +1105,6 @@ cdk_error_t cdk_file_sign (cdk_ctx_t hd, cdk_strlist_t locusr,
const char *file, const char *output,
int sigmode, int encryptflag);
-/*-- verify.c --*/
cdk_error_t cdk_stream_verify (cdk_ctx_t hd, cdk_stream_t inp,
cdk_stream_t data,
cdk_stream_t out);
@@ -1063,13 +1115,11 @@ cdk_error_t cdk_stream_verify (cdk_ctx_t hd, cdk_stream_t inp,
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_pubkey_t pk,
int *r_val, int *r_flags);
-/*-- misc.c --*/
void cdk_strlist_free (cdk_strlist_t sl);
cdk_strlist_t cdk_strlist_add (cdk_strlist_t * list, const char * string);
cdk_strlist_t cdk_strlist_next (cdk_strlist_t root, const char **r_str);
@@ -1078,32 +1128,37 @@ const char * cdk_check_version (const char * req_version);
char* cdk_utf8_encode (const char * string);
char* cdk_utf8_decode (const char * string, size_t length, int delim);
-/*-- keyserver.c --*/
/* Try to receive the key, which has the key ID @KEYID, from the
keyserver host @HOST and the port @PORT. */
cdk_error_t cdk_keyserver_recv_key (const char *host, int port,
const unsigned char *keyid, int kid_type,
cdk_kbnode_t *r_key);
-/*-- keygen.c --*/
cdk_error_t cdk_keygen_new (cdk_keygen_ctx_t * r_hd);
void cdk_keygen_free (cdk_keygen_ctx_t hd);
+
+/* Set the preferences of the given type for the new key.
+ @ARRAY is an array which list of algorithm IDs. */
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,
+cdk_error_t cdk_keygen_set_algo_info (cdk_keygen_ctx_t hd, int type,
int usage, enum cdk_pubkey_algo_t algo,
- unsigned int bits );
-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,
+ 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);
+
+/* Set the user ID specifc parts for the new key.
+ It is suggested to use a name in the form of
+ 'First Name' 'Last Name' <email-address@host.domain> */
+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 * secf);
#ifdef __cplusplus
}
diff --git a/libextra/opencdk/pubkey.c b/libextra/opencdk/pubkey.c
index d8c23bbb63..e3498e0a95 100644
--- a/libextra/opencdk/pubkey.c
+++ b/libextra/opencdk/pubkey.c
@@ -15,7 +15,7 @@
* GNU General Public License for more details.
*/
#ifdef HAVE_CONFIG_H
-# include <config.h>
+#include <config.h>
#endif
#include <stdio.h>
#include <gcrypt.h>
@@ -25,14 +25,15 @@
#include "packet.h"
+/* Convert the given secret key into a gcrypt SEXP object. */
static int
-seckey_to_sexp (gcry_sexp_t * r_skey, cdk_seckey_t sk)
+seckey_to_sexp (gcry_sexp_t *r_skey, cdk_seckey_t sk)
{
gcry_sexp_t sexp = NULL;
- gcry_mpi_t *mpk = NULL, * msk = NULL;
+ gcry_mpi_t *mpk = NULL, *msk = NULL;
+ gcry_error_t err;
cdk_pubkey_t pk;
const char *fmt;
- gcry_error_t err;
if (!r_skey || !sk || !sk->pk)
return CDK_Inv_Value;
@@ -69,13 +70,14 @@ seckey_to_sexp (gcry_sexp_t * r_skey, cdk_seckey_t sk)
}
+/* Convert the given public key to a gcrypt SEXP object. */
static cdk_error_t
pubkey_to_sexp (gcry_sexp_t *r_key_sexp, cdk_pubkey_t pk)
{
gcry_mpi_t *m;
- const char *fmt = NULL;
- int rc = 0;
gcry_error_t err;
+ const char *fmt = NULL;
+ cdk_error_t rc = 0;
if (!r_key_sexp || !pk)
return CDK_Inv_Value;
@@ -123,7 +125,8 @@ enckey_to_sexp (gcry_sexp_t *r_sexp, gcry_mpi_t esk)
static cdk_error_t
-digest_to_sexp (gcry_sexp_t *r_md_sexp, int algo, const byte *md, size_t mdlen)
+digest_to_sexp (gcry_sexp_t *r_md_sexp, int digest_algo,
+ const byte *md, size_t mdlen)
{
gcry_mpi_t m;
gcry_error_t err;
@@ -132,7 +135,7 @@ digest_to_sexp (gcry_sexp_t *r_md_sexp, int algo, const byte *md, size_t mdlen)
return CDK_Inv_Value;
if (!mdlen)
- mdlen = gcry_md_get_algo_dlen (algo);
+ mdlen = gcry_md_get_algo_dlen (digest_algo);
if (!mdlen)
return CDK_Inv_Algo;
@@ -176,7 +179,10 @@ sexp_to_sig (cdk_pkt_signature_t sig, gcry_sexp_t sexp)
/* ElGamal signatures are not supported any longer. */
if (is_ELG (sig->pubkey_algo))
- return CDK_Not_Implemented;
+ {
+ _cdk_log_debug ("sexp_to_sig: unsupported signature type (ElGamal)\n");
+ return CDK_Not_Implemented;
+ }
if (is_RSA (sig->pubkey_algo))
return sexp_to_mpi (sexp, "s", &sig->mpi[0]);
@@ -196,9 +202,9 @@ sexp_to_sig (cdk_pkt_signature_t sig, gcry_sexp_t sexp)
static cdk_error_t
sig_to_sexp (gcry_sexp_t *r_sig_sexp, cdk_pkt_signature_t sig)
{
- const char *fmt;
gcry_error_t err;
cdk_error_t rc;
+ const char *fmt;
if (!r_sig_sexp || !sig)
return CDK_Inv_Value;
@@ -246,11 +252,11 @@ sexp_to_pubenc (cdk_pkt_pubkey_enc_t enc, gcry_sexp_t sexp)
static cdk_error_t
-pubenc_to_sexp( gcry_sexp_t * r_sexp, cdk_pkt_pubkey_enc_t enc)
+pubenc_to_sexp (gcry_sexp_t * r_sexp, cdk_pkt_pubkey_enc_t enc)
{
gcry_sexp_t sexp = NULL;
- const char *fmt;
gcry_error_t err;
+ const char *fmt;
if (!r_sexp || !enc)
return CDK_Inv_Value;
@@ -485,6 +491,15 @@ cdk_pk_verify (cdk_pubkey_t pk, cdk_pkt_signature_t sig, const byte *md)
}
+/**
+ * cdk_pk_get_nbits:
+ * @pk: the public key
+ *
+ * Return the length of the public key in bits.
+ * The meaning of length is actually the size of the 'prime'
+ * object in the key. For RSA keys the modulus, for ElG/DSA
+ * the size of the public prime.
+ **/
int
cdk_pk_get_nbits (cdk_pubkey_t pk)
{
@@ -514,6 +529,13 @@ cdk_pk_get_npkey (int algo)
}
+/**
+ * cdk_pk_get_nskey:
+ * @algo: the public key algorithm
+ *
+ * Return the number of multiprecision integers forming an
+ * secret key with the given algorithm.
+ **/
int
cdk_pk_get_nskey (int algo)
{
@@ -526,6 +548,12 @@ cdk_pk_get_nskey (int algo)
}
+/**
+ * cdk_pk_get_nbits:
+ * @algo: the public key algorithm
+ *
+ * Return the number of MPIs a signature consists of.
+ **/
int
cdk_pk_get_nsig (int algo)
{
@@ -537,6 +565,12 @@ cdk_pk_get_nsig (int algo)
}
+/**
+ * cdk_pk_get_nenc:
+ * @algo: the public key algorithm
+ *
+ * Return the number of MPI's the encrypted data consists of.
+ **/
int
cdk_pk_get_nenc (int algo)
{
@@ -567,17 +601,6 @@ _cdk_pk_algo_usage (int algo)
}
-int
-_cdk_pk_test_algo (int algo, unsigned int usage_flags)
-{
- size_t n = usage_flags;
-
- if (algo < 0 || algo > 110)
- return -1;
- return gcry_pk_algo_info (algo, GCRYCTL_TEST_ALGO, NULL, &n);
-}
-
-
static cdk_error_t
mpi_to_buffer (gcry_mpi_t a, byte *buf, size_t buflen,
size_t *r_nwritten, size_t *r_nbits)
@@ -598,7 +621,17 @@ mpi_to_buffer (gcry_mpi_t a, byte *buf, size_t buflen,
return 0;
}
-
+
+/**
+ * cdk_pk_get_mpi:
+ * @pk: public key
+ * @idx: index of the MPI to retrieve
+ * @buf: buffer to hold the raw data
+ * @r_nwritten: output how large the raw data is
+ * @r_nbits: size of the MPI in bits.
+ *
+ * Return the MPI with the given index of the public key.
+ **/
cdk_error_t
cdk_pk_get_mpi (cdk_pubkey_t pk, size_t idx,
byte *buf, size_t buflen, size_t *r_nwritten, size_t *r_nbits)
@@ -611,9 +644,21 @@ cdk_pk_get_mpi (cdk_pubkey_t pk, size_t idx,
}
+/**
+ * cdk_sk_get_mpi:
+ * @sk: secret key
+ * @idx: index of the MPI to retrieve
+ * @buf: buffer to hold the raw data
+ * @r_nwritten: output length of the raw data
+ * @r_nbits: length of the MPI data in bits.
+ *
+ * Return the MPI of the given secret key with the
+ * index @idx. It is important to check if the key
+ * is protected and thus no real MPI data will be returned then.
+ **/
cdk_error_t
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)
+ byte *buf, size_t buflen, size_t *r_nwritten, size_t *r_nbits)
{
if (!sk || !r_nwritten)
return CDK_Inv_Value;
@@ -633,7 +678,7 @@ checksum_mpi (gcry_mpi_t m)
if (!m)
return 0;
- if (gcry_mpi_print (GCRYMPI_FMT_PGP, buf, 2048, &nread, m))
+ if (gcry_mpi_print (GCRYMPI_FMT_PGP, buf, DIM (buf), &nread, m))
return 0;
for (i=0; i < nread; i++)
chksum += buf[i];
@@ -641,6 +686,13 @@ checksum_mpi (gcry_mpi_t m)
}
+/**
+ * cdk_sk_unprotect:
+ * @sk: the secret key
+ * @pw: the passphrase
+ *
+ * Unprotect the given secret key with the passphrase.
+ **/
cdk_error_t
cdk_sk_unprotect (cdk_pkt_seckey_t sk, const char *pw)
{
@@ -764,8 +816,15 @@ cdk_sk_unprotect (cdk_pkt_seckey_t sk, const char *pw)
}
+/**
+ * cdk_sk_protect:
+ * @sk: the secret key
+ * @pw: the passphrase to use
+ *
+ * Protect the given secret key with a passphrase.
+ **/
cdk_error_t
-cdk_sk_protect (cdk_pkt_seckey_t sk, const char *pass)
+cdk_sk_protect (cdk_pkt_seckey_t sk, const char *pw)
{
gcry_cipher_hd_t hd = NULL;
cdk_dek_t dek = NULL;
@@ -776,13 +835,13 @@ cdk_sk_protect (cdk_pkt_seckey_t sk, const char *pass)
gcry_error_t err;
cdk_error_t rc;
- nskey = cdk_pk_get_nskey (sk->pubkey_algo );
+ 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);
+ rc = cdk_dek_from_passphrase (&dek, GCRY_CIPHER_AES, s2k, 1, pw);
if (rc)
{
cdk_s2k_free (s2k);
@@ -943,6 +1002,17 @@ _cdk_sk_get_csum (cdk_pkt_seckey_t sk)
}
+/**
+ * cdk_pk_get_fingerprint:
+ * @pk: the public key
+ * @fpr: the buffer to hold the fingerprint
+ *
+ * Return the fingerprint of the given public key.
+ * The buffer must be at least 20 octets.
+ * This function should be considered deprecated and
+ * the new cdk_pk_to_fingerprint() should be used whenever
+ * possible to avoid overflows.
+ **/
cdk_error_t
cdk_pk_get_fingerprint (cdk_pubkey_t pk, byte *fpr)
{
@@ -972,6 +1042,57 @@ cdk_pk_get_fingerprint (cdk_pubkey_t pk, byte *fpr)
}
+/**
+ * cdk_pk_to_fingerprint:
+ * @pk: the public key
+ * @fprbuf: buffer to save the fingerprint
+ * @fprbuflen: buffer size
+ * @r_nout: actual length of the fingerprint.
+ *
+ * Calculate a fingerprint of the given key and
+ * return it in the given byte array.
+ **/
+cdk_error_t
+cdk_pk_to_fingerprint (cdk_pubkey_t pk,
+ byte *fprbuf, size_t fprbuflen, size_t *r_nout)
+{
+ size_t key_fprlen;
+ cdk_error_t err;
+
+ if (!pk)
+ return CDK_Inv_Value;
+
+ if (pk->version < 4)
+ key_fprlen = 16;
+ else
+ key_fprlen = 20;
+
+ /* Only return the required buffer size for the fingerprint. */
+ if (!fprbuf && !fprbuflen && r_nout)
+ {
+ *r_nout = key_fprlen;
+ return 0;
+ }
+
+ if (!fprbuf || key_fprlen > fprbuflen)
+ return CDK_Too_Short;
+
+ err = cdk_pk_get_fingerprint (pk, fprbuf);
+ if (r_nout)
+ *r_nout = key_fprlen;
+
+ return err;
+}
+
+
+/**
+ * cdk_pk_fingerprint_get_keyid:
+ * @fpr: the key fingerprint
+ * @fprlen: the length of the fingerprint
+ *
+ * Derive the key ID from the key fingerprint.
+ * For version 3 keys, this is not working.
+ **/
u32
cdk_pk_fingerprint_get_keyid (const byte *fpr, size_t fprlen, u32 *keyid)
{
@@ -980,7 +1101,11 @@ cdk_pk_fingerprint_get_keyid (const byte *fpr, size_t fprlen, u32 *keyid)
/* 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;
+ {
+ keyid[0] = 0;
+ keyid[1] = 0;
+ return 0;
+ }
else if (keyid && fpr)
{
keyid[0] = _cdk_buftou32 (fpr + 12);
@@ -993,6 +1118,13 @@ cdk_pk_fingerprint_get_keyid (const byte *fpr, size_t fprlen, u32 *keyid)
}
+/**
+ * cdk_pk_get_keyid:
+ * @pk: the public key
+ * @keyid: buffer to store the key ID
+ *
+ * Calculate the key ID of the given public key.
+ **/
u32
cdk_pk_get_keyid (cdk_pubkey_t pk, u32 *keyid)
{
@@ -1028,6 +1160,13 @@ cdk_pk_get_keyid (cdk_pubkey_t pk, u32 *keyid)
}
+/**
+ * cdk_sk_get_keyid:
+ * @sk: the secret key
+ * @keyid: buffer to hold the key ID
+ *
+ * Calculate the key ID of the secret key, actually the public key.
+ **/
u32
cdk_sk_get_keyid (cdk_pkt_seckey_t sk, u32 *keyid)
{
@@ -1044,8 +1183,15 @@ cdk_sk_get_keyid (cdk_pkt_seckey_t sk, u32 *keyid)
}
+/**
+ * cdk_sig_get_keyid:
+ * @sig: the signature
+ * @keyid: buffer to hold the key ID
+ *
+ * Retrieve the key ID from the given signature.
+ **/
u32
-cdk_sig_get_keyid( cdk_pkt_signature_t sig, u32 * keyid )
+cdk_sig_get_keyid (cdk_pkt_signature_t sig, u32 *keyid)
{
u32 lowbits = sig ? sig->keyid[1] : 0;
@@ -1058,6 +1204,8 @@ cdk_sig_get_keyid( cdk_pkt_signature_t sig, u32 * keyid )
}
+/* Return the key ID from the given packet.
+ If this is not possible, 0 is returned */
u32
_cdk_pkt_get_keyid (cdk_packet_t pkt, u32 *keyid)
{
@@ -1091,6 +1239,7 @@ _cdk_pkt_get_keyid (cdk_packet_t pkt, u32 *keyid)
}
+/* Get the fingerprint of the packet if possible. */
int
_cdk_pkt_get_fingerprint (cdk_packet_t pkt, byte *fpr)
{
@@ -1113,6 +1262,7 @@ _cdk_pkt_get_fingerprint (cdk_packet_t pkt, byte *fpr)
return 0;
}
+
/**
* cdk_pubkey_to_sexp:
* @pk: the public key
diff --git a/libextra/opencdk/read-packet.c b/libextra/opencdk/read-packet.c
index 992d84ab96..b1f50b6e22 100644
--- a/libextra/opencdk/read-packet.c
+++ b/libextra/opencdk/read-packet.c
@@ -327,11 +327,11 @@ read_mdc (cdk_stream_t inp, cdk_pkt_mdc_t mdc)
if (DEBUG_PKT)
_cdk_log_debug ("read_mdc:\n");
- rc = stream_read (inp, mdc->hash, 20, &n);
+ rc = stream_read (inp, mdc->hash, DIM (mdc->hash), &n);
if (rc)
return rc;
- return n != 20? CDK_Inv_Packet : 0;
+ return n != DIM (mdc->hash)? CDK_Inv_Packet : 0;
}
@@ -881,7 +881,7 @@ read_literal (cdk_stream_t inp, size_t pktlen,
_cdk_log_debug ("read_literal: %d octets\n", pktlen);
pt->mode = cdk_stream_getc (inp);
- if (pt->mode != 0x62 && pt->mode != 0x74)
+ if (pt->mode != 0x62 && pt->mode != 0x74 && pt->mode != 0x75)
return CDK_Inv_Packet;
if (cdk_stream_eof (inp))
return CDK_Inv_Packet;
diff --git a/libextra/opencdk/seskey.c b/libextra/opencdk/seskey.c
index 6c3a0d241b..e6956e6a5c 100644
--- a/libextra/opencdk/seskey.c
+++ b/libextra/opencdk/seskey.c
@@ -1,6 +1,6 @@
/* seskey.c - Session key routines
* Copyright (C) 2002, 2003, 2007 Timo Schulz
- * Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
+ * Copyright (C) 1998-2000, 2002 Free Software Foundation, Inc.
*
* This file is part of OpenCDK.
*
@@ -37,9 +37,8 @@ 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;
size_t nframe = (nbits + 7) / 8;
- size_t i;
+ size_t i, n = 0;
if (!asn || !md || !r_frame || !r_flen)
return CDK_Inv_Value;
@@ -86,16 +85,26 @@ do_encode_md (byte **r_frame, size_t *r_flen, const byte *md, int algo,
* DEK - random session key.
* CKSUM - algebraic checksum of the DEK.
*/
+
+/**
+ * cdk_dek_encode_pkcs1
+ * @dek: DEK object
+ * @nbits: size of the multi precision integer frame
+ * @r_enc: output of the encoded multiprecision integer
+ *
+ * Encode the given random session key in the DEK object
+ * into a multiprecision integer.
+ **/
cdk_error_t
cdk_dek_encode_pkcs1 (cdk_dek_t dek, size_t nbits, gcry_mpi_t *r_enc)
{
gcry_mpi_t a = NULL;
gcry_error_t err;
byte *p, *frame;
- size_t n = 0;
+ size_t n;
size_t nframe = 0;
- u16 chksum = 0;
size_t i;
+ u16 chksum = 0;
if (!r_enc || !dek)
return CDK_Inv_Value;
@@ -154,6 +163,14 @@ cdk_dek_encode_pkcs1 (cdk_dek_t dek, size_t nbits, gcry_mpi_t *r_enc)
}
+/**
+ * cdk_dek_decode_pkcs1:
+ * @ret_dek: the decoded DEK object
+ * @esk: the pkcs#1 encoded session key.
+ *
+ * Decode the given multi precision integer in pkcs#1 and
+ * store it into the DEK object.
+ **/
cdk_error_t
cdk_dek_decode_pkcs1 (cdk_dek_t *ret_dek, gcry_mpi_t esk)
{
@@ -166,6 +183,7 @@ cdk_dek_decode_pkcs1 (cdk_dek_t *ret_dek, gcry_mpi_t esk)
if (!ret_dek || !esk)
return CDK_Inv_Value;
+ *ret_dek = NULL; /* reset */
nframe = DIM (frame)-1;
err = gcry_mpi_print (GCRYMPI_FMT_USG, frame, nframe, &nframe, esk);
if (err)
@@ -198,6 +216,7 @@ cdk_dek_decode_pkcs1 (cdk_dek_t *ret_dek, gcry_mpi_t esk)
dek->algo = frame[n++];
if (dek->keylen != gcry_cipher_get_algo_keylen (dek->algo))
{
+ _cdk_log_debug ("pkcs1 decode: invalid cipher keylen\n");
cdk_free (dek);
return CDK_Inv_Algo;
}
@@ -208,6 +227,7 @@ cdk_dek_decode_pkcs1 (cdk_dek_t *ret_dek, gcry_mpi_t esk)
csum2 += dek->key[n];
if (csum != csum2)
{
+ _cdk_log_debug ("pkcs decode: checksum does not match\n");
cdk_free (dek);
return CDK_Chksum_Error;
}
@@ -216,8 +236,7 @@ cdk_dek_decode_pkcs1 (cdk_dek_t *ret_dek, gcry_mpi_t esk)
}
-/* Do some tests before it calls do_encode_md that depends on the
- public key algorithm that is used. */
+/* Encode the given digest into a pkcs#1 compatible format. */
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)
@@ -300,36 +319,44 @@ _cdk_sk_unprotect_auto (cdk_ctx_t hd, cdk_pkt_seckey_t sk)
char *pw, *p;
cdk_error_t rc;
- 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);
- }
+ if (!sk->is_protected)
+ return 0;
+
+ p = passphrase_prompt (sk);
+ pw = _cdk_passphrase_get (hd, p);
+ cdk_free (p);
+ if (!pw)
+ return CDK_No_Passphrase;
+
+ rc = cdk_sk_unprotect (sk, pw);
+
+ wipemem (pw, strlen (pw));
+ cdk_free (pw);
return rc;
}
-/* Try to extract the DEK from the public key encrypted packet. */
+/**
+ * cdk_dek_extract:
+ * ret_dek: the raw DEK object
+ * hd: the session handle
+ * @enc: the public key encrypted packet
+ * @sk: the secret key.
+ *
+ * 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_t dek = NULL;
- gcry_mpi_t skey =NULL;
+ gcry_mpi_t skey = NULL;
+ cdk_dek_t dek;
cdk_error_t rc;
if (!enc || !sk || !ret_dek)
return CDK_Inv_Value;
+ /* FIXME: it is not very elegant that we need the session handle here. */
if (sk->is_protected)
{
rc = _cdk_sk_unprotect_auto (hd, sk);
@@ -353,6 +380,12 @@ cdk_dek_extract (cdk_dek_t *ret_dek, cdk_ctx_t hd,
}
+/**
+ * cdk_dek_new:
+ * @r_dek: the new DEK object
+ *
+ * Create a new DEK object.
+ **/
cdk_error_t
cdk_dek_new (cdk_dek_t *r_dek)
{
@@ -369,6 +402,13 @@ cdk_dek_new (cdk_dek_t *r_dek)
}
+/**
+ * cdk_dek_set_cipher:
+ * @dek: the DEK object
+ * @algo: the cipher algorithm to use
+ *
+ * Set the cipher for the given DEK object.
+ **/
cdk_error_t
cdk_dek_set_cipher (cdk_dek_t dek, int algo)
{
@@ -384,7 +424,28 @@ cdk_dek_set_cipher (cdk_dek_t dek, int algo)
return 0;
}
+cdk_error_t
+cdk_dek_get_cipher (cdk_dek_t dek, int *r_algo)
+{
+ if (!dek || !r_algo)
+ return CDK_Inv_Value;
+
+
+ *r_algo = dek->algo;
+ return 0;
+}
+
+/**
+ * cdk_dek_set_key:
+ * @dek: the DEK object
+ * @key: the random session key
+ * @keylen: the length of the session key.
+ *
+ * Set the random session key for the given DEK object.
+ * If @key and @keylen is NULL (0) a random key will be generated.
+ * In any case, cdk_dek_set_cipher must be called first.
+ **/
cdk_error_t
cdk_dek_set_key (cdk_dek_t dek, const byte *key, size_t keylen)
{
@@ -392,8 +453,10 @@ cdk_dek_set_key (cdk_dek_t dek, const byte *key, size_t keylen)
size_t i;
if (!dek)
- return CDK_Inv_Value;
-
+ return CDK_Inv_Value;
+
+ /* The given key must be compatible with the symmetric
+ cipher algorithm set before. */
if (keylen > 0 && keylen != dek->keylen)
return CDK_Inv_Mode;
@@ -417,6 +480,7 @@ cdk_dek_set_key (cdk_dek_t dek, const byte *key, size_t keylen)
}
gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM);
}
+ gcry_cipher_close (hd);
return CDK_Weak_Key;
}
@@ -425,6 +489,13 @@ cdk_dek_set_key (cdk_dek_t dek, const byte *key, size_t keylen)
}
+/**
+ * cdk_dek_set_mdc_flag:
+ * @dek: the DEK object
+ * @val: value to enable or disable the use
+ *
+ * Enable or disable the MDC flag for the given DEK object.
+ **/
void
cdk_dek_set_mdc_flag (cdk_dek_t dek, int val)
{
@@ -433,11 +504,28 @@ cdk_dek_set_mdc_flag (cdk_dek_t dek, int val)
}
+int
+cdk_dek_get_mdc_flag (cdk_dek_t dek)
+{
+ if (!dek)
+ return 0;
+ return dek->use_mdc;
+}
+
+
+/**
+ * cdk_dek_free:
+ * @dek: the DEK object
+ *
+ * Release the DEK object.
+ **/
void
cdk_dek_free (cdk_dek_t dek)
{
if (!dek)
return;
+
+ /* Make sure sentensive data is overwritten. */
wipemem (dek->key, sizeof (dek->key));
cdk_free (dek);
}
@@ -445,13 +533,13 @@ cdk_dek_free (cdk_dek_t dek)
/* Hash the passphrase to produce the a DEK.
If create is set, a random salt will be generated. */
-static int
+static cdk_error_t
hash_passphrase (cdk_dek_t dek, const char *pw, cdk_s2k_t s2k, int create)
{
gcry_md_hd_t md;
byte zero[1] = {0x00};
int pass, i;
- int used = 0, pwlen = 0;
+ int used = 0, pwlen;
gcry_error_t err;
if (!dek || !pw || !s2k)
@@ -487,7 +575,7 @@ hash_passphrase (cdk_dek_t dek, const char *pw, cdk_s2k_t s2k, int create)
if (s2k->mode == 3)
{
count = (16ul + (s2k->count & 15)) << ((s2k->count >> 4) + 6);
- if( count < len2 )
+ if (count < len2)
count = len2;
}
/* a little bit complicated because we need a ulong for count */
@@ -545,21 +633,31 @@ cdk_dek_from_passphrase (cdk_dek_t *ret_dek, int cipher_algo, cdk_s2k_t s2k,
if (rc)
return rc;
rc = cdk_dek_set_cipher (dek, cipher_algo);
+ if (!rc)
+ rc = hash_passphrase (dek, pw, s2k, rndsalt);
if (rc)
{
cdk_dek_free (dek);
return rc;
}
-
- hash_passphrase (dek, pw, s2k, rndsalt);
*ret_dek = dek;
return 0;
}
+/**
+ * cdk_s2k_new:
+ * @ret_s2k: output for the new S2K object
+ * @mode: the S2K mode (simple, salted, iter+salted)
+ * @digest_algo: the hash algorithm
+ * @salt: random salt
+ *
+ * Create a new S2K object with the given parameter.
+ * The @salt parameter must be always 8 octets.
+ **/
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 digest_algo, const byte *salt)
{
cdk_s2k_t s2k;
@@ -569,14 +667,14 @@ cdk_s2k_new (cdk_s2k_t *ret_s2k, int mode, int algo, const byte *salt)
if (mode != 0x00 && mode != 0x01 && mode != 0x03)
return CDK_Inv_Mode;
- if (gcry_md_test_algo (algo))
+ if (gcry_md_test_algo (digest_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;
+ s2k->hash_algo = digest_algo;
if (salt)
memcpy (s2k->salt, salt, 8);
*ret_s2k = s2k;
@@ -584,8 +682,31 @@ cdk_s2k_new (cdk_s2k_t *ret_s2k, int mode, int algo, const byte *salt)
}
+/**
+ * cdk_s2k_free:
+ * @s2k: the S2K object
+ *
+ * Release the given S2K object.
+ **/
void
cdk_s2k_free (cdk_s2k_t s2k)
{
cdk_free (s2k);
}
+
+
+/* Make a copy of the source s2k into R_DST. */
+cdk_error_t
+_cdk_s2k_copy (cdk_s2k_t *r_dst, cdk_s2k_t src)
+{
+ cdk_s2k_t dst;
+ cdk_error_t err;
+
+ err = cdk_s2k_new (&dst, src->mode, src->hash_algo, src->salt);
+ if (err)
+ return err;
+ dst->count = src->count;
+ *r_dst = dst;
+
+ return 0;
+}
diff --git a/libextra/opencdk/sig-check.c b/libextra/opencdk/sig-check.c
index edd445e824..75f63a51d9 100644
--- a/libextra/opencdk/sig-check.c
+++ b/libextra/opencdk/sig-check.c
@@ -102,6 +102,8 @@ _cdk_hash_pubkey (cdk_pubkey_t pk, gcry_md_hd_t md, int usefpr)
}
+/* Hash the user ID @uid with the given message digest @md.
+ Use openpgp mode if @is_v4 is 1. */
void
_cdk_hash_userid (cdk_pkt_userid_t uid, int is_v4, gcry_md_hd_t md)
{
@@ -130,6 +132,8 @@ _cdk_hash_userid (cdk_pkt_userid_t uid, int is_v4, gcry_md_hd_t md)
}
+/* Hash all parts of the signature which are needed to derive
+ the correct message digest to verify the sig. */
cdk_error_t
_cdk_hash_sig_data (cdk_pkt_signature_t sig, gcry_md_hd_t md)
{
@@ -185,6 +189,7 @@ _cdk_hash_sig_data (cdk_pkt_signature_t sig, gcry_md_hd_t md)
}
+/* Cache the signature result and store it inside the sig. */
static void
cache_sig_result (cdk_pkt_signature_t sig, int res)
{
@@ -203,6 +208,8 @@ cache_sig_result (cdk_pkt_signature_t sig, int res)
}
+/* Check the given signature @sig with the public key @pk.
+ Use the digest handle @digest. */
cdk_error_t
_cdk_sig_check (cdk_pubkey_t pk, cdk_pkt_signature_t sig,
gcry_md_hd_t digest, int *r_expired)
@@ -240,6 +247,8 @@ _cdk_sig_check (cdk_pubkey_t pk, cdk_pkt_signature_t sig,
}
+/* Check the given key signature.
+ @knode is the key node and @snode the signature node. */
cdk_error_t
_cdk_pk_check_sig (cdk_keydb_hd_t keydb,
cdk_kbnode_t knode, cdk_kbnode_t snode, int *is_selfsig)
diff --git a/libextra/opencdk/stream.c b/libextra/opencdk/stream.c
index 40e31dd8c5..8aa3767623 100644
--- a/libextra/opencdk/stream.c
+++ b/libextra/opencdk/stream.c
@@ -444,6 +444,9 @@ cdk_stream_close (cdk_stream_t s)
s->fname = NULL;
}
+ cdk_free (s->cache.buf);
+ s->cache.alloced = 0;
+
cdk_free (s);
return rc;
}
@@ -927,8 +930,20 @@ cdk_stream_write (cdk_stream_t s, const void * buf, size_t count)
if (s->cache.on)
{
- if (s->cache.size + count > DIM (s->cache.buf))
- return EOF;
+ /* We need to resize the buffer if the additional data wouldn't
+ fit into it. We allocate more memory to avoid to resize it the
+ next time the function is used. */
+ if (s->cache.size + count > s->cache.alloced)
+ {
+ byte *old = s->cache.buf;
+
+ s->cache.buf = cdk_calloc (1, s->cache.alloced+count+STREAM_BUFSIZE);
+ s->cache.alloced += (count + STREAM_BUFSIZE);
+ memcpy (s->cache.buf, old, s->cache.size);
+ cdk_free (old);
+ _cdk_log_debug ("stream: enlarge cache to %d octets\n",
+ s->cache.alloced);
+ }
memcpy (s->cache.buf + s->cache.size, buf, count);
s->cache.size += count;
return count;
@@ -1006,8 +1021,19 @@ stream_flush (cdk_stream_t s)
}
+/**
+ * cdk_stream_set_armor_flag:
+ * @s: the stream object
+ * @type: the type of armor to use
+ *
+ * If the file is in read-mode, no armor type needs to be
+ * defined (armor_type=0) because the armor filter will be
+ * used for decoding existing armor data.
+ * For the write mode, @armor_type can be set to any valid
+ * armor type (message, key, sig).
+ **/
cdk_error_t
-cdk_stream_set_armor_flag (cdk_stream_t s, int type)
+cdk_stream_set_armor_flag (cdk_stream_t s, int armor_type)
{
struct stream_filter_s *f;
@@ -1016,14 +1042,26 @@ cdk_stream_set_armor_flag (cdk_stream_t s, int type)
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->u.afx.idx = f->u.afx.idx2 = armor_type;
f->ctl = stream_get_mode (s);
return 0;
}
+/**
+ * cdk_stream_set_literal_flag:
+ * @s: the stream object
+ * @mode: the mode to use (binary, text, unicode)
+ * @fname: the file name to store in the packet.
+ *
+ * In read mode it kicks off the literal decoding routine to
+ * unwrap the data from the packet. The @mode parameter is ignored.
+ * In write mode the function can be used to wrap the stream data
+ * into a literal packet with the given mode and file name.
+ **/
cdk_error_t
-cdk_stream_set_literal_flag (cdk_stream_t s, int mode, const char *fname)
+cdk_stream_set_literal_flag (cdk_stream_t s, cdk_lit_format_t mode,
+ const char *fname)
{
struct stream_filter_s *f;
const char *orig_fname;
@@ -1050,6 +1088,17 @@ cdk_stream_set_literal_flag (cdk_stream_t s, int mode, const char *fname)
}
+/**
+ * cdk_stream_set_cipher_flag:
+ * @s: the stream object
+ * @dek: the data encryption key
+ * @use_mdc: 1 means to use the MDC mode
+ *
+ * In read mode it kicks off the cipher filter to decrypt the data
+ * from the stream with the key given in @dek.
+ * In write mode the stream data will be encrypted with the DEK object
+ * and optionally, the @use_mdc parameter can be used to enable the MDC mode.
+ **/
cdk_error_t
cdk_stream_set_cipher_flag (cdk_stream_t s, cdk_dek_t dek, int use_mdc)
{
@@ -1074,6 +1123,17 @@ cdk_stream_set_cipher_flag (cdk_stream_t s, cdk_dek_t dek, int use_mdc)
}
+/**
+ * cdk_stream_set_compress_flag:
+ * @s: the stream object
+ * @algo: the compression algo
+ * @level: level of compression (0..9)
+ *
+ * In read mode it kicks off the decompression filter to retrieve
+ * the uncompressed data.
+ * In write mode the stream data will be compressed with the
+ * given algorithm at the given level.
+ **/
cdk_error_t
cdk_stream_set_compress_flag (cdk_stream_t s, int algo, int level)
{
@@ -1091,6 +1151,13 @@ cdk_stream_set_compress_flag (cdk_stream_t s, int algo, int level)
}
+/**
+ * cdk_stream_set_text_flag:
+ * @s: the stream object
+ * @lf: line ending
+ *
+ * Pushes the text filter to store the stream data in cannoncial format.
+ **/
cdk_error_t
cdk_stream_set_text_flag (cdk_stream_t s, const char *lf)
{
@@ -1107,6 +1174,14 @@ cdk_stream_set_text_flag (cdk_stream_t s, const char *lf)
}
+/**
+ * cdk_stream_set_hash_flag:
+ * @s: the stream object
+ * @digest_algo: the digest algorithm to use
+ *
+ * This is for read-only streams. It pushes a digest filter to
+ * calculate the digest of the given stream data.
+ **/
cdk_error_t
cdk_stream_set_hash_flag (cdk_stream_t s, int digest_algo)
{
@@ -1141,6 +1216,12 @@ cdk_stream_enable_cache (cdk_stream_t s, int val)
if (!s->flags.write)
return CDK_Inv_Mode;
s->cache.on = val;
+ if (!s->cache.buf)
+ {
+ s->cache.buf = cdk_calloc (1, STREAM_BUFSIZE);
+ s->cache.alloced = STREAM_BUFSIZE;
+ _cdk_log_debug ("stream: allocate cache of %d octets\n", STREAM_BUFSIZE);
+ }
return 0;
}
@@ -1160,7 +1241,7 @@ stream_cache_flush (cdk_stream_t s, FILE * fp)
return CDK_File_Error;
s->cache.size = 0;
s->cache.on = 0;
- wipemem (s->cache.buf, sizeof s->cache.buf);
+ wipemem (s->cache.buf, s->cache.alloced);
}
return 0;
}
@@ -1328,7 +1409,7 @@ _cdk_stream_set_blockmode (cdk_stream_t s, size_t nbytes)
{
assert (s);
- _cdk_log_debug ("set block mode for stream; blocksize %d\n", nbytes);
+ _cdk_log_debug ("stream: activate block mode with blocksize %d\n", nbytes);
s->blkmode = nbytes;
return 0;
}
diff --git a/libextra/opencdk/stream.h b/libextra/opencdk/stream.h
index ef1d1c725b..df44c6c6b8 100644
--- a/libextra/opencdk/stream.h
+++ b/libextra/opencdk/stream.h
@@ -73,9 +73,10 @@ struct cdk_stream_s {
unsigned compressed:3;
} flags;
struct {
- unsigned char buf[STREAM_BUFSIZE];
+ unsigned char *buf;
unsigned on:1;
- off_t size;
+ size_t size;
+ size_t alloced;
} cache;
char *fname;
FILE *fp;
diff --git a/libextra/opencdk/verify.c b/libextra/opencdk/verify.c
index 7bd388afe5..de6a50ebb9 100644
--- a/libextra/opencdk/verify.c
+++ b/libextra/opencdk/verify.c
@@ -285,9 +285,11 @@ file_verify_clearsign (cdk_ctx_t hd, const char *file, const char *output)
cdk_stream_set_armor_flag (tmp, 0);
cdk_stream_read (tmp, NULL, 0);
+ /* the digest handle will be closed there. */
rc = _cdk_proc_packets (hd, tmp, NULL, NULL, NULL, md);
leave:
+ gcry_md_close (md);
cdk_stream_close (out);
cdk_stream_close (tmp);
cdk_stream_close (inp);