diff options
author | Simon Josefsson <simon@josefsson.org> | 2005-12-15 10:52:19 +0000 |
---|---|---|
committer | Simon Josefsson <simon@josefsson.org> | 2005-12-15 10:52:19 +0000 |
commit | 3860714e697158a17086fff6a87fa9d22877895a (patch) | |
tree | db6ae00dc003790ce52fc23fb7c100db8498ffeb | |
parent | 1b6f0a191d7dd2ab25da837494a53992e01b9229 (diff) | |
download | gnutls-3860714e697158a17086fff6a87fa9d22877895a.tar.gz |
Add TLS/IA support.
-rw-r--r-- | NEWS | 57 | ||||
-rw-r--r-- | doc/Makefile.am | 21 | ||||
-rw-r--r-- | doc/examples/ex-client-tlsia.c | 161 | ||||
-rw-r--r-- | doc/gnutls.texi | 64 | ||||
-rw-r--r-- | doc/manpages/Makefile.am | 2 | ||||
-rw-r--r-- | includes/gnutls/extra.h | 81 | ||||
-rw-r--r-- | includes/gnutls/gnutls.h.in | 24 | ||||
-rw-r--r-- | lib/Makefile.am | 8 | ||||
-rw-r--r-- | lib/debug.c | 2 | ||||
-rw-r--r-- | lib/defines.h | 1 | ||||
-rw-r--r-- | lib/ext_inner_application.c | 121 | ||||
-rw-r--r-- | lib/ext_inner_application.h | 29 | ||||
-rw-r--r-- | lib/gnutls_alert.c | 4 | ||||
-rw-r--r-- | lib/gnutls_buffers.c | 64 | ||||
-rw-r--r-- | lib/gnutls_constate.c | 3 | ||||
-rw-r--r-- | lib/gnutls_errors.c | 8 | ||||
-rw-r--r-- | lib/gnutls_extensions.c | 22 | ||||
-rw-r--r-- | lib/gnutls_int.h | 16 | ||||
-rw-r--r-- | lib/gnutls_kx.c | 4 | ||||
-rw-r--r-- | lib/gnutls_record.c | 26 | ||||
-rw-r--r-- | lib/gnutls_state.c | 2 | ||||
-rw-r--r-- | libextra/Makefile.am | 31 | ||||
-rw-r--r-- | libextra/gnutls_ia.c | 916 | ||||
-rw-r--r-- | tests/Makefile.am | 6 | ||||
-rw-r--r-- | tests/tlsia.c | 575 |
25 files changed, 2181 insertions, 67 deletions
@@ -5,6 +5,11 @@ See the end for copying conditions. * Version 1.3.2 (unreleased) +** GnuTLS now support TLS Inner application (TLS/IA). +This is per draft-funk-tls-inner-application-extension-01. This +functionality is added to libgnutls-extra, so it is licensed under the +GPL. + ** Internal type cleanups. The uint8, uint16, uint32 types have been replaced by uint8_t, uint16_t, uint32_t. Gnulib is used to guarantee the presence of @@ -12,7 +17,57 @@ correct types on platforms that lack them. The uint type have been replaced by unsigned. ** API and ABI modifications: -None +New function, to perform TLS/IA handshake: + gnutls_ia_handshake + +New function to decide whether to do a TLS/IA handshake: + gnutls_ia_handshake_p + +New functions to allocate a TLS/IA credential: + gnutls_ia_allocate_client_credentials + gnutls_ia_free_client_credentials + gnutls_ia_allocate_server_credentials + gnutls_ia_free_server_credentials + +New functions to handle the AVP callback: + gnutls_ia_set_client_avp_function + gnutls_ia_set_client_avp_ptr + gnutls_ia_get_client_avp_ptr + gnutls_ia_set_server_avp_function + gnutls_ia_set_server_avp_ptr + gnutls_ia_get_server_avp_ptr + +New functions, to toggle TLS/IA application phases: + gnutls_ia_require_inner_phase + +New function to mix session keys with inner secret: + gnutls_ia_permute_inner_secret + +Low-level API: + gnutls_ia_endphase_send + gnutls_ia_send + gnutls_ia_recv + +New functions that can be used after successful TLS/IA negotiation: + gnutls_ia_generate_challenge + gnutls_ia_extract_inner_secret + +Enum type with TLS/IA modes: + gnutls_ia_mode_t + +Enum type with TLS/IA packet types: + gnutls_ia_apptype_t + +Enum values for TLS/IA alerts: + GNUTLS_A_INNER_APPLICATION_FAILURE + GNUTLS_A_INNER_APPLICATION_VERIFICATION + +New error codes, to signal when an application phase has finished: + GNUTLS_E_WARNING_IA_IPHF_RECEIVED + GNUTLS_E_WARNING_IA_FPHF_RECEIVED + +New error code to signal TLS/IA verify failure: + GNUTLS_E_IA_VERIFY_FAILED * Version 1.3.1 (released 2005-12-08) diff --git a/doc/Makefile.am b/doc/Makefile.am index 1056f2124b..81e433ada3 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -27,13 +27,14 @@ SUBDIRS += reference endif info_TEXINFOS = gnutls.texi -gnutls_TEXINFOS = gnutls.texi signatures.texi fdl.texi error_codes.texi bibliography.texi \ - gnutls-api.texi gnutls-extra-api.texi x509-api.texi \ - my-bib-macros.texi internals.texi \ - pgp-api.texi examples/ex-client1.c examples/ex-client2.c \ - examples/ex-session-info.c examples/ex-verify.c \ - examples/ex-cert-select.c examples/ex-client-resume.c \ - examples/ex-client-srp.c examples/ex-rfc2818.c \ +gnutls_TEXINFOS = gnutls.texi signatures.texi fdl.texi \ + error_codes.texi bibliography.texi gnutls-api.texi \ + gnutls-extra-api.texi ia-api.texi x509-api.texi pgp-api.texi \ + my-bib-macros.texi internals.texi examples/ex-client1.c \ + examples/ex-client2.c examples/ex-session-info.c \ + examples/ex-verify.c examples/ex-cert-select.c \ + examples/ex-client-resume.c examples/ex-client-srp.c \ + examples/ex-client-tlsia.c examples/ex-rfc2818.c \ examples/ex-serv1.c examples/ex-serv-export.c \ examples/ex-serv-anon.c examples/ex-serv-pgp.c \ examples/ex-serv-srp.c examples/ex-alert.c \ @@ -55,6 +56,9 @@ AM_MAKEINFOHTMLFLAGS = --no-split ../libextra/openpgp/pgp-api.texi: cd ../libextra/openpgp && make pgp-api.texi +../libextra/ia-api.texi: + cd ../libextra && make ia-api.texi + gnutls-api.texi: ../lib/gnutls-api.texi -scripts/sort2.pl < ../lib/gnutls-api.texi > gnutls-api.texi @@ -67,5 +71,8 @@ x509-api.texi: ../lib/x509/x509-api.texi pgp-api.texi: ../libextra/openpgp/pgp-api.texi -scripts/sort2.pl < ../libextra/openpgp/pgp-api.texi > pgp-api.texi +ia-api.texi: ../libextra/ia-api.texi + -scripts/sort2.pl < ../libextra/ia-api.texi > ia-api.texi + error_codes.texi: ../lib/gnutls_errors.c ../src/errcodes.c -../src/errcodes > error_codes.texi diff --git a/doc/examples/ex-client-tlsia.c b/doc/examples/ex-client-tlsia.c new file mode 100644 index 0000000000..d63e7fb4bd --- /dev/null +++ b/doc/examples/ex-client-tlsia.c @@ -0,0 +1,161 @@ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <unistd.h> +#include <gnutls/gnutls.h> +#include <gnutls/extra.h> + +/* A basic TLS client, with anonymous authentication and TLS/IA handshake. + */ + +#define MAX_BUF 1024 +#define SA struct sockaddr +#define MSG "GET / HTTP/1.0\r\n\r\n" + +extern int tcp_connect (void); +extern void tcp_close (int sd); + +int +client_avp (gnutls_session_t session, void *ptr, + const char *last, size_t lastlen, + char **new, size_t *newlen) +{ + + if (last) + printf ("- received %d bytes AVP: `%.*s'\n", + lastlen, lastlen, last); + else + printf ("- new application phase\n"); + + *new = gnutls_strdup ("client avp"); + if (!*new) + return -1; + *newlen = strlen (*new); + + printf ("- sending %d bytes AVP: `%s'\n", *newlen, *new); + + gnutls_ia_permute_inner_secret (session, 3, "foo"); + + return 0; + +} + +int +main (void) +{ + int ret, sd, ii; + gnutls_session_t session; + char buffer[MAX_BUF + 1]; + gnutls_anon_client_credentials_t anoncred; + gnutls_ia_client_credentials_t iacred; + /* Need to enable anonymous KX specifically. */ + const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 }; + + gnutls_global_init (); + + gnutls_anon_allocate_client_credentials (&anoncred); + gnutls_ia_allocate_client_credentials (&iacred); + + /* Set TLS/IA stuff + */ + gnutls_ia_set_client_avp_function (iacred, client_avp); + + /* Initialize TLS session + */ + gnutls_init (&session, GNUTLS_CLIENT); + + /* Use default priorities */ + gnutls_set_default_priority (session); + gnutls_kx_set_priority (session, kx_prio); + + /* put the anonymous and TLS/IA credentials to the current session + */ + gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred); + gnutls_credentials_set (session, GNUTLS_CRD_IA, iacred); + + /* connect to the peer + */ + sd = tcp_connect (); + + gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd); + + /* Perform the TLS handshake + */ + ret = gnutls_handshake (session); + + if (ret < 0) + { + fprintf (stderr, "*** Handshake failed\n"); + gnutls_perror (ret); + goto end; + } + else + { + printf ("- Handshake was completed\n"); + } + + if (!gnutls_ia_handshake_p (session)) + { + fprintf (stderr, "*** TLS/IA not negotiated...\n"); + goto end; + } + else + { + printf ("- Starting TLS/IA handshake...\n"); + + ret = gnutls_ia_handshake (session); + + if (ret < 0) + { + fprintf (stderr, "*** TLS/IA handshake failed\n"); + gnutls_perror (ret); + goto end; + } + else + { + printf ("- TLS/IA Handshake was completed\n"); + } + } + + + gnutls_record_send (session, MSG, strlen (MSG)); + + ret = gnutls_record_recv (session, buffer, MAX_BUF); + if (ret == 0) + { + printf ("- Peer has closed the TLS connection\n"); + goto end; + } + else if (ret < 0) + { + fprintf (stderr, "*** Error: %s\n", gnutls_strerror (ret)); + goto end; + } + + printf ("- Received %d bytes: ", ret); + for (ii = 0; ii < ret; ii++) + { + fputc (buffer[ii], stdout); + } + fputs ("\n", stdout); + + gnutls_bye (session, GNUTLS_SHUT_RDWR); + +end: + + tcp_close (sd); + + gnutls_deinit (session); + + gnutls_ia_free_client_credentials (iacred); + gnutls_anon_free_client_credentials (anoncred); + + gnutls_global_deinit (); + + return 0; +} diff --git a/doc/gnutls.texi b/doc/gnutls.texi index 2a7927ab90..8daa898c17 100644 --- a/doc/gnutls.texi +++ b/doc/gnutls.texi @@ -2510,6 +2510,7 @@ signing_key * X.509 certificate functions:: * GnuTLS-extra functions:: * OpenPGP functions:: +* TLS Inner Application (TLS/IA) functions:: * Error codes and descriptions:: @end menu @@ -2546,11 +2547,70 @@ called @code{gnutls-extra}. The prototypes for this library lie in @cindex @acronym{OpenPGP} functions @anchor{sec:openpgpapi} -The following functions are to be used for @acronym{OpenPGP} certificate -handling. Their prototypes lie in @file{gnutls/openpgp.h}. +The following functions are to be used for @acronym{OpenPGP} +certificate handling. Their prototypes lie in +@file{gnutls/openpgp.h}. You need to link with @file{libgnutls-extra} +to be able to use these functions (@pxref{GnuTLS-extra functions}). @include pgp-api.texi +@node TLS Inner Application (TLS/IA) functions +@section @acronym{TLS} Inner Application (@acronym{TLS/IA}) functions +@cindex @acronym{TLS} Inner Application (@acronym{TLS/IA}) functions +@cindex Inner Application (@acronym{TLS/IA}) functions + +The following functions are used for @acronym{TLS} Inner Application +(@acronym{TLS/IA}). Their prototypes lie in @file{gnutls/extra.h}. +You need to link with @file{libgnutls-extra} to be able to use these +functions (@pxref{GnuTLS-extra functions}). + +The typical control flow in an TLS/IA client (that would not require +an Application Phase for resumed sessions) would be similar to the +following: + +@example +int client_avp (gnuls_session_t *session, void *ptr, + const char *last, size_t lastlen, + char **new, size_t *newlen) +@{ +... +@} +... +int main () +@{ + gnutls_ia_client_credentials_t iacred; +... + gnutls_init (&session, GNUTLS_CLIENT); +... + /* Enable TLS/IA. */ + gnutls_ia_allocate_client_credentials(&iacred); + gnutls_ia_set_client_avp_function(iacred, client_avp); + gnutls_credentials_set (session, GNUTLS_CRD_IA, iacred); +... + ret = gnutls_handshake (session); + // Error handling... +... + if (gnutls_ia_handshake_p (session)) + @{ + ret = gnutls_ia_handshake (session); + // Error handling... +... +@end example + +See below for detailed descriptions of all the functions used above. + +The function @code{client_avp} would have to be implemented by your +application. The function is responsible for handling the AVP data. +See @code{gnutls_ia_set_client_avp_function} below for more +information on how that function should be implemented. + +The control flow in a typical server is similar to the above, use +@code{gnutls_ia_server_credentials_t} instead of +@code{gnutls_ia_client_credentials_t}, and replace the call to the +client functions with the corresponding server functions. + +@include ia-api.texi + @node Error codes and descriptions @section Error codes and descriptions @anchor{Error Codes} diff --git a/doc/manpages/Makefile.am b/doc/manpages/Makefile.am index c34244ed36..1e0fc195fa 100644 --- a/doc/manpages/Makefile.am +++ b/doc/manpages/Makefile.am @@ -26,7 +26,7 @@ if ENABLE_SRP dist_man_MANS += srptool.1 endif -APIMANS = gnutls_server_name_get.3 gnutls_server_name_set.3 gnutls_alert_get_name.3 gnutls_alert_send.3 gnutls_error_to_alert.3 gnutls_alert_send_appropriate.3 gnutls_alert_get.3 gnutls_mac_get_name.3 gnutls_compression_get_name.3 gnutls_cipher_get_key_size.3 gnutls_cipher_get_name.3 gnutls_kx_get_name.3 gnutls_protocol_get_name.3 gnutls_cipher_suite_get_name.3 gnutls_certificate_type_get_name.3 gnutls_sign_algorithm_get_name.3 gnutls_pk_algorithm_get_name.3 gnutls_anon_free_server_credentials.3 gnutls_anon_allocate_server_credentials.3 gnutls_anon_free_client_credentials.3 gnutls_anon_allocate_client_credentials.3 gnutls_anon_set_server_dh_params.3 gnutls_anon_set_server_params_function.3 gnutls_credentials_clear.3 gnutls_credentials_set.3 gnutls_auth_get_type.3 gnutls_auth_server_get_type.3 gnutls_auth_client_get_type.3 gnutls_record_check_pending.3 gnutls_certificate_free_keys.3 gnutls_certificate_free_cas.3 gnutls_certificate_free_ca_names.3 gnutls_certificate_free_credentials.3 gnutls_certificate_allocate_credentials.3 gnutls_certificate_server_set_request.3 gnutls_certificate_client_set_retrieve_function.3 gnutls_certificate_server_set_retrieve_function.3 gnutls_certificate_verify_peers2.3 gnutls_certificate_verify_peers.3 gnutls_certificate_expiration_time_peers.3 gnutls_certificate_activation_time_peers.3 gnutls_db_set_retrieve_function.3 gnutls_db_set_remove_function.3 gnutls_db_set_store_function.3 gnutls_db_set_ptr.3 gnutls_db_get_ptr.3 gnutls_db_set_cache_expiration.3 gnutls_db_check_entry.3 gnutls_db_remove_session.3 gnutls_dh_params_import_raw.3 gnutls_dh_params_init.3 gnutls_dh_params_deinit.3 gnutls_dh_params_cpy.3 gnutls_dh_params_generate2.3 gnutls_dh_params_import_pkcs3.3 gnutls_dh_params_export_pkcs3.3 gnutls_dh_params_export_raw.3 gnutls_error_is_fatal.3 gnutls_perror.3 gnutls_strerror.3 gnutls_global_set_log_function.3 gnutls_global_set_log_level.3 gnutls_global_set_mem_functions.3 gnutls_global_init.3 gnutls_global_deinit.3 gnutls_transport_set_pull_function.3 gnutls_transport_set_push_function.3 gnutls_check_version.3 gnutls_rehandshake.3 gnutls_handshake.3 gnutls_handshake_set_max_packet_length.3 gnutls_handshake_get_last_in.3 gnutls_handshake_get_last_out.3 gnutls_malloc.3 gnutls_free.3 gnutls_cipher_set_priority.3 gnutls_kx_set_priority.3 gnutls_mac_set_priority.3 gnutls_compression_set_priority.3 gnutls_protocol_set_priority.3 gnutls_certificate_type_set_priority.3 gnutls_set_default_priority.3 gnutls_set_default_export_priority.3 gnutls_psk_free_client_credentials.3 gnutls_psk_allocate_client_credentials.3 gnutls_psk_set_client_credentials.3 gnutls_psk_free_server_credentials.3 gnutls_psk_allocate_server_credentials.3 gnutls_psk_set_server_credentials_file.3 gnutls_psk_set_server_credentials_function.3 gnutls_psk_set_client_credentials_function.3 gnutls_psk_server_get_username.3 gnutls_hex_decode.3 gnutls_hex_encode.3 gnutls_psk_set_server_dh_params.3 gnutls_psk_set_server_params_function.3 gnutls_protocol_get_version.3 gnutls_transport_set_lowat.3 gnutls_transport_set_ptr.3 gnutls_transport_set_ptr2.3 gnutls_transport_get_ptr.3 gnutls_transport_get_ptr2.3 gnutls_bye.3 gnutls_record_send.3 gnutls_record_recv.3 gnutls_record_get_max_size.3 gnutls_record_set_max_size.3 gnutls_rsa_params_import_raw.3 gnutls_rsa_params_init.3 gnutls_rsa_params_deinit.3 gnutls_rsa_params_cpy.3 gnutls_rsa_params_generate2.3 gnutls_rsa_params_import_pkcs1.3 gnutls_rsa_params_export_pkcs1.3 gnutls_rsa_params_export_raw.3 gnutls_session_get_data.3 gnutls_session_get_data2.3 gnutls_session_get_id.3 gnutls_session_set_data.3 gnutls_cipher_get.3 gnutls_certificate_type_get.3 gnutls_kx_get.3 gnutls_mac_get.3 gnutls_compression_get.3 gnutls_init.3 gnutls_deinit.3 gnutls_openpgp_send_key.3 gnutls_certificate_send_x509_rdn_sequence.3 gnutls_handshake_set_private_extensions.3 gnutls_session_is_resumed.3 gnutls_session_get_ptr.3 gnutls_session_set_ptr.3 gnutls_record_get_direction.3 gnutls_dh_set_prime_bits.3 gnutls_dh_get_group.3 gnutls_dh_get_pubkey.3 gnutls_rsa_export_get_pubkey.3 gnutls_dh_get_secret_bits.3 gnutls_dh_get_prime_bits.3 gnutls_rsa_export_get_modulus_bits.3 gnutls_dh_get_peers_public_bits.3 gnutls_certificate_get_ours.3 gnutls_certificate_get_peers.3 gnutls_certificate_client_get_request_status.3 gnutls_fingerprint.3 gnutls_certificate_set_dh_params.3 gnutls_certificate_set_params_function.3 gnutls_certificate_set_verify_flags.3 gnutls_certificate_set_verify_limits.3 gnutls_certificate_set_rsa_export_params.3 gnutls_certificate_set_x509_key_mem.3 gnutls_certificate_set_x509_key.3 gnutls_certificate_set_x509_key_file.3 gnutls_certificate_set_x509_trust_mem.3 gnutls_certificate_set_x509_trust.3 gnutls_certificate_set_x509_trust_file.3 gnutls_certificate_set_x509_crl_mem.3 gnutls_certificate_set_x509_crl.3 gnutls_certificate_set_x509_crl_file.3 gnutls_certificate_set_x509_simple_pkcs12_file.3 gnutls_certificate_free_crls.3 gnutls_pem_base64_encode.3 gnutls_pem_base64_encode_alloc.3 gnutls_pem_base64_decode.3 gnutls_pem_base64_decode_alloc.3 gnutls_global_init_extra.3 gnutls_extra_check_version.3 gnutls_certificate_set_openpgp_key_mem.3 gnutls_certificate_set_openpgp_key_file.3 gnutls_certificate_set_openpgp_keyring_file.3 gnutls_certificate_set_openpgp_keyring_mem.3 gnutls_certificate_set_openpgp_keyserver.3 gnutls_certificate_set_openpgp_trustdb.3 gnutls_openpgp_set_recv_key_function.3 gnutls_certificate_set_openpgp_key.3 gnutls_x509_dn_oid_known.3 gnutls_x509_crl_init.3 gnutls_x509_crl_deinit.3 gnutls_x509_crl_import.3 gnutls_x509_crl_get_issuer_dn.3 gnutls_x509_crl_get_issuer_dn_by_oid.3 gnutls_x509_crl_get_dn_oid.3 gnutls_x509_crl_get_signature_algorithm.3 gnutls_x509_crl_get_version.3 gnutls_x509_crl_get_this_update.3 gnutls_x509_crl_get_next_update.3 gnutls_x509_crl_get_crt_count.3 gnutls_x509_crl_get_crt_serial.3 gnutls_x509_crl_export.3 gnutls_x509_crl_set_version.3 gnutls_x509_crl_sign2.3 gnutls_x509_crl_sign.3 gnutls_x509_crl_set_this_update.3 gnutls_x509_crl_set_next_update.3 gnutls_x509_crl_set_crt_serial.3 gnutls_x509_crl_set_crt.3 gnutls_x509_crq_init.3 gnutls_x509_crq_deinit.3 gnutls_x509_crq_import.3 gnutls_x509_crq_get_dn.3 gnutls_x509_crq_get_dn_by_oid.3 gnutls_x509_crq_get_dn_oid.3 gnutls_x509_crq_get_challenge_password.3 gnutls_x509_crq_set_attribute_by_oid.3 gnutls_x509_crq_get_attribute_by_oid.3 gnutls_x509_crq_set_dn_by_oid.3 gnutls_x509_crq_set_version.3 gnutls_x509_crq_get_version.3 gnutls_x509_crq_set_key.3 gnutls_x509_crq_set_challenge_password.3 gnutls_x509_crq_sign2.3 gnutls_x509_crq_sign.3 gnutls_x509_crq_export.3 gnutls_x509_crq_get_pk_algorithm.3 gnutls_x509_rdn_get.3 gnutls_x509_rdn_get_by_oid.3 gnutls_x509_rdn_get_oid.3 gnutls_pkcs12_bag_init.3 gnutls_pkcs12_bag_deinit.3 gnutls_pkcs12_bag_get_type.3 gnutls_pkcs12_bag_get_count.3 gnutls_pkcs12_bag_get_data.3 gnutls_pkcs12_bag_set_data.3 gnutls_pkcs12_bag_set_crt.3 gnutls_pkcs12_bag_set_crl.3 gnutls_pkcs12_bag_set_key_id.3 gnutls_pkcs12_bag_get_key_id.3 gnutls_pkcs12_bag_get_friendly_name.3 gnutls_pkcs12_bag_set_friendly_name.3 gnutls_pkcs12_bag_decrypt.3 gnutls_pkcs12_bag_encrypt.3 gnutls_pkcs12_init.3 gnutls_pkcs12_deinit.3 gnutls_pkcs12_import.3 gnutls_pkcs12_export.3 gnutls_pkcs12_get_bag.3 gnutls_pkcs12_set_bag.3 gnutls_pkcs12_generate_mac.3 gnutls_pkcs12_verify_mac.3 gnutls_pkcs7_init.3 gnutls_pkcs7_deinit.3 gnutls_pkcs7_import.3 gnutls_pkcs7_get_crt_raw.3 gnutls_pkcs7_get_crt_count.3 gnutls_pkcs7_export.3 gnutls_pkcs7_set_crt_raw.3 gnutls_pkcs7_set_crt.3 gnutls_pkcs7_delete_crt.3 gnutls_pkcs7_get_crl_raw.3 gnutls_pkcs7_get_crl_count.3 gnutls_pkcs7_set_crl_raw.3 gnutls_pkcs7_set_crl.3 gnutls_pkcs7_delete_crl.3 gnutls_x509_privkey_init.3 gnutls_x509_privkey_deinit.3 gnutls_x509_privkey_cpy.3 gnutls_x509_privkey_import.3 gnutls_x509_privkey_import_rsa_raw.3 gnutls_x509_privkey_import_dsa_raw.3 gnutls_x509_privkey_get_pk_algorithm.3 gnutls_x509_privkey_export.3 gnutls_x509_privkey_export_rsa_raw.3 gnutls_x509_privkey_export_dsa_raw.3 gnutls_x509_privkey_generate.3 gnutls_x509_privkey_get_key_id.3 gnutls_x509_privkey_sign_data.3 gnutls_x509_privkey_verify_data.3 gnutls_x509_privkey_fix.3 gnutls_x509_privkey_export_pkcs8.3 gnutls_x509_privkey_import_pkcs8.3 gnutls_x509_crt_check_hostname.3 gnutls_x509_crt_check_issuer.3 gnutls_x509_crt_list_verify.3 gnutls_x509_crt_verify.3 gnutls_x509_crl_check_issuer.3 gnutls_x509_crl_verify.3 gnutls_x509_crt_init.3 gnutls_x509_crt_deinit.3 gnutls_x509_crt_import.3 gnutls_x509_crt_get_issuer_dn.3 gnutls_x509_crt_get_issuer_dn_by_oid.3 gnutls_x509_crt_get_issuer_dn_oid.3 gnutls_x509_crt_get_dn.3 gnutls_x509_crt_get_dn_by_oid.3 gnutls_x509_crt_get_dn_oid.3 gnutls_x509_crt_get_signature_algorithm.3 gnutls_x509_crt_get_version.3 gnutls_x509_crt_get_activation_time.3 gnutls_x509_crt_get_expiration_time.3 gnutls_x509_crt_get_serial.3 gnutls_x509_crt_get_subject_key_id.3 gnutls_x509_crt_get_authority_key_id.3 gnutls_x509_crt_get_pk_algorithm.3 gnutls_x509_crt_get_subject_alt_name.3 gnutls_x509_crt_get_ca_status.3 gnutls_x509_crt_get_key_usage.3 gnutls_x509_crt_get_extension_by_oid.3 gnutls_x509_crt_get_extension_oid.3 gnutls_x509_crt_get_fingerprint.3 gnutls_x509_crt_export.3 gnutls_x509_crt_get_key_id.3 gnutls_x509_crt_check_revocation.3 gnutls_x509_crt_verify_data.3 gnutls_x509_crt_get_crl_dist_points.3 gnutls_x509_crt_get_key_purpose_oid.3 gnutls_x509_crt_get_pk_rsa_raw.3 gnutls_x509_crt_get_pk_dsa_raw.3 gnutls_x509_crt_list_import.3 gnutls_x509_crt_set_dn_by_oid.3 gnutls_x509_crt_set_issuer_dn_by_oid.3 gnutls_x509_crt_set_version.3 gnutls_x509_crt_set_key.3 gnutls_x509_crt_set_crq.3 gnutls_x509_crt_set_extension_by_oid.3 gnutls_x509_crt_set_ca_status.3 gnutls_x509_crt_set_key_usage.3 gnutls_x509_crt_set_subject_alternative_name.3 gnutls_x509_crt_sign2.3 gnutls_x509_crt_sign.3 gnutls_x509_crt_set_activation_time.3 gnutls_x509_crt_set_expiration_time.3 gnutls_x509_crt_set_serial.3 gnutls_x509_crt_set_crl_dist_points.3 gnutls_x509_crt_cpy_crl_dist_points.3 gnutls_x509_crt_set_subject_key_id.3 gnutls_x509_crt_set_authority_key_id.3 gnutls_x509_crt_set_key_purpose_oid.3 gnutls_x509_crt_to_xml.3 gnutls_openpgp_keyring_init.3 gnutls_openpgp_keyring_deinit.3 gnutls_openpgp_keyring_check_id.3 gnutls_openpgp_keyring_import.3 gnutls_openpgp_trustdb_init.3 gnutls_openpgp_trustdb_deinit.3 gnutls_openpgp_trustdb_import_file.3 gnutls_openpgp_key_init.3 gnutls_openpgp_key_deinit.3 gnutls_openpgp_key_import.3 gnutls_openpgp_key_export.3 gnutls_openpgp_key_get_fingerprint.3 gnutls_openpgp_key_get_name.3 gnutls_openpgp_key_get_pk_algorithm.3 gnutls_openpgp_key_get_version.3 gnutls_openpgp_key_get_creation_time.3 gnutls_openpgp_key_get_expiration_time.3 gnutls_openpgp_key_get_id.3 gnutls_openpgp_key_check_hostname.3 gnutls_openpgp_key_get_key_usage.3 gnutls_openpgp_key_verify_ring.3 gnutls_openpgp_key_verify_self.3 gnutls_openpgp_key_verify_trustdb.3 gnutls_openpgp_privkey_init.3 gnutls_openpgp_privkey_deinit.3 gnutls_openpgp_privkey_import.3 gnutls_openpgp_privkey_get_pk_algorithm.3 gnutls_openpgp_key_to_xml.3 +APIMANS = gnutls_server_name_get.3 gnutls_server_name_set.3 gnutls_alert_get_name.3 gnutls_alert_send.3 gnutls_error_to_alert.3 gnutls_alert_send_appropriate.3 gnutls_alert_get.3 gnutls_mac_get_name.3 gnutls_compression_get_name.3 gnutls_cipher_get_key_size.3 gnutls_cipher_get_name.3 gnutls_kx_get_name.3 gnutls_protocol_get_name.3 gnutls_cipher_suite_get_name.3 gnutls_certificate_type_get_name.3 gnutls_sign_algorithm_get_name.3 gnutls_pk_algorithm_get_name.3 gnutls_anon_free_server_credentials.3 gnutls_anon_allocate_server_credentials.3 gnutls_anon_free_client_credentials.3 gnutls_anon_allocate_client_credentials.3 gnutls_anon_set_server_dh_params.3 gnutls_anon_set_server_params_function.3 gnutls_credentials_clear.3 gnutls_credentials_set.3 gnutls_auth_get_type.3 gnutls_auth_server_get_type.3 gnutls_auth_client_get_type.3 gnutls_record_check_pending.3 gnutls_certificate_free_keys.3 gnutls_certificate_free_cas.3 gnutls_certificate_free_ca_names.3 gnutls_certificate_free_credentials.3 gnutls_certificate_allocate_credentials.3 gnutls_certificate_server_set_request.3 gnutls_certificate_client_set_retrieve_function.3 gnutls_certificate_server_set_retrieve_function.3 gnutls_certificate_verify_peers2.3 gnutls_certificate_verify_peers.3 gnutls_certificate_expiration_time_peers.3 gnutls_certificate_activation_time_peers.3 gnutls_db_set_retrieve_function.3 gnutls_db_set_remove_function.3 gnutls_db_set_store_function.3 gnutls_db_set_ptr.3 gnutls_db_get_ptr.3 gnutls_db_set_cache_expiration.3 gnutls_db_check_entry.3 gnutls_db_remove_session.3 gnutls_dh_params_import_raw.3 gnutls_dh_params_init.3 gnutls_dh_params_deinit.3 gnutls_dh_params_cpy.3 gnutls_dh_params_generate2.3 gnutls_dh_params_import_pkcs3.3 gnutls_dh_params_export_pkcs3.3 gnutls_dh_params_export_raw.3 gnutls_error_is_fatal.3 gnutls_perror.3 gnutls_strerror.3 gnutls_global_set_log_function.3 gnutls_global_set_log_level.3 gnutls_global_set_mem_functions.3 gnutls_global_init.3 gnutls_global_deinit.3 gnutls_transport_set_pull_function.3 gnutls_transport_set_push_function.3 gnutls_check_version.3 gnutls_rehandshake.3 gnutls_handshake.3 gnutls_handshake_set_max_packet_length.3 gnutls_handshake_get_last_in.3 gnutls_handshake_get_last_out.3 gnutls_malloc.3 gnutls_free.3 gnutls_cipher_set_priority.3 gnutls_kx_set_priority.3 gnutls_mac_set_priority.3 gnutls_compression_set_priority.3 gnutls_protocol_set_priority.3 gnutls_certificate_type_set_priority.3 gnutls_set_default_priority.3 gnutls_set_default_export_priority.3 gnutls_psk_free_client_credentials.3 gnutls_psk_allocate_client_credentials.3 gnutls_psk_set_client_credentials.3 gnutls_psk_free_server_credentials.3 gnutls_psk_allocate_server_credentials.3 gnutls_psk_set_server_credentials_file.3 gnutls_psk_set_server_credentials_function.3 gnutls_psk_set_client_credentials_function.3 gnutls_psk_server_get_username.3 gnutls_hex_decode.3 gnutls_hex_encode.3 gnutls_psk_set_server_dh_params.3 gnutls_psk_set_server_params_function.3 gnutls_protocol_get_version.3 gnutls_transport_set_lowat.3 gnutls_transport_set_ptr.3 gnutls_transport_set_ptr2.3 gnutls_transport_get_ptr.3 gnutls_transport_get_ptr2.3 gnutls_bye.3 gnutls_record_send.3 gnutls_record_recv.3 gnutls_record_get_max_size.3 gnutls_record_set_max_size.3 gnutls_rsa_params_import_raw.3 gnutls_rsa_params_init.3 gnutls_rsa_params_deinit.3 gnutls_rsa_params_cpy.3 gnutls_rsa_params_generate2.3 gnutls_rsa_params_import_pkcs1.3 gnutls_rsa_params_export_pkcs1.3 gnutls_rsa_params_export_raw.3 gnutls_session_get_data.3 gnutls_session_get_data2.3 gnutls_session_get_id.3 gnutls_session_set_data.3 gnutls_cipher_get.3 gnutls_certificate_type_get.3 gnutls_kx_get.3 gnutls_mac_get.3 gnutls_compression_get.3 gnutls_init.3 gnutls_deinit.3 gnutls_openpgp_send_key.3 gnutls_certificate_send_x509_rdn_sequence.3 gnutls_handshake_set_private_extensions.3 gnutls_session_is_resumed.3 gnutls_session_get_ptr.3 gnutls_session_set_ptr.3 gnutls_record_get_direction.3 gnutls_dh_set_prime_bits.3 gnutls_dh_get_group.3 gnutls_dh_get_pubkey.3 gnutls_rsa_export_get_pubkey.3 gnutls_dh_get_secret_bits.3 gnutls_dh_get_prime_bits.3 gnutls_rsa_export_get_modulus_bits.3 gnutls_dh_get_peers_public_bits.3 gnutls_certificate_get_ours.3 gnutls_certificate_get_peers.3 gnutls_certificate_client_get_request_status.3 gnutls_fingerprint.3 gnutls_certificate_set_dh_params.3 gnutls_certificate_set_params_function.3 gnutls_certificate_set_verify_flags.3 gnutls_certificate_set_verify_limits.3 gnutls_certificate_set_rsa_export_params.3 gnutls_psk_set_params_function.3 gnutls_anon_set_params_function.3 gnutls_certificate_set_x509_key_mem.3 gnutls_certificate_set_x509_key.3 gnutls_certificate_set_x509_key_file.3 gnutls_certificate_set_x509_trust_mem.3 gnutls_certificate_set_x509_trust.3 gnutls_certificate_set_x509_trust_file.3 gnutls_certificate_set_x509_crl_mem.3 gnutls_certificate_set_x509_crl.3 gnutls_certificate_set_x509_crl_file.3 gnutls_certificate_set_x509_simple_pkcs12_file.3 gnutls_certificate_free_crls.3 gnutls_pem_base64_encode.3 gnutls_pem_base64_encode_alloc.3 gnutls_pem_base64_decode.3 gnutls_pem_base64_decode_alloc.3 gnutls_global_init_extra.3 gnutls_extra_check_version.3 gnutls_ia_permute_inner_secret.3 gnutls_ia_generate_challenge.3 gnutls_ia_extract_inner_secret.3 gnutls_ia_endphase_send.3 gnutls_ia_verify_endphase.3 gnutls_ia_send.3 gnutls_ia_recv.3 gnutls_ia_handshake_p.3 gnutls_ia_handshake.3 gnutls_ia_allocate_client_credentials.3 gnutls_ia_free_client_credentials.3 gnutls_ia_set_client_avp_function.3 gnutls_ia_set_client_avp_ptr.3 gnutls_ia_get_client_avp_ptr.3 gnutls_ia_allocate_server_credentials.3 gnutls_ia_free_server_credentials.3 gnutls_ia_set_server_avp_function.3 gnutls_ia_set_server_avp_ptr.3 gnutls_ia_get_server_avp_ptr.3 gnutls_ia_require_inner_phase.3 gnutls_certificate_set_openpgp_key_mem.3 gnutls_certificate_set_openpgp_key_file.3 gnutls_certificate_set_openpgp_keyring_file.3 gnutls_certificate_set_openpgp_keyring_mem.3 gnutls_certificate_set_openpgp_keyserver.3 gnutls_certificate_set_openpgp_trustdb.3 gnutls_openpgp_set_recv_key_function.3 gnutls_certificate_set_openpgp_key.3 gnutls_x509_dn_oid_known.3 gnutls_x509_crl_init.3 gnutls_x509_crl_deinit.3 gnutls_x509_crl_import.3 gnutls_x509_crl_get_issuer_dn.3 gnutls_x509_crl_get_issuer_dn_by_oid.3 gnutls_x509_crl_get_dn_oid.3 gnutls_x509_crl_get_signature_algorithm.3 gnutls_x509_crl_get_version.3 gnutls_x509_crl_get_this_update.3 gnutls_x509_crl_get_next_update.3 gnutls_x509_crl_get_crt_count.3 gnutls_x509_crl_get_crt_serial.3 gnutls_x509_crl_export.3 gnutls_x509_crl_set_version.3 gnutls_x509_crl_sign2.3 gnutls_x509_crl_sign.3 gnutls_x509_crl_set_this_update.3 gnutls_x509_crl_set_next_update.3 gnutls_x509_crl_set_crt_serial.3 gnutls_x509_crl_set_crt.3 gnutls_x509_crq_init.3 gnutls_x509_crq_deinit.3 gnutls_x509_crq_import.3 gnutls_x509_crq_get_dn.3 gnutls_x509_crq_get_dn_by_oid.3 gnutls_x509_crq_get_dn_oid.3 gnutls_x509_crq_get_challenge_password.3 gnutls_x509_crq_set_attribute_by_oid.3 gnutls_x509_crq_get_attribute_by_oid.3 gnutls_x509_crq_set_dn_by_oid.3 gnutls_x509_crq_set_version.3 gnutls_x509_crq_get_version.3 gnutls_x509_crq_set_key.3 gnutls_x509_crq_set_challenge_password.3 gnutls_x509_crq_sign2.3 gnutls_x509_crq_sign.3 gnutls_x509_crq_export.3 gnutls_x509_crq_get_pk_algorithm.3 gnutls_x509_rdn_get.3 gnutls_x509_rdn_get_by_oid.3 gnutls_x509_rdn_get_oid.3 gnutls_pkcs12_bag_init.3 gnutls_pkcs12_bag_deinit.3 gnutls_pkcs12_bag_get_type.3 gnutls_pkcs12_bag_get_count.3 gnutls_pkcs12_bag_get_data.3 gnutls_pkcs12_bag_set_data.3 gnutls_pkcs12_bag_set_crt.3 gnutls_pkcs12_bag_set_crl.3 gnutls_pkcs12_bag_set_key_id.3 gnutls_pkcs12_bag_get_key_id.3 gnutls_pkcs12_bag_get_friendly_name.3 gnutls_pkcs12_bag_set_friendly_name.3 gnutls_pkcs12_bag_decrypt.3 gnutls_pkcs12_bag_encrypt.3 gnutls_pkcs12_init.3 gnutls_pkcs12_deinit.3 gnutls_pkcs12_import.3 gnutls_pkcs12_export.3 gnutls_pkcs12_get_bag.3 gnutls_pkcs12_set_bag.3 gnutls_pkcs12_generate_mac.3 gnutls_pkcs12_verify_mac.3 gnutls_pkcs7_init.3 gnutls_pkcs7_deinit.3 gnutls_pkcs7_import.3 gnutls_pkcs7_get_crt_raw.3 gnutls_pkcs7_get_crt_count.3 gnutls_pkcs7_export.3 gnutls_pkcs7_set_crt_raw.3 gnutls_pkcs7_set_crt.3 gnutls_pkcs7_delete_crt.3 gnutls_pkcs7_get_crl_raw.3 gnutls_pkcs7_get_crl_count.3 gnutls_pkcs7_set_crl_raw.3 gnutls_pkcs7_set_crl.3 gnutls_pkcs7_delete_crl.3 gnutls_x509_privkey_init.3 gnutls_x509_privkey_deinit.3 gnutls_x509_privkey_cpy.3 gnutls_x509_privkey_import.3 gnutls_x509_privkey_import_rsa_raw.3 gnutls_x509_privkey_import_dsa_raw.3 gnutls_x509_privkey_get_pk_algorithm.3 gnutls_x509_privkey_export.3 gnutls_x509_privkey_export_rsa_raw.3 gnutls_x509_privkey_export_dsa_raw.3 gnutls_x509_privkey_generate.3 gnutls_x509_privkey_get_key_id.3 gnutls_x509_privkey_sign_data.3 gnutls_x509_privkey_verify_data.3 gnutls_x509_privkey_fix.3 gnutls_x509_privkey_export_pkcs8.3 gnutls_x509_privkey_import_pkcs8.3 gnutls_x509_crt_check_hostname.3 gnutls_x509_crt_check_issuer.3 gnutls_x509_crt_list_verify.3 gnutls_x509_crt_verify.3 gnutls_x509_crl_check_issuer.3 gnutls_x509_crl_verify.3 gnutls_x509_crt_init.3 gnutls_x509_crt_deinit.3 gnutls_x509_crt_import.3 gnutls_x509_crt_get_issuer_dn.3 gnutls_x509_crt_get_issuer_dn_by_oid.3 gnutls_x509_crt_get_issuer_dn_oid.3 gnutls_x509_crt_get_dn.3 gnutls_x509_crt_get_dn_by_oid.3 gnutls_x509_crt_get_dn_oid.3 gnutls_x509_crt_get_signature_algorithm.3 gnutls_x509_crt_get_version.3 gnutls_x509_crt_get_activation_time.3 gnutls_x509_crt_get_expiration_time.3 gnutls_x509_crt_get_serial.3 gnutls_x509_crt_get_subject_key_id.3 gnutls_x509_crt_get_authority_key_id.3 gnutls_x509_crt_get_pk_algorithm.3 gnutls_x509_crt_get_subject_alt_name.3 gnutls_x509_crt_get_ca_status.3 gnutls_x509_crt_get_key_usage.3 gnutls_x509_crt_get_extension_by_oid.3 gnutls_x509_crt_get_extension_oid.3 gnutls_x509_crt_get_fingerprint.3 gnutls_x509_crt_export.3 gnutls_x509_crt_get_key_id.3 gnutls_x509_crt_check_revocation.3 gnutls_x509_crt_verify_data.3 gnutls_x509_crt_get_crl_dist_points.3 gnutls_x509_crt_get_key_purpose_oid.3 gnutls_x509_crt_get_pk_rsa_raw.3 gnutls_x509_crt_get_pk_dsa_raw.3 gnutls_x509_crt_list_import.3 gnutls_x509_crt_set_dn_by_oid.3 gnutls_x509_crt_set_issuer_dn_by_oid.3 gnutls_x509_crt_set_version.3 gnutls_x509_crt_set_key.3 gnutls_x509_crt_set_crq.3 gnutls_x509_crt_set_extension_by_oid.3 gnutls_x509_crt_set_ca_status.3 gnutls_x509_crt_set_key_usage.3 gnutls_x509_crt_set_subject_alternative_name.3 gnutls_x509_crt_sign2.3 gnutls_x509_crt_sign.3 gnutls_x509_crt_set_activation_time.3 gnutls_x509_crt_set_expiration_time.3 gnutls_x509_crt_set_serial.3 gnutls_x509_crt_set_crl_dist_points.3 gnutls_x509_crt_cpy_crl_dist_points.3 gnutls_x509_crt_set_subject_key_id.3 gnutls_x509_crt_set_authority_key_id.3 gnutls_x509_crt_set_key_purpose_oid.3 gnutls_x509_crt_to_xml.3 gnutls_openpgp_keyring_init.3 gnutls_openpgp_keyring_deinit.3 gnutls_openpgp_keyring_check_id.3 gnutls_openpgp_keyring_import.3 gnutls_openpgp_trustdb_init.3 gnutls_openpgp_trustdb_deinit.3 gnutls_openpgp_trustdb_import_file.3 gnutls_openpgp_key_init.3 gnutls_openpgp_key_deinit.3 gnutls_openpgp_key_import.3 gnutls_openpgp_key_export.3 gnutls_openpgp_key_get_fingerprint.3 gnutls_openpgp_key_get_name.3 gnutls_openpgp_key_get_pk_algorithm.3 gnutls_openpgp_key_get_version.3 gnutls_openpgp_key_get_creation_time.3 gnutls_openpgp_key_get_expiration_time.3 gnutls_openpgp_key_get_id.3 gnutls_openpgp_key_check_hostname.3 gnutls_openpgp_key_get_key_usage.3 gnutls_openpgp_key_verify_ring.3 gnutls_openpgp_key_verify_self.3 gnutls_openpgp_key_verify_trustdb.3 gnutls_openpgp_privkey_init.3 gnutls_openpgp_privkey_deinit.3 gnutls_openpgp_privkey_import.3 gnutls_openpgp_privkey_get_pk_algorithm.3 gnutls_openpgp_key_to_xml.3 SRPMANS = gnutls_srp_base64_encode.3 gnutls_srp_base64_encode_alloc.3 gnutls_srp_base64_decode.3 gnutls_srp_base64_decode_alloc.3 gnutls_srp_free_client_credentials.3 gnutls_srp_allocate_client_credentials.3 gnutls_srp_set_client_credentials.3 gnutls_srp_free_server_credentials.3 gnutls_srp_allocate_server_credentials.3 gnutls_srp_set_server_credentials_file.3 gnutls_srp_set_server_credentials_function.3 gnutls_srp_set_client_credentials_function.3 gnutls_srp_server_get_username.3 gnutls_srp_verifier.3 diff --git a/includes/gnutls/extra.h b/includes/gnutls/extra.h index 7769878713..a3f166f72f 100644 --- a/includes/gnutls/extra.h +++ b/includes/gnutls/extra.h @@ -79,6 +79,87 @@ int gnutls_certificate_set_openpgp_keyring_mem( int gnutls_certificate_set_openpgp_keyring_file( gnutls_certificate_credentials_t c, const char *file); + /* TLS/IA stuff + */ + + typedef enum { + GNUTLS_IA_APPLICATION_PAYLOAD = 0, + GNUTLS_IA_INTERMEDIATE_PHASE_FINISHED = 1, + GNUTLS_IA_FINAL_PHASE_FINISHED = 2 + } gnutls_ia_apptype_t; + + /* TLS/IA credential + */ + + typedef int (*gnutls_ia_avp_func) (gnutls_session_t session, void *ptr, + const char *last, size_t lastlen, + char **new, size_t *newlen); + + typedef struct gnutls_ia_server_credentials_st* gnutls_ia_server_credentials_t; + typedef struct gnutls_ia_client_credentials_st* gnutls_ia_client_credentials_t; + + /* Allocate and free TLS/IA credentials. */ + extern void + gnutls_ia_free_client_credentials(gnutls_ia_client_credentials_t sc); + extern int + gnutls_ia_allocate_client_credentials(gnutls_ia_client_credentials_t * sc); + + extern void + gnutls_ia_free_server_credentials(gnutls_ia_server_credentials_t sc); + extern int + gnutls_ia_allocate_server_credentials(gnutls_ia_server_credentials_t * sc); + + /* Client TLS/IA credential functions. */ + extern void + gnutls_ia_set_client_avp_function(gnutls_ia_client_credentials_t cred, + gnutls_ia_avp_func avp_func); + extern void + gnutls_ia_set_client_avp_ptr (gnutls_ia_client_credentials_t cred, + void *ptr); + extern void * + gnutls_ia_get_client_avp_ptr (gnutls_ia_client_credentials_t cred); + + /* Server TLS/IA credential functions. */ + extern void + gnutls_ia_set_server_avp_function(gnutls_ia_server_credentials_t cred, + gnutls_ia_avp_func avp_func); + extern void + gnutls_ia_set_server_avp_ptr (gnutls_ia_server_credentials_t cred, + void *ptr); + extern void * + gnutls_ia_get_server_avp_ptr (gnutls_ia_server_credentials_t cred); + + /* TLS/IA handshake. */ + extern int gnutls_ia_handshake_p (gnutls_session_t session); + + extern int gnutls_ia_handshake (gnutls_session_t session); + + /* TLS/IA low level interface. */ + extern int + gnutls_ia_permute_inner_secret (gnutls_session_t session, + size_t session_keys_size, + const char *session_keys); + extern int + gnutls_ia_endphase_send(gnutls_session_t session, int final_p); + + extern ssize_t + gnutls_ia_send(gnutls_session_t session, char *data, size_t datal); + extern ssize_t + gnutls_ia_recv(gnutls_session_t session, char *data, size_t datal); + + /* Utility stuff. */ + extern int + gnutls_ia_generate_challenge (gnutls_session_t session, + size_t buffer_size, + char *buffer); + extern void + gnutls_ia_extract_inner_secret (gnutls_session_t session, + char *buffer); + + /* Toggle whether inner phases are required. */ + extern void + gnutls_ia_require_inner_phase (gnutls_session_t session, int require); + int gnutls_global_init_extra(void); /* returns libgnutls-extra version (call it with a NULL argument) diff --git a/includes/gnutls/gnutls.h.in b/includes/gnutls/gnutls.h.in index e1d33b9fdd..714d13c50b 100644 --- a/includes/gnutls/gnutls.h.in +++ b/includes/gnutls/gnutls.h.in @@ -86,8 +86,13 @@ typedef enum { GNUTLS_PARAMS_RSA_EXPORT=1, GNUTLS_PARAMS_DH } gnutls_params_type_t; -typedef enum { GNUTLS_CRD_CERTIFICATE=1, GNUTLS_CRD_ANON, GNUTLS_CRD_SRP, - GNUTLS_CRD_PSK } gnutls_credentials_type_t; +typedef enum { + GNUTLS_CRD_CERTIFICATE=1, + GNUTLS_CRD_ANON, + GNUTLS_CRD_SRP, + GNUTLS_CRD_PSK, + GNUTLS_CRD_IA +} gnutls_credentials_type_t; #define GNUTLS_MAC_SHA GNUTLS_MAC_SHA1 #define GNUTLS_DIG_SHA GNUTLS_DIG_SHA1 @@ -137,7 +142,9 @@ typedef enum { GNUTLS_A_CLOSE_NOTIFY, GNUTLS_A_INSUFFICIENT_SECURITY, GNUTLS_A_INTERNAL_ERROR=80, GNUTLS_A_USER_CANCELED=90, GNUTLS_A_NO_RENEGOTIATION=100, GNUTLS_A_UNSUPPORTED_EXTENSION=110, GNUTLS_A_CERTIFICATE_UNOBTAINABLE=111, GNUTLS_A_UNRECOGNIZED_NAME=112, - GNUTLS_A_UNKNOWN_SRP_USERNAME=120, GNUTLS_A_MISSING_SRP_USERNAME=121 + GNUTLS_A_UNKNOWN_SRP_USERNAME=120, GNUTLS_A_MISSING_SRP_USERNAME=121, + GNUTLS_A_INNER_APPLICATION_FAILURE=208, + GNUTLS_A_INNER_APPLICATION_VERIFICATION=209 } gnutls_alert_description_t; typedef enum { GNUTLS_HANDSHAKE_HELLO_REQUEST, @@ -297,6 +304,12 @@ int gnutls_server_name_get(gnutls_session_t session, void *data, size_t *data_length, unsigned int * type, unsigned int indx); +typedef enum { + GNUTLS_IA_DISABLED = 0, + GNUTLS_IA_APP_PHASE_ON_RESUMPTION_NO = 1, + GNUTLS_IA_APP_PHASE_ON_RESUMPTION_YES = 2 +} gnutls_ia_mode_t; + /* functions to set priority of cipher suites */ int gnutls_cipher_set_priority( gnutls_session_t session, const int *list); @@ -919,6 +932,11 @@ void gnutls_psk_set_params_function(gnutls_psk_server_credentials_t res, #define GNUTLS_E_MAC_VERIFY_FAILED -100 /* for PKCS #12 MAC */ #define GNUTLS_E_CONSTRAINT_ERROR -101 +#define GNUTLS_E_WARNING_IA_IPHF_RECEIVED -102 +#define GNUTLS_E_WARNING_IA_FPHF_RECEIVED -103 + +#define GNUTLS_E_IA_VERIFY_FAILED -104 + #define GNUTLS_E_BASE64_ENCODING_ERROR -201 #define GNUTLS_E_INCOMPATIBLE_GCRYPT_LIBRARY -202 /* obsolete */ #define GNUTLS_E_INCOMPATIBLE_CRYPTO_LIBRARY -202 diff --git a/lib/Makefile.am b/lib/Makefile.am index 1af672e3b6..6be50fc8a2 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -69,7 +69,8 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c gnutls_cipher.c \ gnutls_ui.c gnutls_sig.c auth_dhe.c gnutls_dh_primes.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 + auth_rsa_export.c ext_server_name.c auth_dh_common.c \ + gnutls_helper.c ext_inner_application.c HFILES = debug.h gnutls_compress.h defines.h gnutls_cipher.h \ gnutls_buffers.h gnutls_errors.h gnutls_int.h \ @@ -84,8 +85,9 @@ HFILES = debug.h gnutls_compress.h defines.h gnutls_cipher.h \ gnutls_mem.h io_debug.h ext_max_record.h gnutls_session_pack.h \ gnutls_str.h gnutls_state.h gnutls_x509.h ext_cert_type.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_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 # Separate so we can create the documentation diff --git a/lib/debug.c b/lib/debug.c index ee2e220f86..88003dde97 100644 --- a/lib/debug.c +++ b/lib/debug.c @@ -63,6 +63,8 @@ _gnutls_packet2str (content_type_t packet) return "Handshake"; case GNUTLS_APPLICATION_DATA: return "Application Data"; + case GNUTLS_INNER_APPLICATION: + return "Inner Application"; default: return "Unknown Packet"; diff --git a/lib/defines.h b/lib/defines.h index 925d10c982..0126e81c8a 100644 --- a/lib/defines.h +++ b/lib/defines.h @@ -35,6 +35,7 @@ #include <stdio.h> #include <ctype.h> #include <limits.h> +#include <stdint.h> #ifdef NO_SSIZE_T # define HAVE_SSIZE_T diff --git a/lib/ext_inner_application.c b/lib/ext_inner_application.c new file mode 100644 index 0000000000..a05f906e30 --- /dev/null +++ b/lib/ext_inner_application.c @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2005 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_auth_int.h" +#include "gnutls_errors.h" +#include "gnutls_num.h" +#include "ext_inner_application.h" + +#define NO 0 +#define YES 1 + +int +_gnutls_inner_application_recv_params (gnutls_session_t session, + const opaque * data, size_t data_size) +{ + tls_ext_st *ext = &session->security_parameters.extensions; + gnutls_ia_mode_t state; + + if (data_size != 1) + { + gnutls_assert (); + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } + + switch ((unsigned char)*data) + { + case NO: + state = GNUTLS_IA_APP_PHASE_ON_RESUMPTION_NO; + break; + + case YES: + state = GNUTLS_IA_APP_PHASE_ON_RESUMPTION_YES; + break; + + default: + gnutls_assert (); + return 0; + } + + ext->peer_mode = state; + + return 0; +} + +/* returns data_size or a negative number on failure + */ +int +_gnutls_inner_application_send_params (gnutls_session_t session, + opaque * data, size_t data_size) +{ + tls_ext_st *ext = &session->security_parameters.extensions; + + if (data_size < 1) + { + gnutls_assert (); + return GNUTLS_E_SHORT_MEMORY_BUFFER; + } + + if (session->security_parameters.entity == GNUTLS_CLIENT) + { + gnutls_ia_client_credentials_t cred = (gnutls_ia_client_credentials_t) + _gnutls_get_cred(session->key, GNUTLS_CRD_IA, NULL); + + if (cred == NULL) + return 0; + + /* Simple case, just send what the application requested. */ + + if (ext->inner_phase_optional) + *data = NO; + else + *data = YES; + } + else + { + gnutls_ia_server_credentials_t cred = (gnutls_ia_server_credentials_t) + _gnutls_get_cred(session->key, GNUTLS_CRD_IA, NULL); + + if (cred == NULL) + return 0; + + /* The server MUST set app_phase_on_resumption to "yes" if the + client set app_phase_on_resumption to "yes" or if the server + does not resume the session. */ + if ((ext->peer_mode == GNUTLS_IA_APP_PHASE_ON_RESUMPTION_YES) || + !gnutls_session_is_resumed(session)) + *data = YES; + /* The server MAY set app_phase_on_resumption to "yes" for a + resumed session even if the client set + app_phase_on_resumption to "no", as the server may have + reason to proceed with one or more application phases. */ + else if (!ext->inner_phase_optional) + *data = YES; + else + *data = NO; + } + + return 1; +} diff --git a/lib/ext_inner_application.h b/lib/ext_inner_application.h new file mode 100644 index 0000000000..86e0a1e12c --- /dev/null +++ b/lib/ext_inner_application.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2005 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 + * + */ + +int _gnutls_inner_application_recv_params(gnutls_session_t session, + const opaque * data, + size_t data_size); +int _gnutls_inner_application_send_params(gnutls_session_t session, + opaque * data, size_t); diff --git a/lib/gnutls_alert.c b/lib/gnutls_alert.c index 566fe49bf5..92431bc799 100644 --- a/lib/gnutls_alert.c +++ b/lib/gnutls_alert.c @@ -64,6 +64,10 @@ static const gnutls_alert_entry sup_alerts[] = { "The server name sent was not recognized"}, {GNUTLS_A_UNKNOWN_SRP_USERNAME, "The SRP username is not known"}, {GNUTLS_A_MISSING_SRP_USERNAME, "The SRP username was not sent"}, + {GNUTLS_A_INNER_APPLICATION_FAILURE, + "Inner application negotiation failed"}, + {GNUTLS_A_INNER_APPLICATION_VERIFICATION, + "Inner application verification failed"}, {0, NULL} }; diff --git a/lib/gnutls_buffers.c b/lib/gnutls_buffers.c index 2923232cac..7034e5e868 100644 --- a/lib/gnutls_buffers.c +++ b/lib/gnutls_buffers.c @@ -85,42 +85,43 @@ _gnutls_record_buffer_put (content_type_t type, gnutls_session_t session, opaque * data, size_t length) { + gnutls_buffer *buf; + if (length == 0) return 0; + switch (type) { case GNUTLS_APPLICATION_DATA: - - if (_gnutls_buffer_append - (&session->internals.application_data_buffer, data, length) < 0) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - _gnutls_buffers_log ("BUF[REC]: Inserted %d bytes of Data(%d)\n", - length, type); - + buf = &session->internals.application_data_buffer; + _gnutls_buffers_log("BUF[REC]: Inserted %d bytes of Data(%d)\n", + length, type); break; - case GNUTLS_HANDSHAKE: - if (_gnutls_buffer_append - (&session->internals.handshake_data_buffer, data, length) < 0) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - _gnutls_buffers_log ("BUF[HSK]: Inserted %d bytes of Data(%d)\n", - length, type); + case GNUTLS_HANDSHAKE: + buf = &session->internals.handshake_data_buffer; + _gnutls_buffers_log("BUF[HSK]: Inserted %d bytes of Data(%d)\n", + length, type); + break; + case GNUTLS_INNER_APPLICATION: + buf = &session->internals.ia_data_buffer; + _gnutls_buffers_log("BUF[IA]: Inserted %d bytes of Data(%d)\n", + length, type); break; default: - gnutls_assert (); + gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } - return 0; + if (_gnutls_buffer_append (buf, data, length) < 0) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + return 0; } int @@ -134,6 +135,9 @@ _gnutls_record_buffer_get_size (content_type_t type, gnutls_session_t session) case GNUTLS_HANDSHAKE: return session->internals.handshake_data_buffer.length; + case GNUTLS_INNER_APPLICATION: + return session->internals.ia_data_buffer.length; + default: return GNUTLS_E_INVALID_REQUEST; } @@ -211,6 +215,24 @@ _gnutls_record_buffer_get (content_type_t type, session->internals.handshake_data_buffer.length); break; + + case GNUTLS_INNER_APPLICATION: + if (length > session->internals.ia_data_buffer.length) + length = session->internals.ia_data_buffer.length; + + _gnutls_buffers_log("BUF[REC][IA]: Read %d bytes of Data(%d)\n", + length, type); + + session->internals.ia_data_buffer.length -= length; + memcpy(data, session->internals.ia_data_buffer.data, length); + + /* overwrite buffer */ + memmove(session->internals.ia_data_buffer.data, + &session->internals.ia_data_buffer.data[length], + session->internals.ia_data_buffer.length); + + break; + default: gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; diff --git a/lib/gnutls_constate.c b/lib/gnutls_constate.c index 3ac7b3ef2e..55ac8aa49e 100644 --- a/lib/gnutls_constate.c +++ b/lib/gnutls_constate.c @@ -442,7 +442,8 @@ _gnutls_set_write_keys (gnutls_session_t session) dst->max_record_recv_size = src->max_record_recv_size; \ dst->max_record_send_size = src->max_record_send_size; \ dst->version = src->version; \ - memcpy( &dst->extensions, &src->extensions, sizeof(tls_ext_st)); + memcpy( &dst->extensions, &src->extensions, sizeof(tls_ext_st)); \ + memcpy( &dst->inner_secret, &src->inner_secret, sizeof(tls_ext_st)); static void _gnutls_cpy_read_security_parameters (security_parameters_st * diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c index 5409e44752..4307318425 100644 --- a/lib/gnutls_errors.c +++ b/lib/gnutls_errors.c @@ -233,6 +233,14 @@ static gnutls_error_entry error_algorithms[] = { GNUTLS_E_CONSTRAINT_ERROR, 1), ERROR_ENTRY ("Failed to acquire random data.", GNUTLS_E_RANDOM_FAILED, 1), + + ERROR_ENTRY("Received a TLS/IA Intermediate Phase Finished message", + GNUTLS_E_WARNING_IA_IPHF_RECEIVED, 0), + ERROR_ENTRY("Received a TLS/IA Final Phase Finished message", + GNUTLS_E_WARNING_IA_FPHF_RECEIVED, 0), + ERROR_ENTRY("Verifying TLS/IA phase checksum failed", + GNUTLS_E_IA_VERIFY_FAILED, 1), + {NULL, NULL, 0, 0} }; diff --git a/lib/gnutls_extensions.c b/lib/gnutls_extensions.c index 11c35286dd..def360b895 100644 --- a/lib/gnutls_extensions.c +++ b/lib/gnutls_extensions.c @@ -34,6 +34,7 @@ #include <ext_cert_type.h> #include <ext_server_name.h> #include <ext_srp.h> +#include <ext_inner_application.h> #include <gnutls_num.h> /* Key Exchange Section */ @@ -59,6 +60,9 @@ gnutls_extension_entry _gnutls_extensions[MAX_EXT_SIZE] = { _gnutls_srp_recv_params, _gnutls_srp_send_params), #endif + GNUTLS_EXTENSION_ENTRY(GNUTLS_EXTENSION_INNER_APPLICATION, + _gnutls_inner_application_recv_params, + _gnutls_inner_application_send_params), {0, 0, 0, 0} }; @@ -218,12 +222,12 @@ int _gnutls_gen_extensions (gnutls_session_t session, opaque * data, size_t data_size) { - int next, size; + int size; uint16_t pos = 0; opaque *sdata; int sdata_size; ext_send_func ext_send; - + gnutls_extension_entry *p; if (data_size < 2) { @@ -242,11 +246,9 @@ _gnutls_gen_extensions (gnutls_session_t session, opaque * data, } pos += 2; - next = MAX_EXT_TYPES; /* maximum supported extensions */ - do + for(p = _gnutls_extensions; p->name != NULL; p++) { - next--; - ext_send = _gnutls_ext_func_send (next); + ext_send = _gnutls_ext_func_send(p->type); if (ext_send == NULL) continue; size = ext_send (session, sdata, sdata_size); @@ -260,7 +262,7 @@ _gnutls_gen_extensions (gnutls_session_t session, opaque * data, } /* write extension type */ - _gnutls_write_uint16 (next, &data[pos]); + _gnutls_write_uint16(p->type, &data[pos]); pos += 2; /* write size */ @@ -272,10 +274,10 @@ _gnutls_gen_extensions (gnutls_session_t session, opaque * data, /* add this extension to the extension list */ - _gnutls_extension_list_add (session, next); + _gnutls_extension_list_add(session, p->type); _gnutls_debug_log ("EXT[%x]: Sending extension %s\n", session, - _gnutls_extension_get_name (next)); + _gnutls_extension_get_name (p->type)); } else if (size < 0) { @@ -283,9 +285,7 @@ _gnutls_gen_extensions (gnutls_session_t session, opaque * data, gnutls_free (sdata); return size; } - } - while (next >= 0); size = pos; pos -= 2; /* remove the size of the size header! */ diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 6d560bcc60..914c2d1d55 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -31,6 +31,10 @@ #include <gnutls/gnutls.h> #include <gnutls/extra.h> +struct bar { + uint8_t foo; +}; + /* * They are not needed any more. You can simply enable * the gnutls_log callback to get error descriptions. @@ -137,7 +141,8 @@ typedef enum handshake_state_t typedef enum extensions_t { GNUTLS_EXTENSION_SERVER_NAME = 0, GNUTLS_EXTENSION_MAX_RECORD_SIZE = 1, GNUTLS_EXTENSION_SRP = 6, - GNUTLS_EXTENSION_CERT_TYPE = 7 + GNUTLS_EXTENSION_CERT_TYPE = 7, + GNUTLS_EXTENSION_INNER_APPLICATION = 37703 } extensions_t; typedef enum @@ -154,7 +159,8 @@ typedef enum resumable_session_t typedef enum content_type_t { GNUTLS_CHANGE_CIPHER_SPEC = 20, GNUTLS_ALERT, - GNUTLS_HANDSHAKE, GNUTLS_APPLICATION_DATA + GNUTLS_HANDSHAKE, GNUTLS_APPLICATION_DATA, + GNUTLS_INNER_APPLICATION = 24 } content_type_t; #define GNUTLS_PK_ANY (gnutls_pk_algorithm_t)-1 @@ -258,6 +264,9 @@ typedef struct /* limit server_name extensions */ unsigned server_names_size; opaque srp_username[MAX_SRP_USERNAME + 1]; + /* 0 = tls/ia not used, 1 = no, 2 = yes */ + gnutls_ia_mode_t peer_mode; + int inner_phase_optional; } tls_ext_st; /* auth_info_t structures now MAY contain malloced @@ -315,6 +324,8 @@ typedef struct /* holds the negotiated certificate type */ gnutls_certificate_type_t cert_type; gnutls_protocol_t version; /* moved here */ + /* For TLS/IA. XXX: Move to IA credential? */ + opaque inner_secret[TLS_MASTER_SIZE]; } security_parameters_st; /* This structure holds the generated keys @@ -391,6 +402,7 @@ typedef struct mac_hd_t handshake_mac_handle_md5; /* hash of the handshake messages */ gnutls_buffer handshake_data_buffer; /* this is a buffer that holds the current handshake message */ + gnutls_buffer ia_data_buffer; /* holds inner application data (TLS/IA) */ resumable_session_t resumable; /* TRUE or FALSE - if we can resume that session */ handshake_state_t handshake_state; /* holds * a number which indicates where diff --git a/lib/gnutls_kx.c b/lib/gnutls_kx.c index e990d3ac22..f2d1d4b939 100644 --- a/lib/gnutls_kx.c +++ b/lib/gnutls_kx.c @@ -95,6 +95,10 @@ generate_normal_master (gnutls_session_t session, int keep_premaster) session->security_parameters.master_secret); } + /* TLS/IA inner secret is derived from the master secret. */ + memcpy (session->security_parameters.inner_secret, + session->security_parameters.master_secret, TLS_MASTER_SIZE); + if (!keep_premaster) _gnutls_free_datum (&PREMASTER); diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c index 0f34fc629d..24930ad144 100644 --- a/lib/gnutls_record.c +++ b/lib/gnutls_record.c @@ -481,6 +481,7 @@ check_recv_type (content_type_t recv_type) case GNUTLS_ALERT: case GNUTLS_HANDSHAKE: case GNUTLS_APPLICATION_DATA: + case GNUTLS_INNER_APPLICATION: return 0; default: gnutls_assert (); @@ -497,7 +498,9 @@ static int check_buffers (gnutls_session_t session, content_type_t type, opaque * data, int sizeofdata) { - if ((type == GNUTLS_APPLICATION_DATA || type == GNUTLS_HANDSHAKE) + if ((type == GNUTLS_APPLICATION_DATA || + type == GNUTLS_HANDSHAKE || + type == GNUTLS_INNER_APPLICATION) && _gnutls_record_buffer_get_size (type, session) > 0) { int ret, ret2; @@ -634,7 +637,9 @@ record_check_type (gnutls_session_t session, int ret; if ((recv_type == type) - && (type == GNUTLS_APPLICATION_DATA || type == GNUTLS_HANDSHAKE)) + && (type == GNUTLS_APPLICATION_DATA || + type == GNUTLS_HANDSHAKE || + type == GNUTLS_INNER_APPLICATION)) { _gnutls_record_buffer_put (type, session, (void *) data, data_size); } @@ -731,6 +736,17 @@ record_check_type (gnutls_session_t session, return _gnutls_recv_hello_request (session, data, data_size); break; + case GNUTLS_INNER_APPLICATION: + /* even if data is unexpected put it into the buffer */ + if ((ret = _gnutls_record_buffer_put(recv_type, session, + (void *) data, + data_size)) < 0) { + gnutls_assert(); + return ret; + } + gnutls_assert(); + return GNUTLS_E_UNEXPECTED_PACKET; + break; default: _gnutls_record_log @@ -1008,8 +1024,10 @@ begin: /* Get Application data from buffer */ - if ((type == GNUTLS_APPLICATION_DATA || type == GNUTLS_HANDSHAKE) - && (recv_type == type)) + if ((recv_type == type) && + (type == GNUTLS_APPLICATION_DATA || + type == GNUTLS_HANDSHAKE || + type == GNUTLS_INNER_APPLICATION)) { ret = _gnutls_record_buffer_get (type, session, data, sizeofdata); diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c index 7e270132fb..d67077c191 100644 --- a/lib/gnutls_state.c +++ b/lib/gnutls_state.c @@ -262,6 +262,7 @@ gnutls_init (gnutls_session_t * session, gnutls_connection_end_t con_end) _gnutls_buffer_init (&(*session)->internals.application_data_buffer); _gnutls_buffer_init (&(*session)->internals.handshake_data_buffer); _gnutls_buffer_init (&(*session)->internals.handshake_hash_buffer); + _gnutls_buffer_init(&(*session)->internals.ia_data_buffer); _gnutls_buffer_init (&(*session)->internals.record_send_buffer); _gnutls_buffer_init (&(*session)->internals.record_recv_buffer); @@ -354,6 +355,7 @@ gnutls_deinit (gnutls_session_t session) _gnutls_free_datum (&session->connection_state.read_mac_secret); _gnutls_free_datum (&session->connection_state.write_mac_secret); + _gnutls_buffer_clear(&session->internals.ia_data_buffer); _gnutls_buffer_clear (&session->internals.handshake_hash_buffer); _gnutls_buffer_clear (&session->internals.handshake_data_buffer); _gnutls_buffer_clear (&session->internals.application_data_buffer); diff --git a/libextra/Makefile.am b/libextra/Makefile.am index ca8aa3f745..fc1fa833c0 100644 --- a/libextra/Makefile.am +++ b/libextra/Makefile.am @@ -53,14 +53,13 @@ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = gnutls-extra.pc DISTCLEANFILES = $(pkgconfig_DATA) -EXTRA_DIST = gnutls-extra-api.texi +EXTRA_DIST = gnutls-extra-api.texi ia-api.texi lib_LTLIBRARIES = libgnutls-extra.la -COBJECTS = gnutls_extra.c +libgnutls_extra_la_SOURCES = gnutls_extra.c libgnutls_openssl_la_LDFLAGS = -libgnutls_extra_la_SOURCES = # OpenSSL @@ -95,11 +94,17 @@ libgnutls_extra_la_LDFLAGS += $(LIBOPENCDK_LIBS) endif endif +# TLS/IA + +libgnutls_extra_la_SOURCES += gnutls_ia.c + +# Rest + libgnutls_extra_la_LDFLAGS += \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ $(LZO_LIBS) -libgnutls_extra_la_SOURCES += $(COBJECTS) gnutls_extra.h libgnutls-extra.vers +libgnutls_extra_la_SOURCES += gnutls_extra.h libgnutls-extra.vers libgnutls_extra_la_LIBADD += ../lib/libgnutls.la ../gl/libgnu.la @@ -115,12 +120,20 @@ SUBDIRS += minilzo libgnutls_extra_la_LIBADD += minilzo/libminilzo.la endif -gnutls-extra-api.texi: $(COBJECTS) - @echo "" > gnutls-extra-api.texi - @for i in $(COBJECTS); do \ +gnutls-extra-api.texi: gnutls_extra.c + @echo "" > $@ + @for i in $<; do \ + echo -n "Creating documentation for file $$i... " && \ + ../doc/scripts/gdoc -texinfo $$i >> $@ && \ + echo "ok"; \ + done + +ia-api.texi: gnutls_ia.c + @echo "" > $@ + @for i in $<; do \ echo -n "Creating documentation for file $$i... " && \ - ../doc/scripts/gdoc -texinfo $$i >> gnutls-extra-api.texi && \ + ../doc/scripts/gdoc -texinfo $$i >> $@ && \ echo "ok"; \ done -dist-hook: gnutls-extra-api.texi +dist-hook: gnutls-extra-api.texi ia-api.texi diff --git a/libextra/gnutls_ia.c b/libextra/gnutls_ia.c new file mode 100644 index 0000000000..56677ee772 --- /dev/null +++ b/libextra/gnutls_ia.c @@ -0,0 +1,916 @@ +/* + * Copyright (C) 2005 Free Software Foundation + * + * Author: Simon Josefsson + * + * 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 2 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. + * + */ + +#include "gnutls_int.h" +#include "gnutls_record.h" +#include "gnutls_errors.h" +#include "gnutls_num.h" +#include "gnutls_state.h" + +#define CHECKSUM_SIZE 12 + +struct gnutls_ia_client_credentials_st +{ + gnutls_ia_avp_func avp_func; + void *avp_ptr; +}; + +struct gnutls_ia_server_credentials_st +{ + gnutls_ia_avp_func avp_func; + void *avp_ptr; +}; + +static const char server_finished_label[] = "server phase finished"; +static const char client_finished_label[] = "client phase finished"; +static const char inner_permutation_label[] = "inner secret permutation"; +static const char challenge_label[] = "inner application challenge"; + +/* + * The TLS/IA packet is the InnerApplication token, described as + * follows in draft-funk-tls-inner-application-extension-01.txt: + * + * enum { + * application_payload(0), intermediate_phase_finished(1), + * final_phase_finished(2), (255) + * } InnerApplicationType; + * + * struct { + * InnerApplicationType msg_type; + * uint24 length; + * select (InnerApplicationType) { + * case application_payload: ApplicationPayload; + * case intermediate_phase_finished: IntermediatePhaseFinished; + * case final_phase_finished: FinalPhaseFinished; + * } body; + * } InnerApplication; + * + */ + +/* Send TLS/IA data. If data==NULL && sizeofdata==NULL, then the last + send was interrupted for some reason, and then we try to send it + again. Returns the number of bytes sent, or an error code. If + this return E_AGAIN and E_INTERRUPTED, call this function again + with data==NULL&&sizeofdata=0NULL until it returns successfully. */ +static ssize_t +_gnutls_send_inner_application (gnutls_session_t session, + gnutls_ia_apptype_t msg_type, + const char *data, size_t sizeofdata) +{ + opaque *p = NULL; + size_t plen = 0; + ssize_t len; + + if (data != NULL) + { + plen = sizeofdata + 4; + p = gnutls_malloc (plen); + if (!p) + { + gnutls_assert (); + return GNUTLS_E_MEMORY_ERROR; + } + + *(unsigned char *) p = (unsigned char) (msg_type & 0xFF); + _gnutls_write_uint24 (sizeofdata, p + 1); + memcpy (p + 4, data, sizeofdata); + } + + len = _gnutls_send_int (session, GNUTLS_INNER_APPLICATION, -1, p, plen); + + if (p) + gnutls_free (p); + + return len; +} + +/* Receive TLS/IA data. Store received TLS/IA message type in + *MSG_TYPE, and the data in DATA of max SIZEOFDATA size. Return the + number of bytes read, or an error code. */ +static ssize_t +_gnutls_recv_inner_application (gnutls_session_t session, + gnutls_ia_apptype_t * msg_type, + opaque *data, size_t sizeofdata) +{ + ssize_t len; + opaque pkt[4]; + + len = _gnutls_recv_int (session, GNUTLS_INNER_APPLICATION, -1, pkt, 4); + if (len != 4) + { + gnutls_assert (); + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } + + *msg_type = pkt[0]; + len = _gnutls_read_uint24 (&pkt[1]); + + if (*msg_type != GNUTLS_IA_APPLICATION_PAYLOAD && len != CHECKSUM_SIZE) + { + gnutls_assert (); + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } + + if (sizeofdata < len) + { + /* XXX push back pkt to IA buffer? */ + gnutls_assert (); + return GNUTLS_E_SHORT_MEMORY_BUFFER; + } + + if (len > 0) + { + int tmplen = len; + + len = _gnutls_recv_int (session, GNUTLS_INNER_APPLICATION, -1, + data, tmplen); + if (len != tmplen) + { + gnutls_assert (); + /* XXX Correct? */ + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } + } + + return len; +} + +/* Apply the TLS PRF using the TLS/IA inner secret as keying material, + where the seed is the client random concatenated with the server + random concatenated EXTRA of EXTRA_SIZE length (which can be NULL/0 + respectively). LABEL and LABEL_SIZE is used as the label. The + result is placed in pre-allocated OUT of OUTSIZE length. */ +static int +_gnutls_ia_prf (gnutls_session_t session, + size_t label_size, + const char *label, + size_t extra_size, + const char *extra, + size_t outsize, + opaque *out) +{ + int ret; + opaque *seed; + size_t seedsize = 2 * TLS_RANDOM_SIZE + extra_size; + + seed = gnutls_malloc (seedsize); + if (!seed) + { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + memcpy (seed, session->security_parameters.server_random, TLS_RANDOM_SIZE); + memcpy (seed + TLS_RANDOM_SIZE, session->security_parameters.client_random, + TLS_RANDOM_SIZE); + memcpy (seed + 2 * TLS_RANDOM_SIZE, extra, extra_size); + + ret = _gnutls_PRF (session->security_parameters.inner_secret, + TLS_MASTER_SIZE, + label, + label_size, + seed, + seedsize, + outsize, + out); + + gnutls_free (seed); + + return ret; +} + +/** + * gnutls_ia_permute_inner_secret: + * @session: is a #gnutls_session_t structure. + * @session_keys_size: Size of generated session keys (0 if none). + * @session_keys: Generated session keys, used to permute inner secret + * (NULL if none). + * + * Permute the inner secret using the generated session keys. + * + * This can be called in the TLS/IA AVP callback to mix any generated + * session keys with the TLS/IA inner secret. + * + * Return value: Return zero on success, or a negative error code. + **/ +int +gnutls_ia_permute_inner_secret (gnutls_session_t session, + size_t session_keys_size, + const char *session_keys) +{ + return _gnutls_ia_prf (session, + sizeof (inner_permutation_label) - 1, + inner_permutation_label, + session_keys_size, + session_keys, + TLS_RANDOM_SIZE, + session->security_parameters.inner_secret); +} + +/** + * gnutls_ia_generate_challenge: + * @session: is a #gnutls_session_t structure. + * @buffer_size: size of output buffer. + * @buffer: pre-allocated buffer to contain @buffer_size bytes of output. + * + * Generate an application challenge that the client cannot control or + * predict, based on the TLS/IA inner secret. + * + * Return value: Returns 0 on success, or an negative error code. + **/ +int +gnutls_ia_generate_challenge (gnutls_session_t session, + size_t buffer_size, + char *buffer) +{ + return _gnutls_ia_prf (session, + sizeof (challenge_label) - 1, + challenge_label, + 0, + NULL, + buffer_size, + buffer); +} + +/** + * gnutls_ia_extract_inner_secret: + * @session: is a #gnutls_session_t structure. + * @buffer: pre-allocated buffer to hold 48 bytes of inner secret. + * + * Copy the 48 bytes large inner secret into the specified buffer + * + * This function is typically used after the TLS/IA handshake has + * concluded. The TLS/IA inner secret can be used as input to a PRF + * to derive session keys. Do not use the inner secret directly as a + * session key, because for a resumed session that does not include an + * application phase, the inner secret will be identical to the inner + * secret in the original session. It is important to include, for + * example, the client and server randomness when deriving a sesssion + * key from the inner secret. + **/ +void +gnutls_ia_extract_inner_secret (gnutls_session_t session, + char *buffer) +{ + memcpy (buffer, session->security_parameters.inner_secret, TLS_MASTER_SIZE); +} + +/** + * gnutls_ia_endphase_send: + * @session: is a #gnutls_session_t structure. + * @final_p: Set iff this should signal the final phase. + * + * Send a TLS/IA end phase message. + * + * In the client, this should only be used to acknowledge an end phase + * message sent by the server. + * + * In the server, this can be called instead of gnutls_ia_send() if + * the server wishes to end an application phase. + * + * Return value: Return 0 on success, or an error code. + **/ +int +gnutls_ia_endphase_send(gnutls_session_t session, int final_p) +{ + opaque local_checksum[CHECKSUM_SIZE]; + int client = session->security_parameters.entity == GNUTLS_CLIENT; + const char *label = client ? client_finished_label : server_finished_label; + int size_of_label = client ? sizeof (client_finished_label) : + sizeof (server_finished_label); + ssize_t len; + int ret; + + ret = _gnutls_PRF (session->security_parameters.inner_secret, + TLS_MASTER_SIZE, + label, size_of_label - 1, + /* XXX specification unclear on seed. */ + "", 0, CHECKSUM_SIZE, local_checksum); + if (ret < 0) + return ret; + + len = _gnutls_send_inner_application + (session, + final_p ? GNUTLS_IA_FINAL_PHASE_FINISHED : + GNUTLS_IA_INTERMEDIATE_PHASE_FINISHED, + local_checksum, CHECKSUM_SIZE); + + /* XXX Instead of calling this function over and over...? + * while (len == GNUTLS_E_AGAIN || len == GNUTLS_E_INTERRUPTED) + * len = _gnutls_io_write_flush(session); + */ + + if (len < 0) + { + gnutls_assert(); + return len; + } + + return 0; +} + +/** + * gnutls_ia_verify_endphase: + * @session: is a #gnutls_session_t structure. + * @checksum: 12-byte checksum data, received from gnutls_ia_recv(). + * + * Verify TLS/IA end phase checksum data. If verification fails, the + * %GNUTLS_A_INNER_APPLICATION_VERIFICATION alert is sent to the other + * sie. + * + * This function is called when gnutls_ia_recv() return + * %GNUTLS_E_WARNING_IA_IPHF_RECEIVED or + * %GNUTLS_E_WARNING_IA_FPHF_RECEIVED. + * + * Return value: Return 0 on successful verification, or an error + * code. If the checksum verification of the end phase message fails, + * %GNUTLS_E_IA_VERIFY_FAILED is returned. + **/ +int +gnutls_ia_verify_endphase (gnutls_session_t session, char *checksum) +{ + char local_checksum[CHECKSUM_SIZE]; + int client = session->security_parameters.entity == GNUTLS_CLIENT; + const char *label = client ? server_finished_label : client_finished_label; + int size_of_label = client ? sizeof (server_finished_label) : + sizeof (client_finished_label); + int ret; + + ret = _gnutls_PRF (session->security_parameters.inner_secret, + TLS_MASTER_SIZE, + label, size_of_label - 1, + "", 0, CHECKSUM_SIZE, local_checksum); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + if (memcmp (local_checksum, checksum, CHECKSUM_SIZE) != 0) + { + ret = gnutls_alert_send (session, GNUTLS_AL_FATAL, + GNUTLS_A_INNER_APPLICATION_VERIFICATION); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + return GNUTLS_E_IA_VERIFY_FAILED; + } + + return 0; +} + +/** + * gnutls_ia_send: Send peer the specified TLS/IA data. + * @session: is a #gnutls_session_t structure. + * @data: contains the data to send + * @sizeofdata: is the length of the data + * + * Send TLS/IA application payload data. This function has the + * similar semantics with send(). The only difference is that is + * accepts a GNUTLS session, and uses different error codes. + * + * The TLS/IA protocol is synchronous, so you cannot send more than + * one packet at a time. The client always send the first packet. + * + * To finish an application phase in the server, use + * gnutls_ia_endphase_send(). The client cannot end an application + * phase. + * + * If the EINTR is returned by the internal push function (the default + * is send()} then %GNUTLS_E_INTERRUPTED will be returned. If + * %GNUTLS_E_INTERRUPTED or %GNUTLS_E_AGAIN is returned, you must call + * this function again, with the same parameters; alternatively you + * could provide a %NULL pointer for data, and 0 for size. + * + * Returns the number of bytes sent, or a negative error code. + **/ +ssize_t +gnutls_ia_send (gnutls_session_t session, char *data, size_t sizeofdata) +{ + ssize_t len; + + len = _gnutls_send_inner_application (session, + GNUTLS_IA_APPLICATION_PAYLOAD, + data, sizeofdata); + + return len; +} + +/** + * gnutls_ia_recv - read data from the TLS/IA protocol + * @session: is a #gnutls_session_t structure. + * @data: the buffer that the data will be read into, must hold >= 12 bytes. + * @sizeofdata: the number of requested bytes, must be >= 12. + * + * Receive TLS/IA data. This function has the similar semantics with + * recv(). The only difference is that is accepts a GNUTLS session, + * and uses different error codes. + * + * If the server attempt to finish an application phase, this function + * will return %GNUTLS_E_WARNING_IA_IPHF_RECEIVED or + * %GNUTLS_E_WARNING_IA_FPHF_RECEIVED. The caller should then invoke + * gnutls_ia_verify_endphase(). + * + * If EINTR is returned by the internal push function (the default is + * @code{recv()}) then GNUTLS_E_INTERRUPTED will be returned. If + * GNUTLS_E_INTERRUPTED or GNUTLS_E_AGAIN is returned, you must call + * this function again, with the same parameters; alternatively you + * could provide a NULL pointer for data, and 0 for size. + * + * Returns the number of bytes received. A negative error code is + * returned in case of an error. The + * %GNUTLS_E_WARNING_IA_IPHF_RECEIVED and + * %GNUTLS_E_WARNING_IA_FPHF_RECEIVED errors are returned when an + * application phase finished message has been sent by the server. + **/ +ssize_t +gnutls_ia_recv (gnutls_session_t session, char *data, size_t sizeofdata) +{ + gnutls_ia_apptype_t msg_type; + ssize_t len; + + len = _gnutls_recv_inner_application (session, &msg_type, + data, sizeofdata); + + if (msg_type == GNUTLS_IA_INTERMEDIATE_PHASE_FINISHED) + return GNUTLS_E_WARNING_IA_IPHF_RECEIVED; + else if (msg_type == GNUTLS_IA_FINAL_PHASE_FINISHED) + return GNUTLS_E_WARNING_IA_FPHF_RECEIVED; + + return len; +} + +/* XXX rewrite the following two functions as state machines, to + handle EAGAIN/EINTERRUPTED? just add more problems to callers, + though. */ + +int +_gnutls_ia_client_handshake (gnutls_session_t session) +{ + char *buf = NULL; + size_t buflen = 0; + char tmp[1024]; /* XXX */ + ssize_t len; + int ret; + const struct gnutls_ia_client_credentials_st * cred = + _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL); + + if (cred == NULL) + return GNUTLS_E_INTERNAL_ERROR; + + while (1) + { + char *avp; + size_t avplen; + + ret = cred->avp_func (session, cred->avp_ptr, + buf, buflen, &avp, &avplen); + if (ret) + { + int tmpret; + tmpret = gnutls_alert_send (session, GNUTLS_AL_FATAL, + GNUTLS_A_INNER_APPLICATION_FAILURE); + if (tmpret < 0) + gnutls_assert (); + return ret; + } + + len = gnutls_ia_send (session, avp, avplen); + gnutls_free (avp); + if (len < 0) + return len; + + len = gnutls_ia_recv (session, tmp, sizeof (tmp)); + if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED || + len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) + { + ret = gnutls_ia_verify_endphase (session, tmp); + if (ret < 0) + return ret; + + ret = gnutls_ia_endphase_send + (session, len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED); + if (ret < 0) + return ret; + } + + if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED) + { + buf = NULL; + buflen = 0; + continue; + } + else if (len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) + break; + + if (len < 0) + return len; + + buflen = len; + buf = tmp; + } + + return 0; +} + +int +_gnutls_ia_server_handshake (gnutls_session_t session) +{ + gnutls_ia_apptype_t msg_type; + ssize_t len; + char buf[1024]; + int ret; + const struct gnutls_ia_server_credentials_st * cred = + _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL); + + if (cred == NULL) + return GNUTLS_E_INTERNAL_ERROR; + + do + { + char *avp; + size_t avplen; + + len = gnutls_ia_recv (session, buf, sizeof (buf)); + if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED || + len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) + { + ret = gnutls_ia_verify_endphase (session, buf); + if (ret < 0) + return ret; + } + + if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED) + continue; + else if (len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) + break; + + if (len < 0) + return len; + + avp = NULL; + avplen = 0; + + ret = cred->avp_func (session, cred->avp_ptr, buf, len, &avp, &avplen); + if (ret < 0) + { + int tmpret; + tmpret = gnutls_alert_send (session, GNUTLS_AL_FATAL, + GNUTLS_A_INNER_APPLICATION_FAILURE); + if (tmpret < 0) + gnutls_assert (); + return ret; + } + + msg_type = ret; + + if (msg_type != GNUTLS_IA_APPLICATION_PAYLOAD) + { + ret = gnutls_ia_endphase_send (session, msg_type == + GNUTLS_IA_FINAL_PHASE_FINISHED); + if (ret < 0) + return ret; + } + else + { + len = gnutls_ia_send (session, avp, avplen); + gnutls_free (avp); + if (len < 0) + return len; + } + } + while (1); + + return 0; +} + +/** + * gnutls_ia_handshake_p: + * @session: is a #gnutls_session_t structure. + * + * Predicate to be used after gnutls_handshake() to decide whether to + * invoke gnutls_ia_handshake(). Usable by both clients and servers. + * + * Return value: non-zero if TLS/IA handshake is expected, zero + * otherwise. + **/ +int +gnutls_ia_handshake_p (gnutls_session_t session) +{ + tls_ext_st *ext = &session->security_parameters.extensions; + + /* The other side didn't advertise TLS/IA. */ + if (ext->peer_mode == GNUTLS_IA_DISABLED) + return 0; + + /* We don't consider the inner phase optional. */ + if (!ext->inner_phase_optional) + return 1; + + /* This is not a resumed session. always require an inner + application. */ + if (!gnutls_session_is_resumed (session)) + return 1; + + /* Require an inner phase if the other end requested it. */ + return ext->peer_mode == GNUTLS_IA_APP_PHASE_ON_RESUMPTION_YES; +} + +/** + * gnutls_ia_handshake: + * @session: is a #gnutls_session_t structure. + * + * Perform a TLS/IA handshake. This should be called after + * gnutls_handshake() iff gnutls_ia_handshake_p(). + * + * Return 0 on success, or an error code. + **/ +int +gnutls_ia_handshake (gnutls_session_t session) +{ + int ret; + + if (session->security_parameters.entity == GNUTLS_CLIENT) + ret = _gnutls_ia_client_handshake (session); + else + ret = _gnutls_ia_server_handshake (session); + + return ret; +} + +/** + * gnutls_ia_allocate_client_credentials - Used to allocate an gnutls_ia_server_credentials_t structure + * @sc: is a pointer to an #gnutls_ia_server_credentials_t structure. + * + * This structure is complex enough to manipulate directly thus this + * helper function is provided in order to allocate it. + * + * Adding this credential to a session will enable TLS/IA, and will + * require an Application Phase after the TLS handshake (if the server + * support TLS/IA). Use gnutls_ia_require_inner_phase() to toggle the + * TLS/IA mode. + * + * Returns 0 on success. + **/ +int +gnutls_ia_allocate_client_credentials (gnutls_ia_client_credentials_t * sc) +{ + *sc = gnutls_calloc (1, sizeof (**sc)); + + if (*sc == NULL) + return GNUTLS_E_MEMORY_ERROR; + + return 0; +} + +/** + * gnutls_ia_free_client_credentials - Used to free an allocated #gnutls_ia_client_credentials_t structure + * @sc: is an #gnutls_ia_client_credentials_t structure. + * + * This structure is complex enough to manipulate directly thus this + * helper function is provided in order to free (deallocate) it. + * + **/ +void +gnutls_ia_free_client_credentials (gnutls_ia_client_credentials_t sc) +{ + gnutls_free (sc); +} + +/** + * gnutls_ia_set_client_avp_function - Used to set a AVP callback + * @cred: is a #gnutls_ia_client_credentials_t structure. + * @avp_func: is the callback function + * + * Set the TLS/IA AVP callback handler used for the session. + * + * The AVP callback is called to process AVPs received from the + * server, and to get a new AVP to send to the server. + * + * The callback's function form is: + * int (*avp_func) (gnutls_session_t session, void *ptr, + * const char *last, size_t lastlen, + * char **new, size_t *newlen); + * + * The @session parameter is the #gnutls_session_t structure + * corresponding to the current session. The @ptr parameter is the + * application hook pointer, set through + * gnutls_ia_set_client_avp_ptr(). The AVP received from the server + * is present in @last of @lastlen size, which will be %NULL on the + * first invocation. The newly allocated output AVP to send to the + * server should be placed in *@new of *@newlen size. + * + * The callback may invoke gnutls_ia_permute_inner_secret() to mix any + * generated session keys with the TLS/IA inner secret. + * + * Return 0 (%GNUTLS_IA_APPLICATION_PAYLOAD) on success, or a negative + * error code to abort the TLS/IA handshake. + * + * Note that the callback must use allocate the @new parameter using + * gnutls_malloc(), because it is released via gnutls_free() by the + * TLS/IA handshake function. + * + **/ +void +gnutls_ia_set_client_avp_function (gnutls_ia_client_credentials_t cred, + gnutls_ia_avp_func avp_func) +{ + cred->avp_func = avp_func; +} + +/** + * gnutls_ia_set_client_avp_ptr - Sets a pointer to be sent to TLS/IA callback + * @cred: is a #gnutls_ia_client_credentials_t structure. + * @ptr: is the pointer + * + * Sets the pointer that will be provided to the TLS/IA callback + * function as the first argument. + * + **/ +void +gnutls_ia_set_client_avp_ptr (gnutls_ia_client_credentials_t cred, void *ptr) +{ + cred->avp_ptr = ptr; +} + +/** + * gnutls_ia_get_client_avp_ptr - Returns the pointer which is sent to TLS/IA callback + * @cred: is a #gnutls_ia_client_credentials_t structure. + * + * Returns the pointer that will be provided to the TLS/IA callback + * function as the first argument. + * + **/ +void * +gnutls_ia_get_client_avp_ptr (gnutls_ia_client_credentials_t cred) +{ + return cred->avp_ptr; +} + +/** + * gnutls_ia_allocate_server_credentials - Used to allocate an gnutls_ia_server_credentials_t structure + * @sc: is a pointer to an #gnutls_ia_server_credentials_t structure. + * + * This structure is complex enough to manipulate directly thus this + * helper function is provided in order to allocate it. + * + * Adding this credential to a session will enable TLS/IA, and will + * require an Application Phase after the TLS handshake (if the client + * support TLS/IA). Use gnutls_ia_require_inner_phase() to toggle the + * TLS/IA mode. + * + * Returns 0 on success. + **/ +int +gnutls_ia_allocate_server_credentials (gnutls_ia_server_credentials_t * sc) +{ + *sc = gnutls_calloc (1, sizeof (**sc)); + + if (*sc == NULL) + return GNUTLS_E_MEMORY_ERROR; + + return 0; +} + +/** + * gnutls_ia_free_server_credentials - Used to free an allocated #gnutls_ia_server_credentials_t structure + * @sc: is an #gnutls_ia_server_credentials_t structure. + * + * This structure is complex enough to manipulate directly thus this + * helper function is provided in order to free (deallocate) it. + * + **/ +void +gnutls_ia_free_server_credentials (gnutls_ia_server_credentials_t sc) +{ + gnutls_free (sc); +} + +/** + * gnutls_ia_set_server_credentials_function - Used to set a AVP callback + * @cred: is a #gnutls_ia_server_credentials_t structure. + * @func: is the callback function + * + * Set the TLS/IA AVP callback handler used for the session. + * + * The callback's function form is: + * int (*avp_func) (gnutls_session_t session, void *ptr, + * const char *last, size_t lastlen, + * char **new, size_t *newlen); + * + * The @session parameter is the #gnutls_session_t structure + * corresponding to the current session. The @ptr parameter is the + * application hook pointer, set through + * gnutls_ia_set_server_avp_ptr(). The AVP received from the client + * is present in @last of @lastlen size. The newly allocated output + * AVP to send to the client should be placed in *@new of *@newlen + * size. + * + * The AVP callback is called to process incoming AVPs from the + * client, and to get a new AVP to send to the client. It can also be + * used to instruct the TLS/IA handshake to do go into the + * Intermediate or Final phases. It return a negative error code, or + * an #gnutls_ia_apptype_t message type. + * + * The callback may invoke gnutls_ia_permute_inner_secret() to mix any + * generated session keys with the TLS/IA inner secret. + * + * Specifically, return %GNUTLS_IA_APPLICATION_PAYLOAD (0) to send + * another AVP to the client, return + * %GNUTLS_IA_INTERMEDIATE_PHASE_FINISHED (1) to indicate that an + * IntermediatePhaseFinished message should be sent, and return + * %GNUTLS_IA_FINAL_PHASE_FINISHED (2) to indicate that an + * FinalPhaseFinished message should be sent. In the last two cases, + * the contents of the @new and @newlen parameter is not used. + * + * Note that the callback must use allocate the @new parameter using + * gnutls_malloc(), because it is released via gnutls_free() by the + * TLS/IA handshake function. + **/ +void +gnutls_ia_set_server_avp_function (gnutls_ia_server_credentials_t cred, + gnutls_ia_avp_func avp_func) +{ + cred->avp_func = avp_func; +} + +/** + * gnutls_ia_set_server_avp_ptr - Sets a pointer to be sent to TLS/IA callback + * @cred: is a #gnutls_ia_client_credentials_t structure. + * @ptr: is the pointer + * + * Sets the pointer that will be provided to the TLS/IA callback + * function as the first argument. + * + **/ +void +gnutls_ia_set_server_avp_ptr (gnutls_ia_server_credentials_t cred, void *ptr) +{ + cred->avp_ptr = ptr; +} + +/** + * gnutls_ia_get_server_avp_ptr - Returns the pointer which is sent to TLS/IA callback + * @cred: is a #gnutls_ia_client_credentials_t structure. + * + * Returns the pointer that will be provided to the TLS/IA callback + * function as the first argument. + * + **/ +void * +gnutls_ia_get_server_avp_ptr (gnutls_ia_server_credentials_t cred) +{ + return cred->avp_ptr; +} + +/** + * gnutls_ia_require_inner_phase - Set if a TLS/IA inner phase is required + * @session: is a #gnutls_session_t structure. + * @require: non-zero if an inner application phase should be required. + * + * Specify whether a TLS/IA Inner Application Phase will be required + * or not. If the TLS session is resumed, it is possibly to optimize + * away the inner application phase by calling this function and + * specify a zero value for @require. + * + * For this function to have any effect, it must be called before + * gnutls_handshake(). + * + * Whether to invoke the TLS/IA handshake will also depend on whether + * the client supports or requested TLS/IA. A server should thus use + * gnutls_ia_handshake_p() to decide whether to call + * gnutls_ia_handshake() or not. + **/ +void +gnutls_ia_require_inner_phase (gnutls_session_t session, int require) +{ + /* XXX. This function should ideally take a TLS/IA credential, but + we can't do that, since we don't want the LGPL'd + lib/ext_inner_applicaiton.c to call/inspect GPL'd + functions/structures. */ + session->security_parameters.extensions.inner_phase_optional = !require; +} diff --git a/tests/Makefile.am b/tests/Makefile.am index 04707e09c5..734f7c82bd 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -19,7 +19,7 @@ # along with this file; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -AM_CPPFLAGS = -I../includes -I$(top_srcdir)/includes -I$(top_srcdir)/gl +AM_CPPFLAGS = -I../gl -I$(top_srcdir)/gl -I../includes -I$(top_srcdir)/includes AM_LDFLAGS = -no-install LDADD = ../lib/libgnutls.la ../gl/libgnu.la libutils.la @@ -33,8 +33,10 @@ EXTRA_DIST = client.p12 noclient.p12 unclient.p12 EXTRA_DIST += encpkcs8.pem unencpkcs8.pem enc2pkcs8.pem openssl_LDADD = $(LDADD) ../libextra/libgnutls-openssl.la +tlsia_LDADD = $(LDADD) ../libextra/libgnutls-extra.la \ + ../gl/libgnu.la @LTLIBREADLINE@ -ctests = simple anonself pskself openssl gc dhepskself set_pkcs12_cred +ctests = simple anonself pskself openssl gc dhepskself set_pkcs12_cred tlsia TESTS = pkcs12_neon pkcs8 $(ctests) check_PROGRAMS = $(ctests) dist_check_SCRIPTS = pkcs12_neon pkcs8 diff --git a/tests/tlsia.c b/tests/tlsia.c new file mode 100644 index 0000000000..be4fde9e76 --- /dev/null +++ b/tests/tlsia.c @@ -0,0 +1,575 @@ +/* + * Copyright (C) 2004, 2005 Free Software Foundation + * + * Author: Simon Josefsson + * + * This file is part of GNUTLS. + * + * GNUTLS 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. + * + * GNUTLS 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; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* Parts copied from GnuTLS example programs. */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/wait.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <unistd.h> +#include <gnutls/gnutls.h> +#include <gnutls/extra.h> + +#include "utils.h" + +#include <readline.h> + +/* A very basic TLS client, with anonymous authentication. + */ + +#define MAX_BUF 1024 +#define MSG "Hello TLS" + +/* Connects to the peer and returns a socket + * descriptor. + */ +int +tcp_connect (void) +{ + const char *PORT = "5556"; + const char *SERVER = "127.0.0.1"; + int err, sd; + struct sockaddr_in sa; + + /* connects to server + */ + sd = socket (AF_INET, SOCK_STREAM, 0); + + memset (&sa, '\0', sizeof (sa)); + sa.sin_family = AF_INET; + sa.sin_port = htons (atoi (PORT)); + inet_pton (AF_INET, SERVER, &sa.sin_addr); + + err = connect (sd, (struct sockaddr *) & sa, sizeof (sa)); + if (err < 0) + { + fprintf (stderr, "Connect error\n"); + exit (1); + } + + return sd; +} + +/* closes the given socket descriptor. + */ +void +tcp_close (int sd) +{ + shutdown (sd, SHUT_RDWR); /* no more receptions */ + close (sd); +} + +int client_avp (gnutls_session_t session, void *ptr, + const char *last, size_t lastlen, + char **new, size_t *newlen) +{ + static int iter = 0; + char *p; + + if (last) + printf ("client: received %d bytes AVP: `%.*s'\n", + lastlen, lastlen, last); + else + printf ("client: new application phase\n"); + + switch (iter) + { + case 0: + p = "client's first AVP, next will be empty"; + break; + + case 1: + p = ""; + break; + + case 2: + p = "client avp"; + break; + + default: + p = "final client AVP, we'll restart next"; + iter = -1; + break; + } + + iter++; + + if (debug) + p = readline ("Client TLS/IA AVP: "); + + *new = gnutls_strdup (p); + if (!*new) + return -1; + *newlen = strlen (*new); + + printf ("client: sending %d bytes AVP: `%s'\n", *newlen, *new); + + gnutls_ia_permute_inner_secret (session, 3, "foo"); + + return 0; +} + +void +client (void) +{ + int ret, sd, ii; + gnutls_session_t session; + char buffer[MAX_BUF + 1]; + gnutls_anon_client_credentials_t anoncred; + gnutls_ia_client_credentials_t iacred; + /* Need to enable anonymous KX specifically. */ + const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 }; + + gnutls_global_init (); + gnutls_global_init_extra(); + + gnutls_anon_allocate_client_credentials (&anoncred); + gnutls_ia_allocate_client_credentials(&iacred); + + /* Initialize TLS session + */ + gnutls_init (&session, GNUTLS_CLIENT); + + /* Use default priorities */ + gnutls_set_default_priority (session); + gnutls_kx_set_priority (session, kx_prio); + + /* put the anonymous credentials to the current session + */ + gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred); + gnutls_credentials_set (session, GNUTLS_CRD_IA, iacred); + + /* connect to the peer + */ + sd = tcp_connect (); + + gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd); + + /* Enable TLS/IA. */ + gnutls_ia_set_client_avp_function (iacred, client_avp); + + /* Perform the TLS handshake + */ + ret = gnutls_handshake (session); + + if (ret < 0) + { + fail ("client: Handshake failed\n"); + gnutls_perror (ret); + goto end; + } + else + { + success ("client: Handshake was completed\n"); + } + + /* + To test TLS/IA alert's (the server will print that a fatal alert + was received): + gnutls_alert_send(session, GNUTLS_AL_FATAL, + GNUTLS_A_INNER_APPLICATION_FAILURE); + */ + + if (!gnutls_ia_handshake_p (session)) + fail ("client: No TLS/IA negotiation\n"); + else + { + success ("client: TLS/IA handshake\n"); + + ret = gnutls_ia_handshake (session); + + if (ret < 0) + { + fail ("client: TLS/IA handshake failed\n"); + gnutls_perror (ret); + goto end; + } + else + { + success ("client: TLS/IA Handshake was completed\n"); + } + } + + gnutls_record_send (session, MSG, strlen (MSG)); + + ret = gnutls_record_recv (session, buffer, MAX_BUF); + if (ret == 0) + { + success ("client: Peer has closed the TLS connection\n"); + goto end; + } + else if (ret < 0) + { + fail ("client: Error: %s\n", gnutls_strerror (ret)); + goto end; + } + + if (debug) + { + printf ("- Received %d bytes: ", ret); + for (ii = 0; ii < ret; ii++) + { + fputc (buffer[ii], stdout); + } + fputs ("\n", stdout); + } + + gnutls_bye (session, GNUTLS_SHUT_RDWR); + +end: + + tcp_close (sd); + + gnutls_deinit (session); + + gnutls_ia_free_client_credentials (iacred); + + gnutls_anon_free_client_credentials (anoncred); + + gnutls_global_deinit (); +} + +/* This is a sample TLS 1.0 echo server, for anonymous authentication only. + */ + +#define SA struct sockaddr +#define MAX_BUF 1024 +#define PORT 5556 /* listen to 5556 port */ +#define DH_BITS 1024 + +/* These are global */ +gnutls_anon_server_credentials_t anoncred; +gnutls_ia_server_credentials_t iacred; + +gnutls_session_t +initialize_tls_session (void) +{ + gnutls_session_t session; + const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 }; + + gnutls_init (&session, GNUTLS_SERVER); + + /* avoid calling all the priority functions, since the defaults + * are adequate. + */ + gnutls_set_default_priority (session); + gnutls_kx_set_priority (session, kx_prio); + + gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred); + + gnutls_dh_set_prime_bits (session, DH_BITS); + + return session; +} + +static gnutls_dh_params_t dh_params; + +static int +generate_dh_params (void) +{ + + /* Generate Diffie Hellman parameters - for use with DHE + * kx algorithms. These should be discarded and regenerated + * once a day, once a week or once a month. Depending on the + * security requirements. + */ + gnutls_dh_params_init (&dh_params); + gnutls_dh_params_generate2 (dh_params, DH_BITS); + + return 0; +} + +int err, listen_sd, i; +int sd, ret; +struct sockaddr_in sa_serv; +struct sockaddr_in sa_cli; +socklen_t client_len; +char topbuf[512]; +gnutls_session_t session; +char buffer[MAX_BUF + 1]; +int optval = 1; + +int server_avp (gnutls_session_t session, void *ptr, + const char *last, size_t lastlen, + char **new, size_t *newlen) +{ + static int iter = 0; + char *p; + + if (last) + printf ("server: received %d bytes AVP: `%.*s'\n", + lastlen, lastlen, last); + + gnutls_ia_permute_inner_secret (session, 3, "foo"); + + switch (iter) + { + case 0: + p = "first server AVP"; + break; + + case 1: + p = "second server AVP, next will be empty, then a intermediate finish"; + break; + + case 2: + p = ""; + break; + + case 3: + p = "1"; + break; + + case 4: + p = "server avp, after intermediate finish, next another intermediate"; + break; + + case 5: + p = "1"; + break; + + case 6: + p = "server avp, next will be the finish phase"; + break; + + default: + p = "2"; + break; + } + + iter++; + + if (debug) + p = readline ("Server TLS/IA AVP (type '1' to sync, '2' to finish): "); + + if (!p) + return -1; + + if (strcmp (p, "1") == 0) + { + success ("server: Sending IntermediatePhaseFinished...\n"); + return 1; + } + + if (strcmp (p, "2") == 0) + { + success ("server: Sending FinalPhaseFinished...\n"); + return 2; + } + + *new = gnutls_strdup (p); + if (!*new) + return -1; + *newlen = strlen (*new); + + printf ("server: sending %d bytes AVP: `%s'\n", *newlen, *new); + + return 0; +} + +void +server_start (void) +{ + /* this must be called once in the program + */ + gnutls_global_init (); + + gnutls_anon_allocate_server_credentials (&anoncred); + gnutls_ia_allocate_server_credentials (&iacred); + + success ("Launched, generating DH parameters...\n"); + + generate_dh_params (); + + gnutls_anon_set_server_dh_params (anoncred, dh_params); + + /* Socket operations + */ + listen_sd = socket (AF_INET, SOCK_STREAM, 0); + if (err == -1) + { + perror ("socket"); + fail ("server: socket failed\n"); + return; + } + + memset (&sa_serv, '\0', sizeof (sa_serv)); + sa_serv.sin_family = AF_INET; + sa_serv.sin_addr.s_addr = INADDR_ANY; + sa_serv.sin_port = htons (PORT); /* Server Port number */ + + setsockopt (listen_sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (int)); + + err = bind (listen_sd, (SA *) & sa_serv, sizeof (sa_serv)); + if (err == -1) + { + perror ("bind"); + fail ("server: bind failed\n"); + return; + } + + err = listen (listen_sd, 1024); + if (err == -1) + { + perror ("listen"); + fail ("server: listen failed\n"); + return; + } + + success ("server: ready. Listening to port '%d'\n", PORT); +} + +void +server (void) +{ + client_len = sizeof (sa_cli); + + session = initialize_tls_session (); + + sd = accept (listen_sd, (SA *) & sa_cli, &client_len); + + success ("server: connection from %s, port %d\n", + inet_ntop (AF_INET, &sa_cli.sin_addr, topbuf, + sizeof (topbuf)), ntohs (sa_cli.sin_port)); + + gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd); + + /* Enable TLS/IA. */ + gnutls_credentials_set (session, GNUTLS_CRD_IA, iacred); + gnutls_ia_set_server_avp_function (iacred, server_avp); + + ret = gnutls_handshake (session); + if (ret < 0) + { + close (sd); + gnutls_deinit (session); + fail ("server: Handshake has failed (%s)\n\n", gnutls_strerror (ret)); + return; + } + success ("server: Handshake was completed\n"); + + if (!gnutls_ia_handshake_p (session)) + fail ("server: No TLS/IA negotiation\n"); + else + { + success ("server: TLS/IA handshake\n"); + + ret = gnutls_ia_handshake (session); + + if (ret < 0) + { + fail ("server: TLS/IA handshake failed\n"); + gnutls_perror (ret); + return; + } + else + { + success ("server: TLS/IA Handshake was completed\n"); + } + } + + /* see the Getting peer's information example */ + /* print_info(session); */ + + i = 0; + for (;;) + { + bzero (buffer, MAX_BUF + 1); + ret = gnutls_record_recv (session, buffer, MAX_BUF); + + if (ret == 0) + { + success ("server: Peer has closed the GNUTLS connection\n"); + break; + } + else if (ret < 0) + { + if (ret == GNUTLS_E_FATAL_ALERT_RECEIVED) + { + gnutls_alert_description_t alert; + const char *err; + alert = gnutls_alert_get(session); + err = gnutls_alert_get_name(alert); + if (err) + printf ("Fatal alert: %s\n", err); + } + + fail ("server: Received corrupted data(%d). Closing...\n", ret); + break; + } + else if (ret > 0) + { + /* echo data back to the client + */ + gnutls_record_send (session, buffer, strlen (buffer)); + } + } + /* do not wait for the peer to close the connection. + */ + gnutls_bye (session, GNUTLS_SHUT_WR); + + close (sd); + gnutls_deinit (session); + + close (listen_sd); + + gnutls_ia_free_server_credentials (iacred); + + gnutls_anon_free_server_credentials (anoncred); + + gnutls_global_deinit (); + + success ("server: finished\n"); +} + +void +doit (void) +{ + pid_t child; + + server_start (); + if (error_count) + return; + + child = fork (); + if (child < 0) + { + perror ("fork"); + fail ("fork"); + return; + } + + if (child) + { + int status; + /* parent */ + server (); + wait (&status); + } + else + client (); +} |