diff options
author | Simon Josefsson <simon@josefsson.org> | 2007-06-11 10:49:25 +0200 |
---|---|---|
committer | Simon Josefsson <simon@josefsson.org> | 2007-06-11 10:49:25 +0200 |
commit | c86c105e35466f58203a41b2bd9cd94c9967602d (patch) | |
tree | e6165e2471d091e3ec68701a8f34e203593d584d /libextra | |
parent | 37ceaa4697db3397be0191524e89427e42f023f5 (diff) | |
download | gnutls-c86c105e35466f58203a41b2bd9cd94c9967602d.tar.gz |
Update to OpenCDK 0.6.3.
Diffstat (limited to 'libextra')
-rw-r--r-- | libextra/opencdk/armor.c | 214 | ||||
-rw-r--r-- | libextra/opencdk/cipher.c | 73 | ||||
-rw-r--r-- | libextra/opencdk/compress.c | 2 | ||||
-rw-r--r-- | libextra/opencdk/context.h | 39 | ||||
-rw-r--r-- | libextra/opencdk/filters.h | 2 | ||||
-rw-r--r-- | libextra/opencdk/kbnode.c | 2 | ||||
-rw-r--r-- | libextra/opencdk/keydb.c | 176 | ||||
-rw-r--r-- | libextra/opencdk/literal.c | 27 | ||||
-rw-r--r-- | libextra/opencdk/main.c | 94 | ||||
-rw-r--r-- | libextra/opencdk/main.h | 16 | ||||
-rw-r--r-- | libextra/opencdk/misc.c | 119 | ||||
-rw-r--r-- | libextra/opencdk/new-packet.c | 281 | ||||
-rw-r--r-- | libextra/opencdk/opencdk.h | 125 | ||||
-rw-r--r-- | libextra/opencdk/pubkey.c | 212 | ||||
-rw-r--r-- | libextra/opencdk/read-packet.c | 6 | ||||
-rw-r--r-- | libextra/opencdk/seskey.c | 189 | ||||
-rw-r--r-- | libextra/opencdk/sig-check.c | 9 | ||||
-rw-r--r-- | libextra/opencdk/stream.c | 95 | ||||
-rw-r--r-- | libextra/opencdk/stream.h | 5 | ||||
-rw-r--r-- | libextra/opencdk/verify.c | 2 |
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); |