diff options
author | Nikos <nmav@crystal.(none)> | 2008-01-13 15:21:24 +0200 |
---|---|---|
committer | Nikos <nmav@crystal.(none)> | 2008-01-13 15:21:24 +0200 |
commit | a0b2d269d69a25b2611380c85377197d03092283 (patch) | |
tree | 0ae919209178f08a82a5b1818b6c71e9ff07598d | |
parent | a3e4759117cee5d756475215437a440dc12fcc6c (diff) | |
download | gnutls-a0b2d269d69a25b2611380c85377197d03092283.tar.gz |
merged the openpgp branch to head\!
-rw-r--r-- | README | 2 | ||||
-rw-r--r-- | configure.in | 66 | ||||
-rw-r--r-- | includes/gnutls/gnutls.h.in | 2 | ||||
-rw-r--r-- | includes/gnutls/openpgp.h | 51 | ||||
-rw-r--r-- | lib/Makefile.am | 27 | ||||
-rw-r--r-- | lib/auth_cert.c | 124 | ||||
-rw-r--r-- | lib/auth_cert.h | 2 | ||||
-rw-r--r-- | lib/gnutls_cert.c | 65 | ||||
-rw-r--r-- | lib/gnutls_cert.h | 4 | ||||
-rw-r--r-- | lib/gnutls_errors.c | 2 | ||||
-rw-r--r-- | lib/gnutls_extra_hooks.c | 76 | ||||
-rw-r--r-- | lib/gnutls_extra_hooks.h | 106 | ||||
-rw-r--r-- | lib/gnutls_openpgp.c (renamed from libextra/gnutls_openpgp.c) | 430 | ||||
-rw-r--r-- | lib/gnutls_state.c | 4 | ||||
-rw-r--r-- | lib/opencdk/Makefile.am (renamed from libextra/opencdk/Makefile.am) | 6 | ||||
-rw-r--r-- | lib/opencdk/README (renamed from libextra/opencdk/README) | 0 | ||||
-rw-r--r-- | lib/opencdk/armor.c (renamed from libextra/opencdk/armor.c) | 23 | ||||
-rw-r--r-- | lib/opencdk/context.h (renamed from libextra/opencdk/context.h) | 0 | ||||
-rw-r--r-- | lib/opencdk/dummy.c (renamed from libextra/opencdk/dummy.c) | 0 | ||||
-rw-r--r-- | lib/opencdk/filters.h (renamed from libextra/opencdk/filters.h) | 0 | ||||
-rw-r--r-- | lib/opencdk/hash.c | 81 | ||||
-rw-r--r-- | lib/opencdk/kbnode.c (renamed from libextra/opencdk/kbnode.c) | 84 | ||||
-rw-r--r-- | lib/opencdk/keydb.c (renamed from libextra/opencdk/keydb.c) | 37 | ||||
-rw-r--r-- | lib/opencdk/literal.c (renamed from libextra/opencdk/literal.c) | 21 | ||||
-rw-r--r-- | lib/opencdk/main.c (renamed from libextra/opencdk/main.c) | 23 | ||||
-rw-r--r-- | lib/opencdk/main.h (renamed from libextra/opencdk/main.h) | 0 | ||||
-rw-r--r-- | lib/opencdk/misc.c | 324 | ||||
-rw-r--r-- | lib/opencdk/new-packet.c (renamed from libextra/opencdk/new-packet.c) | 23 | ||||
-rw-r--r-- | lib/opencdk/opencdk.h (renamed from libextra/opencdk/opencdk.h) | 13 | ||||
-rw-r--r-- | lib/opencdk/packet.h (renamed from libextra/opencdk/packet.h) | 0 | ||||
-rw-r--r-- | lib/opencdk/pubkey.c (renamed from libextra/opencdk/pubkey.c) | 27 | ||||
-rw-r--r-- | lib/opencdk/read-packet.c (renamed from libextra/opencdk/read-packet.c) | 58 | ||||
-rw-r--r-- | lib/opencdk/seskey.c (renamed from libextra/opencdk/seskey.c) | 23 | ||||
-rw-r--r-- | lib/opencdk/sig-check.c (renamed from libextra/opencdk/sig-check.c) | 23 | ||||
-rw-r--r-- | lib/opencdk/stream.c (renamed from libextra/opencdk/stream.c) | 97 | ||||
-rw-r--r-- | lib/opencdk/stream.h (renamed from libextra/opencdk/stream.h) | 0 | ||||
-rw-r--r-- | lib/opencdk/types.h (renamed from libextra/opencdk/types.h) | 0 | ||||
-rw-r--r-- | lib/opencdk/verify.c (renamed from libextra/opencdk/verify.c) | 23 | ||||
-rw-r--r-- | lib/opencdk/write-packet.c (renamed from libextra/opencdk/write-packet.c) | 23 | ||||
-rw-r--r-- | lib/openpgp/Makefile.am | 50 | ||||
-rw-r--r-- | lib/openpgp/compat.c | 247 | ||||
-rw-r--r-- | lib/openpgp/extras.c | 172 | ||||
-rw-r--r-- | lib/openpgp/gnutls_openpgp.h | 99 | ||||
-rw-r--r-- | lib/openpgp/openpgp.h | 107 | ||||
-rw-r--r-- | lib/openpgp/output.c | 402 | ||||
-rw-r--r-- | lib/openpgp/pgp.c | 1079 | ||||
-rw-r--r-- | lib/openpgp/pgpverify.c | 144 | ||||
-rw-r--r-- | lib/openpgp/privkey.c | 575 | ||||
-rw-r--r-- | libextra/Makefile.am | 19 | ||||
-rw-r--r-- | libextra/gnutls_extra.c | 18 | ||||
-rw-r--r-- | libextra/opencdk/cipher.c | 529 | ||||
-rw-r--r-- | libextra/opencdk/compress.c | 239 | ||||
-rw-r--r-- | libextra/opencdk/misc.c | 564 | ||||
-rw-r--r-- | src/Makefile.am | 12 | ||||
-rw-r--r-- | src/certtool-gaa.c | 127 | ||||
-rw-r--r-- | src/certtool-gaa.h | 28 | ||||
-rw-r--r-- | src/certtool.c | 51 | ||||
-rw-r--r-- | src/certtool.gaa | 2 | ||||
-rw-r--r-- | src/cli.c | 8 | ||||
-rw-r--r-- | src/serv.c | 6 | ||||
-rw-r--r-- | src/tls_test.c | 6 |
61 files changed, 4107 insertions, 2247 deletions
@@ -67,7 +67,7 @@ see http://www.gnu.org/philosophy/why-not-lgpl.html. The GNU Lesser GPL license applies to the main gnutls library, while the gnutls-extra library is under the GPL. The gnutls-extra library contains -the code for the "OpenPGP key" support and the OpenSSL compatibility layer. +the code for "GnuTLS Inner Application" support and the OpenSSL compatibility layer. The gnutls library is located in the lib/ directory, while the gnutls-extra library is at libextra/. diff --git a/configure.in b/configure.in index d5bb2679b0..a201c829c6 100644 --- a/configure.in +++ b/configure.in @@ -198,7 +198,6 @@ AC_HEADER_STDC AC_CHECK_HEADERS(strings.h alloca.h) AC_CHECK_HEADERS(errno.h) AC_CHECK_HEADERS(math.h limits.h float.h stdarg.h ctype.h) -dnl opencdk AC_CHECK_HEADERS(netdb.h) AC_CHECK_FUNCS(umask vasprintf isascii fork,,) AC_FUNC_ALLOCA @@ -488,35 +487,38 @@ AM_CONDITIONAL(ENABLE_OPENPGP, test "$ac_enable_openpgp" = "yes") dnl Test whether to use the included opencdk library dnl -if test x$ac_enable_openpgp = xyes; then - AC_ARG_WITH(included-opencdk, - AS_HELP_STRING([--with-included-opencdk], [use the included opencdk]), - ac_enable_included_opencdk=$withval, - ac_enable_included_opencdk=no) - if test x$ac_enable_included_opencdk = xno;then - AC_LIB_HAVE_LINKFLAGS(opencdk,, [ -#include <opencdk.h>], [ -#if OPENCDK_VERSION_MINOR < 6 || OPENCDK_VERSION_PATCH < 5 -# error "OpenCDK 0.6.5 is required" -#else -cdk_check_version( NULL); -#endif -]) - if test "$ac_cv_libopencdk" != yes; then - ac_enable_included_opencdk=yes - AC_MSG_WARN([[ -*** -*** libopencdk was not found. You may want to get it from -*** ftp://ftp.gnutls.org/pub/gnutls/opencdk/ -*** -*** Will use the included opencdk. -*** -]]) - fi - AC_MSG_CHECKING([whether to use the included opencdk]) - AC_MSG_RESULT($ac_enable_included_opencdk) - fi -fi +dnl We no longer test for it. We use the LGPL parts of this library internally +dnl if test x$ac_enable_openpgp = xyes; then +dnl AC_ARG_WITH(included-opencdk, +dnl AS_HELP_STRING([--with-included-opencdk], [use the included opencdk]), +dnl ac_enable_included_opencdk=$withval, +dnl ac_enable_included_opencdk=no) +dnl if test x$ac_enable_included_opencdk = xno;then +dnl AC_LIB_HAVE_LINKFLAGS(opencdk,, [ +dnl #include <opencdk.h>], [ +dnl #if OPENCDK_VERSION_MINOR < 6 || OPENCDK_VERSION_PATCH < 5 +dnl # error "OpenCDK 0.6.5 is required" +dnl #else +dnl cdk_check_version( NULL); +dnl #endif +dnl ]) +dnl if test "$ac_cv_libopencdk" != yes; then +dnl ac_enable_included_opencdk=yes +dnl AC_MSG_WARN([[ +dnl *** +dnl *** libopencdk was not found. You may want to get it from +dnl *** ftp://ftp.gnutls.org/pub/gnutls/opencdk/ +dnl *** +dnl *** Will use the included opencdk. +dnl *** +dnl ]]) +dnl fi +dnl AC_MSG_CHECKING([whether to use the included opencdk]) +dnl AC_MSG_RESULT($ac_enable_included_opencdk) +dnl fi +dnl fi + +ac_enable_included_opencdk=yes AM_CONDITIONAL(ENABLE_INCLUDED_OPENCDK, test "$ac_enable_included_opencdk" = "yes") @@ -717,8 +719,8 @@ AC_CONFIG_FILES([Makefile po/Makefile.in \ tests/hostname-check/Makefile \ includes/Makefile includes/gnutls/gnutls.h \ lib/Makefile lib/minitasn1/Makefile lib/x509/Makefile \ - libextra/Makefile libextra/openpgp/Makefile libextra/opencdk/Makefile \ - tests/openpgp/Makefile \ + libextra/Makefile lib/openpgp/Makefile lib/opencdk/Makefile \ + libextra/minilzo/Makefile tests/openpgp/Makefile \ src/Makefile \ src/cfg/Makefile src/cfg/platon/Makefile src/cfg/platon/str/Makefile \ lib/libgnutls-config libextra/libgnutls-extra-config \ diff --git a/includes/gnutls/gnutls.h.in b/includes/gnutls/gnutls.h.in index c043c6fd94..11d1526ea2 100644 --- a/includes/gnutls/gnutls.h.in +++ b/includes/gnutls/gnutls.h.in @@ -1275,6 +1275,8 @@ extern "C" #define GNUTLS_E_RANDOM_FAILED -206 #define GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR -207 +#define GNUTLS_E_OPENPGP_SUBKEY_ERROR -208 + #define GNUTLS_E_UNIMPLEMENTED_FEATURE -1250 diff --git a/includes/gnutls/openpgp.h b/includes/gnutls/openpgp.h index fae404c8a8..850dfa08c5 100644 --- a/includes/gnutls/openpgp.h +++ b/includes/gnutls/openpgp.h @@ -37,6 +37,11 @@ extern "C" #include <gnutls/gnutls.h> #include <gnutls/extra.h> + typedef struct + { + unsigned char keyid[8]; + } gnutls_openpgp_keyid_t; + /* gnutls_openpgp_cert_t should be defined in gnutls.h */ @@ -53,6 +58,10 @@ extern "C" void *output_data, size_t * output_data_size); + int gnutls_openpgp_crt_print (gnutls_openpgp_crt_t cert, + gnutls_certificate_print_formats_t format, + gnutls_datum_t *out); + /* The key_usage flags are defined in gnutls.h. They are * the GNUTLS_KEY_* definitions. */ @@ -74,11 +83,24 @@ extern "C" time_t gnutls_openpgp_crt_get_expiration_time (gnutls_openpgp_crt_t key); int gnutls_openpgp_crt_get_id (gnutls_openpgp_crt_t key, - unsigned char keyid[8]); + gnutls_openpgp_keyid_t* keyid); int gnutls_openpgp_crt_check_hostname (gnutls_openpgp_crt_t key, const char *hostname); + int gnutls_openpgp_crt_get_revoked_status (gnutls_openpgp_crt_t key); + + int gnutls_openpgp_crt_get_subkey_count (gnutls_openpgp_crt_t key); + int gnutls_openpgp_crt_get_subkey_idx (gnutls_openpgp_crt_t key, gnutls_openpgp_keyid_t keyid); + int gnutls_openpgp_crt_get_subkey_revoked_status (gnutls_openpgp_crt_t key, unsigned int idx); + gnutls_pk_algorithm_t gnutls_openpgp_crt_get_subkey_pk_algorithm (gnutls_openpgp_crt_t key, + unsigned int idx, unsigned int *bits); + time_t gnutls_openpgp_crt_get_subkey_creation_time (gnutls_openpgp_crt_t key, unsigned int idx); + time_t gnutls_openpgp_crt_get_subkey_expiration_time (gnutls_openpgp_crt_t key, unsigned int idx); + int gnutls_openpgp_crt_get_subkey_id (gnutls_openpgp_crt_t key, unsigned int idx, gnutls_openpgp_keyid_t* keyid); + int gnutls_openpgp_crt_get_subkey_usage (gnutls_openpgp_crt_t key, unsigned int idx, + unsigned int *key_usage); + /* privkey stuff. */ int gnutls_openpgp_privkey_init (gnutls_openpgp_privkey_t * key); @@ -91,14 +113,33 @@ extern "C" gnutls_openpgp_crt_fmt_t format, const char *pass, unsigned int flags); int gnutls_openpgp_privkey_sign_hash (gnutls_openpgp_privkey_t key, - const gnutls_datum_t * hash, - gnutls_datum_t * signature); + gnutls_openpgp_keyid_t subkeyid, + const gnutls_datum_t * hash, + gnutls_datum_t * signature); + int gnutls_openpgp_privkey_get_fingerprint (gnutls_openpgp_privkey_t key, + void *fpr, size_t * fprlen); + int gnutls_openpgp_privkey_get_key_id (gnutls_openpgp_privkey_t key, gnutls_openpgp_keyid_t* keyid); + int gnutls_openpgp_privkey_get_subkey_count (gnutls_openpgp_privkey_t key); + int gnutls_openpgp_privkey_get_subkey_idx (gnutls_openpgp_privkey_t key, gnutls_openpgp_keyid_t keyid); + + int gnutls_openpgp_privkey_get_subkey_revoked_status (gnutls_openpgp_privkey_t key, unsigned int idx); + + int gnutls_openpgp_privkey_get_revoked_status (gnutls_openpgp_privkey_t key); + + gnutls_pk_algorithm_t gnutls_openpgp_privkey_get_subkey_pk_algorithm (gnutls_openpgp_privkey_t key, + unsigned int idx, unsigned int *bits); + + time_t gnutls_openpgp_privkey_get_subkey_expiration_time (gnutls_openpgp_privkey_t key, unsigned int idx); + + int gnutls_openpgp_privkey_get_subkey_id (gnutls_openpgp_privkey_t key, unsigned int idx, gnutls_openpgp_keyid_t* keyid); + + time_t gnutls_openpgp_privkey_get_subkey_creation_time (gnutls_openpgp_privkey_t key, unsigned int idx); /* Keyring stuff. */ struct gnutls_openpgp_keyring_int; /* object to hold (parsed) openpgp keyrings */ typedef struct gnutls_openpgp_keyring_int *gnutls_openpgp_keyring_t; - + int gnutls_openpgp_keyring_init (gnutls_openpgp_keyring_t * keyring); void gnutls_openpgp_keyring_deinit (gnutls_openpgp_keyring_t keyring); @@ -107,7 +148,7 @@ extern "C" gnutls_openpgp_crt_fmt_t format); int gnutls_openpgp_keyring_check_id (gnutls_openpgp_keyring_t ring, - const unsigned char keyid[8], + gnutls_openpgp_keyid_t keyid, unsigned int flags); diff --git a/lib/Makefile.am b/lib/Makefile.am index 62351ecadb..28a3d3dd4d 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -25,16 +25,25 @@ if ENABLE_MINITASN1 SUBDIRS += minitasn1 endif + localedir = $(datadir)/locale AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" \ -I$(top_srcdir)/lgl -I$(top_builddir)/lgl \ -I$(top_srcdir)/includes -I../includes \ -I$(srcdir)/x509 \ - -I$(top_srcdir)/libextra -I$(top_srcdir)/libextra/openpgp/ \ - -I$(top_srcdir)/libextra/opencdk \ + -I$(top_srcdir)/libextra -I$(top_srcdir)/lib/openpgp/ \ + -I$(top_srcdir)/lib/opencdk \ $(LIBOPENCDK_CFLAGS) $(LIBGCRYPT_CFLAGS) +if ENABLE_OPENPGP +if ENABLE_INCLUDED_OPENCDK +SUBDIRS += opencdk +AM_CPPFLAGS += -I$(srcdir)/opencdk +endif +SUBDIRS += openpgp +endif + if ENABLE_MINITASN1 AM_CPPFLAGS += -I$(srcdir)/minitasn1 else @@ -75,7 +84,7 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c gnutls_cipher.c \ ext_max_record.c gnutls_alert.c gnutls_str.c gnutls_state.c \ gnutls_x509.c ext_cert_type.c gnutls_rsa_export.c \ auth_rsa_export.c ext_server_name.c auth_dh_common.c \ - gnutls_helper.c ext_inner_application.c gnutls_extra_hooks.c \ + gnutls_helper.c ext_inner_application.c \ gnutls_supplemental.c if ENABLE_OPRFI @@ -96,7 +105,7 @@ HFILES = debug.h gnutls_compress.h defines.h gnutls_cipher.h \ gnutls_rsa_export.h ext_server_name.h auth_dh_common.h \ ext_srp.h gnutls_srp.h auth_srp.h auth_srp_passwd.h \ gnutls_helper.h auth_psk.h auth_psk_passwd.h \ - ext_inner_application.h gnutls_extra_hooks.h \ + ext_inner_application.h \ gnutls_supplemental.h ext_oprfi.h # Separate so we can create the documentation @@ -110,6 +119,16 @@ libgnutls_la_LDFLAGS = -no-undefined \ libgnutls_la_LIBADD = ../lgl/liblgnu.la x509/libgnutls_x509.la \ @LTLIBZ@ $(LIBGCRYPT_LIBS) @LTLIBINTL@ +if ENABLE_OPENPGP +libgnutls_la_SOURCES += gnutls_openpgp.c +libgnutls_la_LIBADD += openpgp/libgnutls_openpgp.la +if ENABLE_INCLUDED_OPENCDK +libgnutls_la_LIBADD += opencdk/libminiopencdk.la +else +libgnutls_la_LDFLAGS += $(LTLIBOPENCDK) +endif +endif + if HAVE_LD_VERSION_SCRIPT libgnutls_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libgnutls.vers endif diff --git a/lib/auth_cert.c b/lib/auth_cert.c index c9cd8d4ff9..3f97b1e50f 100644 --- a/lib/auth_cert.c +++ b/lib/auth_cert.c @@ -43,15 +43,22 @@ #include <gnutls_state.h> #include <gnutls_pk.h> #include <gnutls_x509.h> -#include <gnutls_extra_hooks.h> #include "debug.h" +#ifdef ENABLE_OPENPGP +# include "openpgp/gnutls_openpgp.h" + +static gnutls_privkey * +alloc_and_load_pgp_key (const gnutls_openpgp_privkey_t key, gnutls_openpgp_keyid_t keyid); +static gnutls_cert * +alloc_and_load_pgp_certs (gnutls_openpgp_crt_t cert, gnutls_openpgp_keyid_t* keyid); + +#endif + static gnutls_cert *alloc_and_load_x509_certs (gnutls_x509_crt_t * certs, unsigned); static gnutls_privkey *alloc_and_load_x509_key (gnutls_x509_privkey_t key); -static gnutls_cert *alloc_and_load_pgp_certs (gnutls_openpgp_crt_t cert); -static gnutls_privkey *alloc_and_load_pgp_key (const gnutls_openpgp_privkey_t - key); + /* Copies data from a internal certificate struct (gnutls_cert) to @@ -255,6 +262,7 @@ _find_x509_cert (const gnutls_certificate_credentials_t cred, } +#ifdef ENABLE_OPENPGP /* Locates the most appropriate openpgp cert */ static int @@ -289,6 +297,7 @@ _find_openpgp_cert (const gnutls_certificate_credentials_t cred, return 0; } +#endif /* Returns the number of issuers in the server's * certificate request packet. @@ -438,8 +447,16 @@ call_get_cert_callback (gnutls_session_t session, if (type == GNUTLS_CRT_X509) { local_certs = alloc_and_load_x509_certs (st.cert.x509, st.ncerts); - if (local_certs != NULL) - local_key = alloc_and_load_x509_key (st.key.x509); + if (local_certs != NULL) + { + local_key = alloc_and_load_x509_key (st.key.x509); + if (local_key == NULL) + { + gnutls_assert(); + ret = GNUTLS_E_INTERNAL_ERROR; + goto cleanup; + } + } } else @@ -451,10 +468,23 @@ call_get_cert_callback (gnutls_session_t session, goto cleanup; } - local_certs = alloc_and_load_pgp_certs (st.cert.pgp); - if (local_certs != NULL) - local_key = alloc_and_load_pgp_key (st.key.pgp); - +#ifdef ENABLE_OPENPGP + { + gnutls_openpgp_keyid_t selected_keyid; + + local_certs = alloc_and_load_pgp_certs (st.cert.pgp, &selected_keyid); + if (local_certs != NULL) + { + local_key = alloc_and_load_pgp_key (st.key.pgp, selected_keyid); + if (local_key == NULL) + { + gnutls_assert(); + ret = GNUTLS_E_INTERNAL_ERROR; + goto cleanup; + } + } + } +#endif } _gnutls_selected_certs_set (session, local_certs, @@ -479,18 +509,13 @@ cleanup: } else { +#ifdef ENABLE_OPENPGP if (st.deinit_all) { - if (_E_gnutls_openpgp_crt_deinit == NULL || - _E_gnutls_openpgp_privkey_deinit == NULL) - { - gnutls_assert (); - return GNUTLS_E_INIT_LIBEXTRA; - } - - _E_gnutls_openpgp_crt_deinit (st.cert.pgp); - _E_gnutls_openpgp_privkey_deinit (st.key.pgp); + gnutls_openpgp_crt_deinit (st.cert.pgp); + gnutls_openpgp_privkey_deinit (st.key.pgp); } +#endif } return ret; @@ -578,9 +603,10 @@ _select_client_cert (gnutls_session_t session, _find_x509_cert (cred, _data, _data_size, pk_algos, pk_algos_length, &indx); +#ifdef ENABLE_OPENPGP if (session->security_parameters.cert_type == GNUTLS_CRT_OPENPGP) result = _find_openpgp_cert (cred, pk_algos, pk_algos_length, &indx); - +#endif if (result < 0) { @@ -670,6 +696,7 @@ _gnutls_gen_x509_crt (gnutls_session_t session, opaque ** data) enum PGPKeyDescriptorType { PGP_KEY_FINGERPRINT, PGP_KEY }; +#ifdef ENABLE_OPENPGP int _gnutls_gen_openpgp_certificate (gnutls_session_t session, opaque ** data) { @@ -767,14 +794,8 @@ _gnutls_gen_openpgp_certificate_fpr (gnutls_session_t session, opaque ** data) fpr_size = 20; - if (_E_gnutls_openpgp_fingerprint == NULL) - { - gnutls_assert (); - return GNUTLS_E_INIT_LIBEXTRA; - } - if ((ret = - _E_gnutls_openpgp_fingerprint (&apr_cert_list[0].raw, pdata, + _gnutls_openpgp_fingerprint (&apr_cert_list[0].raw, pdata, &fpr_size)) < 0) { gnutls_assert (); @@ -783,7 +804,7 @@ _gnutls_gen_openpgp_certificate_fpr (gnutls_session_t session, opaque ** data) return packet_size; } - +#endif int @@ -791,12 +812,13 @@ _gnutls_gen_cert_client_certificate (gnutls_session_t session, opaque ** data) { switch (session->security_parameters.cert_type) { +#ifdef ENABLE_OPENPGP case GNUTLS_CRT_OPENPGP: if (_gnutls_openpgp_send_fingerprint (session) == 0) return _gnutls_gen_openpgp_certificate (session, data); else return _gnutls_gen_openpgp_certificate_fpr (session, data); - +#endif case GNUTLS_CRT_X509: return _gnutls_gen_x509_crt (session, data); @@ -811,8 +833,10 @@ _gnutls_gen_cert_server_certificate (gnutls_session_t session, opaque ** data) { switch (session->security_parameters.cert_type) { +#ifdef ENABLE_OPENPGP case GNUTLS_CRT_OPENPGP: return _gnutls_gen_openpgp_certificate (session, data); +#endif case GNUTLS_CRT_X509: return _gnutls_gen_x509_crt (session, data); default: @@ -967,6 +991,7 @@ cleanup: } #define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) _gnutls_gcert_deinit(&peer_certificate_list[x]) +#ifdef ENABLE_OPENPGP int _gnutls_proc_openpgp_server_certificate (gnutls_session_t session, opaque * data, size_t data_size) @@ -1038,13 +1063,8 @@ _gnutls_proc_openpgp_server_certificate (gnutls_session_t session, /* request the actual key from our database, or * a key server or anything. */ - if (_E_gnutls_openpgp_request_key == NULL) - { - gnutls_assert (); - return GNUTLS_E_INIT_LIBEXTRA; - } if ((ret = - _E_gnutls_openpgp_request_key (session, &akey, cred, p, 20)) < 0) + _gnutls_openpgp_request_key (session, &akey, cred, p, 20)) < 0) { gnutls_assert (); return ret; @@ -1103,15 +1123,8 @@ _gnutls_proc_openpgp_server_certificate (gnutls_session_t session, memset (peer_certificate_list, 0, sizeof (gnutls_cert) * peer_certificate_list_size); - if (_E_gnutls_openpgp_raw_key_to_gcert == NULL) - { - gnutls_assert (); - ret = GNUTLS_E_INIT_LIBEXTRA; - goto cleanup; - } - if ((ret = - _E_gnutls_openpgp_raw_key_to_gcert (&peer_certificate_list[0], + _gnutls_openpgp_raw_crt_to_gcert (&peer_certificate_list[0], &tmp)) < 0) { gnutls_assert (); @@ -1145,6 +1158,7 @@ cleanup: return ret; } +#endif int _gnutls_proc_cert_server_certificate (gnutls_session_t session, @@ -1152,9 +1166,11 @@ _gnutls_proc_cert_server_certificate (gnutls_session_t session, { switch (session->security_parameters.cert_type) { +#ifdef ENABLE_OPENPGP case GNUTLS_CRT_OPENPGP: return _gnutls_proc_openpgp_server_certificate (session, data, data_size); +#endif case GNUTLS_CRT_X509: return _gnutls_proc_x509_server_certificate (session, data, data_size); default: @@ -1582,8 +1598,9 @@ alloc_and_load_x509_key (gnutls_x509_privkey_t key) /* converts the given pgp certificate to gnutls_cert* and allocates * space for them. */ +#ifdef ENABLE_OPENPGP static gnutls_cert * -alloc_and_load_pgp_certs (gnutls_openpgp_crt_t cert) +alloc_and_load_pgp_certs (gnutls_openpgp_crt_t cert, gnutls_openpgp_keyid_t* keyid) { gnutls_cert *local_certs; int ret = 0; @@ -1598,13 +1615,14 @@ alloc_and_load_pgp_certs (gnutls_openpgp_crt_t cert) return NULL; } - if (_E_gnutls_openpgp_crt_to_gcert == NULL) + ret = _gnutls_openpgp_find_valid_subkey( cert, keyid); + if (ret < 0) { - gnutls_assert (); + gnutls_assert(); return NULL; } - ret = _E_gnutls_openpgp_crt_to_gcert (local_certs, cert); + ret = _gnutls_openpgp_crt_to_gcert (local_certs, cert, *keyid); if (ret < 0) { gnutls_assert (); @@ -1626,7 +1644,7 @@ alloc_and_load_pgp_certs (gnutls_openpgp_crt_t cert) * space for it. */ static gnutls_privkey * -alloc_and_load_pgp_key (const gnutls_openpgp_privkey_t key) +alloc_and_load_pgp_key (const gnutls_openpgp_privkey_t key, gnutls_openpgp_keyid_t keyid) { gnutls_privkey *local_key; int ret = 0; @@ -1641,13 +1659,7 @@ alloc_and_load_pgp_key (const gnutls_openpgp_privkey_t key) return NULL; } - if (_E_gnutls_openpgp_privkey_to_gkey == NULL) - { - gnutls_assert (); - return NULL; - } - - ret = _E_gnutls_openpgp_privkey_to_gkey (local_key, key); + ret = _gnutls_openpgp_privkey_to_gkey (local_key, key, keyid); if (ret < 0) { gnutls_assert (); @@ -1656,7 +1668,7 @@ alloc_and_load_pgp_key (const gnutls_openpgp_privkey_t key) return local_key; } - +#endif void _gnutls_selected_certs_deinit (gnutls_session_t session) diff --git a/lib/auth_cert.h b/lib/auth_cert.h index e59e094b9d..d2db7ab158 100644 --- a/lib/auth_cert.h +++ b/lib/auth_cert.h @@ -28,7 +28,7 @@ # include "gnutls_auth.h" # include "auth_dh_common.h" # include "x509/x509.h" -# include "../libextra/openpgp/openpgp.h" +# include "openpgp/openpgp.h" /* This structure may be complex, but it's the only way to * support a server that has multiple certificates diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c index f33b538802..669deb33cc 100644 --- a/lib/gnutls_cert.c +++ b/lib/gnutls_cert.c @@ -40,9 +40,11 @@ #include <gnutls_state.h> #include <gnutls_auth_int.h> #include <gnutls_x509.h> -#include <gnutls_extra_hooks.h> #include "x509/x509.h" #include "x509/mpi.h" +#ifdef ENABLE_OPENPGP +# include "openpgp/gnutls_openpgp.h" +#endif /** * gnutls_certificate_free_keys - Used to free all the keys from a gnutls_certificate_credentials_t structure @@ -191,12 +193,14 @@ gnutls_certificate_free_credentials (gnutls_certificate_credentials_t sc) gnutls_certificate_free_crls (sc); #endif +#ifdef ENABLE_OPENPGP #ifndef KEYRING_HACK if (_E_gnutls_openpgp_keyring_deinit) _E_gnutls_openpgp_keyring_deinit( sc->keyring); #else _gnutls_free_datum( &sc->keyring); #endif +#endif gnutls_free (sc); } @@ -436,6 +440,7 @@ _gnutls_x509_get_raw_crt_expiration_time (const gnutls_datum_t * cert) return result; } +#ifdef ENABLE_OPENPGP /*- * _gnutls_openpgp_crt_verify_peers - This function returns the peer's certificate status * @session: is a gnutls session @@ -485,13 +490,8 @@ _gnutls_openpgp_crt_verify_peers (gnutls_session_t session, /* Verify certificate */ - if (_E_gnutls_openpgp_verify_key == NULL) - { - gnutls_assert (); - return GNUTLS_E_INIT_LIBEXTRA; - } ret = - _E_gnutls_openpgp_verify_key (cred, &info->raw_certificate_list[0], + _gnutls_openpgp_verify_key (cred, &info->raw_certificate_list[0], peer_certificate_list_size, status); if (ret < 0) @@ -502,7 +502,7 @@ _gnutls_openpgp_crt_verify_peers (gnutls_session_t session, return 0; } - +#endif /** * gnutls_certificate_verify_peers2 - This function returns the peer's certificate verification status @@ -551,8 +551,10 @@ gnutls_certificate_verify_peers2 (gnutls_session_t session, { case GNUTLS_CRT_X509: return _gnutls_x509_cert_verify_peers (session, status); +#ifdef ENABLE_OPENPGP case GNUTLS_CRT_OPENPGP: return _gnutls_openpgp_crt_verify_peers (session, status); +#endif default: return GNUTLS_E_INVALID_REQUEST; } @@ -625,12 +627,12 @@ gnutls_certificate_expiration_time_peers (gnutls_session_t session) return _gnutls_x509_get_raw_crt_expiration_time (&info-> raw_certificate_list [0]); +#ifdef ENABLE_OPENPGP case GNUTLS_CRT_OPENPGP: - if (_E_gnutls_openpgp_get_raw_key_expiration_time == NULL) - return (time_t) - 1; - return _E_gnutls_openpgp_get_raw_key_expiration_time (&info-> + return _gnutls_openpgp_get_raw_key_expiration_time (&info-> raw_certificate_list [0]); +#endif default: return (time_t) - 1; } @@ -670,12 +672,12 @@ gnutls_certificate_activation_time_peers (gnutls_session_t session) return _gnutls_x509_get_raw_crt_activation_time (&info-> raw_certificate_list [0]); +#ifdef ENABLE_OPENPGP case GNUTLS_CRT_OPENPGP: - if (_E_gnutls_openpgp_get_raw_key_creation_time == NULL) - return (time_t) - 1; - return _E_gnutls_openpgp_get_raw_key_creation_time (&info-> + return _gnutls_openpgp_get_raw_key_creation_time (&info-> raw_certificate_list [0]); +#endif default: return (time_t) - 1; } @@ -691,45 +693,16 @@ _gnutls_raw_cert_to_gcert (gnutls_cert * gcert, { case GNUTLS_CRT_X509: return _gnutls_x509_raw_cert_to_gcert (gcert, raw_cert, flags); +#ifdef ENABLE_OPENPGP case GNUTLS_CRT_OPENPGP: - if (_E_gnutls_openpgp_raw_key_to_gcert == NULL) - { - gnutls_assert (); - return GNUTLS_E_INIT_LIBEXTRA; - } - return _E_gnutls_openpgp_raw_key_to_gcert (gcert, raw_cert); - default: - gnutls_assert (); - return GNUTLS_E_INTERNAL_ERROR; - } -} - -int -_gnutls_raw_privkey_to_gkey (gnutls_privkey * key, - gnutls_certificate_type_t type, - const gnutls_datum_t * raw_key, - int key_enc /* DER or PEM */ ) -{ - switch (type) - { - case GNUTLS_CRT_X509: - return _gnutls_x509_raw_privkey_to_gkey (key, raw_key, key_enc); - case GNUTLS_CRT_OPENPGP: - if (_E_gnutls_openpgp_raw_privkey_to_gkey == NULL) - { - gnutls_assert (); - return GNUTLS_E_INIT_LIBEXTRA; - } - return _E_gnutls_openpgp_raw_privkey_to_gkey (key, raw_key, - (gnutls_openpgp_crt_fmt_t) - key_enc); + return _gnutls_openpgp_raw_crt_to_gcert (gcert, raw_cert); +#endif default: gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } } - /* This function will convert a der certificate to a format * (structure) that gnutls can understand and use. Actually the * important thing on this function is that it extracts the diff --git a/lib/gnutls_cert.h b/lib/gnutls_cert.h index 6ce0847368..3101e6825c 100644 --- a/lib/gnutls_cert.h +++ b/lib/gnutls_cert.h @@ -124,9 +124,5 @@ int _gnutls_raw_cert_to_gcert (gnutls_cert * gcert, gnutls_certificate_type_t type, const gnutls_datum_t * raw_cert, int flags /* OR of ConvFlags */ ); -int _gnutls_raw_privkey_to_gkey (gnutls_privkey * key, - gnutls_certificate_type_t type, - const gnutls_datum_t * raw_key, - int key_enc /* DER or PEM */ ); #endif diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c index d7635f198d..465806f8f0 100644 --- a/lib/gnutls_errors.c +++ b/lib/gnutls_errors.c @@ -208,6 +208,8 @@ static const gnutls_error_entry error_algorithms[] = { GNUTLS_E_NO_CIPHER_SUITES, 1), ERROR_ENTRY (N_("Could not get OpenPGP key."), GNUTLS_E_OPENPGP_GETKEY_FAILED, 1), + ERROR_ENTRY (N_("Could not find OpenPGP subkey."), + GNUTLS_E_OPENPGP_SUBKEY_ERROR, 1), ERROR_ENTRY (N_("The SRP username supplied is illegal."), GNUTLS_E_ILLEGAL_SRP_USERNAME, 1), diff --git a/lib/gnutls_extra_hooks.c b/lib/gnutls_extra_hooks.c deleted file mode 100644 index eedf902860..0000000000 --- a/lib/gnutls_extra_hooks.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2007 Free Software Foundation - * - * Author: Simon Josefsson - * - * This file is part of GNUTLS. - * - * The GNUTLS library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA - * - */ - -#include <gnutls_int.h> -#include <gnutls_extra_hooks.h> - -/* Variables used by libgnutls, set by - _gnutls_add_openpgp_functions(), typically invoked by - libgnutls_extra. */ -_gnutls_openpgp_verify_key_func _E_gnutls_openpgp_verify_key = NULL; -_gnutls_openpgp_crt_creation_time_func -_E_gnutls_openpgp_get_raw_key_creation_time = NULL; -_gnutls_openpgp_crt_expiration_time_func -_E_gnutls_openpgp_get_raw_key_expiration_time = NULL; -_gnutls_openpgp_fingerprint_func _E_gnutls_openpgp_fingerprint = NULL; -_gnutls_openpgp_crt_request_func _E_gnutls_openpgp_request_key = NULL; -_gnutls_openpgp_raw_key_to_gcert_func _E_gnutls_openpgp_raw_key_to_gcert = NULL; -_gnutls_openpgp_raw_privkey_to_gkey_func _E_gnutls_openpgp_raw_privkey_to_gkey = NULL; -_gnutls_openpgp_crt_to_gcert_func _E_gnutls_openpgp_crt_to_gcert = NULL; -_gnutls_openpgp_privkey_to_gkey_func _E_gnutls_openpgp_privkey_to_gkey = NULL; -_gnutls_openpgp_crt_deinit_func _E_gnutls_openpgp_crt_deinit = NULL; -_gnutls_openpgp_keyring_deinit_func _E_gnutls_openpgp_keyring_deinit = NULL; -_gnutls_openpgp_privkey_deinit_func _E_gnutls_openpgp_privkey_deinit = NULL; - -/* Called by libgnutls_extra to set the OpenPGP functions that are - needed by GnuTLS. */ -extern void -_gnutls_add_openpgp_functions -(_gnutls_openpgp_verify_key_func verify_key, - _gnutls_openpgp_crt_creation_time_func key_creation_time, - _gnutls_openpgp_crt_expiration_time_func key_expiration_time, - _gnutls_openpgp_fingerprint_func fingerprint, - _gnutls_openpgp_crt_request_func request_key, - _gnutls_openpgp_raw_key_to_gcert_func raw_key_to_gcert, - _gnutls_openpgp_raw_privkey_to_gkey_func raw_privkey_to_gkey, - _gnutls_openpgp_crt_to_gcert_func key_to_gcert, - _gnutls_openpgp_privkey_to_gkey_func privkey_to_gkey, - _gnutls_openpgp_crt_deinit_func key_deinit, - _gnutls_openpgp_keyring_deinit_func keyring_deinit, - _gnutls_openpgp_privkey_deinit_func privkey_deinit) -{ - _E_gnutls_openpgp_verify_key = verify_key; - _E_gnutls_openpgp_get_raw_key_creation_time = key_creation_time; - _E_gnutls_openpgp_get_raw_key_expiration_time = key_expiration_time; - _E_gnutls_openpgp_fingerprint = fingerprint; - _E_gnutls_openpgp_request_key = request_key; - _E_gnutls_openpgp_raw_key_to_gcert = raw_key_to_gcert; - _E_gnutls_openpgp_raw_privkey_to_gkey = raw_privkey_to_gkey; - _E_gnutls_openpgp_crt_to_gcert = key_to_gcert; - _E_gnutls_openpgp_privkey_to_gkey = privkey_to_gkey; - _E_gnutls_openpgp_crt_deinit = key_deinit; - _E_gnutls_openpgp_keyring_deinit = keyring_deinit; - _E_gnutls_openpgp_privkey_deinit = privkey_deinit; - -} diff --git a/lib/gnutls_extra_hooks.h b/lib/gnutls_extra_hooks.h deleted file mode 100644 index ac55d06a76..0000000000 --- a/lib/gnutls_extra_hooks.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2007 Free Software Foundation - * - * Author: Simon Josefsson - * - * This file is part of GNUTLS. - * - * The GNUTLS library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA - * - */ - -/* This file is included by libgnutls-extra, and it will call the - _gnutls_add_openpgp_functions() function to register its OpenPGP - functions. */ - -#include <auth_cert.h> - -typedef int (*_gnutls_openpgp_verify_key_func) -(const gnutls_certificate_credentials_t, - const gnutls_datum_t *, int, - unsigned int *); - -typedef time_t (*_gnutls_openpgp_crt_creation_time_func) -(const gnutls_datum_t *); - -typedef time_t (*_gnutls_openpgp_crt_expiration_time_func) -(const gnutls_datum_t *); - -typedef int (*_gnutls_openpgp_crt_request_func) -(gnutls_session_t, gnutls_datum_t *, - const gnutls_certificate_credentials_t, - opaque *, int); - -typedef int (*_gnutls_openpgp_fingerprint_func) -(const gnutls_datum_t *, - unsigned char *, size_t *); - -typedef int (*_gnutls_openpgp_raw_key_to_gcert_func) -(gnutls_cert *, - const gnutls_datum_t *); -typedef int (*_gnutls_openpgp_raw_privkey_to_gkey_func) -(gnutls_privkey *, - const gnutls_datum_t *, - gnutls_openpgp_crt_fmt_t); - -typedef int (*_gnutls_openpgp_crt_to_gcert_func) -(gnutls_cert *, gnutls_openpgp_crt_t); - -typedef int (*_gnutls_openpgp_privkey_to_gkey_func) -(gnutls_privkey *, - gnutls_openpgp_privkey_t); - -typedef void (*_gnutls_openpgp_crt_deinit_func) -(gnutls_openpgp_crt_t); - -typedef void (*_gnutls_openpgp_keyring_deinit_func) -(gnutls_openpgp_keyring_t); - -typedef void (*_gnutls_openpgp_privkey_deinit_func) -(gnutls_openpgp_privkey_t); - -/* These are defined in libgnutls, but not exported from libgnutls, - and not intended to be used by libgnutls-extra or elsewhere. They - are declared here, because this file is included by auth_cert.c and - gnutls_cert.c too. */ -extern _gnutls_openpgp_verify_key_func _E_gnutls_openpgp_verify_key; -extern _gnutls_openpgp_crt_creation_time_func -_E_gnutls_openpgp_get_raw_key_creation_time; -extern _gnutls_openpgp_crt_expiration_time_func -_E_gnutls_openpgp_get_raw_key_expiration_time; -extern _gnutls_openpgp_fingerprint_func _E_gnutls_openpgp_fingerprint; -extern _gnutls_openpgp_crt_request_func _E_gnutls_openpgp_request_key; -extern _gnutls_openpgp_raw_key_to_gcert_func _E_gnutls_openpgp_raw_key_to_gcert; -extern _gnutls_openpgp_raw_privkey_to_gkey_func _E_gnutls_openpgp_raw_privkey_to_gkey; -extern _gnutls_openpgp_crt_to_gcert_func _E_gnutls_openpgp_crt_to_gcert; -extern _gnutls_openpgp_privkey_to_gkey_func _E_gnutls_openpgp_privkey_to_gkey; -extern _gnutls_openpgp_crt_deinit_func _E_gnutls_openpgp_crt_deinit; -extern _gnutls_openpgp_keyring_deinit_func _E_gnutls_openpgp_keyring_deinit; -extern _gnutls_openpgp_privkey_deinit_func _E_gnutls_openpgp_privkey_deinit; - -extern void _gnutls_add_openpgp_functions -(_gnutls_openpgp_verify_key_func verify_key, - _gnutls_openpgp_crt_creation_time_func key_creation_time, - _gnutls_openpgp_crt_expiration_time_func key_expiration_time, - _gnutls_openpgp_fingerprint_func fingerprint, - _gnutls_openpgp_crt_request_func request_key, - _gnutls_openpgp_raw_key_to_gcert_func raw_key_to_gcert, - _gnutls_openpgp_raw_privkey_to_gkey_func raw_privkey_to_gkey, - _gnutls_openpgp_crt_to_gcert_func key_to_gcert, - _gnutls_openpgp_privkey_to_gkey_func privkey_to_gkey, - _gnutls_openpgp_crt_deinit_func key_deinit, - _gnutls_openpgp_keyring_deinit_func keyring_deinit, - _gnutls_openpgp_privkey_deinit_func privkey_deinit); diff --git a/libextra/gnutls_openpgp.c b/lib/gnutls_openpgp.c index 73f9aef08f..8e95b53806 100644 --- a/libextra/gnutls_openpgp.c +++ b/lib/gnutls_openpgp.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation * - * Author: Timo Schulz + * Author: Timo Schulz, Nikos Mavrogiannopoulos * * This file is part of GNUTLS-EXTRA. * @@ -22,6 +22,7 @@ #include "gnutls_int.h" #include "gnutls_errors.h" #include "gnutls_mpi.h" +#include "gnutls_num.h" #include "gnutls_cert.h" #include "gnutls_datum.h" #include "gnutls_global.h" @@ -34,8 +35,6 @@ #include <time.h> #include <sys/stat.h> -#define OPENPGP_NAME_SIZE 256 - #define datum_append(x, y, z) _gnutls_datum_append_m (x, y, z, gnutls_realloc) @@ -82,183 +81,53 @@ _gnutls_map_cdk_rc (int rc) } } - -static unsigned long -buftou32 (const uint8_t * buf) -{ - unsigned a; - a = buf[0] << 24; - a |= buf[1] << 16; - a |= buf[2] << 8; - a |= buf[3]; - return a; -} - -static int -openpgp_pk_to_gnutls_cert (gnutls_cert * cert, cdk_pkt_pubkey_t pk) +/* Finds a subkey to use for authentication + */ +int _gnutls_openpgp_find_valid_subkey( gnutls_openpgp_crt_t crt, gnutls_openpgp_keyid_t* keyid) { - uint8_t buf[512+2]; - size_t nbytes; - int algo, i; - int rc = 0; + int ret, subkeys, i; + unsigned int usage; - if (!cert || !pk) + subkeys = gnutls_openpgp_crt_get_subkey_count( crt); + if (subkeys <= 0) { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - /* GnuTLS OpenPGP does not support ELG keys */ - if (is_ELG (pk->pubkey_algo)) - return GNUTLS_E_UNWANTED_ALGORITHM; - - algo = is_DSA (pk->pubkey_algo) ? GNUTLS_PK_DSA : GNUTLS_PK_RSA; - cert->subject_pk_algorithm = algo; - cert->version = pk->version; - cert->cert_type = GNUTLS_CRT_OPENPGP; - - cert->key_usage = 0; - if (pk->pubkey_usage & CDK_KEY_USG_SIGN) - cert->key_usage = KEY_DIGITAL_SIGNATURE; - if (pk->pubkey_usage & CDK_KEY_USG_ENCR) - cert->key_usage = KEY_KEY_ENCIPHERMENT; - if (!cert->key_usage) /* Fallback code. */ - { - if (pk->pubkey_algo == GCRY_PK_DSA || pk->pubkey_algo == GCRY_PK_RSA_S) - cert->key_usage = KEY_DIGITAL_SIGNATURE; - else if (pk->pubkey_algo == GCRY_PK_RSA_E) - cert->key_usage = KEY_KEY_ENCIPHERMENT; - else if (pk->pubkey_algo == GCRY_PK_RSA) - cert->key_usage = KEY_DIGITAL_SIGNATURE | KEY_KEY_ENCIPHERMENT; - } - - cert->params_size = cdk_pk_get_npkey (pk->pubkey_algo); - for (i = 0; i < cert->params_size; i++) - { - nbytes = sizeof (buf) / sizeof (buf[0]); - cdk_pk_get_mpi (pk, i, buf, nbytes, &nbytes, NULL); - rc = _gnutls_mpi_scan_pgp (&cert->params[i], buf, &nbytes); - if (rc) - { - rc = GNUTLS_E_MPI_SCAN_FAILED; - break; - } + gnutls_assert(); + return GNUTLS_E_OPENPGP_SUBKEY_ERROR; } - if (rc) - release_mpi_array (cert->params, i - 1); - return rc; -} - -/*- - * _gnutls_openpgp_raw_privkey_to_gkey - Converts an OpenPGP secret key to GnuTLS - * @pkey: the GnuTLS private key context to store the key. - * @raw_key: the raw data which contains the whole key packets. - * @format: the format of the key packets. - * - * The RFC2440 (OpenPGP Message Format) data is converted into the - * GnuTLS specific data which is need to perform secret key operations. - * - * This function can read both BASE64 and RAW keys. - -*/ -int -_gnutls_openpgp_raw_privkey_to_gkey (gnutls_privkey * pkey, - const gnutls_datum_t * raw_key, - gnutls_openpgp_crt_fmt_t format) -{ - cdk_kbnode_t snode = NULL; - cdk_packet_t pkt; - cdk_stream_t out; - cdk_pkt_seckey_t sk = NULL; - int pke_algo, i, j; - size_t nbytes = 0; - uint8_t buf[512]; - int rc = 0; - - if (!pkey || raw_key->size <= 0) + /* Try to find a subkey with the authentication flag set. + * if none exists use the last one found + */ + for (i=0;i<subkeys;i++) { - gnutls_assert (); - return GNUTLS_E_CERTIFICATE_ERROR; - } - rc = cdk_stream_tmp_new (&out); - if (rc) - return GNUTLS_E_CERTIFICATE_ERROR; + ret = gnutls_openpgp_crt_get_subkey_revoked_status(crt, i); + if (ret != 0) /* it is revoked. ignore it */ + continue; - if (format == GNUTLS_OPENPGP_FMT_BASE64) - { - rc = cdk_stream_set_armor_flag (out, 0); - if (rc) - { - cdk_stream_close (out); - rc = _gnutls_map_cdk_rc (rc); - gnutls_assert (); - goto leave; - } - } + ret = gnutls_openpgp_crt_get_subkey_id( crt, i, keyid); + if (ret < 0) + { + gnutls_assert(); + return ret; + } - cdk_stream_write (out, raw_key->data, raw_key->size); - cdk_stream_seek (out, 0); + ret = gnutls_openpgp_crt_get_subkey_usage( crt, i, &usage); + if (ret < 0) + { + gnutls_assert(); + return ret; + } - rc = cdk_keydb_get_keyblock (out, &snode); - cdk_stream_close (out); - if (rc) - { - rc = GNUTLS_E_OPENPGP_GETKEY_FAILED; - goto leave; - } - - pkt = cdk_kbnode_find_packet (snode, CDK_PKT_SECRET_KEY); - if (!pkt) - { - rc = GNUTLS_E_OPENPGP_GETKEY_FAILED; - goto leave; - } - sk = pkt->pkt.secret_key; - pke_algo = sk->pk->pubkey_algo; - pkey->params_size = cdk_pk_get_npkey (pke_algo); - for (i = 0; i < pkey->params_size; i++) - { - nbytes = sizeof (buf) / sizeof (buf[0]); - cdk_pk_get_mpi (sk->pk, i, buf, nbytes, &nbytes, NULL); - rc = _gnutls_mpi_scan_pgp (&pkey->params[i], buf, &nbytes); - if (rc) - { - rc = GNUTLS_E_MPI_SCAN_FAILED; - release_mpi_array (pkey->params, i - 1); - goto leave; - } - } - - pkey->params_size += cdk_pk_get_nskey (pke_algo); - for (j = 0; j < cdk_pk_get_nskey (pke_algo); j++, i++) - { - nbytes = sizeof (buf) / sizeof (buf[0]); - cdk_sk_get_mpi (sk, j, buf, nbytes, &nbytes, NULL); - rc = _gnutls_mpi_scan_pgp (&pkey->params[i], buf, &nbytes); - if (rc) - { - rc = GNUTLS_E_MPI_SCAN_FAILED; - release_mpi_array (pkey->params, i - 1); - goto leave; - } + if (usage & GNUTLS_KEY_KEY_AGREEMENT) + break; } - if (is_ELG (pke_algo)) - return GNUTLS_E_UNWANTED_ALGORITHM; - else if (is_DSA (pke_algo)) - pkey->pk_algorithm = GNUTLS_PK_DSA; - else if (is_RSA (pke_algo)) - pkey->pk_algorithm = GNUTLS_PK_RSA; - -leave: - cdk_kbnode_release (snode); - return rc; + return 0; } - /*- - * _gnutls_openpgp_raw_key_to_gcert - Converts raw OpenPGP data to GnuTLS certs + * _gnutls_openpgp_raw_crt_to_gcert - Converts raw OpenPGP data to GnuTLS certs * @cert: the certificate to store the data. * @raw: the buffer which contains the whole OpenPGP key packets. * @@ -266,36 +135,40 @@ leave: * specific certificate. -*/ int -_gnutls_openpgp_raw_key_to_gcert (gnutls_cert * cert, +_gnutls_openpgp_raw_crt_to_gcert (gnutls_cert * gcert, const gnutls_datum_t * raw) { - cdk_kbnode_t knode = NULL; - cdk_packet_t pkt = NULL; - int rc; + int ret; + gnutls_openpgp_crt_t pcrt; + gnutls_openpgp_keyid_t keyid; - if (!cert) + ret = gnutls_openpgp_crt_init (&pcrt); + if (ret < 0) { gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; + return ret; } - memset (cert, 0, sizeof *cert); - - rc = cdk_kbnode_read_from_mem (&knode, raw->data, raw->size); - if (!(rc = _gnutls_map_cdk_rc (rc))) - pkt = cdk_kbnode_find_packet (knode, CDK_PKT_PUBLIC_KEY); - if (!pkt) + ret = gnutls_openpgp_crt_import (pcrt, raw, GNUTLS_OPENPGP_FMT_RAW); + if (ret < 0) { gnutls_assert (); - rc = _gnutls_map_cdk_rc (rc); + gnutls_openpgp_crt_deinit (pcrt); + return ret; } - if (!rc) - rc = _gnutls_set_datum (&cert->raw, raw->data, raw->size); - if (!rc) - rc = openpgp_pk_to_gnutls_cert (cert, pkt->pkt.public_key); - cdk_kbnode_release (knode); - return rc; + ret = _gnutls_openpgp_find_valid_subkey( pcrt, &keyid); + + if (ret < 0) + { + gnutls_assert(); + return ret; + } + + ret = _gnutls_openpgp_crt_to_gcert (gcert, pcrt, keyid); + gnutls_openpgp_crt_deinit (pcrt); + + return ret; } /** @@ -316,6 +189,15 @@ gnutls_certificate_set_openpgp_key (gnutls_certificate_credentials_t gnutls_openpgp_privkey_t pkey) { int ret; + gnutls_openpgp_keyid_t keyid; + + ret = _gnutls_openpgp_find_valid_subkey( crt, &keyid); + + if (ret < 0) + { + gnutls_assert(); + return ret; + } /* this should be first */ @@ -328,7 +210,7 @@ gnutls_certificate_set_openpgp_key (gnutls_certificate_credentials_t return GNUTLS_E_MEMORY_ERROR; } - ret = _gnutls_openpgp_privkey_to_gkey (&res->pkey[res->ncerts], pkey); + ret = _gnutls_openpgp_privkey_to_gkey (&res->pkey[res->ncerts], pkey, keyid); if (ret < 0) { gnutls_assert (); @@ -363,7 +245,7 @@ gnutls_certificate_set_openpgp_key (gnutls_certificate_credentials_t res->cert_list_length[res->ncerts] = 1; - ret = _gnutls_openpgp_crt_to_gcert (res->cert_list[res->ncerts], crt); + ret = _gnutls_openpgp_crt_to_gcert (res->cert_list[res->ncerts], crt, keyid); if (ret < 0) { gnutls_assert (); @@ -410,13 +292,13 @@ gnutls_openpgp_get_key (gnutls_datum_t * key, if (by == KEY_ATTR_SHORT_KEYID) { - keyid[0] = buftou32 (pattern); + keyid[0] = _gnutls_read_uint32(pattern); desc = keyid; } else if (by == KEY_ATTR_KEYID) { - keyid[0] = buftou32 (pattern); - keyid[1] = buftou32 (pattern + 4); + keyid[0] = _gnutls_read_uint32(pattern); + keyid[1] = _gnutls_read_uint32(pattern + 4); desc = keyid; } else @@ -838,84 +720,123 @@ gnutls_openpgp_set_recv_key_function (gnutls_session_t session, /* Copies a gnutls_openpgp_privkey_t to a gnutls_privkey structure. */ int _gnutls_openpgp_privkey_to_gkey (gnutls_privkey * dest, - gnutls_openpgp_privkey_t src) + gnutls_openpgp_privkey_t src, gnutls_openpgp_keyid_t keyid) { - int i, ret; - - memset (dest, 0, sizeof (gnutls_privkey)); - - for (i = 0; i < src->pkey.params_size; i++) + int ret = 0, idx; + uint32_t kid32[2]; + + if (dest==NULL || src == NULL) { - dest->params[i] = _gnutls_mpi_copy (src->pkey.params[i]); - if (dest->params[i] == NULL) - { - gnutls_assert (); - ret = GNUTLS_E_MEMORY_ERROR; - goto cleanup; - } + gnutls_assert (); + return GNUTLS_E_CERTIFICATE_ERROR; } - dest->pk_algorithm = src->pkey.pk_algorithm; - dest->params_size = src->pkey.params_size; - + KEYID_IMPORT(kid32, keyid); + + idx = gnutls_openpgp_privkey_get_subkey_idx( src, keyid); + if (idx < 0) + { + gnutls_assert(); + return idx; + } + + dest->pk_algorithm = gnutls_openpgp_privkey_get_subkey_pk_algorithm( src, idx, NULL); + + dest->params_size = MAX_PRIV_PARAMS_SIZE; + ret = _gnutls_openpgp_privkey_get_mpis( src, kid32, dest->params, &dest->params_size); + + if (ret < 0) + { + gnutls_assert(); + return ret; + } + return 0; -cleanup: - for (i = 0; i < src->pkey.params_size; i++) - _gnutls_mpi_release (&dest->params[i]); - return ret; } /* Converts a parsed gnutls_openpgp_crt_t to a gnutls_cert structure. */ int -_gnutls_openpgp_crt_to_gcert (gnutls_cert * gcert, gnutls_openpgp_crt_t cert) +_gnutls_openpgp_crt_to_gcert (gnutls_cert * gcert, gnutls_openpgp_crt_t cert, + gnutls_openpgp_keyid_t keyid) { - opaque *der; - size_t der_size = 0; - gnutls_datum_t raw; - int ret; + int ret, idx; + uint32_t kid32[2]; + + KEYID_IMPORT(kid32, keyid); memset (gcert, 0, sizeof (gnutls_cert)); gcert->cert_type = GNUTLS_CRT_OPENPGP; - - ret = gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW, - NULL, &der_size); - if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) + idx = gnutls_openpgp_crt_get_subkey_idx( cert, keyid); + if (idx < 0) { - gnutls_assert (); - return ret; + gnutls_assert(); + return idx; } - der = gnutls_malloc (der_size); - if (der == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } + gcert->subject_pk_algorithm = gnutls_openpgp_crt_get_subkey_pk_algorithm( cert, idx, NULL); + gcert->version = gnutls_openpgp_crt_get_version( cert); + + gnutls_openpgp_crt_get_subkey_usage( cert, idx, &gcert->key_usage); - ret = gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW, - der, &der_size); + gcert->params_size = MAX_PUBLIC_PARAMS_SIZE; + ret = _gnutls_openpgp_crt_get_mpis( cert, kid32, gcert->params, &gcert->params_size); + if (ret < 0) { - gnutls_assert (); - gnutls_free (der); + gnutls_assert(); return ret; } - raw.data = der; - raw.size = der_size; + { /* copy the raw certificate */ +#define SMALL_RAW 512 + opaque *raw; + size_t raw_size = SMALL_RAW; - ret = _gnutls_openpgp_raw_key_to_gcert (gcert, &raw); - if (ret < 0) - { - gnutls_assert (); - gnutls_free (der); - return ret; - } + /* initially allocate a bogus size, just in case the certificate + * fits in it. That way we minimize the DER encodings performed. + */ + raw = gnutls_malloc (raw_size); + if (raw == NULL) + { + gnutls_assert (); + return GNUTLS_E_MEMORY_ERROR; + } - gnutls_free (der); + ret = + gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW, raw, &raw_size); + if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) + { + gnutls_assert (); + gnutls_free (raw); + return ret; + } + + if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) + { + raw = gnutls_realloc (raw, raw_size); + if (raw == NULL) + { + gnutls_assert (); + return GNUTLS_E_MEMORY_ERROR; + } + + ret = + gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW, raw, + &raw_size); + if (ret < 0) + { + gnutls_assert (); + gnutls_free (raw); + return ret; + } + } + + gcert->raw.data = raw; + gcert->raw.size = raw_size; + } return 0; @@ -925,20 +846,28 @@ _gnutls_openpgp_crt_to_gcert (gnutls_cert * gcert, gnutls_openpgp_crt_t cert) /** * gnutls_openpgp_privkey_sign_hash - This function will sign the given data using the private key params * @key: Holds the key + * @src_keyid: Holds the keyid to be used * @hash: holds the data to be signed * @signature: will contain newly allocated signature * * This function will sign the given hash using the private key. + * You should use gnutls_openpgp_privkey_set_subkey() before calling this function + * to set the subkey to use. * * Return value: In case of failure a negative value will be returned, * and 0 on success. **/ int gnutls_openpgp_privkey_sign_hash (gnutls_openpgp_privkey_t key, + gnutls_openpgp_keyid_t src_keyid, const gnutls_datum_t * hash, gnutls_datum_t * signature) { - int result; +int result, i; +uint32_t keyid[2]; +mpi_t params[MAX_PUBLIC_PARAMS_SIZE]; +int params_size = MAX_PUBLIC_PARAMS_SIZE; +int pk_algorithm; if (key == NULL) { @@ -946,8 +875,23 @@ gnutls_openpgp_privkey_sign_hash (gnutls_openpgp_privkey_t key, return GNUTLS_E_INVALID_REQUEST; } - result = _gnutls_sign (key->pkey.pk_algorithm, key->pkey.params, - key->pkey.params_size, hash, signature); + KEYID_IMPORT( keyid, src_keyid); + + result = _gnutls_openpgp_privkey_get_mpis( key, keyid, params, ¶ms_size); + if (result < 0) + { + gnutls_assert (); + return result; + } + + pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm (key, NULL); + + result = _gnutls_sign (pk_algorithm, params, + params_size, hash, signature); + + for (i=0;i<params_size;i++) + _gnutls_mpi_release( ¶ms[i]); + if (result < 0) { gnutls_assert (); diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c index 4058dbcf9d..a8ad52ad55 100644 --- a/lib/gnutls_state.c +++ b/lib/gnutls_state.c @@ -624,6 +624,7 @@ _gnutls_dh_set_group (gnutls_session_t session, mpi_t gen, mpi_t prime) return 0; } +#ifdef ENABLE_OPENPGP /** * gnutls_openpgp_send_cert - This function will order gnutls to send the openpgp fingerprint instead of the key * @session: is a pointer to a #gnutls_session_t structure. @@ -640,6 +641,7 @@ gnutls_openpgp_send_cert (gnutls_session_t session, { session->internals.pgp_fingerprint = status; } +#endif /** * gnutls_certificate_send_x509_rdn_sequence - This function will order gnutls to send or not the x.509 rdn sequence @@ -662,11 +664,13 @@ gnutls_certificate_send_x509_rdn_sequence (gnutls_session_t session, session->internals.ignore_rdn_sequence = status; } +#ifdef ENABLE_OPENPGP int _gnutls_openpgp_send_fingerprint (gnutls_session_t session) { return session->internals.pgp_fingerprint; } +#endif /*- * _gnutls_record_set_default_version - Used to set the default version for the first record packet diff --git a/libextra/opencdk/Makefile.am b/lib/opencdk/Makefile.am index 9f6a805f86..7e74320c0e 100644 --- a/libextra/opencdk/Makefile.am +++ b/lib/opencdk/Makefile.am @@ -25,9 +25,9 @@ INCLUDES = -I$(top_srcdir)/lib \ noinst_LTLIBRARIES = libminiopencdk.la -libminiopencdk_la_SOURCES = armor.c filters.h main.c seskey.c types.h \ - cipher.c kbnode.c main.h packet.h dummy.c sig-check.c verify.c \ - compress.c keydb.c misc.c pubkey.c stream.c write-packet.c \ +libminiopencdk_la_SOURCES = armor.c filters.h main.c types.h \ + kbnode.c main.h packet.h dummy.c sig-check.c verify.c hash.c \ + keydb.c pubkey.c stream.c write-packet.c misc.c seskey.c \ context.h literal.c new-packet.c read-packet.c stream.h opencdk.h EXTRA_DIST = README diff --git a/libextra/opencdk/README b/lib/opencdk/README index 2cf780e04c..2cf780e04c 100644 --- a/libextra/opencdk/README +++ b/lib/opencdk/README diff --git a/libextra/opencdk/armor.c b/lib/opencdk/armor.c index 5195d41f72..4921995d1c 100644 --- a/libextra/opencdk/armor.c +++ b/lib/opencdk/armor.c @@ -4,15 +4,20 @@ * * This file is part of OpenCDK. * - * OpenCDK is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * OpenCDK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * The OpenCDK library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA * * ChangeLog for basic BASE64 code (base64_encode, base64_decode): * Original author: Eric S. Raymond (Fetchmail) diff --git a/libextra/opencdk/context.h b/lib/opencdk/context.h index e656952302..e656952302 100644 --- a/libextra/opencdk/context.h +++ b/lib/opencdk/context.h diff --git a/libextra/opencdk/dummy.c b/lib/opencdk/dummy.c index e21e927d43..e21e927d43 100644 --- a/libextra/opencdk/dummy.c +++ b/lib/opencdk/dummy.c diff --git a/libextra/opencdk/filters.h b/lib/opencdk/filters.h index a60881edb8..a60881edb8 100644 --- a/libextra/opencdk/filters.h +++ b/lib/opencdk/filters.h diff --git a/lib/opencdk/hash.c b/lib/opencdk/hash.c new file mode 100644 index 0000000000..abfc101fca --- /dev/null +++ b/lib/opencdk/hash.c @@ -0,0 +1,81 @@ +/* hash.c - Hash filters + * Copyright (C) 2002, 2003, 2007 Timo Schulz + * + * This file is part of OpenCDK. + * + * The OpenCDK library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA + */ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <stdio.h> +#include <assert.h> +#include <sys/stat.h> + +#include "opencdk.h" +#include "main.h" +#include "filters.h" + +static cdk_error_t +hash_encode (void *opaque, FILE *in, FILE *out) +{ + md_filter_t *mfx = opaque; + byte buf[BUFSIZE]; + gcry_error_t err; + int nread; + + if (!mfx) + return CDK_Inv_Value; + + _cdk_log_debug ("hash filter: encode algo=%d\n", mfx->digest_algo); + + if (!mfx->md) + { + err = gcry_md_open (&mfx->md, mfx->digest_algo, 0); + if (err) + return map_gcry_error (err); + } + + while (!feof (in)) + { + nread = fread (buf, 1, BUFSIZE, in); + if (!nread) + break; + gcry_md_write (mfx->md, buf, nread); + } + + wipemem (buf, sizeof (buf)); + return 0; +} + +cdk_error_t +_cdk_filter_hash (void *opaque, int ctl, FILE *in, FILE *out) +{ + if (ctl == STREAMCTL_READ) + return hash_encode (opaque, in, out); + else if (ctl == STREAMCTL_FREE) + { + md_filter_t *mfx = opaque; + if (mfx) + { + _cdk_log_debug ("free hash filter\n"); + gcry_md_close (mfx->md); + mfx->md = NULL; + return 0; + } + } + return CDK_Inv_Mode; +} diff --git a/libextra/opencdk/kbnode.c b/lib/opencdk/kbnode.c index 848a34214b..dd76fd74d5 100644 --- a/libextra/opencdk/kbnode.c +++ b/lib/opencdk/kbnode.c @@ -4,15 +4,20 @@ * * This file is part of OpenCDK. * - * OpenCDK is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * The OpenCDK library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. * - * OpenCDK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA */ #ifdef HAVE_CONFIG_H # include <config.h> @@ -31,7 +36,7 @@ * cdk_kbnode_new: * @pkt: the packet to add * - * Allocate a new key node and add the packet. + * Allocates a new key node and adds a packet. **/ cdk_kbnode_t cdk_kbnode_new (cdk_packet_t pkt) @@ -60,7 +65,7 @@ _cdk_kbnode_clone (cdk_kbnode_t node) * cdk_kbnode_release: * @n: the key node * - * Release the memory of the node. + * Releases the memory of the node. **/ void cdk_kbnode_release (cdk_kbnode_t node) @@ -82,7 +87,7 @@ cdk_kbnode_release (cdk_kbnode_t node) * cdk_kbnode_delete: * @node: the key node * - * Mark the given node as deleted. + * Marks the given node as deleted. **/ void cdk_kbnode_delete (cdk_kbnode_t node) @@ -110,7 +115,7 @@ _cdk_kbnode_add (cdk_kbnode_t root, cdk_kbnode_t node) * @node: the node to add * @pkttype: packet type * - * Insert @node into the list after @root but before a packet which is not of + * Inserts @node into the list after @root but before a packet which is not of * type @pkttype (only if @pkttype != 0). **/ void @@ -145,7 +150,7 @@ cdk_kbnode_insert (cdk_kbnode_t root, cdk_kbnode_t node, int pkttype) * @node: the key node * @pkttype: packet type * - * Find the previous node (if @pkttype = 0) or the previous node + * Finds the previous node (if @pkttype = 0) or the previous node * with pkttype @pkttype in the list starting with @root of @node. **/ cdk_kbnode_t @@ -202,7 +207,7 @@ cdk_kbnode_find_next (cdk_kbnode_t node, int pkttype) * @node: the key node * @pkttype: packet type * - * Try to find the next node with the packettype @pkttype. + * Tries to find the next node with the packettype @pkttype. **/ cdk_kbnode_t cdk_kbnode_find (cdk_kbnode_t node, int pkttype) @@ -233,28 +238,30 @@ cdk_kbnode_find_packet (cdk_kbnode_t node, int pkttype) } -/**************** - * Walk through a list of kbnodes. This function returns +/** + * cdk_kbnode_walk: + * + * Walks through a list of kbnodes. This function returns * the next kbnode for each call; before using the function the first * time, the caller must set CONTEXT to NULL (This has simply the effect * to start with ROOT). */ cdk_kbnode_t -cdk_kbnode_walk (cdk_kbnode_t root, cdk_kbnode_t * context, int all) +cdk_kbnode_walk (cdk_kbnode_t root, cdk_kbnode_t *ctx, int all) { cdk_kbnode_t n; do { - if(! *context ) + if (! *ctx) { - *context = root; + *ctx = root; n = root; } else { - n = (*context)->next; - *context = n; + n = (*ctx)->next; + *ctx = n; } } while (!all && n && n->is_deleted); @@ -266,13 +273,13 @@ cdk_kbnode_walk (cdk_kbnode_t root, cdk_kbnode_t * context, int all) * cdk_kbnode_commit: * @root: the nodes * - * Commit changes made to the kblist at ROOT. Note that ROOT my change, + * Commits changes made to the kblist at ROOT. Note that ROOT my change, * and it is therefore passed by reference. * The function has the effect of removing all nodes marked as deleted. * returns true if any node has been changed */ int -cdk_kbnode_commit (cdk_kbnode_t * root) +cdk_kbnode_commit (cdk_kbnode_t *root) { cdk_kbnode_t n, nl; int changed = 0; @@ -302,7 +309,7 @@ cdk_kbnode_commit (cdk_kbnode_t * root) * @root: the root node * @node: the node to delete * - * Remove a node from the root node. + * Removes a node from the root node. */ void cdk_kbnode_remove (cdk_kbnode_t *root, cdk_kbnode_t node) @@ -334,7 +341,7 @@ cdk_kbnode_remove (cdk_kbnode_t *root, cdk_kbnode_t node) * @node: the node to move * @where: destination place where to move the node. * - * Move NODE behind right after WHERE or to the beginning if WHERE is NULL. + * Moves NODE behind right after WHERE or to the beginning if WHERE is NULL. */ void cdk_kbnode_move (cdk_kbnode_t * root, cdk_kbnode_t node, cdk_kbnode_t where) @@ -370,7 +377,7 @@ cdk_kbnode_move (cdk_kbnode_t * root, cdk_kbnode_t node, cdk_kbnode_t where) * cdk_kbnode_get_packet: * @node: the key node * - * Return the packet which is stored inside the node in @node. + * Returns the packet which is stored inside the node in @node. **/ cdk_packet_t cdk_kbnode_get_packet (cdk_kbnode_t node) @@ -387,7 +394,7 @@ cdk_kbnode_get_packet (cdk_kbnode_t node) * @buf: the buffer which stores the key sequence * @buflen: the length of the buffer * - * Try to read a key node from the memory buffer @buf. + * Tries to read a key node from the memory buffer @buf. **/ cdk_error_t cdk_kbnode_read_from_mem (cdk_kbnode_t *ret_node, @@ -396,10 +403,13 @@ cdk_kbnode_read_from_mem (cdk_kbnode_t *ret_node, cdk_stream_t inp; cdk_error_t rc; - if (!buflen || !ret_node || !buf) + if (!ret_node || !buf) return CDK_Inv_Value; *ret_node = NULL; + if (!buflen) + return CDK_Too_Short; + rc = cdk_stream_tmp_from_mem (buf, buflen, &inp); if (rc) return rc; @@ -408,6 +418,7 @@ cdk_kbnode_read_from_mem (cdk_kbnode_t *ret_node, return rc; } + /** * cdk_kbnode_write_to_mem_alloc: * @node: the key node @@ -426,7 +437,7 @@ cdk_kbnode_write_to_mem_alloc (cdk_kbnode_t node, cdk_error_t rc; size_t len; - if (!node) + if (!node || !r_buf || !r_buflen) return CDK_Inv_Value; *r_buf = NULL; @@ -470,7 +481,7 @@ cdk_kbnode_write_to_mem_alloc (cdk_kbnode_t node, * @buf: the buffer to store the node data * @r_nbytes: the new length of the buffer. * - * Try to write the contents of the key node to the buffer @buf and + * Tries to write the contents of the key node to the buffer @buf and * return the length of it in @r_nbytes. If buf is zero, only the * length of the node is calculated and returned in @r_nbytes. * Whenever it is possible, the cdk_kbnode_write_to_mem_alloc should be used. @@ -479,11 +490,11 @@ cdk_error_t cdk_kbnode_write_to_mem (cdk_kbnode_t node, byte *buf, size_t *r_nbytes) { cdk_kbnode_t n; - cdk_stream_t s; - size_t len; + cdk_stream_t s; cdk_error_t rc; + size_t len; - if (!node) + if (!node || !r_nbytes) return CDK_Inv_Value; rc = cdk_stream_tmp_new (&s); @@ -518,7 +529,10 @@ cdk_kbnode_write_to_mem (cdk_kbnode_t node, byte *buf, size_t *r_nbytes) return 0; } if (*r_nbytes < len) - rc = CDK_Too_Short; + { + *r_nbytes = len; + rc = CDK_Too_Short; + } if (!rc) *r_nbytes = cdk_stream_read (s, buf, len); cdk_stream_close (s); @@ -534,7 +548,7 @@ cdk_kbnode_write_to_mem (cdk_kbnode_t node, byte *buf, size_t *r_nbytes) * @pkttype: packet type to hash (if zero use the packet type from the node) * @flags: flags which depend on the operation * - * Hash the key node contents. Two modes are supported. If the packet + * Hashes the key node contents. Two modes are supported. If the packet * type is used (!= 0) then the function searches the first node with * this type. Otherwise the node is seen as a single node and the type * is extracted from it. diff --git a/libextra/opencdk/keydb.c b/lib/opencdk/keydb.c index 8b04d3f6ac..79b7b89c5a 100644 --- a/libextra/opencdk/keydb.c +++ b/lib/opencdk/keydb.c @@ -3,15 +3,20 @@ * * This file is part of OpenCDK. * - * OpenCDK is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * The OpenCDK library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. * - * OpenCDK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA */ #ifdef HAVE_CONFIG_H # include <config.h> @@ -1499,12 +1504,20 @@ keydb_merge_selfsig (cdk_kbnode_t key, u32 *keyid) s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_KEY_FLAGS); if (s) { - if (s->d[0] & 0x03) /* cert + sign data */ - key_usage |= CDK_KEY_USG_SIGN; - if (s->d[0] & 0x0C) /* encrypt comm. + storage */ - key_usage |= CDK_KEY_USG_ENCR; + if (s->d[0] & 0x01) /* cert + sign data */ + key_usage |= CDK_KEY_USG_CERT_SIGN; + if (s->d[0] & 0x02) /* cert + sign data */ + key_usage |= CDK_KEY_USG_DATA_SIGN; + if (s->d[0] & 0x04) /* encrypt comm. + storage */ + key_usage |= CDK_KEY_USG_COMM_ENCR; + if (s->d[0] & 0x08) /* encrypt comm. + storage */ + key_usage |= CDK_KEY_USG_STORAGE_ENCR; + if (s->d[0] & 0x10) /* encrypt comm. + storage */ + key_usage |= CDK_KEY_USG_SPLIT_KEY; if (s->d[0] & 0x20) key_usage |= CDK_KEY_USG_AUTH; + if (s->d[0] & 0x80) /* encrypt comm. + storage */ + key_usage |= CDK_KEY_USG_SHARED_KEY; } s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PREFS_SYM); if (s) diff --git a/libextra/opencdk/literal.c b/lib/opencdk/literal.c index e38e564bbf..438a0b6526 100644 --- a/libextra/opencdk/literal.c +++ b/lib/opencdk/literal.c @@ -3,15 +3,20 @@ * * This file is part of OpenCDK. * - * OpenCDK is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * The OpenCDK library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. * - * OpenCDK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA */ #ifdef HAVE_CONFIG_H # include <config.h> diff --git a/libextra/opencdk/main.c b/lib/opencdk/main.c index 2d3648ef3a..c0e67da149 100644 --- a/libextra/opencdk/main.c +++ b/lib/opencdk/main.c @@ -3,15 +3,20 @@ * * This file is part of OpenCDK. * - * OpenCDK is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * OpenCDK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * The OpenCDK library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA */ #ifdef HAVE_CONFIG_H # include <config.h> diff --git a/libextra/opencdk/main.h b/lib/opencdk/main.h index 3e9a443d8f..3e9a443d8f 100644 --- a/libextra/opencdk/main.h +++ b/lib/opencdk/main.h diff --git a/lib/opencdk/misc.c b/lib/opencdk/misc.c new file mode 100644 index 0000000000..35c8ad4482 --- /dev/null +++ b/lib/opencdk/misc.c @@ -0,0 +1,324 @@ +/* misc.c + * Copyright (C) 2002, 2003 Timo Schulz + * Copyright (C) 1998-2002, 2007 Free Software Foundation, Inc. + * + * This file is part of OpenCDK. + * + * The OpenCDK library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA + */ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <sys/stat.h> + +#include "opencdk.h" +#include "main.h" + + +u32 +_cdk_buftou32 (const byte *buf) +{ + u32 u; + + if (!buf) + return 0; + u = buf[0] << 24; + u |= buf[1] << 16; + u |= buf[2] << 8; + u |= buf[3]; + return u; +} + + +void +_cdk_u32tobuf (u32 u, byte *buf) +{ + if (!buf) + return; + buf[0] = u >> 24; + buf[1] = u >> 16; + buf[2] = u >> 8; + buf[3] = u ; +} + + +static const char * +parse_version_number (const char *s, int *number) +{ + int val = 0; + + if (*s == '0' && isdigit (s[1])) + return NULL; + /* leading zeros are not allowed */ + for (; isdigit(*s); s++) + { + val *= 10; + val += *s - '0'; + } + *number = val; + return val < 0? NULL : s; +} + + +static const char * +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 */ +} + + +/** + * cdk_check_version: + * @req_version: The requested version + * + * Check that the the version of the library is at minimum the requested + * one and return the version string; return NULL if the condition is + * not satisfied. If a NULL is passed to this function, no check is done, + *but the version string is simply returned. + **/ +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; + + 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) + { + sl2 = sl->next; + cdk_free (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) +{ + cdk_strlist_t sl; + + if (!string) + return NULL; + + sl = cdk_calloc (1, sizeof *sl + strlen (string) + 1); + if (!sl) + return NULL; + strcpy (sl->d, string); + sl->next = *list; + *list = sl; + return sl; +} + + +/** + * cdk_strlist_next: + * @root: the opaque string list. + * @r_str: optional argument to store the string data. + * + * Return the next string list node from @root. The optional + * argument @r_str return the data of the current (!) node. + **/ +cdk_strlist_t +cdk_strlist_next (cdk_strlist_t root, const char **r_str) +{ + cdk_strlist_t node; + + if (root && r_str) + *r_str = root->d; + for (node = root->next; node; node = node->next) + return node; + + return NULL; +} + + +const char* +_cdk_memistr (const char *buf, size_t buflen, const char *sub) +{ + const byte *t, *s; + size_t n; + + for (t = (byte*)buf, n = buflen, s = (byte*)sub ; n ; t++, n--) + { + if (toupper (*t) == toupper (*s)) + { + for (buf = t++, buflen = n--, s++; + n && toupper (*t) == toupper ((byte)*s); t++, s++, n--) + ; + if (!*s) + return buf; + t = (byte*)buf; + n = buflen; + s = (byte*)sub; + } + } + + return NULL; +} + + +/* Map the gcrypt error to a valid opencdk error constant. */ +cdk_error_t +_cdk_map_gcry_error (gcry_error_t err) +{ + /* FIXME: We need to catch them all. */ + switch (gpg_err_code (err)) + { + case GPG_ERR_NO_ERROR: return CDK_Success; + case GPG_ERR_INV_VALUE: return CDK_Inv_Value; + case GPG_ERR_GENERAL: return CDK_General_Error; + case GPG_ERR_INV_PACKET: return CDK_Inv_Packet; + case GPG_ERR_TOO_SHORT: return CDK_Too_Short; + case GPG_ERR_TOO_LARGE: return CDK_Inv_Value; + case GPG_ERR_NO_PUBKEY: + case GPG_ERR_NO_SECKEY: return CDK_Error_No_Key; + case GPG_ERR_BAD_SIGNATURE: return CDK_Bad_Sig; + case GPG_ERR_NO_DATA: return CDK_No_Data; + default: + break; + } + + return (cdk_error_t)err; +} + + +/* Remove all trailing white spaces from the string. */ +void +_cdk_trim_string (char *s, int canon) +{ + while (s && *s && + (s[strlen (s)-1] == '\t' || + s[strlen (s)-1] == '\r' || + s[strlen (s)-1] == '\n' || + s[strlen (s)-1] == ' ')) + s[strlen (s) -1] = '\0'; + if (canon) + strcat (s, "\r\n"); +} + + +int +_cdk_check_args (int overwrite, const char *in, const char *out) +{ + struct stat stbuf; + + if (!in || !out) + return CDK_Inv_Value; + if (strlen (in) == strlen (out) && strcmp (in, out) == 0) + return CDK_Inv_Mode; + if (!overwrite && !stat (out, &stbuf)) + return CDK_Inv_Mode; + return 0; +} + +#ifdef _WIN32 +#include <io.h> +#include <fcntl.h> + +FILE * +my_tmpfile (void) +{ + /* Because the tmpfile() version of wine is not really useful, + we implement our own version to avoid problems with 'make check'. */ + static const char *letters = "abcdefghijklmnopqrstuvwxyz"; + char buf[512], rnd[24]; + FILE *fp; + int fd, i; + + gcry_create_nonce (rnd, DIM (rnd)); + for (i=0; i < DIM (rnd)-1; i++) + { + char c = letters[(unsigned char)rnd[i] % 26]; + rnd[i] = c; + } + rnd[DIM (rnd)-1]=0; + if (!GetTempPath (464, buf)) + return NULL; + strcat (buf, "_cdk_"); + strcat (buf, rnd); + + /* We need to make sure the file will be deleted when it is closed. */ + fd = _open (buf, _O_CREAT | _O_EXCL | _O_TEMPORARY | + _O_RDWR | _O_BINARY, _S_IREAD | _S_IWRITE); + if (fd == -1) + return NULL; + fp = fdopen (fd, "w+b"); + if (fp != NULL) + return fp; + _close (fd); + return NULL; +} +#else +FILE* +my_tmpfile (void) +{ + return tmpfile (); +} +#endif diff --git a/libextra/opencdk/new-packet.c b/lib/opencdk/new-packet.c index 1c7e5da4aa..c824ed0e81 100644 --- a/libextra/opencdk/new-packet.c +++ b/lib/opencdk/new-packet.c @@ -3,15 +3,20 @@ * * This file is part of OpenCDK. * - * OpenCDK is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * OpenCDK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * The OpenCDK library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA */ #ifdef HAVE_CONFIG_H # include <config.h> diff --git a/libextra/opencdk/opencdk.h b/lib/opencdk/opencdk.h index 83ca487e91..da2a869f95 100644 --- a/libextra/opencdk/opencdk.h +++ b/lib/opencdk/opencdk.h @@ -281,12 +281,17 @@ enum cdk_crypto_mode_t { CDK_CRYPTYPE_IMPORT = 6 }; - +#define CDK_KEY_USG_ENCR CDK_KEY_USG_COMM_ENCR|CDK_KEY_USG_STORAGE_ENCR +#define CDK_KEY_USG_SIGN CDK_KEY_USG_DATA_SIGN|CDK_KEY_USG_CERT_SIGN /* A list of valid public key usages. */ enum cdk_key_usage_t { - CDK_KEY_USG_ENCR = 1, /* Key can be used for encryption. */ - CDK_KEY_USG_SIGN = 2, /* Key can be used for signing and certifying. */ - CDK_KEY_USG_AUTH = 4 /* Key can be used for authentication. */ + CDK_KEY_USG_CERT_SIGN = 1, + CDK_KEY_USG_DATA_SIGN = 2, + CDK_KEY_USG_COMM_ENCR = 4, + CDK_KEY_USG_STORAGE_ENCR = 8, + CDK_KEY_USG_SPLIT_KEY = 16, + CDK_KEY_USG_AUTH = 32, + CDK_KEY_USG_SHARED_KEY = 128 }; diff --git a/libextra/opencdk/packet.h b/lib/opencdk/packet.h index 03547acea0..03547acea0 100644 --- a/libextra/opencdk/packet.h +++ b/lib/opencdk/packet.h diff --git a/libextra/opencdk/pubkey.c b/lib/opencdk/pubkey.c index e3498e0a95..5a072b56ba 100644 --- a/libextra/opencdk/pubkey.c +++ b/lib/opencdk/pubkey.c @@ -4,15 +4,20 @@ * * This file is part of OpenCDK. * - * OpenCDK is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * The OpenCDK library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. * - * OpenCDK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA */ #ifdef HAVE_CONFIG_H #include <config.h> @@ -600,14 +605,15 @@ _cdk_pk_algo_usage (int algo) return usage; } - +/* You can use a NULL buf to get the output size only + */ static cdk_error_t mpi_to_buffer (gcry_mpi_t a, byte *buf, size_t buflen, size_t *r_nwritten, size_t *r_nbits) { size_t nbits; - if (!a || !buf || !r_nwritten) + if (!a || !r_nwritten) return CDK_Inv_Value; nbits = gcry_mpi_get_nbits (a); @@ -616,6 +622,7 @@ mpi_to_buffer (gcry_mpi_t a, byte *buf, size_t buflen, if ((nbits+7)/8+2 > buflen) return CDK_Too_Short; *r_nwritten = (nbits+7)/8+2; + if (gcry_mpi_print (GCRYMPI_FMT_PGP, buf, buflen, r_nwritten, a)) return CDK_Wrong_Format; return 0; diff --git a/libextra/opencdk/read-packet.c b/lib/opencdk/read-packet.c index b1f50b6e22..040f564c49 100644 --- a/libextra/opencdk/read-packet.c +++ b/lib/opencdk/read-packet.c @@ -3,15 +3,20 @@ * * This file is part of OpenCDK. * - * OpenCDK is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * OpenCDK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * The OpenCDK library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA */ #ifdef HAVE_CONFIG_H #include <config.h> @@ -73,40 +78,7 @@ read_16 (cdk_stream_t s) static int read_s2k (cdk_stream_t inp, cdk_s2k_t s2k) { - size_t nread; - - if (!inp || !s2k) - return CDK_Inv_Value; - - if (DEBUG_PKT) - _cdk_log_debug ("read_s2k:\n"); - - s2k->mode = cdk_stream_getc (inp); - if (cdk_stream_eof (inp)) - return CDK_Inv_Packet; - if (s2k->mode != CDK_S2K_SIMPLE && s2k->mode != CDK_S2K_SALTED && - s2k->mode != CDK_S2K_ITERSALTED) - return CDK_Inv_Packet; - s2k->hash_algo = cdk_stream_getc (inp); - if (s2k->mode == CDK_S2K_SIMPLE) /* No additional elements. */ - memset (s2k->salt, 0, sizeof (s2k->salt)); - else if (s2k->mode == CDK_S2K_SALTED || - s2k->mode == CDK_S2K_ITERSALTED) - { - if (stream_read (inp, s2k->salt, DIM (s2k->salt), &nread)) - return CDK_Inv_Packet; - if (nread != DIM (s2k->salt)) - return CDK_Inv_Packet; - if (s2k->mode == CDK_S2K_ITERSALTED) - { - s2k->count = cdk_stream_getc (inp); - if (cdk_stream_eof (inp)) - return CDK_Inv_Packet; - } - } - else - return CDK_Inv_Mode; - return 0; + return CDK_Not_Implemented; } diff --git a/libextra/opencdk/seskey.c b/lib/opencdk/seskey.c index 0f5d0f90c0..ebf5381db8 100644 --- a/libextra/opencdk/seskey.c +++ b/lib/opencdk/seskey.c @@ -4,15 +4,20 @@ * * This file is part of OpenCDK. * - * OpenCDK is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * The OpenCDK library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. * - * OpenCDK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA */ #ifdef HAVE_CONFIG_H # include <config.h> @@ -345,7 +350,7 @@ _cdk_sk_unprotect_auto (cdk_ctx_t hd, cdk_pkt_seckey_t sk) * @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 diff --git a/libextra/opencdk/sig-check.c b/lib/opencdk/sig-check.c index 948fe2993b..f81ae12e4e 100644 --- a/libextra/opencdk/sig-check.c +++ b/lib/opencdk/sig-check.c @@ -4,15 +4,20 @@ * * This file is part of OpenCDK. * - * OpenCDK is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * OpenCDK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * The OpenCDK library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA */ #ifdef HAVE_CONFIG_H # include <config.h> diff --git a/libextra/opencdk/stream.c b/lib/opencdk/stream.c index d934ce690b..2e43b8bff4 100644 --- a/libextra/opencdk/stream.c +++ b/lib/opencdk/stream.c @@ -3,15 +3,20 @@ * * This file is part of OpenCDK. * - * OpenCDK is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * The OpenCDK library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. * - * OpenCDK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA */ #ifdef HAVE_CONFIG_H #include <config.h> @@ -53,7 +58,7 @@ FILE *my_tmpfile (void); * @file: The file to open * @ret_s: The new STREAM object * - * Create a new stream based on an existing file. The stream is + * Creates a new stream based on an existing file. The stream is * opened in read-only mode. **/ cdk_error_t @@ -137,9 +142,11 @@ cdk_stream_new_from_cbs (cdk_stream_cbs_t cbs, void *opa, /** - * cdk_stream_new: Create a new stream into into the given file. + * cdk_stream_new: * @file: The name of the new file * @ret_s: The new STREAM object + * + * Create a new stream into into the given file. **/ cdk_error_t cdk_stream_new (const char *file, cdk_stream_t *ret_s) @@ -180,10 +187,11 @@ cdk_stream_new (const char *file, cdk_stream_t *ret_s) /** - * cdk_stream_create: create a new stream. + * cdk_stream_create: * @file: the filename * @ret_s: the object * + * Creates a new stream. * The difference to cdk_stream_new is, that no filtering can be used with * this kind of stream and everything is written directly to the stream. **/ @@ -225,7 +233,7 @@ cdk_stream_create (const char *file, cdk_stream_t *ret_s) * cdk_stream_tmp_new: * @r_out: the new temp stream. * - * Allocate a new tempory stream which is not associated with a file. + * Allocates a new tempory stream which is not associated with a file. */ cdk_error_t cdk_stream_tmp_new (cdk_stream_t *r_out) @@ -241,7 +249,7 @@ cdk_stream_tmp_new (cdk_stream_t *r_out) * @buflen: how large the buffer is * @r_out: the new stream with the given contents. * - * Create a new tempory stream with the given contests. + * Creates a new tempory stream with the given contests. */ cdk_error_t cdk_stream_tmp_from_mem (const void *buf, size_t buflen, cdk_stream_t *r_out) @@ -313,7 +321,7 @@ _cdk_stream_append (const char *file, cdk_stream_t *ret_s) * cdk_stream_is_compressed: * @s: the stream * - * Return 0 if the stream is uncompressed, otherwise the + * Returns 0 if the stream is uncompressed, otherwise the * compression algorithm. */ int @@ -614,18 +622,19 @@ stream_id_to_filter (int type) case fARMOR : return _cdk_filter_armor; case fLITERAL : return _cdk_filter_literal; case fTEXT : return _cdk_filter_text; - case fCIPHER : return _cdk_filter_cipher; - case fCOMPRESS: return _cdk_filter_compress; +/* case fCIPHER : return _cdk_filter_cipher; */ +/* case fCOMPRESS: return _cdk_filter_compress; */ default : return NULL; } } /** - * cdk_stream_filter_disable: Disable the filter with the type 'type' + * cdk_stream_filter_disable: * @s: The STREAM object * @type: The numberic filter ID. * + * Disables the filter with the type 'type'. **/ cdk_error_t cdk_stream_filter_disable (cdk_stream_t s, int type) @@ -810,11 +819,12 @@ _cdk_stream_get_opaque (cdk_stream_t s, int fid) /** - * cdk_stream_read: Try to read count bytes from the STREAM object. + * cdk_stream_read: * @s: The STREAM object. * @buf: The buffer to insert the readed bytes. * @count: Request so much bytes. * + * Tries to read count bytes from the STREAM object. * When this function is called the first time, it can take a while * because all filters need to be processed. Please remember that you * need to add the filters in reserved order. @@ -892,11 +902,12 @@ cdk_stream_getc (cdk_stream_t s) /** - * cdk_stream_write: Try to write count bytes into the stream. + * cdk_stream_write: * @s: The STREAM object * @buf: The buffer with the values to write. * @count: The size of the buffer. * + * Tries to write count bytes into the stream. * In this function we simply write the bytes to the stream. We can't * use the filters here because it would mean they have to support * partial flushing. @@ -1108,6 +1119,8 @@ cdk_stream_set_cipher_flag (cdk_stream_t s, cdk_dek_t dek, int use_mdc) _cdk_log_debug ("stream: enable cipher mode\n"); if (!s) return CDK_Inv_Value; + +#if 0 f = filter_add (s, _cdk_filter_cipher, fCIPHER); if (!f) return CDK_Out_Of_Core; @@ -1121,6 +1134,9 @@ cdk_stream_set_cipher_flag (cdk_stream_t s, cdk_dek_t dek, int use_mdc) f->u.cfx.blkmode.size = s->blkmode; } return 0; +#endif + + return CDK_Not_Implemented; } @@ -1140,6 +1156,9 @@ cdk_stream_set_compress_flag (cdk_stream_t s, int algo, int level) { struct stream_filter_s *f; + return CDK_Not_Implemented; + +#if 0 if (!s) return CDK_Inv_Value; f = filter_add (s, _cdk_filter_compress, fCOMPRESS); @@ -1149,6 +1168,7 @@ cdk_stream_set_compress_flag (cdk_stream_t s, int algo, int level) f->u.zfx.algo = algo; f->u.zfx.level = level; return 0; +#endif } @@ -1207,7 +1227,7 @@ cdk_stream_set_hash_flag (cdk_stream_t s, int digest_algo) * @s: the stream object * @val: 1=on, 0=off * - * Enable or disable the cache section of a stream object. + * Enables or disable the cache section of a stream object. **/ cdk_error_t cdk_stream_enable_cache (cdk_stream_t s, int val) @@ -1292,34 +1312,49 @@ cdk_stream_kick_off (cdk_stream_t inp, cdk_stream_t out) * @ret_buf: the buffer to store the content * @ret_buflen: length of the buffer * - * Map the data of the given stream into a memory section. @ret_count + * Maps the data of the given stream into a memory section. @ret_count * contains the length of the buffer. **/ cdk_error_t cdk_stream_mmap_part (cdk_stream_t s, off_t off, size_t len, byte **ret_buf, size_t *ret_buflen) { - off_t oldpos; - int n; cdk_error_t rc; + off_t oldpos; + int n; - if (!s || !ret_buf || !ret_buflen) + if (!ret_buf || !ret_buflen) + return CDK_Inv_Value; + *ret_buf = NULL; + *ret_buflen = 0; + + if (!s) return CDK_Inv_Value; + + /* Memory mapping is not supported on custom I/O objects. */ if (s->cbs_hd) - return CDK_Inv_Mode; + { + _cdk_log_debug ("cdk_stream_mmap_part: not supported on callbacks\n"); + return CDK_Inv_Mode; + } - *ret_buflen = 0; - *ret_buf = NULL; oldpos = cdk_stream_tell (s); rc = cdk_stream_flush (s); - if (!rc) - rc = cdk_stream_seek (s, off); + if (rc) + return rc; + rc = cdk_stream_seek (s, off); if (rc) return rc; if (!len) len = cdk_stream_get_length (s); - if (!len || len > MAX_MAP_SIZE) - return 0; + if (!len) + { + _cdk_log_debug ("cdk_stream_mmap_part: invalid file size %lu\n", len); + return s->error; + } + if (len > MAX_MAP_SIZE) + return CDK_Too_Short; + *ret_buf = cdk_calloc (1, len+1); *ret_buflen = len; n = cdk_stream_read (s, *ret_buf, len); diff --git a/libextra/opencdk/stream.h b/lib/opencdk/stream.h index df44c6c6b8..df44c6c6b8 100644 --- a/libextra/opencdk/stream.h +++ b/lib/opencdk/stream.h diff --git a/libextra/opencdk/types.h b/lib/opencdk/types.h index c53a0850ae..c53a0850ae 100644 --- a/libextra/opencdk/types.h +++ b/lib/opencdk/types.h diff --git a/libextra/opencdk/verify.c b/lib/opencdk/verify.c index de6a50ebb9..0f4c7bc859 100644 --- a/libextra/opencdk/verify.c +++ b/lib/opencdk/verify.c @@ -3,15 +3,20 @@ * * This file is part of OpenCDK. * - * OpenCDK is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * OpenCDK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * The OpenCDK library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA */ #ifdef HAVE_CONFIG_H # include <config.h> diff --git a/libextra/opencdk/write-packet.c b/lib/opencdk/write-packet.c index 6b8f8eaecb..fb1146e1dd 100644 --- a/libextra/opencdk/write-packet.c +++ b/lib/opencdk/write-packet.c @@ -3,15 +3,20 @@ * * This file is part of OpenCDK. * - * OpenCDK is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * OpenCDK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * The OpenCDK library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA */ #ifdef HAVE_CONFIG_H #include <config.h> diff --git a/lib/openpgp/Makefile.am b/lib/openpgp/Makefile.am new file mode 100644 index 0000000000..93c479ee9f --- /dev/null +++ b/lib/openpgp/Makefile.am @@ -0,0 +1,50 @@ +## Process this file with automake to produce Makefile.in +# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation +# +# Author: Nikos Mavrogiannopoulos +# +# This file is part of GNUTLS-EXTRA. +# +# GNUTLS-EXTRA is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3 of the +# License, or (at your option) any later version. +# +# GNUTLS-EXTRA is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNUTLS-EXTRA; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +AM_CPPFLAGS = -I$(top_srcdir)/lgl -I$(top_builddir)/lgl \ + -I$(top_srcdir)/crypto -I$(top_srcdir)/lib \ + -I$(top_srcdir)/includes -I../../includes \ + -I$(top_srcdir)/lib/opencdk + +if ENABLE_MINITASN1 +AM_CPPFLAGS += -I$(top_srcdir)/lib/minitasn1 +else +AM_CPPFLAGS += $(LIBTASN1_CFLAGS) +endif + +noinst_LTLIBRARIES = libgnutls_openpgp.la + +COBJECTS = pgp.c pgpverify.c extras.c compat.c privkey.c output.c + +libgnutls_openpgp_la_SOURCES = $(COBJECTS) openpgp.h gnutls_openpgp.h + +EXTRA_DIST = pgp-api.texi + +pgp-api.texi: $(COBJECTS) + @echo "" > pgp-api.texi + @for i in ../gnutls_openpgp.c $(COBJECTS); do \ + echo -n "Creating documentation for file $$i... " && \ + $(top_srcdir)/doc/scripts/gdoc -texinfo $$i >> pgp-api.texi && \ + echo "ok"; \ + done + +dist-hook: pgp-api.texi diff --git a/lib/openpgp/compat.c b/lib/openpgp/compat.c new file mode 100644 index 0000000000..c04d861ab7 --- /dev/null +++ b/lib/openpgp/compat.c @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation + * + * Author: Timo Schulz, Nikos Mavrogiannopoulos + * + * This file is part of GNUTLS-EXTRA. + * + * GNUTLS-EXTRA is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNUTLS-EXTRA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* Compatibility functions on OpenPGP key parsing. + */ + +#include <gnutls_int.h> +#include <gnutls_errors.h> +#include <gnutls_openpgp.h> +#include <openpgp.h> + +/*- + * gnutls_openpgp_verify_key - Verify all signatures on the key + * @cert_list: the structure that holds the certificates. + * @cert_list_lenght: the items in the cert_list. + * @status: the output of the verification function + * + * Verify all signatures in the certificate list. When the key + * is not available, the signature is skipped. + * + * The return value is one of the CertificateStatus entries. + * + * NOTE: this function does not verify using any "web of trust". You + * may use GnuPG for that purpose, or any other external PGP application. + -*/ +int +_gnutls_openpgp_verify_key (const gnutls_certificate_credentials_t cred, + const gnutls_datum_t * cert_list, + int cert_list_length, unsigned int *status) +{ + int ret = 0; + gnutls_openpgp_crt_t key = NULL; + unsigned int verify = 0, verify_self = 0; + + if (!cert_list || cert_list_length != 1) + { + gnutls_assert (); + return GNUTLS_E_NO_CERTIFICATE_FOUND; + } + + ret = gnutls_openpgp_crt_init (&key); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + ret = gnutls_openpgp_crt_import (key, &cert_list[0], GNUTLS_OPENPGP_FMT_RAW); + if (ret < 0) + { + gnutls_assert (); + goto leave; + } + +#ifndef KEYRING_HACK + if (cred->keyring != NULL) + { + ret = gnutls_openpgp_crt_verify_ring (key, cred->keyring, 0, &verify); + if (ret < 0) + { + gnutls_assert (); + 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); + if (ret < 0) + { + gnutls_assert (); + goto leave; + } + + *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: + gnutls_openpgp_crt_deinit (key); + + return ret; +} + +/*- + * gnutls_openpgp_fingerprint - Gets the fingerprint + * @cert: the raw data that contains the OpenPGP public key. + * @fpr: the buffer to save the fingerprint. + * @fprlen: the integer to save the length of the fingerprint. + * + * Returns the fingerprint of the OpenPGP key. Depence on the algorithm, + * the fingerprint can be 16 or 20 bytes. + -*/ +int +_gnutls_openpgp_fingerprint (const gnutls_datum_t * cert, + unsigned char *fpr, size_t * fprlen) +{ + gnutls_openpgp_crt_t key; + int ret; + + ret = gnutls_openpgp_crt_init (&key); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + ret = gnutls_openpgp_crt_import (key, cert, GNUTLS_OPENPGP_FMT_RAW); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + ret = gnutls_openpgp_crt_get_fingerprint (key, fpr, fprlen); + gnutls_openpgp_crt_deinit (key); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + return 0; +} + +/*- + * gnutls_openpgp_get_raw_key_creation_time - Extract the timestamp + * @cert: the raw data that contains the OpenPGP public key. + * + * Returns the timestamp when the OpenPGP key was created. + -*/ +time_t +_gnutls_openpgp_get_raw_key_creation_time (const gnutls_datum_t * cert) +{ + gnutls_openpgp_crt_t key; + int ret; + time_t tim; + + ret = gnutls_openpgp_crt_init (&key); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + ret = gnutls_openpgp_crt_import (key, cert, GNUTLS_OPENPGP_FMT_RAW); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + tim = gnutls_openpgp_crt_get_creation_time (key); + + gnutls_openpgp_crt_deinit (key); + + return tim; +} + + +/*- + * gnutls_openpgp_get_raw_key_expiration_time - Extract the expire date + * @cert: the raw data that contains the OpenPGP public key. + * + * Returns the time when the OpenPGP key expires. A value of '0' means + * that the key doesn't expire at all. + -*/ +time_t +_gnutls_openpgp_get_raw_key_expiration_time (const gnutls_datum_t * cert) +{ + gnutls_openpgp_crt_t key; + int ret; + time_t tim; + + ret = gnutls_openpgp_crt_init (&key); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + ret = gnutls_openpgp_crt_import (key, cert, GNUTLS_OPENPGP_FMT_RAW); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + tim = gnutls_openpgp_crt_get_expiration_time (key); + + gnutls_openpgp_crt_deinit (key); + + return tim; +} diff --git a/lib/openpgp/extras.c b/lib/openpgp/extras.c new file mode 100644 index 0000000000..2ce4ce256d --- /dev/null +++ b/lib/openpgp/extras.c @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation + * + * Author: Nikos Mavrogiannopoulos, Timo Schulz + * + * This file is part of GNUTLS-EXTRA. + * + * GNUTLS-EXTRA is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNUTLS-EXTRA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* Functions on OpenPGP keyring parsing + */ + +#include <gnutls_int.h> +#include <gnutls_datum.h> +#include <gnutls_global.h> +#include <gnutls_errors.h> +#include <gnutls_openpgp.h> +#include <gnutls_num.h> +#include <openpgp.h> + +/* Keyring stuff. + */ + +/** + * gnutls_openpgp_keyring_init - This function initializes a gnutls_openpgp_keyring_t structure + * @keyring: The structure to be initialized + * + * This function will initialize an OpenPGP keyring structure. + * + * Returns 0 on success. + * + **/ +int +gnutls_openpgp_keyring_init (gnutls_openpgp_keyring_t * keyring) +{ + *keyring = gnutls_calloc (1, sizeof (gnutls_openpgp_keyring_int)); + + if (*keyring) + return 0; /* success */ + return GNUTLS_E_MEMORY_ERROR; +} + + +/** + * gnutls_openpgp_keyring_deinit - This function deinitializes memory used by a gnutls_openpgp_keyring_t structure + * @keyring: The structure to be initialized + * + * This function will deinitialize a keyring structure. + * + **/ +void +gnutls_openpgp_keyring_deinit (gnutls_openpgp_keyring_t keyring) +{ + if (!keyring) + return; + + if (keyring->db) + { + cdk_keydb_free (keyring->db); + keyring->db = NULL; + } + + /* In some cases the stream is also stored outside the keydb context + and we need to close it here then. */ + if (keyring->db_stream) + { + cdk_stream_close (keyring->db_stream); + keyring->db_stream = NULL; + } + + gnutls_free (keyring); +} + +/** + * gnutls_openpgp_keyring_check_id - Check if a key id exists in the keyring + * @ring: holds the keyring to check against + * @keyid: will hold the keyid to check for. + * @flags: unused (should be 0) + * + * Check if a given key ID exists in the keyring. + * + * Returns 0 on success (if keyid exists) and a negative error code + * on failure. + **/ +int +gnutls_openpgp_keyring_check_id (gnutls_openpgp_keyring_t ring, + gnutls_openpgp_keyid_t keyid, + unsigned int flags) +{ + cdk_pkt_pubkey_t pk; + uint32_t id[2]; + + id[0] = _gnutls_read_uint32 (keyid.keyid); + id[1] = _gnutls_read_uint32 (&keyid.keyid[4]); + + if (!cdk_keydb_get_pk (ring->db, id, &pk)) + { + cdk_pk_release (pk); + return 0; + } + + _gnutls_debug_log ("PGP: key not found %08lX\n", (unsigned long)id[1]); + return GNUTLS_E_NO_CERTIFICATE_FOUND; +} + +/** + * gnutls_openpgp_keyring_import - Import a raw- or Base64-encoded OpenPGP keyring + * @keyring: The structure to store the parsed key. + * @data: The RAW or BASE64 encoded keyring. + * @format: One of #gnutls_openpgp_keyring_fmt elements. + * + * This function will convert the given RAW or Base64 encoded keyring to the + * native #gnutls_openpgp_keyring_t format. The output will be stored in + * 'keyring'. + * + * Returns 0 on success. + * + **/ +int +gnutls_openpgp_keyring_import (gnutls_openpgp_keyring_t keyring, + const gnutls_datum_t *data, + gnutls_openpgp_crt_fmt_t format) +{ + cdk_error_t err; + cdk_stream_t input; + + _gnutls_debug_log ("PGP: keyring import format '%s'\n", + format == GNUTLS_OPENPGP_FMT_RAW? "raw" : "base64"); + + if (format == GNUTLS_OPENPGP_FMT_RAW) + { + err = cdk_keydb_new (&keyring->db, CDK_DBTYPE_DATA, + data->data, data->size); + if (err) + gnutls_assert (); + return _gnutls_map_cdk_rc (err); + } + + /* Create a new stream from the given data, which means to + allocate a new stream and to write the data in the stream. + Then push the armor filter to decode the data and to store + it in the raw format. */ + err = cdk_stream_tmp_from_mem (data->data, data->size, &input); + if (!err) + err = cdk_stream_set_armor_flag (input, 0); + if (!err) + err = cdk_keydb_new_from_stream (&keyring->db, 0, input); + if (err) + { + cdk_stream_close (input); + gnutls_assert (); + } + else + /* The keydb function will not close the stream itself, so we need to + store it separately to close it later. */ + keyring->db_stream = input; + + return _gnutls_map_cdk_rc (err); +} + diff --git a/lib/openpgp/gnutls_openpgp.h b/lib/openpgp/gnutls_openpgp.h new file mode 100644 index 0000000000..067de99831 --- /dev/null +++ b/lib/openpgp/gnutls_openpgp.h @@ -0,0 +1,99 @@ +#include <config.h> + +#ifdef ENABLE_OPENPGP + +#ifndef GNUTLS_OPENPGP_LOCAL_H +#define GNUTLS_OPENPGP_LOCAL_H + +#include <auth_cert.h> +#include <opencdk.h> + +typedef struct +{ + int type; + size_t size; + uint8_t *data; +} keybox_blob; + +typedef enum +{ + KBX_BLOB_FILE = 0x00, + KBX_BLOB_DATA = 0x01 +} keyring_blob_types; + +/* OpenCDK compatible */ +typedef enum +{ + KEY_ATTR_NONE = 0, + KEY_ATTR_SHORT_KEYID = 3, + KEY_ATTR_KEYID = 4, + KEY_ATTR_FPR = 5 +} key_attr_t; + +int +gnutls_certificate_set_openpgp_key_file (gnutls_certificate_credentials_t + res, const char *CERTFILE, + const char *KEYFILE, gnutls_openpgp_crt_fmt_t); + +int 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_openpgp_crt_fmt_t); + +int +gnutls_certificate_set_openpgp_keyring_mem (gnutls_certificate_credentials_t + c, const opaque * data, + size_t dlen, gnutls_openpgp_crt_fmt_t); + +int gnutls_openpgp_get_key (gnutls_datum_t * key, + gnutls_openpgp_keyring_t keyring, + key_attr_t by, opaque * pattern); + +int gnutls_openpgp_recv_key (const char *host, + short port, uint32_t keyid, + gnutls_datum_t * key); + +/* internal */ +int _gnutls_openpgp_raw_crt_to_gcert (gnutls_cert * cert, + const gnutls_datum_t * raw); + +int +_gnutls_openpgp_raw_privkey_to_gkey (gnutls_privkey * pkey, + const gnutls_datum_t * raw_key); + +int +_gnutls_openpgp_request_key (gnutls_session_t, + gnutls_datum_t * ret, + const gnutls_certificate_credentials_t cred, + opaque * key_fpr, int key_fpr_size); + +int _gnutls_openpgp_verify_key (const gnutls_certificate_credentials_t, + const gnutls_datum_t * cert_list, + int cert_list_length, unsigned int *status); +int _gnutls_openpgp_fingerprint (const gnutls_datum_t * cert, + unsigned char *fpr, size_t * fprlen); +time_t _gnutls_openpgp_get_raw_key_creation_time (const gnutls_datum_t * + cert); +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); + +int _gnutls_openpgp_find_valid_subkey( gnutls_openpgp_crt_t crt, gnutls_openpgp_keyid_t* keyid); + +#endif /*GNUTLS_OPENPGP_LOCAL_H */ + +#endif /*ENABLE_OPENPGP */ diff --git a/lib/openpgp/openpgp.h b/lib/openpgp/openpgp.h new file mode 100644 index 0000000000..3ec9ba9111 --- /dev/null +++ b/lib/openpgp/openpgp.h @@ -0,0 +1,107 @@ +#ifndef OPENPGP_LOCAL_H +# define OPENPGP_LOCAL_H + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef ENABLE_OPENPGP + +#include <opencdk.h> +#include <gnutls/openpgp.h> + +#define KEYID_IMPORT(dst, src) \ + dst[0] = _gnutls_read_uint32( src.keyid); \ + dst[1] = _gnutls_read_uint32( src.keyid+4) + +/* Internal context to store the OpenPGP key. */ +typedef struct gnutls_openpgp_crt_int +{ + cdk_kbnode_t knode; +} gnutls_openpgp_crt_int; + +/* Internal context to store the private OpenPGP key. */ +typedef struct gnutls_openpgp_privkey_int +{ + cdk_kbnode_t knode; +} gnutls_openpgp_privkey_int; + + +typedef struct gnutls_openpgp_keyring_int +{ + cdk_keydb_hd_t db; + cdk_stream_t db_stream; +} gnutls_openpgp_keyring_int; + +int _gnutls_map_cdk_rc (int rc); +int gnutls_openpgp_crt_get_name (gnutls_openpgp_crt_t key, + int idx, char *buf, size_t * sizeof_buf); +int gnutls_openpgp_crt_get_fingerprint (gnutls_openpgp_crt_t key, + void *fpr, size_t * fprlen); +gnutls_pk_algorithm_t +gnutls_openpgp_crt_get_pk_algorithm (gnutls_openpgp_crt_t key, + unsigned int *bits); +int gnutls_openpgp_crt_get_version (gnutls_openpgp_crt_t key); +time_t gnutls_openpgp_crt_get_creation_time (gnutls_openpgp_crt_t key); +time_t gnutls_openpgp_crt_get_expiration_time (gnutls_openpgp_crt_t key); +int gnutls_openpgp_crt_get_id (gnutls_openpgp_crt_t key, + gnutls_openpgp_keyid_t* keyid); + +int gnutls_openpgp_crt_init (gnutls_openpgp_crt_t * key); +void gnutls_openpgp_crt_deinit (gnutls_openpgp_crt_t key); +int gnutls_openpgp_crt_import (gnutls_openpgp_crt_t key, + const gnutls_datum_t * data, + gnutls_openpgp_crt_fmt_t format); +int gnutls_openpgp_crt_export (gnutls_openpgp_crt_t key, + gnutls_openpgp_crt_fmt_t format, + void *output_data, size_t * output_data_size); + +void gnutls_openpgp_keyring_deinit (gnutls_openpgp_keyring_t keyring); +int gnutls_openpgp_keyring_init (gnutls_openpgp_keyring_t * keyring); +int gnutls_openpgp_keyring_import (gnutls_openpgp_keyring_t keyring, + const gnutls_datum_t * data, + gnutls_openpgp_crt_fmt_t format); +int gnutls_openpgp_keyring_check_id (gnutls_openpgp_keyring_t ring, + gnutls_openpgp_keyid_t keyid, + unsigned int flags); + +int gnutls_openpgp_crt_verify_ring (gnutls_openpgp_crt_t key, + gnutls_openpgp_keyring_t keyring, + unsigned int flags, unsigned int *verify); + +int gnutls_openpgp_crt_verify_self (gnutls_openpgp_crt_t key, + unsigned int flags, unsigned int *verify); + +int _gnutls_openpgp_crt_to_gcert (gnutls_cert * gcert, + gnutls_openpgp_crt_t cert, gnutls_openpgp_keyid_t keyid); +int _gnutls_openpgp_privkey_to_gkey (gnutls_privkey * dest, + gnutls_openpgp_privkey_t src, gnutls_openpgp_keyid_t); + +void gnutls_openpgp_privkey_deinit (gnutls_openpgp_privkey_t key); + +cdk_packet_t _gnutls_get_valid_subkey(cdk_kbnode_t knode, int key_type); + +unsigned int _gnutls_get_pgp_key_usage(unsigned int pgp_usage); + +int +_gnutls_openpgp_crt_get_mpis (gnutls_openpgp_crt_t cert, uint32_t keyid[2], + mpi_t * params, int *params_size); + +int +_gnutls_openpgp_privkey_get_mpis (gnutls_openpgp_privkey_t pkey, uint32_t keyid[2], + mpi_t * params, int *params_size); + +cdk_packet_t _gnutls_openpgp_find_key( cdk_kbnode_t knode, uint32_t keyid[2], unsigned int priv); + +int _gnutls_read_pgp_mpi( cdk_packet_t pkt, unsigned int priv, size_t idx, mpi_t* m); + +int _gnutls_openpgp_find_subkey_idx( cdk_kbnode_t knode, uint32_t keyid[2], + unsigned int priv); + +#else /* no opencdk */ + +typedef void *gnutls_openpgp_keyring_t; + +#endif /* ENABLE_OPENPGP */ + +#endif /* OPENPGP_LOCAL_H */ diff --git a/lib/openpgp/output.c b/lib/openpgp/output.c new file mode 100644 index 0000000000..71b997133f --- /dev/null +++ b/lib/openpgp/output.c @@ -0,0 +1,402 @@ +/* + * Copyright (C) 2007 Free Software Foundation + * + * Author: Simon Josefsson, Nikos Mavrogiannopoulos + * + * This file is part of GNUTLS. + * + * The GNUTLS library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +/* Functions for printing X.509 Certificate structures + */ + +#include <gnutls_int.h> +#include <gnutls/openpgp.h> +#include <gnutls_errors.h> + +/* I18n of error codes. */ +#include "gettext.h" +#define _(String) dgettext (PACKAGE, String) +#define N_(String) gettext_noop (String) + +#define addf _gnutls_string_append_printf +#define adds _gnutls_string_append_str + +static void +hexdump (gnutls_string * str, const char *data, size_t len, const char *spc) +{ + size_t j; + + if (spc) + adds (str, spc); + for (j = 0; j < len; j++) + { + if (((j + 1) % 16) == 0) + { + addf (str, "%.2x\n", (unsigned char) data[j]); + if (spc && j != (len - 1)) + adds (str, spc); + } + else if (j == (len - 1)) + addf (str, "%.2x", (unsigned char) data[j]); + else + addf (str, "%.2x:", (unsigned char) data[j]); + } + if ((j % 16) != 0) + adds (str, "\n"); +} + +static void +hexprint (gnutls_string * str, const char *data, size_t len) +{ + size_t j; + + if (len == 0) + adds (str, "00"); + else + { + for (j = 0; j < len; j++) + addf (str, "%.2x", (unsigned char) data[j]); + } +} + + +static void +asciiprint (gnutls_string * str, const char *data, size_t len) +{ + size_t j; + + for (j = 0; j < len; j++) + if (isprint (data[j])) + addf (str, "%c", (unsigned char) data[j]); + else + addf (str, "."); +} + +static void +print_key_usage (gnutls_string * str, gnutls_openpgp_crt_t cert, unsigned int idx) +{ + unsigned int key_usage; + int err; + + addf (str, _("\t\tKey Usage:\n")); + + + if (idx == -1) + err = gnutls_openpgp_crt_get_key_usage (cert, &key_usage); + else + err = gnutls_openpgp_crt_get_subkey_usage (cert, idx, &key_usage); + if (err < 0) + { + addf (str, _("error: get_key_usage: %s\n"), gnutls_strerror (err)); + return; + } + + if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) + addf (str, _("\t\t\tDigital signature.\n")); + if (key_usage & GNUTLS_KEY_NON_REPUDIATION) + addf (str, _("\t\t\tNon repudiation.\n")); + if (key_usage & GNUTLS_KEY_KEY_ENCIPHERMENT) + addf (str, _("\t\t\tKey encipherment.\n")); + if (key_usage & GNUTLS_KEY_DATA_ENCIPHERMENT) + addf (str, _("\t\t\tData encipherment.\n")); + if (key_usage & GNUTLS_KEY_KEY_AGREEMENT) + addf (str, _("\t\t\tKey agreement.\n")); + if (key_usage & GNUTLS_KEY_KEY_CERT_SIGN) + addf (str, _("\t\t\tCertificate signing.\n")); + if (key_usage & GNUTLS_KEY_CRL_SIGN) + addf (str, _("\t\t\tCRL signing.\n")); + if (key_usage & GNUTLS_KEY_ENCIPHER_ONLY) + addf (str, _("\t\t\tKey encipher only.\n")); + if (key_usage & GNUTLS_KEY_DECIPHER_ONLY) + addf (str, _("\t\t\tKey decipher only.\n")); +} + +/* idx == -1 indicates main key + * otherwise the subkey. + */ +static void +print_key_id (gnutls_string * str, gnutls_openpgp_crt_t cert, int idx) +{ + gnutls_openpgp_keyid_t id; + int err; + + if (idx < 0) + err = gnutls_openpgp_crt_get_id (cert, &id); + else + err = gnutls_openpgp_crt_get_subkey_id( cert, idx, &id); + + if (err < 0) + addf (str, "error: get_id: %s\n", gnutls_strerror (err)); + else + { + addf (str, _("\tID (hex): ")); + hexprint (str, id.keyid, sizeof(id.keyid)); + addf (str, "\n"); + } +} + +/* idx == -1 indicates main key + * otherwise the subkey. + */ +static void +print_key_fingerprint (gnutls_string * str, gnutls_openpgp_crt_t cert) +{ + char fpr[128]; + size_t fpr_size = sizeof (fpr); + int err; + + err = gnutls_openpgp_crt_get_fingerprint (cert, fpr, &fpr_size); + if (err < 0) + addf (str, "error: get_fingerprint: %s\n", gnutls_strerror (err)); + else + { + addf (str, _("\tFingerprint (hex): ")); + hexprint (str, fpr, fpr_size); + addf (str, "\n"); + } +} + +static void +print_key_revoked (gnutls_string * str, gnutls_openpgp_crt_t cert, int idx) +{ + char fpr[128]; + size_t fpr_size = sizeof (fpr); + int err; + + if (idx < 0) + err = gnutls_openpgp_crt_get_revoked_status (cert); + else + err = gnutls_openpgp_crt_get_subkey_revoked_status( cert, idx); + + if (err != 0) + addf (str, "Revoked: True"); +} + +static void +print_key_times(gnutls_string * str, gnutls_openpgp_crt_t cert, int idx) +{ + time_t tim; + + addf (str, _("\tTime stamps:\n")); + + if (idx == -1) + tim = gnutls_openpgp_crt_get_creation_time (cert); + else + tim = gnutls_openpgp_crt_get_subkey_creation_time (cert, idx); + + { + char s[42]; + size_t max = sizeof (s); + struct tm t; + + if (gmtime_r (&tim, &t) == NULL) + addf (str, "error: gmtime_r (%d)\n", t); + else if (strftime (s, max, "%a %b %e %H:%M:%S UTC %Y", &t) == 0) + addf (str, "error: strftime (%d)\n", t); + else + addf (str, _("\t\tCreation: %s\n"), s); + } + + if (idx == -1) + tim = gnutls_openpgp_crt_get_expiration_time (cert); + else + tim = gnutls_openpgp_crt_get_subkey_expiration_time (cert, idx); + { + char s[42]; + size_t max = sizeof (s); + struct tm t; + + if (gmtime_r (&tim, &t) == NULL) + addf (str, "error: gmtime_r (%d)\n", t); + else if (strftime (s, max, "%a %b %e %H:%M:%S UTC %Y", &t) == 0) + addf (str, "error: strftime (%d)\n", t); + else + addf (str, _("\t\tExpiration: %s\n"), s); + } +} + +static void +print_key_info(gnutls_string * str, gnutls_openpgp_crt_t cert, int idx) +{ + int err; + unsigned int bits; + + if (idx == -1) + err = gnutls_openpgp_crt_get_pk_algorithm (cert, &bits); + else + err = gnutls_openpgp_crt_get_subkey_pk_algorithm (cert, idx, &bits); + + if (err < 0) + addf (str, "error: get_pk_algorithm: %s\n", gnutls_strerror (err)); + else + { + const char *name = gnutls_pk_algorithm_get_name (err); + if (name == NULL) + name = "Unknown"; + + addf (str, _("\tPublic Key Algorithm: %s\n"), name); +#if 0 + switch (err) + { + case GNUTLS_PK_RSA: + { + gnutls_datum_t m, e; + + err = gnutls_openpgp_crt_get_pk_rsa_raw (cert, &m, &e); + if (err < 0) + addf (str, "error: get_pk_rsa_raw: %s\n", + gnutls_strerror (err)); + else + { + addf (str, _("\t\tModulus (bits %d):\n"), bits); + hexdump (str, m.data, m.size, "\t\t\t"); + addf (str, _("\t\tExponent:\n")); + hexdump (str, e.data, e.size, "\t\t\t"); + } + + gnutls_free (m.data); + gnutls_free (e.data); + } + break; + + case GNUTLS_PK_DSA: + { + gnutls_datum_t p, q, g, y; + + err = gnutls_openpgp_crt_get_pk_dsa_raw (cert, &p, &q, &g, &y); + if (err < 0) + addf (str, "error: get_pk_dsa_raw: %s\n", + gnutls_strerror (err)); + else + { + addf (str, _("\t\tPublic key (bits %d):\n"), bits); + hexdump (str, y.data, y.size, "\t\t\t"); + addf (str, _("\t\tP:\n")); + hexdump (str, p.data, p.size, "\t\t\t"); + addf (str, _("\t\tQ:\n")); + hexdump (str, q.data, q.size, "\t\t\t"); + addf (str, _("\t\tG:\n")); + hexdump (str, g.data, g.size, "\t\t\t"); + } + } + break; + + default: + break; + } +#endif + } +} + + +static void +print_cert (gnutls_string * str, gnutls_openpgp_crt_t cert, unsigned int format) +{ +int i, subkeys; +int err; +char dn[1024]; +size_t dn_size = sizeof (dn); + + /* Version. */ + { + int version = gnutls_openpgp_crt_get_version (cert); + if (version < 0) + addf (str, "error: get_version: %s\n", gnutls_strerror (version)); + else + addf (str, _("\tVersion: %d\n"), version); + } + + /* ID. */ + print_key_id( str, cert, -1); + + print_key_fingerprint( str, cert); + + /* Names. */ + i = 0; + do { + + err = gnutls_openpgp_crt_get_name (cert, i++, dn, &dn_size); + + if (err < 0 && err != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { + addf (str, "error: get_name: %s\n", gnutls_strerror (err)); + break; + } + + if (err > 0) + addf (str, _("\tName[%d]: %s\n"), i, dn); + + } while( err > 0); + + print_key_times( str, cert, -1); + + print_key_info( str, cert, -1); + print_key_usage( str, cert, -1); + print_key_revoked( str, cert, -1); + + subkeys = gnutls_openpgp_crt_get_subkey_count( cert); + if (subkeys < 0) + return; + + for (i=0;i<subkeys;i++) { + addf( str, _("\n\tSubkey[%d]:\n"), i); + + print_key_id( str, cert, i); + print_key_times( str, cert, i); + print_key_info( str, cert, i); + print_key_usage( str, cert, i); + print_key_revoked( str, cert, i); + } + +} + +/** + * gnutls_openpgp_crt_print - Pretty print OpenPGP certificates + * @cert: The structure to be printed + * @format: Indicate the format to use + * @out: Newly allocated datum with zero terminated string. + * + * This function will pretty print an OpenPGP certificate, suitable for + * display to a human. + * + * The format should be zero for future compatibility. + * + * The output @out needs to be deallocate using gnutls_free(). + * + * Returns 0 on success. + **/ +int +gnutls_openpgp_crt_print (gnutls_openpgp_crt_t cert, + gnutls_certificate_print_formats_t format, + gnutls_datum_t *out) +{ + gnutls_string str; + + _gnutls_string_init (&str, gnutls_malloc, gnutls_realloc, gnutls_free); + + _gnutls_string_append_str (&str, _("OpenPGP Certificate Information:\n")); + + print_cert (&str, cert, format); + + _gnutls_string_append_data (&str, "\0", 1); + out->data = str.data; + out->size = strlen (str.data); + + return 0; +} + diff --git a/lib/openpgp/pgp.c b/lib/openpgp/pgp.c new file mode 100644 index 0000000000..e0f0472bf6 --- /dev/null +++ b/lib/openpgp/pgp.c @@ -0,0 +1,1079 @@ +/* + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation + * + * Author: Timo Schulz, Nikos Mavrogiannopoulos + * + * This file is part of GNUTLS-EXTRA. + * + * GNUTLS-EXTRA is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNUTLS-EXTRA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* Functions on OpenPGP key parsing + */ + +#include <gnutls_int.h> +#include <gnutls_datum.h> +#include <gnutls_global.h> +#include <gnutls_errors.h> +#include <openpgp.h> +#include <x509/rfc2818.h> +#include <gnutls_num.h> + +/** + * gnutls_openpgp_crt_init - This function initializes a gnutls_openpgp_crt_t structure + * @key: The structure to be initialized + * + * This function will initialize an OpenPGP key structure. + * + * Returns 0 on success. + * + **/ +int +gnutls_openpgp_crt_init (gnutls_openpgp_crt_t * key) +{ + *key = gnutls_calloc (1, sizeof (gnutls_openpgp_crt_int)); + + if (*key) + return 0; /* success */ + return GNUTLS_E_MEMORY_ERROR; +} + +/** + * gnutls_openpgp_crt_deinit - This function deinitializes memory used by a gnutls_openpgp_crt_t structure + * @key: The structure to be initialized + * + * This function will deinitialize a key structure. + **/ +void +gnutls_openpgp_crt_deinit (gnutls_openpgp_crt_t key) +{ + if (!key) + return; + + if (key->knode) + { + cdk_kbnode_release (key->knode); + key->knode = NULL; + } + + gnutls_free (key); +} + +/** + * gnutls_openpgp_crt_import - This function will import a RAW or BASE64 encoded key + * @key: The structure to store the parsed key. + * @data: The RAW or BASE64 encoded key. + * @format: One of gnutls_openpgp_crt_fmt_t elements. + * + * This function will convert the given RAW or Base64 encoded key + * to the native gnutls_openpgp_crt_t format. The output will be stored in 'key'. + * + * Returns 0 on success. + **/ +int +gnutls_openpgp_crt_import (gnutls_openpgp_crt_t key, + const gnutls_datum_t * data, + gnutls_openpgp_crt_fmt_t format) +{ + cdk_stream_t inp; + int rc; + + if (format == GNUTLS_OPENPGP_FMT_RAW) + rc = cdk_kbnode_read_from_mem (&key->knode, data->data, data->size); + else + { + rc = cdk_stream_tmp_from_mem (data->data, data->size, &inp); + if (rc) + { + rc = _gnutls_map_cdk_rc (rc); + gnutls_assert (); + return rc; + } + if (cdk_armor_filter_use (inp)) + rc = cdk_stream_set_armor_flag (inp, 0); + if (!rc) + rc = cdk_keydb_get_keyblock (inp, &key->knode); + cdk_stream_close (inp); + if (rc) + { + rc = _gnutls_map_cdk_rc (rc); + gnutls_assert (); + return rc; + } + } + + return 0; +} + +/** + * gnutls_openpgp_crt_export - This function will export a RAW or BASE64 encoded key + * @key: Holds the key. + * @format: One of gnutls_openpgp_crt_fmt_t elements. + * @output_data: will contain the key base64 encoded or raw + * @output_data_size: holds the size of output_data (and will be replaced by the actual size of parameters) + * + * This function will convert the given key to RAW or Base64 format. + * If the buffer provided is not long enough to hold the output, then + * GNUTLS_E_SHORT_MEMORY_BUFFER will be returned. + * + * Returns 0 on success. + * + **/ +int +gnutls_openpgp_crt_export (gnutls_openpgp_crt_t key, + gnutls_openpgp_crt_fmt_t format, + void *output_data, size_t * output_data_size) +{ + size_t input_data_size = *output_data_size; + size_t calc_size; + int rc; + + rc = cdk_kbnode_write_to_mem (key->knode, output_data, output_data_size); + if (rc) + { + rc = _gnutls_map_cdk_rc (rc); + gnutls_assert (); + return rc; + } + + /* If the caller uses output_data == NULL then return what he expects. + */ + if (!output_data) + { + gnutls_assert(); + return GNUTLS_E_SHORT_MEMORY_BUFFER; + } + + if (format == GNUTLS_OPENPGP_FMT_BASE64) + { + unsigned char *in = cdk_calloc (1, *output_data_size); + memcpy (in, output_data, *output_data_size); + + /* Calculate the size of the encoded data and check if the provided + buffer is large enough. */ + rc = cdk_armor_encode_buffer (in, *output_data_size, + NULL, 0, &calc_size, CDK_ARMOR_PUBKEY); + if (rc || calc_size > input_data_size) + { + cdk_free (in); + *output_data_size = calc_size; + gnutls_assert (); + return GNUTLS_E_SHORT_MEMORY_BUFFER; + } + + rc = cdk_armor_encode_buffer (in, *output_data_size, + output_data, input_data_size, &calc_size, + CDK_ARMOR_PUBKEY); + cdk_free (in); + *output_data_size = calc_size; + } + + return 0; +} + + +/** + * gnutls_openpgp_crt_get_fingerprint - Gets the fingerprint + * @key: the raw data that contains the OpenPGP public key. + * @fpr: the buffer to save the fingerprint, must hold at least 20 bytes. + * @fprlen: the integer to save the length of the fingerprint. + * + * Returns the fingerprint of the OpenPGP key. Depends on the algorithm, + * the fingerprint can be 16 or 20 bytes. + **/ +int +gnutls_openpgp_crt_get_fingerprint (gnutls_openpgp_crt_t key, + void *fpr, size_t * fprlen) +{ + cdk_packet_t pkt; + cdk_pkt_pubkey_t pk = NULL; + + if (!fpr || !fprlen) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + *fprlen = 0; + + pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); + if (!pkt) + return GNUTLS_E_OPENPGP_GETKEY_FAILED; + + pk = pkt->pkt.public_key; + *fprlen = 20; + + /* FIXME: Check if the draft allows old PGP keys. */ + if (is_RSA (pk->pubkey_algo) && pk->version < 4) + *fprlen = 16; + cdk_pk_get_fingerprint (pk, fpr); + + return 0; +} + +int +_gnutls_openpgp_count_key_names (gnutls_openpgp_crt_t key) +{ + cdk_kbnode_t p, ctx; + cdk_packet_t pkt; + int nuids; + + if (key == NULL) + { + gnutls_assert (); + return 0; + } + + ctx = NULL; + nuids = 0; + while ((p = cdk_kbnode_walk (key->knode, &ctx, 0))) + { + pkt = cdk_kbnode_get_packet (p); + if (pkt->pkttype == CDK_PKT_USER_ID) + nuids++; + } + + return nuids; +} + + +/** + * gnutls_openpgp_crt_get_name - Extracts the userID + * @key: the structure that contains the OpenPGP public key. + * @idx: the index of the ID to extract + * @buf: a pointer to a structure to hold the name + * @sizeof_buf: holds the maximum size of @buf, on return hold the + * actual/required size of @buf. + * + * Extracts the userID from the parsed OpenPGP key. + * + * Returns 0 on success, and GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE + * if the index of the ID does not exist. + * + **/ +int +gnutls_openpgp_crt_get_name (gnutls_openpgp_crt_t key, + int idx, char *buf, size_t * sizeof_buf) +{ + cdk_kbnode_t ctx = NULL, p; + cdk_packet_t pkt = NULL; + cdk_pkt_userid_t uid = NULL; + int pos = 0; + + if (!key || !buf) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + if (idx < 0 || idx > _gnutls_openpgp_count_key_names (key)) + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + + if (!idx) + pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_USER_ID); + else + { + pos = 0; + while ((p = cdk_kbnode_walk (key->knode, &ctx, 0))) + { + pkt = cdk_kbnode_get_packet (p); + if (pkt->pkttype == CDK_PKT_USER_ID && ++pos == idx) + break; + } + } + + if (!pkt) + { + gnutls_assert (); + return GNUTLS_E_INTERNAL_ERROR; + } + + uid = pkt->pkt.user_id; + if (uid->len >= *sizeof_buf) + { + gnutls_assert (); + *sizeof_buf = uid->len + 1; + return GNUTLS_E_SHORT_MEMORY_BUFFER; + } + + memcpy (buf, uid->name, uid->len); + buf[uid->len] = '\0'; /* make sure it's a string */ + *sizeof_buf = uid->len + 1; + + if (uid->is_revoked) + return GNUTLS_E_OPENPGP_UID_REVOKED; + + return 0; +} + +/** + * gnutls_openpgp_crt_get_pk_algorithm - This function returns the key's PublicKey algorithm + * @key: is an OpenPGP key + * @bits: if bits is non null it will hold the size of the parameters' in bits + * + * This function will return the public key algorithm of an OpenPGP + * certificate. + * + * If bits is non null, it should have enough size to hold the parameters + * size in bits. For RSA the bits returned is the modulus. + * For DSA the bits returned are of the public exponent. + * + * Returns a member of the GNUTLS_PKAlgorithm enumeration on success, + * or a negative value on error. + * + **/ +gnutls_pk_algorithm_t +gnutls_openpgp_crt_get_pk_algorithm (gnutls_openpgp_crt_t key, + unsigned int *bits) +{ + cdk_packet_t pkt; + int algo; + + if (!key) + return GNUTLS_PK_UNKNOWN; + + algo = 0; + pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); + if (pkt) + { + if (bits) + *bits = cdk_pk_get_nbits (pkt->pkt.public_key); + algo = pkt->pkt.public_key->pubkey_algo; + if (is_RSA (algo)) + algo = GNUTLS_PK_RSA; + else if (is_DSA (algo)) + algo = GNUTLS_PK_DSA; + else + algo = GNUTLS_E_UNKNOWN_PK_ALGORITHM; + } + + return algo; +} + + +/** + * gnutls_openpgp_crt_get_version - Extracts the version of the key. + * @key: the structure that contains the OpenPGP public key. + * + * Extract the version of the OpenPGP key. + **/ +int +gnutls_openpgp_crt_get_version (gnutls_openpgp_crt_t key) +{ + cdk_packet_t pkt; + int version; + + if (!key) + return -1; + + pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); + if (pkt) + version = pkt->pkt.public_key->version; + else + version = 0; + + return version; +} + + +/** + * gnutls_openpgp_crt_get_creation_time - Extract the timestamp + * @key: the structure that contains the OpenPGP public key. + * + * Returns the timestamp when the OpenPGP key was created. + **/ +time_t +gnutls_openpgp_crt_get_creation_time (gnutls_openpgp_crt_t key) +{ + cdk_packet_t pkt; + time_t timestamp; + + if (!key) + return (time_t) - 1; + + pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); + if (pkt) + timestamp = pkt->pkt.public_key->timestamp; + else + timestamp = 0; + + return timestamp; +} + + +/** + * gnutls_openpgp_crt_get_expiration_time - Extract the expire date + * @key: the structure that contains the OpenPGP public key. + * + * Returns the time when the OpenPGP key expires. A value of '0' means + * that the key doesn't expire at all. + **/ +time_t +gnutls_openpgp_crt_get_expiration_time (gnutls_openpgp_crt_t key) +{ + cdk_packet_t pkt; + time_t expiredate; + + if (!key) + return (time_t) - 1; + + pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); + if (pkt) + expiredate = pkt->pkt.public_key->expiredate; + else + expiredate = 0; + + return expiredate; +} + +/** + * gnutls_openpgp_crt_get_id - Gets the keyID + * @key: the structure that contains the OpenPGP public key. + * @keyid: the buffer to save the keyid. + * + * Returns the 64-bit keyID of the OpenPGP key. + **/ +int +gnutls_openpgp_crt_get_id (gnutls_openpgp_crt_t key, gnutls_openpgp_keyid_t* keyid) +{ + cdk_packet_t pkt; + uint32_t kid[2]; + + if (!key || !keyid) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); + if (!pkt) + return GNUTLS_E_OPENPGP_GETKEY_FAILED; + + cdk_pk_get_keyid (pkt->pkt.public_key, kid); + _gnutls_write_uint32( kid[0], keyid->keyid); + _gnutls_write_uint32( kid[1], keyid->keyid+4); + + return 0; +} + +/** + * gnutls_openpgp_crt_get_revoked_status - Gets the revoked status of the key + * @key: the structure that contains the OpenPGP public key. + * + * Returns the true (1) or false (0) based on whether this key has been revoked + * or not. + * + **/ +int +gnutls_openpgp_crt_get_revoked_status (gnutls_openpgp_crt_t key) +{ + cdk_packet_t pkt; + + if (!key) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); + if (!pkt) + return GNUTLS_E_OPENPGP_GETKEY_FAILED; + + if (pkt->pkt.public_key->is_revoked != 0) return 1; + return 0; +} + +/** + * gnutls_openpgp_crt_check_hostname - This function compares the given hostname with the hostname in the key + * @key: should contain an gnutls_openpgp_crt_t structure + * @hostname: A null terminated string that contains a DNS name + * + * This function will check if the given key's owner matches + * the given hostname. This is a basic implementation of the matching + * described in RFC2818 (HTTPS), which takes into account wildcards. + * + * Returns non zero on success, and zero on failure. + * + **/ +int +gnutls_openpgp_crt_check_hostname (gnutls_openpgp_crt_t key, + const char *hostname) +{ + char dnsname[MAX_CN]; + size_t dnsnamesize; + int ret; + int i; + + /* Check through all included names. */ + for (i = 0; !(ret < 0); i++) + { + dnsnamesize = sizeof (dnsname); + ret = gnutls_openpgp_crt_get_name (key, i, dnsname, &dnsnamesize); + /* FIXME: ret is not used */ + if (_gnutls_hostname_compare (dnsname, hostname)) + return 1; + } + + /* not found a matching name */ + return 0; +} + +unsigned int _gnutls_get_pgp_key_usage(unsigned int cdk_usage) +{ +unsigned int usage = 0; + + if (cdk_usage & CDK_KEY_USG_CERT_SIGN) + usage |= GNUTLS_KEY_KEY_CERT_SIGN; + if (cdk_usage & CDK_KEY_USG_DATA_SIGN) + usage |= GNUTLS_KEY_DIGITAL_SIGNATURE; + if (cdk_usage & CDK_KEY_USG_COMM_ENCR) + usage |= GNUTLS_KEY_KEY_ENCIPHERMENT; + if (cdk_usage & CDK_KEY_USG_STORAGE_ENCR) + usage |= GNUTLS_KEY_DATA_ENCIPHERMENT; + if (cdk_usage & CDK_KEY_USG_AUTH) + usage |= GNUTLS_KEY_KEY_AGREEMENT; + + return usage; +} + +/** + * gnutls_openpgp_crt_get_key_usage - This function returns the key's usage + * @key: should contain a gnutls_openpgp_crt_t structure + * @key_usage: where the key usage bits will be stored + * + * This function will return certificate's key usage, by checking the + * key algorithm. The key usage value will ORed values of the: + * GNUTLS_KEY_DIGITAL_SIGNATURE, GNUTLS_KEY_KEY_ENCIPHERMENT. + * + * A negative value may be returned in case of parsing error. + * + */ +int +gnutls_openpgp_crt_get_key_usage (gnutls_openpgp_crt_t key, + unsigned int *key_usage) +{ + cdk_packet_t pkt; + + if (!key) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); + if (!pkt) + return GNUTLS_E_OPENPGP_GETKEY_FAILED; + + *key_usage = _gnutls_get_pgp_key_usage(pkt->pkt.public_key->pubkey_usage); + + return 0; +} + +/** + * gnutls_openpgp_crt_get_subkey_count - This function returns the number of subkeys + * @key: is an OpenPGP key + * + * This function will return the number of subkeys present in the given + * OpenPGP certificate. + * + * Returns then number of subkeys or a negative value on error. + * + **/ +int +gnutls_openpgp_crt_get_subkey_count (gnutls_openpgp_crt_t key) +{ + cdk_kbnode_t p, ctx; + cdk_packet_t pkt; + int subkeys; + + if (key == NULL) + { + gnutls_assert (); + return 0; + } + + ctx = NULL; + subkeys = 0; + while ((p = cdk_kbnode_walk (key->knode, &ctx, 0))) + { + pkt = cdk_kbnode_get_packet (p); + if (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY) + subkeys++; + } + + return subkeys; +} + +/* returns the subkey with the given index */ +static cdk_packet_t _get_public_subkey(gnutls_openpgp_crt_t key, unsigned int indx) +{ + cdk_kbnode_t p, ctx; + cdk_packet_t pkt; + int subkeys; + + if (key == NULL) + { + gnutls_assert (); + return NULL; + } + + ctx = NULL; + subkeys = 0; + while ((p = cdk_kbnode_walk (key->knode, &ctx, 0))) + { + pkt = cdk_kbnode_get_packet (p); + if (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY && indx == subkeys++) + return pkt; + } + + return NULL; +} + +/* returns the key with the given keyid + * depending on what requested: + * pkt->pkt.secret_key; + * pkt->pkt.public_key; + */ +cdk_packet_t _gnutls_openpgp_find_key( cdk_kbnode_t knode, uint32_t keyid[2], + unsigned int priv) +{ + cdk_pkt_pubkey_t ret; + cdk_kbnode_t p, ctx; + cdk_packet_t pkt; + int subkeys; + uint32_t local_keyid[2]; + + ctx = NULL; + while ((p = cdk_kbnode_walk (knode, &ctx, 0))) + { + pkt = cdk_kbnode_get_packet (p); + + if ( (priv == 0 && (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY || pkt->pkttype == CDK_PKT_PUBLIC_KEY)) || \ + (priv != 0 && (pkt->pkttype == CDK_PKT_SECRET_SUBKEY || pkt->pkttype == CDK_PKT_SECRET_KEY))) + { + if (priv == 0) + cdk_pk_get_keyid (pkt->pkt.public_key, local_keyid); + else + cdk_pk_get_keyid (pkt->pkt.secret_key->pk, local_keyid); + + if (local_keyid[0] == keyid[0] && \ + local_keyid[1] == keyid[1]) + { + return pkt; + } + } + } + + return NULL; +} + +/* returns the key with the given keyid + * depending on what requested: + * pkt->pkt.secret_key; + * pkt->pkt.public_key; + */ +int _gnutls_openpgp_find_subkey_idx( cdk_kbnode_t knode, uint32_t keyid[2], + unsigned int priv) +{ + cdk_pkt_pubkey_t ret; + cdk_kbnode_t p, ctx; + cdk_packet_t pkt; + int subkeys, i=0; + uint32_t local_keyid[2]; + + ctx = NULL; + while ((p = cdk_kbnode_walk (knode, &ctx, 0))) + { + pkt = cdk_kbnode_get_packet (p); + + if ( (priv == 0 && (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)) || \ + (priv != 0 && (pkt->pkttype == CDK_PKT_SECRET_SUBKEY))) + { + if (priv == 0) + cdk_pk_get_keyid (pkt->pkt.public_key, local_keyid); + else + cdk_pk_get_keyid (pkt->pkt.secret_key->pk, local_keyid); + + if (local_keyid[0] == keyid[0] && \ + local_keyid[1] == keyid[1]) + { + return i; + } + i++; + } + } + + gnutls_assert(); + return GNUTLS_E_OPENPGP_SUBKEY_ERROR; +} + +/** + * gnutls_openpgp_crt_get_subkey_revoked_status - Gets the revoked status of the key + * @key: the structure that contains the OpenPGP public key. + * @idx: is the subkey index + * + * Returns the true (1) or false (0) based on whether this key has been revoked + * or not. A negative value indicates an error. + * + **/ +int +gnutls_openpgp_crt_get_subkey_revoked_status (gnutls_openpgp_crt_t key, unsigned int idx) +{ + cdk_packet_t pkt; + + if (!key) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + pkt = _get_public_subkey( key, idx); + if (!pkt) + return GNUTLS_E_OPENPGP_GETKEY_FAILED; + + if (pkt->pkt.public_key->is_revoked != 0) return 1; + return 0; +} + +/** + * gnutls_openpgp_crt_get_subkey_pk_algorithm - This function returns the subkey's PublicKey algorithm + * @key: is an OpenPGP key + * @idx: is the subkey index + * @bits: if bits is non null it will hold the size of the parameters' in bits + * + * This function will return the public key algorithm of a subkey of an OpenPGP + * certificate. + * + * If bits is non null, it should have enough size to hold the parameters + * size in bits. For RSA the bits returned is the modulus. + * For DSA the bits returned are of the public exponent. + * + * Returns a member of the gnutls_pk_algorithm_t enumeration on success, + * or a negative value on error. + * + **/ +gnutls_pk_algorithm_t +gnutls_openpgp_crt_get_subkey_pk_algorithm (gnutls_openpgp_crt_t key, + unsigned int idx, unsigned int *bits) +{ + cdk_packet_t pkt; + int algo; + + if (!key) + return GNUTLS_PK_UNKNOWN; + + pkt = _get_public_subkey( key, idx); + + algo = 0; + if (pkt) + { + if (bits) + *bits = cdk_pk_get_nbits (pkt->pkt.public_key); + algo = pkt->pkt.public_key->pubkey_algo; + if (is_RSA (algo)) + algo = GNUTLS_PK_RSA; + else if (is_DSA (algo)) + algo = GNUTLS_PK_DSA; + else + algo = GNUTLS_E_UNKNOWN_PK_ALGORITHM; + } + + return algo; +} + +/** + * gnutls_openpgp_crt_get_subkey_creation_time - Extract the timestamp + * @key: the structure that contains the OpenPGP public key. + * @idx: the subkey index + * + * Returns the timestamp when the OpenPGP key was created. + **/ +time_t +gnutls_openpgp_crt_get_subkey_creation_time (gnutls_openpgp_crt_t key, unsigned int idx) +{ + cdk_packet_t pkt; + time_t timestamp; + + if (!key) + return (time_t) - 1; + + pkt = _get_public_subkey( key, idx); + if (pkt) + timestamp = pkt->pkt.public_key->timestamp; + else + timestamp = 0; + + return timestamp; +} + + +/** + * gnutls_openpgp_crt_get_subkey_expiration_time - Extract the expire date + * @key: the structure that contains the OpenPGP public key. + * @idx: the subkey index + * + * Returns the time when the OpenPGP key expires. A value of '0' means + * that the key doesn't expire at all. + **/ +time_t +gnutls_openpgp_crt_get_subkey_expiration_time (gnutls_openpgp_crt_t key, unsigned int idx) +{ + cdk_packet_t pkt; + time_t expiredate; + + if (!key) + return (time_t) - 1; + + pkt = _get_public_subkey( key, idx); + if (pkt) + expiredate = pkt->pkt.public_key->expiredate; + else + expiredate = 0; + + return expiredate; +} + +/** + * gnutls_openpgp_crt_get_subkey_id - Gets the keyID + * @key: the structure that contains the OpenPGP public key. + * @idx: the subkey index + * @keyid: the buffer to save the keyid. + * + * Returns the 64-bit keyID of the OpenPGP key. + **/ +int +gnutls_openpgp_crt_get_subkey_id (gnutls_openpgp_crt_t key, unsigned int idx, gnutls_openpgp_keyid_t* keyid) +{ + cdk_packet_t pkt; + uint32_t kid[2]; + + if (!key || !keyid) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + pkt = _get_public_subkey( key, idx); + if (!pkt) + return GNUTLS_E_OPENPGP_GETKEY_FAILED; + + cdk_pk_get_keyid (pkt->pkt.public_key, kid); + _gnutls_write_uint32( kid[0], keyid->keyid); + _gnutls_write_uint32( kid[1], keyid->keyid+4); + + return 0; +} + +/** + * gnutls_openpgp_crt_get_subkey_idx - Returns the subkey's index + * @key: the structure that contains the OpenPGP public key. + * @keyid: the keyid. + * + * Returns the index of the subkey or a negative error value. + * + **/ +int +gnutls_openpgp_crt_get_subkey_idx (gnutls_openpgp_crt_t key, gnutls_openpgp_keyid_t keyid) +{ + cdk_packet_t pkt; + int ret; + uint32_t kid[2]; + + if (!key) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + KEYID_IMPORT( kid, keyid); + ret = _gnutls_openpgp_find_subkey_idx( key->knode, kid, 0); + + if (ret < 0) + { + gnutls_assert(); + } + + return ret; +} + +/** + * gnutls_openpgp_crt_get_subkey_usage - This function returns the key's usage + * @key: should contain a gnutls_openpgp_crt_t structure + * @idx: the subkey index + * @key_usage: where the key usage bits will be stored + * + * This function will return certificate's key usage, by checking the + * key algorithm. The key usage value will ORed values of the: + * GNUTLS_KEY_DIGITAL_SIGNATURE, GNUTLS_KEY_KEY_ENCIPHERMENT. + * + * A negative value may be returned in case of parsing error. + * + */ +int +gnutls_openpgp_crt_get_subkey_usage (gnutls_openpgp_crt_t key, unsigned int idx, + unsigned int *key_usage) +{ + cdk_packet_t pkt; + + if (!key) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + pkt = _get_public_subkey( key, idx); + if (!pkt) + return GNUTLS_E_OPENPGP_SUBKEY_ERROR; + + *key_usage = _gnutls_get_pgp_key_usage(pkt->pkt.public_key->pubkey_usage); + + return 0; +} + +int _gnutls_read_pgp_mpi( cdk_packet_t pkt, unsigned int priv, size_t idx, mpi_t* m) +{ +size_t buf_size = 512; +opaque * buf = gnutls_malloc( buf_size); +int err; +int max_pub_params; + + if (priv !=0) + max_pub_params = cdk_pk_get_npkey(pkt->pkt.secret_key->pk->pubkey_algo); + + if (buf == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + /* FIXME: Note that opencdk doesn't like the buf to be NULL. + */ + if (priv == 0) + err = cdk_pk_get_mpi (pkt->pkt.public_key, idx, buf, buf_size, &buf_size, NULL); + else + { + if (idx < max_pub_params) + err = cdk_pk_get_mpi (pkt->pkt.secret_key->pk, idx, buf, buf_size, &buf_size, NULL); + else + { + err = cdk_sk_get_mpi (pkt->pkt.secret_key, idx-max_pub_params, buf, buf_size, &buf_size, NULL); + } + } + + if (err == CDK_Too_Short) + { + buf = gnutls_realloc_fast( buf, buf_size); + if (buf == NULL) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + if (priv == 0) + err = cdk_pk_get_mpi (pkt->pkt.public_key, idx, buf, buf_size, &buf_size, NULL); + else + { + if (idx < max_pub_params) + err = cdk_pk_get_mpi (pkt->pkt.secret_key->pk, idx, buf, buf_size, &buf_size, NULL); + else + { + err = cdk_sk_get_mpi (pkt->pkt.secret_key, idx-max_pub_params, buf, buf_size, &buf_size, NULL); + } + } + } + + if (err != CDK_Success) + { +_gnutls_x509_log( "err: %d/%d\n", err, idx); + gnutls_assert(); + gnutls_free( buf); + return _gnutls_map_cdk_rc( err); + } + + err = _gnutls_mpi_scan_pgp (m, buf, &buf_size); + gnutls_free( buf); + + if (err < 0) + { + gnutls_assert(); + return err; + } + + return 0; +} + + +/* Extracts DSA and RSA parameters from a certificate. + */ +int +_gnutls_openpgp_crt_get_mpis (gnutls_openpgp_crt_t cert, uint32_t keyid[2], + mpi_t * params, int *params_size) +{ + int result, i; + int pk_algorithm, local_params; + cdk_packet_t pkt; + + /* Read the algorithm's OID + */ + pk_algorithm = gnutls_openpgp_crt_get_pk_algorithm (cert, NULL); + + switch (pk_algorithm) + { + case GNUTLS_PK_RSA: + local_params = RSA_PUBLIC_PARAMS; + break; + case GNUTLS_PK_DSA: + local_params = DSA_PUBLIC_PARAMS; + break; + default: + gnutls_assert (); + return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE; + } + + if (*params_size < local_params) + { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + *params_size = local_params; + + pkt = _gnutls_openpgp_find_key( cert->knode, keyid, 0); + if (pkt == NULL) + { + gnutls_assert(); + return GNUTLS_E_OPENPGP_GETKEY_FAILED; + } + + for (i = 0; i < local_params; i++) + { + result = _gnutls_read_pgp_mpi( pkt, 0, i, ¶ms[i]); + if (result < 0) + { + gnutls_assert(); + goto error; + } + } + + return 0; + +error: + { + int j; + for (j=0;j<i;j++) + _gnutls_mpi_release( ¶ms[j]); + } + + return result; +} diff --git a/lib/openpgp/pgpverify.c b/lib/openpgp/pgpverify.c new file mode 100644 index 0000000000..34b06a0834 --- /dev/null +++ b/lib/openpgp/pgpverify.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation + * + * Author: Timo Schulz, Nikos Mavrogiannopoulos + * + * This file is part of GNUTLS-EXTRA. + * + * GNUTLS-EXTRA is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNUTLS-EXTRA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* Functions on OpenPGP key parsing + */ + +#include <gnutls_int.h> +#include <openpgp.h> +#include <gnutls_errors.h> +#include <gnutls_openpgp.h> +#include <gnutls_num.h> +#include <x509/verify.h> /* lib/x509/verify.h */ + + +/** + * gnutls_openpgp_crt_verify_ring - Verify all signatures in the key + * @key: the structure that holds the key. + * @keyring: holds the keyring to check against + * @flags: unused (should be 0) + * @verify: will hold the certificate verification output. + * + * Verify all signatures in the key, using the given set of keys (keyring). + * + * The key verification output will be put in @verify and will be + * one or more of the gnutls_certificate_status_t enumerated elements bitwise or'd. + * + * GNUTLS_CERT_INVALID: A signature on the key is invalid. + * + * GNUTLS_CERT_REVOKED: The key has been revoked. + * + * Note that this function does not verify using any "web of + * trust". You may use GnuPG for that purpose, or any other external + * PGP application. + * + * Returns 0 on success. + **/ +int +gnutls_openpgp_crt_verify_ring (gnutls_openpgp_crt_t key, + gnutls_openpgp_keyring_t keyring, + unsigned int flags, unsigned int *verify) +{ + gnutls_openpgp_keyid_t id; + cdk_error_t rc; + int status; + + if (!key || !keyring) + { + gnutls_assert (); + return GNUTLS_E_NO_CERTIFICATE_FOUND; + } + + *verify = 0; + + rc = cdk_pk_check_sigs (key->knode, keyring->db, &status); + if (rc == CDK_Error_No_Key) + { + rc = GNUTLS_E_NO_CERTIFICATE_FOUND; + gnutls_assert (); + return rc; + } + else if (rc != CDK_Success) + { + _gnutls_x509_log("cdk_pk_check_sigs: error %d\n", rc); + rc = _gnutls_map_cdk_rc (rc); + gnutls_assert (); + return rc; + } + _gnutls_x509_log("status: %x\n", status); + + if (status & CDK_KEY_INVALID) + *verify |= GNUTLS_CERT_INVALID; + if (status & CDK_KEY_REVOKED) + *verify |= GNUTLS_CERT_REVOKED; + if (status & CDK_KEY_NOSIGNER) + *verify |= GNUTLS_CERT_SIGNER_NOT_FOUND; + + /* Check if the key is included in the ring. */ + if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_SAME)) + { + rc = gnutls_openpgp_crt_get_id (key, &id); + if (rc < 0) + { + gnutls_assert (); + return rc; + } + + rc = gnutls_openpgp_keyring_check_id (keyring, id, 0); + /* If it exists in the keyring don't treat it as unknown. */ + if (rc == 0 && *verify & GNUTLS_CERT_SIGNER_NOT_FOUND) + *verify ^= GNUTLS_CERT_SIGNER_NOT_FOUND; + } + + return 0; +} + + +/** + * gnutls_openpgp_crt_verify_self - Verify the self signature on the key + * @key: the structure that holds the key. + * @flags: unused (should be 0) + * @verify: will hold the key verification output. + * + * Verifies the self signature in the key. + * The key verification output will be put in @verify and will be + * one or more of the gnutls_certificate_status_t enumerated elements bitwise or'd. + * + * GNUTLS_CERT_INVALID: The self signature on the key is invalid. + * + * Returns 0 on success. + **/ +int +gnutls_openpgp_crt_verify_self (gnutls_openpgp_crt_t key, + unsigned int flags, unsigned int *verify) +{ + int status; + cdk_error_t rc; + + rc = cdk_pk_check_self_sig (key->knode, &status); + if (rc || status != CDK_KEY_VALID) + *verify |= GNUTLS_CERT_INVALID; + else + *verify = 0; + + return 0; +} + diff --git a/lib/openpgp/privkey.c b/lib/openpgp/privkey.c new file mode 100644 index 0000000000..1083e30f22 --- /dev/null +++ b/lib/openpgp/privkey.c @@ -0,0 +1,575 @@ +/* + * Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation + * + * Author: Nikos Mavrogiannopoulos + * + * This file is part of GNUTLS-EXTRA. + * + * GNUTLS-EXTRA is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNUTLS-EXTRA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* Functions on OpenPGP privkey parsing + */ + +#include <gnutls_int.h> +#include <gnutls_datum.h> +#include <gnutls_global.h> +#include <gnutls_errors.h> +#include <gnutls_num.h> +#include <openpgp.h> +#include <gnutls_openpgp.h> +#include <x509/rfc2818.h> +#include <gnutls_cert.h> + +/** + * gnutls_openpgp_privkey_init - This function initializes a gnutls_openpgp_privkey_t structure + * @key: The structure to be initialized + * + * This function will initialize an OpenPGP key structure. + * + * Returns 0 on success. + * + **/ +int +gnutls_openpgp_privkey_init (gnutls_openpgp_privkey_t * key) +{ + *key = gnutls_calloc (1, sizeof (gnutls_openpgp_privkey_int)); + + if (*key) + return 0; /* success */ + return GNUTLS_E_MEMORY_ERROR; +} + +/** + * gnutls_openpgp_privkey_deinit - This function deinitializes memory used by a gnutls_openpgp_privkey_t structure + * @key: The structure to be initialized + * + * This function will deinitialize a key structure. + * + **/ +void +gnutls_openpgp_privkey_deinit (gnutls_openpgp_privkey_t key) +{ + if (!key) + return; + + if (key->knode) + { + cdk_kbnode_release (key->knode); + key->knode = NULL; + } + + gnutls_free (key); +} + +/** + * gnutls_openpgp_privkey_import - This function will import a RAW or BASE64 encoded key + * @key: The structure to store the parsed key. + * @data: The RAW or BASE64 encoded key. + * @format: One of gnutls_openpgp_crt_fmt_t elements. + * @pass: Unused for now + * @flags: should be zero + * + * This function will convert the given RAW or Base64 encoded key + * to the native gnutls_openpgp_privkey_t format. The output will be stored in 'key'. + * + * Returns 0 on success. + * + **/ +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) +{ + cdk_stream_t inp; + int rc; + + if (format == GNUTLS_OPENPGP_FMT_RAW) + rc = cdk_kbnode_read_from_mem (&key->knode, data->data, data->size); + else + { + rc = cdk_stream_tmp_from_mem (data->data, data->size, &inp); + if (rc) + { + rc = _gnutls_map_cdk_rc (rc); + gnutls_assert (); + return rc; + } + if (cdk_armor_filter_use (inp)) + rc = cdk_stream_set_armor_flag (inp, 0); + if (!rc) + rc = cdk_keydb_get_keyblock (inp, &key->knode); + cdk_stream_close (inp); + if (rc) + { + rc = _gnutls_map_cdk_rc (rc); + gnutls_assert (); + return rc; + } + } + + return 0; +} + + +/** + * gnutls_openpgp_privkey_get_pk_algorithm - This function returns the key's PublicKey algorithm + * @key: is an OpenPGP key + * @bits: if bits is non null it will hold the size of the parameters' in bits + * + * This function will return the public key algorithm of an OpenPGP + * certificate. + * + * If bits is non null, it should have enough size to hold the parameters + * size in bits. For RSA the bits returned is the modulus. + * For DSA the bits returned are of the public exponent. + * + * Returns a member of the GNUTLS_PKAlgorithm enumeration on success, + * or a negative value on error. + * + **/ +gnutls_pk_algorithm_t +gnutls_openpgp_privkey_get_pk_algorithm (gnutls_openpgp_privkey_t key, + unsigned int *bits) +{ + cdk_packet_t pkt; + int algo; + + if (!key) + return GNUTLS_PK_UNKNOWN; + + algo = 0; + pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY); + if (pkt) + { + if (bits) + *bits = cdk_pk_get_nbits (pkt->pkt.secret_key->pk); + algo = pkt->pkt.secret_key->pk->pubkey_algo; + if (is_RSA (algo)) + algo = GNUTLS_PK_RSA; + else if (is_DSA (algo)) + algo = GNUTLS_PK_DSA; + else + algo = GNUTLS_PK_UNKNOWN; + } + + return algo; +} + +/** + * gnutls_openpgp_privkey_get_revoked_ status - Gets the revoked status of the key + * @key: the structure that contains the OpenPGP public key. + * + * Returns the true (1) or false (0) based on whether this key has been revoked + * or not. A negative value indicates an error. + * + **/ +int +gnutls_openpgp_privkey_get_revoked_status (gnutls_openpgp_privkey_t key) +{ + cdk_packet_t pkt; + + if (!key) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY); + if (!pkt) + return GNUTLS_E_OPENPGP_GETKEY_FAILED; + + if (pkt->pkt.secret_key->is_revoked != 0) return 1; + return 0; +} + +/** + * gnutls_openpgp_privkey_get_fingerprint - Gets the fingerprint + * @key: the raw data that contains the OpenPGP secret key. + * @fpr: the buffer to save the fingerprint, must hold at least 20 bytes. + * @fprlen: the integer to save the length of the fingerprint. + * + * Returns the fingerprint of the OpenPGP key. Depends on the algorithm, + * the fingerprint can be 16 or 20 bytes. + **/ +int +gnutls_openpgp_privkey_get_fingerprint (gnutls_openpgp_privkey_t key, + void *fpr, size_t * fprlen) +{ + cdk_packet_t pkt; + cdk_pkt_pubkey_t pk = NULL; + + if (!fpr || !fprlen) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + *fprlen = 0; + + pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY); + if (!pkt) + { + gnutls_assert(); + return GNUTLS_E_OPENPGP_GETKEY_FAILED; + } + + pk = pkt->pkt.secret_key->pk; + *fprlen = 20; + + if (is_RSA (pk->pubkey_algo) && pk->version < 4) + *fprlen = 16; + + cdk_pk_get_fingerprint (pk, fpr); + + return 0; +} + +/** + * gnutls_openpgp_privkey_get_key_id - Gets the keyID + * @key: the structure that contains the OpenPGP secret key. + * @keyid: the buffer to save the keyid. + * + * Returns the 64-bit keyID of the OpenPGP key. + **/ +int +gnutls_openpgp_privkey_get_key_id (gnutls_openpgp_privkey_t key, gnutls_openpgp_keyid_t* keyid) +{ + cdk_packet_t pkt; + uint32_t kid[2]; + + if (!key || !keyid) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY); + if (!pkt) + return GNUTLS_E_OPENPGP_GETKEY_FAILED; + + cdk_sk_get_keyid (pkt->pkt.secret_key, kid); + _gnutls_write_uint32( kid[0], keyid->keyid); + _gnutls_write_uint32( kid[1], keyid->keyid+4); + + return 0; +} + + +/** + * gnutls_openpgp_privkey_get_subkey_count - This function returns the number of subkeys + * @key: is an OpenPGP key + * + * This function will return the number of subkeys present in the given + * OpenPGP certificate. + * + * Returns then number of subkeys or a negative value on error. + * + **/ +int +gnutls_openpgp_privkey_get_subkey_count (gnutls_openpgp_privkey_t key) +{ + cdk_kbnode_t p, ctx; + cdk_packet_t pkt; + int subkeys; + + if (key == NULL) + { + gnutls_assert (); + return 0; + } + + ctx = NULL; + subkeys = 0; + while ((p = cdk_kbnode_walk (key->knode, &ctx, 0))) + { + pkt = cdk_kbnode_get_packet (p); + if (pkt->pkttype == CDK_PKT_SECRET_SUBKEY) + subkeys++; + } + + return subkeys; +} + +/* returns the subkey with the given index */ +static cdk_packet_t _get_secret_subkey(gnutls_openpgp_privkey_t key, unsigned int indx) +{ + cdk_kbnode_t p, ctx; + cdk_packet_t pkt; + int subkeys; + + ctx = NULL; + subkeys = 0; + while ((p = cdk_kbnode_walk (key->knode, &ctx, 0))) + { + pkt = cdk_kbnode_get_packet (p); + if (pkt->pkttype == CDK_PKT_SECRET_SUBKEY && indx == subkeys++) + return pkt; + } + + return NULL; +} + +/** + * gnutls_openpgp_privkey_get_subkey_revoked_ status - Gets the revoked status of the key + * @key: the structure that contains the OpenPGP public key. + * @idx: is the subkey index + * + * Returns the true (1) or false (0) based on whether this key has been revoked + * or not. A negative value indicates an error. + * + **/ +int +gnutls_openpgp_privkey_get_subkey_revoked_status (gnutls_openpgp_privkey_t key, unsigned int idx) +{ + cdk_packet_t pkt; + + if (!key) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + pkt = _get_secret_subkey( key, idx); + if (!pkt) + return GNUTLS_E_OPENPGP_GETKEY_FAILED; + + if (pkt->pkt.secret_key->is_revoked != 0) return 1; + return 0; +} + +/** + * gnutls_openpgp_privkey_get_subkey_pk_algorithm - This function returns the subkey's PublicKey algorithm + * @key: is an OpenPGP key + * @idx: is the subkey index + * @bits: if bits is non null it will hold the size of the parameters' in bits + * + * This function will return the public key algorithm of a subkey of an OpenPGP + * certificate. + * + * If bits is non null, it should have enough size to hold the parameters + * size in bits. For RSA the bits returned is the modulus. + * For DSA the bits returned are of the public exponent. + * + * Returns a member of the gnutls_pk_algorithm_t enumeration on success, + * or a negative value on error. + * + **/ +gnutls_pk_algorithm_t +gnutls_openpgp_privkey_get_subkey_pk_algorithm (gnutls_openpgp_privkey_t key, + unsigned int idx, unsigned int *bits) +{ + cdk_packet_t pkt; + int algo; + + if (!key) + return GNUTLS_PK_UNKNOWN; + + pkt = _get_secret_subkey( key, idx); + + algo = 0; + if (pkt) + { + if (bits) + *bits = cdk_pk_get_nbits (pkt->pkt.secret_key->pk); + algo = pkt->pkt.secret_key->pubkey_algo; + if (is_RSA (algo)) + algo = GNUTLS_PK_RSA; + else if (is_DSA (algo)) + algo = GNUTLS_PK_DSA; + else + algo = GNUTLS_E_UNKNOWN_PK_ALGORITHM; + } + + return algo; +} + +/** + * gnutls_openpgp_privkey_get_subkey_idx - Returns the subkey's index + * @key: the structure that contains the OpenPGP public key. + * @keyid: the keyid. + * + * Returns the index of the subkey or a negative error value. + * + **/ +int +gnutls_openpgp_privkey_get_subkey_idx (gnutls_openpgp_privkey_t key, gnutls_openpgp_keyid_t keyid) +{ + cdk_packet_t pkt; + int ret; + uint32_t kid[2]; + + if (!key) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + KEYID_IMPORT( kid, keyid); + ret = _gnutls_openpgp_find_subkey_idx( key->knode, kid, 1); + + if (ret < 0) + { + gnutls_assert(); + } + + return ret; +} + +/** + * gnutls_openpgp_privkey_get_subkey_creation_time - Extract the timestamp + * @key: the structure that contains the OpenPGP public key. + * @idx: the subkey index + * + * Returns the timestamp when the OpenPGP key was created. + **/ +time_t +gnutls_openpgp_privkey_get_subkey_creation_time (gnutls_openpgp_privkey_t key, unsigned int idx) +{ + cdk_packet_t pkt; + time_t timestamp; + + if (!key) + return (time_t) - 1; + + pkt = _get_secret_subkey( key, idx); + if (pkt) + timestamp = pkt->pkt.secret_key->pk->timestamp; + else + timestamp = 0; + + return timestamp; +} + +/** + * gnutls_openpgp_privkey_get_subkey_expiration_time - Extract the expire date + * @key: the structure that contains the OpenPGP public key. + * @idx: the subkey index + * + * Returns the time when the OpenPGP key expires. A value of '0' means + * that the key doesn't expire at all. + **/ +time_t +gnutls_openpgp_privkey_get_subkey_expiration_time (gnutls_openpgp_privkey_t key, unsigned int idx) +{ + cdk_packet_t pkt; + time_t expiredate; + + if (!key) + return (time_t) - 1; + + pkt = _get_secret_subkey( key, idx); + if (pkt) + expiredate = pkt->pkt.secret_key->expiredate; + else + expiredate = 0; + + return expiredate; +} + +/** + * gnutls_openpgp_privkey_get_subkey_id - Gets the keyID + * @key: the structure that contains the OpenPGP secret key. + * @idx: the subkey index + * @keyid: the buffer to save the keyid. + * + * Returns the 64-bit keyID of the OpenPGP key. + **/ +int +gnutls_openpgp_privkey_get_subkey_id (gnutls_openpgp_privkey_t key, unsigned int idx, gnutls_openpgp_keyid_t* keyid) +{ + cdk_packet_t pkt; + uint32_t kid[2]; + + if (!key || !keyid) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + pkt = _get_secret_subkey( key, idx); + if (!pkt) + return GNUTLS_E_OPENPGP_GETKEY_FAILED; + + cdk_sk_get_keyid (pkt->pkt.secret_key, kid); + _gnutls_write_uint32( kid[0], keyid->keyid); + _gnutls_write_uint32( kid[1], keyid->keyid+4); + + return 0; +} + +/* Extracts DSA and RSA parameters from a certificate. + */ +int +_gnutls_openpgp_privkey_get_mpis (gnutls_openpgp_privkey_t pkey, uint32_t keyid[2], + mpi_t * params, int *params_size) +{ + int result, i; + int pk_algorithm, local_params; + cdk_packet_t pkt; + + /* Read the algorithm's OID + */ + pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm (pkey, NULL); + + switch (pk_algorithm) + { + case GNUTLS_PK_RSA: + local_params = RSA_PRIVATE_PARAMS; + break; + case GNUTLS_PK_DSA: + local_params = DSA_PRIVATE_PARAMS; + break; + default: + gnutls_assert (); + return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE; + } + + if (*params_size < local_params) + { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + *params_size = local_params; + + pkt = _gnutls_openpgp_find_key( pkey->knode, keyid, 1); + if (pkt == NULL) + { + gnutls_assert(); + return GNUTLS_E_OPENPGP_GETKEY_FAILED; + } + + for (i = 0; i < local_params; i++) + { + result = _gnutls_read_pgp_mpi( pkt, 1, i, ¶ms[i]); + if (result < 0) + { + gnutls_assert(); + goto error; + } + } + + return 0; + +error: + { + int j; + for (j=0;j<i;j++) + _gnutls_mpi_release( ¶ms[j]); + } + + return result; +} diff --git a/libextra/Makefile.am b/libextra/Makefile.am index 68edc77ece..5d03a9f512 100644 --- a/libextra/Makefile.am +++ b/libextra/Makefile.am @@ -22,7 +22,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/lgl -I$(top_builddir)/lgl \ -I$(top_srcdir)/lib -I../includes -I$(top_srcdir)/includes \ - -I$(top_srcdir)/lib/minitasn1 -I$(srcdir)/openpgp \ + -I$(top_srcdir)/lib/minitasn1 \ $(LIBGCRYPT_CFLAGS) if ENABLE_MINITASN1 @@ -33,14 +33,6 @@ endif SUBDIRS = -if ENABLE_OPENPGP -if ENABLE_INCLUDED_OPENCDK -SUBDIRS += opencdk -AM_CPPFLAGS += -I$(srcdir)/opencdk -endif -SUBDIRS += openpgp -endif - bin_SCRIPTS = libgnutls-extra-config m4datadir = $(datadir)/aclocal @@ -91,15 +83,6 @@ endif libgnutls_extra_la_LIBADD = libgnutls_extra_la_LDFLAGS = -no-undefined -L$(top_srcdir)/lib/.libs -if ENABLE_OPENPGP -libgnutls_extra_la_SOURCES += gnutls_openpgp.c -libgnutls_extra_la_LIBADD += openpgp/libgnutls_openpgp.la -if ENABLE_INCLUDED_OPENCDK -libgnutls_extra_la_LIBADD += opencdk/libminiopencdk.la -else -libgnutls_extra_la_LDFLAGS += $(LTLIBOPENCDK) -endif -endif # TLS/IA diff --git a/libextra/gnutls_extra.c b/libextra/gnutls_extra.c index 3bb038f645..da22415a79 100644 --- a/libextra/gnutls_extra.c +++ b/libextra/gnutls_extra.c @@ -22,9 +22,7 @@ #include <gnutls_int.h> #include <gnutls_errors.h> #include <gnutls_extensions.h> -#include <gnutls_openpgp.h> #include <gnutls_extra.h> -#include <gnutls_extra_hooks.h> #include <gnutls_algorithms.h> #ifdef USE_LZO # ifdef USE_MINILZO @@ -137,22 +135,6 @@ gnutls_global_init_extra (void) } #endif - /* Register the openpgp functions. This is because some - * of them are defined to be NULL in the main library. - */ - _gnutls_add_openpgp_functions (_gnutls_openpgp_verify_key, - _gnutls_openpgp_get_raw_key_creation_time, - _gnutls_openpgp_get_raw_key_expiration_time, - _gnutls_openpgp_fingerprint, - _gnutls_openpgp_request_key, - _gnutls_openpgp_raw_key_to_gcert, - _gnutls_openpgp_raw_privkey_to_gkey, - _gnutls_openpgp_crt_to_gcert, - _gnutls_openpgp_privkey_to_gkey, - gnutls_openpgp_crt_deinit, - gnutls_openpgp_keyring_deinit, - gnutls_openpgp_privkey_deinit); - return 0; } diff --git a/libextra/opencdk/cipher.c b/libextra/opencdk/cipher.c deleted file mode 100644 index de58cc07d6..0000000000 --- a/libextra/opencdk/cipher.c +++ /dev/null @@ -1,529 +0,0 @@ -/* cipher.c - Cipher filters - * Copyright (C) 2002, 2003, 2007 Timo Schulz - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation - * - * This file is part of OpenCDK. - * - * OpenCDK is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * OpenCDK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include <stdio.h> -#include <assert.h> -#include <sys/stat.h> - -#include "opencdk.h" -#include "main.h" -#include "filters.h" - - -/* The maximal cipher block size in octets. */ -#define MAX_CIPHER_BLKSIZE 16 - - -static off_t -fp_get_length (FILE *fp) -{ - struct stat statbuf; - - if (fstat (fileno (fp), &statbuf)) - return (off_t)-1; - return statbuf.st_size; -} - - -static cdk_error_t -hash_encode (void *opaque, FILE *in, FILE *out) -{ - md_filter_t *mfx = opaque; - byte buf[BUFSIZE]; - gcry_error_t err; - int nread; - - if (!mfx) - return CDK_Inv_Value; - - _cdk_log_debug ("hash filter: encode algo=%d\n", mfx->digest_algo); - - if (!mfx->md) - { - err = gcry_md_open (&mfx->md, mfx->digest_algo, 0); - if (err) - return map_gcry_error (err); - } - - while (!feof (in)) - { - nread = fread (buf, 1, BUFSIZE, in); - if (!nread) - break; - gcry_md_write (mfx->md, buf, nread); - } - - wipemem (buf, sizeof (buf)); - return 0; -} - - -cdk_error_t -_cdk_filter_hash (void *opaque, int ctl, FILE *in, FILE *out) -{ - if (ctl == STREAMCTL_READ) - return hash_encode (opaque, in, out); - else if (ctl == STREAMCTL_FREE) - { - md_filter_t *mfx = opaque; - if (mfx) - { - _cdk_log_debug ("free hash filter\n"); - gcry_md_close (mfx->md); - mfx->md = NULL; - return 0; - } - } - return CDK_Inv_Mode; -} - - -static cdk_error_t -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[MAX_CIPHER_BLKSIZE+2]; - size_t blocksize; - int use_mdc, nprefix; - gcry_error_t err; - - blocksize = gcry_cipher_get_algo_blklen (dek->algo); - if (blocksize < 8 || blocksize > 16) - return CDK_Inv_Algo; - - /* It might be possible the receiver does not understand the MDC - output and thus we offer to supress the MDC packet. */ - use_mdc = dek->use_mdc; - if (blocksize == 8) - 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; - - cdk_pkt_alloc (&pkt, CDK_PKT_ENCRYPTED_MDC); - ed = pkt->pkt.encrypted; - if (!cfx->blkmode.on) - { - ed->len = cfx->datalen; - ed->extralen = blocksize + 2; - } - else - cfx->blkmode.nleft = DEF_BLOCKSIZE; - - if (use_mdc) - { - ed->mdc_method = GCRY_MD_SHA1; - err = gcry_md_open (&cfx->mdc, GCRY_MD_SHA1, 0); - if (err) - return map_gcry_error (err); - } - - /* When we use partial bodies, the MDC feature or a blocksize - larger than 8, we force the use of the new packet format. */ - if (cfx->blkmode.on || use_mdc || blocksize != 8) - pkt->old_ctb = 0; - else - pkt->old_ctb = 1; - pkt->pkttype = use_mdc? CDK_PKT_ENCRYPTED_MDC : CDK_PKT_ENCRYPTED; - rc = _cdk_pkt_write_fp (out, pkt); - cdk_pkt_release (pkt); - if (rc) - return rc; - - nprefix = blocksize; - gcry_randomize (temp, nprefix, GCRY_STRONG_RANDOM); - temp[nprefix] = temp[nprefix - 2]; - temp[nprefix + 1] = temp[nprefix - 1]; - err = gcry_cipher_open (&cfx->hd, dek->algo, GCRY_CIPHER_MODE_CFB, - use_mdc? 0 : GCRY_CIPHER_ENABLE_SYNC); - if (err) - return map_gcry_error (err); - err = gcry_cipher_setiv (cfx->hd, NULL, 0); - if (err) - return map_gcry_error (err); - err = gcry_cipher_setkey (cfx->hd, dek->key, dek->keylen); - if (err) - return map_gcry_error (err); - if (cfx->mdc) - gcry_md_write (cfx->mdc, temp, nprefix + 2); - gcry_cipher_encrypt (cfx->hd, temp, nprefix + 2, NULL, 0); - gcry_cipher_sync (cfx->hd); - fwrite (temp, 1, nprefix+2, out); - if (cfx->blkmode.on) - { - cfx->blkmode.nleft -= (nprefix+2); - if (use_mdc) - cfx->blkmode.nleft--; /* 1 byte version */ - } - return rc; -} - - -static cdk_error_t -write_mdc_packet (FILE *out, cipher_filter_t *cfx) -{ - byte pktdata[22]; - int dlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1); - - if (!out || !cfx) - return CDK_Inv_Value; - if (dlen != 20) - return CDK_Inv_Algo; - - /* We must hash the prefix of the MDC packet here */ - pktdata[0] = 0xD3; - pktdata[1] = 0x14; - gcry_md_write (cfx->mdc, pktdata, 2); - gcry_md_final (cfx->mdc); - memcpy (pktdata + 2, gcry_md_read (cfx->mdc, GCRY_MD_SHA1), dlen); - gcry_cipher_encrypt (cfx->hd, pktdata, dlen+2, NULL, 0); - fwrite (pktdata, 1, dlen+2, out); - wipemem (pktdata, sizeof (pktdata)); - return 0; -} - - -static inline int -num2bits (size_t n) -{ - size_t i; - - for (i = 0; n > 1; i++) - n >>= 1; - return i; -} - - -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; - - if (!out || !cfx) - return CDK_Inv_Value; - - if (!cfx->blkmode.nleft && *r_len > 0) - { - if (*r_len > DEF_BLOCKSIZE) - { - /*_cdk_log_debug ("write_partial_block: size %lu block %d\n", - *r_len, DEF_BLOCKSIZE);*/ - fputc ((0xE0|DEF_BLOCKBITS), out); - cfx->blkmode.nleft = DEF_BLOCKSIZE; - (*r_len) -= DEF_BLOCKSIZE; - } - else if (*r_len > 512) - { - n = num2bits (*r_len); - cfx->blkmode.nleft = (1 << n); - /*_cdk_log_debug ("write_partial_block: size %lu bits %d block %d\n", - *r_len, n, (1<<n));*/ - fputc ((0xE0|n), out); - (*r_len) -= cfx->blkmode.nleft; - } - else - { - size_t pktlen = *r_len; - - /* If we use the MDC mode, we need to increase the final - partial body length to hold the mdc packet itself. */ - if (cfx->mdc) - pktlen += 22; - - if (pktlen < 192) - fputc (pktlen, out); - else if (pktlen < 8384) - { - pktlen -= 192; - fputc ((pktlen/256) + 192, out); - fputc ((pktlen % 256), out); - } - cfx->blkmode.nleft = pktlen; - /*_cdk_log_debug ("write_partial_block: end %d block\n", pktlen);*/ - (*r_len) -= pktlen; - } - } - else - (*r_len) -= cfx->blkmode.nleft; - - n = cfx->blkmode.nleft < DIM (buf)? cfx->blkmode.nleft : DIM (buf); - nread = fread (buf, 1, n, in); - if (!nread) - return CDK_EOF; - if (cfx->mdc) - gcry_md_write (cfx->mdc, buf, nread); - err = gcry_cipher_encrypt (cfx->hd, buf, nread, NULL, 0); - if (err) - return map_gcry_error (err); - fwrite (buf, 1, nread, out); - cfx->blkmode.nleft -= nread; - return 0; -} - - -static cdk_error_t -cipher_encode_file (void *opaque, FILE *in, FILE *out) -{ - cipher_filter_t *cfx = opaque; - byte buf[BUFSIZE]; - off_t len, len2; - int nread; - cdk_error_t rc; - - if (!cfx || !in || !out) - return CDK_Inv_Value; - - len = len2 = fp_get_length (in); - if (len == (off_t)-1) - return CDK_File_Error; - while (!feof (in)) - { - if (cfx->blkmode.on) - { - rc = write_partial_block (in, out, &len2, cfx); - if (rc == CDK_EOF) - break; - if (rc) - { - wipemem (buf, sizeof (buf)); - return rc; - } - continue; - } - nread = fread (buf, 1, DIM (buf), in); - if (!nread) - break; - if (cfx->mdc) - gcry_md_write (cfx->mdc, buf, nread); - gcry_cipher_encrypt (cfx->hd, buf, nread, NULL, 0); - fwrite (buf, 1, nread, out); - } - if (cfx->mdc) - rc = write_mdc_packet (out, cfx); - else - rc = 0; - - wipemem (buf, sizeof (buf)); - return rc; -} - - -static cdk_error_t -read_header (cipher_filter_t * cfx, FILE * in) -{ - cdk_dek_t dek; - byte temp[32]; - int blocksize, nprefix; - int i, c; - gcry_error_t err; - - if (!cfx || !in) - return CDK_Inv_Value; - - dek = cfx->dek; - blocksize = gcry_cipher_get_algo_blklen (dek->algo); - if (blocksize < 8 || blocksize > 16) - return CDK_Inv_Algo; - - nprefix = blocksize; - if (cfx->datalen > 0 && cfx->datalen < (nprefix + 2)) - return CDK_Inv_Value; - if (cfx->mdc_method) - { - err = gcry_md_open (&cfx->mdc, cfx->mdc_method, 0); - if (err) - return map_gcry_error (err); - } - err = gcry_cipher_open (&cfx->hd, dek->algo, GCRY_CIPHER_MODE_CFB, - cfx->mdc_method? 0 : GCRY_CIPHER_ENABLE_SYNC); - if (err) - return map_gcry_error (err); - err = gcry_cipher_setiv (cfx->hd, NULL, 0); - if (err) - return map_gcry_error (err); - err = gcry_cipher_setkey (cfx->hd, dek->key, dek->keylen); - if (err) - return map_gcry_error (err); - - for (i = 0; i < (nprefix + 2); i++ ) - { - c = fgetc (in); - if (c == EOF) - return CDK_File_Error; - temp[i] = c; - } - gcry_cipher_decrypt (cfx->hd, temp, nprefix + 2, NULL, 0); - gcry_cipher_sync (cfx->hd); - i = nprefix; - if (temp[i - 2] != temp[i] || temp[i - 1] != temp[i + 1]) - return CDK_Chksum_Error; - if (cfx->mdc) - gcry_md_write (cfx->mdc, temp, nprefix + 2); - if (cfx->blkmode.on) - cfx->blkmode.size -= (nprefix + 2); - return 0; -} - - -static cdk_error_t -finalize_mdc (gcry_md_hd_t md, const byte *buf, size_t nread) -{ - byte mdcbuf[20]; - int dlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1); - cdk_error_t rc; - - if (dlen != 20) - return CDK_Inv_Algo; - - if (buf[nread - dlen - 2] == 0xD3 && buf[nread - dlen - 1] == 0x14) - { - gcry_md_write (md, buf, nread - dlen); - gcry_md_final (md); - memcpy (mdcbuf, gcry_md_read (md, GCRY_MD_SHA1), dlen); - if (memcmp (mdcbuf, buf + nread - dlen, dlen)) - rc = CDK_Bad_MDC; - else - rc = CDK_Success; - wipemem (mdcbuf, sizeof (mdcbuf)); - return rc; - } - - return CDK_Inv_Packet; -} - - -static cdk_error_t -cipher_decode_file (void *opaque, FILE *in, FILE *out) -{ - cipher_filter_t *cfx = opaque; - cdk_error_t rc; - byte buf[BUFSIZE]; - int nread, nreq; - - if (!cfx || !in || !out) - return CDK_Inv_Value; - - while (!feof (in)) - { - /*_cdk_log_debug ("partial on=%d size=%lu\n", - cfx->blkmode.on, cfx->blkmode.size);*/ - nreq = cfx->blkmode.on? cfx->blkmode.size : DIM (buf); - nread = fread (buf, 1, nreq, in); - if (!nread) - break; - gcry_cipher_decrypt (cfx->hd, buf, nread, NULL, 0); - if (feof (in) && cfx->mdc) - { - rc = finalize_mdc (cfx->mdc, buf, nread); - if (rc) - { - wipemem (buf, sizeof (buf)); - return rc; - } - /* We need to correct the size here to avoid the MDC - packet will be written to the output. */ - nread -= 22; - } - else if (cfx->mdc) - gcry_md_write (cfx->mdc, buf, nread); - fwrite (buf, 1, nread, out); - if (cfx->blkmode.on) - { - cfx->blkmode.size = _cdk_pkt_read_len (in, &cfx->blkmode.on); - if (cfx->blkmode.size == (size_t)EOF) - return CDK_Inv_Packet; - } - } - - wipemem (buf, sizeof (buf)); - return 0; -} - - -static cdk_error_t -cipher_decode (void * opaque, FILE * in, FILE * out) -{ - cipher_filter_t *cfx = opaque; - cdk_error_t rc; - - _cdk_log_debug ("cipher filter: decode\n"); - - 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) -{ - cipher_filter_t *cfx = opaque; - cdk_error_t rc; - - _cdk_log_debug ("cipher filter: encode\n"); - - if (!cfx || !in || !out) - return CDK_Inv_Value; - - cfx->datalen = fp_get_length (in); - if (cfx->datalen < BUFSIZE && cfx->blkmode.on) - cfx->blkmode.on = 0; - rc = write_header (cfx, out); - if (!rc) - rc = cipher_encode_file (cfx, in, out); - return rc; -} - - -cdk_error_t -_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; - return 0; - } - } - return CDK_Inv_Mode; -} - diff --git a/libextra/opencdk/compress.c b/libextra/opencdk/compress.c deleted file mode 100644 index f9dd0ca2a7..0000000000 --- a/libextra/opencdk/compress.c +++ /dev/null @@ -1,239 +0,0 @@ -/* compress.c - Compression filters - * Copyright (C) 2002, 2003 Timo Schulz - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation - * - * This file is part of OpenCDK. - * - * OpenCDK is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * OpenCDK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include <stdio.h> -#include <time.h> -#ifdef HAVE_LIBZ -# include <zlib.h> -#endif - -#include "opencdk.h" -#include "main.h" -#include "filters.h" - -#ifdef HAVE_LIBZ -static int -compress_data (z_stream *zs, int flush, byte *inbuf, size_t insize, FILE *out) -{ - int nbytes, zrc; - byte buf[4096]; - - zs->next_in = inbuf; - zs->avail_in = insize; - - do - { - zs->next_out = buf; - zs->avail_out = DIM (buf); - - zrc = deflate (zs, flush); - if (zrc == Z_STREAM_END && flush == Z_FINISH) - ; - else if (zrc != Z_OK) - break; - nbytes = DIM (buf) - zs->avail_out; - fwrite (buf, 1, nbytes, out); - } - while (zs->avail_out == 0 || (flush == Z_FINISH && zrc != Z_STREAM_END)); - return zrc; -} - - -static int -decompress_data (compress_filter_t *zfx, z_stream *zs, - FILE *in, size_t *ret_len) -{ - int nread, nold; - int rc, zrc; - - rc = 0; - nread = 0; - while (zs->avail_out != 0) - { - if (!zs->avail_in) - { - nread = fread (zfx->inbuf, 1, zfx->inbufsize, in); - zs->next_in = zfx->inbuf; - zs->avail_in = nread; - } - nold = zs->avail_out; - zrc = inflate (zs, Z_SYNC_FLUSH); - if (zrc != Z_OK && zrc != Z_STREAM_END) - { - rc = CDK_Zlib_Error; - break; - } - *ret_len = zfx->outbufsize - zs->avail_out; - if (nold == zs->avail_out) - break; - if (zrc == Z_STREAM_END) - { - rc = EOF; /* eof */ - break; - } - } - if (!nread && feof (in)) - rc = -1; - return rc; -} - - -static cdk_error_t -compress_decode (void *opaque, FILE *in, FILE *out) -{ - compress_filter_t *zfx = opaque; - z_stream * zs; - size_t nbytes; - int zrc; - cdk_error_t rc = 0; - - _cdk_log_debug ("compress filter: decode (algo=%d)\n", zfx->algo); - - if (!zfx || !in || !out) - return CDK_Inv_Value; - - zs = cdk_calloc (1, sizeof *zs); - if (!zs) - return CDK_Out_Of_Core; - if (zfx->algo == CDK_COMPRESS_ZIP) - zrc = inflateInit2 (zs, -13); - else - zrc = inflateInit (zs); - if (zrc != Z_OK) - return CDK_Zlib_Error; - - zfx->outbufsize = 8192; - zfx->inbufsize = 2048; - memset (zfx->inbuf, 0, sizeof zfx->inbuf); - zs->avail_in = 0; - - nbytes = 0; - while (rc != -1) - { - zs->next_out = zfx->outbuf; - zs->avail_out = 8192; - rc = decompress_data (zfx, zs, in, &nbytes); - fwrite (zfx->outbuf, 1, nbytes, out); - } - inflateEnd (zs); - cdk_free (zs); - if (rc == CDK_EOF) - rc = 0; - return rc; -} - - -static cdk_error_t -compress_encode(void *opaque, FILE *in, FILE *out) -{ - compress_filter_t *zfx = opaque; - z_stream *zs; - struct cdk_pkt_compressed_s cd; - struct cdk_packet_s pkt; - int zrc, nread; - cdk_error_t rc; - - _cdk_log_debug ("compress filter: encode\n"); - - if (!zfx || !in || !out) - return CDK_Inv_Value; - - if (!zfx->algo) - zfx->algo = CDK_COMPRESS_ZIP; - - memset (&cd, 0, sizeof (cd)); - cd.len = 0; - cd.algorithm = zfx->algo; - pkt.pkttype = CDK_PKT_COMPRESSED; - pkt.pkt.compressed = &cd; - rc = _cdk_pkt_write_fp (out, &pkt); - if (rc) - return rc; - - zs = cdk_calloc (1, sizeof *zs); - if (!zs) - return CDK_Out_Of_Core; - if (zfx->algo == CDK_COMPRESS_ZIP) - rc = deflateInit2 (zs, zfx->level, Z_DEFLATED, -13, 8, - Z_DEFAULT_STRATEGY); - else - rc = deflateInit (zs, zfx->level); - if (rc != Z_OK) - { - cdk_free (zs); - return CDK_Zlib_Error; - } - zfx->outbufsize = 8192; - memset (zfx->outbuf, 0, sizeof zfx->outbuf); - - while (!feof (in)) - { - nread = fread (zfx->outbuf, 1, zfx->outbufsize, in); - if (!nread) - break; - zrc = compress_data (zs, Z_NO_FLUSH, zfx->outbuf, nread, out); - if (zrc) - { - rc = CDK_Zlib_Error; - break; - } - } - if (!rc) - { - nread = 0; - zrc = compress_data (zs, Z_FINISH, zfx->outbuf, nread, out); - if (zrc != Z_STREAM_END) - rc = CDK_Zlib_Error; - } - deflateEnd (zs); - cdk_free (zs); - return rc; -} - - -cdk_error_t -_cdk_filter_compress (void *opaque, int ctl, FILE *in, FILE *out) -{ - if (ctl == STREAMCTL_READ) - return compress_decode (opaque, in, out); - else if (ctl == STREAMCTL_WRITE) - return compress_encode (opaque, in, out); - else if (ctl == STREAMCTL_FREE) - { - compress_filter_t * zfx = opaque; - if (zfx) - { - _cdk_log_debug ("free compress filter\n"); - zfx->level = 0; - zfx->algo = 0; - return 0; - } - } - return CDK_Inv_Mode; -} - -#else -cdk_error_t -_cdk_filter_compress (void *opaque, int ctl, FILE *in, FILE *out) -{ - return CDK_Not_Implemented; -} -#endif /* HAVE_LIBZ */ - - diff --git a/libextra/opencdk/misc.c b/libextra/opencdk/misc.c deleted file mode 100644 index eb047f054e..0000000000 --- a/libextra/opencdk/misc.c +++ /dev/null @@ -1,564 +0,0 @@ -/* misc.c - * Copyright (C) 2002, 2003 Timo Schulz - * Copyright (C) 1998-2002, 2007 Free Software Foundation, Inc. - * - * This file is part of OpenCDK. - * - * OpenCDK is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * OpenCDK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <sys/stat.h> - -#include "opencdk.h" -#include "main.h" - - -u32 -_cdk_buftou32 (const byte *buf) -{ - u32 u; - - if (!buf) - return 0; - u = buf[0] << 24; - u |= buf[1] << 16; - u |= buf[2] << 8; - u |= buf[3]; - return u; -} - - -void -_cdk_u32tobuf (u32 u, byte *buf) -{ - if (!buf) - return; - buf[0] = u >> 24; - buf[1] = u >> 16; - buf[2] = u >> 8; - buf[3] = u ; -} - - -static const char * -parse_version_number (const char *s, int *number) -{ - int val = 0; - - if (*s == '0' && isdigit (s[1])) - return NULL; - /* leading zeros are not allowed */ - for (; isdigit(*s); s++) - { - val *= 10; - val += *s - '0'; - } - *number = val; - return val < 0? NULL : s; -} - - -static const char * -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 */ -} - - -/** - * cdk_check_version: - * @req_version: The requested version - * - * Check that the the version of the library is at minimum the requested - * one and return the version string; return NULL if the condition is - * not satisfied. If a NULL is passed to this function, no check is done, - *but the version string is simply returned. - **/ -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; - - 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) - { - sl2 = sl->next; - cdk_free (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) -{ - cdk_strlist_t sl; - - if (!string) - return NULL; - - sl = cdk_calloc (1, sizeof *sl + strlen (string) + 1); - if (!sl) - return NULL; - strcpy (sl->d, string); - sl->next = *list; - *list = sl; - return sl; -} - - -/** - * cdk_strlist_next: - * @root: the opaque string list. - * @r_str: optional argument to store the string data. - * - * Return the next string list node from @root. The optional - * argument @r_str return the data of the current (!) node. - **/ -cdk_strlist_t -cdk_strlist_next (cdk_strlist_t root, const char **r_str) -{ - cdk_strlist_t node; - - if (root && r_str) - *r_str = root->d; - for (node = root->next; node; node = node->next) - return node; - - return NULL; -} - - -const char* -_cdk_memistr (const char *buf, size_t buflen, const char *sub) -{ - const byte *t, *s; - size_t n; - - for (t = (byte*)buf, n = buflen, s = (byte*)sub ; n ; t++, n--) - { - if (toupper (*t) == toupper (*s)) - { - for (buf = t++, buflen = n--, s++; - n && toupper (*t) == toupper ((byte)*s); t++, s++, n--) - ; - if (!*s) - return buf; - t = (byte*)buf; - n = buflen; - s = (byte*)sub; - } - } - - return NULL; -} - - -/** - * cdk_utf8_encode: - * @string: - * - * Encode the given string in utf8 and return it. - **/ -char* -cdk_utf8_encode (const char *string) -{ - const byte *s; - char *buffer; - byte *p; - size_t length; - - /* FIXME: We should use iconv if possible for utf8 issues. */ - for (s = (const byte*)string, length = 0; *s; s++) - { - length++; - if (*s & 0x80) - length++; - } - - buffer = cdk_calloc (1, length + 1); - for (p = (byte*)buffer, s = (byte*)string; *s; s++) - { - if (*s & 0x80) - { - *p++ = 0xc0 | ((*s >> 6) & 3); - *p++ = 0x80 | (*s & 0x3f); - } - else - *p++ = *s; - } - *p = 0; - return buffer; -} - - -/** - * 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) -{ - int nleft; - int i; - byte encbuf[8]; - int encidx; - const byte *s; - size_t n; - byte *buffer = NULL, *p = NULL; - unsigned long val = 0; - size_t slen; - int resync = 0; - - /* 1. pass (p==NULL): count the extended utf-8 characters */ - /* 2. pass (p!=NULL): create string */ - for (;;) - { - for (slen = length, nleft = encidx = 0, n = 0, s = (byte*)string; slen; - s++, slen--) - { - if (resync) - { - if (!(*s < 128 || (*s >= 0xc0 && *s <= 0xfd))) - { - /* still invalid */ - if (p) - { - sprintf ((char*)p, "\\x%02x", *s); - p += 4; - } - n += 4; - continue; - } - resync = 0; - } - if (!nleft) - { - if (!(*s & 0x80)) - { /* plain ascii */ - if (*s < 0x20 || *s == 0x7f || *s == delim || - (delim && *s == '\\')) - { - n++; - if (p) - *p++ = '\\'; - switch (*s) - { - case '\n': - n++; - if (p) - *p++ = 'n'; - break; - case '\r': - n++; - if (p) - *p++ = 'r'; - break; - case '\f': - n++; - if (p) - *p++ = 'f'; - break; - case '\v': - n++; - if (p) - *p++ = 'v'; - break; - case '\b': - n++; - if (p) - *p++ = 'b'; - break; - case 0: - n++; - if (p) - *p++ = '0'; - break; - default: - n += 3; - if (p) - { - sprintf ((char*)p, "x%02x", *s); - p += 3; - } - break; - } - } - else - { - if (p) - *p++ = *s; - n++; - } - } - else if ((*s & 0xe0) == 0xc0) - { /* 110x xxxx */ - val = *s & 0x1f; - nleft = 1; - encidx = 0; - encbuf[encidx++] = *s; - } - else if ((*s & 0xf0) == 0xe0) - { /* 1110 xxxx */ - val = *s & 0x0f; - nleft = 2; - encidx = 0; - encbuf[encidx++] = *s; - } - else if ((*s & 0xf8) == 0xf0) - { /* 1111 0xxx */ - val = *s & 0x07; - nleft = 3; - encidx = 0; - encbuf[encidx++] = *s; - } - else if ((*s & 0xfc) == 0xf8) - { /* 1111 10xx */ - val = *s & 0x03; - nleft = 4; - encidx = 0; - encbuf[encidx++] = *s; - } - else if ((*s & 0xfe) == 0xfc) - { /* 1111 110x */ - val = *s & 0x01; - nleft = 5; - encidx = 0; - encbuf[encidx++] = *s; - } - else - { /* invalid encoding: print as \xnn */ - if (p) - { - sprintf ((char*)p, "\\x%02x", *s); - p += 4; - } - n += 4; - resync = 1; - } - } - else if (*s < 0x80 || *s >= 0xc0) - { /* invalid */ - if (p) - { - for (i = 0; i < encidx; i++) - { - sprintf ((char*)p, "\\x%02x", encbuf[i]); - p += 4; - } - sprintf ((char*)p, "\\x%02x", *s); - p += 4; - } - n += 4 + 4 * encidx; - nleft = 0; - encidx = 0; - resync = 1; - } - else - { - encbuf[encidx++] = *s; - val <<= 6; - val |= *s & 0x3f; - if (!--nleft) - { /* ready native set */ - if (val >= 0x80 && val < 256) - { - n++; /* we can simply print this character */ - if (p) - *p++ = val; - } - else - { /* we do not have a translation: print utf8 */ - if (p) - { - for (i = 0; i < encidx; i++) - { - sprintf ((char*)p, "\\x%02x", encbuf[i]); - p += 4; - } - } - n += encidx * 4; - encidx = 0; - } - } - } - - } - if (!buffer) /* allocate the buffer after the first pass */ - buffer = p = cdk_malloc (n + 1); - else - { - *p = 0; /* make a string */ - return (char*)buffer; - } - } -} - - -/* Map the gcrypt error to a valid opencdk error constant. */ -cdk_error_t -_cdk_map_gcry_error (gcry_error_t err) -{ - /* FIXME: We need to catch them all. */ - switch (gpg_err_code (err)) - { - case GPG_ERR_NO_ERROR: return CDK_Success; - case GPG_ERR_INV_VALUE: return CDK_Inv_Value; - case GPG_ERR_GENERAL: return CDK_General_Error; - case GPG_ERR_INV_PACKET: return CDK_Inv_Packet; - case GPG_ERR_TOO_SHORT: return CDK_Too_Short; - case GPG_ERR_TOO_LARGE: return CDK_Inv_Value; - case GPG_ERR_NO_PUBKEY: - case GPG_ERR_NO_SECKEY: return CDK_Error_No_Key; - case GPG_ERR_BAD_SIGNATURE: return CDK_Bad_Sig; - case GPG_ERR_NO_DATA: return CDK_No_Data; - default: - break; - } - - return (cdk_error_t)err; -} - - -/* Remove all trailing white spaces from the string. */ -void -_cdk_trim_string (char *s, int canon) -{ - while (s && *s && - (s[strlen (s)-1] == '\t' || - s[strlen (s)-1] == '\r' || - s[strlen (s)-1] == '\n' || - s[strlen (s)-1] == ' ')) - s[strlen (s) -1] = '\0'; - if (canon) - strcat (s, "\r\n"); -} - - -int -_cdk_check_args (int overwrite, const char *in, const char *out) -{ - struct stat stbuf; - - if (!in || !out) - return CDK_Inv_Value; - if (strlen (in) == strlen (out) && strcmp (in, out) == 0) - return CDK_Inv_Mode; - if (!overwrite && !stat (out, &stbuf)) - return CDK_Inv_Mode; - return 0; -} - -#ifdef _WIN32 -#include <io.h> -#include <fcntl.h> - -FILE * -my_tmpfile (void) -{ - /* Because the tmpfile() version of wine is not really useful, - we implement our own version to avoid problems with 'make check'. */ - static const char *letters = "abcdefghijklmnopqrstuvwxyz"; - char buf[512], rnd[24]; - FILE *fp; - int fd, i; - - gcry_create_nonce (rnd, DIM (rnd)); - for (i=0; i < DIM (rnd)-1; i++) - { - char c = letters[(unsigned char)rnd[i] % 26]; - rnd[i] = c; - } - rnd[DIM (rnd)-1]=0; - if (!GetTempPath (464, buf)) - return NULL; - strcat (buf, "_cdk_"); - strcat (buf, rnd); - - /* We need to make sure the file will be deleted when it is closed. */ - fd = _open (buf, _O_CREAT | _O_EXCL | _O_TEMPORARY | - _O_RDWR | _O_BINARY, _S_IREAD | _S_IWRITE); - if (fd == -1) - return NULL; - fp = fdopen (fd, "w+b"); - if (fp != NULL) - return fp; - _close (fd); - return NULL; -} -#else -FILE* -my_tmpfile (void) -{ - return tmpfile (); -} -#endif diff --git a/src/Makefile.am b/src/Makefile.am index 37ad263684..d5c8910c1f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -36,35 +36,35 @@ endif gnutls_serv_SOURCES = serv.gaa serv-gaa.h serv-gaa.c list.h serv.c \ common.h common.c select.c -gnutls_serv_LDADD = ../lib/libgnutls.la ../libextra/libgnutls-extra.la \ +gnutls_serv_LDADD = ../lib/libgnutls.la \ $(LIBGCRYPT_LIBS) $(LIBTASN1_LIBS) ../gl/libgnu.la if ENABLE_SRP srptool_SOURCES = crypt.gaa crypt-gaa.h crypt-gaa.c crypt.c -srptool_LDADD = ../lib/libgnutls.la ../libextra/libgnutls-extra.la \ +srptool_LDADD = ../lib/libgnutls.la \ $(LIBGCRYPT_LIBS) $(LIBTASN1_LIBS) \ ../gl/libgnu.la ../lgl/liblgnu.la endif psktool_SOURCES = psk.gaa psk-gaa.h psk-gaa.c psk.c -psktool_LDADD = ../lib/libgnutls.la ../libextra/libgnutls-extra.la \ +psktool_LDADD = ../lib/libgnutls.la \ $(LIBGCRYPT_LIBS) $(LIBTASN1_LIBS) \ ../gl/libgnu.la ../lgl/liblgnu.la gnutls_cli_SOURCES = cli.gaa cli-gaa.h cli-gaa.c cli.c common.h \ common.c select.c -gnutls_cli_LDADD = ../lib/libgnutls.la ../libextra/libgnutls-extra.la \ +gnutls_cli_LDADD = ../lib/libgnutls.la \ $(LIBGCRYPT_LIBS) $(LIBTASN1_LIBS) ../gl/libgnu.la gnutls_cli_debug_SOURCES = tls_test.gaa tls_test-gaa.h tls_test-gaa.c \ tls_test.c tests.h tests.c common.h common.c gnutls_cli_debug_LDADD = ../lib/libgnutls.la \ - ../libextra/libgnutls-extra.la $(LIBGCRYPT_LIBS) \ + $(LIBGCRYPT_LIBS) \ $(LIBTASN1_LIBS) ../gl/libgnu.la certtool_SOURCES = certtool.gaa certtool-gaa.h certtool-cfg.h \ certtool-gaa.c certtool.c prime.c certtool-cfg.c -certtool_LDADD = ../lib/libgnutls.la $(LIBGCRYPT_LIBS) \ +certtool_LDADD = ../lib/libgnutls.la $(LIBGCRYPT_LIBS) \ $(LIBTASN1_LIBS) ../gl/libgnu.la @LTLIBREADLINE@ if HAVE_LIBCFG certtool_LDADD += -lcfg+ diff --git a/src/certtool-gaa.c b/src/certtool-gaa.c index d6835e2c38..77130b6b10 100644 --- a/src/certtool-gaa.c +++ b/src/certtool-gaa.c @@ -147,6 +147,7 @@ void gaa_help(void) __gaa_helpsingle(0, "load-ca-certificate", "FILE ", "Certificate authority's certificate file to use."); __gaa_helpsingle(0, "password", "PASSWORD ", "Password to use."); __gaa_helpsingle('i', "certificate-info", "", "Print information on a certificate."); + __gaa_helpsingle(0, "pgp-certificate-info", "", "Print information on a OpenPGP certificate."); __gaa_helpsingle('l', "crl-info", "", "Print information on a CRL."); __gaa_helpsingle(0, "p12-info", "", "Print information on a PKCS #12 structure."); __gaa_helpsingle(0, "p7-info", "", "Print information on a PKCS #7 structure."); @@ -155,7 +156,7 @@ void gaa_help(void) __gaa_helpsingle(0, "fix-key", "", "Regenerate the parameters in a private key."); __gaa_helpsingle(0, "v1", "", "Generate an X.509 version 1 certificate (no extensions)."); __gaa_helpsingle(0, "to-p12", "", "Generate a PKCS #12 structure."); - __gaa_helpsingle(0, "to-p8", "", "Generate a PKCS #8 structure."); + __gaa_helpsingle(0, "to-p8", "", "Generate a PKCS #8 key structure."); __gaa_helpsingle('8', "pkcs8", "", "Use PKCS #8 format for private keys."); __gaa_helpsingle(0, "dsa", "", "Use DSA keys."); __gaa_helpsingle(0, "hash", "STR ", "Hash algorithm to use for signing (MD5,SHA1,RMD160,SHA256,SHA384,SHA512)."); @@ -184,33 +185,33 @@ typedef struct _gaainfo gaainfo; struct _gaainfo { -#line 112 "certtool.gaa" +#line 114 "certtool.gaa" int debug; -#line 108 "certtool.gaa" +#line 110 "certtool.gaa" char *template; -#line 105 "certtool.gaa" +#line 107 "certtool.gaa" char *infile; -#line 102 "certtool.gaa" +#line 104 "certtool.gaa" char *outfile; -#line 99 "certtool.gaa" +#line 101 "certtool.gaa" int quick_random; -#line 96 "certtool.gaa" +#line 98 "certtool.gaa" int bits; -#line 93 "certtool.gaa" +#line 95 "certtool.gaa" int outcert_format; -#line 90 "certtool.gaa" +#line 92 "certtool.gaa" int incert_format; -#line 87 "certtool.gaa" +#line 89 "certtool.gaa" int export; -#line 84 "certtool.gaa" +#line 86 "certtool.gaa" char *hash; -#line 81 "certtool.gaa" +#line 83 "certtool.gaa" int dsa; -#line 78 "certtool.gaa" +#line 80 "certtool.gaa" int pkcs8; -#line 71 "certtool.gaa" +#line 73 "certtool.gaa" int v1_cert; -#line 68 "certtool.gaa" +#line 70 "certtool.gaa" int fix_key; #line 53 "certtool.gaa" char *pass; @@ -280,7 +281,7 @@ static int gaa_error = 0; #define GAA_MULTIPLE_OPTION 3 #define GAA_REST 0 -#define GAA_NB_OPTION 41 +#define GAA_NB_OPTION 42 #define GAAOPTID_version 1 #define GAAOPTID_help 2 #define GAAOPTID_debug 3 @@ -304,24 +305,25 @@ static int gaa_error = 0; #define GAAOPTID_p7_info 21 #define GAAOPTID_p12_info 22 #define GAAOPTID_crl_info 23 -#define GAAOPTID_certificate_info 24 -#define GAAOPTID_password 25 -#define GAAOPTID_load_ca_certificate 26 -#define GAAOPTID_load_ca_privkey 27 -#define GAAOPTID_load_certificate 28 -#define GAAOPTID_load_request 29 -#define GAAOPTID_load_privkey 30 -#define GAAOPTID_get_dh_params 31 -#define GAAOPTID_generate_dh_params 32 -#define GAAOPTID_verify_crl 33 -#define GAAOPTID_verify_chain 34 -#define GAAOPTID_generate_request 35 -#define GAAOPTID_generate_privkey 36 -#define GAAOPTID_update_certificate 37 -#define GAAOPTID_generate_crl 38 -#define GAAOPTID_generate_proxy 39 -#define GAAOPTID_generate_certificate 40 -#define GAAOPTID_generate_self_signed 41 +#define GAAOPTID_pgp_certificate_info 24 +#define GAAOPTID_certificate_info 25 +#define GAAOPTID_password 26 +#define GAAOPTID_load_ca_certificate 27 +#define GAAOPTID_load_ca_privkey 28 +#define GAAOPTID_load_certificate 29 +#define GAAOPTID_load_request 30 +#define GAAOPTID_load_privkey 31 +#define GAAOPTID_get_dh_params 32 +#define GAAOPTID_generate_dh_params 33 +#define GAAOPTID_verify_crl 34 +#define GAAOPTID_verify_chain 35 +#define GAAOPTID_generate_request 36 +#define GAAOPTID_generate_privkey 37 +#define GAAOPTID_update_certificate 38 +#define GAAOPTID_generate_crl 39 +#define GAAOPTID_generate_proxy 40 +#define GAAOPTID_generate_certificate 41 +#define GAAOPTID_generate_self_signed 42 #line 168 "gaa.skel" @@ -640,6 +642,7 @@ static int gaa_get_option_num(char *str, int status) GAA_CHECK1STR("", GAAOPTID_p7_info); GAA_CHECK1STR("", GAAOPTID_p12_info); GAA_CHECK1STR("l", GAAOPTID_crl_info); + GAA_CHECK1STR("", GAAOPTID_pgp_certificate_info); GAA_CHECK1STR("i", GAAOPTID_certificate_info); GAA_CHECK1STR("", GAAOPTID_get_dh_params); GAA_CHECK1STR("", GAAOPTID_generate_dh_params); @@ -679,6 +682,7 @@ static int gaa_get_option_num(char *str, int status) GAA_CHECKSTR("p7-info", GAAOPTID_p7_info); GAA_CHECKSTR("p12-info", GAAOPTID_p12_info); GAA_CHECKSTR("crl-info", GAAOPTID_crl_info); + GAA_CHECKSTR("pgp-certificate-info", GAAOPTID_pgp_certificate_info); GAA_CHECKSTR("certificate-info", GAAOPTID_certificate_info); GAA_CHECKSTR("password", GAAOPTID_password); GAA_CHECKSTR("load-ca-certificate", GAAOPTID_load_ca_certificate); @@ -743,14 +747,14 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) { case GAAOPTID_version: OK = 0; -#line 117 "certtool.gaa" +#line 119 "certtool.gaa" { certtool_version(); exit(0); ;}; return GAA_OK; break; case GAAOPTID_help: OK = 0; -#line 115 "certtool.gaa" +#line 117 "certtool.gaa" { gaa_help(); exit(0); ;}; return GAA_OK; @@ -760,7 +764,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_debug.arg1, gaa_getint, GAATMP_debug.size1); gaa_index++; -#line 113 "certtool.gaa" +#line 115 "certtool.gaa" { gaaval->debug = GAATMP_debug.arg1 ;}; return GAA_OK; @@ -770,7 +774,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_template.arg1, gaa_getstr, GAATMP_template.size1); gaa_index++; -#line 109 "certtool.gaa" +#line 111 "certtool.gaa" { gaaval->template = GAATMP_template.arg1 ;}; return GAA_OK; @@ -780,7 +784,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_infile.arg1, gaa_getstr, GAATMP_infile.size1); gaa_index++; -#line 106 "certtool.gaa" +#line 108 "certtool.gaa" { gaaval->infile = GAATMP_infile.arg1 ;}; return GAA_OK; @@ -790,14 +794,14 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_outfile.arg1, gaa_getstr, GAATMP_outfile.size1); gaa_index++; -#line 103 "certtool.gaa" +#line 105 "certtool.gaa" { gaaval->outfile = GAATMP_outfile.arg1 ;}; return GAA_OK; break; case GAAOPTID_disable_quick_random: OK = 0; -#line 100 "certtool.gaa" +#line 102 "certtool.gaa" { gaaval->quick_random = 0; ;}; return GAA_OK; @@ -807,28 +811,28 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_bits.arg1, gaa_getint, GAATMP_bits.size1); gaa_index++; -#line 97 "certtool.gaa" +#line 99 "certtool.gaa" { gaaval->bits = GAATMP_bits.arg1 ;}; return GAA_OK; break; case GAAOPTID_outder: OK = 0; -#line 94 "certtool.gaa" +#line 96 "certtool.gaa" { gaaval->outcert_format=1 ;}; return GAA_OK; break; case GAAOPTID_inder: OK = 0; -#line 91 "certtool.gaa" +#line 93 "certtool.gaa" { gaaval->incert_format=1 ;}; return GAA_OK; break; case GAAOPTID_export_ciphers: OK = 0; -#line 88 "certtool.gaa" +#line 90 "certtool.gaa" { gaaval->export=1 ;}; return GAA_OK; @@ -838,88 +842,95 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_hash.arg1, gaa_getstr, GAATMP_hash.size1); gaa_index++; -#line 85 "certtool.gaa" +#line 87 "certtool.gaa" { gaaval->hash = GAATMP_hash.arg1 ;}; return GAA_OK; break; case GAAOPTID_dsa: OK = 0; -#line 82 "certtool.gaa" +#line 84 "certtool.gaa" { gaaval->dsa=1 ;}; return GAA_OK; break; case GAAOPTID_pkcs8: OK = 0; -#line 79 "certtool.gaa" +#line 81 "certtool.gaa" { gaaval->pkcs8=1 ;}; return GAA_OK; break; case GAAOPTID_to_p8: OK = 0; -#line 76 "certtool.gaa" +#line 78 "certtool.gaa" { gaaval->action = 18; ;}; return GAA_OK; break; case GAAOPTID_to_p12: OK = 0; -#line 74 "certtool.gaa" +#line 76 "certtool.gaa" { gaaval->action = 8; ;}; return GAA_OK; break; case GAAOPTID_v1: OK = 0; -#line 72 "certtool.gaa" +#line 74 "certtool.gaa" { gaaval->v1_cert = 1; ;}; return GAA_OK; break; case GAAOPTID_fix_key: OK = 0; -#line 69 "certtool.gaa" +#line 71 "certtool.gaa" { gaaval->fix_key = 1; ;}; return GAA_OK; break; case GAAOPTID_key_info: OK = 0; -#line 66 "certtool.gaa" +#line 68 "certtool.gaa" { gaaval->action = 6; ;}; return GAA_OK; break; case GAAOPTID_smime_to_p7: OK = 0; -#line 64 "certtool.gaa" +#line 66 "certtool.gaa" { gaaval->action = 15; ;}; return GAA_OK; break; case GAAOPTID_p7_info: OK = 0; -#line 62 "certtool.gaa" +#line 64 "certtool.gaa" { gaaval->action = 12; ;}; return GAA_OK; break; case GAAOPTID_p12_info: OK = 0; -#line 60 "certtool.gaa" +#line 62 "certtool.gaa" { gaaval->action = 9; ;}; return GAA_OK; break; case GAAOPTID_crl_info: OK = 0; -#line 58 "certtool.gaa" +#line 60 "certtool.gaa" { gaaval->action = 11; ;}; return GAA_OK; break; + case GAAOPTID_pgp_certificate_info: + OK = 0; +#line 58 "certtool.gaa" +{ gaaval->action = 19; ;}; + + return GAA_OK; + break; case GAAOPTID_certificate_info: OK = 0; #line 56 "certtool.gaa" @@ -1088,7 +1099,7 @@ int gaa(int argc, char **argv, gaainfo *gaaval) if(inited == 0) { -#line 119 "certtool.gaa" +#line 121 "certtool.gaa" { gaaval->bits = 2048; gaaval->pkcs8 = 0; gaaval->privkey = NULL; gaaval->ca=NULL; gaaval->ca_privkey = NULL; gaaval->debug=1; gaaval->request = NULL; gaaval->infile = NULL; gaaval->outfile = NULL; gaaval->cert = NULL; gaaval->incert_format = 0; gaaval->outcert_format = 0; gaaval->action=-1; gaaval->pass = NULL; gaaval->v1_cert = 0; diff --git a/src/certtool-gaa.h b/src/certtool-gaa.h index 2965344059..a7f70bbc6f 100644 --- a/src/certtool-gaa.h +++ b/src/certtool-gaa.h @@ -8,33 +8,33 @@ typedef struct _gaainfo gaainfo; struct _gaainfo { -#line 112 "certtool.gaa" +#line 114 "certtool.gaa" int debug; -#line 108 "certtool.gaa" +#line 110 "certtool.gaa" char *template; -#line 105 "certtool.gaa" +#line 107 "certtool.gaa" char *infile; -#line 102 "certtool.gaa" +#line 104 "certtool.gaa" char *outfile; -#line 99 "certtool.gaa" +#line 101 "certtool.gaa" int quick_random; -#line 96 "certtool.gaa" +#line 98 "certtool.gaa" int bits; -#line 93 "certtool.gaa" +#line 95 "certtool.gaa" int outcert_format; -#line 90 "certtool.gaa" +#line 92 "certtool.gaa" int incert_format; -#line 87 "certtool.gaa" +#line 89 "certtool.gaa" int export; -#line 84 "certtool.gaa" +#line 86 "certtool.gaa" char *hash; -#line 81 "certtool.gaa" +#line 83 "certtool.gaa" int dsa; -#line 78 "certtool.gaa" +#line 80 "certtool.gaa" int pkcs8; -#line 71 "certtool.gaa" +#line 73 "certtool.gaa" int v1_cert; -#line 68 "certtool.gaa" +#line 70 "certtool.gaa" int fix_key; #line 53 "certtool.gaa" char *pass; diff --git a/src/certtool.c b/src/certtool.c index 56b71dec84..ff006ff169 100644 --- a/src/certtool.c +++ b/src/certtool.c @@ -26,6 +26,7 @@ #include <string.h> #include <ctype.h> #include <gnutls/x509.h> +#include <gnutls/openpgp.h> #include <time.h> #include "certtool-gaa.h" #include <gnutls/pkcs12.h> @@ -55,6 +56,7 @@ gnutls_x509_privkey_t load_ca_private_key (void); gnutls_x509_crt_t load_ca_cert (void); gnutls_x509_crt_t load_cert (int mand); void certificate_info (void); +void pgp_certificate_info (void); void crl_info (void); void privkey_info (void); static void print_certificate_info (gnutls_x509_crt_t crt, FILE * out, @@ -897,6 +899,9 @@ gaa_parser (int argc, char **argv) case 18: generate_pkcs8 (); break; + case 19: + pgp_certificate_info(); + break; default: gaa_help (); exit (0); @@ -959,6 +964,52 @@ certificate_info (void) } } +void +pgp_certificate_info (void) +{ + gnutls_openpgp_crt_t crt; + size_t size; + int ret, i, count; + gnutls_datum_t pem, out_data; + + pem.data = fread_file (infile, &size); + pem.size = size; + + ret = gnutls_openpgp_crt_init( &crt); + if (ret < 0) + error (EXIT_FAILURE, 0, "openpgp_crt_init: %s", gnutls_strerror (ret)); + + ret = gnutls_openpgp_crt_import (crt, &pem, info.incert_format); + + if (ret < 0) + error (EXIT_FAILURE, 0, "Import error: %s", gnutls_strerror (ret)); + + free (pem.data); + + if (info.outcert_format == GNUTLS_OPENPGP_FMT_BASE64) + { + ret = gnutls_openpgp_crt_print (crt, 0, &out_data); + + if (ret == 0) + { + fprintf (outfile, "%s\n", out_data.data); + gnutls_free (out_data.data); + } + } + + size = sizeof (buffer); + ret = gnutls_openpgp_crt_export (crt, info.outcert_format, buffer, + &size); + if (ret < 0) { + error (EXIT_FAILURE, 0, "Export error: %s", gnutls_strerror (ret)); + fwrite (buffer, 1, size, outfile); + } + + fprintf (outfile, "%s\n", buffer); + + gnutls_openpgp_crt_deinit( crt); +} + static void print_hex_datum (gnutls_datum_t * dat) { diff --git a/src/certtool.gaa b/src/certtool.gaa index 51c3545136..9575ab4184 100644 --- a/src/certtool.gaa +++ b/src/certtool.gaa @@ -55,6 +55,8 @@ option (password) STR "PASSWORD" { $pass = $1 } "Password to use." option (i, certificate-info) { $action = 2; } "Print information on a certificate." +option (pgp-certificate-info) { $action = 19; } "Print information on a OpenPGP certificate." + option (l, crl-info) { $action = 11; } "Print information on a CRL." option (p12-info) { $action = 9; } "Print information on a PKCS #12 structure." @@ -419,8 +419,10 @@ const char *err; gnutls_certificate_client_set_retrieve_function (xcred, cert_callback); /* send the fingerprint */ +#ifdef ENABLE_OPENPGP if (fingerprint != 0) gnutls_openpgp_send_cert (session, GNUTLS_OPENPGP_CERT_FINGERPRINT); +#endif /* use the max record size extension */ if (record_max_size > 0 && disable_extensions == 0) @@ -532,12 +534,6 @@ main (int argc, char **argv) exit (1); } - if ((ret = gnutls_global_init_extra ()) < 0) - { - fprintf (stderr, "global_init_extra: %s\n", gnutls_strerror (ret)); -// exit (1); - } - gaa_parser (argc, argv); if (hostname == NULL) { diff --git a/src/serv.c b/src/serv.c index 0ff113d750..b16c18be78 100644 --- a/src/serv.c +++ b/src/serv.c @@ -837,12 +837,6 @@ main (int argc, char **argv) gnutls_global_set_log_function (tls_log_func); gnutls_global_set_log_level (debug); - if ((ret = gnutls_global_init_extra ()) < 0) - { - fprintf (stderr, "global_init_extra: %s\n", gnutls_strerror (ret)); - exit (1); - } - /* Note that servers must generate parameters for * Diffie Hellman. See gnutls_dh_params_generate(), and * gnutls_dh_params_set(). diff --git a/src/tls_test.c b/src/tls_test.c index fcb0bba9bb..1422a46a91 100644 --- a/src/tls_test.c +++ b/src/tls_test.c @@ -187,12 +187,6 @@ main (int argc, char **argv) gnutls_global_set_log_function (tls_log_func); gnutls_global_set_log_level (debug); - if (gnutls_global_init_extra () < 0) - { - fprintf (stderr, "global state initialization error\n"); - exit (1); - } - printf ("Resolving '%s'...\n", hostname); /* get server name */ memset (&hints, 0, sizeof (hints)); |