diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2007-10-24 23:44:45 +0300 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2007-10-24 23:44:45 +0300 |
commit | 3a9bb9663e20587447699352ad78b231e35ad9f0 (patch) | |
tree | 90877fd0409d3bef96afcaacb9fa2016772e367b /libextra | |
parent | e3b8eea08c24fd71a66669f4e7424d2636c9aaca (diff) | |
download | gnutls-3a9bb9663e20587447699352ad78b231e35ad9f0.tar.gz |
Several changes to openpgp code:
* gnutls_certificate_set_openpgp_* functions were modified to include format
* KEYRING_HACK is defined to overcome a bug in opencdk which makes keyrings reentrant.
Once fixed, the KEYRING_HACK code should be removed.
Diffstat (limited to 'libextra')
-rw-r--r-- | libextra/gnutls_openpgp.c | 395 | ||||
-rw-r--r-- | libextra/openpgp/compat.c | 33 | ||||
-rw-r--r-- | libextra/openpgp/gnutls_openpgp.h | 31 | ||||
-rw-r--r-- | libextra/openpgp/openpgp.h | 7 |
4 files changed, 221 insertions, 245 deletions
diff --git a/libextra/gnutls_openpgp.c b/libextra/gnutls_openpgp.c index 8151deed04..36b54077b4 100644 --- a/libextra/gnutls_openpgp.c +++ b/libextra/gnutls_openpgp.c @@ -28,7 +28,7 @@ #include "gnutls_cert.h" #include "gnutls_datum.h" #include "gnutls_global.h" -#include <openpgp/gnutls_openpgp.h> +#include "openpgp/gnutls_openpgp.h" #include "read-file.h" #include <gnutls_str.h> #include <gnutls_sig.h> @@ -123,7 +123,7 @@ kbx_blob_new (keybox_blob ** r_ctx) } -void +static void kbx_blob_release (keybox_blob * ctx) { if (!ctx) @@ -133,7 +133,7 @@ kbx_blob_release (keybox_blob * ctx) } -cdk_keydb_hd_t +static cdk_keydb_hd_t kbx_to_keydb (keybox_blob * blob) { cdk_keydb_hd_t db; @@ -166,7 +166,7 @@ kbx_to_keydb (keybox_blob * blob) /* Extract a keybox blob from the given position. */ -keybox_blob * +static keybox_blob * kbx_read_blob (const gnutls_datum_t * keyring, size_t pos) { keybox_blob *blob = NULL; @@ -441,6 +441,85 @@ _gnutls_openpgp_raw_key_to_gcert (gnutls_cert * cert, return rc; } +/** + * gnutls_certificate_set_openpgp_key - Used to set keys in a gnutls_certificate_credentials_t structure + * @res: is an #gnutls_certificate_credentials_t structure. + * @key: contains an openpgp public key + * @pkey: is an openpgp private key + * + * This function sets a certificate/private key pair in the + * gnutls_certificate_credentials_t structure. This function may be called + * more than once (in case multiple keys/certificates exist for the + * server). + * + **/ +int +gnutls_certificate_set_openpgp_key (gnutls_certificate_credentials_t + res, gnutls_openpgp_crt_t crt, + gnutls_openpgp_privkey_t pkey) +{ + int ret; + + /* this should be first */ + + res->pkey = gnutls_realloc_fast (res->pkey, + (res->ncerts + 1) * + sizeof (gnutls_privkey)); + if (res->pkey == NULL) + { + gnutls_assert (); + return GNUTLS_E_MEMORY_ERROR; + } + + ret = _gnutls_openpgp_privkey_to_gkey (&res->pkey[res->ncerts], pkey); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + res->cert_list = gnutls_realloc_fast (res->cert_list, + (1 + + res->ncerts) * + sizeof (gnutls_cert *)); + if (res->cert_list == NULL) + { + gnutls_assert (); + return GNUTLS_E_MEMORY_ERROR; + } + + res->cert_list_length = gnutls_realloc_fast (res->cert_list_length, + (1 + + res->ncerts) * sizeof (int)); + if (res->cert_list_length == NULL) + { + gnutls_assert (); + return GNUTLS_E_MEMORY_ERROR; + } + + res->cert_list[res->ncerts] = gnutls_calloc (1, sizeof (gnutls_cert)); + if (res->cert_list[res->ncerts] == NULL) + { + gnutls_assert (); + return GNUTLS_E_MEMORY_ERROR; + } + + res->cert_list_length[res->ncerts] = 1; + + ret = _gnutls_openpgp_crt_to_gcert (res->cert_list[res->ncerts], crt); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + res->ncerts++; + + /* FIXME: Check if the keys match. */ + + return 0; +} + /*- * gnutls_openpgp_get_key - Retrieve a key from the keyring. @@ -555,148 +634,49 @@ stream_to_datum (cdk_stream_t inp, gnutls_datum_t * raw) **/ int gnutls_certificate_set_openpgp_key_mem (gnutls_certificate_credentials_t - res, const gnutls_datum_t * cert, - const gnutls_datum_t * key) + res, const gnutls_datum_t * icert, + const gnutls_datum_t * ikey, + gnutls_openpgp_crt_fmt_t format) { - gnutls_datum_t raw; - cdk_kbnode_t knode = NULL, ctx = NULL, p; - cdk_packet_t pkt; - int i = 0; - int rc = 0; - cdk_stream_t inp = NULL; - - if (!res || !key || !cert) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - rc = cdk_stream_tmp_from_mem (cert->data, cert->size, &inp); - if (rc) - { - rc = _gnutls_map_cdk_rc (rc); - gnutls_assert (); - return rc; - } - - if (cdk_armor_filter_use (inp)) - cdk_stream_set_armor_flag (inp, 0); - - res->cert_list = gnutls_realloc_fast (res->cert_list, - (1 + res->ncerts) * - sizeof (gnutls_cert *)); - if (res->cert_list == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - res->cert_list_length = gnutls_realloc_fast (res->cert_list_length, - (1 + - res->ncerts) * sizeof (int)); - if (res->cert_list_length == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - res->cert_list[res->ncerts] = gnutls_calloc (1, sizeof (gnutls_cert)); - if (res->cert_list[res->ncerts] == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - i = 1; - rc = cdk_keydb_get_keyblock (inp, &knode); - - while (knode && (p = cdk_kbnode_walk (knode, &ctx, 0))) - { - pkt = cdk_kbnode_get_packet (p); - if (i > MAX_PUBLIC_PARAMS_SIZE) - { - gnutls_assert (); - break; - } - if (pkt->pkttype == CDK_PKT_PUBLIC_KEY) - { - int n = res->ncerts; - - cdk_pkt_pubkey_t pk = pkt->pkt.public_key; - res->cert_list_length[n] = 1; - - if (stream_to_datum (inp, &res->cert_list[n][0].raw)) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - rc = openpgp_pk_to_gnutls_cert (&res->cert_list[n][0], pk); - if (rc < 0) - { - gnutls_assert (); - return rc; - } - i++; - } - } - - if (rc == CDK_EOF && i > 1) - rc = 0; - - cdk_stream_close (inp); - - if (rc) - { - cdk_kbnode_release (knode); - gnutls_assert (); - rc = _gnutls_map_cdk_rc (rc); - goto leave; - } - - res->ncerts++; - res->pkey = gnutls_realloc_fast (res->pkey, - (res->ncerts) * sizeof (gnutls_privkey)); - if (!res->pkey) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - /* ncerts has been incremented before */ - - rc = cdk_stream_tmp_from_mem (key->data, key->size, &inp); - if (rc) - { - gnutls_assert (); - return GNUTLS_E_INTERNAL_ERROR; - } - - if (cdk_armor_filter_use (inp)) - cdk_stream_set_armor_flag (inp, 0); + gnutls_openpgp_privkey_t key; + gnutls_openpgp_crt_t cert; + int ret; + + ret = gnutls_openpgp_privkey_init( &key); + if (ret < 0) { + gnutls_assert(); + return ret; + } - memset (&raw, 0, sizeof raw); + ret = gnutls_openpgp_privkey_import( key, ikey, format, NULL, 0); + if (ret < 0) { + gnutls_assert(); + gnutls_openpgp_privkey_deinit( key); + return ret; + } - if (stream_to_datum (inp, &raw)) - { - gnutls_assert (); - return GNUTLS_E_INTERNAL_ERROR; - } - cdk_stream_close (inp); + ret = gnutls_openpgp_crt_init( &cert); + if (ret < 0) { + gnutls_assert(); + gnutls_openpgp_privkey_deinit( key); + return ret; + } - rc = _gnutls_openpgp_raw_privkey_to_gkey (&res->pkey[res->ncerts - 1], - &raw, - GNUTLS_OPENPGP_FMT_RAW); - if (rc) - { - gnutls_assert (); - } + ret = gnutls_openpgp_crt_import( cert, icert, format); + if (ret < 0) { + gnutls_assert(); + gnutls_openpgp_privkey_deinit( key); + gnutls_openpgp_crt_deinit( cert); + return ret; + } - _gnutls_free_datum (&raw); -leave: - cdk_kbnode_release (knode); + ret = gnutls_certificate_set_openpgp_key( res, cert, key); - return rc; + gnutls_openpgp_privkey_deinit( key); + gnutls_openpgp_crt_deinit( cert); + + return ret; } @@ -713,7 +693,8 @@ leave: int gnutls_certificate_set_openpgp_key_file (gnutls_certificate_credentials_t res, const char *certfile, - const char *keyfile) + const char *keyfile, + gnutls_openpgp_crt_fmt_t format) { struct stat statbuf; gnutls_datum_t key, cert; @@ -749,7 +730,7 @@ gnutls_certificate_set_openpgp_key_file (gnutls_certificate_credentials_t return GNUTLS_E_FILE_ERROR; } - rc = gnutls_certificate_set_openpgp_key_mem (res, &cert, &key); + rc = gnutls_certificate_set_openpgp_key_mem (res, &cert, &key, format); free (cert.data); free (key.data); @@ -812,7 +793,7 @@ gnutls_openpgp_count_key_names (const gnutls_datum_t * cert) **/ int gnutls_certificate_set_openpgp_keyring_file - (gnutls_certificate_credentials_t c, const char *file) + (gnutls_certificate_credentials_t c, const char *file, gnutls_openpgp_crt_fmt_t format) { gnutls_datum ring; size_t size; @@ -832,7 +813,7 @@ int rc; return GNUTLS_E_FILE_ERROR; } - rc = gnutls_certificate_set_openpgp_keyring_mem (c, ring.data, ring.size); + rc = gnutls_certificate_set_openpgp_keyring_mem (c, ring.data, ring.size, format); free( ring.data); @@ -854,8 +835,9 @@ int rc; int gnutls_certificate_set_openpgp_keyring_mem (gnutls_certificate_credentials_t c, const opaque * data, - size_t dlen) + size_t dlen, gnutls_openpgp_crt_fmt_t format) { +#ifndef KEYRING_HACK cdk_stream_t inp; size_t count; uint8_t *buf; @@ -877,7 +859,7 @@ gnutls_certificate_set_openpgp_keyring_mem (gnutls_certificate_credentials_t return rc; } - rc = gnutls_openpgp_keyring_import( c->keyring, &ddata, GNUTLS_OPENPGP_FMT_BASE64); + rc = gnutls_openpgp_keyring_import( c->keyring, &ddata, format); if ( rc < 0) { gnutls_assert(); gnutls_openpgp_keyring_deinit( c->keyring); @@ -885,6 +867,21 @@ gnutls_certificate_set_openpgp_keyring_mem (gnutls_certificate_credentials_t } return 0; +#else + + c->keyring_format = format; + + c->keyring.data = gnutls_malloc( dlen+1); + if (c->keyring.data == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + memcpy(c->keyring.data, data, dlen); + c->keyring.data[dlen]=0; + c->keyring.size = dlen; + +#endif } /*- @@ -904,6 +901,9 @@ _gnutls_openpgp_request_key (gnutls_session_t session, gnutls_datum_t * ret, opaque * key_fpr, int key_fpr_size) { int rc = 0; +#ifdef KEYRING_HACK + gnutls_openpgp_keyring_t kring; +#endif if (!ret || !cred || !key_fpr) { @@ -914,9 +914,27 @@ _gnutls_openpgp_request_key (gnutls_session_t session, gnutls_datum_t * ret, if (key_fpr_size != 16 && key_fpr_size != 20) return GNUTLS_E_HASH_FAILED; /* only MD5 and SHA1 are supported */ +#ifndef KEYRING_HACK rc = gnutls_openpgp_get_key (ret, cred->keyring, KEY_ATTR_FPR, key_fpr); - if (rc >= 0) /* key was found */ +#else + rc = gnutls_openpgp_keyring_init( &kring); + if ( rc < 0) { + gnutls_assert(); return rc; + } + + rc = gnutls_openpgp_keyring_import( kring, &cred->keyring, cred->keyring_format); + if ( rc < 0) { + gnutls_assert(); + gnutls_openpgp_keyring_deinit( kring); + return rc; + } +#endif + if (rc >= 0) /* key was found */ + { + rc = 0; + goto error; + } else rc = GNUTLS_E_OPENPGP_GETKEY_FAILED; @@ -929,10 +947,15 @@ _gnutls_openpgp_request_key (gnutls_session_t session, gnutls_datum_t * ret, if (rc < 0) { gnutls_assert (); - return GNUTLS_E_OPENPGP_GETKEY_FAILED; + rc = GNUTLS_E_OPENPGP_GETKEY_FAILED; + goto error; } } + error: +#ifdef KEYRING_HACK + gnutls_openpgp_keyring_deinit( kring); +#endif return rc; } @@ -1040,84 +1063,6 @@ _gnutls_openpgp_crt_to_gcert (gnutls_cert * gcert, gnutls_openpgp_crt_t cert) } -/** - * gnutls_certificate_set_openpgp_key - Used to set keys in a gnutls_certificate_credentials_t structure - * @res: is an #gnutls_certificate_credentials_t structure. - * @key: contains an openpgp public key - * @pkey: is an openpgp private key - * - * This function sets a certificate/private key pair in the - * gnutls_certificate_credentials_t structure. This function may be called - * more than once (in case multiple keys/certificates exist for the - * server). - * - **/ -int -gnutls_certificate_set_openpgp_key (gnutls_certificate_credentials_t - res, gnutls_openpgp_crt_t key, - gnutls_openpgp_privkey_t pkey) -{ - int ret; - - /* this should be first */ - - res->pkey = gnutls_realloc_fast (res->pkey, - (res->ncerts + 1) * - sizeof (gnutls_privkey)); - if (res->pkey == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - ret = _gnutls_openpgp_privkey_to_gkey (&res->pkey[res->ncerts], pkey); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - - res->cert_list = gnutls_realloc_fast (res->cert_list, - (1 + - res->ncerts) * - sizeof (gnutls_cert *)); - if (res->cert_list == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - res->cert_list_length = gnutls_realloc_fast (res->cert_list_length, - (1 + - res->ncerts) * sizeof (int)); - if (res->cert_list_length == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - res->cert_list[res->ncerts] = gnutls_calloc (1, sizeof (gnutls_cert)); - if (res->cert_list[res->ncerts] == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - res->cert_list_length[res->ncerts] = 1; - - ret = _gnutls_openpgp_crt_to_gcert (res->cert_list[res->ncerts], key); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - - res->ncerts++; - - /* FIXME: Check if the keys match. */ - - return 0; -} /** * gnutls_openpgp_privkey_sign_hash - This function will sign the given data using the private key params diff --git a/libextra/openpgp/compat.c b/libextra/openpgp/compat.c index 4f7e784108..02385db6f9 100644 --- a/libextra/openpgp/compat.c +++ b/libextra/openpgp/compat.c @@ -73,6 +73,7 @@ _gnutls_openpgp_verify_key (const gnutls_certificate_credentials_t cred, goto leave; } +#ifndef KEYRING_HACK if (cred->keyring != NULL) { ret = gnutls_openpgp_crt_verify_ring (key, cred->keyring, 0, &verify); @@ -82,6 +83,33 @@ _gnutls_openpgp_verify_key (const gnutls_certificate_credentials_t cred, goto leave; } } +#else + { + gnutls_openpgp_keyring_t kring; + + ret = gnutls_openpgp_keyring_init( &kring); + if ( ret < 0) { + gnutls_assert(); + return ret; + } + + ret = gnutls_openpgp_keyring_import( kring, &cred->keyring, cred->keyring_format); + if ( ret < 0) { + gnutls_assert(); + gnutls_openpgp_keyring_deinit( kring); + return ret; + } + + ret = gnutls_openpgp_crt_verify_ring (key, kring, 0, &verify); + if (ret < 0) + { + gnutls_assert (); + gnutls_openpgp_keyring_deinit( kring); + return ret; + } + gnutls_openpgp_keyring_deinit( kring); + } +#endif /* Now try the self signature. */ ret = gnutls_openpgp_crt_verify_self (key, 0, &verify_self); @@ -93,10 +121,15 @@ _gnutls_openpgp_verify_key (const gnutls_certificate_credentials_t cred, *status = verify_self | verify; +#ifndef KEYRING_HACK /* If we only checked the self signature. */ if (!cred->keyring) +#else + if (!cred->keyring.data || !cred->keyring.size) +#endif *status |= GNUTLS_CERT_SIGNER_NOT_FOUND; + ret = 0; leave: diff --git a/libextra/openpgp/gnutls_openpgp.h b/libextra/openpgp/gnutls_openpgp.h index 9c4124dbac..9894b084ba 100644 --- a/libextra/openpgp/gnutls_openpgp.h +++ b/libextra/openpgp/gnutls_openpgp.h @@ -33,23 +33,17 @@ typedef enum int gnutls_certificate_set_openpgp_key_file (gnutls_certificate_credentials_t res, const char *CERTFILE, - const char *KEYFILE); + const char *KEYFILE, gnutls_openpgp_crt_fmt_t); int gnutls_openpgp_count_key_names (const gnutls_datum_t * cert); -int gnutls_openpgp_add_keyring_mem (gnutls_datum_t * keyring, - const void *data, size_t len); - -int gnutls_openpgp_add_keyring_file (gnutls_datum_t * keyring, - const char *name); - int gnutls_certificate_set_openpgp_keyring_file - (gnutls_certificate_credentials_t c, const char *file); + (gnutls_certificate_credentials_t c, const char *file, gnutls_openpgp_crt_fmt_t); int gnutls_certificate_set_openpgp_keyring_mem (gnutls_certificate_credentials_t c, const opaque * data, - size_t dlen); + size_t dlen, gnutls_openpgp_crt_fmt_t); int gnutls_openpgp_get_key (gnutls_datum_t * key, gnutls_openpgp_keyring_t keyring, @@ -74,10 +68,6 @@ _gnutls_openpgp_request_key (gnutls_session_t, const gnutls_certificate_credentials_t cred, opaque * key_fpr, int key_fpr_size); -keybox_blob *kbx_read_blob (const gnutls_datum_t * keyring, size_t pos); -cdk_keydb_hd_t kbx_to_keydb (keybox_blob * blob); -void kbx_blob_release (keybox_blob * ctx); - int _gnutls_openpgp_verify_key (const gnutls_certificate_credentials_t, const gnutls_datum_t * cert_list, int cert_list_length, unsigned int *status); @@ -88,6 +78,21 @@ time_t _gnutls_openpgp_get_raw_key_creation_time (const gnutls_datum_t * time_t _gnutls_openpgp_get_raw_key_expiration_time (const gnutls_datum_t * cert); +int +gnutls_openpgp_privkey_init (gnutls_openpgp_privkey_t * key); + +int +gnutls_openpgp_privkey_init (gnutls_openpgp_privkey_t * key); + +void +gnutls_openpgp_privkey_deinit (gnutls_openpgp_privkey_t key); + +int +gnutls_openpgp_privkey_import (gnutls_openpgp_privkey_t key, + const gnutls_datum_t * data, + gnutls_openpgp_crt_fmt_t format, + const char *pass, unsigned int flags); + #endif /*GNUTLS_OPENPGP_H */ #endif /*ENABLE_OPENPGP */ diff --git a/libextra/openpgp/openpgp.h b/libextra/openpgp/openpgp.h index 84a1ad7625..ecdee694cc 100644 --- a/libextra/openpgp/openpgp.h +++ b/libextra/openpgp/openpgp.h @@ -5,13 +5,6 @@ # include <config.h> #endif -/* The format the OpenPGP key is stored in. */ -typedef enum gnutls_openpgp_crt_fmt_t -{ - GNUTLS_OPENPGP_FMT_RAW, - GNUTLS_OPENPGP_FMT_BASE64 -} gnutls_openpgp_crt_fmt_t; - #ifdef ENABLE_OPENPGP #include <opencdk.h> |