diff options
author | Nils Larsch <nils@openssl.org> | 2006-03-10 23:06:27 +0000 |
---|---|---|
committer | Nils Larsch <nils@openssl.org> | 2006-03-10 23:06:27 +0000 |
commit | ddac197404f585b8da58df794fc3beb9d08e8cd2 (patch) | |
tree | be75e03f93b8ad8c2cf5e76f58d3b11bb73854ed /ssl | |
parent | 0e8e6f19b2919e14c5bb7b645a359b96ad9fc13d (diff) |
add initial support for RFC 4279 PSK SSL ciphersuites
PR: 1191
Submitted by: Mika Kousa and Pasi Eronen of Nokia Corporation
Reviewed by: Nils Larsch
Diffstat (limited to 'ssl')
-rw-r--r-- | ssl/s3_clnt.c | 180 | ||||
-rw-r--r-- | ssl/s3_enc.c | 27 | ||||
-rw-r--r-- | ssl/s3_lib.c | 89 | ||||
-rw-r--r-- | ssl/s3_srvr.c | 158 | ||||
-rw-r--r-- | ssl/ssl.h | 77 | ||||
-rw-r--r-- | ssl/ssl_asn1.c | 89 | ||||
-rw-r--r-- | ssl/ssl_ciph.c | 39 | ||||
-rw-r--r-- | ssl/ssl_err.c | 6 | ||||
-rw-r--r-- | ssl/ssl_lib.c | 114 | ||||
-rw-r--r-- | ssl/ssl_locl.h | 36 | ||||
-rw-r--r-- | ssl/ssl_sess.c | 36 | ||||
-rw-r--r-- | ssl/ssl_stat.c | 30 | ||||
-rw-r--r-- | ssl/ssl_txt.c | 32 | ||||
-rw-r--r-- | ssl/ssltest.c | 142 | ||||
-rw-r--r-- | ssl/t1_enc.c | 27 | ||||
-rw-r--r-- | ssl/tls1.h | 38 |
16 files changed, 1101 insertions, 19 deletions
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index 995c8298b8..237dfb61d9 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -121,6 +121,32 @@ * 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 diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c index 4baba2efb5..b4c6f0f19b 100644 --- a/ssl/s3_enc.c +++ b/ssl/s3_enc.c @@ -108,6 +108,32 @@ * 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); } } diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 6ccd8b1324..aecf6d62a8 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -121,6 +121,32 @@ * 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; diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 44b9c9cdac..8859540fa8 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -121,6 +121,32 @@ * 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) { @@ -2178,6 +2235,101 @@ int ssl3_get_client_key_exchange(SSL *s) } 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; SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, @@ -166,6 +166,32 @@ * 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 */ @@ -764,6 +797,14 @@ struct ssl_ctx_st 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 }; #define SSL_SESS_CACHE_OFF 0x0000 @@ -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 diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c index 1ff31d4402..a8193a58da 100644 --- a/ssl/ssl_asn1.c +++ b/ssl/ssl_asn1.c @@ -55,6 +55,32 @@ * 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 |