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
This commit is contained in:
180
ssl/s3_clnt.c
180
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
|
||||
|
Reference in New Issue
Block a user