diff options
author | Simon Josefsson <simon@josefsson.org> | 2008-06-04 10:21:57 +0200 |
---|---|---|
committer | Simon Josefsson <simon@josefsson.org> | 2008-06-04 10:21:57 +0200 |
commit | 639425f8b816802560d3dc563e5a31107e6be3f5 (patch) | |
tree | 9a4b4ef5d2e26022f3deca4cbff906e085aa1a66 /doc | |
parent | 6aea6e159330e2a7a00817deff33546af37c8a18 (diff) | |
parent | aa2c7264a52b993aca39c613e5fe1aed7511c972 (diff) | |
download | gnutls-639425f8b816802560d3dc563e5a31107e6be3f5.tar.gz |
Merge branch 'gnutls_with_netconf'
Conflicts:
ChangeLog
Makefile.am
NEWS
configure.in
doc/examples/Makefile.am
doc/gnutls.texi
doc/manpages/Makefile.am
src/cli.c
src/psk-gaa.c
src/psk.gaa
tests/Makefile.am
Diffstat (limited to 'doc')
-rw-r--r-- | doc/examples/Makefile.am | 5 | ||||
-rw-r--r-- | doc/examples/ex-client-psk.c | 119 | ||||
-rw-r--r-- | doc/examples/ex-serv-psk.c | 226 | ||||
-rw-r--r-- | doc/gnutls.texi | 129 |
4 files changed, 477 insertions, 2 deletions
diff --git a/doc/examples/Makefile.am b/doc/examples/Makefile.am index dc7cafd366..c8d925269e 100644 --- a/doc/examples/Makefile.am +++ b/doc/examples/Makefile.am @@ -31,8 +31,9 @@ LDADD = libexamples.la \ CXX_LDADD = $(LDADD) \ ../../lib/libgnutlsxx.la -noinst_PROGRAMS = ex-cert-select ex-client2 ex-client-resume \ - ex-crq ex-serv1 ex-serv-export +noinst_PROGRAMS = ex-client2 ex-client-resume ex-client-psk +noinst_PROGRAMS += ex-cert-select ex-crq +noinst_PROGRAMS += ex-serv1 ex-serv-export ex-serv-psk if ENABLE_CXX ex_cxx_SOURCES = ex-cxx.cpp diff --git a/doc/examples/ex-client-psk.c b/doc/examples/ex-client-psk.c new file mode 100644 index 0000000000..be718e0bde --- /dev/null +++ b/doc/examples/ex-client-psk.c @@ -0,0 +1,119 @@ +/* Copyright 2007, 2008 Free Software Foundation + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <unistd.h> +#include <gnutls/gnutls.h> + +/* A very basic TLS client, with PSK authentication. + */ + +#define MAX_BUF 1024 +#define CAFILE "ca.pem" +#define MSG "GET / HTTP/1.0\r\n\r\n" + +extern int tcp_connect (void); +extern void tcp_close (int sd); + +int +main (void) +{ + int ret, sd, ii; + gnutls_session_t session; + char buffer[MAX_BUF + 1]; + const char *err; + gnutls_psk_client_credentials_t pskcred; + const gnutls_datum_t key = { "DEADBEEF", 8 }; + + gnutls_global_init (); + + gnutls_psk_allocate_client_credentials (&pskcred); + gnutls_psk_set_client_credentials (pskcred, "test", &key, + GNUTLS_PSK_KEY_HEX); + + /* Initialize TLS session + */ + gnutls_init (&session, GNUTLS_CLIENT); + + /* Use default priorities */ + ret = gnutls_priority_set_direct (session, "PERFORMANCE", &err); + if (ret < 0) { + if (ret == GNUTLS_E_INVALID_REQUEST) { + fprintf(stderr, "Syntax error at: %s\n", err); + } + exit(1); + } + + /* put the x509 credentials to the current session + */ + gnutls_credentials_set (session, GNUTLS_CRD_PSK, pskcred); + + /* 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"); + } + + 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_psk_free_client_credentials (pskcred); + + gnutls_global_deinit (); + + return 0; +} diff --git a/doc/examples/ex-serv-psk.c b/doc/examples/ex-serv-psk.c new file mode 100644 index 0000000000..a5ef67db68 --- /dev/null +++ b/doc/examples/ex-serv-psk.c @@ -0,0 +1,226 @@ +/* Copyright 2007, 2008 Free Software Foundation + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. + */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <netinet/in.h> +#include <string.h> +#include <unistd.h> +#include <gnutls/gnutls.h> +#include <gcrypt.h> /* for gcry_control */ + +#define KEYFILE "key.pem" +#define CERTFILE "cert.pem" +#define CAFILE "ca.pem" +#define CRLFILE "crl.pem" + +/* This is a sample TLS echo server, supporting X.509 and PSK + authentication. + */ + + +#define SA struct sockaddr +#define SOCKET_ERR(err,s) if(err==-1) {perror(s);return(1);} +#define MAX_BUF 1024 +#define PORT 5556 /* listen to 5556 port */ +#define DH_BITS 1024 + +/* These are global */ +gnutls_certificate_credentials_t x509_cred; +gnutls_psk_server_credentials_t psk_cred; +gnutls_priority_t priority_cache; + +gnutls_session_t +initialize_tls_session (void) +{ + gnutls_session_t session; + + gnutls_init (&session, GNUTLS_SERVER); + + gnutls_priority_set (session, priority_cache); + + gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, x509_cred); + gnutls_credentials_set (session, GNUTLS_CRD_PSK, psk_cred); + + /* request client certificate if any. + */ + gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUEST); + + 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. When short bit length is used, it might + * be wise to regenerate parameters. + * + * Check the ex-serv-export.c example for using static + * parameters. + */ + gnutls_dh_params_init (&dh_params); + gnutls_dh_params_generate2 (dh_params, DH_BITS); + + return 0; +} + +static int +pskfunc (gnutls_session_t session, const char *username, gnutls_datum_t * key) +{ + printf ("psk: username %s\n", username); + key->data = gnutls_malloc (4); + key->data[0] = 0xDE; + key->data[1] = 0xAD; + key->data[2] = 0xBE; + key->data[3] = 0xEF; + key->size = 4; + return 0; +} + +int +main (void) +{ + int err, listen_sd, i; + int sd, ret; + struct sockaddr_in sa_serv; + struct sockaddr_in sa_cli; + int client_len; + char topbuf[512]; + gnutls_session_t session; + char buffer[MAX_BUF + 1]; + int optval = 1; + + /* to disallow usage of the blocking /dev/random + */ + gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); + + /* this must be called once in the program + */ + gnutls_global_init (); + + gnutls_certificate_allocate_credentials (&x509_cred); + gnutls_certificate_set_x509_trust_file (x509_cred, CAFILE, + GNUTLS_X509_FMT_PEM); + + gnutls_certificate_set_x509_crl_file (x509_cred, CRLFILE, + GNUTLS_X509_FMT_PEM); + + gnutls_certificate_set_x509_key_file (x509_cred, CERTFILE, KEYFILE, + GNUTLS_X509_FMT_PEM); + + gnutls_psk_allocate_server_credentials (&psk_cred); + gnutls_psk_set_server_credentials_function (psk_cred, pskfunc); + + generate_dh_params (); + + gnutls_priority_init( &priority_cache, "NORMAL:PSK", NULL); + + + gnutls_certificate_set_dh_params (x509_cred, dh_params); + + /* Socket operations + */ + listen_sd = socket (AF_INET, SOCK_STREAM, 0); + SOCKET_ERR (listen_sd, "socket"); + + 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)); + SOCKET_ERR (err, "bind"); + err = listen (listen_sd, 1024); + SOCKET_ERR (err, "listen"); + + printf ("Server ready. Listening to port '%d'.\n\n", PORT); + + client_len = sizeof (sa_cli); + for (;;) + { + session = initialize_tls_session (); + + sd = accept (listen_sd, (SA *) & sa_cli, &client_len); + + printf ("- 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); + ret = gnutls_handshake (session); + if (ret < 0) + { + close (sd); + gnutls_deinit (session); + fprintf (stderr, "*** Handshake has failed (%s)\n\n", + gnutls_strerror (ret)); + continue; + } + printf ("- Handshake was completed\n"); + + /* see the Getting peer's information example */ + /* print_info(session); */ + + i = 0; + for (;;) + { + memset (buffer, 0, MAX_BUF + 1); + ret = gnutls_record_recv (session, buffer, MAX_BUF); + + if (ret == 0) + { + printf ("\n- Peer has closed the GNUTLS connection\n"); + break; + } + else if (ret < 0) + { + fprintf (stderr, "\n*** Received corrupted " + "data(%d). Closing the connection.\n\n", ret); + break; + } + else if (ret > 0) + { + /* echo data back to the client + */ + gnutls_record_send (session, buffer, strlen (buffer)); + } + } + printf ("\n"); + /* 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_certificate_free_credentials (x509_cred); + gnutls_psk_free_server_credentials (psk_cred); + + gnutls_priority_deinit(priority_cache); + + gnutls_global_deinit (); + + return 0; + +} diff --git a/doc/gnutls.texi b/doc/gnutls.texi index 7e79f31004..d8ec68e235 100644 --- a/doc/gnutls.texi +++ b/doc/gnutls.texi @@ -1492,6 +1492,17 @@ file can be stored to the credentials structure by calling password file format is to be used, then the function @ref{gnutls_psk_set_server_credentials_function}, should be used instead. +The server can help the client chose a suitable username and password, +by sending a hint. In the server, specify the hint by calling +@ref{gnutls_psk_set_server_credentials_hint}. The client can retrieve +the hint, for example in the callback function, using +@ref{gnutls_psk_client_get_hint}. + +There is no standard mechanism to derive a PSK key from a password +specified by the TLS PSK document. However, GnuTLS provides +@ref{gnutls_psk_netconf_derive_key} which follows the algorithm +specified in @file{draft-ietf-netconf-tls-02.txt}. + Some helper functions such as: @itemize @@ -2517,6 +2528,7 @@ application. The applications are discussed in this chapter. * Invoking gnutls-cli-debug:: * Invoking gnutls-serv:: * Invoking certtool:: +* Invoking psktool:: @end menu @node Invoking srptool @@ -2628,6 +2640,63 @@ like: $ gnutls-cli -p 5556 test.gnutls.org --pskusername jas --pskkey 9e32cf7786321a828ef7668f09fb35db --priority NORMAL:+PSK:-RSA:-DHE-RSA -d 4711 @end smallexample +@menu +* Example client PSK connection:: +@end menu + +@node Example client PSK connection +@subsection Example client PSK connection +@cindex PSK client + +If your server only supports the PSK ciphersuite, connecting to it +should be as simple as connecting to the server: + +@smallexample +$ ./gnutls-cli -p 5556 localhost +Resolving 'localhost'... +Connecting to '127.0.0.1:5556'... +- PSK client callback. PSK hint 'psk_identity_hint' +Enter PSK identity: psk_identity +Enter password: +- PSK authentication. PSK hint 'psk_identity_hint' +- Version: TLS1.1 +- Key Exchange: PSK +- Cipher: AES-128-CBC +- MAC: SHA1 +- Compression: NULL +- Handshake was completed + +- Simple Client Mode: +@end smallexample + +If the server supports several cipher suites, you may need to force it +to chose PSK by using a cipher priority parameter such as +@code{--priority NORMAL:+PSK:-RSA:-DHE-RSA:-DHE-PSK}. + +@cindex Netconf +Instead of using the Netconf-way to derive the PSK key from a +password, you can also give the PSK username and key directly on the +command line: + +@smallexample +$ ./gnutls-cli -p 5556 localhost --pskusername psk_identity --pskkey 88f3824b3e5659f52d00e959bacab954b6540344 +Resolving 'localhost'... +Connecting to '127.0.0.1:5556'... +- PSK authentication. PSK hint 'psk_identity_hint' +- Version: TLS1.1 +- Key Exchange: PSK +- Cipher: AES-128-CBC +- MAC: SHA1 +- Compression: NULL +- Handshake was completed + +- Simple Client Mode: +@end smallexample + +By keeping the @code{--pskusername} parameter and removing the +@code{--pskkey} parameter, it will query only for the password during +the handshake. + @node Invoking gnutls-cli-debug @section Invoking gnutls-cli-debug @cindex gnutls-cli-debug @@ -2903,6 +2972,39 @@ gnutls-serv --http \ --pskpasswd psk-passwd.txt @end example +@menu +* Example server PSK connection:: +@end menu + +@node Example server PSK connection +@subsection Example server PSK connection +@cindex PSK server + +To set up a PSK server with @code{gnutls-serv} you need to create PSK +password file (@pxref{Invoking psktool}). In the example below, I +type @code{password} at the prompt. + +@smallexample +$ ./psktool -u psk_identity -p psks.txt -n psk_identity_hint +Enter password: +Key stored to psks.txt +$ cat psks.txt +psk_identity:88f3824b3e5659f52d00e959bacab954b6540344 +$ +@end smallexample + +After this, start the server pointing to the password file. We +disable DHE-PSK. + +@smallexample +$ ./gnutls-serv --pskpasswd psks.txt --pskhint psk_identity_hint --priority NORMAL:-DHE-PSK +Set static Diffie Hellman parameters, consider --dhparams. +Echo Server ready. Listening to port '5556'. +@end smallexample + +You can now connect to the server using a PSK client (@pxref{Example +client PSK connection}). + @node Invoking certtool @section Invoking certtool @cindex certtool @@ -3206,6 +3308,33 @@ signing_key #time_stamping_key @end example +@node Invoking psktool +@section Invoking psktool +@cindex psktool + +This is a program to manage @acronym{PSK} username and keys. + +@verbatim +PSKtool help +Usage : psktool [options] + -u, --username username + specify username. + -p, --passwd FILE specify a password file. + -n, --netconf-hint HINT + derive key from Netconf password, using + HINT as the psk_identity_hint. + -s, --keysize SIZE specify the key size in bytes. + -v, --version prints the program's version number + -h, --help shows this help text +@end verbatim + +Normally the file will generate random keys for the indicate username. +You may also derive PSK keys from passwords, using the algorithm +specified in @file{draft-ietf-netconf-tls-02.txt}. The algorithm +needs a PSK identity hint, which you specify using +@code{--netconf-hint}. To derive a PSK key from a password with an +empty PSK identity hint, using @code{--netconf-hint ""}. + @node Function reference @chapter Function Reference @cindex Function reference |