summaryrefslogtreecommitdiff
path: root/libextra
diff options
context:
space:
mode:
authorSimon Josefsson <simon@josefsson.org>2007-10-27 20:51:54 +0200
committerSimon Josefsson <simon@josefsson.org>2007-10-27 20:51:54 +0200
commitb0fe9d060db77689d32987e0e488704ae0defcb9 (patch)
tree98f6ea9da40107e4b3c1e0b69f4c38c2d6dbdce8 /libextra
parente188ad5c26777938ebbff589e54a8cdcef548d71 (diff)
downloadgnutls-b0fe9d060db77689d32987e0e488704ae0defcb9.tar.gz
Sync with OpenCDK 0.6.5.
Diffstat (limited to 'libextra')
-rw-r--r--libextra/opencdk/cipher.c20
-rw-r--r--libextra/opencdk/keydb.c309
-rw-r--r--libextra/opencdk/new-packet.c30
-rw-r--r--libextra/opencdk/opencdk.h10
-rw-r--r--libextra/opencdk/seskey.c19
5 files changed, 261 insertions, 127 deletions
diff --git a/libextra/opencdk/cipher.c b/libextra/opencdk/cipher.c
index 900fb7a21b..1dc1771b02 100644
--- a/libextra/opencdk/cipher.c
+++ b/libextra/opencdk/cipher.c
@@ -26,6 +26,10 @@
#include "filters.h"
+/* The maximal cipher block size in octets. */
+#define MAX_CIPHER_BLKSIZE 16
+
+
static off_t
fp_get_length (FILE *fp)
{
@@ -95,11 +99,11 @@ write_header (cipher_filter_t *cfx, FILE *out)
{
cdk_pkt_encrypted_t ed;
cdk_packet_t pkt;
+ cdk_error_t rc;
cdk_dek_t dek = cfx->dek;
- byte temp[18];
+ byte temp[MAX_CIPHER_BLKSIZE+2];
size_t blocksize;
- int use_mdc, nprefix;
- cdk_error_t rc = 0;
+ int use_mdc, nprefix;
gcry_error_t err;
blocksize = gcry_cipher_get_algo_blklen (dek->algo);
@@ -415,11 +419,11 @@ finalize_mdc (gcry_md_hd_t md, const byte *buf, size_t nread)
static cdk_error_t
cipher_decode_file (void *opaque, FILE *in, FILE *out)
-{
+{
cipher_filter_t *cfx = opaque;
- byte buf[BUFSIZE];
- int nread, nreq;
cdk_error_t rc;
+ byte buf[BUFSIZE];
+ int nread, nreq;
if (!cfx || !in || !out)
return CDK_Inv_Value;
@@ -464,7 +468,7 @@ cipher_decode_file (void *opaque, FILE *in, FILE *out)
static cdk_error_t
cipher_decode (void * opaque, FILE * in, FILE * out)
{
- cipher_filter_t * cfx = opaque;
+ cipher_filter_t *cfx = opaque;
cdk_error_t rc;
_cdk_log_debug ("cipher filter: decode\n");
@@ -482,7 +486,7 @@ cipher_decode (void * opaque, FILE * in, FILE * out)
static cdk_error_t
cipher_encode (void *opaque, FILE *in, FILE *out)
{
- cipher_filter_t * cfx = opaque;
+ cipher_filter_t *cfx = opaque;
cdk_error_t rc;
_cdk_log_debug ("cipher filter: encode\n");
diff --git a/libextra/opencdk/keydb.c b/libextra/opencdk/keydb.c
index 311565e27f..acebd56fff 100644
--- a/libextra/opencdk/keydb.c
+++ b/libextra/opencdk/keydb.c
@@ -45,12 +45,14 @@ 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;
+struct cdk_dbsearch_s
+{
+ union
+ {
+ char *pattern; /* A search is performed by pattern. */
+ u32 keyid[2]; /* A search by keyid. */
+ byte fpr[KEY_FPR_LEN]; /* A search by fingerprint. */
+ } u;
int type;
};
typedef struct cdk_dbsearch_s *cdk_dbsearch_t;
@@ -58,7 +60,7 @@ 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;
+ struct key_table_s *next;
off_t offset;
cdk_dbsearch_t desc;
};
@@ -67,19 +69,24 @@ 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;
+ int type; /* type of the key db handle. */
+ int fp_ref; /* 1=means it is a reference and shall not be closed. */
+ cdk_stream_t fp;
cdk_stream_t idx;
cdk_dbsearch_t dbs;
- char *name;
- char *idx_name;
+ char *name; /* name of the underlying file or NULL. */
+ char *idx_name; /* name of the index file or NULL. */
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;
+ unsigned int secret:1; /* contain secret keys. */
+ unsigned int isopen:1; /* the underlying stream is opened. */
+ unsigned int no_cache:1; /* disable the index cache. */
+ unsigned int search:1; /* handle is in search mode. */
+
+ /* structure to store some stats about the keydb. */
+ struct {
+ size_t new_keys; /* amount of new keys that were imported. */
+ } stats;
};
@@ -141,7 +148,10 @@ keydb_idx_build (const char *file)
rc = cdk_stream_create (idx_name, &out);
cdk_free (idx_name);
if (rc)
- goto leave;
+ {
+ cdk_stream_close (inp);
+ return rc;
+ }
cdk_pkt_new (&pkt);
while (!cdk_stream_eof (inp))
@@ -170,7 +180,6 @@ keydb_idx_build (const char *file)
cdk_pkt_release (pkt);
- leave:
cdk_stream_close (out);
cdk_stream_close (inp);
return rc;
@@ -305,14 +314,14 @@ cdk_keydb_new_from_mem (cdk_keydb_hd_t *r_db, int secret,
return CDK_Inv_Value;
*r_db = NULL;
db = calloc (1, sizeof *db);
- rc = cdk_stream_tmp_from_mem (data, datlen, &db->buf);
- if (!db->buf)
+ rc = cdk_stream_tmp_from_mem (data, datlen, &db->fp);
+ if (!db->fp)
{
cdk_free (db);
return rc;
}
- if (cdk_armor_filter_use (db->buf))
- cdk_stream_set_armor_flag (db->buf, 0);
+ if (cdk_armor_filter_use (db->fp))
+ cdk_stream_set_armor_flag (db->fp, 0);
db->type = CDK_DBTYPE_DATA;
db->secret = secret;
*r_db = db;
@@ -341,8 +350,8 @@ cdk_keydb_new_from_stream (cdk_keydb_hd_t *r_hd, int secret,
*r_hd = NULL;
hd = calloc (1, sizeof *hd);
- hd->buf = in;
- hd->buf_ref = 1;
+ hd->fp = in;
+ hd->fp_ref = 1;
hd->type = CDK_DBTYPE_STREAM;
hd->secret = secret;
*r_hd = hd;
@@ -427,10 +436,10 @@ cdk_keydb_free (cdk_keydb_hd_t hd)
hd->name = NULL;
}
- if (hd->buf && !hd->buf_ref)
+ if (hd->fp && !hd->fp_ref)
{
- cdk_stream_close (hd->buf);
- hd->buf = NULL;
+ cdk_stream_close (hd->fp);
+ hd->fp = NULL;
}
if (hd->idx)
@@ -460,25 +469,25 @@ _cdk_keydb_open (cdk_keydb_hd_t hd, cdk_stream_t *ret_kr)
rc = 0;
if ((hd->type == CDK_DBTYPE_DATA || hd->type == CDK_DBTYPE_STREAM)
- && hd->buf)
- cdk_stream_seek (hd->buf, 0);
+ && hd->fp)
+ cdk_stream_seek (hd->fp, 0);
else if (hd->type == CDK_DBTYPE_PK_KEYRING ||
hd->type == CDK_DBTYPE_SK_KEYRING)
{
if (!hd->isopen && hd->name)
{
- rc = cdk_stream_open (hd->name, &hd->buf);
+ rc = cdk_stream_open (hd->name, &hd->fp);
if (rc)
goto leave;
- if (cdk_armor_filter_use (hd->buf))
- cdk_stream_set_armor_flag (hd->buf, 0);
+ if (cdk_armor_filter_use (hd->fp))
+ cdk_stream_set_armor_flag (hd->fp, 0);
hd->isopen = 1;
/* We disable the index cache for smaller keyrings. */
- if (cdk_stream_get_length (hd->buf) < 524288)
+ if (cdk_stream_get_length (hd->fp) < 524288)
{
hd->no_cache = 1;
goto leave;
- }
+ }
cdk_free (hd->idx_name);
hd->idx_name = keydb_idx_mkname (hd->name);
if (!hd->idx_name)
@@ -512,7 +521,7 @@ _cdk_keydb_open (cdk_keydb_hd_t hd, cdk_stream_t *ret_kr)
this mode is an enumeration and no seeking is needed. */
if (!hd->search ||
(hd->search && hd->dbs->type != CDK_DBSEARCH_NEXT))
- cdk_stream_seek (hd->buf, 0);
+ cdk_stream_seek (hd->fp, 0);
}
}
else
@@ -521,10 +530,10 @@ _cdk_keydb_open (cdk_keydb_hd_t hd, cdk_stream_t *ret_kr)
leave:
if (rc)
{
- cdk_stream_close (hd->buf);
- hd->buf = NULL;
+ cdk_stream_close (hd->fp);
+ hd->fp = NULL;
}
- *ret_kr = hd->buf;
+ *ret_kr = hd->fp;
return rc;
}
@@ -555,7 +564,8 @@ find_by_keyid (cdk_kbnode_t knode, cdk_dbsearch_t ks)
return 1;
break;
- default: /* Invalid mode */
+ default:
+ _cdk_log_debug ("find_by_keyid: invalid mode = %d\n", ks->type);
return 0;
}
}
@@ -639,7 +649,7 @@ keydb_search_free (cdk_dbsearch_t dbs)
return;
if (dbs->type == CDK_DBSEARCH_EXACT ||
dbs->type == CDK_DBSEARCH_SUBSTR)
- cdk_free( dbs->u.pattern );
+ cdk_free (dbs->u.pattern);
dbs->type = 0;
cdk_free (dbs);
}
@@ -793,7 +803,7 @@ cdk_keydb_search_start (cdk_keydb_hd_t db, int type, void *desc)
dbs->u.pattern = cdk_strdup (desc);
if (!dbs->u.pattern)
{
- cdk_free( dbs );
+ cdk_free (dbs);
return CDK_Out_Of_Core;
}
break;
@@ -837,12 +847,12 @@ cdk_keydb_search_start (cdk_keydb_hd_t db, int type, void *desc)
p = desc;
if (!strncmp (p, "0x", 2))
p += 2;
- if (strlen (p) == 8 )
+ if (strlen (p) == 8)
{
dbs->u.keyid[0] = 0;
dbs->u.keyid[1] = strtoul (p, NULL, 16);
}
- else if (strlen (p) == 16 )
+ else if (strlen (p) == 16)
{
dbs->u.keyid[0] = strtoul (p , NULL, 16);
dbs->u.keyid[1] = strtoul (p + 8, NULL, 16);
@@ -874,6 +884,7 @@ cdk_keydb_search_start (cdk_keydb_hd_t db, int type, void *desc)
default:
cdk_free (dbs);
+ _cdk_log_debug ("cdk_keydb_search_start: invalid mode = %d\n", type);
return CDK_Inv_Mode;
}
@@ -943,18 +954,19 @@ keydb_pos_from_cache (cdk_keydb_hd_t hd, cdk_dbsearch_t ks,
cdk_error_t
cdk_keydb_search (cdk_keydb_hd_t hd, cdk_kbnode_t *ret_key)
{
- cdk_stream_t kr = NULL;
- cdk_kbnode_t knode = NULL;
+ cdk_stream_t kr;
+ cdk_kbnode_t knode;
cdk_dbsearch_t ks;
- off_t pos = 0, off = 0;
- int key_found = 0, cache_hit = 0;
cdk_error_t rc = 0;
+ off_t pos = 0, off = 0;
+ int key_found = 0, cache_hit = 0;
if (!hd || !ret_key)
return CDK_Inv_Value;
*ret_key = NULL;
- hd->search = 1;
+ kr = NULL;
+ hd->search = 1;
rc = _cdk_keydb_open (hd, &kr);
if (rc)
return rc;
@@ -969,6 +981,7 @@ cdk_keydb_search (cdk_keydb_hd_t hd, cdk_kbnode_t *ret_key)
cache_hit = 0;
}
+ knode = NULL;
ks = hd->dbs;
while (!key_found && !rc)
{
@@ -1076,11 +1089,14 @@ static int
keydb_check_key (cdk_packet_t pkt)
{
cdk_pkt_pubkey_t pk;
- int is_sk = 0, valid = 0;
+ int is_sk, valid;
if (pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
- pk = pkt->pkt.public_key;
+ {
+ pk = pkt->pkt.public_key;
+ is_sk = 0;
+ }
else if (pkt->pkttype == CDK_PKT_SECRET_KEY ||
pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
{
@@ -1118,7 +1134,7 @@ kbnode_find_valid (cdk_kbnode_t root, int pkttype)
static cdk_kbnode_t
keydb_find_byusage (cdk_kbnode_t root, int req_usage, int is_pk)
{
- cdk_kbnode_t node, key = NULL;
+ cdk_kbnode_t node, key;
int req_type;
long timestamp;
@@ -1129,7 +1145,8 @@ keydb_find_byusage (cdk_kbnode_t root, int req_usage, int is_pk)
node = cdk_kbnode_find (root, req_type);
if (node && !keydb_check_key (node->pkt))
return NULL;
-
+
+ key = NULL;
timestamp = 0;
/* We iteratre over the all nodes and search for keys or
subkeys which match the usage and which are not invalid.
@@ -1171,7 +1188,7 @@ keydb_find_bykeyid (cdk_kbnode_t root, const u32 *keyid, int search_mode)
if (search_mode == CDK_DBSEARCH_SHORT_KEYID &&
kid[1] == keyid[1])
return node;
- if (kid[0] == keyid[0] && kid[1] == keyid[1])
+ else if (kid[0] == keyid[0] && kid[1] == keyid[1])
return node;
}
return NULL;
@@ -1183,7 +1200,7 @@ _cdk_keydb_get_sk_byusage (cdk_keydb_hd_t hd, const char *name,
cdk_seckey_t* ret_sk, int usage)
{
cdk_kbnode_t knode = NULL;
- cdk_kbnode_t node, sk_node;
+ cdk_kbnode_t node, sk_node, pk_node;
cdk_pkt_seckey_t sk;
cdk_error_t rc;
const char *s;
@@ -1227,12 +1244,20 @@ _cdk_keydb_get_sk_byusage (cdk_keydb_hd_t hd, const char *name,
}
}
}
-
- node = find_selfsig_node (knode, sk->pk);
+
+ /* To find the self signature, we need the primary public key because
+ the selected secret key might be different from the primary key. */
+ pk_node = cdk_kbnode_find (knode, CDK_PKT_SECRET_KEY);
+ if (!pk_node)
+ {
+ cdk_kbnode_release (knode);
+ return CDK_Unusable_Key;
+ }
+ node = find_selfsig_node (knode, pk_node->pkt->pkt.secret_key->pk);
if (sk->pk->uid && node)
_cdk_copy_signature (&sk->pk->uid->selfsig, node->pkt->pkt.signature);
- /* We release the outer packet. */
+ /* We only release the outer packet. */
_cdk_pkt_detach_free (sk_node->pkt, &pkttype, (void*)&sk);
cdk_kbnode_release (knode);
*ret_sk = sk;
@@ -1244,8 +1269,8 @@ cdk_error_t
_cdk_keydb_get_pk_byusage (cdk_keydb_hd_t hd, const char *name,
cdk_pubkey_t *ret_pk, int usage)
{
- cdk_kbnode_t knode, node = NULL;
- cdk_pkt_pubkey_t pk = NULL;
+ cdk_kbnode_t knode, node, pk_node;
+ cdk_pkt_pubkey_t pk;
const char *s;
cdk_error_t rc;
@@ -1268,6 +1293,7 @@ _cdk_keydb_get_pk_byusage (cdk_keydb_hd_t hd, const char *name,
return CDK_Unusable_Key;
}
+ pk = NULL;
_cdk_copy_pubkey (&pk, node->pkt->pkt.public_key);
for (node = knode; node; node = node->next)
{
@@ -1282,7 +1308,15 @@ _cdk_keydb_get_pk_byusage (cdk_keydb_hd_t hd, const char *name,
}
}
- node = find_selfsig_node (knode, pk);
+ /* Same as in the sk code, the selected key can be a sub key
+ and thus we need the primary key to find the self sig. */
+ pk_node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY);
+ if (!pk_node)
+ {
+ cdk_kbnode_release (knode);
+ return CDK_Unusable_Key;
+ }
+ node = find_selfsig_node (knode, pk_node->pkt->pkt.public_key);
if (pk->uid && node)
_cdk_copy_signature (&pk->uid->selfsig, node->pkt->pkt.signature);
cdk_kbnode_release (knode);
@@ -1292,6 +1326,15 @@ _cdk_keydb_get_pk_byusage (cdk_keydb_hd_t hd, const char *name,
}
+/**
+ * cdk_keydb_get_pk:
+ * @hd: key db handle
+ * @keyid: keyid of the key
+ * @r_pk: the allocated public key
+ *
+ * Perform a key database search by keyid and return the raw public
+ * key without any signatures or user id's.
+ **/
cdk_error_t
cdk_keydb_get_pk (cdk_keydb_hd_t hd, u32 *keyid, cdk_pubkey_t *r_pk)
{
@@ -1332,6 +1375,16 @@ cdk_keydb_get_pk (cdk_keydb_hd_t hd, u32 *keyid, cdk_pubkey_t *r_pk)
}
+/**
+ * cdk_keydb_get_sk:
+ * @hd: key db handle
+ * @keyid: the keyid of the key
+ * @ret_sk: the allocated secret key
+ *
+ * Perform a key database search by keyid and return
+ * only the raw secret key without the additional nodes,
+ * like the user id or the signatures.
+ **/
cdk_error_t
cdk_keydb_get_sk (cdk_keydb_hd_t hd, u32 *keyid, cdk_seckey_t *ret_sk)
{
@@ -1376,27 +1429,37 @@ is_selfsig (cdk_kbnode_t node, const u32 *keyid)
if (node->pkt->pkttype != CDK_PKT_SIGNATURE)
return 0;
sig = node->pkt->pkt.signature;
- if ((sig->sig_class == 0x13 || sig->sig_class == 0x10) &&
+ if ((sig->sig_class >= 0x10 && sig->sig_class <= 0x13) &&
sig->keyid[0] == keyid[0] && sig->keyid[1] == keyid[1])
return 1;
+
return 0;
}
+/* Find the newest self signature for the public key @pk
+ and return the signature node. */
static cdk_kbnode_t
find_selfsig_node (cdk_kbnode_t key, cdk_pkt_pubkey_t pk)
{
- cdk_kbnode_t n;
+ cdk_kbnode_t n, sig;
+ unsigned int ts;
u32 keyid[2];
cdk_pk_get_keyid (pk, keyid);
+ sig = NULL;
+ ts = 0;
for (n = key; n; n = n->next)
{
- if (is_selfsig (n, keyid))
- break;
+ if (is_selfsig (n, keyid) &&
+ n->pkt->pkt.signature->timestamp > ts)
+ {
+ ts = n->pkt->pkt.signature->timestamp;
+ sig = n;
+ }
}
- return n;
+ return sig;
}
@@ -1686,18 +1749,20 @@ cdk_keydb_get_keyblock (cdk_stream_t inp, cdk_kbnode_t *r_knode)
cdk_packet_t pkt;
cdk_kbnode_t knode, node;
cdk_desig_revoker_t revkeys;
+ cdk_error_t rc;
u32 keyid[2], main_keyid[2];
off_t old_off;
- int key_seen = 0, got_key = 0;
- cdk_error_t rc;
+ int key_seen, got_key;
if (!inp || !r_knode)
return CDK_Inv_Value;
+ /* Reset all values. */
keyid[0] = keyid[1] = 0;
main_keyid[0] = main_keyid[1] = 0;
revkeys = NULL;
knode = NULL;
+ key_seen = got_key = 0;
*r_knode = NULL;
rc = CDK_EOF;
@@ -1797,6 +1862,8 @@ cdk_keydb_get_keyblock (cdk_stream_t inp, cdk_kbnode_t *r_knode)
}
+/* Return the type of the given data. In case it cannot be classified,
+ a substring search will be performed. */
static int
classify_data (const byte *buf, size_t len)
{
@@ -1809,6 +1876,7 @@ classify_data (const byte *buf, size_t len)
len -= 2;
}
+ /* The length of the data does not match either a keyid or a fingerprint. */
if (len != 8 && len != 16 && len != 40)
return CDK_DBSEARCH_SUBSTR;
@@ -1831,13 +1899,23 @@ classify_data (const byte *buf, size_t len)
}
+/**
+ * cdk_keydb_export:
+ * hd: the keydb handle
+ * @out: the output stream
+ * @remusr: the list of key pattern to export
+ *
+ * Export a list of keys to the given output stream.
+ * Use string list with names for pattering searching.
+ * This procedure strips local signatures.
+ **/
cdk_error_t
cdk_keydb_export (cdk_keydb_hd_t hd, cdk_stream_t out, cdk_strlist_t remusr)
{
cdk_kbnode_t knode, node;
cdk_strlist_t r;
- int old_ctb = 0;
cdk_error_t rc;
+ int old_ctb;
for (r = remusr; r; r = r->next)
{
@@ -1847,6 +1925,17 @@ cdk_keydb_export (cdk_keydb_hd_t hd, cdk_stream_t out, cdk_strlist_t remusr)
rc = cdk_keydb_search (hd, &knode);
if (rc)
return rc;
+ node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY);
+ if (!node)
+ return CDK_Error_No_Key;
+
+ /* If the key is a version 3 key, use the old packet
+ format for the output. */
+ if (node->pkt->pkt.public_key->version == 3)
+ old_ctb = 1;
+ else
+ old_ctb = 0;
+
for (node = knode; node; node = node->next)
{
/* No specified format; skip them */
@@ -1860,9 +1949,8 @@ cdk_keydb_export (cdk_keydb_hd_t hd, cdk_stream_t out, cdk_strlist_t remusr)
if (node->pkt->pkttype == CDK_PKT_SIGNATURE &&
!KEY_CAN_SIGN (node->pkt->pkt.signature->pubkey_algo))
continue;
- if (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY
- && node->pkt->pkt.public_key->version == 3)
- old_ctb = 1;
+
+ /* Adjust the ctb flag if needed. */
node->pkt->old_ctb = old_ctb;
rc = cdk_pkt_write (out, node->pkt);
if (rc)
@@ -1894,26 +1982,47 @@ find_key_packet (cdk_kbnode_t knode, int *r_is_sk)
}
+/* Return 1 if the is allowd in a key node. */
+static int
+is_key_node (cdk_kbnode_t node)
+{
+ switch (node->pkt->pkttype)
+ {
+ case CDK_PKT_SIGNATURE:
+ case CDK_PKT_SECRET_KEY:
+ case CDK_PKT_PUBLIC_KEY:
+ case CDK_PKT_SECRET_SUBKEY:
+ case CDK_PKT_PUBLIC_SUBKEY:
+ case CDK_PKT_USER_ID:
+ case CDK_PKT_ATTRIBUTE:
+ return 1;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+
cdk_error_t
cdk_keydb_import (cdk_keydb_hd_t hd, cdk_kbnode_t knode)
{
- cdk_kbnode_t node, chk = NULL;
+ cdk_kbnode_t node, chk;
cdk_packet_t pkt;
- cdk_stream_t out;
- u32 keyid[2];
- int is_sk = 0;
+ cdk_stream_t out;
cdk_error_t rc;
+ u32 keyid[2];
- /* FIXME: as a feedback we might have an additional function
- like cdk_keydb_get_import_stats () */
if (!hd || !knode)
return CDK_Inv_Value;
- pkt = find_key_packet (knode, &is_sk);
+ pkt = find_key_packet (knode, NULL);
if (!pkt)
return CDK_Inv_Packet;
_cdk_pkt_get_keyid (pkt, keyid);
+ chk = NULL;
cdk_keydb_get_bykeyid (hd, keyid, &chk);
if (chk)
{ /* FIXME: search for new signatures */
@@ -1921,10 +2030,12 @@ cdk_keydb_import (cdk_keydb_hd_t hd, cdk_kbnode_t knode)
return 0;
}
- if (hd->buf)
+ /* We append data to the stream so we need to close
+ the stream here to re-open it later. */
+ if (hd->fp)
{
- cdk_stream_close (hd->buf);
- hd->buf = NULL;
+ cdk_stream_close (hd->fp);
+ hd->fp = NULL;
}
rc = _cdk_stream_append (hd->name, &out);
@@ -1938,9 +2049,17 @@ cdk_keydb_import (cdk_keydb_hd_t hd, cdk_kbnode_t knode)
if (node->pkt->pkttype == CDK_PKT_SIGNATURE &&
!node->pkt->pkt.signature->flags.exportable)
{
- _cdk_log_debug ("Key import: skip local signature\n");
+ _cdk_log_debug ("key db import: skip local signature\n");
+ continue;
+ }
+
+ if (!is_key_node (node))
+ {
+ _cdk_log_debug ("key db import: skip invalid node of type %d\n",
+ node->pkt->pkttype);
continue;
}
+
rc = cdk_pkt_write (out, node->pkt);
if (rc)
{
@@ -1952,16 +2071,18 @@ cdk_keydb_import (cdk_keydb_hd_t hd, cdk_kbnode_t knode)
cdk_stream_close (out);
if (!hd->no_cache)
cdk_keydb_idx_rebuild (hd);
+ hd->stats.new_keys++;
+
return 0;
}
cdk_error_t
-_cdk_keydb_check_userid (cdk_keydb_hd_t hd, u32 * keyid, const char *id)
+_cdk_keydb_check_userid (cdk_keydb_hd_t hd, u32 *keyid, const char *id)
{
- cdk_kbnode_t knode = NULL, unode = NULL;
- int check = 0;
+ cdk_kbnode_t knode = NULL, unode = NULL;
cdk_error_t rc;
+ int check;
if (!hd)
return CDK_Inv_Value;
@@ -1982,6 +2103,7 @@ _cdk_keydb_check_userid (cdk_keydb_hd_t hd, u32 * keyid, const char *id)
return rc;
}
+ check = 0;
cdk_keydb_search_start (hd, CDK_DBSEARCH_KEYID, keyid);
if (unode && find_by_keyid (unode, hd->dbs))
check++;
@@ -1996,13 +2118,21 @@ _cdk_keydb_check_userid (cdk_keydb_hd_t hd, u32 * keyid, const char *id)
}
+/**
+ * cdk_keydb_check_sk:
+ * @hd: the key db handle
+ * @keyid: the 64-bit keyid
+ *
+ * Check if a secret key with the given key ID is available
+ * in the key database.
+ **/
cdk_error_t
cdk_keydb_check_sk (cdk_keydb_hd_t hd, u32 *keyid)
{
cdk_stream_t db;
- cdk_packet_t pkt;
- u32 kid[2];
+ cdk_packet_t pkt;
cdk_error_t rc;
+ u32 kid[2];
if (!hd || !keyid)
return CDK_Inv_Value;
@@ -2120,8 +2250,8 @@ cdk_listkey_next (cdk_listkey_t ctx, cdk_kbnode_t *ret_key)
if (!ctx->init)
return CDK_Inv_Mode;
- if (ctx->type && ctx->u.patt[0] == '*' )
- return cdk_keydb_get_keyblock( ctx->inp, ret_key );
+ if (ctx->type && ctx->u.patt[0] == '*')
+ return cdk_keydb_get_keyblock (ctx->inp, ret_key);
else if (ctx->type)
{
cdk_kbnode_t node;
@@ -2158,6 +2288,7 @@ 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)
{
diff --git a/libextra/opencdk/new-packet.c b/libextra/opencdk/new-packet.c
index 865997f691..1c7e5da4aa 100644
--- a/libextra/opencdk/new-packet.c
+++ b/libextra/opencdk/new-packet.c
@@ -25,6 +25,7 @@
#include "packet.h"
+/* Release an array of MPI values. */
void
_cdk_free_mpibuf (size_t n, gcry_mpi_t *array)
{
@@ -36,6 +37,12 @@ _cdk_free_mpibuf (size_t n, gcry_mpi_t *array)
}
+/**
+ * cdk_pkt_new:
+ * @r_pkt: the new packet
+ *
+ * Allocate a new packet.
+ **/
cdk_error_t
cdk_pkt_new (cdk_packet_t *r_pkt)
{
@@ -70,11 +77,7 @@ free_pubkey_enc (cdk_pkt_pubkey_enc_t enc)
return;
nenc = cdk_pk_get_nenc (enc->pubkey_algo);
- while (nenc--)
- {
- gcry_mpi_release (enc->mpi[nenc]);
- enc->mpi[nenc] = NULL;
- }
+ _cdk_free_mpibuf (nenc, enc->mpi);
cdk_free (enc);
}
@@ -114,11 +117,8 @@ _cdk_free_signature (cdk_pkt_signature_t sig)
return;
nsig = cdk_pk_get_nsig (sig->pubkey_algo);
- while (nsig--)
- {
- gcry_mpi_release (sig->mpi[nsig]);
- sig->mpi[nsig] = NULL;
- }
+ _cdk_free_mpibuf (nsig, sig->mpi);
+
cdk_subpkt_free (sig->hashed);
sig->hashed = NULL;
cdk_subpkt_free (sig->unhashed);
@@ -146,11 +146,7 @@ cdk_pk_release (cdk_pubkey_t pk)
pk->uid = NULL;
cdk_free (pk->prefs);
pk->prefs = NULL;
- while (npkey--)
- {
- gcry_mpi_release (pk->mpi[npkey]);
- pk->mpi[npkey] = NULL;
- }
+ _cdk_free_mpibuf (npkey, pk->mpi);
cdk_free (pk);
}
@@ -164,8 +160,7 @@ cdk_sk_release (cdk_seckey_t sk)
return;
nskey = cdk_pk_get_nskey (sk->pubkey_algo);
- while (nskey--)
- gcry_mpi_release (sk->mpi[nskey]);
+ _cdk_free_mpibuf (nskey, sk->mpi);
cdk_free (sk->encdata);
sk->encdata = NULL;
cdk_pk_release (sk->pk);
@@ -248,6 +243,7 @@ cdk_pkt_free (cdk_packet_t pkt)
case CDK_PKT_COMPRESSED : cdk_free (pkt->pkt.compressed); break;
default : break;
}
+
/* Reset the packet type to avoid, when cdk_pkt_release() will be
used, that the second cdk_pkt_free() call will double free the data. */
pkt->pkttype = 0;
diff --git a/libextra/opencdk/opencdk.h b/libextra/opencdk/opencdk.h
index ea2f1b24bd..7cd538db05 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.4"
+#define OPENCDK_VERSION "0.6.5"
/* The OpenCDK version as integer components major.minor.path */
#define OPENCDK_VERSION_MAJOR 0
#define OPENCDK_VERSION_MINOR 6
-#define OPENCDK_VERSION_PATCH 4
+#define OPENCDK_VERSION_PATCH 5
#ifdef __cplusplus
extern "C" {
@@ -149,7 +149,8 @@ enum cdk_control_flags {
enum cdk_log_level_t {
CDK_LOG_NONE = 0, /* No log message will be shown. */
CDK_LOG_INFO = 1,
- CDK_LOG_DEBUG = 2
+ CDK_LOG_DEBUG = 2,
+ CDK_LOG_DEBUG_PKT = 3
};
@@ -195,8 +196,7 @@ enum cdk_cipher_algo_t {
CDK_CIPHER_AES = 7,
CDK_CIPHER_AES192 = 8,
CDK_CIPHER_AES256 = 9,
- CDK_CIPHER_TWOFISH = 10,
- CDK_CIPHER_CAMELLIA256 = 11 /* experimental use only, upcoming 2440bis */
+ CDK_CIPHER_TWOFISH = 10
};
diff --git a/libextra/opencdk/seskey.c b/libextra/opencdk/seskey.c
index e6956e6a5c..268a648933 100644
--- a/libextra/opencdk/seskey.c
+++ b/libextra/opencdk/seskey.c
@@ -102,14 +102,15 @@ cdk_dek_encode_pkcs1 (cdk_dek_t dek, size_t nbits, gcry_mpi_t *r_enc)
gcry_error_t err;
byte *p, *frame;
size_t n;
- size_t nframe = 0;
+ size_t nframe;
size_t i;
- u16 chksum = 0;
+ u16 chksum;
if (!r_enc || !dek)
return CDK_Inv_Value;
*r_enc = NULL;
+ chksum = 0;
for (i = 0; i < dek->keylen; i++)
chksum += dek->key[i];
nframe = (nbits + 7) / 8;
@@ -157,8 +158,7 @@ cdk_dek_encode_pkcs1 (cdk_dek_t dek, size_t nbits, gcry_mpi_t *r_enc)
cdk_free (frame);
if (err)
return map_gcry_error (err);
- else
- *r_enc = a;
+ *r_enc = a;
return 0;
}
@@ -177,7 +177,7 @@ cdk_dek_decode_pkcs1 (cdk_dek_t *ret_dek, gcry_mpi_t esk)
cdk_dek_t dek;
byte frame[MAX_MPI_BYTES+2+1];
size_t nframe, n;
- u16 csum = 0, csum2 = 0;
+ u16 csum, csum2;
gcry_error_t err;
if (!ret_dek || !esk)
@@ -216,13 +216,14 @@ 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_log_debug ("pkcs1 decode: invalid cipher keylen %d\n", dek->keylen);
cdk_free (dek);
return CDK_Inv_Algo;
}
csum = frame[nframe-2] << 8;
csum |= frame[nframe-1];
memcpy (dek->key, frame + n, dek->keylen);
+ csum2 = 0;
for (n = 0; n < dek->keylen; n++)
csum2 += dek->key[n];
if (csum != csum2)
@@ -242,7 +243,7 @@ _cdk_digest_encode_pkcs1 (byte **r_md, size_t *r_mdlen, int pk_algo,
const byte *md, int digest_algo, unsigned nbits)
{
gcry_error_t err;
- int dlen;
+ size_t dlen;
if (!md || !r_md || !r_mdlen)
return CDK_Inv_Value;
@@ -250,7 +251,7 @@ _cdk_digest_encode_pkcs1 (byte **r_md, size_t *r_mdlen, int pk_algo,
dlen = gcry_md_get_algo_dlen (digest_algo);
if (!dlen)
return CDK_Inv_Algo;
- if (is_DSA (pk_algo))
+ if (is_DSA (pk_algo)) /* DSS does not use a special encoding. */
{
*r_md = cdk_malloc (dlen + 1);
if (!*r_md)
@@ -286,6 +287,8 @@ _cdk_digest_encode_pkcs1 (byte **r_md, size_t *r_mdlen, int pk_algo,
}
+/* FIXME: The prompt should be provided in a more generic way.
+ Like: (keyid, algorithm, [user-id]) */
static char*
passphrase_prompt (cdk_pkt_seckey_t sk)
{