From d4a56ec6bf9bb0e7c7f3179aa7fa6ea0b99aa9ed Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Tue, 16 Apr 2013 18:05:29 +0200 Subject: [PATCH] Added pre-shared key handling for the client side of SSL / TLS Client side handling of the pure PSK ciphersuites is now in the base code. --- include/polarssl/config.h | 19 +++++ include/polarssl/ssl.h | 28 ++++++- include/polarssl/ssl_ciphersuites.h | 20 +++++ library/ssl_ciphersuites.c | 112 +++++++++++++++++++++++++ library/ssl_cli.c | 122 ++++++++++++++++++++++++---- library/ssl_tls.c | 27 ++++++ programs/ssl/ssl_client2.c | 79 ++++++++++++++++-- 7 files changed, 381 insertions(+), 26 deletions(-) diff --git a/include/polarssl/config.h b/include/polarssl/config.h index 850053cad..29d4f0d9e 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -161,6 +161,21 @@ #define POLARSSL_ENABLE_WEAK_CIPHERSUITES */ +/** + * \def POLARSSL_KEY_EXCHANGE_PSK_ENABLED + * + * Enable the PSK based ciphersuite modes in SSL / TLS + * In combination with POLARSSL_RSA_C it also enables RSA_PSK ciphersuites + * and in combination with POLARSSL_DHM_C it enables the DHE_PSK ciphersuites + * + * This enables the following ciphersuites: + * TLS_PSK_WITH_RC4_128_SHA + * TLS_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_PSK_WITH_AES_128_CBC_SHA + * TLS_PSK_WITH_AES_256_CBC_SHA + */ +#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED + /** * \def POLARSSL_ERROR_STRERROR_DUMMY * @@ -348,6 +363,8 @@ * TLS_RSA_WITH_AES_256_GCM_SHA384 * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * TLS_PSK_WITH_AES_128_CBC_SHA + * TLS_PSK_WITH_AES_256_CBC_SHA * * PEM uses AES for decrypting encrypted keys. */ @@ -366,6 +383,7 @@ * TLS_RSA_WITH_RC4_128_MD5 * TLS_RSA_WITH_RC4_128_SHA * TLS_ECDHE_RSA_WITH_RC4_128_SHA + * TLS_PSK_WITH_RC4_128_SHA */ #define POLARSSL_ARC4_C @@ -511,6 +529,7 @@ * TLS_RSA_WITH_3DES_EDE_CBC_SHA * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA * TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_PSK_WITH_3DES_EDE_CBC_SHA * * PEM uses DES/3DES for decrypting encrypted keys. */ diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 43e80699c..5c86bb3ac 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -201,6 +201,7 @@ #define SSL_ALERT_MSG_NO_RENEGOTIATION 100 /* 0x64 */ #define SSL_ALERT_MSG_UNSUPPORTED_EXT 110 /* 0x6E */ #define SSL_ALERT_MSG_UNRECOGNIZED_NAME 112 /* 0x70 */ +#define SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY 115 /* 0x73 */ #define SSL_HS_HELLO_REQUEST 0 #define SSL_HS_CLIENT_HELLO 1 @@ -226,7 +227,6 @@ #define TLS_EXT_RENEGOTIATION_INFO 0xFF01 - /* * Generic function pointers for allowing external RSA private key * implementations. @@ -441,6 +441,7 @@ struct _ssl_context size_t in_hslen; /*!< current handshake message length */ int nb_zero; /*!< # of 0-length encrypted messages */ + int record_read; /*!< record is already present */ /* * Record layer (outgoing data) @@ -483,6 +484,16 @@ struct _ssl_context mpi dhm_G; /*!< generator for DHM */ #endif +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) + /* + * PSK values + */ + const unsigned char *psk; + size_t psk_len; + const unsigned char *psk_identity; + size_t psk_identity_len; +#endif + /* * TLS extensions */ @@ -780,6 +791,21 @@ void ssl_set_own_cert_alt( ssl_context *ssl, x509_cert *own_cert, rsa_sign_func rsa_sign, rsa_key_len_func rsa_key_len ); +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) +/** + * \brief Set the Pre Shared Key (PSK) and the identity name connected + * to it. The PSK is used in all PSK-based ciphersuites. + * + * \param ssl SSL context + * \param psk pointer to the pre-shared key + * \param psk_len pre-shared key length + * \param psk_identity pointer to the pre-shared key identity + * \param psk_identity_len identity key length + */ +void ssl_set_psk( ssl_context *ssl, const unsigned char *psk, size_t psk_len, + const unsigned char *psk_identity, size_t psk_identity_len ); +#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */ + #if defined(POLARSSL_DHM_C) /** * \brief Set the Diffie-Hellman public P and G values, diff --git a/include/polarssl/ssl_ciphersuites.h b/include/polarssl/ssl_ciphersuites.h index 7ec31ae0b..665c2195f 100644 --- a/include/polarssl/ssl_ciphersuites.h +++ b/include/polarssl/ssl_ciphersuites.h @@ -53,6 +53,7 @@ extern "C" { #define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x33 #define TLS_RSA_WITH_AES_256_CBC_SHA 0x35 #define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x39 + #define TLS_RSA_WITH_AES_128_CBC_SHA256 0x3C /**< TLS 1.2 */ #define TLS_RSA_WITH_AES_256_CBC_SHA256 0x3D /**< TLS 1.2 */ #define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x67 /**< TLS 1.2 */ @@ -62,6 +63,22 @@ extern "C" { #define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x45 #define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x84 #define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x88 + +#define TLS_PSK_WITH_RC4_128_SHA 0x8A +#define TLS_PSK_WITH_3DES_EDE_CBC_SHA 0x8B +#define TLS_PSK_WITH_AES_128_CBC_SHA 0x8C +#define TLS_PSK_WITH_AES_256_CBC_SHA 0x8D + +#define TLS_DHE_PSK_WITH_RC4_128_SHA 0x8E +#define TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA 0x8F +#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x90 +#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x91 + +#define TLS_RSA_PSK_WITH_RC4_128_SHA 0x92 +#define TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA 0x93 +#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA 0x94 +#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA 0x95 + #define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBA /**< TLS 1.2 */ #define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE /**< TLS 1.2 */ #define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC0 /**< TLS 1.2 */ @@ -91,6 +108,9 @@ typedef enum { POLARSSL_KEY_EXCHANGE_RSA, POLARSSL_KEY_EXCHANGE_DHE_RSA, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + POLARSSL_KEY_EXCHANGE_PSK, + POLARSSL_KEY_EXCHANGE_DHE_PSK, + POLARSSL_KEY_EXCHANGE_RSA_PSK, } key_exchange_type_t; typedef struct _ssl_ciphersuite_t ssl_ciphersuite_t; diff --git a/library/ssl_ciphersuites.c b/library/ssl_ciphersuites.c index 6e1a4f840..99629658d 100644 --- a/library/ssl_ciphersuites.c +++ b/library/ssl_ciphersuites.c @@ -70,6 +70,12 @@ static const int ciphersuite_preference[] = TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, + /* The PSK ephemeral suites */ + TLS_DHE_PSK_WITH_AES_256_CBC_SHA, + TLS_DHE_PSK_WITH_AES_128_CBC_SHA, + TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, + TLS_DHE_PSK_WITH_RC4_128_SHA, + /* All AES-256 suites */ TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_256_GCM_SHA384, @@ -93,6 +99,18 @@ static const int ciphersuite_preference[] = TLS_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_RC4_128_MD5, + /* The RSA PSK suites */ + TLS_RSA_PSK_WITH_AES_256_CBC_SHA, + TLS_RSA_PSK_WITH_AES_128_CBC_SHA, + TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, + TLS_RSA_PSK_WITH_RC4_128_SHA, + + /* The PSK suites */ + TLS_PSK_WITH_AES_256_CBC_SHA, + TLS_PSK_WITH_AES_128_CBC_SHA, + TLS_PSK_WITH_3DES_EDE_CBC_SHA, + TLS_PSK_WITH_RC4_128_SHA, + /* Weak or NULL suites */ TLS_DHE_RSA_WITH_DES_CBC_SHA, TLS_RSA_WITH_DES_CBC_SHA, @@ -370,6 +388,100 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] = 0 }, #endif /* POLARSSL_DES_C */ +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) +#if defined(POLARSSL_AES_C) + { TLS_PSK_WITH_AES_128_CBC_SHA, "TLS-PSK-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_PSK_WITH_AES_256_CBC_SHA, "TLS-PSK-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_DES_C) + { TLS_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-PSK-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ARC4_C) + { TLS_PSK_WITH_RC4_128_SHA, "TLS-PSK-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_ARC4_C */ + +#if defined(POLARSSL_DHM_C) +#if defined(POLARSSL_AES_C) + { TLS_DHE_PSK_WITH_AES_128_CBC_SHA, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_DHE_PSK_WITH_AES_256_CBC_SHA, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_DES_C) + { TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ARC4_C) + { TLS_DHE_PSK_WITH_RC4_128_SHA, "TLS-DHE-PSK-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_ARC4_C */ +#endif /* POLARSSL_DHM_C */ + +#if defined(POLARSSL_AES_C) + { TLS_RSA_PSK_WITH_AES_128_CBC_SHA, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_RSA_PSK_WITH_AES_256_CBC_SHA, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_DES_C) + { TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-PSK-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ARC4_C) + { TLS_RSA_PSK_WITH_RC4_128_SHA, "TLS-RSA-PSK-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_ARC4_C */ +#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */ + #if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) #if defined(POLARSSL_CIPHER_NULL_CIPHER) { TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5", diff --git a/library/ssl_cli.c b/library/ssl_cli.c index c5ca73336..86d720b40 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -727,7 +727,8 @@ static int ssl_parse_server_hello( ssl_context *ssl ) return( 0 ); } -#if !defined(POLARSSL_DHM_C) && !defined(POLARSSL_ECDH_C) +#if !defined(POLARSSL_DHM_C) && !defined(POLARSSL_ECDH_C) && \ + !defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) static int ssl_parse_server_key_exchange( ssl_context *ssl ) { SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) ); @@ -809,6 +810,36 @@ static int ssl_parse_server_ecdh_params( ssl_context *ssl, return( ret ); } +static int ssl_parse_server_psk_hint( ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) + size_t len; + + /* + * PSK parameters: + * + * opaque psk_identity_hint<0..2^16-1>; + */ + len = (*p)[1] << 8 | (*p)[0]; + + if( (*p) + len > end ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message (psk_identity_hint length)" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + // TODO: Retrieve PSK identity hint and callback to app + // + *p += len; +#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */ + + return( ret ); +} + static int ssl_parse_signature_algorithm( ssl_context *ssl, unsigned char **p, unsigned char *end, @@ -822,7 +853,6 @@ static int ssl_parse_signature_algorithm( ssl_context *ssl, if( (*p)[1] != SSL_SIG_RSA ) { SSL_DEBUG_MSG( 2, ( "server used unsupported SignatureAlgorithm %d", (*p)[1] ) ); - SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } @@ -880,7 +910,8 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) ); if( ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_DHE_RSA && - ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_ECDHE_RSA ) + ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_ECDHE_RSA && + ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_PSK ) { SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); ssl->state++; @@ -901,8 +932,8 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) if( ssl->in_msg[0] != SSL_HS_SERVER_KEY_EXCHANGE ) { - SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + ssl->record_read = 1; + goto exit; } SSL_DEBUG_BUF( 3, "server key exchange", ssl->in_msg + 4, ssl->in_hslen - 4 ); @@ -913,15 +944,22 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA ) { if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "failed to parsebad server key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ) + { + if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 ) { SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } } - - if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ) + else if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ) { - if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 ) + if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 ) { SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); @@ -1028,6 +1066,7 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) } } +exit: ssl->state++; SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) ); @@ -1057,16 +1096,21 @@ static int ssl_parse_certificate_request( ssl_context *ssl ) * n+4 .. ... Distinguished Name #1 * ... .. ... length of DN 2, etc. */ - if( ( ret = ssl_read_record( ssl ) ) != 0 ) + if( ssl->record_read == 0 ) { - SSL_DEBUG_RET( 1, "ssl_read_record", ret ); - return( ret ); - } + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } - if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) - { - SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); - return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + ssl->record_read = 1; } ssl->client_auth = 0; @@ -1081,6 +1125,8 @@ static int ssl_parse_certificate_request( ssl_context *ssl ) if( ssl->client_auth == 0 ) goto exit; + ssl->record_read = 0; + // TODO: handshake_failure alert for an anonymous server to request // client authentication @@ -1154,7 +1200,7 @@ static int ssl_parse_server_hello_done( ssl_context *ssl ) SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) ); - if( ssl->client_auth != 0 ) + if( ssl->record_read == 0 ) { if( ( ret = ssl_read_record( ssl ) ) != 0 ) { @@ -1168,6 +1214,7 @@ static int ssl_parse_server_hello_done( ssl_context *ssl ) return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); } } + ssl->record_read = 0; if( ssl->in_hslen != 4 || ssl->in_msg[0] != SSL_HS_SERVER_HELLO_DONE ) @@ -1265,6 +1312,43 @@ static int ssl_write_client_key_exchange( ssl_context *ssl ) } else #endif /* POLARSSL_ECDH_C */ +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ) + { + unsigned char *p = ssl->handshake->premaster; + + /* + * PSK key exchange + * + * opaque psk_identity<0..2^16-1>; + */ + if( ssl->hostname == NULL ) + return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED ); + + if( sizeof(ssl->handshake->premaster) < 4 + 2 * ssl->psk_len ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + n = ssl->psk_identity_len; + + ssl->out_msg[4] = (unsigned char)( n >> 8 ); + ssl->out_msg[5] = (unsigned char)( n ); + i = 6; + + memcpy( ssl->out_msg + i, ssl->psk_identity, ssl->psk_identity_len ); + + *(p++) = (unsigned char)( ssl->psk_len >> 8 ); + *(p++) = (unsigned char)( ssl->psk_len ); + p += ssl->psk_len; + + *(p++) = (unsigned char)( ssl->psk_len >> 8 ); + *(p++) = (unsigned char)( ssl->psk_len ); + memcpy( p, ssl->psk, ssl->psk_len ); + p += ssl->psk_len; + + ssl->handshake->pmslen = 4 + 2 * ssl->psk_len; + } + else +#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */ { /* * RSA key exchange -- send rsa_public(pkcs1 v1.5(premaster)) @@ -1331,10 +1415,12 @@ static int ssl_write_certificate_verify( ssl_context *ssl ) unsigned char hash[48]; md_type_t md_alg = POLARSSL_MD_NONE; unsigned int hashlen = 0; + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); - if( ssl->client_auth == 0 || ssl->own_cert == NULL ) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ssl->client_auth == 0 || ssl->own_cert == NULL ) { SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); ssl->state++; diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 85fc7fee1..6b478383f 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1848,9 +1848,17 @@ int ssl_write_certificate( ssl_context *ssl ) int ret; size_t i, n; const x509_cert *crt; + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + if( ssl->endpoint == SSL_IS_CLIENT ) { if( ssl->client_auth == 0 ) @@ -1944,9 +1952,17 @@ int ssl_parse_certificate( ssl_context *ssl ) { int ret; size_t i, n; + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + if( ssl->endpoint == SSL_IS_SERVER && ssl->authmode == SSL_VERIFY_NONE ) { @@ -2753,6 +2769,7 @@ int ssl_session_reset( ssl_context *ssl ) ssl->in_hslen = 0; ssl->nb_zero = 0; + ssl->record_read = 0; ssl->out_msg = ssl->out_ctr + 13; ssl->out_msgtype = 0; @@ -2908,6 +2925,16 @@ void ssl_set_own_cert_alt( ssl_context *ssl, x509_cert *own_cert, ssl->rsa_key_len = rsa_key_len; } +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) +void ssl_set_psk( ssl_context *ssl, const unsigned char *psk, size_t psk_len, + const unsigned char *psk_identity, size_t psk_identity_len ) +{ + ssl->psk = psk; + ssl->psk_len = psk_len; + ssl->psk_identity = psk_identity; + ssl->psk_identity_len = psk_identity_len; +} +#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */ #if defined(POLARSSL_DHM_C) int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G ) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 89820a341..62daab184 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -49,6 +49,8 @@ #define DFL_CA_PATH "" #define DFL_CRT_FILE "" #define DFL_KEY_FILE "" +#define DFL_PSK "" +#define DFL_PSK_IDENTITY "Client_identity" #define DFL_FORCE_CIPHER 0 #define DFL_RENEGOTIATION SSL_RENEGOTIATION_ENABLED #define DFL_ALLOW_LEGACY SSL_LEGACY_NO_RENEGOTIATION @@ -71,6 +73,8 @@ struct options char *ca_path; /* the path with the CA certificate(s) reside */ char *crt_file; /* the file with the client certificate */ char *key_file; /* the file with the client key */ + char *psk; /* the pre-shared key */ + char *psk_identity; /* the pre-shared key identity */ int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */ int renegotiation; /* enable / disable renegotiation */ int allow_legacy; /* allow legacy renegotiation */ @@ -158,6 +162,8 @@ int my_verify( void *data, x509_cert *crt, int depth, int *flags ) " options: ssl3, tls1, tls1_1, tls1_2\n" \ " auth_mode=%%s default: \"optional\"\n" \ " options: none, optional, required\n" \ + " psk=%%s default: \"\" (in hex, without 0x)\n" \ + " psk_identity=%%s default: \"Client_identity\"\n" \ "\n" \ " force_ciphersuite= default: all enabled\n"\ " acceptable ciphersuite names:\n" @@ -180,8 +186,10 @@ int main( int argc, char *argv[] ) #else int main( int argc, char *argv[] ) { - int ret = 0, len, server_fd; + int ret = 0, len, server_fd, i; unsigned char buf[1024]; + unsigned char psk[256]; + size_t psk_len = 0; char *pers = "ssl_client2"; entropy_context entropy; @@ -190,7 +198,6 @@ int main( int argc, char *argv[] ) x509_cert cacert; x509_cert clicert; rsa_context rsa; - int i; char *p, *q; const int *list; @@ -229,6 +236,8 @@ int main( int argc, char *argv[] ) opt.ca_path = DFL_CA_PATH; opt.crt_file = DFL_CRT_FILE; opt.key_file = DFL_KEY_FILE; + opt.psk = DFL_PSK; + opt.psk_identity = DFL_PSK_IDENTITY; opt.force_ciphersuite[0]= DFL_FORCE_CIPHER; opt.renegotiation = DFL_RENEGOTIATION; opt.allow_legacy = DFL_ALLOW_LEGACY; @@ -267,6 +276,10 @@ int main( int argc, char *argv[] ) opt.crt_file = q; else if( strcmp( p, "key_file" ) == 0 ) opt.key_file = q; + else if( strcmp( p, "psk" ) == 0 ) + opt.psk = q; + else if( strcmp( p, "psk_identity" ) == 0 ) + opt.psk_identity = q; else if( strcmp( p, "force_ciphersuite" ) == 0 ) { opt.force_ciphersuite[0] = -1; @@ -357,6 +370,54 @@ int main( int argc, char *argv[] ) goto usage; } + /* + * Unhexify the pre-shared key if any is given + */ + if( strlen( opt.psk ) ) + { + unsigned char c; + size_t j; + + if( strlen( opt.psk ) % 2 != 0 ) + { + printf("pre-shared key not valid hex\n"); + goto exit; + } + + psk_len = strlen( opt.psk ) / 2; + + for( j = 0; j < strlen( opt.psk ); j += 2 ) + { + c = opt.psk[j]; + if( c >= '0' && c <= '9' ) + c -= '0'; + else if( c >= 'a' && c <= 'f' ) + c -= 'a' - 10; + else if( c >= 'A' && c <= 'F' ) + c -= 'A' - 10; + else + { + printf("pre-shared key not valid hex\n"); + goto exit; + } + psk[ j / 2 ] = c << 4; + + c = opt.psk[j + 1]; + if( c >= '0' && c <= '9' ) + c -= '0'; + else if( c >= 'a' && c <= 'f' ) + c -= 'a' - 10; + else if( c >= 'A' && c <= 'F' ) + c -= 'A' - 10; + else + { + printf("pre-shared key not valid hex\n"); + goto exit; + } + psk[ j / 2 ] |= c; + } + } + /* * 0. Initialize the RNG and the session data */ @@ -502,7 +563,8 @@ int main( int argc, char *argv[] ) ssl_set_ca_chain( &ssl, &cacert, NULL, opt.server_name ); ssl_set_own_cert( &ssl, &clicert, &rsa ); - + ssl_set_psk( &ssl, psk, psk_len, (unsigned char *) opt.psk_identity, + strlen( opt.psk_identity ) ); ssl_set_hostname( &ssl, opt.server_name ); if( opt.min_version != -1 ) @@ -554,10 +616,13 @@ int main( int argc, char *argv[] ) else printf( " ok\n" ); - printf( " . Peer certificate information ...\n" ); - x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, " ", - ssl_get_peer_cert( &ssl ) ); - printf( "%s\n", buf ); + if( ssl_get_peer_cert( &ssl ) != NULL ) + { + printf( " . Peer certificate information ...\n" ); + x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, " ", + ssl_get_peer_cert( &ssl ) ); + printf( "%s\n", buf ); + } /* * 6. Write the GET request