add initial support for RFC 4279 PSK SSL ciphersuites
authorNils Larsch <nils@openssl.org>
Fri, 10 Mar 2006 23:06:27 +0000 (23:06 +0000)
committerNils Larsch <nils@openssl.org>
Fri, 10 Mar 2006 23:06:27 +0000 (23:06 +0000)
PR: 1191
Submitted by: Mika Kousa and Pasi Eronen of Nokia Corporation
Reviewed by: Nils Larsch

26 files changed:
CHANGES
apps/s_client.c
apps/s_server.c
doc/apps/s_client.pod
doc/apps/s_server.pod
doc/ssl/SSL_CTX_set_psk_client_callback.pod [new file with mode: 0644]
doc/ssl/SSL_CTX_use_psk_identity_hint.pod [new file with mode: 0644]
doc/ssl/SSL_get_psk_identity.pod [new file with mode: 0644]
doc/ssl/ssl.pod
ssl/s3_clnt.c
ssl/s3_enc.c
ssl/s3_lib.c
ssl/s3_srvr.c
ssl/ssl.h
ssl/ssl_asn1.c
ssl/ssl_ciph.c
ssl/ssl_err.c
ssl/ssl_lib.c
ssl/ssl_locl.h
ssl/ssl_sess.c
ssl/ssl_stat.c
ssl/ssl_txt.c
ssl/ssltest.c
ssl/t1_enc.c
ssl/tls1.h
test/testssl

diff --git a/CHANGES b/CHANGES
index 9884a47..807338d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,22 @@
 
  Changes between 0.9.8a and 0.9.9  [xx XXX xxxx]
 
+  *) Add initial support for RFC 4279 PSK TLS ciphersuites. Add members
+     for the psk identity [hint] and the psk callback functions to the
+     SSL_SESSION, SSL and SSL_CTX structure.
+     
+     New ciphersuites:
+         PSK-RC4-SHA, PSK-3DES-EDE-CBC-SHA, PSK-AES128-CBC-SHA,
+         PSK-AES256-CBC-SHA
+     New functions:
+         SSL_CTX_use_psk_identity_hint
+         SSL_get_psk_identity_hint
+         SSL_get_psk_identity
+         SSL_use_psk_identity_hint
+
+     [Mika Kousa and Pasi Eronen of Nokia Corporation]
+
   *) Add RFC 3161 compliant time stamp request creation, response generation
      and response verification functionality.
      [Zoltán Glózik <zglozik@opentsa.org>, The OpenTSA Project]
index 50e27a0..138aa31 100644 (file)
  * Hudson (tjh@cryptsoft.com).
  *
  */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
 
 #include <assert.h>
+#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -171,6 +198,69 @@ static BIO *bio_c_out=NULL;
 static int c_quiet=0;
 static int c_ign_eof=0;
 
+#ifndef OPENSSL_NO_PSK
+/* Default PSK identity and key */
+static char *psk_identity="Client_identity";
+static char *psk_key=NULL; /* by default PSK is not used */
+
+static unsigned int psk_client_cb(SSL *ssl, const char *hint, char *identity,
+       unsigned int max_identity_len, unsigned char *psk,
+       unsigned int max_psk_len)
+       {
+       unsigned int psk_len = 0;
+       int ret;
+        BIGNUM *bn=NULL;
+
+       if (c_debug)
+               BIO_printf(bio_c_out, "psk_client_cb\n");
+       if (!hint)
+                {
+                /* no ServerKeyExchange message*/
+               if (c_debug)
+                       BIO_printf(bio_c_out,"NULL received PSK identity hint, continuing anyway\n");
+                }
+        else if (c_debug)
+               BIO_printf(bio_c_out, "Received PSK identity hint '%s'\n", hint);
+
+       /* lookup PSK identity and PSK key based on the given identity hint here */
+       ret = snprintf(identity, max_identity_len, psk_identity);
+       if (ret < 0 || ret > max_identity_len)
+               goto out_err;
+       if (c_debug)
+               BIO_printf(bio_c_out, "created identity '%s' len=%d\n", identity, ret);
+        ret=BN_hex2bn(&bn, psk_key);
+        if (!ret)
+                {
+                BIO_printf(bio_err,"Could not convert PSK key '%s' to BIGNUM\n", psk_key);
+                if (bn)
+                        BN_free(bn);
+                return 0;
+                }
+
+        if (BN_num_bytes(bn) > max_psk_len)
+                {
+                BIO_printf(bio_err,"psk buffer of callback is too small (%d) for key (%d)\n",
+                        max_psk_len, BN_num_bytes(bn));
+                BN_free(bn);
+                return 0;
+                }
+
+        psk_len=BN_bn2bin(bn, psk);
+        BN_free(bn);
+        if (psk_len == 0)
+                goto out_err;
+
+       if (c_debug)
+               BIO_printf(bio_c_out, "created PSK len=%d\n", psk_len);
+
+        return psk_len;
+ out_err:
+       if (c_debug)
+               BIO_printf(bio_err, "Error in PSK client callback\n");
+        return 0;
+       }
+#endif
+
 static void sc_usage(void)
        {
        BIO_printf(bio_err,"usage: s_client args\n");
@@ -204,6 +294,10 @@ static void sc_usage(void)
        BIO_printf(bio_err," -crlf         - convert LF from terminal into CRLF\n");
        BIO_printf(bio_err," -quiet        - no s_client output\n");
        BIO_printf(bio_err," -ign_eof      - ignore input eof (default when -quiet)\n");
+#ifndef OPENSSL_NO_PSK
+       BIO_printf(bio_err," -psk_identity arg - PSK identity\n");
+       BIO_printf(bio_err," -psk arg      - PSK in hex (without 0x)\n");
+#endif
        BIO_printf(bio_err," -ssl2         - just use SSLv2\n");
        BIO_printf(bio_err," -ssl3         - just use SSLv3\n");
        BIO_printf(bio_err," -tls1         - just use TLSv1\n");
@@ -404,6 +498,27 @@ int MAIN(int argc, char **argv)
                        nbio_test=1;
                else if (strcmp(*argv,"-state") == 0)
                        state=1;
+#ifndef OPENSSL_NO_PSK
+                else if (strcmp(*argv,"-psk_identity") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       psk_identity=*(++argv);
+                       }
+                else if (strcmp(*argv,"-psk") == 0)
+                       {
+                        size_t j;
+
+                       if (--argc < 1) goto bad;
+                       psk_key=*(++argv);
+                       for (j = 0; j < strlen(psk_key); j++)
+                                {
+                                if (isxdigit((int)psk_key[j]))
+                                        continue;
+                                BIO_printf(bio_err,"Not a hex number '%s'\n",*argv);
+                                goto bad;
+                                }
+                       }
+#endif
 #ifndef OPENSSL_NO_SSL2
                else if (strcmp(*argv,"-ssl2") == 0)
                        meth=SSLv2_client_method();
@@ -599,6 +714,14 @@ bad:
                goto end;
                }
 
+#ifndef OPENSSL_NO_PSK
+       if (psk_key != NULL)
+               {
+               if (c_debug)
+                       BIO_printf(bio_c_out, "PSK key given, setting client callback\n");
+               SSL_CTX_set_psk_client_callback(ctx, psk_client_cb);
+               }
+#endif
        if (bugs)
                SSL_CTX_set_options(ctx,SSL_OP_ALL|off);
        else
index 583bfcc..aeec035 100644 (file)
  * ECC cipher suite support in OpenSSL originally developed by 
  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
  */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
 
 /* Until the key-gen callbacks are modified to use newer prototypes, we allow
  * deprecated functions for openssl-internal code */
 #endif
 
 #include <assert.h>
+#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -263,6 +290,70 @@ static int enable_timeouts = 0;
 static long socket_mtu;
 static int cert_chain = 0;
 
+#ifndef OPENSSL_NO_PSK
+static char *psk_identity="Client_identity";
+static char *psk_key=NULL; /* by default PSK is not used */
+
+static unsigned int psk_server_cb(SSL *ssl, const char *identity,
+       unsigned char *psk, unsigned int max_psk_len)
+       {
+       unsigned int psk_len = 0;
+       int ret;
+       BIGNUM *bn = NULL;
+
+       if (s_debug)
+               BIO_printf(bio_s_out,"psk_server_cb\n");
+       if (!identity)
+               {
+               BIO_printf(bio_err,"Error: client did not send PSK identity\n");
+               goto out_err;
+               }
+       if (s_debug)
+               BIO_printf(bio_s_out,"identity_len=%d identity=%s\n",
+                       identity ? strlen(identity) : 0, identity);
+
+       /* here we could lookup the given identity e.g. from a database */
+       if (strcmp(identity, psk_identity) != 0)
+               {
+                BIO_printf(bio_s_out, "PSK error: client identity not found\n");
+               goto out_err;
+                }
+       if (s_debug)
+               BIO_printf(bio_s_out, "PSK client identity found\n");
+
+       /* convert the PSK key to binary */
+       ret = BN_hex2bn(&bn, psk_key);
+       if (!ret)
+               {
+               BIO_printf(bio_err,"Could not convert PSK key '%s' to BIGNUM\n", psk_key);
+               if (bn)
+                       BN_free(bn);
+               return 0;
+               }
+       if (BN_num_bytes(bn) > (int)max_psk_len)
+               {
+               BIO_printf(bio_err,"psk buffer of callback is too small (%d) for key (%d)\n",
+                       max_psk_len, BN_num_bytes(bn));
+               BN_free(bn);
+               return 0;
+               }
+
+       ret = BN_bn2bin(bn, psk);
+       BN_free(bn);
+
+       if (ret < 0)
+               goto out_err;
+       psk_len = (unsigned int)ret;
+
+       if (s_debug)
+               BIO_printf(bio_s_out, "fetched PSK len=%d\n", psk_len);
+        return psk_len;
+ out_err:
+       if (s_debug)
+               BIO_printf(bio_err, "Error in PSK server callback\n");
+       return 0;
+        }
+#endif
 
 #ifdef MONOLITH
 static void s_server_init(void)
@@ -339,6 +430,10 @@ static void sv_usage(void)
        BIO_printf(bio_err," -serverpref   - Use server's cipher preferences\n");
        BIO_printf(bio_err," -quiet        - No server output\n");
        BIO_printf(bio_err," -no_tmp_rsa   - Do not generate a tmp RSA key\n");
+#ifndef OPENSSL_NO_PSK
+       BIO_printf(bio_err," -psk_hint arg - PSK identity hint to use\n");
+       BIO_printf(bio_err," -psk arg      - PSK in hex (without 0x)\n");
+#endif
        BIO_printf(bio_err," -ssl2         - Just talk SSLv2\n");
        BIO_printf(bio_err," -ssl3         - Just talk SSLv3\n");
        BIO_printf(bio_err," -tls1         - Just talk TLSv1\n");
@@ -600,6 +695,10 @@ int MAIN(int argc, char *argv[])
 #ifndef OPENSSL_NO_TLSEXT
         tlsextctx tlsextcbp = {NULL, NULL, SSL_TLSEXT_ERR_ALERT_WARNING};
 #endif
+#ifndef OPENSSL_NO_PSK
+       /* by default do not send a PSK identity hint */
+       static char *psk_identity_hint=NULL;
+#endif
 #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
        meth=SSLv23_server_method();
 #elif !defined(OPENSSL_NO_SSL3)
@@ -782,6 +881,27 @@ int MAIN(int argc, char *argv[])
                        { no_dhe=1; }
                else if (strcmp(*argv,"-no_ecdhe") == 0)
                        { no_ecdhe=1; }
+#ifndef OPENSSL_NO_PSK
+                else if (strcmp(*argv,"-psk_hint") == 0)
+                       {
+                        if (--argc < 1) goto bad;
+                        psk_identity_hint= *(++argv);
+                        }
+                else if (strcmp(*argv,"-psk") == 0)
+                       {
+                       int i;
+
+                       if (--argc < 1) goto bad;
+                       psk_key=*(++argv);
+                       for (i=0; i<strlen(psk_key); i++)
+                               {
+                               if (isxdigit((int)psk_key[i]))
+                                       continue;
+                               BIO_printf(bio_err,"Not a hex number '%s'\n",*argv);
+                               goto bad;
+                               }
+                       }
+#endif
                else if (strcmp(*argv,"-www") == 0)
                        { www=1; }
                else if (strcmp(*argv,"-WWW") == 0)
@@ -1259,6 +1379,22 @@ bad:
 #endif
 #endif
 
+#ifndef OPENSSL_NO_PSK
+       if (psk_key != NULL)
+               {
+               if (s_debug)
+                       BIO_printf(bio_s_out, "PSK key given, setting server callback\n");
+               SSL_CTX_set_psk_server_callback(ctx, psk_server_cb);
+               }
+
+       if (!SSL_CTX_use_psk_identity_hint(ctx, psk_identity_hint))
+               {
+               BIO_printf(bio_err,"error setting PSK identity hint to context\n");
+               ERR_print_errors(bio_err);
+               goto end;
+               }
+#endif
+
        if (cipher != NULL)
                {
                if(!SSL_CTX_set_cipher_list(ctx,cipher))
index e1e1ba9..3cdd1e2 100644 (file)
@@ -157,6 +157,16 @@ input.
 inhibit printing of session and certificate information.  This implicitly
 turns on B<-ign_eof> as well.
 
+=item B<-psk_identity identity>
+
+Use the PSK identity B<identity> when using a PSK cipher suite.
+
+=item B<-psk key>
+
+Use the PSK key B<key> when using a PSK cipher suite. The key is
+given as a hexadecimal number without leading 0x, for example -psk
+1a2b3c4d.
+
 =item B<-ssl2>, B<-ssl3>, B<-tls1>, B<-no_ssl2>, B<-no_ssl3>, B<-no_tls1>
 
 these options disable the use of certain SSL or TLS protocols. By default
index 7c1a958..8c15add 100644 (file)
@@ -181,6 +181,16 @@ this option translated a line feed from the terminal into CR+LF.
 
 inhibit printing of session and certificate information.
 
+=item B<-psk_hint hint>
+
+Use the PSK identity hint B<hint> when using a PSK cipher suite.
+
+=item B<-psk key>
+
+Use the PSK key B<key> when using a PSK cipher suite. The key is
+given as a hexadecimal number without leading 0x, for example -psk
+1a2b3c4d.
+
 =item B<-ssl2>, B<-ssl3>, B<-tls1>, B<-no_ssl2>, B<-no_ssl3>, B<-no_tls1>
 
 these options disable the use of certain SSL or TLS protocols. By default
diff --git a/doc/ssl/SSL_CTX_set_psk_client_callback.pod b/doc/ssl/SSL_CTX_set_psk_client_callback.pod
new file mode 100644 (file)
index 0000000..573f89a
--- /dev/null
@@ -0,0 +1,81 @@
+=pod
+
+=begin comment
+
+Copyright 2005 Nokia. All rights reserved.
+
+The portions of the attached software ("Contribution") is developed by
+Nokia Corporation and is licensed pursuant to the OpenSSL open source
+license.
+
+The Contribution, originally written by Mika Kousa and Pasi Eronen of
+Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+support (see RFC 4279) to OpenSSL.
+
+No patent licenses or other rights except those expressly stated in
+the OpenSSL open source license shall be deemed granted or received
+expressly, by implication, estoppel, or otherwise.
+
+No assurances are provided by Nokia that the Contribution does not
+infringe the patent or other intellectual property rights of any third
+party or that the license provides you with all the necessary rights
+to make use of the Contribution.
+
+THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+OTHERWISE.
+
+=end comment
+
+=head1 NAME
+
+SSL_CTX_set_psk_client_callback, SSL_set_psk_client_callback - set PSK client callback
+
+=head1 SYNOPSIS
+
+ #include <openssl/ssl.h>
+
+ void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx,
+       unsigned int (*callback)(SSL *ssl, const char *hint,
+       char *identity, unsigned int max_identity_len,
+       unsigned char *psk, unsigned int max_psk_len));
+ void SSL_set_psk_client_callback(SSL *ssl,
+       unsigned int (*callback)(SSL *ssl, const char *hint,
+       char *identity, unsigned int max_identity_len,
+       unsigned char *psk, unsigned int max_psk_len));
+
+
+=head1 DESCRIPTION
+
+A client application must provide a callback function which is called
+when the client is sending the ClientKeyExchange message to the server.
+
+The purpose of the callback function is to select the PSK identity and
+the pre-shared key to use during the connection setup phase.
+
+The callback is set using functions SSL_CTX_set_psk_client_callback()
+or SSL_set_psk_client_callback(). The callback function is given the
+connection in parameter B<ssl>, a B<NULL>-terminated PSK identity hint
+sent by the server in parameter B<hint>, a buffer B<identity> of
+length B<max_identity_len> bytes where the the resulting
+B<NULL>-terminated identity is to be stored, and a buffer B<psk> of
+length B<max_psk_len> bytes where the resulting pre-shared key is to
+be stored.
+
+=head1 NOTES
+
+Note that parameter B<hint> given to the callback may be B<NULL>.
+
+=head1 RETURN VALUES
+
+Return values from the client callback are interpreted as follows:
+
+On success (callback found a PSK identity and a pre-shared key to use)
+the length (> 0) of B<psk> in bytes is returned.
+
+Otherwise or on errors callback should return 0. In this case
+the connection setup fails.
+
+=cut
diff --git a/doc/ssl/SSL_CTX_use_psk_identity_hint.pod b/doc/ssl/SSL_CTX_use_psk_identity_hint.pod
new file mode 100644 (file)
index 0000000..b80e25b
--- /dev/null
@@ -0,0 +1,102 @@
+=pod
+
+=begin comment
+
+Copyright 2005 Nokia. All rights reserved.
+
+The portions of the attached software ("Contribution") is developed by
+Nokia Corporation and is licensed pursuant to the OpenSSL open source
+license.
+
+The Contribution, originally written by Mika Kousa and Pasi Eronen of
+Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+support (see RFC 4279) to OpenSSL.
+
+No patent licenses or other rights except those expressly stated in
+the OpenSSL open source license shall be deemed granted or received
+expressly, by implication, estoppel, or otherwise.
+
+No assurances are provided by Nokia that the Contribution does not
+infringe the patent or other intellectual property rights of any third
+party or that the license provides you with all the necessary rights
+to make use of the Contribution.
+
+THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+OTHERWISE.
+
+=end comment
+
+=head1 NAME
+
+SSL_CTX_use_psk_identity_hint, SSL_use_psk_identity_hint,
+SSL_CTX_set_psk_server_callback, SSL_set_psk_server_callback - set PSK
+identity hint to use
+
+
+=head1 SYNOPSIS
+
+ #include <openssl/ssl.h>
+
+ int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *hint);
+ int SSL_use_psk_identity_hint(SSL *ssl, const char *hint);
+
+ void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx,
+       unsigned int (*callback)(SSL *ssl, const char *identity,
+       unsigned char *psk, int max_psk_len));
+ void SSL_set_psk_server_callback(SSL *ssl,
+       unsigned int (*callback)(SSL *ssl, const char *identity,
+       unsigned char *psk, int max_psk_len));
+
+
+=head1 DESCRIPTION
+
+SSL_CTX_use_psk_identity_hint() sets the given B<NULL>-terminated PSK
+identity hint B<hint> to SSL context object
+B<ctx>. SSL_use_psk_identity_hint() sets the given B<NULL>-terminated
+PSK identity hint B<hint> to SSL connection object B<ssl>. If B<hint>
+is B<NULL> the current hint from B<ctx> or B<ssl> is deleted.
+
+In the case where PSK identity hint is B<NULL>, the server
+does not send the ServerKeyExchange message to the client.
+
+A server application must provide a callback function which is called
+when the server receives the ClientKeyExchange message from the
+client. The purpose of the callback function is to validate the
+received PSK identity and to fetch the pre-shared key used during the
+connection setup phase. The callback is set using functions
+SSL_CTX_set_psk_server_callback() or
+SSL_set_psk_server_callback(). The callback function is given the
+connection in parameter B<ssl>, B<NULL>-terminated PSK identity sent
+by the client in parameter B<identity>, and a buffer B<psk> of length
+B<max_psk_len> bytes where the pre-shared key is to be stored.
+
+
+=head1 RETURN VALUES
+
+SSL_CTX_use_psk_identity_hint() and SSL_use_psk_identity_hint() return
+1 on success, 0 otherwise.
+
+Return values from the server callback are interpreted as follows:
+
+=item > 0
+
+PSK identity was found and the server callback has provided the PSK
+successfully in parameter B<psk>. Return value is the length of
+B<psk> in bytes. It is an error to return a value greater than
+B<max_psk_len>.
+
+If the PSK identity was not found but the callback instructs the
+protocol to continue anyway, the callback must provide some random
+data to B<psk> and return the length of the random data, so the
+connection will fail with decryption_error before it will be finished
+completely.
+
+=item 0
+
+PSK identity was not found. An "unknown_psk_identity" alert message
+will be sent and the connection setup fails.
+
+=cut
diff --git a/doc/ssl/SSL_get_psk_identity.pod b/doc/ssl/SSL_get_psk_identity.pod
new file mode 100644 (file)
index 0000000..fe62916
--- /dev/null
@@ -0,0 +1,63 @@
+=pod
+
+=begin comment
+
+Copyright 2005 Nokia. All rights reserved.
+
+The portions of the attached software ("Contribution") is developed by
+Nokia Corporation and is licensed pursuant to the OpenSSL open source
+license.
+
+The Contribution, originally written by Mika Kousa and Pasi Eronen of
+Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+support (see RFC 4279) to OpenSSL.
+
+No patent licenses or other rights except those expressly stated in
+the OpenSSL open source license shall be deemed granted or received
+expressly, by implication, estoppel, or otherwise.
+
+No assurances are provided by Nokia that the Contribution does not
+infringe the patent or other intellectual property rights of any third
+party or that the license provides you with all the necessary rights
+to make use of the Contribution.
+
+THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+OTHERWISE.
+
+=end comment
+
+=head1 NAME
+
+SSL_get_psk_identity, SSL_get_psk_identity_hint - get PSK client identity and hint
+
+
+=head1 SYNOPSIS
+
+ #include <openssl/ssl.h>
+
+ const char *SSL_get_psk_identity_hint(const SSL *ssl);
+ const char *SSL_get_psk_identity(const SSL *ssl);
+
+
+=head1 DESCRIPTION
+
+SSL_get_psk_identity_hint() is used to retrieve the PSK identity hint
+used during the connection setup related to SSL object
+B<ssl>. Similarly, SSL_get_psk_identity() is used to retrieve the PSK
+identity used during the connection setup.
+
+
+=head1 RETURN VALUES
+
+If non-B<NULL>, SSL_get_psk_identity_hint() returns the PSK identity
+hint and SSL_get_psk_identity() returns the PSK identity. Both are
+B<NULL>-terminated. SSL_get_psk_identity_hint() may return B<NULL> if
+no PSK identity hint was used during the connection setup.
+
+Note that the return value is valid only during the lifetime of the
+SSL object B<ssl>.
+
+=cut
index 8391c66..2b6004e 100644 (file)
@@ -374,6 +374,15 @@ session instead of a context.
 
 =item int B<SSL_CTX_use_certificate_file>(SSL_CTX *ctx, char *file, int type);
 
+=item void B<SSL_CTX_set_psk_client_callback>(SSL_CTX *ctx, unsigned int (*callback)(SSL *ssl, const char *hint, char *identity, unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len));
+
+=item int B<SSL_CTX_use_psk_identity_hint>(SSL_CTX *ctx, const char *hint);
+
+=item void B<SSL_CTX_set_psk_server_callback>(SSL_CTX *ctx, unsigned int (*callback)(SSL *ssl, const char *identity, unsigned char *psk, int max_psk_len));
+
+
+
+
 =back
 
 =head2 DEALING WITH SESSIONS
@@ -650,6 +659,16 @@ connection defined in the B<SSL> structure.
 
 =item int B<SSL_write>(SSL *ssl, const void *buf, int num);
 
+=item void B<SSL_set_psk_client_callback>(SSL *ssl, unsigned int (*callback)(SSL *ssl, const char *hint, char *identity, unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len));
+
+=item int B<SSL_use_psk_identity_hint>(SSL *ssl, const char *hint);
+
+=item void B<SSL_set_psk_server_callback>(SSL *ssl, unsigned int (*callback)(SSL *ssl, const char *identity, unsigned char *psk, int max_psk_len));
+
+=item const char *B<SSL_get_psk_identity_hint>(SSL *ssl);
+
+=item const char *B<SSL_get_psk_identity>(SSL *ssl);
+
 =back
 
 =head1 SEE ALSO
@@ -726,7 +745,10 @@ L<SSL_write(3)|SSL_write(3)>,
 L<SSL_SESSION_free(3)|SSL_SESSION_free(3)>,
 L<SSL_SESSION_get_ex_new_index(3)|SSL_SESSION_get_ex_new_index(3)>,
 L<SSL_SESSION_get_time(3)|SSL_SESSION_get_time(3)>,
-L<d2i_SSL_SESSION(3)|d2i_SSL_SESSION(3)>
+L<d2i_SSL_SESSION(3)|d2i_SSL_SESSION(3)>,
+L<SSL_CTX_set_psk_client_callback(3)|SSL_CTX_set_psk_client_callback(3)>,
+L<SSL_CTX_use_psk_identity_hint(3)|SSL_CTX_use_psk_identity_hint(3)>,
+L<SSL_get_psk_identity(3)|SSL_get_psk_identity(3)>
 
 =head1 HISTORY
 
index 995c829..237dfb6 100644 (file)
  * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
  *
  */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
 
 #include <stdio.h>
 #include "ssl_locl.h"
@@ -266,7 +292,9 @@ int ssl3_connect(SSL *s)
                case SSL3_ST_CR_CERT_A:
                case SSL3_ST_CR_CERT_B:
                        /* Check if it is anon DH/ECDH */
-                       if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL))
+                       /* or PSK */
+                       if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL)
+                               && !(s->s3->tmp.new_cipher->algorithms & SSL_kPSK))
                                {
                                ret=ssl3_get_server_certificate(s);
                                if (ret <= 0) goto end;
@@ -1043,17 +1071,28 @@ int ssl3_get_key_exchange(SSL *s)
                -1,
                s->max_cert_list,
                &ok);
-
        if (!ok) return((int)n);
 
        if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE)
                {
+#ifndef OPENSSL_NO_PSK
+               /* In plain PSK ciphersuite, ServerKeyExchange can be
+                  omitted if no identity hint is sent. Set
+                  session->sess_cert anyway to avoid problems
+                  later.*/
+                if (s->s3->tmp.new_cipher->algorithms & SSL_kPSK)
+                       {
+                       s->session->sess_cert=ssl_sess_cert_new();
+                       if (s->ctx->psk_identity_hint)
+                               OPENSSL_free(s->ctx->psk_identity_hint);
+                       s->ctx->psk_identity_hint = NULL;
+                       }
+#endif
                s->s3->tmp.reuse_message=1;
                return(1);
                }
 
        param=p=(unsigned char *)s->init_msg;
-
        if (s->session->sess_cert != NULL)
                {
 #ifndef OPENSSL_NO_RSA
@@ -1087,6 +1126,51 @@ int ssl3_get_key_exchange(SSL *s)
        alg=s->s3->tmp.new_cipher->algorithms;
        EVP_MD_CTX_init(&md_ctx);
 
+#ifndef OPENSSL_NO_PSK
+       if (alg & SSL_kPSK)
+               {
+               char tmp_id_hint[PSK_MAX_IDENTITY_LEN+1];
+
+               al=SSL_AD_HANDSHAKE_FAILURE;
+               n2s(p,i);
+               param_len=i+2;
+               /* Store PSK identity hint for later use, hint is used
+                * in ssl3_send_client_key_exchange.  Assume that the
+                * maximum length of a PSK identity hint can be as
+                * long as the maximum length of a PSK identity. */
+               if (i > PSK_MAX_IDENTITY_LEN)
+                       {
+                       SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+                               SSL_R_DATA_LENGTH_TOO_LONG);
+                       goto f_err;
+                       }
+               if (param_len > n)
+                       {
+                       al=SSL_AD_DECODE_ERROR;
+                       SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+                               SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH);
+                       goto f_err;
+                       }
+               /* If received PSK identity hint contains NULL
+                * characters, the hint is truncated from the first
+                * NULL. p may not be ending with NULL, so create a
+                * NULL-terminated string. */
+               memcpy(tmp_id_hint, p, i);
+               memset(tmp_id_hint+i, 0, PSK_MAX_IDENTITY_LEN+1-i);
+               if (s->ctx->psk_identity_hint != NULL)
+                       OPENSSL_free(s->ctx->psk_identity_hint);
+               s->ctx->psk_identity_hint = BUF_strdup(tmp_id_hint);
+               if (s->ctx->psk_identity_hint == NULL)
+                       {
+                       SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+                       goto f_err;
+                       }           
+
+               p+=i;
+               n-=param_len;
+               }
+       else
+#endif /* !OPENSSL_NO_PSK */
 #ifndef OPENSSL_NO_RSA
        if (alg & SSL_kRSA)
                {
@@ -1430,12 +1514,13 @@ int ssl3_get_key_exchange(SSL *s)
                }
        else
                {
-               /* still data left over */
-               if (!(alg & SSL_aNULL))
+               if (!(alg & SSL_aNULL) && !(alg & SSL_kPSK))
+                       /* aNULL or kPSK do not need public keys */
                        {
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
                        goto err;
                        }
+               /* still data left over */
                if (n != 0)
                        {
                        al=SSL_AD_DECODE_ERROR;
@@ -2104,6 +2189,88 @@ int ssl3_send_client_key_exchange(SSL *s)
                        EVP_PKEY_free(srvr_pub_pkey);
                        }
 #endif /* !OPENSSL_NO_ECDH */
+#ifndef OPENSSL_NO_PSK
+               else if (l & SSL_kPSK)
+                       {
+                       char identity[PSK_MAX_IDENTITY_LEN];
+                       unsigned char *t = NULL;
+                       unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4];
+                       unsigned int pre_ms_len = 0, psk_len = 0;
+                       int psk_err = 1;
+
+                       n = 0;
+                       if (s->psk_client_callback == NULL)
+                               {
+                               SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+                                       SSL_R_PSK_NO_CLIENT_CB);
+                               goto err;
+                               }
+
+                       psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint,
+                               identity, PSK_MAX_IDENTITY_LEN,
+                               psk_or_pre_ms, sizeof(psk_or_pre_ms));
+                       if (psk_len > PSK_MAX_PSK_LEN)
+                               {
+                               SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+                                       ERR_R_INTERNAL_ERROR);
+                               goto psk_err;
+                               }
+                       else if (psk_len == 0)
+                               {
+                               SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+                                       SSL_R_PSK_IDENTITY_NOT_FOUND);
+                               goto psk_err;
+                               }
+
+                       /* create PSK pre_master_secret */
+                       pre_ms_len = 2+psk_len+2+psk_len;
+                       t = psk_or_pre_ms;
+                       memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len);
+                       s2n(psk_len, t);
+                       memset(t, 0, psk_len);
+                       t+=psk_len;
+                       s2n(psk_len, t);
+
+                       if (s->session->psk_identity_hint != NULL)
+                               OPENSSL_free(s->session->psk_identity_hint);
+                       s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint);
+                       if (s->ctx->psk_identity_hint != NULL &&
+                               s->session->psk_identity_hint == NULL)
+                               {
+                               SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+                                       ERR_R_MALLOC_FAILURE);
+                               goto psk_err;
+                               }
+
+                       if (s->session->psk_identity != NULL)
+                               OPENSSL_free(s->session->psk_identity);
+                       s->session->psk_identity = BUF_strdup(identity);
+                       if (s->session->psk_identity == NULL)
+                               {
+                               SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+                                       ERR_R_MALLOC_FAILURE);
+                               goto psk_err;
+                               }
+
+                       s->session->master_key_length =
+                               s->method->ssl3_enc->generate_master_secret(s,
+                                       s->session->master_key,
+                                       psk_or_pre_ms, pre_ms_len); 
+                       n = strlen(identity);
+                       s2n(n, p);
+                       memcpy(p, identity, n);
+                       n+=2;
+                       psk_err = 0;
+               psk_err:
+                       OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN);
+                       OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));  
+                       if (psk_err != 0)
+                               {
+                               ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+                               goto err;
+                               }
+                       }
+#endif
                else
                        {
                        ssl3_send_alert(s, SSL3_AL_FATAL,
@@ -2316,7 +2483,6 @@ int ssl3_check_cert_and_algorithm(SSL *s)
 #endif
 
        sc=s->session->sess_cert;
-
        if (sc == NULL)
                {
                SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,ERR_R_INTERNAL_ERROR);
@@ -2326,7 +2492,7 @@ int ssl3_check_cert_and_algorithm(SSL *s)
        algs=s->s3->tmp.new_cipher->algorithms;
 
        /* we don't have a certificate */
-       if (algs & (SSL_aDH|SSL_aNULL|SSL_aKRB5))
+       if (algs & (SSL_aDH|SSL_aNULL|SSL_aKRB5|SSL_kPSK))
                return(1);
 
 #ifndef OPENSSL_NO_RSA
index 4baba2e..b4c6f0f 100644 (file)
  * Hudson (tjh@cryptsoft.com).
  *
  */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
 
 #include <stdio.h>
 #include "ssl_locl.h"
@@ -714,6 +740,7 @@ int ssl3_alert_code(int code)
        case SSL_AD_UNRECOGNIZED_NAME:  return(SSL3_AD_HANDSHAKE_FAILURE);
        case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: return(SSL3_AD_HANDSHAKE_FAILURE);
        case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(SSL3_AD_HANDSHAKE_FAILURE);
+       case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY);
        default:                        return(-1);
                }
        }
index 6ccd8b1..aecf6d6 100644 (file)
  * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
  *
  */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
 
 #include <stdio.h>
 #include <openssl/objects.h>
@@ -997,6 +1023,63 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
            SSL_ALL_STRENGTHS
            },
 #endif
+#ifndef OPENSSL_NO_PSK
+       /* Cipher 8A */
+       {
+       1,
+       TLS1_TXT_PSK_WITH_RC4_128_SHA,
+       TLS1_CK_PSK_WITH_RC4_128_SHA,
+       SSL_kPSK|SSL_aPSK|SSL_RC4|SSL_SHA|SSL_TLSV1,
+       SSL_NOT_EXP|SSL_MEDIUM,
+       0,
+       128,
+       128,
+       SSL_ALL_CIPHERS,
+       SSL_ALL_STRENGTHS,
+       },
+
+       /* Cipher 8B */
+       {
+       1,
+       TLS1_TXT_PSK_WITH_3DES_EDE_CBC_SHA,
+       TLS1_CK_PSK_WITH_3DES_EDE_CBC_SHA,
+       SSL_kPSK|SSL_aPSK|SSL_3DES|SSL_SHA|SSL_TLSV1,
+       SSL_NOT_EXP|SSL_HIGH,
+       0,
+       168,
+       168,
+       SSL_ALL_CIPHERS,
+       SSL_ALL_STRENGTHS,
+       },
+
+       /* Cipher 8C */
+       {
+       1,
+       TLS1_TXT_PSK_WITH_AES_128_CBC_SHA,
+       TLS1_CK_PSK_WITH_AES_128_CBC_SHA,
+       SSL_kPSK|SSL_aPSK|SSL_AES|SSL_SHA|SSL_TLSV1,
+       SSL_NOT_EXP|SSL_MEDIUM,
+       0,
+       128,
+       128,
+       SSL_ALL_CIPHERS,
+       SSL_ALL_STRENGTHS,
+       },
+
+       /* Cipher 8D */
+       {
+       1,
+       TLS1_TXT_PSK_WITH_AES_256_CBC_SHA,
+       TLS1_CK_PSK_WITH_AES_256_CBC_SHA,
+       SSL_kPSK|SSL_aPSK|SSL_AES|SSL_SHA|SSL_TLSV1,
+       SSL_NOT_EXP|SSL_HIGH,
+       0,
+       256,
+       256,
+       SSL_ALL_CIPHERS,
+       SSL_ALL_STRENGTHS,
+       },
+#endif  /* OPENSSL_NO_PSK */
 #ifndef OPENSSL_NO_ECDH
        /* Cipher C001 */
            {
@@ -2018,6 +2101,12 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
                             continue;
                         }
 #endif /* OPENSSL_NO_KRB5 */
+#ifndef OPENSSL_NO_PSK
+               /* with PSK there must be server callback set */
+               if ((alg & SSL_PSK) && s->psk_server_callback == NULL)
+                       continue;
+#endif /* OPENSSL_NO_PSK */
+
                if (SSL_C_IS_EXPORT(c))
                        {
                        ok=((alg & emask) == alg)?1:0;
index 44b9c9c..8859540 100644 (file)
  * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
  *
  */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
 
 #define REUSE_CIPHER_BUG
 #define NETSCAPE_HANG_BUG
@@ -302,7 +328,9 @@ int ssl3_accept(SSL *s)
                case SSL3_ST_SW_CERT_A:
                case SSL3_ST_SW_CERT_B:
                        /* Check if it is anon DH or anon ECDH */
-                       if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL))
+                       /* or normal PSK */
+                       if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL)
+                               && !(s->s3->tmp.new_cipher->algorithms & SSL_kPSK))
                                {
                                ret=ssl3_send_server_certificate(s);
                                if (ret <= 0) goto end;
@@ -336,6 +364,8 @@ int ssl3_accept(SSL *s)
                        /* only send if a DH key exchange, fortezza or
                         * RSA but we have a sign only certificate
                         *
+                        * PSK: may send PSK identity hints
+                        *
                         * For ECC ciphersuites, we send a serverKeyExchange
                         * message only if the cipher suite is either
                         * ECDH-anon or ECDHE. In other cases, the
@@ -343,6 +373,11 @@ int ssl3_accept(SSL *s)
                         * public key for key exchange.
                         */
                        if (s->s3->tmp.use_rsa_tmp
+                       /* PSK: send ServerKeyExchange if PSK identity
+                        * hint if provided */
+#ifndef OPENSSL_NO_PSK
+                           || ((l & SSL_kPSK) && s->ctx->psk_identity_hint)
+#endif
                            || (l & SSL_kECDHE)
                            || (l & (SSL_DH|SSL_kFZA))
                            || ((l & SSL_kRSA)
@@ -380,7 +415,10 @@ int ssl3_accept(SSL *s)
                                  * (against the specs, but s3_clnt.c accepts this for SSL 3) */
                                 !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) ||
                                  /* never request cert in Kerberos ciphersuites */
-                                (s->s3->tmp.new_cipher->algorithms & SSL_aKRB5))
+                                (s->s3->tmp.new_cipher->algorithms & SSL_aKRB5)
+                               /* With normal PSK Certificates and
+                                * Certificate Requests are omitted */
+                                || (s->s3->tmp.new_cipher->algorithms & SSL_kPSK))
                                {
                                /* no cert request */
                                skip=1;
@@ -1390,6 +1428,14 @@ int ssl3_send_server_key_exchange(SSL *s)
                        }
                else 
 #endif /* !OPENSSL_NO_ECDH */
+#ifndef OPENSSL_NO_PSK
+                       if (type & SSL_kPSK)
+                               {
+                               /* reserve size for record length and PSK identity hint*/
+                               n+=2+strlen(s->ctx->psk_identity_hint);
+                               }
+                       else
+#endif /* !OPENSSL_NO_PSK */
                        {
                        al=SSL_AD_HANDSHAKE_FAILURE;
                        SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
@@ -1401,7 +1447,8 @@ int ssl3_send_server_key_exchange(SSL *s)
                        n+=2+nr[i];
                        }
 
-               if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL))
+               if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL)
+                       && !(s->s3->tmp.new_cipher->algorithms & SSL_kPSK))
                        {
                        if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher))
                                == NULL)
@@ -1457,6 +1504,16 @@ int ssl3_send_server_key_exchange(SSL *s)
                        }
 #endif
 
+#ifndef OPENSSL_NO_PSK
+               if (type & SSL_kPSK)
+                       {
+                       /* copy PSK identity hint */
+                       s2n(strlen(s->ctx->psk_identity_hint), p); 
+                       strncpy(p, s->ctx->psk_identity_hint, strlen(s->ctx->psk_identity_hint));
+                       p+=strlen(s->ctx->psk_identity_hint);
+                       }
+#endif
+
                /* not anonymous */
                if (pkey != NULL)
                        {
@@ -2177,6 +2234,101 @@ int ssl3_get_client_key_exchange(SSL *s)
                 return (ret);
                }
        else
+#endif
+#ifndef OPENSSL_NO_PSK
+               if (l & SSL_kPSK)
+                       {
+                       unsigned char *t = NULL;
+                       unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4];
+                       unsigned int pre_ms_len = 0, psk_len = 0;
+                       int psk_err = 1;
+                       char tmp_id[PSK_MAX_IDENTITY_LEN+1];
+
+                       al=SSL_AD_HANDSHAKE_FAILURE;
+
+                       n2s(p,i);
+                       if (n != i+2)
+                               {
+                               SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+                                       SSL_R_LENGTH_MISMATCH);
+                               goto psk_err;
+                               }
+                       if (i > PSK_MAX_IDENTITY_LEN)
+                               {
+                               SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+                                       SSL_R_DATA_LENGTH_TOO_LONG);
+                               goto psk_err;
+                               }
+                       if (s->psk_server_callback == NULL)
+                               {
+                               SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+                                      SSL_R_PSK_NO_SERVER_CB);
+                               goto psk_err;
+                               }
+
+                       /* Create guaranteed NULL-terminated identity
+                        * string for the callback */
+                       memcpy(tmp_id, p, i);
+                       memset(tmp_id+i, 0, PSK_MAX_IDENTITY_LEN+1-i);
+                       psk_len = s->psk_server_callback(s, tmp_id,
+                               psk_or_pre_ms, sizeof(psk_or_pre_ms));
+                       OPENSSL_cleanse(tmp_id, PSK_MAX_IDENTITY_LEN+1);
+
+                       if (psk_len > PSK_MAX_PSK_LEN)
+                               {
+                               SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+                                       ERR_R_INTERNAL_ERROR);
+                               goto psk_err;
+                               }
+                       else if (psk_len == 0)
+                               {
+                               /* PSK related to the given identity not found */
+                               SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+                                      SSL_R_PSK_IDENTITY_NOT_FOUND);
+                               al=SSL_AD_UNKNOWN_PSK_IDENTITY;
+                               goto psk_err;
+                               }
+
+                       /* create PSK pre_master_secret */
+                       pre_ms_len=2+psk_len+2+psk_len;
+                       t = psk_or_pre_ms;
+                       memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len);
+                       s2n(psk_len, t);
+                       memset(t, 0, psk_len);
+                       t+=psk_len;
+                       s2n(psk_len, t);
+
+                       if (s->session->psk_identity != NULL)
+                               OPENSSL_free(s->session->psk_identity);
+                       s->session->psk_identity = BUF_strdup(p);
+                       if (s->session->psk_identity == NULL)
+                               {
+                               SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+                                       ERR_R_MALLOC_FAILURE);
+                               goto psk_err;
+                               }
+
+                       if (s->session->psk_identity_hint != NULL)
+                               OPENSSL_free(s->session->psk_identity_hint);
+                       s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint);
+                       if (s->ctx->psk_identity_hint != NULL &&
+                               s->session->psk_identity_hint == NULL)
+                               {
+                               SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+                                       ERR_R_MALLOC_FAILURE);
+                               goto psk_err;
+                               }
+
+                       s->session->master_key_length=
+                               s->method->ssl3_enc->generate_master_secret(s,
+                                       s->session->master_key, psk_or_pre_ms, pre_ms_len);
+                       psk_err = 0;
+               psk_err:
+                       OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));
+                        if (psk_err != 0)
+                                goto f_err;
+                       }
+               else
 #endif
                {
                al=SSL_AD_HANDSHAKE_FAILURE;
index e4534f3..33792ea 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
  * ECC cipher suite support in OpenSSL originally developed by 
  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
  */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
 
 #ifndef HEADER_SSL_H 
 #define HEADER_SSL_H 
@@ -294,6 +320,9 @@ extern "C" {
 #define SSL_TXT_TLSV1          "TLSv1"
 #define SSL_TXT_ALL            "ALL"
 #define SSL_TXT_ECC            "ECCdraft" /* ECC ciphersuites are not yet official */
+#define SSL_TXT_PSK             "PSK"
+#define SSL_TXT_kPSK            "kPSK"
+#define SSL_TXT_aPSK            "aPSK"
 
 /*
  * COMPLEMENTOF* definitions. These identifiers are used to (de-select)
@@ -410,8 +439,9 @@ typedef struct ssl_method_st
  *     Timeout [ 2 ] EXPLICIT  INTEGER,        -- optional Timeout ins seconds
  *     Peer [ 3 ] EXPLICIT     X509,           -- optional Peer Certificate
  *     Session_ID_context [ 4 ] EXPLICIT OCTET_STRING,   -- the Session ID context
- *     Verify_result [ 5 ] EXPLICIT INTEGER    -- X509_V_... code for `Peer'
- *     Compression [6] IMPLICIT ASN1_OBJECT    -- compression OID XXXXX
+ *     Verify_result [ 5 ] EXPLICIT INTEGER,   -- X509_V_... code for `Peer'
+ *     PSK_identity_hint [ 6 ] EXPLICIT OCTET_STRING, -- PSK identity hint
+ *      PSK_identity [ 7 ] EXPLICIT OCTET_STRING -- PSK identity
  *     }
  * Look in ssl/ssl_asn1.c for more details
  * I'm using EXPLICIT tags so I can read the damn things using asn1parse :-).
@@ -439,7 +469,10 @@ typedef struct ssl_session_st
         unsigned int krb5_client_princ_len;
         unsigned char krb5_client_princ[SSL_MAX_KRB5_PRINCIPAL_LENGTH];
 #endif /* OPENSSL_NO_KRB5 */
-
+#ifndef OPENSSL_NO_PSK
+       char *psk_identity_hint;
+       char *psk_identity;
+#endif
        int not_resumable;
 
        /* The cert is the certificate used to establish this connection */
@@ -763,6 +796,14 @@ struct ssl_ctx_st
        /* TLS extensions servername callback */
        int (*tlsext_servername_callback)(SSL*, int *, void *);
        void *tlsext_servername_arg;
+#endif
+#ifndef OPENSSL_NO_PSK
+       char *psk_identity_hint;
+       unsigned int (*psk_client_callback)(SSL *ssl, const char *hint, char *identity,
+               unsigned int max_identity_len, unsigned char *psk,
+               unsigned int max_psk_len);
+       unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
+               unsigned char *psk, unsigned int max_psk_len);
 #endif
        };
 
@@ -816,6 +857,21 @@ struct ssl_ctx_st
 #define SSL_CTX_set_cookie_generate_cb(ctx,cb) ((ctx)->app_gen_cookie_cb=(cb))
 #define SSL_CTX_set_cookie_verify_cb(ctx,cb) ((ctx)->app_verify_cookie_cb=(cb))
 
+#ifndef OPENSSL_NO_PSK
+/* the maximum length of the buffer given to callbacks containing the
+ * resulting identity/psk */
+#define PSK_MAX_IDENTITY_LEN 128
+#define PSK_MAX_PSK_LEN 64
+#define SSL_CTX_set_psk_client_callback(ctx,cb) ((ctx)->psk_client_callback=(cb))
+#define SSL_set_psk_client_callback(ssl, cb) ((ssl)->psk_client_callback=(cb))
+#define SSL_CTX_set_psk_server_callback(ctx,cb) ((ctx)->psk_server_callback=(cb))
+#define SSL_set_psk_server_callback(ssl, cb) ((ssl)->psk_server_callback=(cb))
+int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint);
+int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint);
+const char *SSL_get_psk_identity_hint(const SSL *s);
+const char *SSL_get_psk_identity(const SSL *s);
+#endif
+
 #define SSL_NOTHING    1
 #define SSL_WRITING    2
 #define SSL_READING    3
@@ -966,6 +1022,14 @@ struct ssl_st
        KSSL_CTX *kssl_ctx;     /* Kerberos 5 context */
 #endif /* OPENSSL_NO_KRB5 */
 
+#ifndef OPENSSL_NO_PSK
+       unsigned int (*psk_client_callback)(SSL *ssl, const char *hint, char *identity,
+               unsigned int max_identity_len, unsigned char *psk,
+               unsigned int max_psk_len);
+       unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
+               unsigned char *psk, unsigned int max_psk_len);
+#endif
+
        SSL_CTX *ctx;
        /* set this flag to 1 and a sleep(1) is put into all SSL_read()
         * and SSL_write() calls, good for nbio debuging :-) */
@@ -1149,6 +1213,7 @@ size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);
 #define SSL_AD_UNRECOGNIZED_NAME       TLS1_AD_UNRECOGNIZED_NAME
 #define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
 #define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE
+#define SSL_AD_UNKNOWN_PSK_IDENTITY     TLS1_AD_UNKNOWN_PSK_IDENTITY /* fatal */
 
 #define SSL_ERROR_NONE                 0
 #define SSL_ERROR_SSL                  1
@@ -1718,6 +1783,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_SSL_CTX_USE_PRIVATEKEY                    174
 #define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1               175
 #define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE               176
+#define SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT             272
 #define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY                         177
 #define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1            178
 #define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE            179
@@ -1756,6 +1822,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_SSL_USE_PRIVATEKEY                        201
 #define SSL_F_SSL_USE_PRIVATEKEY_ASN1                   202
 #define SSL_F_SSL_USE_PRIVATEKEY_FILE                   203
+#define SSL_F_SSL_USE_PSK_IDENTITY_HINT                         273
 #define SSL_F_SSL_USE_RSAPRIVATEKEY                     204
 #define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1                205
 #define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE                206
@@ -1789,6 +1856,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_R_BAD_MESSAGE_TYPE                          114
 #define SSL_R_BAD_PACKET_LENGTH                                 115
 #define SSL_R_BAD_PROTOCOL_VERSION_NUMBER               116
+#define SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH              157
 #define SSL_R_BAD_RESPONSE_ARGUMENT                     117
 #define SSL_R_BAD_RSA_DECRYPT                           118
 #define SSL_R_BAD_RSA_ENCRYPT                           119
@@ -1908,6 +1976,9 @@ void ERR_load_SSL_strings(void);
 #define SSL_R_PRE_MAC_LENGTH_TOO_LONG                   205
 #define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS                 206
 #define SSL_R_PROTOCOL_IS_SHUTDOWN                      207
+#define SSL_R_PSK_IDENTITY_NOT_FOUND                    223
+#define SSL_R_PSK_NO_CLIENT_CB                          224
+#define SSL_R_PSK_NO_SERVER_CB                          225
 #define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR                  208
 #define SSL_R_PUBLIC_KEY_IS_NOT_RSA                     209
 #define SSL_R_PUBLIC_KEY_NOT_RSA                        210
index 1ff31d4..a8193a5 100644 (file)
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -81,12 +107,16 @@ typedef struct ssl_session_asn1_st
 #ifndef OPENSSL_NO_TLSEXT
        ASN1_OCTET_STRING tlsext_hostname;
 #endif /* OPENSSL_NO_TLSEXT */
+#ifndef OPENSSL_NO_PSK
+       ASN1_OCTET_STRING psk_identity_hint;
+       ASN1_OCTET_STRING psk_identity;
+#endif /* OPENSSL_NO_PSK */
        } SSL_SESSION_ASN1;
 
 int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
        {
 #define LSIZE2 (sizeof(long)*2)
-       int v1=0,v2=0,v3=0,v4=0,v5=0,v6=0;
+       int v1=0,v2=0,v3=0,v4=0,v5=0,v6=0,v7=0,v8=0;
        unsigned char buf[4],ibuf1[LSIZE2],ibuf2[LSIZE2];
        unsigned char ibuf3[LSIZE2],ibuf4[LSIZE2],ibuf5[LSIZE2];
        long l;
@@ -156,7 +186,7 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
                a.krb5_princ.data=in->krb5_client_princ;
                }
 #endif /* OPENSSL_NO_KRB5 */
+
        if (in->time != 0L)
                {
                a.time.length=LSIZE2;
@@ -189,6 +219,20 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
                 a.tlsext_hostname.data=(unsigned char *)in->tlsext_hostname;
                 }                
 #endif /* OPENSSL_NO_TLSEXT */
+#ifndef OPENSSL_NO_PSK
+       if (in->psk_identity_hint)
+               {
+               a.psk_identity_hint.length=strlen(in->psk_identity_hint);
+               a.psk_identity_hint.type=V_ASN1_OCTET_STRING;
+               a.psk_identity_hint.data=in->psk_identity_hint;
+               }
+       if (in->psk_identity)
+               {
+               a.psk_identity.length=strlen(in->psk_identity);
+               a.psk_identity.type=V_ASN1_OCTET_STRING;
+               a.psk_identity.data=in->psk_identity;
+               }
+#endif /* OPENSSL_NO_PSK */
 
        M_ASN1_I2D_len(&(a.version),            i2d_ASN1_INTEGER);
        M_ASN1_I2D_len(&(a.ssl_version),        i2d_ASN1_INTEGER);
@@ -215,6 +259,13 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
        if (in->tlsext_hostname)
                M_ASN1_I2D_len_EXP_opt(&(a.tlsext_hostname), i2d_ASN1_OCTET_STRING,6,v6);
 #endif /* OPENSSL_NO_TLSEXT */
+#ifndef OPENSSL_NO_PSK
+       if (in->psk_identity_hint)
+               M_ASN1_I2D_len_EXP_opt(&(a.psk_identity_hint), i2d_ASN1_OCTET_STRING,6,v7);
+       if (in->psk_identity)
+               M_ASN1_I2D_len_EXP_opt(&(a.psk_identity), i2d_ASN1_OCTET_STRING,7,v8);
+#endif /* OPENSSL_NO_PSK */
+
        M_ASN1_I2D_seq_total();
 
        M_ASN1_I2D_put(&(a.version),            i2d_ASN1_INTEGER);
@@ -242,6 +293,12 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
        if (in->tlsext_hostname)
                M_ASN1_I2D_put_EXP_opt(&(a.tlsext_hostname), i2d_ASN1_OCTET_STRING,6,v6);
 #endif /* OPENSSL_NO_TLSEXT */
+#ifndef OPENSSL_NO_PSK
+       if (in->psk_identity_hint)
+               M_ASN1_I2D_put_EXP_opt(&(a.psk_identity_hint), i2d_ASN1_OCTET_STRING,6,v6);
+       if (in->psk_identity)
+               M_ASN1_I2D_put_EXP_opt(&(a.psk_identity), i2d_ASN1_OCTET_STRING,7,v7);
+#endif /* OPENSSL_NO_PSK */
        M_ASN1_I2D_finish();
        }
 
@@ -429,5 +486,33 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
 
 #endif /* OPENSSL_NO_TLSEXT */
 
+#ifndef OPENSSL_NO_PSK
+       os.length=0;
+       os.data=NULL;
+       M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,6);
+       if (os.data)
+               {
+               ret->psk_identity_hint = BUF_strndup(os.data, os.length);
+               OPENSSL_free(os.data);
+               os.data = NULL;
+               os.length = 0;
+               }
+       else
+               ret->psk_identity_hint=NULL;
+
+       os.length=0;
+       os.data=NULL;
+       M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,7);
+       if (os.data)
+               {
+               ret->psk_identity = BUF_strndup(os.data, os.length);
+               OPENSSL_free(os.data);
+               os.data = NULL;
+               os.length = 0;
+               }
+       else
+               ret->psk_identity=NULL;
+#endif /* OPENSSL_NO_KRB5 */
+
        M_ASN1_D2I_Finish(a,SSL_SESSION_free,SSL_F_D2I_SSL_SESSION);
        }
index cdd7a9a..5f9ce0d 100644 (file)
  * ECC cipher suite support in OpenSSL originally developed by 
  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
  */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
 #include <stdio.h>
 #include <openssl/objects.h>
 #include <openssl/comp.h>
@@ -120,6 +147,7 @@ static const SSL_CIPHER cipher_aliases[]={
        {0,SSL_TXT_kDHd,0,SSL_kDHd,  0,0,0,0,SSL_MKEY_MASK,0},
        {0,SSL_TXT_kEDH,0,SSL_kEDH,  0,0,0,0,SSL_MKEY_MASK,0},
        {0,SSL_TXT_kFZA,0,SSL_kFZA,  0,0,0,0,SSL_MKEY_MASK,0},
+        {0,SSL_TXT_kPSK,0,SSL_kPSK,  0,0,0,0,SSL_MKEY_MASK,0},
        {0,SSL_TXT_DH,  0,SSL_DH,    0,0,0,0,SSL_MKEY_MASK,0},
        {0,SSL_TXT_ECC, 0,(SSL_kECDH|SSL_kECDHE), 0,0,0,0,SSL_MKEY_MASK,0},
        {0,SSL_TXT_EDH, 0,SSL_EDH,   0,0,0,0,SSL_MKEY_MASK|SSL_AUTH_MASK,0},
@@ -127,6 +155,7 @@ static const SSL_CIPHER cipher_aliases[]={
        {0,SSL_TXT_aRSA,0,SSL_aRSA,  0,0,0,0,SSL_AUTH_MASK,0},
        {0,SSL_TXT_aDSS,0,SSL_aDSS,  0,0,0,0,SSL_AUTH_MASK,0},
        {0,SSL_TXT_aFZA,0,SSL_aFZA,  0,0,0,0,SSL_AUTH_MASK,0},
+        {0,SSL_TXT_aPSK,0,SSL_aPSK,  0,0,0,0,SSL_AUTH_MASK,0},
        {0,SSL_TXT_aNULL,0,SSL_aNULL,0,0,0,0,SSL_AUTH_MASK,0},
        {0,SSL_TXT_aDH, 0,SSL_aDH,   0,0,0,0,SSL_AUTH_MASK,0},
        {0,SSL_TXT_DSS, 0,SSL_DSS,   0,0,0,0,SSL_AUTH_MASK,0},
@@ -151,6 +180,7 @@ static const SSL_CIPHER cipher_aliases[]={
        {0,SSL_TXT_RSA, 0,SSL_RSA,   0,0,0,0,SSL_AUTH_MASK|SSL_MKEY_MASK,0},
        {0,SSL_TXT_ADH, 0,SSL_ADH,   0,0,0,0,SSL_AUTH_MASK|SSL_MKEY_MASK,0},
        {0,SSL_TXT_FZA, 0,SSL_FZA,   0,0,0,0,SSL_AUTH_MASK|SSL_MKEY_MASK|SSL_ENC_MASK,0},
+        {0,SSL_TXT_PSK, 0,SSL_PSK,   0,0,0,0,SSL_AUTH_MASK|SSL_MKEY_MASK,0},
 
        {0,SSL_TXT_SSLV2, 0,SSL_SSLV2, 0,0,0,0,SSL_SSL_MASK,0},
        {0,SSL_TXT_SSLV3, 0,SSL_SSLV3, 0,0,0,0,SSL_SSL_MASK,0},
@@ -370,6 +400,9 @@ static unsigned long ssl_cipher_get_disabled(void)
 #ifdef OPENSSL_NO_ECDH
        mask |= SSL_kECDH|SSL_kECDHE;
 #endif
+#ifdef OPENSSL_NO_PSK
+       mask |= SSL_kPSK;
+#endif
 #ifdef SSL_FORBID_ENULL
        mask |= SSL_eNULL;
 #endif
@@ -986,6 +1019,9 @@ char *SSL_CIPHER_description(SSL_CIPHER *cipher, char *buf, int len)
        case SSL_kECDHE:
                kx=is_export?"ECDH(<=163)":"ECDH";
                break;
+       case SSL_kPSK:
+               kx="PSK";
+               break;
        default:
                kx="unknown";
                }
@@ -1012,6 +1048,9 @@ char *SSL_CIPHER_description(SSL_CIPHER *cipher, char *buf, int len)
        case SSL_aECDSA:
                au="ECDSA";
                break;
+       case SSL_aPSK:
+               au="PSK";
+               break;
        default:
                au="unknown";
                break;
index dd66571..67a1d4f 100644 (file)
@@ -195,6 +195,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY),       "SSL_CTX_use_PrivateKey"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1),  "SSL_CTX_use_PrivateKey_ASN1"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE),  "SSL_CTX_use_PrivateKey_file"},
+{ERR_FUNC(SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT),        "SSL_CTX_use_psk_identity_hint"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY),    "SSL_CTX_use_RSAPrivateKey"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1),       "SSL_CTX_use_RSAPrivateKey_ASN1"},
 {ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE),       "SSL_CTX_use_RSAPrivateKey_file"},
@@ -233,6 +234,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {ERR_FUNC(SSL_F_SSL_USE_PRIVATEKEY),   "SSL_use_PrivateKey"},
 {ERR_FUNC(SSL_F_SSL_USE_PRIVATEKEY_ASN1),      "SSL_use_PrivateKey_ASN1"},
 {ERR_FUNC(SSL_F_SSL_USE_PRIVATEKEY_FILE),      "SSL_use_PrivateKey_file"},
+{ERR_FUNC(SSL_F_SSL_USE_PSK_IDENTITY_HINT),    "SSL_use_psk_identity_hint"},
 {ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY),        "SSL_use_RSAPrivateKey"},
 {ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1),   "SSL_use_RSAPrivateKey_ASN1"},
 {ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE),   "SSL_use_RSAPrivateKey_file"},
@@ -269,6 +271,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
 {ERR_REASON(SSL_R_BAD_MESSAGE_TYPE)      ,"bad message type"},
 {ERR_REASON(SSL_R_BAD_PACKET_LENGTH)     ,"bad packet length"},
 {ERR_REASON(SSL_R_BAD_PROTOCOL_VERSION_NUMBER),"bad protocol version number"},
+{ERR_REASON(SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH),"bad psk identity hint length"},
 {ERR_REASON(SSL_R_BAD_RESPONSE_ARGUMENT) ,"bad response argument"},
 {ERR_REASON(SSL_R_BAD_RSA_DECRYPT)       ,"bad rsa decrypt"},
 {ERR_REASON(SSL_R_BAD_RSA_ENCRYPT)       ,"bad rsa encrypt"},
@@ -388,6 +391,9 @@ static ERR_STRING_DATA SSL_str_reasons[]=
 {ERR_REASON(SSL_R_PRE_MAC_LENGTH_TOO_LONG),"pre mac length too long"},
 {ERR_REASON(SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS),"problems mapping cipher functions"},
 {ERR_REASON(SSL_R_PROTOCOL_IS_SHUTDOWN)  ,"protocol is shutdown"},
+{ERR_REASON(SSL_R_PSK_IDENTITY_NOT_FOUND),"psk identity not found"},
+{ERR_REASON(SSL_R_PSK_NO_CLIENT_CB)      ,"psk no client cb"},
+{ERR_REASON(SSL_R_PSK_NO_SERVER_CB)      ,"psk no server cb"},
 {ERR_REASON(SSL_R_PUBLIC_KEY_ENCRYPT_ERROR),"public key encrypt error"},
 {ERR_REASON(SSL_R_PUBLIC_KEY_IS_NOT_RSA) ,"public key is not rsa"},
 {ERR_REASON(SSL_R_PUBLIC_KEY_NOT_RSA)    ,"public key not rsa"},
index 7eec7f6..2c691da 100644 (file)
  * ECC cipher suite support in OpenSSL originally developed by 
  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
  */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
 
 #ifdef REF_CHECK
 #  include <assert.h>
@@ -326,6 +352,11 @@ SSL *SSL_new(SSL_CTX *ctx)
 
        CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data);
 
+#ifndef OPENSSL_NO_PSK
+       s->psk_client_callback=ctx->psk_client_callback;
+       s->psk_server_callback=ctx->psk_server_callback;
+#endif
+
        return(s);
 err:
        if (s != NULL)
@@ -1271,7 +1302,11 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
                 if ((c->algorithms & SSL_KRB5) && nokrb5)
                     continue;
 #endif /* OPENSSL_NO_KRB5 */                    
-
+#ifndef OPENSSL_NO_PSK
+               /* with PSK there must be client callback set */
+               if ((c->algorithms & SSL_PSK) && s->psk_client_callback == NULL)
+                       continue;
+#endif /* OPENSSL_NO_PSK */
                j = put_cb ? put_cb(c,p) : ssl_put_cipher_by_char(s,c,p);
                p+=j;
                }
@@ -1500,6 +1535,11 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
 #ifndef OPENSSL_NO_TLSEXT
        ret->tlsext_servername_callback = 0;
        ret->tlsext_servername_arg = NULL;
+#endif
+#ifndef OPENSSL_NO_PSK
+       ret->psk_identity_hint=NULL;
+       ret->psk_client_callback=NULL;
+       ret->psk_server_callback=NULL;
 #endif
        return(ret);
 err:
@@ -1571,6 +1611,11 @@ void SSL_CTX_free(SSL_CTX *a)
 #else
        a->comp_methods = NULL;
 #endif
+
+#ifndef OPENSSL_NO_PSK
+       if (a->psk_identity_hint)
+               OPENSSL_free(a->psk_identity_hint);
+#endif
        OPENSSL_free(a);
        }
 
@@ -1763,6 +1808,12 @@ void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher)
                emask|=SSL_kECDHE;
                }
 #endif
+
+#ifndef OPENSSL_NO_PSK
+       mask  |= SSL_kPSK | SSL_aPSK;
+       emask |= SSL_kPSK | SSL_aPSK;
+#endif
+
        c->mask=mask;
        c->export_mask=emask;
        c->valid=1;
@@ -2634,6 +2685,67 @@ void SSL_set_tmp_ecdh_callback(SSL *ssl,EC_KEY *(*ecdh)(SSL *ssl,int is_export,
        }
 #endif
 
+#ifndef OPENSSL_NO_PSK
+int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint)
+       {
+       if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN)
+               {
+               SSLerr(SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG);
+               return 0;
+               }
+       if (ctx->psk_identity_hint != NULL)
+               OPENSSL_free(ctx->psk_identity_hint);
+       if (identity_hint != NULL)
+               {
+               ctx->psk_identity_hint = BUF_strdup(identity_hint);
+               if (ctx->psk_identity_hint == NULL)
+                       return 0;
+               }
+       else
+               ctx->psk_identity_hint = NULL;
+       return 1;
+       }
+
+int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint)
+       {
+       if (s == NULL)
+               return 0;
+
+       if (s->session == NULL)
+               return 1; /* session not created yet, ignored */
+
+       if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN)
+               {
+               SSLerr(SSL_F_SSL_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG);
+               return 0;
+               }
+       if (s->session->psk_identity_hint != NULL)
+               OPENSSL_free(s->session->psk_identity_hint);
+       if (identity_hint != NULL)
+               {
+               s->session->psk_identity_hint = BUF_strdup(identity_hint);
+               if (s->session->psk_identity_hint == NULL)
+                       return 0;
+               }
+       else
+               s->session->psk_identity_hint = NULL;
+       return 1;
+       }
+
+const char *SSL_get_psk_identity_hint(const SSL *s)
+       {
+       if (s == NULL || s->session == NULL)
+               return NULL;
+       return(s->session->psk_identity_hint);
+       }
+
+const char *SSL_get_psk_identity(const SSL *s)
+       {
+       if (s == NULL || s->session == NULL)
+               return NULL;
+       return(s->session->psk_identity);
+       }
+#endif
 
 void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg))
        {
index f8ec859..2beffcb 100644 (file)
@@ -1,3 +1,4 @@
+
 /* ssl/ssl_locl.h */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  * ECC cipher suite support in OpenSSL originally developed by 
  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
  */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
 
 #ifndef HEADER_SSL_LOCL_H
 #define HEADER_SSL_LOCL_H
  * that the different entities within are mutually exclusive:
  * ONLY ONE BIT PER MASK CAN BE SET AT A TIME.
  */
-#define SSL_MKEY_MASK          0x000000FFL
+#define SSL_MKEY_MASK          0x080000FFL
 #define SSL_kRSA               0x00000001L /* RSA key exchange */
 #define SSL_kDHr               0x00000002L /* DH cert RSA CA cert */
 #define SSL_kDHd               0x00000004L /* DH cert DSA CA cert */
 #define SSL_kECDH               0x00000040L /* ECDH w/ long-term keys */
 #define SSL_kECDHE              0x00000080L /* ephemeral ECDH */
 #define SSL_EDH                        (SSL_kEDH|(SSL_AUTH_MASK^SSL_aNULL))
+#define SSL_kPSK                0x08000000L /* PSK */
 
-#define SSL_AUTH_MASK          0x00007F00L
+#define SSL_AUTH_MASK          0x10007f00L
 #define SSL_aRSA               0x00000100L /* Authenticate with RSA */
 #define SSL_aDSS               0x00000200L /* Authenticate with DSS */
 #define SSL_DSS                SSL_aDSS
 #define SSL_aDH                0x00001000L /* no Authenticate, ADH */
 #define SSL_aKRB5               0x00002000L /* Authenticate with KRB5 */
 #define SSL_aECDSA              0x00004000L /* Authenticate with ECDSA */
+#define SSL_aPSK                0x10000000L /* PSK */
 
 #define SSL_NULL               (SSL_eNULL)
 #define SSL_ADH                        (SSL_kEDH|SSL_aNULL)
 #define SSL_ECDH               (SSL_kECDH|SSL_kECDHE)
 #define SSL_FZA                        (SSL_aFZA|SSL_kFZA|SSL_eFZA)
 #define SSL_KRB5                (SSL_kKRB5|SSL_aKRB5)
+#define SSL_PSK                 (SSL_kPSK|SSL_aPSK)
 
 #define SSL_ENC_MASK           0x043F8000L
 #define SSL_DES                        0x00008000L
 #define SSL_SSLV3              0x02000000L
 #define SSL_TLSV1              SSL_SSLV3       /* for now */
 
-/* we have used 07ffffff - 5 bits left to go. */
+/* we have used 1fffffff - 3 bits left to go. */
 
 /*
  * Export and cipher strength information. For each cipher we have to decide
index ffacf94..a4a3a4b 100644 (file)
  * Hudson (tjh@cryptsoft.com).
  *
  */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
 
 #include <stdio.h>
 #include <openssl/lhash.h>
@@ -179,6 +205,10 @@ SSL_SESSION *SSL_SESSION_new(void)
        ss->tlsext_hostname = NULL; 
 #endif
        CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
+#ifndef OPENSSL_NO_PSK
+       ss->psk_identity_hint=NULL;
+       ss->psk_identity=NULL;
+#endif
        return(ss);
        }
 
@@ -614,6 +644,12 @@ void SSL_SESSION_free(SSL_SESSION *ss)
        if (ss->ciphers != NULL) sk_SSL_CIPHER_free(ss->ciphers);
 #ifndef OPENSSL_NO_TLSEXT
        if (ss->tlsext_hostname != NULL) OPENSSL_free(ss->tlsext_hostname);
+#endif
+#ifndef OPENSSL_NO_PSK
+       if (ss->psk_identity_hint != NULL)
+               OPENSSL_free(ss->psk_identity_hint);
+       if (ss->psk_identity != NULL)
+               OPENSSL_free(ss->psk_identity);
 #endif
        OPENSSL_cleanse(ss,sizeof(*ss));
        OPENSSL_free(ss);
index ccc010b..c20a475 100644 (file)
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
 
 #include <stdio.h>
 #include "ssl_locl.h"
@@ -404,6 +430,7 @@ const char *SSL_alert_desc_string(int value)
        case TLS1_AD_UNRECOGNIZED_NAME:         str="UN"; break;
        case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE: str="BR"; break;
        case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE: str="BH"; break;
+       case TLS1_AD_UNKNOWN_PSK_IDENTITY:      str="UP"; break;
        default:                                str="UK"; break;
                }
        return(str);
@@ -502,6 +529,9 @@ const char *SSL_alert_desc_string_long(int value)
        case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE:
                str="bad certificate hash value";
                break;
+       case TLS1_AD_UNKNOWN_PSK_IDENTITY:
+               str="unknown PSK identity";
+               break;
        default: str="unknown"; break;
                }
        return(str);
index 4eb0867..f51e48b 100644 (file)
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
 
 #include <stdio.h>
 #include <openssl/buffer.h>
@@ -151,6 +177,12 @@ int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x)
                        if (BIO_printf(bp,"%02X",x->krb5_client_princ[i]) <= 0) goto err;
                        }
 #endif /* OPENSSL_NO_KRB5 */
+#ifndef OPENSSL_NO_PSK
+       if (BIO_puts(bp,"\n    PSK identity: ") <= 0) goto err;
+       if (BIO_printf(bp, "%s", x->psk_identity ? x->psk_identity : "None") <= 0) goto err;
+       if (BIO_puts(bp,"\n    PSK identity hint: ") <= 0) goto err;
+       if (BIO_printf(bp, "%s", x->psk_identity_hint ? x->psk_identity_hint : "None") <= 0) goto err;
+#endif
 #ifndef OPENSSL_NO_COMP
        if (x->compress_meth != 0)
                {
index dfe18b0..0d61116 100644 (file)
  * ECC cipher suite support in OpenSSL originally developed by 
  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
  */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
 
 #define _BSD_SOURCE 1          /* Or gethostname won't be declared properly
                                   on Linux and GNU platforms. */
@@ -207,6 +233,16 @@ static DH *get_dh1024(void);
 static DH *get_dh1024dsa(void);
 #endif
 
+
+static char *psk_key=NULL; /* by default PSK is not used */
+#ifndef OPENSSL_NO_PSK
+static unsigned int psk_client_callback(SSL *ssl, const char *hint, char *identity,
+       unsigned int max_identity_len, unsigned char *psk,
+       unsigned int max_psk_len);
+static unsigned int psk_server_callback(SSL *ssl, const char *identity, unsigned char *psk,
+       unsigned int max_psk_len);
+#endif
+
 static BIO *bio_err=NULL;
 static BIO *bio_stdout=NULL;
 
@@ -247,6 +283,9 @@ static void sv_usage(void)
 #ifndef OPENSSL_NO_ECDH
        fprintf(stderr," -no_ecdhe     - disable ECDHE\n");
 #endif
+#ifndef OPENSSL_NO_PSK
+       fprintf(stderr," -psk arg      - PSK in hex (without 0x)\n");
+#endif
 #ifndef OPENSSL_NO_SSL2
        fprintf(stderr," -ssl2         - use SSLv2\n");
 #endif
@@ -417,6 +456,7 @@ int main(int argc, char *argv[])
 #endif
        int no_dhe = 0;
        int no_ecdhe = 0;
+       int no_psk = 0;
        int print_time = 0;
        clock_t s_time = 0, c_time = 0;
        int comp = 0;
@@ -496,6 +536,20 @@ int main(int argc, char *argv[])
                        no_dhe=1;
                else if (strcmp(*argv,"-no_ecdhe") == 0)
                        no_ecdhe=1;
+               else if (strcmp(*argv,"-psk") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       psk_key=*(++argv);
+#ifndef OPENSSL_NO_PSK
+                       if (strspn(psk_key, "abcdefABCDEF1234567890") != strlen(psk_key))
+                               {
+                               BIO_printf(bio_err,"Not a hex number '%s'\n",*argv);
+                               goto bad;
+                               }
+#else
+                       no_psk=1;
+#endif
+                       }
                else if (strcmp(*argv,"-ssl2") == 0)
                        ssl2=1;
                else if (strcmp(*argv,"-tls1") == 0)
@@ -833,6 +887,31 @@ bad:
                SSL_CTX_set_session_id_context(s_ctx, (void *)&session_id_context, sizeof session_id_context);
        }
 
+       /* Use PSK only if PSK key is given */
+       if (psk_key != NULL)
+               {
+               /* no_psk is used to avoid putting psk command to openssl tool */
+               if (no_psk)
+                       {
+                       /* if PSK is not compiled in and psk key is
+                        * given, do nothing and exit successfully */
+                       ret=0;
+                       goto end;
+                       }
+#ifndef OPENSSL_NO_PSK
+               SSL_CTX_set_psk_client_callback(c_ctx, psk_client_callback);
+               SSL_CTX_set_psk_server_callback(s_ctx, psk_server_callback);
+               if (debug)
+                       BIO_printf(bio_err,"setting PSK identity hint to s_ctx\n");
+               if (!SSL_CTX_use_psk_identity_hint(s_ctx, "ctx server identity_hint"))
+                       {
+                       BIO_printf(bio_err,"error setting PSK identity hint to s_ctx\n");
+                       ERR_print_errors(bio_err);
+                       goto end;
+                       }
+#endif
+               }
+
        c_ssl=SSL_new(c_ctx);
        s_ssl=SSL_new(s_ctx);
 
@@ -2236,6 +2315,69 @@ static DH *get_dh1024dsa()
        }
 #endif
 
+#ifndef OPENSSL_NO_PSK
+/* convert the PSK key (psk_key) in ascii to binary (psk) */
+static int psk_key2bn(const char *pskkey, unsigned char *psk,
+       unsigned int max_psk_len)
+       {
+       int ret;
+       BIGNUM *bn = NULL;
+
+       ret = BN_hex2bn(&bn, pskkey);
+       if (!ret)
+               {
+               BIO_printf(bio_err,"Could not convert PSK key '%s' to BIGNUM\n", pskkey); 
+               if (bn)
+                       BN_free(bn);
+               return 0;
+               }
+       if (BN_num_bytes(bn) > (int)max_psk_len)
+               {
+               BIO_printf(bio_err,"psk buffer of callback is too small (%d) for key (%d)\n",
+                       max_psk_len, BN_num_bytes(bn));
+               BN_free(bn);
+               return 0;
+               }
+       ret = BN_bn2bin(bn, psk);
+       BN_free(bn);
+       return ret;
+       }
+
+static unsigned int psk_client_callback(SSL *ssl, const char *hint, char *identity,
+       unsigned int max_identity_len, unsigned char *psk,
+       unsigned int max_psk_len)
+       {
+       int ret;
+       unsigned int psk_len = 0;
+
+       ret = snprintf(identity, max_identity_len, "Client_identity");
+       if (ret < 0)
+               goto out_err;
+       if (debug)
+               fprintf(stderr, "client: created identity '%s' len=%d\n", identity, ret);
+       ret = psk_key2bn(psk_key, psk, max_psk_len);
+       if (ret < 0)
+               goto out_err;
+       psk_len = ret;
+out_err:
+       return psk_len;
+       }
+
+static unsigned int psk_server_callback(SSL *ssl, const char *identity,
+       unsigned char *psk, unsigned int max_psk_len)
+       {
+       unsigned int psk_len=0;
+
+       if (strcmp(identity, "Client_identity") != 0)
+               {
+               BIO_printf(bio_err, "server: PSK error: client identity not found\n");
+               return 0;
+               }
+       psk_len=psk_key2bn(psk_key, psk, max_psk_len);
+       return psk_len;
+       }
+#endif
+
 static int do_test_cipherlist(void)
        {
        int i = 0;
index 6b4884a..cf38aa0 100644 (file)
  * Hudson (tjh@cryptsoft.com).
  *
  */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
 
 #include <stdio.h>
 #include "ssl_locl.h"
@@ -828,6 +854,7 @@ int tls1_alert_code(int code)
        case SSL_AD_UNRECOGNIZED_NAME:  return(TLS1_AD_UNRECOGNIZED_NAME);
        case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: return(TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE);
        case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(TLS1_AD_BAD_CERTIFICATE_HASH_VALUE);
+       case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY);
 #if 0 /* not appropriate for TLS, not used for DTLS */
        case DTLS1_AD_MISSING_HANDSHAKE_MESSAGE: return 
                                          (DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
index 0a9c1ea..4a33278 100644 (file)
  * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
  *
  */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
 
 #ifndef HEADER_TLS1_H 
 #define HEADER_TLS1_H 
@@ -155,6 +181,7 @@ extern "C" {
 #define TLS1_AD_UNRECOGNIZED_NAME      112
 #define TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE 113
 #define TLS1_AD_BAD_CERTIFICATE_HASH_VALUE 114
+#define TLS1_AD_UNKNOWN_PSK_IDENTITY   115     /* fatal */
 
 /* ExtensionType values from RFC 3546 */
 #define TLSEXT_TYPE_server_name                        0
@@ -191,6 +218,11 @@ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG,0, (void *)arg)
 
 #endif
 
+/* PSK ciphersuites from 4279 */
+#define TLS1_CK_PSK_WITH_RC4_128_SHA                    0x0300008A
+#define TLS1_CK_PSK_WITH_3DES_EDE_CBC_SHA               0x0300008B
+#define TLS1_CK_PSK_WITH_AES_128_CBC_SHA                0x0300008C
+#define TLS1_CK_PSK_WITH_AES_256_CBC_SHA                0x0300008D
 
 /* Additional TLS ciphersuites from expired Internet Draft
  * draft-ietf-tls-56-bit-ciphersuites-01.txt
@@ -313,6 +345,12 @@ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG,0, (void *)arg)
 #define TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA         "AECDH-AES128-SHA"
 #define TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA         "AECDH-AES256-SHA"
 
+/* PSK ciphersuites from RFC 4279 */
+#define TLS1_TXT_PSK_WITH_RC4_128_SHA                  "PSK-RC4-SHA"
+#define TLS1_TXT_PSK_WITH_3DES_EDE_CBC_SHA             "PSK-3DES-EDE-CBC-SHA"
+#define TLS1_TXT_PSK_WITH_AES_128_CBC_SHA              "PSK-AES128-CBC-SHA"
+#define TLS1_TXT_PSK_WITH_AES_256_CBC_SHA              "PSK-AES256-CBC-SHA"
+
 #define TLS_CT_RSA_SIGN                        1
 #define TLS_CT_DSS_SIGN                        2
 #define TLS_CT_RSA_FIXED_DH            3
index 8ac90ae..f9d7c5d 100644 (file)
@@ -142,4 +142,10 @@ else
   fi
 fi
 
+echo test tls1 with PSK
+$ssltest -tls1 -cipher PSK -psk abc123 $extra || exit 1
+
+echo test tls1 with PSK via BIO pair
+$ssltest -bio_pair -tls1 -cipher PSK -psk abc123 $extra || exit 1
+
 exit 0