Pinned to some recent date

Committer:
Simon Cooksey
Date:
Thu Nov 17 16:43:53 2016 +0000
Revision:
0:fb7af294d5d9
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Simon Cooksey 0:fb7af294d5d9 1 /*
Simon Cooksey 0:fb7af294d5d9 2 * SSLv3/TLSv1 server-side functions
Simon Cooksey 0:fb7af294d5d9 3 *
Simon Cooksey 0:fb7af294d5d9 4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Simon Cooksey 0:fb7af294d5d9 5 * SPDX-License-Identifier: Apache-2.0
Simon Cooksey 0:fb7af294d5d9 6 *
Simon Cooksey 0:fb7af294d5d9 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
Simon Cooksey 0:fb7af294d5d9 8 * not use this file except in compliance with the License.
Simon Cooksey 0:fb7af294d5d9 9 * You may obtain a copy of the License at
Simon Cooksey 0:fb7af294d5d9 10 *
Simon Cooksey 0:fb7af294d5d9 11 * http://www.apache.org/licenses/LICENSE-2.0
Simon Cooksey 0:fb7af294d5d9 12 *
Simon Cooksey 0:fb7af294d5d9 13 * Unless required by applicable law or agreed to in writing, software
Simon Cooksey 0:fb7af294d5d9 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
Simon Cooksey 0:fb7af294d5d9 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Simon Cooksey 0:fb7af294d5d9 16 * See the License for the specific language governing permissions and
Simon Cooksey 0:fb7af294d5d9 17 * limitations under the License.
Simon Cooksey 0:fb7af294d5d9 18 *
Simon Cooksey 0:fb7af294d5d9 19 * This file is part of mbed TLS (https://tls.mbed.org)
Simon Cooksey 0:fb7af294d5d9 20 */
Simon Cooksey 0:fb7af294d5d9 21
Simon Cooksey 0:fb7af294d5d9 22 #if !defined(MBEDTLS_CONFIG_FILE)
Simon Cooksey 0:fb7af294d5d9 23 #include "mbedtls/config.h"
Simon Cooksey 0:fb7af294d5d9 24 #else
Simon Cooksey 0:fb7af294d5d9 25 #include MBEDTLS_CONFIG_FILE
Simon Cooksey 0:fb7af294d5d9 26 #endif
Simon Cooksey 0:fb7af294d5d9 27
Simon Cooksey 0:fb7af294d5d9 28 #if defined(MBEDTLS_SSL_SRV_C)
Simon Cooksey 0:fb7af294d5d9 29
Simon Cooksey 0:fb7af294d5d9 30 #if defined(MBEDTLS_PLATFORM_C)
Simon Cooksey 0:fb7af294d5d9 31 #include "mbedtls/platform.h"
Simon Cooksey 0:fb7af294d5d9 32 #else
Simon Cooksey 0:fb7af294d5d9 33 #include <stdlib.h>
Simon Cooksey 0:fb7af294d5d9 34 #define mbedtls_calloc calloc
Simon Cooksey 0:fb7af294d5d9 35 #define mbedtls_free free
Simon Cooksey 0:fb7af294d5d9 36 #endif
Simon Cooksey 0:fb7af294d5d9 37
Simon Cooksey 0:fb7af294d5d9 38 #include "mbedtls/debug.h"
Simon Cooksey 0:fb7af294d5d9 39 #include "mbedtls/ssl.h"
Simon Cooksey 0:fb7af294d5d9 40 #include "mbedtls/ssl_internal.h"
Simon Cooksey 0:fb7af294d5d9 41
Simon Cooksey 0:fb7af294d5d9 42 #include <string.h>
Simon Cooksey 0:fb7af294d5d9 43
Simon Cooksey 0:fb7af294d5d9 44 #if defined(MBEDTLS_ECP_C)
Simon Cooksey 0:fb7af294d5d9 45 #include "mbedtls/ecp.h"
Simon Cooksey 0:fb7af294d5d9 46 #endif
Simon Cooksey 0:fb7af294d5d9 47
Simon Cooksey 0:fb7af294d5d9 48 #if defined(MBEDTLS_HAVE_TIME)
Simon Cooksey 0:fb7af294d5d9 49 #include "mbedtls/platform_time.h"
Simon Cooksey 0:fb7af294d5d9 50 #endif
Simon Cooksey 0:fb7af294d5d9 51
Simon Cooksey 0:fb7af294d5d9 52 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
Simon Cooksey 0:fb7af294d5d9 53 /* Implementation that should never be optimized out by the compiler */
Simon Cooksey 0:fb7af294d5d9 54 static void mbedtls_zeroize( void *v, size_t n ) {
Simon Cooksey 0:fb7af294d5d9 55 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
Simon Cooksey 0:fb7af294d5d9 56 }
Simon Cooksey 0:fb7af294d5d9 57 #endif
Simon Cooksey 0:fb7af294d5d9 58
Simon Cooksey 0:fb7af294d5d9 59 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
Simon Cooksey 0:fb7af294d5d9 60 int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 61 const unsigned char *info,
Simon Cooksey 0:fb7af294d5d9 62 size_t ilen )
Simon Cooksey 0:fb7af294d5d9 63 {
Simon Cooksey 0:fb7af294d5d9 64 if( ssl->conf->endpoint != MBEDTLS_SSL_IS_SERVER )
Simon Cooksey 0:fb7af294d5d9 65 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
Simon Cooksey 0:fb7af294d5d9 66
Simon Cooksey 0:fb7af294d5d9 67 mbedtls_free( ssl->cli_id );
Simon Cooksey 0:fb7af294d5d9 68
Simon Cooksey 0:fb7af294d5d9 69 if( ( ssl->cli_id = mbedtls_calloc( 1, ilen ) ) == NULL )
Simon Cooksey 0:fb7af294d5d9 70 return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
Simon Cooksey 0:fb7af294d5d9 71
Simon Cooksey 0:fb7af294d5d9 72 memcpy( ssl->cli_id, info, ilen );
Simon Cooksey 0:fb7af294d5d9 73 ssl->cli_id_len = ilen;
Simon Cooksey 0:fb7af294d5d9 74
Simon Cooksey 0:fb7af294d5d9 75 return( 0 );
Simon Cooksey 0:fb7af294d5d9 76 }
Simon Cooksey 0:fb7af294d5d9 77
Simon Cooksey 0:fb7af294d5d9 78 void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf,
Simon Cooksey 0:fb7af294d5d9 79 mbedtls_ssl_cookie_write_t *f_cookie_write,
Simon Cooksey 0:fb7af294d5d9 80 mbedtls_ssl_cookie_check_t *f_cookie_check,
Simon Cooksey 0:fb7af294d5d9 81 void *p_cookie )
Simon Cooksey 0:fb7af294d5d9 82 {
Simon Cooksey 0:fb7af294d5d9 83 conf->f_cookie_write = f_cookie_write;
Simon Cooksey 0:fb7af294d5d9 84 conf->f_cookie_check = f_cookie_check;
Simon Cooksey 0:fb7af294d5d9 85 conf->p_cookie = p_cookie;
Simon Cooksey 0:fb7af294d5d9 86 }
Simon Cooksey 0:fb7af294d5d9 87 #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
Simon Cooksey 0:fb7af294d5d9 88
Simon Cooksey 0:fb7af294d5d9 89 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
Simon Cooksey 0:fb7af294d5d9 90 static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 91 const unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 92 size_t len )
Simon Cooksey 0:fb7af294d5d9 93 {
Simon Cooksey 0:fb7af294d5d9 94 int ret;
Simon Cooksey 0:fb7af294d5d9 95 size_t servername_list_size, hostname_len;
Simon Cooksey 0:fb7af294d5d9 96 const unsigned char *p;
Simon Cooksey 0:fb7af294d5d9 97
Simon Cooksey 0:fb7af294d5d9 98 MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) );
Simon Cooksey 0:fb7af294d5d9 99
Simon Cooksey 0:fb7af294d5d9 100 servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
Simon Cooksey 0:fb7af294d5d9 101 if( servername_list_size + 2 != len )
Simon Cooksey 0:fb7af294d5d9 102 {
Simon Cooksey 0:fb7af294d5d9 103 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 104 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 105 }
Simon Cooksey 0:fb7af294d5d9 106
Simon Cooksey 0:fb7af294d5d9 107 p = buf + 2;
Simon Cooksey 0:fb7af294d5d9 108 while( servername_list_size > 0 )
Simon Cooksey 0:fb7af294d5d9 109 {
Simon Cooksey 0:fb7af294d5d9 110 hostname_len = ( ( p[1] << 8 ) | p[2] );
Simon Cooksey 0:fb7af294d5d9 111 if( hostname_len + 3 > servername_list_size )
Simon Cooksey 0:fb7af294d5d9 112 {
Simon Cooksey 0:fb7af294d5d9 113 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 114 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 115 }
Simon Cooksey 0:fb7af294d5d9 116
Simon Cooksey 0:fb7af294d5d9 117 if( p[0] == MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME )
Simon Cooksey 0:fb7af294d5d9 118 {
Simon Cooksey 0:fb7af294d5d9 119 ret = ssl->conf->f_sni( ssl->conf->p_sni,
Simon Cooksey 0:fb7af294d5d9 120 ssl, p + 3, hostname_len );
Simon Cooksey 0:fb7af294d5d9 121 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 122 {
Simon Cooksey 0:fb7af294d5d9 123 MBEDTLS_SSL_DEBUG_RET( 1, "ssl_sni_wrapper", ret );
Simon Cooksey 0:fb7af294d5d9 124 mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
Simon Cooksey 0:fb7af294d5d9 125 MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME );
Simon Cooksey 0:fb7af294d5d9 126 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 127 }
Simon Cooksey 0:fb7af294d5d9 128 return( 0 );
Simon Cooksey 0:fb7af294d5d9 129 }
Simon Cooksey 0:fb7af294d5d9 130
Simon Cooksey 0:fb7af294d5d9 131 servername_list_size -= hostname_len + 3;
Simon Cooksey 0:fb7af294d5d9 132 p += hostname_len + 3;
Simon Cooksey 0:fb7af294d5d9 133 }
Simon Cooksey 0:fb7af294d5d9 134
Simon Cooksey 0:fb7af294d5d9 135 if( servername_list_size != 0 )
Simon Cooksey 0:fb7af294d5d9 136 {
Simon Cooksey 0:fb7af294d5d9 137 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 138 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 139 }
Simon Cooksey 0:fb7af294d5d9 140
Simon Cooksey 0:fb7af294d5d9 141 return( 0 );
Simon Cooksey 0:fb7af294d5d9 142 }
Simon Cooksey 0:fb7af294d5d9 143 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
Simon Cooksey 0:fb7af294d5d9 144
Simon Cooksey 0:fb7af294d5d9 145 static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 146 const unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 147 size_t len )
Simon Cooksey 0:fb7af294d5d9 148 {
Simon Cooksey 0:fb7af294d5d9 149 int ret;
Simon Cooksey 0:fb7af294d5d9 150
Simon Cooksey 0:fb7af294d5d9 151 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 152 if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
Simon Cooksey 0:fb7af294d5d9 153 {
Simon Cooksey 0:fb7af294d5d9 154 /* Check verify-data in constant-time. The length OTOH is no secret */
Simon Cooksey 0:fb7af294d5d9 155 if( len != 1 + ssl->verify_data_len ||
Simon Cooksey 0:fb7af294d5d9 156 buf[0] != ssl->verify_data_len ||
Simon Cooksey 0:fb7af294d5d9 157 mbedtls_ssl_safer_memcmp( buf + 1, ssl->peer_verify_data,
Simon Cooksey 0:fb7af294d5d9 158 ssl->verify_data_len ) != 0 )
Simon Cooksey 0:fb7af294d5d9 159 {
Simon Cooksey 0:fb7af294d5d9 160 MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) );
Simon Cooksey 0:fb7af294d5d9 161
Simon Cooksey 0:fb7af294d5d9 162 if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 163 return( ret );
Simon Cooksey 0:fb7af294d5d9 164
Simon Cooksey 0:fb7af294d5d9 165 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 166 }
Simon Cooksey 0:fb7af294d5d9 167 }
Simon Cooksey 0:fb7af294d5d9 168 else
Simon Cooksey 0:fb7af294d5d9 169 #endif /* MBEDTLS_SSL_RENEGOTIATION */
Simon Cooksey 0:fb7af294d5d9 170 {
Simon Cooksey 0:fb7af294d5d9 171 if( len != 1 || buf[0] != 0x0 )
Simon Cooksey 0:fb7af294d5d9 172 {
Simon Cooksey 0:fb7af294d5d9 173 MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) );
Simon Cooksey 0:fb7af294d5d9 174
Simon Cooksey 0:fb7af294d5d9 175 if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 176 return( ret );
Simon Cooksey 0:fb7af294d5d9 177
Simon Cooksey 0:fb7af294d5d9 178 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 179 }
Simon Cooksey 0:fb7af294d5d9 180
Simon Cooksey 0:fb7af294d5d9 181 ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION;
Simon Cooksey 0:fb7af294d5d9 182 }
Simon Cooksey 0:fb7af294d5d9 183
Simon Cooksey 0:fb7af294d5d9 184 return( 0 );
Simon Cooksey 0:fb7af294d5d9 185 }
Simon Cooksey 0:fb7af294d5d9 186
Simon Cooksey 0:fb7af294d5d9 187 #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
Simon Cooksey 0:fb7af294d5d9 188 defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
Simon Cooksey 0:fb7af294d5d9 189 static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 190 const unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 191 size_t len )
Simon Cooksey 0:fb7af294d5d9 192 {
Simon Cooksey 0:fb7af294d5d9 193 size_t sig_alg_list_size;
Simon Cooksey 0:fb7af294d5d9 194 const unsigned char *p;
Simon Cooksey 0:fb7af294d5d9 195 const unsigned char *end = buf + len;
Simon Cooksey 0:fb7af294d5d9 196 const int *md_cur;
Simon Cooksey 0:fb7af294d5d9 197
Simon Cooksey 0:fb7af294d5d9 198
Simon Cooksey 0:fb7af294d5d9 199 sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
Simon Cooksey 0:fb7af294d5d9 200 if( sig_alg_list_size + 2 != len ||
Simon Cooksey 0:fb7af294d5d9 201 sig_alg_list_size % 2 != 0 )
Simon Cooksey 0:fb7af294d5d9 202 {
Simon Cooksey 0:fb7af294d5d9 203 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 204 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 205 }
Simon Cooksey 0:fb7af294d5d9 206
Simon Cooksey 0:fb7af294d5d9 207 /*
Simon Cooksey 0:fb7af294d5d9 208 * For now, ignore the SignatureAlgorithm part and rely on offered
Simon Cooksey 0:fb7af294d5d9 209 * ciphersuites only for that part. To be fixed later.
Simon Cooksey 0:fb7af294d5d9 210 *
Simon Cooksey 0:fb7af294d5d9 211 * So, just look at the HashAlgorithm part.
Simon Cooksey 0:fb7af294d5d9 212 */
Simon Cooksey 0:fb7af294d5d9 213 for( md_cur = ssl->conf->sig_hashes; *md_cur != MBEDTLS_MD_NONE; md_cur++ ) {
Simon Cooksey 0:fb7af294d5d9 214 for( p = buf + 2; p < end; p += 2 ) {
Simon Cooksey 0:fb7af294d5d9 215 if( *md_cur == (int) mbedtls_ssl_md_alg_from_hash( p[0] ) ) {
Simon Cooksey 0:fb7af294d5d9 216 ssl->handshake->sig_alg = p[0];
Simon Cooksey 0:fb7af294d5d9 217 goto have_sig_alg;
Simon Cooksey 0:fb7af294d5d9 218 }
Simon Cooksey 0:fb7af294d5d9 219 }
Simon Cooksey 0:fb7af294d5d9 220 }
Simon Cooksey 0:fb7af294d5d9 221
Simon Cooksey 0:fb7af294d5d9 222 /* Some key echanges do not need signatures at all */
Simon Cooksey 0:fb7af294d5d9 223 MBEDTLS_SSL_DEBUG_MSG( 3, ( "no signature_algorithm in common" ) );
Simon Cooksey 0:fb7af294d5d9 224 return( 0 );
Simon Cooksey 0:fb7af294d5d9 225
Simon Cooksey 0:fb7af294d5d9 226 have_sig_alg:
Simon Cooksey 0:fb7af294d5d9 227 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d",
Simon Cooksey 0:fb7af294d5d9 228 ssl->handshake->sig_alg ) );
Simon Cooksey 0:fb7af294d5d9 229
Simon Cooksey 0:fb7af294d5d9 230 return( 0 );
Simon Cooksey 0:fb7af294d5d9 231 }
Simon Cooksey 0:fb7af294d5d9 232 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 &&
Simon Cooksey 0:fb7af294d5d9 233 MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */
Simon Cooksey 0:fb7af294d5d9 234
Simon Cooksey 0:fb7af294d5d9 235 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
Simon Cooksey 0:fb7af294d5d9 236 defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 237 static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 238 const unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 239 size_t len )
Simon Cooksey 0:fb7af294d5d9 240 {
Simon Cooksey 0:fb7af294d5d9 241 size_t list_size, our_size;
Simon Cooksey 0:fb7af294d5d9 242 const unsigned char *p;
Simon Cooksey 0:fb7af294d5d9 243 const mbedtls_ecp_curve_info *curve_info, **curves;
Simon Cooksey 0:fb7af294d5d9 244
Simon Cooksey 0:fb7af294d5d9 245 list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
Simon Cooksey 0:fb7af294d5d9 246 if( list_size + 2 != len ||
Simon Cooksey 0:fb7af294d5d9 247 list_size % 2 != 0 )
Simon Cooksey 0:fb7af294d5d9 248 {
Simon Cooksey 0:fb7af294d5d9 249 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 250 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 251 }
Simon Cooksey 0:fb7af294d5d9 252
Simon Cooksey 0:fb7af294d5d9 253 /* Should never happen unless client duplicates the extension */
Simon Cooksey 0:fb7af294d5d9 254 if( ssl->handshake->curves != NULL )
Simon Cooksey 0:fb7af294d5d9 255 {
Simon Cooksey 0:fb7af294d5d9 256 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 257 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 258 }
Simon Cooksey 0:fb7af294d5d9 259
Simon Cooksey 0:fb7af294d5d9 260 /* Don't allow our peer to make us allocate too much memory,
Simon Cooksey 0:fb7af294d5d9 261 * and leave room for a final 0 */
Simon Cooksey 0:fb7af294d5d9 262 our_size = list_size / 2 + 1;
Simon Cooksey 0:fb7af294d5d9 263 if( our_size > MBEDTLS_ECP_DP_MAX )
Simon Cooksey 0:fb7af294d5d9 264 our_size = MBEDTLS_ECP_DP_MAX;
Simon Cooksey 0:fb7af294d5d9 265
Simon Cooksey 0:fb7af294d5d9 266 if( ( curves = mbedtls_calloc( our_size, sizeof( *curves ) ) ) == NULL )
Simon Cooksey 0:fb7af294d5d9 267 return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
Simon Cooksey 0:fb7af294d5d9 268
Simon Cooksey 0:fb7af294d5d9 269 ssl->handshake->curves = curves;
Simon Cooksey 0:fb7af294d5d9 270
Simon Cooksey 0:fb7af294d5d9 271 p = buf + 2;
Simon Cooksey 0:fb7af294d5d9 272 while( list_size > 0 && our_size > 1 )
Simon Cooksey 0:fb7af294d5d9 273 {
Simon Cooksey 0:fb7af294d5d9 274 curve_info = mbedtls_ecp_curve_info_from_tls_id( ( p[0] << 8 ) | p[1] );
Simon Cooksey 0:fb7af294d5d9 275
Simon Cooksey 0:fb7af294d5d9 276 if( curve_info != NULL )
Simon Cooksey 0:fb7af294d5d9 277 {
Simon Cooksey 0:fb7af294d5d9 278 *curves++ = curve_info;
Simon Cooksey 0:fb7af294d5d9 279 our_size--;
Simon Cooksey 0:fb7af294d5d9 280 }
Simon Cooksey 0:fb7af294d5d9 281
Simon Cooksey 0:fb7af294d5d9 282 list_size -= 2;
Simon Cooksey 0:fb7af294d5d9 283 p += 2;
Simon Cooksey 0:fb7af294d5d9 284 }
Simon Cooksey 0:fb7af294d5d9 285
Simon Cooksey 0:fb7af294d5d9 286 return( 0 );
Simon Cooksey 0:fb7af294d5d9 287 }
Simon Cooksey 0:fb7af294d5d9 288
Simon Cooksey 0:fb7af294d5d9 289 static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 290 const unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 291 size_t len )
Simon Cooksey 0:fb7af294d5d9 292 {
Simon Cooksey 0:fb7af294d5d9 293 size_t list_size;
Simon Cooksey 0:fb7af294d5d9 294 const unsigned char *p;
Simon Cooksey 0:fb7af294d5d9 295
Simon Cooksey 0:fb7af294d5d9 296 list_size = buf[0];
Simon Cooksey 0:fb7af294d5d9 297 if( list_size + 1 != len )
Simon Cooksey 0:fb7af294d5d9 298 {
Simon Cooksey 0:fb7af294d5d9 299 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 300 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 301 }
Simon Cooksey 0:fb7af294d5d9 302
Simon Cooksey 0:fb7af294d5d9 303 p = buf + 1;
Simon Cooksey 0:fb7af294d5d9 304 while( list_size > 0 )
Simon Cooksey 0:fb7af294d5d9 305 {
Simon Cooksey 0:fb7af294d5d9 306 if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED ||
Simon Cooksey 0:fb7af294d5d9 307 p[0] == MBEDTLS_ECP_PF_COMPRESSED )
Simon Cooksey 0:fb7af294d5d9 308 {
Simon Cooksey 0:fb7af294d5d9 309 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)
Simon Cooksey 0:fb7af294d5d9 310 ssl->handshake->ecdh_ctx.point_format = p[0];
Simon Cooksey 0:fb7af294d5d9 311 #endif
Simon Cooksey 0:fb7af294d5d9 312 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 313 ssl->handshake->ecjpake_ctx.point_format = p[0];
Simon Cooksey 0:fb7af294d5d9 314 #endif
Simon Cooksey 0:fb7af294d5d9 315 MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) );
Simon Cooksey 0:fb7af294d5d9 316 return( 0 );
Simon Cooksey 0:fb7af294d5d9 317 }
Simon Cooksey 0:fb7af294d5d9 318
Simon Cooksey 0:fb7af294d5d9 319 list_size--;
Simon Cooksey 0:fb7af294d5d9 320 p++;
Simon Cooksey 0:fb7af294d5d9 321 }
Simon Cooksey 0:fb7af294d5d9 322
Simon Cooksey 0:fb7af294d5d9 323 return( 0 );
Simon Cooksey 0:fb7af294d5d9 324 }
Simon Cooksey 0:fb7af294d5d9 325 #endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
Simon Cooksey 0:fb7af294d5d9 326 MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
Simon Cooksey 0:fb7af294d5d9 327
Simon Cooksey 0:fb7af294d5d9 328 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 329 static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 330 const unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 331 size_t len )
Simon Cooksey 0:fb7af294d5d9 332 {
Simon Cooksey 0:fb7af294d5d9 333 int ret;
Simon Cooksey 0:fb7af294d5d9 334
Simon Cooksey 0:fb7af294d5d9 335 if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 )
Simon Cooksey 0:fb7af294d5d9 336 {
Simon Cooksey 0:fb7af294d5d9 337 MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) );
Simon Cooksey 0:fb7af294d5d9 338 return( 0 );
Simon Cooksey 0:fb7af294d5d9 339 }
Simon Cooksey 0:fb7af294d5d9 340
Simon Cooksey 0:fb7af294d5d9 341 if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx,
Simon Cooksey 0:fb7af294d5d9 342 buf, len ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 343 {
Simon Cooksey 0:fb7af294d5d9 344 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret );
Simon Cooksey 0:fb7af294d5d9 345 return( ret );
Simon Cooksey 0:fb7af294d5d9 346 }
Simon Cooksey 0:fb7af294d5d9 347
Simon Cooksey 0:fb7af294d5d9 348 /* Only mark the extension as OK when we're sure it is */
Simon Cooksey 0:fb7af294d5d9 349 ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK;
Simon Cooksey 0:fb7af294d5d9 350
Simon Cooksey 0:fb7af294d5d9 351 return( 0 );
Simon Cooksey 0:fb7af294d5d9 352 }
Simon Cooksey 0:fb7af294d5d9 353 #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
Simon Cooksey 0:fb7af294d5d9 354
Simon Cooksey 0:fb7af294d5d9 355 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
Simon Cooksey 0:fb7af294d5d9 356 static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 357 const unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 358 size_t len )
Simon Cooksey 0:fb7af294d5d9 359 {
Simon Cooksey 0:fb7af294d5d9 360 if( len != 1 || buf[0] >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID )
Simon Cooksey 0:fb7af294d5d9 361 {
Simon Cooksey 0:fb7af294d5d9 362 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 363 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 364 }
Simon Cooksey 0:fb7af294d5d9 365
Simon Cooksey 0:fb7af294d5d9 366 ssl->session_negotiate->mfl_code = buf[0];
Simon Cooksey 0:fb7af294d5d9 367
Simon Cooksey 0:fb7af294d5d9 368 return( 0 );
Simon Cooksey 0:fb7af294d5d9 369 }
Simon Cooksey 0:fb7af294d5d9 370 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
Simon Cooksey 0:fb7af294d5d9 371
Simon Cooksey 0:fb7af294d5d9 372 #if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
Simon Cooksey 0:fb7af294d5d9 373 static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 374 const unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 375 size_t len )
Simon Cooksey 0:fb7af294d5d9 376 {
Simon Cooksey 0:fb7af294d5d9 377 if( len != 0 )
Simon Cooksey 0:fb7af294d5d9 378 {
Simon Cooksey 0:fb7af294d5d9 379 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 380 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 381 }
Simon Cooksey 0:fb7af294d5d9 382
Simon Cooksey 0:fb7af294d5d9 383 ((void) buf);
Simon Cooksey 0:fb7af294d5d9 384
Simon Cooksey 0:fb7af294d5d9 385 if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED )
Simon Cooksey 0:fb7af294d5d9 386 ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED;
Simon Cooksey 0:fb7af294d5d9 387
Simon Cooksey 0:fb7af294d5d9 388 return( 0 );
Simon Cooksey 0:fb7af294d5d9 389 }
Simon Cooksey 0:fb7af294d5d9 390 #endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
Simon Cooksey 0:fb7af294d5d9 391
Simon Cooksey 0:fb7af294d5d9 392 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
Simon Cooksey 0:fb7af294d5d9 393 static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 394 const unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 395 size_t len )
Simon Cooksey 0:fb7af294d5d9 396 {
Simon Cooksey 0:fb7af294d5d9 397 if( len != 0 )
Simon Cooksey 0:fb7af294d5d9 398 {
Simon Cooksey 0:fb7af294d5d9 399 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 400 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 401 }
Simon Cooksey 0:fb7af294d5d9 402
Simon Cooksey 0:fb7af294d5d9 403 ((void) buf);
Simon Cooksey 0:fb7af294d5d9 404
Simon Cooksey 0:fb7af294d5d9 405 if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 406 ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 )
Simon Cooksey 0:fb7af294d5d9 407 {
Simon Cooksey 0:fb7af294d5d9 408 ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED;
Simon Cooksey 0:fb7af294d5d9 409 }
Simon Cooksey 0:fb7af294d5d9 410
Simon Cooksey 0:fb7af294d5d9 411 return( 0 );
Simon Cooksey 0:fb7af294d5d9 412 }
Simon Cooksey 0:fb7af294d5d9 413 #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
Simon Cooksey 0:fb7af294d5d9 414
Simon Cooksey 0:fb7af294d5d9 415 #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
Simon Cooksey 0:fb7af294d5d9 416 static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 417 const unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 418 size_t len )
Simon Cooksey 0:fb7af294d5d9 419 {
Simon Cooksey 0:fb7af294d5d9 420 if( len != 0 )
Simon Cooksey 0:fb7af294d5d9 421 {
Simon Cooksey 0:fb7af294d5d9 422 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 423 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 424 }
Simon Cooksey 0:fb7af294d5d9 425
Simon Cooksey 0:fb7af294d5d9 426 ((void) buf);
Simon Cooksey 0:fb7af294d5d9 427
Simon Cooksey 0:fb7af294d5d9 428 if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 429 ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 )
Simon Cooksey 0:fb7af294d5d9 430 {
Simon Cooksey 0:fb7af294d5d9 431 ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED;
Simon Cooksey 0:fb7af294d5d9 432 }
Simon Cooksey 0:fb7af294d5d9 433
Simon Cooksey 0:fb7af294d5d9 434 return( 0 );
Simon Cooksey 0:fb7af294d5d9 435 }
Simon Cooksey 0:fb7af294d5d9 436 #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
Simon Cooksey 0:fb7af294d5d9 437
Simon Cooksey 0:fb7af294d5d9 438 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
Simon Cooksey 0:fb7af294d5d9 439 static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 440 unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 441 size_t len )
Simon Cooksey 0:fb7af294d5d9 442 {
Simon Cooksey 0:fb7af294d5d9 443 int ret;
Simon Cooksey 0:fb7af294d5d9 444 mbedtls_ssl_session session;
Simon Cooksey 0:fb7af294d5d9 445
Simon Cooksey 0:fb7af294d5d9 446 mbedtls_ssl_session_init( &session );
Simon Cooksey 0:fb7af294d5d9 447
Simon Cooksey 0:fb7af294d5d9 448 if( ssl->conf->f_ticket_parse == NULL ||
Simon Cooksey 0:fb7af294d5d9 449 ssl->conf->f_ticket_write == NULL )
Simon Cooksey 0:fb7af294d5d9 450 {
Simon Cooksey 0:fb7af294d5d9 451 return( 0 );
Simon Cooksey 0:fb7af294d5d9 452 }
Simon Cooksey 0:fb7af294d5d9 453
Simon Cooksey 0:fb7af294d5d9 454 /* Remember the client asked us to send a new ticket */
Simon Cooksey 0:fb7af294d5d9 455 ssl->handshake->new_session_ticket = 1;
Simon Cooksey 0:fb7af294d5d9 456
Simon Cooksey 0:fb7af294d5d9 457 MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", len ) );
Simon Cooksey 0:fb7af294d5d9 458
Simon Cooksey 0:fb7af294d5d9 459 if( len == 0 )
Simon Cooksey 0:fb7af294d5d9 460 return( 0 );
Simon Cooksey 0:fb7af294d5d9 461
Simon Cooksey 0:fb7af294d5d9 462 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 463 if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
Simon Cooksey 0:fb7af294d5d9 464 {
Simon Cooksey 0:fb7af294d5d9 465 MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket rejected: renegotiating" ) );
Simon Cooksey 0:fb7af294d5d9 466 return( 0 );
Simon Cooksey 0:fb7af294d5d9 467 }
Simon Cooksey 0:fb7af294d5d9 468 #endif /* MBEDTLS_SSL_RENEGOTIATION */
Simon Cooksey 0:fb7af294d5d9 469
Simon Cooksey 0:fb7af294d5d9 470 /*
Simon Cooksey 0:fb7af294d5d9 471 * Failures are ok: just ignore the ticket and proceed.
Simon Cooksey 0:fb7af294d5d9 472 */
Simon Cooksey 0:fb7af294d5d9 473 if( ( ret = ssl->conf->f_ticket_parse( ssl->conf->p_ticket, &session,
Simon Cooksey 0:fb7af294d5d9 474 buf, len ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 475 {
Simon Cooksey 0:fb7af294d5d9 476 mbedtls_ssl_session_free( &session );
Simon Cooksey 0:fb7af294d5d9 477
Simon Cooksey 0:fb7af294d5d9 478 if( ret == MBEDTLS_ERR_SSL_INVALID_MAC )
Simon Cooksey 0:fb7af294d5d9 479 MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is not authentic" ) );
Simon Cooksey 0:fb7af294d5d9 480 else if( ret == MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED )
Simon Cooksey 0:fb7af294d5d9 481 MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is expired" ) );
Simon Cooksey 0:fb7af294d5d9 482 else
Simon Cooksey 0:fb7af294d5d9 483 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_parse", ret );
Simon Cooksey 0:fb7af294d5d9 484
Simon Cooksey 0:fb7af294d5d9 485 return( 0 );
Simon Cooksey 0:fb7af294d5d9 486 }
Simon Cooksey 0:fb7af294d5d9 487
Simon Cooksey 0:fb7af294d5d9 488 /*
Simon Cooksey 0:fb7af294d5d9 489 * Keep the session ID sent by the client, since we MUST send it back to
Simon Cooksey 0:fb7af294d5d9 490 * inform them we're accepting the ticket (RFC 5077 section 3.4)
Simon Cooksey 0:fb7af294d5d9 491 */
Simon Cooksey 0:fb7af294d5d9 492 session.id_len = ssl->session_negotiate->id_len;
Simon Cooksey 0:fb7af294d5d9 493 memcpy( &session.id, ssl->session_negotiate->id, session.id_len );
Simon Cooksey 0:fb7af294d5d9 494
Simon Cooksey 0:fb7af294d5d9 495 mbedtls_ssl_session_free( ssl->session_negotiate );
Simon Cooksey 0:fb7af294d5d9 496 memcpy( ssl->session_negotiate, &session, sizeof( mbedtls_ssl_session ) );
Simon Cooksey 0:fb7af294d5d9 497
Simon Cooksey 0:fb7af294d5d9 498 /* Zeroize instead of free as we copied the content */
Simon Cooksey 0:fb7af294d5d9 499 mbedtls_zeroize( &session, sizeof( mbedtls_ssl_session ) );
Simon Cooksey 0:fb7af294d5d9 500
Simon Cooksey 0:fb7af294d5d9 501 MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from ticket" ) );
Simon Cooksey 0:fb7af294d5d9 502
Simon Cooksey 0:fb7af294d5d9 503 ssl->handshake->resume = 1;
Simon Cooksey 0:fb7af294d5d9 504
Simon Cooksey 0:fb7af294d5d9 505 /* Don't send a new ticket after all, this one is OK */
Simon Cooksey 0:fb7af294d5d9 506 ssl->handshake->new_session_ticket = 0;
Simon Cooksey 0:fb7af294d5d9 507
Simon Cooksey 0:fb7af294d5d9 508 return( 0 );
Simon Cooksey 0:fb7af294d5d9 509 }
Simon Cooksey 0:fb7af294d5d9 510 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
Simon Cooksey 0:fb7af294d5d9 511
Simon Cooksey 0:fb7af294d5d9 512 #if defined(MBEDTLS_SSL_ALPN)
Simon Cooksey 0:fb7af294d5d9 513 static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 514 const unsigned char *buf, size_t len )
Simon Cooksey 0:fb7af294d5d9 515 {
Simon Cooksey 0:fb7af294d5d9 516 size_t list_len, cur_len, ours_len;
Simon Cooksey 0:fb7af294d5d9 517 const unsigned char *theirs, *start, *end;
Simon Cooksey 0:fb7af294d5d9 518 const char **ours;
Simon Cooksey 0:fb7af294d5d9 519
Simon Cooksey 0:fb7af294d5d9 520 /* If ALPN not configured, just ignore the extension */
Simon Cooksey 0:fb7af294d5d9 521 if( ssl->conf->alpn_list == NULL )
Simon Cooksey 0:fb7af294d5d9 522 return( 0 );
Simon Cooksey 0:fb7af294d5d9 523
Simon Cooksey 0:fb7af294d5d9 524 /*
Simon Cooksey 0:fb7af294d5d9 525 * opaque ProtocolName<1..2^8-1>;
Simon Cooksey 0:fb7af294d5d9 526 *
Simon Cooksey 0:fb7af294d5d9 527 * struct {
Simon Cooksey 0:fb7af294d5d9 528 * ProtocolName protocol_name_list<2..2^16-1>
Simon Cooksey 0:fb7af294d5d9 529 * } ProtocolNameList;
Simon Cooksey 0:fb7af294d5d9 530 */
Simon Cooksey 0:fb7af294d5d9 531
Simon Cooksey 0:fb7af294d5d9 532 /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */
Simon Cooksey 0:fb7af294d5d9 533 if( len < 4 )
Simon Cooksey 0:fb7af294d5d9 534 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 535
Simon Cooksey 0:fb7af294d5d9 536 list_len = ( buf[0] << 8 ) | buf[1];
Simon Cooksey 0:fb7af294d5d9 537 if( list_len != len - 2 )
Simon Cooksey 0:fb7af294d5d9 538 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 539
Simon Cooksey 0:fb7af294d5d9 540 /*
Simon Cooksey 0:fb7af294d5d9 541 * Use our order of preference
Simon Cooksey 0:fb7af294d5d9 542 */
Simon Cooksey 0:fb7af294d5d9 543 start = buf + 2;
Simon Cooksey 0:fb7af294d5d9 544 end = buf + len;
Simon Cooksey 0:fb7af294d5d9 545 for( ours = ssl->conf->alpn_list; *ours != NULL; ours++ )
Simon Cooksey 0:fb7af294d5d9 546 {
Simon Cooksey 0:fb7af294d5d9 547 ours_len = strlen( *ours );
Simon Cooksey 0:fb7af294d5d9 548 for( theirs = start; theirs != end; theirs += cur_len )
Simon Cooksey 0:fb7af294d5d9 549 {
Simon Cooksey 0:fb7af294d5d9 550 /* If the list is well formed, we should get equality first */
Simon Cooksey 0:fb7af294d5d9 551 if( theirs > end )
Simon Cooksey 0:fb7af294d5d9 552 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 553
Simon Cooksey 0:fb7af294d5d9 554 cur_len = *theirs++;
Simon Cooksey 0:fb7af294d5d9 555
Simon Cooksey 0:fb7af294d5d9 556 /* Empty strings MUST NOT be included */
Simon Cooksey 0:fb7af294d5d9 557 if( cur_len == 0 )
Simon Cooksey 0:fb7af294d5d9 558 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 559
Simon Cooksey 0:fb7af294d5d9 560 if( cur_len == ours_len &&
Simon Cooksey 0:fb7af294d5d9 561 memcmp( theirs, *ours, cur_len ) == 0 )
Simon Cooksey 0:fb7af294d5d9 562 {
Simon Cooksey 0:fb7af294d5d9 563 ssl->alpn_chosen = *ours;
Simon Cooksey 0:fb7af294d5d9 564 return( 0 );
Simon Cooksey 0:fb7af294d5d9 565 }
Simon Cooksey 0:fb7af294d5d9 566 }
Simon Cooksey 0:fb7af294d5d9 567 }
Simon Cooksey 0:fb7af294d5d9 568
Simon Cooksey 0:fb7af294d5d9 569 /* If we get there, no match was found */
Simon Cooksey 0:fb7af294d5d9 570 mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
Simon Cooksey 0:fb7af294d5d9 571 MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL );
Simon Cooksey 0:fb7af294d5d9 572 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 573 }
Simon Cooksey 0:fb7af294d5d9 574 #endif /* MBEDTLS_SSL_ALPN */
Simon Cooksey 0:fb7af294d5d9 575
Simon Cooksey 0:fb7af294d5d9 576 /*
Simon Cooksey 0:fb7af294d5d9 577 * Auxiliary functions for ServerHello parsing and related actions
Simon Cooksey 0:fb7af294d5d9 578 */
Simon Cooksey 0:fb7af294d5d9 579
Simon Cooksey 0:fb7af294d5d9 580 #if defined(MBEDTLS_X509_CRT_PARSE_C)
Simon Cooksey 0:fb7af294d5d9 581 /*
Simon Cooksey 0:fb7af294d5d9 582 * Return 0 if the given key uses one of the acceptable curves, -1 otherwise
Simon Cooksey 0:fb7af294d5d9 583 */
Simon Cooksey 0:fb7af294d5d9 584 #if defined(MBEDTLS_ECDSA_C)
Simon Cooksey 0:fb7af294d5d9 585 static int ssl_check_key_curve( mbedtls_pk_context *pk,
Simon Cooksey 0:fb7af294d5d9 586 const mbedtls_ecp_curve_info **curves )
Simon Cooksey 0:fb7af294d5d9 587 {
Simon Cooksey 0:fb7af294d5d9 588 const mbedtls_ecp_curve_info **crv = curves;
Simon Cooksey 0:fb7af294d5d9 589 mbedtls_ecp_group_id grp_id = mbedtls_pk_ec( *pk )->grp.id;
Simon Cooksey 0:fb7af294d5d9 590
Simon Cooksey 0:fb7af294d5d9 591 while( *crv != NULL )
Simon Cooksey 0:fb7af294d5d9 592 {
Simon Cooksey 0:fb7af294d5d9 593 if( (*crv)->grp_id == grp_id )
Simon Cooksey 0:fb7af294d5d9 594 return( 0 );
Simon Cooksey 0:fb7af294d5d9 595 crv++;
Simon Cooksey 0:fb7af294d5d9 596 }
Simon Cooksey 0:fb7af294d5d9 597
Simon Cooksey 0:fb7af294d5d9 598 return( -1 );
Simon Cooksey 0:fb7af294d5d9 599 }
Simon Cooksey 0:fb7af294d5d9 600 #endif /* MBEDTLS_ECDSA_C */
Simon Cooksey 0:fb7af294d5d9 601
Simon Cooksey 0:fb7af294d5d9 602 /*
Simon Cooksey 0:fb7af294d5d9 603 * Try picking a certificate for this ciphersuite,
Simon Cooksey 0:fb7af294d5d9 604 * return 0 on success and -1 on failure.
Simon Cooksey 0:fb7af294d5d9 605 */
Simon Cooksey 0:fb7af294d5d9 606 static int ssl_pick_cert( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 607 const mbedtls_ssl_ciphersuite_t * ciphersuite_info )
Simon Cooksey 0:fb7af294d5d9 608 {
Simon Cooksey 0:fb7af294d5d9 609 mbedtls_ssl_key_cert *cur, *list, *fallback = NULL;
Simon Cooksey 0:fb7af294d5d9 610 mbedtls_pk_type_t pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info );
Simon Cooksey 0:fb7af294d5d9 611 uint32_t flags;
Simon Cooksey 0:fb7af294d5d9 612
Simon Cooksey 0:fb7af294d5d9 613 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
Simon Cooksey 0:fb7af294d5d9 614 if( ssl->handshake->sni_key_cert != NULL )
Simon Cooksey 0:fb7af294d5d9 615 list = ssl->handshake->sni_key_cert;
Simon Cooksey 0:fb7af294d5d9 616 else
Simon Cooksey 0:fb7af294d5d9 617 #endif
Simon Cooksey 0:fb7af294d5d9 618 list = ssl->conf->key_cert;
Simon Cooksey 0:fb7af294d5d9 619
Simon Cooksey 0:fb7af294d5d9 620 if( pk_alg == MBEDTLS_PK_NONE )
Simon Cooksey 0:fb7af294d5d9 621 return( 0 );
Simon Cooksey 0:fb7af294d5d9 622
Simon Cooksey 0:fb7af294d5d9 623 MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite requires certificate" ) );
Simon Cooksey 0:fb7af294d5d9 624
Simon Cooksey 0:fb7af294d5d9 625 if( list == NULL )
Simon Cooksey 0:fb7af294d5d9 626 {
Simon Cooksey 0:fb7af294d5d9 627 MBEDTLS_SSL_DEBUG_MSG( 3, ( "server has no certificate" ) );
Simon Cooksey 0:fb7af294d5d9 628 return( -1 );
Simon Cooksey 0:fb7af294d5d9 629 }
Simon Cooksey 0:fb7af294d5d9 630
Simon Cooksey 0:fb7af294d5d9 631 for( cur = list; cur != NULL; cur = cur->next )
Simon Cooksey 0:fb7af294d5d9 632 {
Simon Cooksey 0:fb7af294d5d9 633 MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate",
Simon Cooksey 0:fb7af294d5d9 634 cur->cert );
Simon Cooksey 0:fb7af294d5d9 635
Simon Cooksey 0:fb7af294d5d9 636 if( ! mbedtls_pk_can_do( cur->key, pk_alg ) )
Simon Cooksey 0:fb7af294d5d9 637 {
Simon Cooksey 0:fb7af294d5d9 638 MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) );
Simon Cooksey 0:fb7af294d5d9 639 continue;
Simon Cooksey 0:fb7af294d5d9 640 }
Simon Cooksey 0:fb7af294d5d9 641
Simon Cooksey 0:fb7af294d5d9 642 /*
Simon Cooksey 0:fb7af294d5d9 643 * This avoids sending the client a cert it'll reject based on
Simon Cooksey 0:fb7af294d5d9 644 * keyUsage or other extensions.
Simon Cooksey 0:fb7af294d5d9 645 *
Simon Cooksey 0:fb7af294d5d9 646 * It also allows the user to provision different certificates for
Simon Cooksey 0:fb7af294d5d9 647 * different uses based on keyUsage, eg if they want to avoid signing
Simon Cooksey 0:fb7af294d5d9 648 * and decrypting with the same RSA key.
Simon Cooksey 0:fb7af294d5d9 649 */
Simon Cooksey 0:fb7af294d5d9 650 if( mbedtls_ssl_check_cert_usage( cur->cert, ciphersuite_info,
Simon Cooksey 0:fb7af294d5d9 651 MBEDTLS_SSL_IS_SERVER, &flags ) != 0 )
Simon Cooksey 0:fb7af294d5d9 652 {
Simon Cooksey 0:fb7af294d5d9 653 MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: "
Simon Cooksey 0:fb7af294d5d9 654 "(extended) key usage extension" ) );
Simon Cooksey 0:fb7af294d5d9 655 continue;
Simon Cooksey 0:fb7af294d5d9 656 }
Simon Cooksey 0:fb7af294d5d9 657
Simon Cooksey 0:fb7af294d5d9 658 #if defined(MBEDTLS_ECDSA_C)
Simon Cooksey 0:fb7af294d5d9 659 if( pk_alg == MBEDTLS_PK_ECDSA &&
Simon Cooksey 0:fb7af294d5d9 660 ssl_check_key_curve( cur->key, ssl->handshake->curves ) != 0 )
Simon Cooksey 0:fb7af294d5d9 661 {
Simon Cooksey 0:fb7af294d5d9 662 MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) );
Simon Cooksey 0:fb7af294d5d9 663 continue;
Simon Cooksey 0:fb7af294d5d9 664 }
Simon Cooksey 0:fb7af294d5d9 665 #endif
Simon Cooksey 0:fb7af294d5d9 666
Simon Cooksey 0:fb7af294d5d9 667 /*
Simon Cooksey 0:fb7af294d5d9 668 * Try to select a SHA-1 certificate for pre-1.2 clients, but still
Simon Cooksey 0:fb7af294d5d9 669 * present them a SHA-higher cert rather than failing if it's the only
Simon Cooksey 0:fb7af294d5d9 670 * one we got that satisfies the other conditions.
Simon Cooksey 0:fb7af294d5d9 671 */
Simon Cooksey 0:fb7af294d5d9 672 if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 &&
Simon Cooksey 0:fb7af294d5d9 673 cur->cert->sig_md != MBEDTLS_MD_SHA1 )
Simon Cooksey 0:fb7af294d5d9 674 {
Simon Cooksey 0:fb7af294d5d9 675 if( fallback == NULL )
Simon Cooksey 0:fb7af294d5d9 676 fallback = cur;
Simon Cooksey 0:fb7af294d5d9 677 {
Simon Cooksey 0:fb7af294d5d9 678 MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate not preferred: "
Simon Cooksey 0:fb7af294d5d9 679 "sha-2 with pre-TLS 1.2 client" ) );
Simon Cooksey 0:fb7af294d5d9 680 continue;
Simon Cooksey 0:fb7af294d5d9 681 }
Simon Cooksey 0:fb7af294d5d9 682 }
Simon Cooksey 0:fb7af294d5d9 683
Simon Cooksey 0:fb7af294d5d9 684 /* If we get there, we got a winner */
Simon Cooksey 0:fb7af294d5d9 685 break;
Simon Cooksey 0:fb7af294d5d9 686 }
Simon Cooksey 0:fb7af294d5d9 687
Simon Cooksey 0:fb7af294d5d9 688 if( cur == NULL )
Simon Cooksey 0:fb7af294d5d9 689 cur = fallback;
Simon Cooksey 0:fb7af294d5d9 690
Simon Cooksey 0:fb7af294d5d9 691 /* Do not update ssl->handshake->key_cert unless there is a match */
Simon Cooksey 0:fb7af294d5d9 692 if( cur != NULL )
Simon Cooksey 0:fb7af294d5d9 693 {
Simon Cooksey 0:fb7af294d5d9 694 ssl->handshake->key_cert = cur;
Simon Cooksey 0:fb7af294d5d9 695 MBEDTLS_SSL_DEBUG_CRT( 3, "selected certificate chain, certificate",
Simon Cooksey 0:fb7af294d5d9 696 ssl->handshake->key_cert->cert );
Simon Cooksey 0:fb7af294d5d9 697 return( 0 );
Simon Cooksey 0:fb7af294d5d9 698 }
Simon Cooksey 0:fb7af294d5d9 699
Simon Cooksey 0:fb7af294d5d9 700 return( -1 );
Simon Cooksey 0:fb7af294d5d9 701 }
Simon Cooksey 0:fb7af294d5d9 702 #endif /* MBEDTLS_X509_CRT_PARSE_C */
Simon Cooksey 0:fb7af294d5d9 703
Simon Cooksey 0:fb7af294d5d9 704 /*
Simon Cooksey 0:fb7af294d5d9 705 * Check if a given ciphersuite is suitable for use with our config/keys/etc
Simon Cooksey 0:fb7af294d5d9 706 * Sets ciphersuite_info only if the suite matches.
Simon Cooksey 0:fb7af294d5d9 707 */
Simon Cooksey 0:fb7af294d5d9 708 static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id,
Simon Cooksey 0:fb7af294d5d9 709 const mbedtls_ssl_ciphersuite_t **ciphersuite_info )
Simon Cooksey 0:fb7af294d5d9 710 {
Simon Cooksey 0:fb7af294d5d9 711 const mbedtls_ssl_ciphersuite_t *suite_info;
Simon Cooksey 0:fb7af294d5d9 712
Simon Cooksey 0:fb7af294d5d9 713 suite_info = mbedtls_ssl_ciphersuite_from_id( suite_id );
Simon Cooksey 0:fb7af294d5d9 714 if( suite_info == NULL )
Simon Cooksey 0:fb7af294d5d9 715 {
Simon Cooksey 0:fb7af294d5d9 716 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
Simon Cooksey 0:fb7af294d5d9 717 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
Simon Cooksey 0:fb7af294d5d9 718 }
Simon Cooksey 0:fb7af294d5d9 719
Simon Cooksey 0:fb7af294d5d9 720 MBEDTLS_SSL_DEBUG_MSG( 3, ( "trying ciphersuite: %s", suite_info->name ) );
Simon Cooksey 0:fb7af294d5d9 721
Simon Cooksey 0:fb7af294d5d9 722 if( suite_info->min_minor_ver > ssl->minor_ver ||
Simon Cooksey 0:fb7af294d5d9 723 suite_info->max_minor_ver < ssl->minor_ver )
Simon Cooksey 0:fb7af294d5d9 724 {
Simon Cooksey 0:fb7af294d5d9 725 MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: version" ) );
Simon Cooksey 0:fb7af294d5d9 726 return( 0 );
Simon Cooksey 0:fb7af294d5d9 727 }
Simon Cooksey 0:fb7af294d5d9 728
Simon Cooksey 0:fb7af294d5d9 729 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 730 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
Simon Cooksey 0:fb7af294d5d9 731 ( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) )
Simon Cooksey 0:fb7af294d5d9 732 return( 0 );
Simon Cooksey 0:fb7af294d5d9 733 #endif
Simon Cooksey 0:fb7af294d5d9 734
Simon Cooksey 0:fb7af294d5d9 735 #if defined(MBEDTLS_ARC4_C)
Simon Cooksey 0:fb7af294d5d9 736 if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED &&
Simon Cooksey 0:fb7af294d5d9 737 suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 )
Simon Cooksey 0:fb7af294d5d9 738 {
Simon Cooksey 0:fb7af294d5d9 739 MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: rc4" ) );
Simon Cooksey 0:fb7af294d5d9 740 return( 0 );
Simon Cooksey 0:fb7af294d5d9 741 }
Simon Cooksey 0:fb7af294d5d9 742 #endif
Simon Cooksey 0:fb7af294d5d9 743
Simon Cooksey 0:fb7af294d5d9 744 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 745 if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE &&
Simon Cooksey 0:fb7af294d5d9 746 ( ssl->handshake->cli_exts & MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK ) == 0 )
Simon Cooksey 0:fb7af294d5d9 747 {
Simon Cooksey 0:fb7af294d5d9 748 MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: ecjpake "
Simon Cooksey 0:fb7af294d5d9 749 "not configured or ext missing" ) );
Simon Cooksey 0:fb7af294d5d9 750 return( 0 );
Simon Cooksey 0:fb7af294d5d9 751 }
Simon Cooksey 0:fb7af294d5d9 752 #endif
Simon Cooksey 0:fb7af294d5d9 753
Simon Cooksey 0:fb7af294d5d9 754
Simon Cooksey 0:fb7af294d5d9 755 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)
Simon Cooksey 0:fb7af294d5d9 756 if( mbedtls_ssl_ciphersuite_uses_ec( suite_info ) &&
Simon Cooksey 0:fb7af294d5d9 757 ( ssl->handshake->curves == NULL ||
Simon Cooksey 0:fb7af294d5d9 758 ssl->handshake->curves[0] == NULL ) )
Simon Cooksey 0:fb7af294d5d9 759 {
Simon Cooksey 0:fb7af294d5d9 760 MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: "
Simon Cooksey 0:fb7af294d5d9 761 "no common elliptic curve" ) );
Simon Cooksey 0:fb7af294d5d9 762 return( 0 );
Simon Cooksey 0:fb7af294d5d9 763 }
Simon Cooksey 0:fb7af294d5d9 764 #endif
Simon Cooksey 0:fb7af294d5d9 765
Simon Cooksey 0:fb7af294d5d9 766 #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 767 /* If the ciphersuite requires a pre-shared key and we don't
Simon Cooksey 0:fb7af294d5d9 768 * have one, skip it now rather than failing later */
Simon Cooksey 0:fb7af294d5d9 769 if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) &&
Simon Cooksey 0:fb7af294d5d9 770 ssl->conf->f_psk == NULL &&
Simon Cooksey 0:fb7af294d5d9 771 ( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL ||
Simon Cooksey 0:fb7af294d5d9 772 ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) )
Simon Cooksey 0:fb7af294d5d9 773 {
Simon Cooksey 0:fb7af294d5d9 774 MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no pre-shared key" ) );
Simon Cooksey 0:fb7af294d5d9 775 return( 0 );
Simon Cooksey 0:fb7af294d5d9 776 }
Simon Cooksey 0:fb7af294d5d9 777 #endif
Simon Cooksey 0:fb7af294d5d9 778
Simon Cooksey 0:fb7af294d5d9 779 #if defined(MBEDTLS_X509_CRT_PARSE_C)
Simon Cooksey 0:fb7af294d5d9 780 /*
Simon Cooksey 0:fb7af294d5d9 781 * Final check: if ciphersuite requires us to have a
Simon Cooksey 0:fb7af294d5d9 782 * certificate/key of a particular type:
Simon Cooksey 0:fb7af294d5d9 783 * - select the appropriate certificate if we have one, or
Simon Cooksey 0:fb7af294d5d9 784 * - try the next ciphersuite if we don't
Simon Cooksey 0:fb7af294d5d9 785 * This must be done last since we modify the key_cert list.
Simon Cooksey 0:fb7af294d5d9 786 */
Simon Cooksey 0:fb7af294d5d9 787 if( ssl_pick_cert( ssl, suite_info ) != 0 )
Simon Cooksey 0:fb7af294d5d9 788 {
Simon Cooksey 0:fb7af294d5d9 789 MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: "
Simon Cooksey 0:fb7af294d5d9 790 "no suitable certificate" ) );
Simon Cooksey 0:fb7af294d5d9 791 return( 0 );
Simon Cooksey 0:fb7af294d5d9 792 }
Simon Cooksey 0:fb7af294d5d9 793 #endif
Simon Cooksey 0:fb7af294d5d9 794
Simon Cooksey 0:fb7af294d5d9 795 *ciphersuite_info = suite_info;
Simon Cooksey 0:fb7af294d5d9 796 return( 0 );
Simon Cooksey 0:fb7af294d5d9 797 }
Simon Cooksey 0:fb7af294d5d9 798
Simon Cooksey 0:fb7af294d5d9 799 #if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO)
Simon Cooksey 0:fb7af294d5d9 800 static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 801 {
Simon Cooksey 0:fb7af294d5d9 802 int ret, got_common_suite;
Simon Cooksey 0:fb7af294d5d9 803 unsigned int i, j;
Simon Cooksey 0:fb7af294d5d9 804 size_t n;
Simon Cooksey 0:fb7af294d5d9 805 unsigned int ciph_len, sess_len, chal_len;
Simon Cooksey 0:fb7af294d5d9 806 unsigned char *buf, *p;
Simon Cooksey 0:fb7af294d5d9 807 const int *ciphersuites;
Simon Cooksey 0:fb7af294d5d9 808 const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
Simon Cooksey 0:fb7af294d5d9 809
Simon Cooksey 0:fb7af294d5d9 810 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello v2" ) );
Simon Cooksey 0:fb7af294d5d9 811
Simon Cooksey 0:fb7af294d5d9 812 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 813 if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
Simon Cooksey 0:fb7af294d5d9 814 {
Simon Cooksey 0:fb7af294d5d9 815 MBEDTLS_SSL_DEBUG_MSG( 1, ( "client hello v2 illegal for renegotiation" ) );
Simon Cooksey 0:fb7af294d5d9 816
Simon Cooksey 0:fb7af294d5d9 817 if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 818 return( ret );
Simon Cooksey 0:fb7af294d5d9 819
Simon Cooksey 0:fb7af294d5d9 820 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 821 }
Simon Cooksey 0:fb7af294d5d9 822 #endif /* MBEDTLS_SSL_RENEGOTIATION */
Simon Cooksey 0:fb7af294d5d9 823
Simon Cooksey 0:fb7af294d5d9 824 buf = ssl->in_hdr;
Simon Cooksey 0:fb7af294d5d9 825
Simon Cooksey 0:fb7af294d5d9 826 MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, 5 );
Simon Cooksey 0:fb7af294d5d9 827
Simon Cooksey 0:fb7af294d5d9 828 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message type: %d",
Simon Cooksey 0:fb7af294d5d9 829 buf[2] ) );
Simon Cooksey 0:fb7af294d5d9 830 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message len.: %d",
Simon Cooksey 0:fb7af294d5d9 831 ( ( buf[0] & 0x7F ) << 8 ) | buf[1] ) );
Simon Cooksey 0:fb7af294d5d9 832 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, max. version: [%d:%d]",
Simon Cooksey 0:fb7af294d5d9 833 buf[3], buf[4] ) );
Simon Cooksey 0:fb7af294d5d9 834
Simon Cooksey 0:fb7af294d5d9 835 /*
Simon Cooksey 0:fb7af294d5d9 836 * SSLv2 Client Hello
Simon Cooksey 0:fb7af294d5d9 837 *
Simon Cooksey 0:fb7af294d5d9 838 * Record layer:
Simon Cooksey 0:fb7af294d5d9 839 * 0 . 1 message length
Simon Cooksey 0:fb7af294d5d9 840 *
Simon Cooksey 0:fb7af294d5d9 841 * SSL layer:
Simon Cooksey 0:fb7af294d5d9 842 * 2 . 2 message type
Simon Cooksey 0:fb7af294d5d9 843 * 3 . 4 protocol version
Simon Cooksey 0:fb7af294d5d9 844 */
Simon Cooksey 0:fb7af294d5d9 845 if( buf[2] != MBEDTLS_SSL_HS_CLIENT_HELLO ||
Simon Cooksey 0:fb7af294d5d9 846 buf[3] != MBEDTLS_SSL_MAJOR_VERSION_3 )
Simon Cooksey 0:fb7af294d5d9 847 {
Simon Cooksey 0:fb7af294d5d9 848 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 849 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 850 }
Simon Cooksey 0:fb7af294d5d9 851
Simon Cooksey 0:fb7af294d5d9 852 n = ( ( buf[0] << 8 ) | buf[1] ) & 0x7FFF;
Simon Cooksey 0:fb7af294d5d9 853
Simon Cooksey 0:fb7af294d5d9 854 if( n < 17 || n > 512 )
Simon Cooksey 0:fb7af294d5d9 855 {
Simon Cooksey 0:fb7af294d5d9 856 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 857 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 858 }
Simon Cooksey 0:fb7af294d5d9 859
Simon Cooksey 0:fb7af294d5d9 860 ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3;
Simon Cooksey 0:fb7af294d5d9 861 ssl->minor_ver = ( buf[4] <= ssl->conf->max_minor_ver )
Simon Cooksey 0:fb7af294d5d9 862 ? buf[4] : ssl->conf->max_minor_ver;
Simon Cooksey 0:fb7af294d5d9 863
Simon Cooksey 0:fb7af294d5d9 864 if( ssl->minor_ver < ssl->conf->min_minor_ver )
Simon Cooksey 0:fb7af294d5d9 865 {
Simon Cooksey 0:fb7af294d5d9 866 MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum"
Simon Cooksey 0:fb7af294d5d9 867 " [%d:%d] < [%d:%d]",
Simon Cooksey 0:fb7af294d5d9 868 ssl->major_ver, ssl->minor_ver,
Simon Cooksey 0:fb7af294d5d9 869 ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) );
Simon Cooksey 0:fb7af294d5d9 870
Simon Cooksey 0:fb7af294d5d9 871 mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
Simon Cooksey 0:fb7af294d5d9 872 MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION );
Simon Cooksey 0:fb7af294d5d9 873 return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION );
Simon Cooksey 0:fb7af294d5d9 874 }
Simon Cooksey 0:fb7af294d5d9 875
Simon Cooksey 0:fb7af294d5d9 876 ssl->handshake->max_major_ver = buf[3];
Simon Cooksey 0:fb7af294d5d9 877 ssl->handshake->max_minor_ver = buf[4];
Simon Cooksey 0:fb7af294d5d9 878
Simon Cooksey 0:fb7af294d5d9 879 if( ( ret = mbedtls_ssl_fetch_input( ssl, 2 + n ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 880 {
Simon Cooksey 0:fb7af294d5d9 881 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
Simon Cooksey 0:fb7af294d5d9 882 return( ret );
Simon Cooksey 0:fb7af294d5d9 883 }
Simon Cooksey 0:fb7af294d5d9 884
Simon Cooksey 0:fb7af294d5d9 885 ssl->handshake->update_checksum( ssl, buf + 2, n );
Simon Cooksey 0:fb7af294d5d9 886
Simon Cooksey 0:fb7af294d5d9 887 buf = ssl->in_msg;
Simon Cooksey 0:fb7af294d5d9 888 n = ssl->in_left - 5;
Simon Cooksey 0:fb7af294d5d9 889
Simon Cooksey 0:fb7af294d5d9 890 /*
Simon Cooksey 0:fb7af294d5d9 891 * 0 . 1 ciphersuitelist length
Simon Cooksey 0:fb7af294d5d9 892 * 2 . 3 session id length
Simon Cooksey 0:fb7af294d5d9 893 * 4 . 5 challenge length
Simon Cooksey 0:fb7af294d5d9 894 * 6 . .. ciphersuitelist
Simon Cooksey 0:fb7af294d5d9 895 * .. . .. session id
Simon Cooksey 0:fb7af294d5d9 896 * .. . .. challenge
Simon Cooksey 0:fb7af294d5d9 897 */
Simon Cooksey 0:fb7af294d5d9 898 MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, n );
Simon Cooksey 0:fb7af294d5d9 899
Simon Cooksey 0:fb7af294d5d9 900 ciph_len = ( buf[0] << 8 ) | buf[1];
Simon Cooksey 0:fb7af294d5d9 901 sess_len = ( buf[2] << 8 ) | buf[3];
Simon Cooksey 0:fb7af294d5d9 902 chal_len = ( buf[4] << 8 ) | buf[5];
Simon Cooksey 0:fb7af294d5d9 903
Simon Cooksey 0:fb7af294d5d9 904 MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciph_len: %d, sess_len: %d, chal_len: %d",
Simon Cooksey 0:fb7af294d5d9 905 ciph_len, sess_len, chal_len ) );
Simon Cooksey 0:fb7af294d5d9 906
Simon Cooksey 0:fb7af294d5d9 907 /*
Simon Cooksey 0:fb7af294d5d9 908 * Make sure each parameter length is valid
Simon Cooksey 0:fb7af294d5d9 909 */
Simon Cooksey 0:fb7af294d5d9 910 if( ciph_len < 3 || ( ciph_len % 3 ) != 0 )
Simon Cooksey 0:fb7af294d5d9 911 {
Simon Cooksey 0:fb7af294d5d9 912 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 913 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 914 }
Simon Cooksey 0:fb7af294d5d9 915
Simon Cooksey 0:fb7af294d5d9 916 if( sess_len > 32 )
Simon Cooksey 0:fb7af294d5d9 917 {
Simon Cooksey 0:fb7af294d5d9 918 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 919 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 920 }
Simon Cooksey 0:fb7af294d5d9 921
Simon Cooksey 0:fb7af294d5d9 922 if( chal_len < 8 || chal_len > 32 )
Simon Cooksey 0:fb7af294d5d9 923 {
Simon Cooksey 0:fb7af294d5d9 924 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 925 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 926 }
Simon Cooksey 0:fb7af294d5d9 927
Simon Cooksey 0:fb7af294d5d9 928 if( n != 6 + ciph_len + sess_len + chal_len )
Simon Cooksey 0:fb7af294d5d9 929 {
Simon Cooksey 0:fb7af294d5d9 930 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 931 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 932 }
Simon Cooksey 0:fb7af294d5d9 933
Simon Cooksey 0:fb7af294d5d9 934 MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist",
Simon Cooksey 0:fb7af294d5d9 935 buf + 6, ciph_len );
Simon Cooksey 0:fb7af294d5d9 936 MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id",
Simon Cooksey 0:fb7af294d5d9 937 buf + 6 + ciph_len, sess_len );
Simon Cooksey 0:fb7af294d5d9 938 MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, challenge",
Simon Cooksey 0:fb7af294d5d9 939 buf + 6 + ciph_len + sess_len, chal_len );
Simon Cooksey 0:fb7af294d5d9 940
Simon Cooksey 0:fb7af294d5d9 941 p = buf + 6 + ciph_len;
Simon Cooksey 0:fb7af294d5d9 942 ssl->session_negotiate->id_len = sess_len;
Simon Cooksey 0:fb7af294d5d9 943 memset( ssl->session_negotiate->id, 0,
Simon Cooksey 0:fb7af294d5d9 944 sizeof( ssl->session_negotiate->id ) );
Simon Cooksey 0:fb7af294d5d9 945 memcpy( ssl->session_negotiate->id, p, ssl->session_negotiate->id_len );
Simon Cooksey 0:fb7af294d5d9 946
Simon Cooksey 0:fb7af294d5d9 947 p += sess_len;
Simon Cooksey 0:fb7af294d5d9 948 memset( ssl->handshake->randbytes, 0, 64 );
Simon Cooksey 0:fb7af294d5d9 949 memcpy( ssl->handshake->randbytes + 32 - chal_len, p, chal_len );
Simon Cooksey 0:fb7af294d5d9 950
Simon Cooksey 0:fb7af294d5d9 951 /*
Simon Cooksey 0:fb7af294d5d9 952 * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV
Simon Cooksey 0:fb7af294d5d9 953 */
Simon Cooksey 0:fb7af294d5d9 954 for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 )
Simon Cooksey 0:fb7af294d5d9 955 {
Simon Cooksey 0:fb7af294d5d9 956 if( p[0] == 0 && p[1] == 0 && p[2] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO )
Simon Cooksey 0:fb7af294d5d9 957 {
Simon Cooksey 0:fb7af294d5d9 958 MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) );
Simon Cooksey 0:fb7af294d5d9 959 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 960 if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
Simon Cooksey 0:fb7af294d5d9 961 {
Simon Cooksey 0:fb7af294d5d9 962 MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV "
Simon Cooksey 0:fb7af294d5d9 963 "during renegotiation" ) );
Simon Cooksey 0:fb7af294d5d9 964
Simon Cooksey 0:fb7af294d5d9 965 if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 966 return( ret );
Simon Cooksey 0:fb7af294d5d9 967
Simon Cooksey 0:fb7af294d5d9 968 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 969 }
Simon Cooksey 0:fb7af294d5d9 970 #endif /* MBEDTLS_SSL_RENEGOTIATION */
Simon Cooksey 0:fb7af294d5d9 971 ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION;
Simon Cooksey 0:fb7af294d5d9 972 break;
Simon Cooksey 0:fb7af294d5d9 973 }
Simon Cooksey 0:fb7af294d5d9 974 }
Simon Cooksey 0:fb7af294d5d9 975
Simon Cooksey 0:fb7af294d5d9 976 #if defined(MBEDTLS_SSL_FALLBACK_SCSV)
Simon Cooksey 0:fb7af294d5d9 977 for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 )
Simon Cooksey 0:fb7af294d5d9 978 {
Simon Cooksey 0:fb7af294d5d9 979 if( p[0] == 0 &&
Simon Cooksey 0:fb7af294d5d9 980 p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) &&
Simon Cooksey 0:fb7af294d5d9 981 p[2] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) & 0xff ) )
Simon Cooksey 0:fb7af294d5d9 982 {
Simon Cooksey 0:fb7af294d5d9 983 MBEDTLS_SSL_DEBUG_MSG( 3, ( "received FALLBACK_SCSV" ) );
Simon Cooksey 0:fb7af294d5d9 984
Simon Cooksey 0:fb7af294d5d9 985 if( ssl->minor_ver < ssl->conf->max_minor_ver )
Simon Cooksey 0:fb7af294d5d9 986 {
Simon Cooksey 0:fb7af294d5d9 987 MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) );
Simon Cooksey 0:fb7af294d5d9 988
Simon Cooksey 0:fb7af294d5d9 989 mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
Simon Cooksey 0:fb7af294d5d9 990 MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK );
Simon Cooksey 0:fb7af294d5d9 991
Simon Cooksey 0:fb7af294d5d9 992 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 993 }
Simon Cooksey 0:fb7af294d5d9 994
Simon Cooksey 0:fb7af294d5d9 995 break;
Simon Cooksey 0:fb7af294d5d9 996 }
Simon Cooksey 0:fb7af294d5d9 997 }
Simon Cooksey 0:fb7af294d5d9 998 #endif /* MBEDTLS_SSL_FALLBACK_SCSV */
Simon Cooksey 0:fb7af294d5d9 999
Simon Cooksey 0:fb7af294d5d9 1000 got_common_suite = 0;
Simon Cooksey 0:fb7af294d5d9 1001 ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver];
Simon Cooksey 0:fb7af294d5d9 1002 ciphersuite_info = NULL;
Simon Cooksey 0:fb7af294d5d9 1003 #if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE)
Simon Cooksey 0:fb7af294d5d9 1004 for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 )
Simon Cooksey 0:fb7af294d5d9 1005 {
Simon Cooksey 0:fb7af294d5d9 1006 for( i = 0; ciphersuites[i] != 0; i++ )
Simon Cooksey 0:fb7af294d5d9 1007 #else
Simon Cooksey 0:fb7af294d5d9 1008 for( i = 0; ciphersuites[i] != 0; i++ )
Simon Cooksey 0:fb7af294d5d9 1009 {
Simon Cooksey 0:fb7af294d5d9 1010 for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 )
Simon Cooksey 0:fb7af294d5d9 1011 #endif
Simon Cooksey 0:fb7af294d5d9 1012 {
Simon Cooksey 0:fb7af294d5d9 1013 if( p[0] != 0 ||
Simon Cooksey 0:fb7af294d5d9 1014 p[1] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) ||
Simon Cooksey 0:fb7af294d5d9 1015 p[2] != ( ( ciphersuites[i] ) & 0xFF ) )
Simon Cooksey 0:fb7af294d5d9 1016 continue;
Simon Cooksey 0:fb7af294d5d9 1017
Simon Cooksey 0:fb7af294d5d9 1018 got_common_suite = 1;
Simon Cooksey 0:fb7af294d5d9 1019
Simon Cooksey 0:fb7af294d5d9 1020 if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i],
Simon Cooksey 0:fb7af294d5d9 1021 &ciphersuite_info ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1022 return( ret );
Simon Cooksey 0:fb7af294d5d9 1023
Simon Cooksey 0:fb7af294d5d9 1024 if( ciphersuite_info != NULL )
Simon Cooksey 0:fb7af294d5d9 1025 goto have_ciphersuite_v2;
Simon Cooksey 0:fb7af294d5d9 1026 }
Simon Cooksey 0:fb7af294d5d9 1027 }
Simon Cooksey 0:fb7af294d5d9 1028
Simon Cooksey 0:fb7af294d5d9 1029 if( got_common_suite )
Simon Cooksey 0:fb7af294d5d9 1030 {
Simon Cooksey 0:fb7af294d5d9 1031 MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, "
Simon Cooksey 0:fb7af294d5d9 1032 "but none of them usable" ) );
Simon Cooksey 0:fb7af294d5d9 1033 return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE );
Simon Cooksey 0:fb7af294d5d9 1034 }
Simon Cooksey 0:fb7af294d5d9 1035 else
Simon Cooksey 0:fb7af294d5d9 1036 {
Simon Cooksey 0:fb7af294d5d9 1037 MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) );
Simon Cooksey 0:fb7af294d5d9 1038 return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN );
Simon Cooksey 0:fb7af294d5d9 1039 }
Simon Cooksey 0:fb7af294d5d9 1040
Simon Cooksey 0:fb7af294d5d9 1041 have_ciphersuite_v2:
Simon Cooksey 0:fb7af294d5d9 1042 MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) );
Simon Cooksey 0:fb7af294d5d9 1043
Simon Cooksey 0:fb7af294d5d9 1044 ssl->session_negotiate->ciphersuite = ciphersuites[i];
Simon Cooksey 0:fb7af294d5d9 1045 ssl->transform_negotiate->ciphersuite_info = ciphersuite_info;
Simon Cooksey 0:fb7af294d5d9 1046
Simon Cooksey 0:fb7af294d5d9 1047 /*
Simon Cooksey 0:fb7af294d5d9 1048 * SSLv2 Client Hello relevant renegotiation security checks
Simon Cooksey 0:fb7af294d5d9 1049 */
Simon Cooksey 0:fb7af294d5d9 1050 if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
Simon Cooksey 0:fb7af294d5d9 1051 ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE )
Simon Cooksey 0:fb7af294d5d9 1052 {
Simon Cooksey 0:fb7af294d5d9 1053 MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
Simon Cooksey 0:fb7af294d5d9 1054
Simon Cooksey 0:fb7af294d5d9 1055 if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1056 return( ret );
Simon Cooksey 0:fb7af294d5d9 1057
Simon Cooksey 0:fb7af294d5d9 1058 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1059 }
Simon Cooksey 0:fb7af294d5d9 1060
Simon Cooksey 0:fb7af294d5d9 1061 ssl->in_left = 0;
Simon Cooksey 0:fb7af294d5d9 1062 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 1063
Simon Cooksey 0:fb7af294d5d9 1064 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello v2" ) );
Simon Cooksey 0:fb7af294d5d9 1065
Simon Cooksey 0:fb7af294d5d9 1066 return( 0 );
Simon Cooksey 0:fb7af294d5d9 1067 }
Simon Cooksey 0:fb7af294d5d9 1068 #endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */
Simon Cooksey 0:fb7af294d5d9 1069
Simon Cooksey 0:fb7af294d5d9 1070 static int ssl_parse_client_hello( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 1071 {
Simon Cooksey 0:fb7af294d5d9 1072 int ret, got_common_suite;
Simon Cooksey 0:fb7af294d5d9 1073 size_t i, j;
Simon Cooksey 0:fb7af294d5d9 1074 size_t ciph_offset, comp_offset, ext_offset;
Simon Cooksey 0:fb7af294d5d9 1075 size_t msg_len, ciph_len, sess_len, comp_len, ext_len;
Simon Cooksey 0:fb7af294d5d9 1076 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 1077 size_t cookie_offset, cookie_len;
Simon Cooksey 0:fb7af294d5d9 1078 #endif
Simon Cooksey 0:fb7af294d5d9 1079 unsigned char *buf, *p, *ext;
Simon Cooksey 0:fb7af294d5d9 1080 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 1081 int renegotiation_info_seen = 0;
Simon Cooksey 0:fb7af294d5d9 1082 #endif
Simon Cooksey 0:fb7af294d5d9 1083 int handshake_failure = 0;
Simon Cooksey 0:fb7af294d5d9 1084 const int *ciphersuites;
Simon Cooksey 0:fb7af294d5d9 1085 const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
Simon Cooksey 0:fb7af294d5d9 1086 int major, minor;
Simon Cooksey 0:fb7af294d5d9 1087
Simon Cooksey 0:fb7af294d5d9 1088 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) );
Simon Cooksey 0:fb7af294d5d9 1089
Simon Cooksey 0:fb7af294d5d9 1090 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
Simon Cooksey 0:fb7af294d5d9 1091 read_record_header:
Simon Cooksey 0:fb7af294d5d9 1092 #endif
Simon Cooksey 0:fb7af294d5d9 1093 /*
Simon Cooksey 0:fb7af294d5d9 1094 * If renegotiating, then the input was read with mbedtls_ssl_read_record(),
Simon Cooksey 0:fb7af294d5d9 1095 * otherwise read it ourselves manually in order to support SSLv2
Simon Cooksey 0:fb7af294d5d9 1096 * ClientHello, which doesn't use the same record layer format.
Simon Cooksey 0:fb7af294d5d9 1097 */
Simon Cooksey 0:fb7af294d5d9 1098 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 1099 if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
Simon Cooksey 0:fb7af294d5d9 1100 #endif
Simon Cooksey 0:fb7af294d5d9 1101 {
Simon Cooksey 0:fb7af294d5d9 1102 if( ( ret = mbedtls_ssl_fetch_input( ssl, 5 ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1103 {
Simon Cooksey 0:fb7af294d5d9 1104 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
Simon Cooksey 0:fb7af294d5d9 1105 return( ret );
Simon Cooksey 0:fb7af294d5d9 1106 }
Simon Cooksey 0:fb7af294d5d9 1107 }
Simon Cooksey 0:fb7af294d5d9 1108
Simon Cooksey 0:fb7af294d5d9 1109 buf = ssl->in_hdr;
Simon Cooksey 0:fb7af294d5d9 1110
Simon Cooksey 0:fb7af294d5d9 1111 #if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO)
Simon Cooksey 0:fb7af294d5d9 1112 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 1113 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM )
Simon Cooksey 0:fb7af294d5d9 1114 #endif
Simon Cooksey 0:fb7af294d5d9 1115 if( ( buf[0] & 0x80 ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1116 return ssl_parse_client_hello_v2( ssl );
Simon Cooksey 0:fb7af294d5d9 1117 #endif
Simon Cooksey 0:fb7af294d5d9 1118
Simon Cooksey 0:fb7af294d5d9 1119 MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, mbedtls_ssl_hdr_len( ssl ) );
Simon Cooksey 0:fb7af294d5d9 1120
Simon Cooksey 0:fb7af294d5d9 1121 /*
Simon Cooksey 0:fb7af294d5d9 1122 * SSLv3/TLS Client Hello
Simon Cooksey 0:fb7af294d5d9 1123 *
Simon Cooksey 0:fb7af294d5d9 1124 * Record layer:
Simon Cooksey 0:fb7af294d5d9 1125 * 0 . 0 message type
Simon Cooksey 0:fb7af294d5d9 1126 * 1 . 2 protocol version
Simon Cooksey 0:fb7af294d5d9 1127 * 3 . 11 DTLS: epoch + record sequence number
Simon Cooksey 0:fb7af294d5d9 1128 * 3 . 4 message length
Simon Cooksey 0:fb7af294d5d9 1129 */
Simon Cooksey 0:fb7af294d5d9 1130 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message type: %d",
Simon Cooksey 0:fb7af294d5d9 1131 buf[0] ) );
Simon Cooksey 0:fb7af294d5d9 1132
Simon Cooksey 0:fb7af294d5d9 1133 if( buf[0] != MBEDTLS_SSL_MSG_HANDSHAKE )
Simon Cooksey 0:fb7af294d5d9 1134 {
Simon Cooksey 0:fb7af294d5d9 1135 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1136 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1137 }
Simon Cooksey 0:fb7af294d5d9 1138
Simon Cooksey 0:fb7af294d5d9 1139 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message len.: %d",
Simon Cooksey 0:fb7af294d5d9 1140 ( ssl->in_len[0] << 8 ) | ssl->in_len[1] ) );
Simon Cooksey 0:fb7af294d5d9 1141
Simon Cooksey 0:fb7af294d5d9 1142 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, protocol version: [%d:%d]",
Simon Cooksey 0:fb7af294d5d9 1143 buf[1], buf[2] ) );
Simon Cooksey 0:fb7af294d5d9 1144
Simon Cooksey 0:fb7af294d5d9 1145 mbedtls_ssl_read_version( &major, &minor, ssl->conf->transport, buf + 1 );
Simon Cooksey 0:fb7af294d5d9 1146
Simon Cooksey 0:fb7af294d5d9 1147 /* According to RFC 5246 Appendix E.1, the version here is typically
Simon Cooksey 0:fb7af294d5d9 1148 * "{03,00}, the lowest version number supported by the client, [or] the
Simon Cooksey 0:fb7af294d5d9 1149 * value of ClientHello.client_version", so the only meaningful check here
Simon Cooksey 0:fb7af294d5d9 1150 * is the major version shouldn't be less than 3 */
Simon Cooksey 0:fb7af294d5d9 1151 if( major < MBEDTLS_SSL_MAJOR_VERSION_3 )
Simon Cooksey 0:fb7af294d5d9 1152 {
Simon Cooksey 0:fb7af294d5d9 1153 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1154 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1155 }
Simon Cooksey 0:fb7af294d5d9 1156
Simon Cooksey 0:fb7af294d5d9 1157 /* For DTLS if this is the initial handshake, remember the client sequence
Simon Cooksey 0:fb7af294d5d9 1158 * number to use it in our next message (RFC 6347 4.2.1) */
Simon Cooksey 0:fb7af294d5d9 1159 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 1160 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM
Simon Cooksey 0:fb7af294d5d9 1161 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 1162 && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE
Simon Cooksey 0:fb7af294d5d9 1163 #endif
Simon Cooksey 0:fb7af294d5d9 1164 )
Simon Cooksey 0:fb7af294d5d9 1165 {
Simon Cooksey 0:fb7af294d5d9 1166 /* Epoch should be 0 for initial handshakes */
Simon Cooksey 0:fb7af294d5d9 1167 if( ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0 )
Simon Cooksey 0:fb7af294d5d9 1168 {
Simon Cooksey 0:fb7af294d5d9 1169 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1170 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1171 }
Simon Cooksey 0:fb7af294d5d9 1172
Simon Cooksey 0:fb7af294d5d9 1173 memcpy( ssl->out_ctr + 2, ssl->in_ctr + 2, 6 );
Simon Cooksey 0:fb7af294d5d9 1174
Simon Cooksey 0:fb7af294d5d9 1175 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
Simon Cooksey 0:fb7af294d5d9 1176 if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1177 {
Simon Cooksey 0:fb7af294d5d9 1178 MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record, discarding" ) );
Simon Cooksey 0:fb7af294d5d9 1179 ssl->next_record_offset = 0;
Simon Cooksey 0:fb7af294d5d9 1180 ssl->in_left = 0;
Simon Cooksey 0:fb7af294d5d9 1181 goto read_record_header;
Simon Cooksey 0:fb7af294d5d9 1182 }
Simon Cooksey 0:fb7af294d5d9 1183
Simon Cooksey 0:fb7af294d5d9 1184 /* No MAC to check yet, so we can update right now */
Simon Cooksey 0:fb7af294d5d9 1185 mbedtls_ssl_dtls_replay_update( ssl );
Simon Cooksey 0:fb7af294d5d9 1186 #endif
Simon Cooksey 0:fb7af294d5d9 1187 }
Simon Cooksey 0:fb7af294d5d9 1188 #endif /* MBEDTLS_SSL_PROTO_DTLS */
Simon Cooksey 0:fb7af294d5d9 1189
Simon Cooksey 0:fb7af294d5d9 1190 msg_len = ( ssl->in_len[0] << 8 ) | ssl->in_len[1];
Simon Cooksey 0:fb7af294d5d9 1191
Simon Cooksey 0:fb7af294d5d9 1192 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 1193 if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
Simon Cooksey 0:fb7af294d5d9 1194 {
Simon Cooksey 0:fb7af294d5d9 1195 /* Set by mbedtls_ssl_read_record() */
Simon Cooksey 0:fb7af294d5d9 1196 msg_len = ssl->in_hslen;
Simon Cooksey 0:fb7af294d5d9 1197 }
Simon Cooksey 0:fb7af294d5d9 1198 else
Simon Cooksey 0:fb7af294d5d9 1199 #endif
Simon Cooksey 0:fb7af294d5d9 1200 {
Simon Cooksey 0:fb7af294d5d9 1201 if( msg_len > MBEDTLS_SSL_MAX_CONTENT_LEN )
Simon Cooksey 0:fb7af294d5d9 1202 {
Simon Cooksey 0:fb7af294d5d9 1203 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1204 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1205 }
Simon Cooksey 0:fb7af294d5d9 1206
Simon Cooksey 0:fb7af294d5d9 1207 if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) + msg_len ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1208 {
Simon Cooksey 0:fb7af294d5d9 1209 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
Simon Cooksey 0:fb7af294d5d9 1210 return( ret );
Simon Cooksey 0:fb7af294d5d9 1211 }
Simon Cooksey 0:fb7af294d5d9 1212
Simon Cooksey 0:fb7af294d5d9 1213 /* Done reading this record, get ready for the next one */
Simon Cooksey 0:fb7af294d5d9 1214 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 1215 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
Simon Cooksey 0:fb7af294d5d9 1216 ssl->next_record_offset = msg_len + mbedtls_ssl_hdr_len( ssl );
Simon Cooksey 0:fb7af294d5d9 1217 else
Simon Cooksey 0:fb7af294d5d9 1218 #endif
Simon Cooksey 0:fb7af294d5d9 1219 ssl->in_left = 0;
Simon Cooksey 0:fb7af294d5d9 1220 }
Simon Cooksey 0:fb7af294d5d9 1221
Simon Cooksey 0:fb7af294d5d9 1222 buf = ssl->in_msg;
Simon Cooksey 0:fb7af294d5d9 1223
Simon Cooksey 0:fb7af294d5d9 1224 MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, msg_len );
Simon Cooksey 0:fb7af294d5d9 1225
Simon Cooksey 0:fb7af294d5d9 1226 ssl->handshake->update_checksum( ssl, buf, msg_len );
Simon Cooksey 0:fb7af294d5d9 1227
Simon Cooksey 0:fb7af294d5d9 1228 /*
Simon Cooksey 0:fb7af294d5d9 1229 * Handshake layer:
Simon Cooksey 0:fb7af294d5d9 1230 * 0 . 0 handshake type
Simon Cooksey 0:fb7af294d5d9 1231 * 1 . 3 handshake length
Simon Cooksey 0:fb7af294d5d9 1232 * 4 . 5 DTLS only: message seqence number
Simon Cooksey 0:fb7af294d5d9 1233 * 6 . 8 DTLS only: fragment offset
Simon Cooksey 0:fb7af294d5d9 1234 * 9 . 11 DTLS only: fragment length
Simon Cooksey 0:fb7af294d5d9 1235 */
Simon Cooksey 0:fb7af294d5d9 1236 if( msg_len < mbedtls_ssl_hs_hdr_len( ssl ) )
Simon Cooksey 0:fb7af294d5d9 1237 {
Simon Cooksey 0:fb7af294d5d9 1238 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1239 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1240 }
Simon Cooksey 0:fb7af294d5d9 1241
Simon Cooksey 0:fb7af294d5d9 1242 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake type: %d", buf[0] ) );
Simon Cooksey 0:fb7af294d5d9 1243
Simon Cooksey 0:fb7af294d5d9 1244 if( buf[0] != MBEDTLS_SSL_HS_CLIENT_HELLO )
Simon Cooksey 0:fb7af294d5d9 1245 {
Simon Cooksey 0:fb7af294d5d9 1246 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1247 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1248 }
Simon Cooksey 0:fb7af294d5d9 1249
Simon Cooksey 0:fb7af294d5d9 1250 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d",
Simon Cooksey 0:fb7af294d5d9 1251 ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) );
Simon Cooksey 0:fb7af294d5d9 1252
Simon Cooksey 0:fb7af294d5d9 1253 /* We don't support fragmentation of ClientHello (yet?) */
Simon Cooksey 0:fb7af294d5d9 1254 if( buf[1] != 0 ||
Simon Cooksey 0:fb7af294d5d9 1255 msg_len != mbedtls_ssl_hs_hdr_len( ssl ) + ( ( buf[2] << 8 ) | buf[3] ) )
Simon Cooksey 0:fb7af294d5d9 1256 {
Simon Cooksey 0:fb7af294d5d9 1257 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1258 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1259 }
Simon Cooksey 0:fb7af294d5d9 1260
Simon Cooksey 0:fb7af294d5d9 1261 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 1262 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
Simon Cooksey 0:fb7af294d5d9 1263 {
Simon Cooksey 0:fb7af294d5d9 1264 /*
Simon Cooksey 0:fb7af294d5d9 1265 * Copy the client's handshake message_seq on initial handshakes,
Simon Cooksey 0:fb7af294d5d9 1266 * check sequence number on renego.
Simon Cooksey 0:fb7af294d5d9 1267 */
Simon Cooksey 0:fb7af294d5d9 1268 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 1269 if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
Simon Cooksey 0:fb7af294d5d9 1270 {
Simon Cooksey 0:fb7af294d5d9 1271 /* This couldn't be done in ssl_prepare_handshake_record() */
Simon Cooksey 0:fb7af294d5d9 1272 unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) |
Simon Cooksey 0:fb7af294d5d9 1273 ssl->in_msg[5];
Simon Cooksey 0:fb7af294d5d9 1274
Simon Cooksey 0:fb7af294d5d9 1275 if( cli_msg_seq != ssl->handshake->in_msg_seq )
Simon Cooksey 0:fb7af294d5d9 1276 {
Simon Cooksey 0:fb7af294d5d9 1277 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message_seq: "
Simon Cooksey 0:fb7af294d5d9 1278 "%d (expected %d)", cli_msg_seq,
Simon Cooksey 0:fb7af294d5d9 1279 ssl->handshake->in_msg_seq ) );
Simon Cooksey 0:fb7af294d5d9 1280 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1281 }
Simon Cooksey 0:fb7af294d5d9 1282
Simon Cooksey 0:fb7af294d5d9 1283 ssl->handshake->in_msg_seq++;
Simon Cooksey 0:fb7af294d5d9 1284 }
Simon Cooksey 0:fb7af294d5d9 1285 else
Simon Cooksey 0:fb7af294d5d9 1286 #endif
Simon Cooksey 0:fb7af294d5d9 1287 {
Simon Cooksey 0:fb7af294d5d9 1288 unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) |
Simon Cooksey 0:fb7af294d5d9 1289 ssl->in_msg[5];
Simon Cooksey 0:fb7af294d5d9 1290 ssl->handshake->out_msg_seq = cli_msg_seq;
Simon Cooksey 0:fb7af294d5d9 1291 ssl->handshake->in_msg_seq = cli_msg_seq + 1;
Simon Cooksey 0:fb7af294d5d9 1292 }
Simon Cooksey 0:fb7af294d5d9 1293
Simon Cooksey 0:fb7af294d5d9 1294 /*
Simon Cooksey 0:fb7af294d5d9 1295 * For now we don't support fragmentation, so make sure
Simon Cooksey 0:fb7af294d5d9 1296 * fragment_offset == 0 and fragment_length == length
Simon Cooksey 0:fb7af294d5d9 1297 */
Simon Cooksey 0:fb7af294d5d9 1298 if( ssl->in_msg[6] != 0 || ssl->in_msg[7] != 0 || ssl->in_msg[8] != 0 ||
Simon Cooksey 0:fb7af294d5d9 1299 memcmp( ssl->in_msg + 1, ssl->in_msg + 9, 3 ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1300 {
Simon Cooksey 0:fb7af294d5d9 1301 MBEDTLS_SSL_DEBUG_MSG( 1, ( "ClientHello fragmentation not supported" ) );
Simon Cooksey 0:fb7af294d5d9 1302 return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
Simon Cooksey 0:fb7af294d5d9 1303 }
Simon Cooksey 0:fb7af294d5d9 1304 }
Simon Cooksey 0:fb7af294d5d9 1305 #endif /* MBEDTLS_SSL_PROTO_DTLS */
Simon Cooksey 0:fb7af294d5d9 1306
Simon Cooksey 0:fb7af294d5d9 1307 buf += mbedtls_ssl_hs_hdr_len( ssl );
Simon Cooksey 0:fb7af294d5d9 1308 msg_len -= mbedtls_ssl_hs_hdr_len( ssl );
Simon Cooksey 0:fb7af294d5d9 1309
Simon Cooksey 0:fb7af294d5d9 1310 /*
Simon Cooksey 0:fb7af294d5d9 1311 * ClientHello layer:
Simon Cooksey 0:fb7af294d5d9 1312 * 0 . 1 protocol version
Simon Cooksey 0:fb7af294d5d9 1313 * 2 . 33 random bytes (starting with 4 bytes of Unix time)
Simon Cooksey 0:fb7af294d5d9 1314 * 34 . 35 session id length (1 byte)
Simon Cooksey 0:fb7af294d5d9 1315 * 35 . 34+x session id
Simon Cooksey 0:fb7af294d5d9 1316 * 35+x . 35+x DTLS only: cookie length (1 byte)
Simon Cooksey 0:fb7af294d5d9 1317 * 36+x . .. DTLS only: cookie
Simon Cooksey 0:fb7af294d5d9 1318 * .. . .. ciphersuite list length (2 bytes)
Simon Cooksey 0:fb7af294d5d9 1319 * .. . .. ciphersuite list
Simon Cooksey 0:fb7af294d5d9 1320 * .. . .. compression alg. list length (1 byte)
Simon Cooksey 0:fb7af294d5d9 1321 * .. . .. compression alg. list
Simon Cooksey 0:fb7af294d5d9 1322 * .. . .. extensions length (2 bytes, optional)
Simon Cooksey 0:fb7af294d5d9 1323 * .. . .. extensions (optional)
Simon Cooksey 0:fb7af294d5d9 1324 */
Simon Cooksey 0:fb7af294d5d9 1325
Simon Cooksey 0:fb7af294d5d9 1326 /*
Simon Cooksey 0:fb7af294d5d9 1327 * Minimal length (with everything empty and extensions ommitted) is
Simon Cooksey 0:fb7af294d5d9 1328 * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can
Simon Cooksey 0:fb7af294d5d9 1329 * read at least up to session id length without worrying.
Simon Cooksey 0:fb7af294d5d9 1330 */
Simon Cooksey 0:fb7af294d5d9 1331 if( msg_len < 38 )
Simon Cooksey 0:fb7af294d5d9 1332 {
Simon Cooksey 0:fb7af294d5d9 1333 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1334 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1335 }
Simon Cooksey 0:fb7af294d5d9 1336
Simon Cooksey 0:fb7af294d5d9 1337 /*
Simon Cooksey 0:fb7af294d5d9 1338 * Check and save the protocol version
Simon Cooksey 0:fb7af294d5d9 1339 */
Simon Cooksey 0:fb7af294d5d9 1340 MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, version", buf, 2 );
Simon Cooksey 0:fb7af294d5d9 1341
Simon Cooksey 0:fb7af294d5d9 1342 mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver,
Simon Cooksey 0:fb7af294d5d9 1343 ssl->conf->transport, buf );
Simon Cooksey 0:fb7af294d5d9 1344
Simon Cooksey 0:fb7af294d5d9 1345 ssl->handshake->max_major_ver = ssl->major_ver;
Simon Cooksey 0:fb7af294d5d9 1346 ssl->handshake->max_minor_ver = ssl->minor_ver;
Simon Cooksey 0:fb7af294d5d9 1347
Simon Cooksey 0:fb7af294d5d9 1348 if( ssl->major_ver < ssl->conf->min_major_ver ||
Simon Cooksey 0:fb7af294d5d9 1349 ssl->minor_ver < ssl->conf->min_minor_ver )
Simon Cooksey 0:fb7af294d5d9 1350 {
Simon Cooksey 0:fb7af294d5d9 1351 MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum"
Simon Cooksey 0:fb7af294d5d9 1352 " [%d:%d] < [%d:%d]",
Simon Cooksey 0:fb7af294d5d9 1353 ssl->major_ver, ssl->minor_ver,
Simon Cooksey 0:fb7af294d5d9 1354 ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) );
Simon Cooksey 0:fb7af294d5d9 1355
Simon Cooksey 0:fb7af294d5d9 1356 mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
Simon Cooksey 0:fb7af294d5d9 1357 MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION );
Simon Cooksey 0:fb7af294d5d9 1358
Simon Cooksey 0:fb7af294d5d9 1359 return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION );
Simon Cooksey 0:fb7af294d5d9 1360 }
Simon Cooksey 0:fb7af294d5d9 1361
Simon Cooksey 0:fb7af294d5d9 1362 if( ssl->major_ver > ssl->conf->max_major_ver )
Simon Cooksey 0:fb7af294d5d9 1363 {
Simon Cooksey 0:fb7af294d5d9 1364 ssl->major_ver = ssl->conf->max_major_ver;
Simon Cooksey 0:fb7af294d5d9 1365 ssl->minor_ver = ssl->conf->max_minor_ver;
Simon Cooksey 0:fb7af294d5d9 1366 }
Simon Cooksey 0:fb7af294d5d9 1367 else if( ssl->minor_ver > ssl->conf->max_minor_ver )
Simon Cooksey 0:fb7af294d5d9 1368 ssl->minor_ver = ssl->conf->max_minor_ver;
Simon Cooksey 0:fb7af294d5d9 1369
Simon Cooksey 0:fb7af294d5d9 1370 /*
Simon Cooksey 0:fb7af294d5d9 1371 * Save client random (inc. Unix time)
Simon Cooksey 0:fb7af294d5d9 1372 */
Simon Cooksey 0:fb7af294d5d9 1373 MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 2, 32 );
Simon Cooksey 0:fb7af294d5d9 1374
Simon Cooksey 0:fb7af294d5d9 1375 memcpy( ssl->handshake->randbytes, buf + 2, 32 );
Simon Cooksey 0:fb7af294d5d9 1376
Simon Cooksey 0:fb7af294d5d9 1377 /*
Simon Cooksey 0:fb7af294d5d9 1378 * Check the session ID length and save session ID
Simon Cooksey 0:fb7af294d5d9 1379 */
Simon Cooksey 0:fb7af294d5d9 1380 sess_len = buf[34];
Simon Cooksey 0:fb7af294d5d9 1381
Simon Cooksey 0:fb7af294d5d9 1382 if( sess_len > sizeof( ssl->session_negotiate->id ) ||
Simon Cooksey 0:fb7af294d5d9 1383 sess_len + 34 + 2 > msg_len ) /* 2 for cipherlist length field */
Simon Cooksey 0:fb7af294d5d9 1384 {
Simon Cooksey 0:fb7af294d5d9 1385 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1386 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1387 }
Simon Cooksey 0:fb7af294d5d9 1388
Simon Cooksey 0:fb7af294d5d9 1389 MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 35, sess_len );
Simon Cooksey 0:fb7af294d5d9 1390
Simon Cooksey 0:fb7af294d5d9 1391 ssl->session_negotiate->id_len = sess_len;
Simon Cooksey 0:fb7af294d5d9 1392 memset( ssl->session_negotiate->id, 0,
Simon Cooksey 0:fb7af294d5d9 1393 sizeof( ssl->session_negotiate->id ) );
Simon Cooksey 0:fb7af294d5d9 1394 memcpy( ssl->session_negotiate->id, buf + 35,
Simon Cooksey 0:fb7af294d5d9 1395 ssl->session_negotiate->id_len );
Simon Cooksey 0:fb7af294d5d9 1396
Simon Cooksey 0:fb7af294d5d9 1397 /*
Simon Cooksey 0:fb7af294d5d9 1398 * Check the cookie length and content
Simon Cooksey 0:fb7af294d5d9 1399 */
Simon Cooksey 0:fb7af294d5d9 1400 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 1401 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
Simon Cooksey 0:fb7af294d5d9 1402 {
Simon Cooksey 0:fb7af294d5d9 1403 cookie_offset = 35 + sess_len;
Simon Cooksey 0:fb7af294d5d9 1404 cookie_len = buf[cookie_offset];
Simon Cooksey 0:fb7af294d5d9 1405
Simon Cooksey 0:fb7af294d5d9 1406 if( cookie_offset + 1 + cookie_len + 2 > msg_len )
Simon Cooksey 0:fb7af294d5d9 1407 {
Simon Cooksey 0:fb7af294d5d9 1408 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1409 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1410 }
Simon Cooksey 0:fb7af294d5d9 1411
Simon Cooksey 0:fb7af294d5d9 1412 MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie",
Simon Cooksey 0:fb7af294d5d9 1413 buf + cookie_offset + 1, cookie_len );
Simon Cooksey 0:fb7af294d5d9 1414
Simon Cooksey 0:fb7af294d5d9 1415 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
Simon Cooksey 0:fb7af294d5d9 1416 if( ssl->conf->f_cookie_check != NULL
Simon Cooksey 0:fb7af294d5d9 1417 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 1418 && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE
Simon Cooksey 0:fb7af294d5d9 1419 #endif
Simon Cooksey 0:fb7af294d5d9 1420 )
Simon Cooksey 0:fb7af294d5d9 1421 {
Simon Cooksey 0:fb7af294d5d9 1422 if( ssl->conf->f_cookie_check( ssl->conf->p_cookie,
Simon Cooksey 0:fb7af294d5d9 1423 buf + cookie_offset + 1, cookie_len,
Simon Cooksey 0:fb7af294d5d9 1424 ssl->cli_id, ssl->cli_id_len ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1425 {
Simon Cooksey 0:fb7af294d5d9 1426 MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification failed" ) );
Simon Cooksey 0:fb7af294d5d9 1427 ssl->handshake->verify_cookie_len = 1;
Simon Cooksey 0:fb7af294d5d9 1428 }
Simon Cooksey 0:fb7af294d5d9 1429 else
Simon Cooksey 0:fb7af294d5d9 1430 {
Simon Cooksey 0:fb7af294d5d9 1431 MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification passed" ) );
Simon Cooksey 0:fb7af294d5d9 1432 ssl->handshake->verify_cookie_len = 0;
Simon Cooksey 0:fb7af294d5d9 1433 }
Simon Cooksey 0:fb7af294d5d9 1434 }
Simon Cooksey 0:fb7af294d5d9 1435 else
Simon Cooksey 0:fb7af294d5d9 1436 #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
Simon Cooksey 0:fb7af294d5d9 1437 {
Simon Cooksey 0:fb7af294d5d9 1438 /* We know we didn't send a cookie, so it should be empty */
Simon Cooksey 0:fb7af294d5d9 1439 if( cookie_len != 0 )
Simon Cooksey 0:fb7af294d5d9 1440 {
Simon Cooksey 0:fb7af294d5d9 1441 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1442 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1443 }
Simon Cooksey 0:fb7af294d5d9 1444
Simon Cooksey 0:fb7af294d5d9 1445 MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification skipped" ) );
Simon Cooksey 0:fb7af294d5d9 1446 }
Simon Cooksey 0:fb7af294d5d9 1447
Simon Cooksey 0:fb7af294d5d9 1448 /*
Simon Cooksey 0:fb7af294d5d9 1449 * Check the ciphersuitelist length (will be parsed later)
Simon Cooksey 0:fb7af294d5d9 1450 */
Simon Cooksey 0:fb7af294d5d9 1451 ciph_offset = cookie_offset + 1 + cookie_len;
Simon Cooksey 0:fb7af294d5d9 1452 }
Simon Cooksey 0:fb7af294d5d9 1453 else
Simon Cooksey 0:fb7af294d5d9 1454 #endif /* MBEDTLS_SSL_PROTO_DTLS */
Simon Cooksey 0:fb7af294d5d9 1455 ciph_offset = 35 + sess_len;
Simon Cooksey 0:fb7af294d5d9 1456
Simon Cooksey 0:fb7af294d5d9 1457 ciph_len = ( buf[ciph_offset + 0] << 8 )
Simon Cooksey 0:fb7af294d5d9 1458 | ( buf[ciph_offset + 1] );
Simon Cooksey 0:fb7af294d5d9 1459
Simon Cooksey 0:fb7af294d5d9 1460 if( ciph_len < 2 ||
Simon Cooksey 0:fb7af294d5d9 1461 ciph_len + 2 + ciph_offset + 1 > msg_len || /* 1 for comp. alg. len */
Simon Cooksey 0:fb7af294d5d9 1462 ( ciph_len % 2 ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1463 {
Simon Cooksey 0:fb7af294d5d9 1464 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1465 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1466 }
Simon Cooksey 0:fb7af294d5d9 1467
Simon Cooksey 0:fb7af294d5d9 1468 MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist",
Simon Cooksey 0:fb7af294d5d9 1469 buf + ciph_offset + 2, ciph_len );
Simon Cooksey 0:fb7af294d5d9 1470
Simon Cooksey 0:fb7af294d5d9 1471 /*
Simon Cooksey 0:fb7af294d5d9 1472 * Check the compression algorithms length and pick one
Simon Cooksey 0:fb7af294d5d9 1473 */
Simon Cooksey 0:fb7af294d5d9 1474 comp_offset = ciph_offset + 2 + ciph_len;
Simon Cooksey 0:fb7af294d5d9 1475
Simon Cooksey 0:fb7af294d5d9 1476 comp_len = buf[comp_offset];
Simon Cooksey 0:fb7af294d5d9 1477
Simon Cooksey 0:fb7af294d5d9 1478 if( comp_len < 1 ||
Simon Cooksey 0:fb7af294d5d9 1479 comp_len > 16 ||
Simon Cooksey 0:fb7af294d5d9 1480 comp_len + comp_offset + 1 > msg_len )
Simon Cooksey 0:fb7af294d5d9 1481 {
Simon Cooksey 0:fb7af294d5d9 1482 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1483 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1484 }
Simon Cooksey 0:fb7af294d5d9 1485
Simon Cooksey 0:fb7af294d5d9 1486 MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, compression",
Simon Cooksey 0:fb7af294d5d9 1487 buf + comp_offset + 1, comp_len );
Simon Cooksey 0:fb7af294d5d9 1488
Simon Cooksey 0:fb7af294d5d9 1489 ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL;
Simon Cooksey 0:fb7af294d5d9 1490 #if defined(MBEDTLS_ZLIB_SUPPORT)
Simon Cooksey 0:fb7af294d5d9 1491 for( i = 0; i < comp_len; ++i )
Simon Cooksey 0:fb7af294d5d9 1492 {
Simon Cooksey 0:fb7af294d5d9 1493 if( buf[comp_offset + 1 + i] == MBEDTLS_SSL_COMPRESS_DEFLATE )
Simon Cooksey 0:fb7af294d5d9 1494 {
Simon Cooksey 0:fb7af294d5d9 1495 ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_DEFLATE;
Simon Cooksey 0:fb7af294d5d9 1496 break;
Simon Cooksey 0:fb7af294d5d9 1497 }
Simon Cooksey 0:fb7af294d5d9 1498 }
Simon Cooksey 0:fb7af294d5d9 1499 #endif
Simon Cooksey 0:fb7af294d5d9 1500
Simon Cooksey 0:fb7af294d5d9 1501 /* See comments in ssl_write_client_hello() */
Simon Cooksey 0:fb7af294d5d9 1502 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 1503 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
Simon Cooksey 0:fb7af294d5d9 1504 ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL;
Simon Cooksey 0:fb7af294d5d9 1505 #endif
Simon Cooksey 0:fb7af294d5d9 1506
Simon Cooksey 0:fb7af294d5d9 1507 /* Do not parse the extensions if the protocol is SSLv3 */
Simon Cooksey 0:fb7af294d5d9 1508 #if defined(MBEDTLS_SSL_PROTO_SSL3)
Simon Cooksey 0:fb7af294d5d9 1509 if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) )
Simon Cooksey 0:fb7af294d5d9 1510 {
Simon Cooksey 0:fb7af294d5d9 1511 #endif
Simon Cooksey 0:fb7af294d5d9 1512 /*
Simon Cooksey 0:fb7af294d5d9 1513 * Check the extension length
Simon Cooksey 0:fb7af294d5d9 1514 */
Simon Cooksey 0:fb7af294d5d9 1515 ext_offset = comp_offset + 1 + comp_len;
Simon Cooksey 0:fb7af294d5d9 1516 if( msg_len > ext_offset )
Simon Cooksey 0:fb7af294d5d9 1517 {
Simon Cooksey 0:fb7af294d5d9 1518 if( msg_len < ext_offset + 2 )
Simon Cooksey 0:fb7af294d5d9 1519 {
Simon Cooksey 0:fb7af294d5d9 1520 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1521 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1522 }
Simon Cooksey 0:fb7af294d5d9 1523
Simon Cooksey 0:fb7af294d5d9 1524 ext_len = ( buf[ext_offset + 0] << 8 )
Simon Cooksey 0:fb7af294d5d9 1525 | ( buf[ext_offset + 1] );
Simon Cooksey 0:fb7af294d5d9 1526
Simon Cooksey 0:fb7af294d5d9 1527 if( ( ext_len > 0 && ext_len < 4 ) ||
Simon Cooksey 0:fb7af294d5d9 1528 msg_len != ext_offset + 2 + ext_len )
Simon Cooksey 0:fb7af294d5d9 1529 {
Simon Cooksey 0:fb7af294d5d9 1530 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1531 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1532 }
Simon Cooksey 0:fb7af294d5d9 1533 }
Simon Cooksey 0:fb7af294d5d9 1534 else
Simon Cooksey 0:fb7af294d5d9 1535 ext_len = 0;
Simon Cooksey 0:fb7af294d5d9 1536
Simon Cooksey 0:fb7af294d5d9 1537 ext = buf + ext_offset + 2;
Simon Cooksey 0:fb7af294d5d9 1538 MBEDTLS_SSL_DEBUG_BUF( 3, "client hello extensions", ext, ext_len );
Simon Cooksey 0:fb7af294d5d9 1539
Simon Cooksey 0:fb7af294d5d9 1540 while( ext_len != 0 )
Simon Cooksey 0:fb7af294d5d9 1541 {
Simon Cooksey 0:fb7af294d5d9 1542 unsigned int ext_id = ( ( ext[0] << 8 )
Simon Cooksey 0:fb7af294d5d9 1543 | ( ext[1] ) );
Simon Cooksey 0:fb7af294d5d9 1544 unsigned int ext_size = ( ( ext[2] << 8 )
Simon Cooksey 0:fb7af294d5d9 1545 | ( ext[3] ) );
Simon Cooksey 0:fb7af294d5d9 1546
Simon Cooksey 0:fb7af294d5d9 1547 if( ext_size + 4 > ext_len )
Simon Cooksey 0:fb7af294d5d9 1548 {
Simon Cooksey 0:fb7af294d5d9 1549 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1550 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1551 }
Simon Cooksey 0:fb7af294d5d9 1552 switch( ext_id )
Simon Cooksey 0:fb7af294d5d9 1553 {
Simon Cooksey 0:fb7af294d5d9 1554 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
Simon Cooksey 0:fb7af294d5d9 1555 case MBEDTLS_TLS_EXT_SERVERNAME:
Simon Cooksey 0:fb7af294d5d9 1556 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) );
Simon Cooksey 0:fb7af294d5d9 1557 if( ssl->conf->f_sni == NULL )
Simon Cooksey 0:fb7af294d5d9 1558 break;
Simon Cooksey 0:fb7af294d5d9 1559
Simon Cooksey 0:fb7af294d5d9 1560 ret = ssl_parse_servername_ext( ssl, ext + 4, ext_size );
Simon Cooksey 0:fb7af294d5d9 1561 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 1562 return( ret );
Simon Cooksey 0:fb7af294d5d9 1563 break;
Simon Cooksey 0:fb7af294d5d9 1564 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
Simon Cooksey 0:fb7af294d5d9 1565
Simon Cooksey 0:fb7af294d5d9 1566 case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO:
Simon Cooksey 0:fb7af294d5d9 1567 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) );
Simon Cooksey 0:fb7af294d5d9 1568 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 1569 renegotiation_info_seen = 1;
Simon Cooksey 0:fb7af294d5d9 1570 #endif
Simon Cooksey 0:fb7af294d5d9 1571
Simon Cooksey 0:fb7af294d5d9 1572 ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size );
Simon Cooksey 0:fb7af294d5d9 1573 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 1574 return( ret );
Simon Cooksey 0:fb7af294d5d9 1575 break;
Simon Cooksey 0:fb7af294d5d9 1576
Simon Cooksey 0:fb7af294d5d9 1577 #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
Simon Cooksey 0:fb7af294d5d9 1578 defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
Simon Cooksey 0:fb7af294d5d9 1579 case MBEDTLS_TLS_EXT_SIG_ALG:
Simon Cooksey 0:fb7af294d5d9 1580 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) );
Simon Cooksey 0:fb7af294d5d9 1581 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 1582 if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
Simon Cooksey 0:fb7af294d5d9 1583 break;
Simon Cooksey 0:fb7af294d5d9 1584 #endif
Simon Cooksey 0:fb7af294d5d9 1585
Simon Cooksey 0:fb7af294d5d9 1586 ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size );
Simon Cooksey 0:fb7af294d5d9 1587 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 1588 return( ret );
Simon Cooksey 0:fb7af294d5d9 1589 break;
Simon Cooksey 0:fb7af294d5d9 1590 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 &&
Simon Cooksey 0:fb7af294d5d9 1591 MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */
Simon Cooksey 0:fb7af294d5d9 1592
Simon Cooksey 0:fb7af294d5d9 1593 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
Simon Cooksey 0:fb7af294d5d9 1594 defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 1595 case MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES:
Simon Cooksey 0:fb7af294d5d9 1596 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported elliptic curves extension" ) );
Simon Cooksey 0:fb7af294d5d9 1597
Simon Cooksey 0:fb7af294d5d9 1598 ret = ssl_parse_supported_elliptic_curves( ssl, ext + 4, ext_size );
Simon Cooksey 0:fb7af294d5d9 1599 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 1600 return( ret );
Simon Cooksey 0:fb7af294d5d9 1601 break;
Simon Cooksey 0:fb7af294d5d9 1602
Simon Cooksey 0:fb7af294d5d9 1603 case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS:
Simon Cooksey 0:fb7af294d5d9 1604 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported point formats extension" ) );
Simon Cooksey 0:fb7af294d5d9 1605 ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT;
Simon Cooksey 0:fb7af294d5d9 1606
Simon Cooksey 0:fb7af294d5d9 1607 ret = ssl_parse_supported_point_formats( ssl, ext + 4, ext_size );
Simon Cooksey 0:fb7af294d5d9 1608 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 1609 return( ret );
Simon Cooksey 0:fb7af294d5d9 1610 break;
Simon Cooksey 0:fb7af294d5d9 1611 #endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
Simon Cooksey 0:fb7af294d5d9 1612 MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
Simon Cooksey 0:fb7af294d5d9 1613
Simon Cooksey 0:fb7af294d5d9 1614 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 1615 case MBEDTLS_TLS_EXT_ECJPAKE_KKPP:
Simon Cooksey 0:fb7af294d5d9 1616 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake kkpp extension" ) );
Simon Cooksey 0:fb7af294d5d9 1617
Simon Cooksey 0:fb7af294d5d9 1618 ret = ssl_parse_ecjpake_kkpp( ssl, ext + 4, ext_size );
Simon Cooksey 0:fb7af294d5d9 1619 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 1620 return( ret );
Simon Cooksey 0:fb7af294d5d9 1621 break;
Simon Cooksey 0:fb7af294d5d9 1622 #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
Simon Cooksey 0:fb7af294d5d9 1623
Simon Cooksey 0:fb7af294d5d9 1624 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
Simon Cooksey 0:fb7af294d5d9 1625 case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH:
Simon Cooksey 0:fb7af294d5d9 1626 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max fragment length extension" ) );
Simon Cooksey 0:fb7af294d5d9 1627
Simon Cooksey 0:fb7af294d5d9 1628 ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size );
Simon Cooksey 0:fb7af294d5d9 1629 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 1630 return( ret );
Simon Cooksey 0:fb7af294d5d9 1631 break;
Simon Cooksey 0:fb7af294d5d9 1632 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
Simon Cooksey 0:fb7af294d5d9 1633
Simon Cooksey 0:fb7af294d5d9 1634 #if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
Simon Cooksey 0:fb7af294d5d9 1635 case MBEDTLS_TLS_EXT_TRUNCATED_HMAC:
Simon Cooksey 0:fb7af294d5d9 1636 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated hmac extension" ) );
Simon Cooksey 0:fb7af294d5d9 1637
Simon Cooksey 0:fb7af294d5d9 1638 ret = ssl_parse_truncated_hmac_ext( ssl, ext + 4, ext_size );
Simon Cooksey 0:fb7af294d5d9 1639 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 1640 return( ret );
Simon Cooksey 0:fb7af294d5d9 1641 break;
Simon Cooksey 0:fb7af294d5d9 1642 #endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
Simon Cooksey 0:fb7af294d5d9 1643
Simon Cooksey 0:fb7af294d5d9 1644 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
Simon Cooksey 0:fb7af294d5d9 1645 case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC:
Simon Cooksey 0:fb7af294d5d9 1646 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt then mac extension" ) );
Simon Cooksey 0:fb7af294d5d9 1647
Simon Cooksey 0:fb7af294d5d9 1648 ret = ssl_parse_encrypt_then_mac_ext( ssl, ext + 4, ext_size );
Simon Cooksey 0:fb7af294d5d9 1649 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 1650 return( ret );
Simon Cooksey 0:fb7af294d5d9 1651 break;
Simon Cooksey 0:fb7af294d5d9 1652 #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
Simon Cooksey 0:fb7af294d5d9 1653
Simon Cooksey 0:fb7af294d5d9 1654 #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
Simon Cooksey 0:fb7af294d5d9 1655 case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET:
Simon Cooksey 0:fb7af294d5d9 1656 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended master secret extension" ) );
Simon Cooksey 0:fb7af294d5d9 1657
Simon Cooksey 0:fb7af294d5d9 1658 ret = ssl_parse_extended_ms_ext( ssl, ext + 4, ext_size );
Simon Cooksey 0:fb7af294d5d9 1659 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 1660 return( ret );
Simon Cooksey 0:fb7af294d5d9 1661 break;
Simon Cooksey 0:fb7af294d5d9 1662 #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
Simon Cooksey 0:fb7af294d5d9 1663
Simon Cooksey 0:fb7af294d5d9 1664 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
Simon Cooksey 0:fb7af294d5d9 1665 case MBEDTLS_TLS_EXT_SESSION_TICKET:
Simon Cooksey 0:fb7af294d5d9 1666 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session ticket extension" ) );
Simon Cooksey 0:fb7af294d5d9 1667
Simon Cooksey 0:fb7af294d5d9 1668 ret = ssl_parse_session_ticket_ext( ssl, ext + 4, ext_size );
Simon Cooksey 0:fb7af294d5d9 1669 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 1670 return( ret );
Simon Cooksey 0:fb7af294d5d9 1671 break;
Simon Cooksey 0:fb7af294d5d9 1672 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
Simon Cooksey 0:fb7af294d5d9 1673
Simon Cooksey 0:fb7af294d5d9 1674 #if defined(MBEDTLS_SSL_ALPN)
Simon Cooksey 0:fb7af294d5d9 1675 case MBEDTLS_TLS_EXT_ALPN:
Simon Cooksey 0:fb7af294d5d9 1676 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) );
Simon Cooksey 0:fb7af294d5d9 1677
Simon Cooksey 0:fb7af294d5d9 1678 ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size );
Simon Cooksey 0:fb7af294d5d9 1679 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 1680 return( ret );
Simon Cooksey 0:fb7af294d5d9 1681 break;
Simon Cooksey 0:fb7af294d5d9 1682 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
Simon Cooksey 0:fb7af294d5d9 1683
Simon Cooksey 0:fb7af294d5d9 1684 default:
Simon Cooksey 0:fb7af294d5d9 1685 MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)",
Simon Cooksey 0:fb7af294d5d9 1686 ext_id ) );
Simon Cooksey 0:fb7af294d5d9 1687 }
Simon Cooksey 0:fb7af294d5d9 1688
Simon Cooksey 0:fb7af294d5d9 1689 ext_len -= 4 + ext_size;
Simon Cooksey 0:fb7af294d5d9 1690 ext += 4 + ext_size;
Simon Cooksey 0:fb7af294d5d9 1691
Simon Cooksey 0:fb7af294d5d9 1692 if( ext_len > 0 && ext_len < 4 )
Simon Cooksey 0:fb7af294d5d9 1693 {
Simon Cooksey 0:fb7af294d5d9 1694 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1695 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1696 }
Simon Cooksey 0:fb7af294d5d9 1697 }
Simon Cooksey 0:fb7af294d5d9 1698 #if defined(MBEDTLS_SSL_PROTO_SSL3)
Simon Cooksey 0:fb7af294d5d9 1699 }
Simon Cooksey 0:fb7af294d5d9 1700 #endif
Simon Cooksey 0:fb7af294d5d9 1701
Simon Cooksey 0:fb7af294d5d9 1702 #if defined(MBEDTLS_SSL_FALLBACK_SCSV)
Simon Cooksey 0:fb7af294d5d9 1703 for( i = 0, p = buf + 41 + sess_len; i < ciph_len; i += 2, p += 2 )
Simon Cooksey 0:fb7af294d5d9 1704 {
Simon Cooksey 0:fb7af294d5d9 1705 if( p[0] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) &&
Simon Cooksey 0:fb7af294d5d9 1706 p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) & 0xff ) )
Simon Cooksey 0:fb7af294d5d9 1707 {
Simon Cooksey 0:fb7af294d5d9 1708 MBEDTLS_SSL_DEBUG_MSG( 2, ( "received FALLBACK_SCSV" ) );
Simon Cooksey 0:fb7af294d5d9 1709
Simon Cooksey 0:fb7af294d5d9 1710 if( ssl->minor_ver < ssl->conf->max_minor_ver )
Simon Cooksey 0:fb7af294d5d9 1711 {
Simon Cooksey 0:fb7af294d5d9 1712 MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) );
Simon Cooksey 0:fb7af294d5d9 1713
Simon Cooksey 0:fb7af294d5d9 1714 mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
Simon Cooksey 0:fb7af294d5d9 1715 MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK );
Simon Cooksey 0:fb7af294d5d9 1716
Simon Cooksey 0:fb7af294d5d9 1717 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1718 }
Simon Cooksey 0:fb7af294d5d9 1719
Simon Cooksey 0:fb7af294d5d9 1720 break;
Simon Cooksey 0:fb7af294d5d9 1721 }
Simon Cooksey 0:fb7af294d5d9 1722 }
Simon Cooksey 0:fb7af294d5d9 1723 #endif /* MBEDTLS_SSL_FALLBACK_SCSV */
Simon Cooksey 0:fb7af294d5d9 1724
Simon Cooksey 0:fb7af294d5d9 1725 /*
Simon Cooksey 0:fb7af294d5d9 1726 * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV
Simon Cooksey 0:fb7af294d5d9 1727 */
Simon Cooksey 0:fb7af294d5d9 1728 for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 )
Simon Cooksey 0:fb7af294d5d9 1729 {
Simon Cooksey 0:fb7af294d5d9 1730 if( p[0] == 0 && p[1] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO )
Simon Cooksey 0:fb7af294d5d9 1731 {
Simon Cooksey 0:fb7af294d5d9 1732 MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) );
Simon Cooksey 0:fb7af294d5d9 1733 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 1734 if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
Simon Cooksey 0:fb7af294d5d9 1735 {
Simon Cooksey 0:fb7af294d5d9 1736 MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV during renegotiation" ) );
Simon Cooksey 0:fb7af294d5d9 1737
Simon Cooksey 0:fb7af294d5d9 1738 if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1739 return( ret );
Simon Cooksey 0:fb7af294d5d9 1740
Simon Cooksey 0:fb7af294d5d9 1741 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1742 }
Simon Cooksey 0:fb7af294d5d9 1743 #endif
Simon Cooksey 0:fb7af294d5d9 1744 ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION;
Simon Cooksey 0:fb7af294d5d9 1745 break;
Simon Cooksey 0:fb7af294d5d9 1746 }
Simon Cooksey 0:fb7af294d5d9 1747 }
Simon Cooksey 0:fb7af294d5d9 1748
Simon Cooksey 0:fb7af294d5d9 1749 /*
Simon Cooksey 0:fb7af294d5d9 1750 * Renegotiation security checks
Simon Cooksey 0:fb7af294d5d9 1751 */
Simon Cooksey 0:fb7af294d5d9 1752 if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION &&
Simon Cooksey 0:fb7af294d5d9 1753 ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE )
Simon Cooksey 0:fb7af294d5d9 1754 {
Simon Cooksey 0:fb7af294d5d9 1755 MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
Simon Cooksey 0:fb7af294d5d9 1756 handshake_failure = 1;
Simon Cooksey 0:fb7af294d5d9 1757 }
Simon Cooksey 0:fb7af294d5d9 1758 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 1759 else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
Simon Cooksey 0:fb7af294d5d9 1760 ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION &&
Simon Cooksey 0:fb7af294d5d9 1761 renegotiation_info_seen == 0 )
Simon Cooksey 0:fb7af294d5d9 1762 {
Simon Cooksey 0:fb7af294d5d9 1763 MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) );
Simon Cooksey 0:fb7af294d5d9 1764 handshake_failure = 1;
Simon Cooksey 0:fb7af294d5d9 1765 }
Simon Cooksey 0:fb7af294d5d9 1766 else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
Simon Cooksey 0:fb7af294d5d9 1767 ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
Simon Cooksey 0:fb7af294d5d9 1768 ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION )
Simon Cooksey 0:fb7af294d5d9 1769 {
Simon Cooksey 0:fb7af294d5d9 1770 MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) );
Simon Cooksey 0:fb7af294d5d9 1771 handshake_failure = 1;
Simon Cooksey 0:fb7af294d5d9 1772 }
Simon Cooksey 0:fb7af294d5d9 1773 else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
Simon Cooksey 0:fb7af294d5d9 1774 ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
Simon Cooksey 0:fb7af294d5d9 1775 renegotiation_info_seen == 1 )
Simon Cooksey 0:fb7af294d5d9 1776 {
Simon Cooksey 0:fb7af294d5d9 1777 MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) );
Simon Cooksey 0:fb7af294d5d9 1778 handshake_failure = 1;
Simon Cooksey 0:fb7af294d5d9 1779 }
Simon Cooksey 0:fb7af294d5d9 1780 #endif /* MBEDTLS_SSL_RENEGOTIATION */
Simon Cooksey 0:fb7af294d5d9 1781
Simon Cooksey 0:fb7af294d5d9 1782 if( handshake_failure == 1 )
Simon Cooksey 0:fb7af294d5d9 1783 {
Simon Cooksey 0:fb7af294d5d9 1784 if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1785 return( ret );
Simon Cooksey 0:fb7af294d5d9 1786
Simon Cooksey 0:fb7af294d5d9 1787 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
Simon Cooksey 0:fb7af294d5d9 1788 }
Simon Cooksey 0:fb7af294d5d9 1789
Simon Cooksey 0:fb7af294d5d9 1790 /*
Simon Cooksey 0:fb7af294d5d9 1791 * Search for a matching ciphersuite
Simon Cooksey 0:fb7af294d5d9 1792 * (At the end because we need information from the EC-based extensions
Simon Cooksey 0:fb7af294d5d9 1793 * and certificate from the SNI callback triggered by the SNI extension.)
Simon Cooksey 0:fb7af294d5d9 1794 */
Simon Cooksey 0:fb7af294d5d9 1795 got_common_suite = 0;
Simon Cooksey 0:fb7af294d5d9 1796 ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver];
Simon Cooksey 0:fb7af294d5d9 1797 ciphersuite_info = NULL;
Simon Cooksey 0:fb7af294d5d9 1798 #if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE)
Simon Cooksey 0:fb7af294d5d9 1799 for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 )
Simon Cooksey 0:fb7af294d5d9 1800 {
Simon Cooksey 0:fb7af294d5d9 1801 for( i = 0; ciphersuites[i] != 0; i++ )
Simon Cooksey 0:fb7af294d5d9 1802 #else
Simon Cooksey 0:fb7af294d5d9 1803 for( i = 0; ciphersuites[i] != 0; i++ )
Simon Cooksey 0:fb7af294d5d9 1804 {
Simon Cooksey 0:fb7af294d5d9 1805 for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 )
Simon Cooksey 0:fb7af294d5d9 1806 #endif
Simon Cooksey 0:fb7af294d5d9 1807 {
Simon Cooksey 0:fb7af294d5d9 1808 if( p[0] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) ||
Simon Cooksey 0:fb7af294d5d9 1809 p[1] != ( ( ciphersuites[i] ) & 0xFF ) )
Simon Cooksey 0:fb7af294d5d9 1810 continue;
Simon Cooksey 0:fb7af294d5d9 1811
Simon Cooksey 0:fb7af294d5d9 1812 got_common_suite = 1;
Simon Cooksey 0:fb7af294d5d9 1813
Simon Cooksey 0:fb7af294d5d9 1814 if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i],
Simon Cooksey 0:fb7af294d5d9 1815 &ciphersuite_info ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1816 return( ret );
Simon Cooksey 0:fb7af294d5d9 1817
Simon Cooksey 0:fb7af294d5d9 1818 if( ciphersuite_info != NULL )
Simon Cooksey 0:fb7af294d5d9 1819 goto have_ciphersuite;
Simon Cooksey 0:fb7af294d5d9 1820 }
Simon Cooksey 0:fb7af294d5d9 1821 }
Simon Cooksey 0:fb7af294d5d9 1822
Simon Cooksey 0:fb7af294d5d9 1823 if( got_common_suite )
Simon Cooksey 0:fb7af294d5d9 1824 {
Simon Cooksey 0:fb7af294d5d9 1825 MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, "
Simon Cooksey 0:fb7af294d5d9 1826 "but none of them usable" ) );
Simon Cooksey 0:fb7af294d5d9 1827 mbedtls_ssl_send_fatal_handshake_failure( ssl );
Simon Cooksey 0:fb7af294d5d9 1828 return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE );
Simon Cooksey 0:fb7af294d5d9 1829 }
Simon Cooksey 0:fb7af294d5d9 1830 else
Simon Cooksey 0:fb7af294d5d9 1831 {
Simon Cooksey 0:fb7af294d5d9 1832 MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) );
Simon Cooksey 0:fb7af294d5d9 1833 mbedtls_ssl_send_fatal_handshake_failure( ssl );
Simon Cooksey 0:fb7af294d5d9 1834 return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN );
Simon Cooksey 0:fb7af294d5d9 1835 }
Simon Cooksey 0:fb7af294d5d9 1836
Simon Cooksey 0:fb7af294d5d9 1837 have_ciphersuite:
Simon Cooksey 0:fb7af294d5d9 1838 MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) );
Simon Cooksey 0:fb7af294d5d9 1839
Simon Cooksey 0:fb7af294d5d9 1840 ssl->session_negotiate->ciphersuite = ciphersuites[i];
Simon Cooksey 0:fb7af294d5d9 1841 ssl->transform_negotiate->ciphersuite_info = ciphersuite_info;
Simon Cooksey 0:fb7af294d5d9 1842
Simon Cooksey 0:fb7af294d5d9 1843 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 1844
Simon Cooksey 0:fb7af294d5d9 1845 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 1846 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
Simon Cooksey 0:fb7af294d5d9 1847 mbedtls_ssl_recv_flight_completed( ssl );
Simon Cooksey 0:fb7af294d5d9 1848 #endif
Simon Cooksey 0:fb7af294d5d9 1849
Simon Cooksey 0:fb7af294d5d9 1850 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) );
Simon Cooksey 0:fb7af294d5d9 1851
Simon Cooksey 0:fb7af294d5d9 1852 return( 0 );
Simon Cooksey 0:fb7af294d5d9 1853 }
Simon Cooksey 0:fb7af294d5d9 1854
Simon Cooksey 0:fb7af294d5d9 1855 #if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
Simon Cooksey 0:fb7af294d5d9 1856 static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 1857 unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 1858 size_t *olen )
Simon Cooksey 0:fb7af294d5d9 1859 {
Simon Cooksey 0:fb7af294d5d9 1860 unsigned char *p = buf;
Simon Cooksey 0:fb7af294d5d9 1861
Simon Cooksey 0:fb7af294d5d9 1862 if( ssl->session_negotiate->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED )
Simon Cooksey 0:fb7af294d5d9 1863 {
Simon Cooksey 0:fb7af294d5d9 1864 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 1865 return;
Simon Cooksey 0:fb7af294d5d9 1866 }
Simon Cooksey 0:fb7af294d5d9 1867
Simon Cooksey 0:fb7af294d5d9 1868 MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding truncated hmac extension" ) );
Simon Cooksey 0:fb7af294d5d9 1869
Simon Cooksey 0:fb7af294d5d9 1870 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 1871 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 1872
Simon Cooksey 0:fb7af294d5d9 1873 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 1874 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 1875
Simon Cooksey 0:fb7af294d5d9 1876 *olen = 4;
Simon Cooksey 0:fb7af294d5d9 1877 }
Simon Cooksey 0:fb7af294d5d9 1878 #endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
Simon Cooksey 0:fb7af294d5d9 1879
Simon Cooksey 0:fb7af294d5d9 1880 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
Simon Cooksey 0:fb7af294d5d9 1881 static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 1882 unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 1883 size_t *olen )
Simon Cooksey 0:fb7af294d5d9 1884 {
Simon Cooksey 0:fb7af294d5d9 1885 unsigned char *p = buf;
Simon Cooksey 0:fb7af294d5d9 1886 const mbedtls_ssl_ciphersuite_t *suite = NULL;
Simon Cooksey 0:fb7af294d5d9 1887 const mbedtls_cipher_info_t *cipher = NULL;
Simon Cooksey 0:fb7af294d5d9 1888
Simon Cooksey 0:fb7af294d5d9 1889 if( ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_EXTENDED_MS_DISABLED ||
Simon Cooksey 0:fb7af294d5d9 1890 ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
Simon Cooksey 0:fb7af294d5d9 1891 {
Simon Cooksey 0:fb7af294d5d9 1892 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 1893 return;
Simon Cooksey 0:fb7af294d5d9 1894 }
Simon Cooksey 0:fb7af294d5d9 1895
Simon Cooksey 0:fb7af294d5d9 1896 /*
Simon Cooksey 0:fb7af294d5d9 1897 * RFC 7366: "If a server receives an encrypt-then-MAC request extension
Simon Cooksey 0:fb7af294d5d9 1898 * from a client and then selects a stream or Authenticated Encryption
Simon Cooksey 0:fb7af294d5d9 1899 * with Associated Data (AEAD) ciphersuite, it MUST NOT send an
Simon Cooksey 0:fb7af294d5d9 1900 * encrypt-then-MAC response extension back to the client."
Simon Cooksey 0:fb7af294d5d9 1901 */
Simon Cooksey 0:fb7af294d5d9 1902 if( ( suite = mbedtls_ssl_ciphersuite_from_id(
Simon Cooksey 0:fb7af294d5d9 1903 ssl->session_negotiate->ciphersuite ) ) == NULL ||
Simon Cooksey 0:fb7af294d5d9 1904 ( cipher = mbedtls_cipher_info_from_type( suite->cipher ) ) == NULL ||
Simon Cooksey 0:fb7af294d5d9 1905 cipher->mode != MBEDTLS_MODE_CBC )
Simon Cooksey 0:fb7af294d5d9 1906 {
Simon Cooksey 0:fb7af294d5d9 1907 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 1908 return;
Simon Cooksey 0:fb7af294d5d9 1909 }
Simon Cooksey 0:fb7af294d5d9 1910
Simon Cooksey 0:fb7af294d5d9 1911 MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding encrypt then mac extension" ) );
Simon Cooksey 0:fb7af294d5d9 1912
Simon Cooksey 0:fb7af294d5d9 1913 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 1914 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 1915
Simon Cooksey 0:fb7af294d5d9 1916 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 1917 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 1918
Simon Cooksey 0:fb7af294d5d9 1919 *olen = 4;
Simon Cooksey 0:fb7af294d5d9 1920 }
Simon Cooksey 0:fb7af294d5d9 1921 #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
Simon Cooksey 0:fb7af294d5d9 1922
Simon Cooksey 0:fb7af294d5d9 1923 #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
Simon Cooksey 0:fb7af294d5d9 1924 static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 1925 unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 1926 size_t *olen )
Simon Cooksey 0:fb7af294d5d9 1927 {
Simon Cooksey 0:fb7af294d5d9 1928 unsigned char *p = buf;
Simon Cooksey 0:fb7af294d5d9 1929
Simon Cooksey 0:fb7af294d5d9 1930 if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED ||
Simon Cooksey 0:fb7af294d5d9 1931 ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
Simon Cooksey 0:fb7af294d5d9 1932 {
Simon Cooksey 0:fb7af294d5d9 1933 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 1934 return;
Simon Cooksey 0:fb7af294d5d9 1935 }
Simon Cooksey 0:fb7af294d5d9 1936
Simon Cooksey 0:fb7af294d5d9 1937 MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding extended master secret "
Simon Cooksey 0:fb7af294d5d9 1938 "extension" ) );
Simon Cooksey 0:fb7af294d5d9 1939
Simon Cooksey 0:fb7af294d5d9 1940 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 1941 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 1942
Simon Cooksey 0:fb7af294d5d9 1943 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 1944 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 1945
Simon Cooksey 0:fb7af294d5d9 1946 *olen = 4;
Simon Cooksey 0:fb7af294d5d9 1947 }
Simon Cooksey 0:fb7af294d5d9 1948 #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
Simon Cooksey 0:fb7af294d5d9 1949
Simon Cooksey 0:fb7af294d5d9 1950 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
Simon Cooksey 0:fb7af294d5d9 1951 static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 1952 unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 1953 size_t *olen )
Simon Cooksey 0:fb7af294d5d9 1954 {
Simon Cooksey 0:fb7af294d5d9 1955 unsigned char *p = buf;
Simon Cooksey 0:fb7af294d5d9 1956
Simon Cooksey 0:fb7af294d5d9 1957 if( ssl->handshake->new_session_ticket == 0 )
Simon Cooksey 0:fb7af294d5d9 1958 {
Simon Cooksey 0:fb7af294d5d9 1959 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 1960 return;
Simon Cooksey 0:fb7af294d5d9 1961 }
Simon Cooksey 0:fb7af294d5d9 1962
Simon Cooksey 0:fb7af294d5d9 1963 MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding session ticket extension" ) );
Simon Cooksey 0:fb7af294d5d9 1964
Simon Cooksey 0:fb7af294d5d9 1965 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 1966 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 1967
Simon Cooksey 0:fb7af294d5d9 1968 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 1969 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 1970
Simon Cooksey 0:fb7af294d5d9 1971 *olen = 4;
Simon Cooksey 0:fb7af294d5d9 1972 }
Simon Cooksey 0:fb7af294d5d9 1973 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
Simon Cooksey 0:fb7af294d5d9 1974
Simon Cooksey 0:fb7af294d5d9 1975 static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 1976 unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 1977 size_t *olen )
Simon Cooksey 0:fb7af294d5d9 1978 {
Simon Cooksey 0:fb7af294d5d9 1979 unsigned char *p = buf;
Simon Cooksey 0:fb7af294d5d9 1980
Simon Cooksey 0:fb7af294d5d9 1981 if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION )
Simon Cooksey 0:fb7af294d5d9 1982 {
Simon Cooksey 0:fb7af294d5d9 1983 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 1984 return;
Simon Cooksey 0:fb7af294d5d9 1985 }
Simon Cooksey 0:fb7af294d5d9 1986
Simon Cooksey 0:fb7af294d5d9 1987 MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, secure renegotiation extension" ) );
Simon Cooksey 0:fb7af294d5d9 1988
Simon Cooksey 0:fb7af294d5d9 1989 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 1990 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 1991
Simon Cooksey 0:fb7af294d5d9 1992 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 1993 if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
Simon Cooksey 0:fb7af294d5d9 1994 {
Simon Cooksey 0:fb7af294d5d9 1995 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 1996 *p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF;
Simon Cooksey 0:fb7af294d5d9 1997 *p++ = ssl->verify_data_len * 2 & 0xFF;
Simon Cooksey 0:fb7af294d5d9 1998
Simon Cooksey 0:fb7af294d5d9 1999 memcpy( p, ssl->peer_verify_data, ssl->verify_data_len );
Simon Cooksey 0:fb7af294d5d9 2000 p += ssl->verify_data_len;
Simon Cooksey 0:fb7af294d5d9 2001 memcpy( p, ssl->own_verify_data, ssl->verify_data_len );
Simon Cooksey 0:fb7af294d5d9 2002 p += ssl->verify_data_len;
Simon Cooksey 0:fb7af294d5d9 2003 }
Simon Cooksey 0:fb7af294d5d9 2004 else
Simon Cooksey 0:fb7af294d5d9 2005 #endif /* MBEDTLS_SSL_RENEGOTIATION */
Simon Cooksey 0:fb7af294d5d9 2006 {
Simon Cooksey 0:fb7af294d5d9 2007 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 2008 *p++ = 0x01;
Simon Cooksey 0:fb7af294d5d9 2009 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 2010 }
Simon Cooksey 0:fb7af294d5d9 2011
Simon Cooksey 0:fb7af294d5d9 2012 *olen = p - buf;
Simon Cooksey 0:fb7af294d5d9 2013 }
Simon Cooksey 0:fb7af294d5d9 2014
Simon Cooksey 0:fb7af294d5d9 2015 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
Simon Cooksey 0:fb7af294d5d9 2016 static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 2017 unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 2018 size_t *olen )
Simon Cooksey 0:fb7af294d5d9 2019 {
Simon Cooksey 0:fb7af294d5d9 2020 unsigned char *p = buf;
Simon Cooksey 0:fb7af294d5d9 2021
Simon Cooksey 0:fb7af294d5d9 2022 if( ssl->session_negotiate->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE )
Simon Cooksey 0:fb7af294d5d9 2023 {
Simon Cooksey 0:fb7af294d5d9 2024 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 2025 return;
Simon Cooksey 0:fb7af294d5d9 2026 }
Simon Cooksey 0:fb7af294d5d9 2027
Simon Cooksey 0:fb7af294d5d9 2028 MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, max_fragment_length extension" ) );
Simon Cooksey 0:fb7af294d5d9 2029
Simon Cooksey 0:fb7af294d5d9 2030 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 2031 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 2032
Simon Cooksey 0:fb7af294d5d9 2033 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 2034 *p++ = 1;
Simon Cooksey 0:fb7af294d5d9 2035
Simon Cooksey 0:fb7af294d5d9 2036 *p++ = ssl->session_negotiate->mfl_code;
Simon Cooksey 0:fb7af294d5d9 2037
Simon Cooksey 0:fb7af294d5d9 2038 *olen = 5;
Simon Cooksey 0:fb7af294d5d9 2039 }
Simon Cooksey 0:fb7af294d5d9 2040 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
Simon Cooksey 0:fb7af294d5d9 2041
Simon Cooksey 0:fb7af294d5d9 2042 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
Simon Cooksey 0:fb7af294d5d9 2043 defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2044 static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 2045 unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 2046 size_t *olen )
Simon Cooksey 0:fb7af294d5d9 2047 {
Simon Cooksey 0:fb7af294d5d9 2048 unsigned char *p = buf;
Simon Cooksey 0:fb7af294d5d9 2049 ((void) ssl);
Simon Cooksey 0:fb7af294d5d9 2050
Simon Cooksey 0:fb7af294d5d9 2051 if( ( ssl->handshake->cli_exts &
Simon Cooksey 0:fb7af294d5d9 2052 MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT ) == 0 )
Simon Cooksey 0:fb7af294d5d9 2053 {
Simon Cooksey 0:fb7af294d5d9 2054 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 2055 return;
Simon Cooksey 0:fb7af294d5d9 2056 }
Simon Cooksey 0:fb7af294d5d9 2057
Simon Cooksey 0:fb7af294d5d9 2058 MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, supported_point_formats extension" ) );
Simon Cooksey 0:fb7af294d5d9 2059
Simon Cooksey 0:fb7af294d5d9 2060 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 2061 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 2062
Simon Cooksey 0:fb7af294d5d9 2063 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 2064 *p++ = 2;
Simon Cooksey 0:fb7af294d5d9 2065
Simon Cooksey 0:fb7af294d5d9 2066 *p++ = 1;
Simon Cooksey 0:fb7af294d5d9 2067 *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED;
Simon Cooksey 0:fb7af294d5d9 2068
Simon Cooksey 0:fb7af294d5d9 2069 *olen = 6;
Simon Cooksey 0:fb7af294d5d9 2070 }
Simon Cooksey 0:fb7af294d5d9 2071 #endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2072
Simon Cooksey 0:fb7af294d5d9 2073 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2074 static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 2075 unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 2076 size_t *olen )
Simon Cooksey 0:fb7af294d5d9 2077 {
Simon Cooksey 0:fb7af294d5d9 2078 int ret;
Simon Cooksey 0:fb7af294d5d9 2079 unsigned char *p = buf;
Simon Cooksey 0:fb7af294d5d9 2080 const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
Simon Cooksey 0:fb7af294d5d9 2081 size_t kkpp_len;
Simon Cooksey 0:fb7af294d5d9 2082
Simon Cooksey 0:fb7af294d5d9 2083 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 2084
Simon Cooksey 0:fb7af294d5d9 2085 /* Skip costly computation if not needed */
Simon Cooksey 0:fb7af294d5d9 2086 if( ssl->transform_negotiate->ciphersuite_info->key_exchange !=
Simon Cooksey 0:fb7af294d5d9 2087 MBEDTLS_KEY_EXCHANGE_ECJPAKE )
Simon Cooksey 0:fb7af294d5d9 2088 return;
Simon Cooksey 0:fb7af294d5d9 2089
Simon Cooksey 0:fb7af294d5d9 2090 MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, ecjpake kkpp extension" ) );
Simon Cooksey 0:fb7af294d5d9 2091
Simon Cooksey 0:fb7af294d5d9 2092 if( end - p < 4 )
Simon Cooksey 0:fb7af294d5d9 2093 {
Simon Cooksey 0:fb7af294d5d9 2094 MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
Simon Cooksey 0:fb7af294d5d9 2095 return;
Simon Cooksey 0:fb7af294d5d9 2096 }
Simon Cooksey 0:fb7af294d5d9 2097
Simon Cooksey 0:fb7af294d5d9 2098 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 2099 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 2100
Simon Cooksey 0:fb7af294d5d9 2101 ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx,
Simon Cooksey 0:fb7af294d5d9 2102 p + 2, end - p - 2, &kkpp_len,
Simon Cooksey 0:fb7af294d5d9 2103 ssl->conf->f_rng, ssl->conf->p_rng );
Simon Cooksey 0:fb7af294d5d9 2104 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 2105 {
Simon Cooksey 0:fb7af294d5d9 2106 MBEDTLS_SSL_DEBUG_RET( 1 , "mbedtls_ecjpake_write_round_one", ret );
Simon Cooksey 0:fb7af294d5d9 2107 return;
Simon Cooksey 0:fb7af294d5d9 2108 }
Simon Cooksey 0:fb7af294d5d9 2109
Simon Cooksey 0:fb7af294d5d9 2110 *p++ = (unsigned char)( ( kkpp_len >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 2111 *p++ = (unsigned char)( ( kkpp_len ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 2112
Simon Cooksey 0:fb7af294d5d9 2113 *olen = kkpp_len + 4;
Simon Cooksey 0:fb7af294d5d9 2114 }
Simon Cooksey 0:fb7af294d5d9 2115 #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2116
Simon Cooksey 0:fb7af294d5d9 2117 #if defined(MBEDTLS_SSL_ALPN )
Simon Cooksey 0:fb7af294d5d9 2118 static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 2119 unsigned char *buf, size_t *olen )
Simon Cooksey 0:fb7af294d5d9 2120 {
Simon Cooksey 0:fb7af294d5d9 2121 if( ssl->alpn_chosen == NULL )
Simon Cooksey 0:fb7af294d5d9 2122 {
Simon Cooksey 0:fb7af294d5d9 2123 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 2124 return;
Simon Cooksey 0:fb7af294d5d9 2125 }
Simon Cooksey 0:fb7af294d5d9 2126
Simon Cooksey 0:fb7af294d5d9 2127 MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding alpn extension" ) );
Simon Cooksey 0:fb7af294d5d9 2128
Simon Cooksey 0:fb7af294d5d9 2129 /*
Simon Cooksey 0:fb7af294d5d9 2130 * 0 . 1 ext identifier
Simon Cooksey 0:fb7af294d5d9 2131 * 2 . 3 ext length
Simon Cooksey 0:fb7af294d5d9 2132 * 4 . 5 protocol list length
Simon Cooksey 0:fb7af294d5d9 2133 * 6 . 6 protocol name length
Simon Cooksey 0:fb7af294d5d9 2134 * 7 . 7+n protocol name
Simon Cooksey 0:fb7af294d5d9 2135 */
Simon Cooksey 0:fb7af294d5d9 2136 buf[0] = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 2137 buf[1] = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 2138
Simon Cooksey 0:fb7af294d5d9 2139 *olen = 7 + strlen( ssl->alpn_chosen );
Simon Cooksey 0:fb7af294d5d9 2140
Simon Cooksey 0:fb7af294d5d9 2141 buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 2142 buf[3] = (unsigned char)( ( ( *olen - 4 ) ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 2143
Simon Cooksey 0:fb7af294d5d9 2144 buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 2145 buf[5] = (unsigned char)( ( ( *olen - 6 ) ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 2146
Simon Cooksey 0:fb7af294d5d9 2147 buf[6] = (unsigned char)( ( ( *olen - 7 ) ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 2148
Simon Cooksey 0:fb7af294d5d9 2149 memcpy( buf + 7, ssl->alpn_chosen, *olen - 7 );
Simon Cooksey 0:fb7af294d5d9 2150 }
Simon Cooksey 0:fb7af294d5d9 2151 #endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */
Simon Cooksey 0:fb7af294d5d9 2152
Simon Cooksey 0:fb7af294d5d9 2153 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
Simon Cooksey 0:fb7af294d5d9 2154 static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 2155 {
Simon Cooksey 0:fb7af294d5d9 2156 int ret;
Simon Cooksey 0:fb7af294d5d9 2157 unsigned char *p = ssl->out_msg + 4;
Simon Cooksey 0:fb7af294d5d9 2158 unsigned char *cookie_len_byte;
Simon Cooksey 0:fb7af294d5d9 2159
Simon Cooksey 0:fb7af294d5d9 2160 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello verify request" ) );
Simon Cooksey 0:fb7af294d5d9 2161
Simon Cooksey 0:fb7af294d5d9 2162 /*
Simon Cooksey 0:fb7af294d5d9 2163 * struct {
Simon Cooksey 0:fb7af294d5d9 2164 * ProtocolVersion server_version;
Simon Cooksey 0:fb7af294d5d9 2165 * opaque cookie<0..2^8-1>;
Simon Cooksey 0:fb7af294d5d9 2166 * } HelloVerifyRequest;
Simon Cooksey 0:fb7af294d5d9 2167 */
Simon Cooksey 0:fb7af294d5d9 2168
Simon Cooksey 0:fb7af294d5d9 2169 /* The RFC is not clear on this point, but sending the actual negotiated
Simon Cooksey 0:fb7af294d5d9 2170 * version looks like the most interoperable thing to do. */
Simon Cooksey 0:fb7af294d5d9 2171 mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
Simon Cooksey 0:fb7af294d5d9 2172 ssl->conf->transport, p );
Simon Cooksey 0:fb7af294d5d9 2173 MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 );
Simon Cooksey 0:fb7af294d5d9 2174 p += 2;
Simon Cooksey 0:fb7af294d5d9 2175
Simon Cooksey 0:fb7af294d5d9 2176 /* If we get here, f_cookie_check is not null */
Simon Cooksey 0:fb7af294d5d9 2177 if( ssl->conf->f_cookie_write == NULL )
Simon Cooksey 0:fb7af294d5d9 2178 {
Simon Cooksey 0:fb7af294d5d9 2179 MBEDTLS_SSL_DEBUG_MSG( 1, ( "inconsistent cookie callbacks" ) );
Simon Cooksey 0:fb7af294d5d9 2180 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
Simon Cooksey 0:fb7af294d5d9 2181 }
Simon Cooksey 0:fb7af294d5d9 2182
Simon Cooksey 0:fb7af294d5d9 2183 /* Skip length byte until we know the length */
Simon Cooksey 0:fb7af294d5d9 2184 cookie_len_byte = p++;
Simon Cooksey 0:fb7af294d5d9 2185
Simon Cooksey 0:fb7af294d5d9 2186 if( ( ret = ssl->conf->f_cookie_write( ssl->conf->p_cookie,
Simon Cooksey 0:fb7af294d5d9 2187 &p, ssl->out_buf + MBEDTLS_SSL_BUFFER_LEN,
Simon Cooksey 0:fb7af294d5d9 2188 ssl->cli_id, ssl->cli_id_len ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2189 {
Simon Cooksey 0:fb7af294d5d9 2190 MBEDTLS_SSL_DEBUG_RET( 1, "f_cookie_write", ret );
Simon Cooksey 0:fb7af294d5d9 2191 return( ret );
Simon Cooksey 0:fb7af294d5d9 2192 }
Simon Cooksey 0:fb7af294d5d9 2193
Simon Cooksey 0:fb7af294d5d9 2194 *cookie_len_byte = (unsigned char)( p - ( cookie_len_byte + 1 ) );
Simon Cooksey 0:fb7af294d5d9 2195
Simon Cooksey 0:fb7af294d5d9 2196 MBEDTLS_SSL_DEBUG_BUF( 3, "cookie sent", cookie_len_byte + 1, *cookie_len_byte );
Simon Cooksey 0:fb7af294d5d9 2197
Simon Cooksey 0:fb7af294d5d9 2198 ssl->out_msglen = p - ssl->out_msg;
Simon Cooksey 0:fb7af294d5d9 2199 ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
Simon Cooksey 0:fb7af294d5d9 2200 ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST;
Simon Cooksey 0:fb7af294d5d9 2201
Simon Cooksey 0:fb7af294d5d9 2202 ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT;
Simon Cooksey 0:fb7af294d5d9 2203
Simon Cooksey 0:fb7af294d5d9 2204 if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2205 {
Simon Cooksey 0:fb7af294d5d9 2206 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
Simon Cooksey 0:fb7af294d5d9 2207 return( ret );
Simon Cooksey 0:fb7af294d5d9 2208 }
Simon Cooksey 0:fb7af294d5d9 2209
Simon Cooksey 0:fb7af294d5d9 2210 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello verify request" ) );
Simon Cooksey 0:fb7af294d5d9 2211
Simon Cooksey 0:fb7af294d5d9 2212 return( 0 );
Simon Cooksey 0:fb7af294d5d9 2213 }
Simon Cooksey 0:fb7af294d5d9 2214 #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
Simon Cooksey 0:fb7af294d5d9 2215
Simon Cooksey 0:fb7af294d5d9 2216 static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 2217 {
Simon Cooksey 0:fb7af294d5d9 2218 #if defined(MBEDTLS_HAVE_TIME)
Simon Cooksey 0:fb7af294d5d9 2219 mbedtls_time_t t;
Simon Cooksey 0:fb7af294d5d9 2220 #endif
Simon Cooksey 0:fb7af294d5d9 2221 int ret;
Simon Cooksey 0:fb7af294d5d9 2222 size_t olen, ext_len = 0, n;
Simon Cooksey 0:fb7af294d5d9 2223 unsigned char *buf, *p;
Simon Cooksey 0:fb7af294d5d9 2224
Simon Cooksey 0:fb7af294d5d9 2225 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello" ) );
Simon Cooksey 0:fb7af294d5d9 2226
Simon Cooksey 0:fb7af294d5d9 2227 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
Simon Cooksey 0:fb7af294d5d9 2228 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
Simon Cooksey 0:fb7af294d5d9 2229 ssl->handshake->verify_cookie_len != 0 )
Simon Cooksey 0:fb7af294d5d9 2230 {
Simon Cooksey 0:fb7af294d5d9 2231 MBEDTLS_SSL_DEBUG_MSG( 2, ( "client hello was not authenticated" ) );
Simon Cooksey 0:fb7af294d5d9 2232 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) );
Simon Cooksey 0:fb7af294d5d9 2233
Simon Cooksey 0:fb7af294d5d9 2234 return( ssl_write_hello_verify_request( ssl ) );
Simon Cooksey 0:fb7af294d5d9 2235 }
Simon Cooksey 0:fb7af294d5d9 2236 #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
Simon Cooksey 0:fb7af294d5d9 2237
Simon Cooksey 0:fb7af294d5d9 2238 if( ssl->conf->f_rng == NULL )
Simon Cooksey 0:fb7af294d5d9 2239 {
Simon Cooksey 0:fb7af294d5d9 2240 MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") );
Simon Cooksey 0:fb7af294d5d9 2241 return( MBEDTLS_ERR_SSL_NO_RNG );
Simon Cooksey 0:fb7af294d5d9 2242 }
Simon Cooksey 0:fb7af294d5d9 2243
Simon Cooksey 0:fb7af294d5d9 2244 /*
Simon Cooksey 0:fb7af294d5d9 2245 * 0 . 0 handshake type
Simon Cooksey 0:fb7af294d5d9 2246 * 1 . 3 handshake length
Simon Cooksey 0:fb7af294d5d9 2247 * 4 . 5 protocol version
Simon Cooksey 0:fb7af294d5d9 2248 * 6 . 9 UNIX time()
Simon Cooksey 0:fb7af294d5d9 2249 * 10 . 37 random bytes
Simon Cooksey 0:fb7af294d5d9 2250 */
Simon Cooksey 0:fb7af294d5d9 2251 buf = ssl->out_msg;
Simon Cooksey 0:fb7af294d5d9 2252 p = buf + 4;
Simon Cooksey 0:fb7af294d5d9 2253
Simon Cooksey 0:fb7af294d5d9 2254 mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
Simon Cooksey 0:fb7af294d5d9 2255 ssl->conf->transport, p );
Simon Cooksey 0:fb7af294d5d9 2256 p += 2;
Simon Cooksey 0:fb7af294d5d9 2257
Simon Cooksey 0:fb7af294d5d9 2258 MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]",
Simon Cooksey 0:fb7af294d5d9 2259 buf[4], buf[5] ) );
Simon Cooksey 0:fb7af294d5d9 2260
Simon Cooksey 0:fb7af294d5d9 2261 #if defined(MBEDTLS_HAVE_TIME)
Simon Cooksey 0:fb7af294d5d9 2262 t = mbedtls_time( NULL );
Simon Cooksey 0:fb7af294d5d9 2263 *p++ = (unsigned char)( t >> 24 );
Simon Cooksey 0:fb7af294d5d9 2264 *p++ = (unsigned char)( t >> 16 );
Simon Cooksey 0:fb7af294d5d9 2265 *p++ = (unsigned char)( t >> 8 );
Simon Cooksey 0:fb7af294d5d9 2266 *p++ = (unsigned char)( t );
Simon Cooksey 0:fb7af294d5d9 2267
Simon Cooksey 0:fb7af294d5d9 2268 MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) );
Simon Cooksey 0:fb7af294d5d9 2269 #else
Simon Cooksey 0:fb7af294d5d9 2270 if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2271 return( ret );
Simon Cooksey 0:fb7af294d5d9 2272
Simon Cooksey 0:fb7af294d5d9 2273 p += 4;
Simon Cooksey 0:fb7af294d5d9 2274 #endif /* MBEDTLS_HAVE_TIME */
Simon Cooksey 0:fb7af294d5d9 2275
Simon Cooksey 0:fb7af294d5d9 2276 if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2277 return( ret );
Simon Cooksey 0:fb7af294d5d9 2278
Simon Cooksey 0:fb7af294d5d9 2279 p += 28;
Simon Cooksey 0:fb7af294d5d9 2280
Simon Cooksey 0:fb7af294d5d9 2281 memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 );
Simon Cooksey 0:fb7af294d5d9 2282
Simon Cooksey 0:fb7af294d5d9 2283 MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 );
Simon Cooksey 0:fb7af294d5d9 2284
Simon Cooksey 0:fb7af294d5d9 2285 /*
Simon Cooksey 0:fb7af294d5d9 2286 * Resume is 0 by default, see ssl_handshake_init().
Simon Cooksey 0:fb7af294d5d9 2287 * It may be already set to 1 by ssl_parse_session_ticket_ext().
Simon Cooksey 0:fb7af294d5d9 2288 * If not, try looking up session ID in our cache.
Simon Cooksey 0:fb7af294d5d9 2289 */
Simon Cooksey 0:fb7af294d5d9 2290 if( ssl->handshake->resume == 0 &&
Simon Cooksey 0:fb7af294d5d9 2291 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 2292 ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE &&
Simon Cooksey 0:fb7af294d5d9 2293 #endif
Simon Cooksey 0:fb7af294d5d9 2294 ssl->session_negotiate->id_len != 0 &&
Simon Cooksey 0:fb7af294d5d9 2295 ssl->conf->f_get_cache != NULL &&
Simon Cooksey 0:fb7af294d5d9 2296 ssl->conf->f_get_cache( ssl->conf->p_cache, ssl->session_negotiate ) == 0 )
Simon Cooksey 0:fb7af294d5d9 2297 {
Simon Cooksey 0:fb7af294d5d9 2298 MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from cache" ) );
Simon Cooksey 0:fb7af294d5d9 2299 ssl->handshake->resume = 1;
Simon Cooksey 0:fb7af294d5d9 2300 }
Simon Cooksey 0:fb7af294d5d9 2301
Simon Cooksey 0:fb7af294d5d9 2302 if( ssl->handshake->resume == 0 )
Simon Cooksey 0:fb7af294d5d9 2303 {
Simon Cooksey 0:fb7af294d5d9 2304 /*
Simon Cooksey 0:fb7af294d5d9 2305 * New session, create a new session id,
Simon Cooksey 0:fb7af294d5d9 2306 * unless we're about to issue a session ticket
Simon Cooksey 0:fb7af294d5d9 2307 */
Simon Cooksey 0:fb7af294d5d9 2308 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 2309
Simon Cooksey 0:fb7af294d5d9 2310 #if defined(MBEDTLS_HAVE_TIME)
Simon Cooksey 0:fb7af294d5d9 2311 ssl->session_negotiate->start = mbedtls_time( NULL );
Simon Cooksey 0:fb7af294d5d9 2312 #endif
Simon Cooksey 0:fb7af294d5d9 2313
Simon Cooksey 0:fb7af294d5d9 2314 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
Simon Cooksey 0:fb7af294d5d9 2315 if( ssl->handshake->new_session_ticket != 0 )
Simon Cooksey 0:fb7af294d5d9 2316 {
Simon Cooksey 0:fb7af294d5d9 2317 ssl->session_negotiate->id_len = n = 0;
Simon Cooksey 0:fb7af294d5d9 2318 memset( ssl->session_negotiate->id, 0, 32 );
Simon Cooksey 0:fb7af294d5d9 2319 }
Simon Cooksey 0:fb7af294d5d9 2320 else
Simon Cooksey 0:fb7af294d5d9 2321 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
Simon Cooksey 0:fb7af294d5d9 2322 {
Simon Cooksey 0:fb7af294d5d9 2323 ssl->session_negotiate->id_len = n = 32;
Simon Cooksey 0:fb7af294d5d9 2324 if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id,
Simon Cooksey 0:fb7af294d5d9 2325 n ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2326 return( ret );
Simon Cooksey 0:fb7af294d5d9 2327 }
Simon Cooksey 0:fb7af294d5d9 2328 }
Simon Cooksey 0:fb7af294d5d9 2329 else
Simon Cooksey 0:fb7af294d5d9 2330 {
Simon Cooksey 0:fb7af294d5d9 2331 /*
Simon Cooksey 0:fb7af294d5d9 2332 * Resuming a session
Simon Cooksey 0:fb7af294d5d9 2333 */
Simon Cooksey 0:fb7af294d5d9 2334 n = ssl->session_negotiate->id_len;
Simon Cooksey 0:fb7af294d5d9 2335 ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC;
Simon Cooksey 0:fb7af294d5d9 2336
Simon Cooksey 0:fb7af294d5d9 2337 if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2338 {
Simon Cooksey 0:fb7af294d5d9 2339 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
Simon Cooksey 0:fb7af294d5d9 2340 return( ret );
Simon Cooksey 0:fb7af294d5d9 2341 }
Simon Cooksey 0:fb7af294d5d9 2342 }
Simon Cooksey 0:fb7af294d5d9 2343
Simon Cooksey 0:fb7af294d5d9 2344 /*
Simon Cooksey 0:fb7af294d5d9 2345 * 38 . 38 session id length
Simon Cooksey 0:fb7af294d5d9 2346 * 39 . 38+n session id
Simon Cooksey 0:fb7af294d5d9 2347 * 39+n . 40+n chosen ciphersuite
Simon Cooksey 0:fb7af294d5d9 2348 * 41+n . 41+n chosen compression alg.
Simon Cooksey 0:fb7af294d5d9 2349 * 42+n . 43+n extensions length
Simon Cooksey 0:fb7af294d5d9 2350 * 44+n . 43+n+m extensions
Simon Cooksey 0:fb7af294d5d9 2351 */
Simon Cooksey 0:fb7af294d5d9 2352 *p++ = (unsigned char) ssl->session_negotiate->id_len;
Simon Cooksey 0:fb7af294d5d9 2353 memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->id_len );
Simon Cooksey 0:fb7af294d5d9 2354 p += ssl->session_negotiate->id_len;
Simon Cooksey 0:fb7af294d5d9 2355
Simon Cooksey 0:fb7af294d5d9 2356 MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
Simon Cooksey 0:fb7af294d5d9 2357 MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n );
Simon Cooksey 0:fb7af294d5d9 2358 MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
Simon Cooksey 0:fb7af294d5d9 2359 ssl->handshake->resume ? "a" : "no" ) );
Simon Cooksey 0:fb7af294d5d9 2360
Simon Cooksey 0:fb7af294d5d9 2361 *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite >> 8 );
Simon Cooksey 0:fb7af294d5d9 2362 *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite );
Simon Cooksey 0:fb7af294d5d9 2363 *p++ = (unsigned char)( ssl->session_negotiate->compression );
Simon Cooksey 0:fb7af294d5d9 2364
Simon Cooksey 0:fb7af294d5d9 2365 MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s",
Simon Cooksey 0:fb7af294d5d9 2366 mbedtls_ssl_get_ciphersuite_name( ssl->session_negotiate->ciphersuite ) ) );
Simon Cooksey 0:fb7af294d5d9 2367 MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: 0x%02X",
Simon Cooksey 0:fb7af294d5d9 2368 ssl->session_negotiate->compression ) );
Simon Cooksey 0:fb7af294d5d9 2369
Simon Cooksey 0:fb7af294d5d9 2370 /* Do not write the extensions if the protocol is SSLv3 */
Simon Cooksey 0:fb7af294d5d9 2371 #if defined(MBEDTLS_SSL_PROTO_SSL3)
Simon Cooksey 0:fb7af294d5d9 2372 if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) )
Simon Cooksey 0:fb7af294d5d9 2373 {
Simon Cooksey 0:fb7af294d5d9 2374 #endif
Simon Cooksey 0:fb7af294d5d9 2375
Simon Cooksey 0:fb7af294d5d9 2376 /*
Simon Cooksey 0:fb7af294d5d9 2377 * First write extensions, then the total length
Simon Cooksey 0:fb7af294d5d9 2378 */
Simon Cooksey 0:fb7af294d5d9 2379 ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen );
Simon Cooksey 0:fb7af294d5d9 2380 ext_len += olen;
Simon Cooksey 0:fb7af294d5d9 2381
Simon Cooksey 0:fb7af294d5d9 2382 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
Simon Cooksey 0:fb7af294d5d9 2383 ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen );
Simon Cooksey 0:fb7af294d5d9 2384 ext_len += olen;
Simon Cooksey 0:fb7af294d5d9 2385 #endif
Simon Cooksey 0:fb7af294d5d9 2386
Simon Cooksey 0:fb7af294d5d9 2387 #if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
Simon Cooksey 0:fb7af294d5d9 2388 ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen );
Simon Cooksey 0:fb7af294d5d9 2389 ext_len += olen;
Simon Cooksey 0:fb7af294d5d9 2390 #endif
Simon Cooksey 0:fb7af294d5d9 2391
Simon Cooksey 0:fb7af294d5d9 2392 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
Simon Cooksey 0:fb7af294d5d9 2393 ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen );
Simon Cooksey 0:fb7af294d5d9 2394 ext_len += olen;
Simon Cooksey 0:fb7af294d5d9 2395 #endif
Simon Cooksey 0:fb7af294d5d9 2396
Simon Cooksey 0:fb7af294d5d9 2397 #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
Simon Cooksey 0:fb7af294d5d9 2398 ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen );
Simon Cooksey 0:fb7af294d5d9 2399 ext_len += olen;
Simon Cooksey 0:fb7af294d5d9 2400 #endif
Simon Cooksey 0:fb7af294d5d9 2401
Simon Cooksey 0:fb7af294d5d9 2402 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
Simon Cooksey 0:fb7af294d5d9 2403 ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen );
Simon Cooksey 0:fb7af294d5d9 2404 ext_len += olen;
Simon Cooksey 0:fb7af294d5d9 2405 #endif
Simon Cooksey 0:fb7af294d5d9 2406
Simon Cooksey 0:fb7af294d5d9 2407 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
Simon Cooksey 0:fb7af294d5d9 2408 defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2409 ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
Simon Cooksey 0:fb7af294d5d9 2410 ext_len += olen;
Simon Cooksey 0:fb7af294d5d9 2411 #endif
Simon Cooksey 0:fb7af294d5d9 2412
Simon Cooksey 0:fb7af294d5d9 2413 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2414 ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen );
Simon Cooksey 0:fb7af294d5d9 2415 ext_len += olen;
Simon Cooksey 0:fb7af294d5d9 2416 #endif
Simon Cooksey 0:fb7af294d5d9 2417
Simon Cooksey 0:fb7af294d5d9 2418 #if defined(MBEDTLS_SSL_ALPN)
Simon Cooksey 0:fb7af294d5d9 2419 ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen );
Simon Cooksey 0:fb7af294d5d9 2420 ext_len += olen;
Simon Cooksey 0:fb7af294d5d9 2421 #endif
Simon Cooksey 0:fb7af294d5d9 2422
Simon Cooksey 0:fb7af294d5d9 2423 MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d", ext_len ) );
Simon Cooksey 0:fb7af294d5d9 2424
Simon Cooksey 0:fb7af294d5d9 2425 if( ext_len > 0 )
Simon Cooksey 0:fb7af294d5d9 2426 {
Simon Cooksey 0:fb7af294d5d9 2427 *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 2428 *p++ = (unsigned char)( ( ext_len ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 2429 p += ext_len;
Simon Cooksey 0:fb7af294d5d9 2430 }
Simon Cooksey 0:fb7af294d5d9 2431
Simon Cooksey 0:fb7af294d5d9 2432 #if defined(MBEDTLS_SSL_PROTO_SSL3)
Simon Cooksey 0:fb7af294d5d9 2433 }
Simon Cooksey 0:fb7af294d5d9 2434 #endif
Simon Cooksey 0:fb7af294d5d9 2435
Simon Cooksey 0:fb7af294d5d9 2436 ssl->out_msglen = p - buf;
Simon Cooksey 0:fb7af294d5d9 2437 ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
Simon Cooksey 0:fb7af294d5d9 2438 ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO;
Simon Cooksey 0:fb7af294d5d9 2439
Simon Cooksey 0:fb7af294d5d9 2440 ret = mbedtls_ssl_write_record( ssl );
Simon Cooksey 0:fb7af294d5d9 2441
Simon Cooksey 0:fb7af294d5d9 2442 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) );
Simon Cooksey 0:fb7af294d5d9 2443
Simon Cooksey 0:fb7af294d5d9 2444 return( ret );
Simon Cooksey 0:fb7af294d5d9 2445 }
Simon Cooksey 0:fb7af294d5d9 2446
Simon Cooksey 0:fb7af294d5d9 2447 #if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \
Simon Cooksey 0:fb7af294d5d9 2448 !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \
Simon Cooksey 0:fb7af294d5d9 2449 !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \
Simon Cooksey 0:fb7af294d5d9 2450 !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
Simon Cooksey 0:fb7af294d5d9 2451 !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \
Simon Cooksey 0:fb7af294d5d9 2452 !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2453 static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 2454 {
Simon Cooksey 0:fb7af294d5d9 2455 const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
Simon Cooksey 0:fb7af294d5d9 2456
Simon Cooksey 0:fb7af294d5d9 2457 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) );
Simon Cooksey 0:fb7af294d5d9 2458
Simon Cooksey 0:fb7af294d5d9 2459 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
Simon Cooksey 0:fb7af294d5d9 2460 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
Simon Cooksey 0:fb7af294d5d9 2461 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
Simon Cooksey 0:fb7af294d5d9 2462 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
Simon Cooksey 0:fb7af294d5d9 2463 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
Simon Cooksey 0:fb7af294d5d9 2464 {
Simon Cooksey 0:fb7af294d5d9 2465 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) );
Simon Cooksey 0:fb7af294d5d9 2466 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 2467 return( 0 );
Simon Cooksey 0:fb7af294d5d9 2468 }
Simon Cooksey 0:fb7af294d5d9 2469
Simon Cooksey 0:fb7af294d5d9 2470 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
Simon Cooksey 0:fb7af294d5d9 2471 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
Simon Cooksey 0:fb7af294d5d9 2472 }
Simon Cooksey 0:fb7af294d5d9 2473 #else
Simon Cooksey 0:fb7af294d5d9 2474 static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 2475 {
Simon Cooksey 0:fb7af294d5d9 2476 int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
Simon Cooksey 0:fb7af294d5d9 2477 const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
Simon Cooksey 0:fb7af294d5d9 2478 size_t dn_size, total_dn_size; /* excluding length bytes */
Simon Cooksey 0:fb7af294d5d9 2479 size_t ct_len, sa_len; /* including length bytes */
Simon Cooksey 0:fb7af294d5d9 2480 unsigned char *buf, *p;
Simon Cooksey 0:fb7af294d5d9 2481 const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
Simon Cooksey 0:fb7af294d5d9 2482 const mbedtls_x509_crt *crt;
Simon Cooksey 0:fb7af294d5d9 2483 int authmode;
Simon Cooksey 0:fb7af294d5d9 2484
Simon Cooksey 0:fb7af294d5d9 2485 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) );
Simon Cooksey 0:fb7af294d5d9 2486
Simon Cooksey 0:fb7af294d5d9 2487 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 2488
Simon Cooksey 0:fb7af294d5d9 2489 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
Simon Cooksey 0:fb7af294d5d9 2490 if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET )
Simon Cooksey 0:fb7af294d5d9 2491 authmode = ssl->handshake->sni_authmode;
Simon Cooksey 0:fb7af294d5d9 2492 else
Simon Cooksey 0:fb7af294d5d9 2493 #endif
Simon Cooksey 0:fb7af294d5d9 2494 authmode = ssl->conf->authmode;
Simon Cooksey 0:fb7af294d5d9 2495
Simon Cooksey 0:fb7af294d5d9 2496 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
Simon Cooksey 0:fb7af294d5d9 2497 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
Simon Cooksey 0:fb7af294d5d9 2498 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
Simon Cooksey 0:fb7af294d5d9 2499 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
Simon Cooksey 0:fb7af294d5d9 2500 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ||
Simon Cooksey 0:fb7af294d5d9 2501 authmode == MBEDTLS_SSL_VERIFY_NONE )
Simon Cooksey 0:fb7af294d5d9 2502 {
Simon Cooksey 0:fb7af294d5d9 2503 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) );
Simon Cooksey 0:fb7af294d5d9 2504 return( 0 );
Simon Cooksey 0:fb7af294d5d9 2505 }
Simon Cooksey 0:fb7af294d5d9 2506
Simon Cooksey 0:fb7af294d5d9 2507 /*
Simon Cooksey 0:fb7af294d5d9 2508 * 0 . 0 handshake type
Simon Cooksey 0:fb7af294d5d9 2509 * 1 . 3 handshake length
Simon Cooksey 0:fb7af294d5d9 2510 * 4 . 4 cert type count
Simon Cooksey 0:fb7af294d5d9 2511 * 5 .. m-1 cert types
Simon Cooksey 0:fb7af294d5d9 2512 * m .. m+1 sig alg length (TLS 1.2 only)
Simon Cooksey 0:fb7af294d5d9 2513 * m+1 .. n-1 SignatureAndHashAlgorithms (TLS 1.2 only)
Simon Cooksey 0:fb7af294d5d9 2514 * n .. n+1 length of all DNs
Simon Cooksey 0:fb7af294d5d9 2515 * n+2 .. n+3 length of DN 1
Simon Cooksey 0:fb7af294d5d9 2516 * n+4 .. ... Distinguished Name #1
Simon Cooksey 0:fb7af294d5d9 2517 * ... .. ... length of DN 2, etc.
Simon Cooksey 0:fb7af294d5d9 2518 */
Simon Cooksey 0:fb7af294d5d9 2519 buf = ssl->out_msg;
Simon Cooksey 0:fb7af294d5d9 2520 p = buf + 4;
Simon Cooksey 0:fb7af294d5d9 2521
Simon Cooksey 0:fb7af294d5d9 2522 /*
Simon Cooksey 0:fb7af294d5d9 2523 * Supported certificate types
Simon Cooksey 0:fb7af294d5d9 2524 *
Simon Cooksey 0:fb7af294d5d9 2525 * ClientCertificateType certificate_types<1..2^8-1>;
Simon Cooksey 0:fb7af294d5d9 2526 * enum { (255) } ClientCertificateType;
Simon Cooksey 0:fb7af294d5d9 2527 */
Simon Cooksey 0:fb7af294d5d9 2528 ct_len = 0;
Simon Cooksey 0:fb7af294d5d9 2529
Simon Cooksey 0:fb7af294d5d9 2530 #if defined(MBEDTLS_RSA_C)
Simon Cooksey 0:fb7af294d5d9 2531 p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_RSA_SIGN;
Simon Cooksey 0:fb7af294d5d9 2532 #endif
Simon Cooksey 0:fb7af294d5d9 2533 #if defined(MBEDTLS_ECDSA_C)
Simon Cooksey 0:fb7af294d5d9 2534 p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN;
Simon Cooksey 0:fb7af294d5d9 2535 #endif
Simon Cooksey 0:fb7af294d5d9 2536
Simon Cooksey 0:fb7af294d5d9 2537 p[0] = (unsigned char) ct_len++;
Simon Cooksey 0:fb7af294d5d9 2538 p += ct_len;
Simon Cooksey 0:fb7af294d5d9 2539
Simon Cooksey 0:fb7af294d5d9 2540 sa_len = 0;
Simon Cooksey 0:fb7af294d5d9 2541 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
Simon Cooksey 0:fb7af294d5d9 2542 /*
Simon Cooksey 0:fb7af294d5d9 2543 * Add signature_algorithms for verify (TLS 1.2)
Simon Cooksey 0:fb7af294d5d9 2544 *
Simon Cooksey 0:fb7af294d5d9 2545 * SignatureAndHashAlgorithm supported_signature_algorithms<2..2^16-2>;
Simon Cooksey 0:fb7af294d5d9 2546 *
Simon Cooksey 0:fb7af294d5d9 2547 * struct {
Simon Cooksey 0:fb7af294d5d9 2548 * HashAlgorithm hash;
Simon Cooksey 0:fb7af294d5d9 2549 * SignatureAlgorithm signature;
Simon Cooksey 0:fb7af294d5d9 2550 * } SignatureAndHashAlgorithm;
Simon Cooksey 0:fb7af294d5d9 2551 *
Simon Cooksey 0:fb7af294d5d9 2552 * enum { (255) } HashAlgorithm;
Simon Cooksey 0:fb7af294d5d9 2553 * enum { (255) } SignatureAlgorithm;
Simon Cooksey 0:fb7af294d5d9 2554 */
Simon Cooksey 0:fb7af294d5d9 2555 if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
Simon Cooksey 0:fb7af294d5d9 2556 {
Simon Cooksey 0:fb7af294d5d9 2557 const int *cur;
Simon Cooksey 0:fb7af294d5d9 2558
Simon Cooksey 0:fb7af294d5d9 2559 /*
Simon Cooksey 0:fb7af294d5d9 2560 * Supported signature algorithms
Simon Cooksey 0:fb7af294d5d9 2561 */
Simon Cooksey 0:fb7af294d5d9 2562 for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ )
Simon Cooksey 0:fb7af294d5d9 2563 {
Simon Cooksey 0:fb7af294d5d9 2564 unsigned char hash = mbedtls_ssl_hash_from_md_alg( *cur );
Simon Cooksey 0:fb7af294d5d9 2565
Simon Cooksey 0:fb7af294d5d9 2566 if( MBEDTLS_SSL_HASH_NONE == hash || mbedtls_ssl_set_calc_verify_md( ssl, hash ) )
Simon Cooksey 0:fb7af294d5d9 2567 continue;
Simon Cooksey 0:fb7af294d5d9 2568
Simon Cooksey 0:fb7af294d5d9 2569 #if defined(MBEDTLS_RSA_C)
Simon Cooksey 0:fb7af294d5d9 2570 p[2 + sa_len++] = hash;
Simon Cooksey 0:fb7af294d5d9 2571 p[2 + sa_len++] = MBEDTLS_SSL_SIG_RSA;
Simon Cooksey 0:fb7af294d5d9 2572 #endif
Simon Cooksey 0:fb7af294d5d9 2573 #if defined(MBEDTLS_ECDSA_C)
Simon Cooksey 0:fb7af294d5d9 2574 p[2 + sa_len++] = hash;
Simon Cooksey 0:fb7af294d5d9 2575 p[2 + sa_len++] = MBEDTLS_SSL_SIG_ECDSA;
Simon Cooksey 0:fb7af294d5d9 2576 #endif
Simon Cooksey 0:fb7af294d5d9 2577 }
Simon Cooksey 0:fb7af294d5d9 2578
Simon Cooksey 0:fb7af294d5d9 2579 p[0] = (unsigned char)( sa_len >> 8 );
Simon Cooksey 0:fb7af294d5d9 2580 p[1] = (unsigned char)( sa_len );
Simon Cooksey 0:fb7af294d5d9 2581 sa_len += 2;
Simon Cooksey 0:fb7af294d5d9 2582 p += sa_len;
Simon Cooksey 0:fb7af294d5d9 2583 }
Simon Cooksey 0:fb7af294d5d9 2584 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
Simon Cooksey 0:fb7af294d5d9 2585
Simon Cooksey 0:fb7af294d5d9 2586 /*
Simon Cooksey 0:fb7af294d5d9 2587 * DistinguishedName certificate_authorities<0..2^16-1>;
Simon Cooksey 0:fb7af294d5d9 2588 * opaque DistinguishedName<1..2^16-1>;
Simon Cooksey 0:fb7af294d5d9 2589 */
Simon Cooksey 0:fb7af294d5d9 2590 p += 2;
Simon Cooksey 0:fb7af294d5d9 2591 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
Simon Cooksey 0:fb7af294d5d9 2592 if( ssl->handshake->sni_ca_chain != NULL )
Simon Cooksey 0:fb7af294d5d9 2593 crt = ssl->handshake->sni_ca_chain;
Simon Cooksey 0:fb7af294d5d9 2594 else
Simon Cooksey 0:fb7af294d5d9 2595 #endif
Simon Cooksey 0:fb7af294d5d9 2596 crt = ssl->conf->ca_chain;
Simon Cooksey 0:fb7af294d5d9 2597
Simon Cooksey 0:fb7af294d5d9 2598 total_dn_size = 0;
Simon Cooksey 0:fb7af294d5d9 2599 while( crt != NULL && crt->version != 0 )
Simon Cooksey 0:fb7af294d5d9 2600 {
Simon Cooksey 0:fb7af294d5d9 2601 dn_size = crt->subject_raw.len;
Simon Cooksey 0:fb7af294d5d9 2602
Simon Cooksey 0:fb7af294d5d9 2603 if( end < p ||
Simon Cooksey 0:fb7af294d5d9 2604 (size_t)( end - p ) < dn_size ||
Simon Cooksey 0:fb7af294d5d9 2605 (size_t)( end - p ) < 2 + dn_size )
Simon Cooksey 0:fb7af294d5d9 2606 {
Simon Cooksey 0:fb7af294d5d9 2607 MBEDTLS_SSL_DEBUG_MSG( 1, ( "skipping CAs: buffer too short" ) );
Simon Cooksey 0:fb7af294d5d9 2608 break;
Simon Cooksey 0:fb7af294d5d9 2609 }
Simon Cooksey 0:fb7af294d5d9 2610
Simon Cooksey 0:fb7af294d5d9 2611 *p++ = (unsigned char)( dn_size >> 8 );
Simon Cooksey 0:fb7af294d5d9 2612 *p++ = (unsigned char)( dn_size );
Simon Cooksey 0:fb7af294d5d9 2613 memcpy( p, crt->subject_raw.p, dn_size );
Simon Cooksey 0:fb7af294d5d9 2614 p += dn_size;
Simon Cooksey 0:fb7af294d5d9 2615
Simon Cooksey 0:fb7af294d5d9 2616 MBEDTLS_SSL_DEBUG_BUF( 3, "requested DN", p - dn_size, dn_size );
Simon Cooksey 0:fb7af294d5d9 2617
Simon Cooksey 0:fb7af294d5d9 2618 total_dn_size += 2 + dn_size;
Simon Cooksey 0:fb7af294d5d9 2619 crt = crt->next;
Simon Cooksey 0:fb7af294d5d9 2620 }
Simon Cooksey 0:fb7af294d5d9 2621
Simon Cooksey 0:fb7af294d5d9 2622 ssl->out_msglen = p - buf;
Simon Cooksey 0:fb7af294d5d9 2623 ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
Simon Cooksey 0:fb7af294d5d9 2624 ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_REQUEST;
Simon Cooksey 0:fb7af294d5d9 2625 ssl->out_msg[4 + ct_len + sa_len] = (unsigned char)( total_dn_size >> 8 );
Simon Cooksey 0:fb7af294d5d9 2626 ssl->out_msg[5 + ct_len + sa_len] = (unsigned char)( total_dn_size );
Simon Cooksey 0:fb7af294d5d9 2627
Simon Cooksey 0:fb7af294d5d9 2628 ret = mbedtls_ssl_write_record( ssl );
Simon Cooksey 0:fb7af294d5d9 2629
Simon Cooksey 0:fb7af294d5d9 2630 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) );
Simon Cooksey 0:fb7af294d5d9 2631
Simon Cooksey 0:fb7af294d5d9 2632 return( ret );
Simon Cooksey 0:fb7af294d5d9 2633 }
Simon Cooksey 0:fb7af294d5d9 2634 #endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 2635 !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 2636 !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 2637 !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 2638 !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 2639 !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2640
Simon Cooksey 0:fb7af294d5d9 2641 #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2642 defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2643 static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 2644 {
Simon Cooksey 0:fb7af294d5d9 2645 int ret;
Simon Cooksey 0:fb7af294d5d9 2646
Simon Cooksey 0:fb7af294d5d9 2647 if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECKEY ) )
Simon Cooksey 0:fb7af294d5d9 2648 {
Simon Cooksey 0:fb7af294d5d9 2649 MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) );
Simon Cooksey 0:fb7af294d5d9 2650 return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
Simon Cooksey 0:fb7af294d5d9 2651 }
Simon Cooksey 0:fb7af294d5d9 2652
Simon Cooksey 0:fb7af294d5d9 2653 if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx,
Simon Cooksey 0:fb7af294d5d9 2654 mbedtls_pk_ec( *mbedtls_ssl_own_key( ssl ) ),
Simon Cooksey 0:fb7af294d5d9 2655 MBEDTLS_ECDH_OURS ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2656 {
Simon Cooksey 0:fb7af294d5d9 2657 MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret );
Simon Cooksey 0:fb7af294d5d9 2658 return( ret );
Simon Cooksey 0:fb7af294d5d9 2659 }
Simon Cooksey 0:fb7af294d5d9 2660
Simon Cooksey 0:fb7af294d5d9 2661 return( 0 );
Simon Cooksey 0:fb7af294d5d9 2662 }
Simon Cooksey 0:fb7af294d5d9 2663 #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
Simon Cooksey 0:fb7af294d5d9 2664 MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2665
Simon Cooksey 0:fb7af294d5d9 2666 static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 2667 {
Simon Cooksey 0:fb7af294d5d9 2668 int ret;
Simon Cooksey 0:fb7af294d5d9 2669 size_t n = 0;
Simon Cooksey 0:fb7af294d5d9 2670 const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
Simon Cooksey 0:fb7af294d5d9 2671 ssl->transform_negotiate->ciphersuite_info;
Simon Cooksey 0:fb7af294d5d9 2672
Simon Cooksey 0:fb7af294d5d9 2673 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2674 defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2675 defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2676 defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2677 defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2678 defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2679 unsigned char *p = ssl->out_msg + 4;
Simon Cooksey 0:fb7af294d5d9 2680 unsigned char *dig_signed = p;
Simon Cooksey 0:fb7af294d5d9 2681 size_t dig_signed_len = 0, len;
Simon Cooksey 0:fb7af294d5d9 2682 ((void) dig_signed);
Simon Cooksey 0:fb7af294d5d9 2683 ((void) dig_signed_len);
Simon Cooksey 0:fb7af294d5d9 2684 ((void) len);
Simon Cooksey 0:fb7af294d5d9 2685 #endif
Simon Cooksey 0:fb7af294d5d9 2686
Simon Cooksey 0:fb7af294d5d9 2687 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
Simon Cooksey 0:fb7af294d5d9 2688
Simon Cooksey 0:fb7af294d5d9 2689 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2690 defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2691 defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2692 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ||
Simon Cooksey 0:fb7af294d5d9 2693 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
Simon Cooksey 0:fb7af294d5d9 2694 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
Simon Cooksey 0:fb7af294d5d9 2695 {
Simon Cooksey 0:fb7af294d5d9 2696 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
Simon Cooksey 0:fb7af294d5d9 2697 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 2698 return( 0 );
Simon Cooksey 0:fb7af294d5d9 2699 }
Simon Cooksey 0:fb7af294d5d9 2700 #endif
Simon Cooksey 0:fb7af294d5d9 2701
Simon Cooksey 0:fb7af294d5d9 2702 #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2703 defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2704 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA ||
Simon Cooksey 0:fb7af294d5d9 2705 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA )
Simon Cooksey 0:fb7af294d5d9 2706 {
Simon Cooksey 0:fb7af294d5d9 2707 ssl_get_ecdh_params_from_cert( ssl );
Simon Cooksey 0:fb7af294d5d9 2708
Simon Cooksey 0:fb7af294d5d9 2709 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
Simon Cooksey 0:fb7af294d5d9 2710 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 2711 return( 0 );
Simon Cooksey 0:fb7af294d5d9 2712 }
Simon Cooksey 0:fb7af294d5d9 2713 #endif
Simon Cooksey 0:fb7af294d5d9 2714
Simon Cooksey 0:fb7af294d5d9 2715 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2716 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
Simon Cooksey 0:fb7af294d5d9 2717 {
Simon Cooksey 0:fb7af294d5d9 2718 size_t jlen;
Simon Cooksey 0:fb7af294d5d9 2719 const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
Simon Cooksey 0:fb7af294d5d9 2720
Simon Cooksey 0:fb7af294d5d9 2721 ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx,
Simon Cooksey 0:fb7af294d5d9 2722 p, end - p, &jlen, ssl->conf->f_rng, ssl->conf->p_rng );
Simon Cooksey 0:fb7af294d5d9 2723 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 2724 {
Simon Cooksey 0:fb7af294d5d9 2725 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret );
Simon Cooksey 0:fb7af294d5d9 2726 return( ret );
Simon Cooksey 0:fb7af294d5d9 2727 }
Simon Cooksey 0:fb7af294d5d9 2728
Simon Cooksey 0:fb7af294d5d9 2729 p += jlen;
Simon Cooksey 0:fb7af294d5d9 2730 n += jlen;
Simon Cooksey 0:fb7af294d5d9 2731 }
Simon Cooksey 0:fb7af294d5d9 2732 #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2733
Simon Cooksey 0:fb7af294d5d9 2734 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2735 defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2736 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
Simon Cooksey 0:fb7af294d5d9 2737 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
Simon Cooksey 0:fb7af294d5d9 2738 {
Simon Cooksey 0:fb7af294d5d9 2739 /* Note: we don't support identity hints, until someone asks
Simon Cooksey 0:fb7af294d5d9 2740 * for them. */
Simon Cooksey 0:fb7af294d5d9 2741 *(p++) = 0x00;
Simon Cooksey 0:fb7af294d5d9 2742 *(p++) = 0x00;
Simon Cooksey 0:fb7af294d5d9 2743
Simon Cooksey 0:fb7af294d5d9 2744 n += 2;
Simon Cooksey 0:fb7af294d5d9 2745 }
Simon Cooksey 0:fb7af294d5d9 2746 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 2747 MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2748
Simon Cooksey 0:fb7af294d5d9 2749 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2750 defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2751 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ||
Simon Cooksey 0:fb7af294d5d9 2752 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK )
Simon Cooksey 0:fb7af294d5d9 2753 {
Simon Cooksey 0:fb7af294d5d9 2754 if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL )
Simon Cooksey 0:fb7af294d5d9 2755 {
Simon Cooksey 0:fb7af294d5d9 2756 MBEDTLS_SSL_DEBUG_MSG( 1, ( "no DH parameters set" ) );
Simon Cooksey 0:fb7af294d5d9 2757 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
Simon Cooksey 0:fb7af294d5d9 2758 }
Simon Cooksey 0:fb7af294d5d9 2759
Simon Cooksey 0:fb7af294d5d9 2760 /*
Simon Cooksey 0:fb7af294d5d9 2761 * Ephemeral DH parameters:
Simon Cooksey 0:fb7af294d5d9 2762 *
Simon Cooksey 0:fb7af294d5d9 2763 * struct {
Simon Cooksey 0:fb7af294d5d9 2764 * opaque dh_p<1..2^16-1>;
Simon Cooksey 0:fb7af294d5d9 2765 * opaque dh_g<1..2^16-1>;
Simon Cooksey 0:fb7af294d5d9 2766 * opaque dh_Ys<1..2^16-1>;
Simon Cooksey 0:fb7af294d5d9 2767 * } ServerDHParams;
Simon Cooksey 0:fb7af294d5d9 2768 */
Simon Cooksey 0:fb7af294d5d9 2769 if( ( ret = mbedtls_mpi_copy( &ssl->handshake->dhm_ctx.P, &ssl->conf->dhm_P ) ) != 0 ||
Simon Cooksey 0:fb7af294d5d9 2770 ( ret = mbedtls_mpi_copy( &ssl->handshake->dhm_ctx.G, &ssl->conf->dhm_G ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2771 {
Simon Cooksey 0:fb7af294d5d9 2772 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_mpi_copy", ret );
Simon Cooksey 0:fb7af294d5d9 2773 return( ret );
Simon Cooksey 0:fb7af294d5d9 2774 }
Simon Cooksey 0:fb7af294d5d9 2775
Simon Cooksey 0:fb7af294d5d9 2776 if( ( ret = mbedtls_dhm_make_params( &ssl->handshake->dhm_ctx,
Simon Cooksey 0:fb7af294d5d9 2777 (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ),
Simon Cooksey 0:fb7af294d5d9 2778 p, &len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2779 {
Simon Cooksey 0:fb7af294d5d9 2780 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_params", ret );
Simon Cooksey 0:fb7af294d5d9 2781 return( ret );
Simon Cooksey 0:fb7af294d5d9 2782 }
Simon Cooksey 0:fb7af294d5d9 2783
Simon Cooksey 0:fb7af294d5d9 2784 dig_signed = p;
Simon Cooksey 0:fb7af294d5d9 2785 dig_signed_len = len;
Simon Cooksey 0:fb7af294d5d9 2786
Simon Cooksey 0:fb7af294d5d9 2787 p += len;
Simon Cooksey 0:fb7af294d5d9 2788 n += len;
Simon Cooksey 0:fb7af294d5d9 2789
Simon Cooksey 0:fb7af294d5d9 2790 MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X );
Simon Cooksey 0:fb7af294d5d9 2791 MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P );
Simon Cooksey 0:fb7af294d5d9 2792 MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G );
Simon Cooksey 0:fb7af294d5d9 2793 MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX );
Simon Cooksey 0:fb7af294d5d9 2794 }
Simon Cooksey 0:fb7af294d5d9 2795 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 2796 MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2797
Simon Cooksey 0:fb7af294d5d9 2798 #if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2799 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
Simon Cooksey 0:fb7af294d5d9 2800 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ||
Simon Cooksey 0:fb7af294d5d9 2801 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
Simon Cooksey 0:fb7af294d5d9 2802 {
Simon Cooksey 0:fb7af294d5d9 2803 /*
Simon Cooksey 0:fb7af294d5d9 2804 * Ephemeral ECDH parameters:
Simon Cooksey 0:fb7af294d5d9 2805 *
Simon Cooksey 0:fb7af294d5d9 2806 * struct {
Simon Cooksey 0:fb7af294d5d9 2807 * ECParameters curve_params;
Simon Cooksey 0:fb7af294d5d9 2808 * ECPoint public;
Simon Cooksey 0:fb7af294d5d9 2809 * } ServerECDHParams;
Simon Cooksey 0:fb7af294d5d9 2810 */
Simon Cooksey 0:fb7af294d5d9 2811 const mbedtls_ecp_curve_info **curve = NULL;
Simon Cooksey 0:fb7af294d5d9 2812 const mbedtls_ecp_group_id *gid;
Simon Cooksey 0:fb7af294d5d9 2813
Simon Cooksey 0:fb7af294d5d9 2814 /* Match our preference list against the offered curves */
Simon Cooksey 0:fb7af294d5d9 2815 for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ )
Simon Cooksey 0:fb7af294d5d9 2816 for( curve = ssl->handshake->curves; *curve != NULL; curve++ )
Simon Cooksey 0:fb7af294d5d9 2817 if( (*curve)->grp_id == *gid )
Simon Cooksey 0:fb7af294d5d9 2818 goto curve_matching_done;
Simon Cooksey 0:fb7af294d5d9 2819
Simon Cooksey 0:fb7af294d5d9 2820 curve_matching_done:
Simon Cooksey 0:fb7af294d5d9 2821 if( curve == NULL || *curve == NULL )
Simon Cooksey 0:fb7af294d5d9 2822 {
Simon Cooksey 0:fb7af294d5d9 2823 MBEDTLS_SSL_DEBUG_MSG( 1, ( "no matching curve for ECDHE" ) );
Simon Cooksey 0:fb7af294d5d9 2824 return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN );
Simon Cooksey 0:fb7af294d5d9 2825 }
Simon Cooksey 0:fb7af294d5d9 2826
Simon Cooksey 0:fb7af294d5d9 2827 MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) );
Simon Cooksey 0:fb7af294d5d9 2828
Simon Cooksey 0:fb7af294d5d9 2829 if( ( ret = mbedtls_ecp_group_load( &ssl->handshake->ecdh_ctx.grp,
Simon Cooksey 0:fb7af294d5d9 2830 (*curve)->grp_id ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2831 {
Simon Cooksey 0:fb7af294d5d9 2832 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecp_group_load", ret );
Simon Cooksey 0:fb7af294d5d9 2833 return( ret );
Simon Cooksey 0:fb7af294d5d9 2834 }
Simon Cooksey 0:fb7af294d5d9 2835
Simon Cooksey 0:fb7af294d5d9 2836 if( ( ret = mbedtls_ecdh_make_params( &ssl->handshake->ecdh_ctx, &len,
Simon Cooksey 0:fb7af294d5d9 2837 p, MBEDTLS_SSL_MAX_CONTENT_LEN - n,
Simon Cooksey 0:fb7af294d5d9 2838 ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2839 {
Simon Cooksey 0:fb7af294d5d9 2840 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret );
Simon Cooksey 0:fb7af294d5d9 2841 return( ret );
Simon Cooksey 0:fb7af294d5d9 2842 }
Simon Cooksey 0:fb7af294d5d9 2843
Simon Cooksey 0:fb7af294d5d9 2844 dig_signed = p;
Simon Cooksey 0:fb7af294d5d9 2845 dig_signed_len = len;
Simon Cooksey 0:fb7af294d5d9 2846
Simon Cooksey 0:fb7af294d5d9 2847 p += len;
Simon Cooksey 0:fb7af294d5d9 2848 n += len;
Simon Cooksey 0:fb7af294d5d9 2849
Simon Cooksey 0:fb7af294d5d9 2850 MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q );
Simon Cooksey 0:fb7af294d5d9 2851 }
Simon Cooksey 0:fb7af294d5d9 2852 #endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2853
Simon Cooksey 0:fb7af294d5d9 2854 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2855 defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2856 defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2857 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ||
Simon Cooksey 0:fb7af294d5d9 2858 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
Simon Cooksey 0:fb7af294d5d9 2859 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA )
Simon Cooksey 0:fb7af294d5d9 2860 {
Simon Cooksey 0:fb7af294d5d9 2861 size_t signature_len = 0;
Simon Cooksey 0:fb7af294d5d9 2862 unsigned int hashlen = 0;
Simon Cooksey 0:fb7af294d5d9 2863 unsigned char hash[64];
Simon Cooksey 0:fb7af294d5d9 2864 mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE;
Simon Cooksey 0:fb7af294d5d9 2865
Simon Cooksey 0:fb7af294d5d9 2866 /*
Simon Cooksey 0:fb7af294d5d9 2867 * Choose hash algorithm. NONE means MD5 + SHA1 here.
Simon Cooksey 0:fb7af294d5d9 2868 */
Simon Cooksey 0:fb7af294d5d9 2869 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
Simon Cooksey 0:fb7af294d5d9 2870 if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
Simon Cooksey 0:fb7af294d5d9 2871 {
Simon Cooksey 0:fb7af294d5d9 2872 md_alg = mbedtls_ssl_md_alg_from_hash( ssl->handshake->sig_alg );
Simon Cooksey 0:fb7af294d5d9 2873
Simon Cooksey 0:fb7af294d5d9 2874 if( md_alg == MBEDTLS_MD_NONE )
Simon Cooksey 0:fb7af294d5d9 2875 {
Simon Cooksey 0:fb7af294d5d9 2876 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
Simon Cooksey 0:fb7af294d5d9 2877 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
Simon Cooksey 0:fb7af294d5d9 2878 }
Simon Cooksey 0:fb7af294d5d9 2879 }
Simon Cooksey 0:fb7af294d5d9 2880 else
Simon Cooksey 0:fb7af294d5d9 2881 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
Simon Cooksey 0:fb7af294d5d9 2882 #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
Simon Cooksey 0:fb7af294d5d9 2883 defined(MBEDTLS_SSL_PROTO_TLS1_1)
Simon Cooksey 0:fb7af294d5d9 2884 if( ciphersuite_info->key_exchange ==
Simon Cooksey 0:fb7af294d5d9 2885 MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA )
Simon Cooksey 0:fb7af294d5d9 2886 {
Simon Cooksey 0:fb7af294d5d9 2887 md_alg = MBEDTLS_MD_SHA1;
Simon Cooksey 0:fb7af294d5d9 2888 }
Simon Cooksey 0:fb7af294d5d9 2889 else
Simon Cooksey 0:fb7af294d5d9 2890 #endif
Simon Cooksey 0:fb7af294d5d9 2891 {
Simon Cooksey 0:fb7af294d5d9 2892 md_alg = MBEDTLS_MD_NONE;
Simon Cooksey 0:fb7af294d5d9 2893 }
Simon Cooksey 0:fb7af294d5d9 2894
Simon Cooksey 0:fb7af294d5d9 2895 /*
Simon Cooksey 0:fb7af294d5d9 2896 * Compute the hash to be signed
Simon Cooksey 0:fb7af294d5d9 2897 */
Simon Cooksey 0:fb7af294d5d9 2898 #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
Simon Cooksey 0:fb7af294d5d9 2899 defined(MBEDTLS_SSL_PROTO_TLS1_1)
Simon Cooksey 0:fb7af294d5d9 2900 if( md_alg == MBEDTLS_MD_NONE )
Simon Cooksey 0:fb7af294d5d9 2901 {
Simon Cooksey 0:fb7af294d5d9 2902 mbedtls_md5_context mbedtls_md5;
Simon Cooksey 0:fb7af294d5d9 2903 mbedtls_sha1_context mbedtls_sha1;
Simon Cooksey 0:fb7af294d5d9 2904
Simon Cooksey 0:fb7af294d5d9 2905 mbedtls_md5_init( &mbedtls_md5 );
Simon Cooksey 0:fb7af294d5d9 2906 mbedtls_sha1_init( &mbedtls_sha1 );
Simon Cooksey 0:fb7af294d5d9 2907
Simon Cooksey 0:fb7af294d5d9 2908 /*
Simon Cooksey 0:fb7af294d5d9 2909 * digitally-signed struct {
Simon Cooksey 0:fb7af294d5d9 2910 * opaque md5_hash[16];
Simon Cooksey 0:fb7af294d5d9 2911 * opaque sha_hash[20];
Simon Cooksey 0:fb7af294d5d9 2912 * };
Simon Cooksey 0:fb7af294d5d9 2913 *
Simon Cooksey 0:fb7af294d5d9 2914 * md5_hash
Simon Cooksey 0:fb7af294d5d9 2915 * MD5(ClientHello.random + ServerHello.random
Simon Cooksey 0:fb7af294d5d9 2916 * + ServerParams);
Simon Cooksey 0:fb7af294d5d9 2917 * sha_hash
Simon Cooksey 0:fb7af294d5d9 2918 * SHA(ClientHello.random + ServerHello.random
Simon Cooksey 0:fb7af294d5d9 2919 * + ServerParams);
Simon Cooksey 0:fb7af294d5d9 2920 */
Simon Cooksey 0:fb7af294d5d9 2921 mbedtls_md5_starts( &mbedtls_md5 );
Simon Cooksey 0:fb7af294d5d9 2922 mbedtls_md5_update( &mbedtls_md5, ssl->handshake->randbytes, 64 );
Simon Cooksey 0:fb7af294d5d9 2923 mbedtls_md5_update( &mbedtls_md5, dig_signed, dig_signed_len );
Simon Cooksey 0:fb7af294d5d9 2924 mbedtls_md5_finish( &mbedtls_md5, hash );
Simon Cooksey 0:fb7af294d5d9 2925
Simon Cooksey 0:fb7af294d5d9 2926 mbedtls_sha1_starts( &mbedtls_sha1 );
Simon Cooksey 0:fb7af294d5d9 2927 mbedtls_sha1_update( &mbedtls_sha1, ssl->handshake->randbytes, 64 );
Simon Cooksey 0:fb7af294d5d9 2928 mbedtls_sha1_update( &mbedtls_sha1, dig_signed, dig_signed_len );
Simon Cooksey 0:fb7af294d5d9 2929 mbedtls_sha1_finish( &mbedtls_sha1, hash + 16 );
Simon Cooksey 0:fb7af294d5d9 2930
Simon Cooksey 0:fb7af294d5d9 2931 hashlen = 36;
Simon Cooksey 0:fb7af294d5d9 2932
Simon Cooksey 0:fb7af294d5d9 2933 mbedtls_md5_free( &mbedtls_md5 );
Simon Cooksey 0:fb7af294d5d9 2934 mbedtls_sha1_free( &mbedtls_sha1 );
Simon Cooksey 0:fb7af294d5d9 2935 }
Simon Cooksey 0:fb7af294d5d9 2936 else
Simon Cooksey 0:fb7af294d5d9 2937 #endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \
Simon Cooksey 0:fb7af294d5d9 2938 MBEDTLS_SSL_PROTO_TLS1_1 */
Simon Cooksey 0:fb7af294d5d9 2939 #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
Simon Cooksey 0:fb7af294d5d9 2940 defined(MBEDTLS_SSL_PROTO_TLS1_2)
Simon Cooksey 0:fb7af294d5d9 2941 if( md_alg != MBEDTLS_MD_NONE )
Simon Cooksey 0:fb7af294d5d9 2942 {
Simon Cooksey 0:fb7af294d5d9 2943 mbedtls_md_context_t ctx;
Simon Cooksey 0:fb7af294d5d9 2944 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
Simon Cooksey 0:fb7af294d5d9 2945
Simon Cooksey 0:fb7af294d5d9 2946 mbedtls_md_init( &ctx );
Simon Cooksey 0:fb7af294d5d9 2947
Simon Cooksey 0:fb7af294d5d9 2948 /* Info from md_alg will be used instead */
Simon Cooksey 0:fb7af294d5d9 2949 hashlen = 0;
Simon Cooksey 0:fb7af294d5d9 2950
Simon Cooksey 0:fb7af294d5d9 2951 /*
Simon Cooksey 0:fb7af294d5d9 2952 * digitally-signed struct {
Simon Cooksey 0:fb7af294d5d9 2953 * opaque client_random[32];
Simon Cooksey 0:fb7af294d5d9 2954 * opaque server_random[32];
Simon Cooksey 0:fb7af294d5d9 2955 * ServerDHParams params;
Simon Cooksey 0:fb7af294d5d9 2956 * };
Simon Cooksey 0:fb7af294d5d9 2957 */
Simon Cooksey 0:fb7af294d5d9 2958 if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2959 {
Simon Cooksey 0:fb7af294d5d9 2960 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret );
Simon Cooksey 0:fb7af294d5d9 2961 return( ret );
Simon Cooksey 0:fb7af294d5d9 2962 }
Simon Cooksey 0:fb7af294d5d9 2963
Simon Cooksey 0:fb7af294d5d9 2964 mbedtls_md_starts( &ctx );
Simon Cooksey 0:fb7af294d5d9 2965 mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 );
Simon Cooksey 0:fb7af294d5d9 2966 mbedtls_md_update( &ctx, dig_signed, dig_signed_len );
Simon Cooksey 0:fb7af294d5d9 2967 mbedtls_md_finish( &ctx, hash );
Simon Cooksey 0:fb7af294d5d9 2968 mbedtls_md_free( &ctx );
Simon Cooksey 0:fb7af294d5d9 2969 }
Simon Cooksey 0:fb7af294d5d9 2970 else
Simon Cooksey 0:fb7af294d5d9 2971 #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
Simon Cooksey 0:fb7af294d5d9 2972 MBEDTLS_SSL_PROTO_TLS1_2 */
Simon Cooksey 0:fb7af294d5d9 2973 {
Simon Cooksey 0:fb7af294d5d9 2974 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
Simon Cooksey 0:fb7af294d5d9 2975 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
Simon Cooksey 0:fb7af294d5d9 2976 }
Simon Cooksey 0:fb7af294d5d9 2977
Simon Cooksey 0:fb7af294d5d9 2978 MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen :
Simon Cooksey 0:fb7af294d5d9 2979 (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) );
Simon Cooksey 0:fb7af294d5d9 2980
Simon Cooksey 0:fb7af294d5d9 2981 /*
Simon Cooksey 0:fb7af294d5d9 2982 * Make the signature
Simon Cooksey 0:fb7af294d5d9 2983 */
Simon Cooksey 0:fb7af294d5d9 2984 if( mbedtls_ssl_own_key( ssl ) == NULL )
Simon Cooksey 0:fb7af294d5d9 2985 {
Simon Cooksey 0:fb7af294d5d9 2986 MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) );
Simon Cooksey 0:fb7af294d5d9 2987 return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
Simon Cooksey 0:fb7af294d5d9 2988 }
Simon Cooksey 0:fb7af294d5d9 2989
Simon Cooksey 0:fb7af294d5d9 2990 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
Simon Cooksey 0:fb7af294d5d9 2991 if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
Simon Cooksey 0:fb7af294d5d9 2992 {
Simon Cooksey 0:fb7af294d5d9 2993 *(p++) = ssl->handshake->sig_alg;
Simon Cooksey 0:fb7af294d5d9 2994 *(p++) = mbedtls_ssl_sig_from_pk( mbedtls_ssl_own_key( ssl ) );
Simon Cooksey 0:fb7af294d5d9 2995
Simon Cooksey 0:fb7af294d5d9 2996 n += 2;
Simon Cooksey 0:fb7af294d5d9 2997 }
Simon Cooksey 0:fb7af294d5d9 2998 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
Simon Cooksey 0:fb7af294d5d9 2999
Simon Cooksey 0:fb7af294d5d9 3000 if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash, hashlen,
Simon Cooksey 0:fb7af294d5d9 3001 p + 2 , &signature_len,
Simon Cooksey 0:fb7af294d5d9 3002 ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3003 {
Simon Cooksey 0:fb7af294d5d9 3004 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret );
Simon Cooksey 0:fb7af294d5d9 3005 return( ret );
Simon Cooksey 0:fb7af294d5d9 3006 }
Simon Cooksey 0:fb7af294d5d9 3007
Simon Cooksey 0:fb7af294d5d9 3008 *(p++) = (unsigned char)( signature_len >> 8 );
Simon Cooksey 0:fb7af294d5d9 3009 *(p++) = (unsigned char)( signature_len );
Simon Cooksey 0:fb7af294d5d9 3010 n += 2;
Simon Cooksey 0:fb7af294d5d9 3011
Simon Cooksey 0:fb7af294d5d9 3012 MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", p, signature_len );
Simon Cooksey 0:fb7af294d5d9 3013
Simon Cooksey 0:fb7af294d5d9 3014 n += signature_len;
Simon Cooksey 0:fb7af294d5d9 3015 }
Simon Cooksey 0:fb7af294d5d9 3016 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) ||
Simon Cooksey 0:fb7af294d5d9 3017 MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 3018 MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
Simon Cooksey 0:fb7af294d5d9 3019
Simon Cooksey 0:fb7af294d5d9 3020 ssl->out_msglen = 4 + n;
Simon Cooksey 0:fb7af294d5d9 3021 ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
Simon Cooksey 0:fb7af294d5d9 3022 ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE;
Simon Cooksey 0:fb7af294d5d9 3023
Simon Cooksey 0:fb7af294d5d9 3024 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 3025
Simon Cooksey 0:fb7af294d5d9 3026 if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3027 {
Simon Cooksey 0:fb7af294d5d9 3028 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
Simon Cooksey 0:fb7af294d5d9 3029 return( ret );
Simon Cooksey 0:fb7af294d5d9 3030 }
Simon Cooksey 0:fb7af294d5d9 3031
Simon Cooksey 0:fb7af294d5d9 3032 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) );
Simon Cooksey 0:fb7af294d5d9 3033
Simon Cooksey 0:fb7af294d5d9 3034 return( 0 );
Simon Cooksey 0:fb7af294d5d9 3035 }
Simon Cooksey 0:fb7af294d5d9 3036
Simon Cooksey 0:fb7af294d5d9 3037 static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 3038 {
Simon Cooksey 0:fb7af294d5d9 3039 int ret;
Simon Cooksey 0:fb7af294d5d9 3040
Simon Cooksey 0:fb7af294d5d9 3041 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) );
Simon Cooksey 0:fb7af294d5d9 3042
Simon Cooksey 0:fb7af294d5d9 3043 ssl->out_msglen = 4;
Simon Cooksey 0:fb7af294d5d9 3044 ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
Simon Cooksey 0:fb7af294d5d9 3045 ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO_DONE;
Simon Cooksey 0:fb7af294d5d9 3046
Simon Cooksey 0:fb7af294d5d9 3047 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 3048
Simon Cooksey 0:fb7af294d5d9 3049 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 3050 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
Simon Cooksey 0:fb7af294d5d9 3051 mbedtls_ssl_send_flight_completed( ssl );
Simon Cooksey 0:fb7af294d5d9 3052 #endif
Simon Cooksey 0:fb7af294d5d9 3053
Simon Cooksey 0:fb7af294d5d9 3054 if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3055 {
Simon Cooksey 0:fb7af294d5d9 3056 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
Simon Cooksey 0:fb7af294d5d9 3057 return( ret );
Simon Cooksey 0:fb7af294d5d9 3058 }
Simon Cooksey 0:fb7af294d5d9 3059
Simon Cooksey 0:fb7af294d5d9 3060 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) );
Simon Cooksey 0:fb7af294d5d9 3061
Simon Cooksey 0:fb7af294d5d9 3062 return( 0 );
Simon Cooksey 0:fb7af294d5d9 3063 }
Simon Cooksey 0:fb7af294d5d9 3064
Simon Cooksey 0:fb7af294d5d9 3065 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 3066 defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 3067 static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char **p,
Simon Cooksey 0:fb7af294d5d9 3068 const unsigned char *end )
Simon Cooksey 0:fb7af294d5d9 3069 {
Simon Cooksey 0:fb7af294d5d9 3070 int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
Simon Cooksey 0:fb7af294d5d9 3071 size_t n;
Simon Cooksey 0:fb7af294d5d9 3072
Simon Cooksey 0:fb7af294d5d9 3073 /*
Simon Cooksey 0:fb7af294d5d9 3074 * Receive G^Y mod P, premaster = (G^Y)^X mod P
Simon Cooksey 0:fb7af294d5d9 3075 */
Simon Cooksey 0:fb7af294d5d9 3076 if( *p + 2 > end )
Simon Cooksey 0:fb7af294d5d9 3077 {
Simon Cooksey 0:fb7af294d5d9 3078 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
Simon Cooksey 0:fb7af294d5d9 3079 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 3080 }
Simon Cooksey 0:fb7af294d5d9 3081
Simon Cooksey 0:fb7af294d5d9 3082 n = ( (*p)[0] << 8 ) | (*p)[1];
Simon Cooksey 0:fb7af294d5d9 3083 *p += 2;
Simon Cooksey 0:fb7af294d5d9 3084
Simon Cooksey 0:fb7af294d5d9 3085 if( *p + n > end )
Simon Cooksey 0:fb7af294d5d9 3086 {
Simon Cooksey 0:fb7af294d5d9 3087 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
Simon Cooksey 0:fb7af294d5d9 3088 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 3089 }
Simon Cooksey 0:fb7af294d5d9 3090
Simon Cooksey 0:fb7af294d5d9 3091 if( ( ret = mbedtls_dhm_read_public( &ssl->handshake->dhm_ctx, *p, n ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3092 {
Simon Cooksey 0:fb7af294d5d9 3093 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_read_public", ret );
Simon Cooksey 0:fb7af294d5d9 3094 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP );
Simon Cooksey 0:fb7af294d5d9 3095 }
Simon Cooksey 0:fb7af294d5d9 3096
Simon Cooksey 0:fb7af294d5d9 3097 *p += n;
Simon Cooksey 0:fb7af294d5d9 3098
Simon Cooksey 0:fb7af294d5d9 3099 MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY );
Simon Cooksey 0:fb7af294d5d9 3100
Simon Cooksey 0:fb7af294d5d9 3101 return( ret );
Simon Cooksey 0:fb7af294d5d9 3102 }
Simon Cooksey 0:fb7af294d5d9 3103 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 3104 MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
Simon Cooksey 0:fb7af294d5d9 3105
Simon Cooksey 0:fb7af294d5d9 3106 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 3107 defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 3108 static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 3109 const unsigned char *p,
Simon Cooksey 0:fb7af294d5d9 3110 const unsigned char *end,
Simon Cooksey 0:fb7af294d5d9 3111 size_t pms_offset )
Simon Cooksey 0:fb7af294d5d9 3112 {
Simon Cooksey 0:fb7af294d5d9 3113 int ret;
Simon Cooksey 0:fb7af294d5d9 3114 size_t len = mbedtls_pk_get_len( mbedtls_ssl_own_key( ssl ) );
Simon Cooksey 0:fb7af294d5d9 3115 unsigned char *pms = ssl->handshake->premaster + pms_offset;
Simon Cooksey 0:fb7af294d5d9 3116 unsigned char ver[2];
Simon Cooksey 0:fb7af294d5d9 3117 unsigned char fake_pms[48], peer_pms[48];
Simon Cooksey 0:fb7af294d5d9 3118 unsigned char mask;
Simon Cooksey 0:fb7af294d5d9 3119 size_t i, peer_pmslen;
Simon Cooksey 0:fb7af294d5d9 3120 unsigned int diff;
Simon Cooksey 0:fb7af294d5d9 3121
Simon Cooksey 0:fb7af294d5d9 3122 if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_RSA ) )
Simon Cooksey 0:fb7af294d5d9 3123 {
Simon Cooksey 0:fb7af294d5d9 3124 MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) );
Simon Cooksey 0:fb7af294d5d9 3125 return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
Simon Cooksey 0:fb7af294d5d9 3126 }
Simon Cooksey 0:fb7af294d5d9 3127
Simon Cooksey 0:fb7af294d5d9 3128 /*
Simon Cooksey 0:fb7af294d5d9 3129 * Decrypt the premaster using own private RSA key
Simon Cooksey 0:fb7af294d5d9 3130 */
Simon Cooksey 0:fb7af294d5d9 3131 #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
Simon Cooksey 0:fb7af294d5d9 3132 defined(MBEDTLS_SSL_PROTO_TLS1_2)
Simon Cooksey 0:fb7af294d5d9 3133 if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 )
Simon Cooksey 0:fb7af294d5d9 3134 {
Simon Cooksey 0:fb7af294d5d9 3135 if( *p++ != ( ( len >> 8 ) & 0xFF ) ||
Simon Cooksey 0:fb7af294d5d9 3136 *p++ != ( ( len ) & 0xFF ) )
Simon Cooksey 0:fb7af294d5d9 3137 {
Simon Cooksey 0:fb7af294d5d9 3138 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
Simon Cooksey 0:fb7af294d5d9 3139 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 3140 }
Simon Cooksey 0:fb7af294d5d9 3141 }
Simon Cooksey 0:fb7af294d5d9 3142 #endif
Simon Cooksey 0:fb7af294d5d9 3143
Simon Cooksey 0:fb7af294d5d9 3144 if( p + len != end )
Simon Cooksey 0:fb7af294d5d9 3145 {
Simon Cooksey 0:fb7af294d5d9 3146 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
Simon Cooksey 0:fb7af294d5d9 3147 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 3148 }
Simon Cooksey 0:fb7af294d5d9 3149
Simon Cooksey 0:fb7af294d5d9 3150 mbedtls_ssl_write_version( ssl->handshake->max_major_ver,
Simon Cooksey 0:fb7af294d5d9 3151 ssl->handshake->max_minor_ver,
Simon Cooksey 0:fb7af294d5d9 3152 ssl->conf->transport, ver );
Simon Cooksey 0:fb7af294d5d9 3153
Simon Cooksey 0:fb7af294d5d9 3154 /*
Simon Cooksey 0:fb7af294d5d9 3155 * Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding
Simon Cooksey 0:fb7af294d5d9 3156 * must not cause the connection to end immediately; instead, send a
Simon Cooksey 0:fb7af294d5d9 3157 * bad_record_mac later in the handshake.
Simon Cooksey 0:fb7af294d5d9 3158 * Also, avoid data-dependant branches here to protect against
Simon Cooksey 0:fb7af294d5d9 3159 * timing-based variants.
Simon Cooksey 0:fb7af294d5d9 3160 */
Simon Cooksey 0:fb7af294d5d9 3161 ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) );
Simon Cooksey 0:fb7af294d5d9 3162 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 3163 return( ret );
Simon Cooksey 0:fb7af294d5d9 3164
Simon Cooksey 0:fb7af294d5d9 3165 ret = mbedtls_pk_decrypt( mbedtls_ssl_own_key( ssl ), p, len,
Simon Cooksey 0:fb7af294d5d9 3166 peer_pms, &peer_pmslen,
Simon Cooksey 0:fb7af294d5d9 3167 sizeof( peer_pms ),
Simon Cooksey 0:fb7af294d5d9 3168 ssl->conf->f_rng, ssl->conf->p_rng );
Simon Cooksey 0:fb7af294d5d9 3169
Simon Cooksey 0:fb7af294d5d9 3170 diff = (unsigned int) ret;
Simon Cooksey 0:fb7af294d5d9 3171 diff |= peer_pmslen ^ 48;
Simon Cooksey 0:fb7af294d5d9 3172 diff |= peer_pms[0] ^ ver[0];
Simon Cooksey 0:fb7af294d5d9 3173 diff |= peer_pms[1] ^ ver[1];
Simon Cooksey 0:fb7af294d5d9 3174
Simon Cooksey 0:fb7af294d5d9 3175 #if defined(MBEDTLS_SSL_DEBUG_ALL)
Simon Cooksey 0:fb7af294d5d9 3176 if( diff != 0 )
Simon Cooksey 0:fb7af294d5d9 3177 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
Simon Cooksey 0:fb7af294d5d9 3178 #endif
Simon Cooksey 0:fb7af294d5d9 3179
Simon Cooksey 0:fb7af294d5d9 3180 if( sizeof( ssl->handshake->premaster ) < pms_offset ||
Simon Cooksey 0:fb7af294d5d9 3181 sizeof( ssl->handshake->premaster ) - pms_offset < 48 )
Simon Cooksey 0:fb7af294d5d9 3182 {
Simon Cooksey 0:fb7af294d5d9 3183 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
Simon Cooksey 0:fb7af294d5d9 3184 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
Simon Cooksey 0:fb7af294d5d9 3185 }
Simon Cooksey 0:fb7af294d5d9 3186 ssl->handshake->pmslen = 48;
Simon Cooksey 0:fb7af294d5d9 3187
Simon Cooksey 0:fb7af294d5d9 3188 /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */
Simon Cooksey 0:fb7af294d5d9 3189 /* MSVC has a warning about unary minus on unsigned, but this is
Simon Cooksey 0:fb7af294d5d9 3190 * well-defined and precisely what we want to do here */
Simon Cooksey 0:fb7af294d5d9 3191 #if defined(_MSC_VER)
Simon Cooksey 0:fb7af294d5d9 3192 #pragma warning( push )
Simon Cooksey 0:fb7af294d5d9 3193 #pragma warning( disable : 4146 )
Simon Cooksey 0:fb7af294d5d9 3194 #endif
Simon Cooksey 0:fb7af294d5d9 3195 mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) );
Simon Cooksey 0:fb7af294d5d9 3196 #if defined(_MSC_VER)
Simon Cooksey 0:fb7af294d5d9 3197 #pragma warning( pop )
Simon Cooksey 0:fb7af294d5d9 3198 #endif
Simon Cooksey 0:fb7af294d5d9 3199
Simon Cooksey 0:fb7af294d5d9 3200 for( i = 0; i < ssl->handshake->pmslen; i++ )
Simon Cooksey 0:fb7af294d5d9 3201 pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] );
Simon Cooksey 0:fb7af294d5d9 3202
Simon Cooksey 0:fb7af294d5d9 3203 return( 0 );
Simon Cooksey 0:fb7af294d5d9 3204 }
Simon Cooksey 0:fb7af294d5d9 3205 #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 3206 MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
Simon Cooksey 0:fb7af294d5d9 3207
Simon Cooksey 0:fb7af294d5d9 3208 #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 3209 static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned char **p,
Simon Cooksey 0:fb7af294d5d9 3210 const unsigned char *end )
Simon Cooksey 0:fb7af294d5d9 3211 {
Simon Cooksey 0:fb7af294d5d9 3212 int ret = 0;
Simon Cooksey 0:fb7af294d5d9 3213 size_t n;
Simon Cooksey 0:fb7af294d5d9 3214
Simon Cooksey 0:fb7af294d5d9 3215 if( ssl->conf->f_psk == NULL &&
Simon Cooksey 0:fb7af294d5d9 3216 ( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL ||
Simon Cooksey 0:fb7af294d5d9 3217 ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) )
Simon Cooksey 0:fb7af294d5d9 3218 {
Simon Cooksey 0:fb7af294d5d9 3219 MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no pre-shared key" ) );
Simon Cooksey 0:fb7af294d5d9 3220 return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
Simon Cooksey 0:fb7af294d5d9 3221 }
Simon Cooksey 0:fb7af294d5d9 3222
Simon Cooksey 0:fb7af294d5d9 3223 /*
Simon Cooksey 0:fb7af294d5d9 3224 * Receive client pre-shared key identity name
Simon Cooksey 0:fb7af294d5d9 3225 */
Simon Cooksey 0:fb7af294d5d9 3226 if( *p + 2 > end )
Simon Cooksey 0:fb7af294d5d9 3227 {
Simon Cooksey 0:fb7af294d5d9 3228 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
Simon Cooksey 0:fb7af294d5d9 3229 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 3230 }
Simon Cooksey 0:fb7af294d5d9 3231
Simon Cooksey 0:fb7af294d5d9 3232 n = ( (*p)[0] << 8 ) | (*p)[1];
Simon Cooksey 0:fb7af294d5d9 3233 *p += 2;
Simon Cooksey 0:fb7af294d5d9 3234
Simon Cooksey 0:fb7af294d5d9 3235 if( n < 1 || n > 65535 || *p + n > end )
Simon Cooksey 0:fb7af294d5d9 3236 {
Simon Cooksey 0:fb7af294d5d9 3237 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
Simon Cooksey 0:fb7af294d5d9 3238 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 3239 }
Simon Cooksey 0:fb7af294d5d9 3240
Simon Cooksey 0:fb7af294d5d9 3241 if( ssl->conf->f_psk != NULL )
Simon Cooksey 0:fb7af294d5d9 3242 {
Simon Cooksey 0:fb7af294d5d9 3243 if( ssl->conf->f_psk( ssl->conf->p_psk, ssl, *p, n ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3244 ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY;
Simon Cooksey 0:fb7af294d5d9 3245 }
Simon Cooksey 0:fb7af294d5d9 3246 else
Simon Cooksey 0:fb7af294d5d9 3247 {
Simon Cooksey 0:fb7af294d5d9 3248 /* Identity is not a big secret since clients send it in the clear,
Simon Cooksey 0:fb7af294d5d9 3249 * but treat it carefully anyway, just in case */
Simon Cooksey 0:fb7af294d5d9 3250 if( n != ssl->conf->psk_identity_len ||
Simon Cooksey 0:fb7af294d5d9 3251 mbedtls_ssl_safer_memcmp( ssl->conf->psk_identity, *p, n ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3252 {
Simon Cooksey 0:fb7af294d5d9 3253 ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY;
Simon Cooksey 0:fb7af294d5d9 3254 }
Simon Cooksey 0:fb7af294d5d9 3255 }
Simon Cooksey 0:fb7af294d5d9 3256
Simon Cooksey 0:fb7af294d5d9 3257 if( ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY )
Simon Cooksey 0:fb7af294d5d9 3258 {
Simon Cooksey 0:fb7af294d5d9 3259 MBEDTLS_SSL_DEBUG_BUF( 3, "Unknown PSK identity", *p, n );
Simon Cooksey 0:fb7af294d5d9 3260 if( ( ret = mbedtls_ssl_send_alert_message( ssl,
Simon Cooksey 0:fb7af294d5d9 3261 MBEDTLS_SSL_ALERT_LEVEL_FATAL,
Simon Cooksey 0:fb7af294d5d9 3262 MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3263 {
Simon Cooksey 0:fb7af294d5d9 3264 return( ret );
Simon Cooksey 0:fb7af294d5d9 3265 }
Simon Cooksey 0:fb7af294d5d9 3266
Simon Cooksey 0:fb7af294d5d9 3267 return( MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY );
Simon Cooksey 0:fb7af294d5d9 3268 }
Simon Cooksey 0:fb7af294d5d9 3269
Simon Cooksey 0:fb7af294d5d9 3270 *p += n;
Simon Cooksey 0:fb7af294d5d9 3271
Simon Cooksey 0:fb7af294d5d9 3272 return( 0 );
Simon Cooksey 0:fb7af294d5d9 3273 }
Simon Cooksey 0:fb7af294d5d9 3274 #endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
Simon Cooksey 0:fb7af294d5d9 3275
Simon Cooksey 0:fb7af294d5d9 3276 static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 3277 {
Simon Cooksey 0:fb7af294d5d9 3278 int ret;
Simon Cooksey 0:fb7af294d5d9 3279 const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
Simon Cooksey 0:fb7af294d5d9 3280 unsigned char *p, *end;
Simon Cooksey 0:fb7af294d5d9 3281
Simon Cooksey 0:fb7af294d5d9 3282 ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
Simon Cooksey 0:fb7af294d5d9 3283
Simon Cooksey 0:fb7af294d5d9 3284 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) );
Simon Cooksey 0:fb7af294d5d9 3285
Simon Cooksey 0:fb7af294d5d9 3286 if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3287 {
Simon Cooksey 0:fb7af294d5d9 3288 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
Simon Cooksey 0:fb7af294d5d9 3289 return( ret );
Simon Cooksey 0:fb7af294d5d9 3290 }
Simon Cooksey 0:fb7af294d5d9 3291
Simon Cooksey 0:fb7af294d5d9 3292 p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
Simon Cooksey 0:fb7af294d5d9 3293 end = ssl->in_msg + ssl->in_hslen;
Simon Cooksey 0:fb7af294d5d9 3294
Simon Cooksey 0:fb7af294d5d9 3295 if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
Simon Cooksey 0:fb7af294d5d9 3296 {
Simon Cooksey 0:fb7af294d5d9 3297 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
Simon Cooksey 0:fb7af294d5d9 3298 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 3299 }
Simon Cooksey 0:fb7af294d5d9 3300
Simon Cooksey 0:fb7af294d5d9 3301 if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE )
Simon Cooksey 0:fb7af294d5d9 3302 {
Simon Cooksey 0:fb7af294d5d9 3303 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
Simon Cooksey 0:fb7af294d5d9 3304 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 3305 }
Simon Cooksey 0:fb7af294d5d9 3306
Simon Cooksey 0:fb7af294d5d9 3307 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 3308 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA )
Simon Cooksey 0:fb7af294d5d9 3309 {
Simon Cooksey 0:fb7af294d5d9 3310 if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3311 {
Simon Cooksey 0:fb7af294d5d9 3312 MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret );
Simon Cooksey 0:fb7af294d5d9 3313 return( ret );
Simon Cooksey 0:fb7af294d5d9 3314 }
Simon Cooksey 0:fb7af294d5d9 3315
Simon Cooksey 0:fb7af294d5d9 3316 if( p != end )
Simon Cooksey 0:fb7af294d5d9 3317 {
Simon Cooksey 0:fb7af294d5d9 3318 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) );
Simon Cooksey 0:fb7af294d5d9 3319 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 3320 }
Simon Cooksey 0:fb7af294d5d9 3321
Simon Cooksey 0:fb7af294d5d9 3322 if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx,
Simon Cooksey 0:fb7af294d5d9 3323 ssl->handshake->premaster,
Simon Cooksey 0:fb7af294d5d9 3324 MBEDTLS_PREMASTER_SIZE,
Simon Cooksey 0:fb7af294d5d9 3325 &ssl->handshake->pmslen,
Simon Cooksey 0:fb7af294d5d9 3326 ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3327 {
Simon Cooksey 0:fb7af294d5d9 3328 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret );
Simon Cooksey 0:fb7af294d5d9 3329 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS );
Simon Cooksey 0:fb7af294d5d9 3330 }
Simon Cooksey 0:fb7af294d5d9 3331
Simon Cooksey 0:fb7af294d5d9 3332 MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K );
Simon Cooksey 0:fb7af294d5d9 3333 }
Simon Cooksey 0:fb7af294d5d9 3334 else
Simon Cooksey 0:fb7af294d5d9 3335 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */
Simon Cooksey 0:fb7af294d5d9 3336 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 3337 defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 3338 defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 3339 defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 3340 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
Simon Cooksey 0:fb7af294d5d9 3341 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ||
Simon Cooksey 0:fb7af294d5d9 3342 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA ||
Simon Cooksey 0:fb7af294d5d9 3343 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA )
Simon Cooksey 0:fb7af294d5d9 3344 {
Simon Cooksey 0:fb7af294d5d9 3345 if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx,
Simon Cooksey 0:fb7af294d5d9 3346 p, end - p) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3347 {
Simon Cooksey 0:fb7af294d5d9 3348 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret );
Simon Cooksey 0:fb7af294d5d9 3349 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP );
Simon Cooksey 0:fb7af294d5d9 3350 }
Simon Cooksey 0:fb7af294d5d9 3351
Simon Cooksey 0:fb7af294d5d9 3352 MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp );
Simon Cooksey 0:fb7af294d5d9 3353
Simon Cooksey 0:fb7af294d5d9 3354 if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx,
Simon Cooksey 0:fb7af294d5d9 3355 &ssl->handshake->pmslen,
Simon Cooksey 0:fb7af294d5d9 3356 ssl->handshake->premaster,
Simon Cooksey 0:fb7af294d5d9 3357 MBEDTLS_MPI_MAX_SIZE,
Simon Cooksey 0:fb7af294d5d9 3358 ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3359 {
Simon Cooksey 0:fb7af294d5d9 3360 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret );
Simon Cooksey 0:fb7af294d5d9 3361 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS );
Simon Cooksey 0:fb7af294d5d9 3362 }
Simon Cooksey 0:fb7af294d5d9 3363
Simon Cooksey 0:fb7af294d5d9 3364 MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z ", &ssl->handshake->ecdh_ctx.z );
Simon Cooksey 0:fb7af294d5d9 3365 }
Simon Cooksey 0:fb7af294d5d9 3366 else
Simon Cooksey 0:fb7af294d5d9 3367 #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 3368 MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 3369 MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 3370 MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
Simon Cooksey 0:fb7af294d5d9 3371 #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 3372 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK )
Simon Cooksey 0:fb7af294d5d9 3373 {
Simon Cooksey 0:fb7af294d5d9 3374 if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3375 {
Simon Cooksey 0:fb7af294d5d9 3376 MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret );
Simon Cooksey 0:fb7af294d5d9 3377 return( ret );
Simon Cooksey 0:fb7af294d5d9 3378 }
Simon Cooksey 0:fb7af294d5d9 3379
Simon Cooksey 0:fb7af294d5d9 3380 if( p != end )
Simon Cooksey 0:fb7af294d5d9 3381 {
Simon Cooksey 0:fb7af294d5d9 3382 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) );
Simon Cooksey 0:fb7af294d5d9 3383 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 3384 }
Simon Cooksey 0:fb7af294d5d9 3385
Simon Cooksey 0:fb7af294d5d9 3386 if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl,
Simon Cooksey 0:fb7af294d5d9 3387 ciphersuite_info->key_exchange ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3388 {
Simon Cooksey 0:fb7af294d5d9 3389 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret );
Simon Cooksey 0:fb7af294d5d9 3390 return( ret );
Simon Cooksey 0:fb7af294d5d9 3391 }
Simon Cooksey 0:fb7af294d5d9 3392 }
Simon Cooksey 0:fb7af294d5d9 3393 else
Simon Cooksey 0:fb7af294d5d9 3394 #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
Simon Cooksey 0:fb7af294d5d9 3395 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 3396 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
Simon Cooksey 0:fb7af294d5d9 3397 {
Simon Cooksey 0:fb7af294d5d9 3398 if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3399 {
Simon Cooksey 0:fb7af294d5d9 3400 MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret );
Simon Cooksey 0:fb7af294d5d9 3401 return( ret );
Simon Cooksey 0:fb7af294d5d9 3402 }
Simon Cooksey 0:fb7af294d5d9 3403
Simon Cooksey 0:fb7af294d5d9 3404 if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3405 {
Simon Cooksey 0:fb7af294d5d9 3406 MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_encrypted_pms" ), ret );
Simon Cooksey 0:fb7af294d5d9 3407 return( ret );
Simon Cooksey 0:fb7af294d5d9 3408 }
Simon Cooksey 0:fb7af294d5d9 3409
Simon Cooksey 0:fb7af294d5d9 3410 if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl,
Simon Cooksey 0:fb7af294d5d9 3411 ciphersuite_info->key_exchange ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3412 {
Simon Cooksey 0:fb7af294d5d9 3413 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret );
Simon Cooksey 0:fb7af294d5d9 3414 return( ret );
Simon Cooksey 0:fb7af294d5d9 3415 }
Simon Cooksey 0:fb7af294d5d9 3416 }
Simon Cooksey 0:fb7af294d5d9 3417 else
Simon Cooksey 0:fb7af294d5d9 3418 #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
Simon Cooksey 0:fb7af294d5d9 3419 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 3420 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK )
Simon Cooksey 0:fb7af294d5d9 3421 {
Simon Cooksey 0:fb7af294d5d9 3422 if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3423 {
Simon Cooksey 0:fb7af294d5d9 3424 MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret );
Simon Cooksey 0:fb7af294d5d9 3425 return( ret );
Simon Cooksey 0:fb7af294d5d9 3426 }
Simon Cooksey 0:fb7af294d5d9 3427 if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3428 {
Simon Cooksey 0:fb7af294d5d9 3429 MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret );
Simon Cooksey 0:fb7af294d5d9 3430 return( ret );
Simon Cooksey 0:fb7af294d5d9 3431 }
Simon Cooksey 0:fb7af294d5d9 3432
Simon Cooksey 0:fb7af294d5d9 3433 if( p != end )
Simon Cooksey 0:fb7af294d5d9 3434 {
Simon Cooksey 0:fb7af294d5d9 3435 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) );
Simon Cooksey 0:fb7af294d5d9 3436 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 3437 }
Simon Cooksey 0:fb7af294d5d9 3438
Simon Cooksey 0:fb7af294d5d9 3439 if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl,
Simon Cooksey 0:fb7af294d5d9 3440 ciphersuite_info->key_exchange ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3441 {
Simon Cooksey 0:fb7af294d5d9 3442 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret );
Simon Cooksey 0:fb7af294d5d9 3443 return( ret );
Simon Cooksey 0:fb7af294d5d9 3444 }
Simon Cooksey 0:fb7af294d5d9 3445 }
Simon Cooksey 0:fb7af294d5d9 3446 else
Simon Cooksey 0:fb7af294d5d9 3447 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
Simon Cooksey 0:fb7af294d5d9 3448 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 3449 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
Simon Cooksey 0:fb7af294d5d9 3450 {
Simon Cooksey 0:fb7af294d5d9 3451 if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3452 {
Simon Cooksey 0:fb7af294d5d9 3453 MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret );
Simon Cooksey 0:fb7af294d5d9 3454 return( ret );
Simon Cooksey 0:fb7af294d5d9 3455 }
Simon Cooksey 0:fb7af294d5d9 3456
Simon Cooksey 0:fb7af294d5d9 3457 if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx,
Simon Cooksey 0:fb7af294d5d9 3458 p, end - p ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3459 {
Simon Cooksey 0:fb7af294d5d9 3460 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret );
Simon Cooksey 0:fb7af294d5d9 3461 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP );
Simon Cooksey 0:fb7af294d5d9 3462 }
Simon Cooksey 0:fb7af294d5d9 3463
Simon Cooksey 0:fb7af294d5d9 3464 MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp );
Simon Cooksey 0:fb7af294d5d9 3465
Simon Cooksey 0:fb7af294d5d9 3466 if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl,
Simon Cooksey 0:fb7af294d5d9 3467 ciphersuite_info->key_exchange ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3468 {
Simon Cooksey 0:fb7af294d5d9 3469 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret );
Simon Cooksey 0:fb7af294d5d9 3470 return( ret );
Simon Cooksey 0:fb7af294d5d9 3471 }
Simon Cooksey 0:fb7af294d5d9 3472 }
Simon Cooksey 0:fb7af294d5d9 3473 else
Simon Cooksey 0:fb7af294d5d9 3474 #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
Simon Cooksey 0:fb7af294d5d9 3475 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 3476 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA )
Simon Cooksey 0:fb7af294d5d9 3477 {
Simon Cooksey 0:fb7af294d5d9 3478 if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 0 ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3479 {
Simon Cooksey 0:fb7af294d5d9 3480 MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_parse_encrypted_pms_secret" ), ret );
Simon Cooksey 0:fb7af294d5d9 3481 return( ret );
Simon Cooksey 0:fb7af294d5d9 3482 }
Simon Cooksey 0:fb7af294d5d9 3483 }
Simon Cooksey 0:fb7af294d5d9 3484 else
Simon Cooksey 0:fb7af294d5d9 3485 #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */
Simon Cooksey 0:fb7af294d5d9 3486 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 3487 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
Simon Cooksey 0:fb7af294d5d9 3488 {
Simon Cooksey 0:fb7af294d5d9 3489 ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx,
Simon Cooksey 0:fb7af294d5d9 3490 p, end - p );
Simon Cooksey 0:fb7af294d5d9 3491 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 3492 {
Simon Cooksey 0:fb7af294d5d9 3493 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret );
Simon Cooksey 0:fb7af294d5d9 3494 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 3495 }
Simon Cooksey 0:fb7af294d5d9 3496
Simon Cooksey 0:fb7af294d5d9 3497 ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx,
Simon Cooksey 0:fb7af294d5d9 3498 ssl->handshake->premaster, 32, &ssl->handshake->pmslen,
Simon Cooksey 0:fb7af294d5d9 3499 ssl->conf->f_rng, ssl->conf->p_rng );
Simon Cooksey 0:fb7af294d5d9 3500 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 3501 {
Simon Cooksey 0:fb7af294d5d9 3502 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret );
Simon Cooksey 0:fb7af294d5d9 3503 return( ret );
Simon Cooksey 0:fb7af294d5d9 3504 }
Simon Cooksey 0:fb7af294d5d9 3505 }
Simon Cooksey 0:fb7af294d5d9 3506 else
Simon Cooksey 0:fb7af294d5d9 3507 #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
Simon Cooksey 0:fb7af294d5d9 3508 {
Simon Cooksey 0:fb7af294d5d9 3509 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
Simon Cooksey 0:fb7af294d5d9 3510 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
Simon Cooksey 0:fb7af294d5d9 3511 }
Simon Cooksey 0:fb7af294d5d9 3512
Simon Cooksey 0:fb7af294d5d9 3513 if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3514 {
Simon Cooksey 0:fb7af294d5d9 3515 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
Simon Cooksey 0:fb7af294d5d9 3516 return( ret );
Simon Cooksey 0:fb7af294d5d9 3517 }
Simon Cooksey 0:fb7af294d5d9 3518
Simon Cooksey 0:fb7af294d5d9 3519 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 3520
Simon Cooksey 0:fb7af294d5d9 3521 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) );
Simon Cooksey 0:fb7af294d5d9 3522
Simon Cooksey 0:fb7af294d5d9 3523 return( 0 );
Simon Cooksey 0:fb7af294d5d9 3524 }
Simon Cooksey 0:fb7af294d5d9 3525
Simon Cooksey 0:fb7af294d5d9 3526 #if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \
Simon Cooksey 0:fb7af294d5d9 3527 !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \
Simon Cooksey 0:fb7af294d5d9 3528 !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \
Simon Cooksey 0:fb7af294d5d9 3529 !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
Simon Cooksey 0:fb7af294d5d9 3530 !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \
Simon Cooksey 0:fb7af294d5d9 3531 !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 3532 static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 3533 {
Simon Cooksey 0:fb7af294d5d9 3534 const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
Simon Cooksey 0:fb7af294d5d9 3535
Simon Cooksey 0:fb7af294d5d9 3536 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
Simon Cooksey 0:fb7af294d5d9 3537
Simon Cooksey 0:fb7af294d5d9 3538 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
Simon Cooksey 0:fb7af294d5d9 3539 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
Simon Cooksey 0:fb7af294d5d9 3540 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
Simon Cooksey 0:fb7af294d5d9 3541 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
Simon Cooksey 0:fb7af294d5d9 3542 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
Simon Cooksey 0:fb7af294d5d9 3543 {
Simon Cooksey 0:fb7af294d5d9 3544 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
Simon Cooksey 0:fb7af294d5d9 3545 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 3546 return( 0 );
Simon Cooksey 0:fb7af294d5d9 3547 }
Simon Cooksey 0:fb7af294d5d9 3548
Simon Cooksey 0:fb7af294d5d9 3549 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
Simon Cooksey 0:fb7af294d5d9 3550 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
Simon Cooksey 0:fb7af294d5d9 3551 }
Simon Cooksey 0:fb7af294d5d9 3552 #else
Simon Cooksey 0:fb7af294d5d9 3553 static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 3554 {
Simon Cooksey 0:fb7af294d5d9 3555 int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
Simon Cooksey 0:fb7af294d5d9 3556 size_t i, sig_len;
Simon Cooksey 0:fb7af294d5d9 3557 unsigned char hash[48];
Simon Cooksey 0:fb7af294d5d9 3558 unsigned char *hash_start = hash;
Simon Cooksey 0:fb7af294d5d9 3559 size_t hashlen;
Simon Cooksey 0:fb7af294d5d9 3560 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
Simon Cooksey 0:fb7af294d5d9 3561 mbedtls_pk_type_t pk_alg;
Simon Cooksey 0:fb7af294d5d9 3562 #endif
Simon Cooksey 0:fb7af294d5d9 3563 mbedtls_md_type_t md_alg;
Simon Cooksey 0:fb7af294d5d9 3564 const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
Simon Cooksey 0:fb7af294d5d9 3565
Simon Cooksey 0:fb7af294d5d9 3566 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
Simon Cooksey 0:fb7af294d5d9 3567
Simon Cooksey 0:fb7af294d5d9 3568 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
Simon Cooksey 0:fb7af294d5d9 3569 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
Simon Cooksey 0:fb7af294d5d9 3570 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
Simon Cooksey 0:fb7af294d5d9 3571 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
Simon Cooksey 0:fb7af294d5d9 3572 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ||
Simon Cooksey 0:fb7af294d5d9 3573 ssl->session_negotiate->peer_cert == NULL )
Simon Cooksey 0:fb7af294d5d9 3574 {
Simon Cooksey 0:fb7af294d5d9 3575 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
Simon Cooksey 0:fb7af294d5d9 3576 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 3577 return( 0 );
Simon Cooksey 0:fb7af294d5d9 3578 }
Simon Cooksey 0:fb7af294d5d9 3579
Simon Cooksey 0:fb7af294d5d9 3580 /* Read the message without adding it to the checksum */
Simon Cooksey 0:fb7af294d5d9 3581 do {
Simon Cooksey 0:fb7af294d5d9 3582
Simon Cooksey 0:fb7af294d5d9 3583 if( ( ret = mbedtls_ssl_read_record_layer( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3584 {
Simon Cooksey 0:fb7af294d5d9 3585 MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret );
Simon Cooksey 0:fb7af294d5d9 3586 return( ret );
Simon Cooksey 0:fb7af294d5d9 3587 }
Simon Cooksey 0:fb7af294d5d9 3588
Simon Cooksey 0:fb7af294d5d9 3589 ret = mbedtls_ssl_handle_message_type( ssl );
Simon Cooksey 0:fb7af294d5d9 3590
Simon Cooksey 0:fb7af294d5d9 3591 } while( MBEDTLS_ERR_SSL_NON_FATAL == ret );
Simon Cooksey 0:fb7af294d5d9 3592
Simon Cooksey 0:fb7af294d5d9 3593 if( 0 != ret )
Simon Cooksey 0:fb7af294d5d9 3594 {
Simon Cooksey 0:fb7af294d5d9 3595 MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret );
Simon Cooksey 0:fb7af294d5d9 3596 return( ret );
Simon Cooksey 0:fb7af294d5d9 3597 }
Simon Cooksey 0:fb7af294d5d9 3598
Simon Cooksey 0:fb7af294d5d9 3599 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 3600
Simon Cooksey 0:fb7af294d5d9 3601 /* Process the message contents */
Simon Cooksey 0:fb7af294d5d9 3602 if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ||
Simon Cooksey 0:fb7af294d5d9 3603 ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE_VERIFY )
Simon Cooksey 0:fb7af294d5d9 3604 {
Simon Cooksey 0:fb7af294d5d9 3605 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
Simon Cooksey 0:fb7af294d5d9 3606 return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
Simon Cooksey 0:fb7af294d5d9 3607 }
Simon Cooksey 0:fb7af294d5d9 3608
Simon Cooksey 0:fb7af294d5d9 3609 i = mbedtls_ssl_hs_hdr_len( ssl );
Simon Cooksey 0:fb7af294d5d9 3610
Simon Cooksey 0:fb7af294d5d9 3611 /*
Simon Cooksey 0:fb7af294d5d9 3612 * struct {
Simon Cooksey 0:fb7af294d5d9 3613 * SignatureAndHashAlgorithm algorithm; -- TLS 1.2 only
Simon Cooksey 0:fb7af294d5d9 3614 * opaque signature<0..2^16-1>;
Simon Cooksey 0:fb7af294d5d9 3615 * } DigitallySigned;
Simon Cooksey 0:fb7af294d5d9 3616 */
Simon Cooksey 0:fb7af294d5d9 3617 #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
Simon Cooksey 0:fb7af294d5d9 3618 defined(MBEDTLS_SSL_PROTO_TLS1_1)
Simon Cooksey 0:fb7af294d5d9 3619 if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 )
Simon Cooksey 0:fb7af294d5d9 3620 {
Simon Cooksey 0:fb7af294d5d9 3621 md_alg = MBEDTLS_MD_NONE;
Simon Cooksey 0:fb7af294d5d9 3622 hashlen = 36;
Simon Cooksey 0:fb7af294d5d9 3623
Simon Cooksey 0:fb7af294d5d9 3624 /* For ECDSA, use SHA-1, not MD-5 + SHA-1 */
Simon Cooksey 0:fb7af294d5d9 3625 if( mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk,
Simon Cooksey 0:fb7af294d5d9 3626 MBEDTLS_PK_ECDSA ) )
Simon Cooksey 0:fb7af294d5d9 3627 {
Simon Cooksey 0:fb7af294d5d9 3628 hash_start += 16;
Simon Cooksey 0:fb7af294d5d9 3629 hashlen -= 16;
Simon Cooksey 0:fb7af294d5d9 3630 md_alg = MBEDTLS_MD_SHA1;
Simon Cooksey 0:fb7af294d5d9 3631 }
Simon Cooksey 0:fb7af294d5d9 3632 }
Simon Cooksey 0:fb7af294d5d9 3633 else
Simon Cooksey 0:fb7af294d5d9 3634 #endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 ||
Simon Cooksey 0:fb7af294d5d9 3635 MBEDTLS_SSL_PROTO_TLS1_1 */
Simon Cooksey 0:fb7af294d5d9 3636 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
Simon Cooksey 0:fb7af294d5d9 3637 if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
Simon Cooksey 0:fb7af294d5d9 3638 {
Simon Cooksey 0:fb7af294d5d9 3639 if( i + 2 > ssl->in_hslen )
Simon Cooksey 0:fb7af294d5d9 3640 {
Simon Cooksey 0:fb7af294d5d9 3641 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
Simon Cooksey 0:fb7af294d5d9 3642 return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
Simon Cooksey 0:fb7af294d5d9 3643 }
Simon Cooksey 0:fb7af294d5d9 3644
Simon Cooksey 0:fb7af294d5d9 3645 /*
Simon Cooksey 0:fb7af294d5d9 3646 * Hash
Simon Cooksey 0:fb7af294d5d9 3647 */
Simon Cooksey 0:fb7af294d5d9 3648 md_alg = mbedtls_ssl_md_alg_from_hash( ssl->in_msg[i] );
Simon Cooksey 0:fb7af294d5d9 3649
Simon Cooksey 0:fb7af294d5d9 3650 if( md_alg == MBEDTLS_MD_NONE || mbedtls_ssl_set_calc_verify_md( ssl, ssl->in_msg[i] ) )
Simon Cooksey 0:fb7af294d5d9 3651 {
Simon Cooksey 0:fb7af294d5d9 3652 MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg"
Simon Cooksey 0:fb7af294d5d9 3653 " for verify message" ) );
Simon Cooksey 0:fb7af294d5d9 3654 return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
Simon Cooksey 0:fb7af294d5d9 3655 }
Simon Cooksey 0:fb7af294d5d9 3656
Simon Cooksey 0:fb7af294d5d9 3657 #if !defined(MBEDTLS_MD_SHA1)
Simon Cooksey 0:fb7af294d5d9 3658 if( MBEDTLS_MD_SHA1 == md_alg )
Simon Cooksey 0:fb7af294d5d9 3659 hash_start += 16;
Simon Cooksey 0:fb7af294d5d9 3660 #endif
Simon Cooksey 0:fb7af294d5d9 3661
Simon Cooksey 0:fb7af294d5d9 3662 /* Info from md_alg will be used instead */
Simon Cooksey 0:fb7af294d5d9 3663 hashlen = 0;
Simon Cooksey 0:fb7af294d5d9 3664
Simon Cooksey 0:fb7af294d5d9 3665 i++;
Simon Cooksey 0:fb7af294d5d9 3666
Simon Cooksey 0:fb7af294d5d9 3667 /*
Simon Cooksey 0:fb7af294d5d9 3668 * Signature
Simon Cooksey 0:fb7af294d5d9 3669 */
Simon Cooksey 0:fb7af294d5d9 3670 if( ( pk_alg = mbedtls_ssl_pk_alg_from_sig( ssl->in_msg[i] ) )
Simon Cooksey 0:fb7af294d5d9 3671 == MBEDTLS_PK_NONE )
Simon Cooksey 0:fb7af294d5d9 3672 {
Simon Cooksey 0:fb7af294d5d9 3673 MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg"
Simon Cooksey 0:fb7af294d5d9 3674 " for verify message" ) );
Simon Cooksey 0:fb7af294d5d9 3675 return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
Simon Cooksey 0:fb7af294d5d9 3676 }
Simon Cooksey 0:fb7af294d5d9 3677
Simon Cooksey 0:fb7af294d5d9 3678 /*
Simon Cooksey 0:fb7af294d5d9 3679 * Check the certificate's key type matches the signature alg
Simon Cooksey 0:fb7af294d5d9 3680 */
Simon Cooksey 0:fb7af294d5d9 3681 if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) )
Simon Cooksey 0:fb7af294d5d9 3682 {
Simon Cooksey 0:fb7af294d5d9 3683 MBEDTLS_SSL_DEBUG_MSG( 1, ( "sig_alg doesn't match cert key" ) );
Simon Cooksey 0:fb7af294d5d9 3684 return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
Simon Cooksey 0:fb7af294d5d9 3685 }
Simon Cooksey 0:fb7af294d5d9 3686
Simon Cooksey 0:fb7af294d5d9 3687 i++;
Simon Cooksey 0:fb7af294d5d9 3688 }
Simon Cooksey 0:fb7af294d5d9 3689 else
Simon Cooksey 0:fb7af294d5d9 3690 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
Simon Cooksey 0:fb7af294d5d9 3691 {
Simon Cooksey 0:fb7af294d5d9 3692 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
Simon Cooksey 0:fb7af294d5d9 3693 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
Simon Cooksey 0:fb7af294d5d9 3694 }
Simon Cooksey 0:fb7af294d5d9 3695
Simon Cooksey 0:fb7af294d5d9 3696 if( i + 2 > ssl->in_hslen )
Simon Cooksey 0:fb7af294d5d9 3697 {
Simon Cooksey 0:fb7af294d5d9 3698 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
Simon Cooksey 0:fb7af294d5d9 3699 return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
Simon Cooksey 0:fb7af294d5d9 3700 }
Simon Cooksey 0:fb7af294d5d9 3701
Simon Cooksey 0:fb7af294d5d9 3702 sig_len = ( ssl->in_msg[i] << 8 ) | ssl->in_msg[i+1];
Simon Cooksey 0:fb7af294d5d9 3703 i += 2;
Simon Cooksey 0:fb7af294d5d9 3704
Simon Cooksey 0:fb7af294d5d9 3705 if( i + sig_len != ssl->in_hslen )
Simon Cooksey 0:fb7af294d5d9 3706 {
Simon Cooksey 0:fb7af294d5d9 3707 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
Simon Cooksey 0:fb7af294d5d9 3708 return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
Simon Cooksey 0:fb7af294d5d9 3709 }
Simon Cooksey 0:fb7af294d5d9 3710
Simon Cooksey 0:fb7af294d5d9 3711 /* Calculate hash and verify signature */
Simon Cooksey 0:fb7af294d5d9 3712 ssl->handshake->calc_verify( ssl, hash );
Simon Cooksey 0:fb7af294d5d9 3713
Simon Cooksey 0:fb7af294d5d9 3714 if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk,
Simon Cooksey 0:fb7af294d5d9 3715 md_alg, hash_start, hashlen,
Simon Cooksey 0:fb7af294d5d9 3716 ssl->in_msg + i, sig_len ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3717 {
Simon Cooksey 0:fb7af294d5d9 3718 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret );
Simon Cooksey 0:fb7af294d5d9 3719 return( ret );
Simon Cooksey 0:fb7af294d5d9 3720 }
Simon Cooksey 0:fb7af294d5d9 3721
Simon Cooksey 0:fb7af294d5d9 3722 mbedtls_ssl_update_handshake_status( ssl );
Simon Cooksey 0:fb7af294d5d9 3723
Simon Cooksey 0:fb7af294d5d9 3724 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) );
Simon Cooksey 0:fb7af294d5d9 3725
Simon Cooksey 0:fb7af294d5d9 3726 return( ret );
Simon Cooksey 0:fb7af294d5d9 3727 }
Simon Cooksey 0:fb7af294d5d9 3728 #endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 3729 !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 3730 !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 3731 !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 3732 !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 3733 !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
Simon Cooksey 0:fb7af294d5d9 3734
Simon Cooksey 0:fb7af294d5d9 3735 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
Simon Cooksey 0:fb7af294d5d9 3736 static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 3737 {
Simon Cooksey 0:fb7af294d5d9 3738 int ret;
Simon Cooksey 0:fb7af294d5d9 3739 size_t tlen;
Simon Cooksey 0:fb7af294d5d9 3740 uint32_t lifetime;
Simon Cooksey 0:fb7af294d5d9 3741
Simon Cooksey 0:fb7af294d5d9 3742 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write new session ticket" ) );
Simon Cooksey 0:fb7af294d5d9 3743
Simon Cooksey 0:fb7af294d5d9 3744 ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
Simon Cooksey 0:fb7af294d5d9 3745 ssl->out_msg[0] = MBEDTLS_SSL_HS_NEW_SESSION_TICKET;
Simon Cooksey 0:fb7af294d5d9 3746
Simon Cooksey 0:fb7af294d5d9 3747 /*
Simon Cooksey 0:fb7af294d5d9 3748 * struct {
Simon Cooksey 0:fb7af294d5d9 3749 * uint32 ticket_lifetime_hint;
Simon Cooksey 0:fb7af294d5d9 3750 * opaque ticket<0..2^16-1>;
Simon Cooksey 0:fb7af294d5d9 3751 * } NewSessionTicket;
Simon Cooksey 0:fb7af294d5d9 3752 *
Simon Cooksey 0:fb7af294d5d9 3753 * 4 . 7 ticket_lifetime_hint (0 = unspecified)
Simon Cooksey 0:fb7af294d5d9 3754 * 8 . 9 ticket_len (n)
Simon Cooksey 0:fb7af294d5d9 3755 * 10 . 9+n ticket content
Simon Cooksey 0:fb7af294d5d9 3756 */
Simon Cooksey 0:fb7af294d5d9 3757
Simon Cooksey 0:fb7af294d5d9 3758 if( ( ret = ssl->conf->f_ticket_write( ssl->conf->p_ticket,
Simon Cooksey 0:fb7af294d5d9 3759 ssl->session_negotiate,
Simon Cooksey 0:fb7af294d5d9 3760 ssl->out_msg + 10,
Simon Cooksey 0:fb7af294d5d9 3761 ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN,
Simon Cooksey 0:fb7af294d5d9 3762 &tlen, &lifetime ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3763 {
Simon Cooksey 0:fb7af294d5d9 3764 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_write", ret );
Simon Cooksey 0:fb7af294d5d9 3765 tlen = 0;
Simon Cooksey 0:fb7af294d5d9 3766 }
Simon Cooksey 0:fb7af294d5d9 3767
Simon Cooksey 0:fb7af294d5d9 3768 ssl->out_msg[4] = ( lifetime >> 24 ) & 0xFF;
Simon Cooksey 0:fb7af294d5d9 3769 ssl->out_msg[5] = ( lifetime >> 16 ) & 0xFF;
Simon Cooksey 0:fb7af294d5d9 3770 ssl->out_msg[6] = ( lifetime >> 8 ) & 0xFF;
Simon Cooksey 0:fb7af294d5d9 3771 ssl->out_msg[7] = ( lifetime ) & 0xFF;
Simon Cooksey 0:fb7af294d5d9 3772
Simon Cooksey 0:fb7af294d5d9 3773 ssl->out_msg[8] = (unsigned char)( ( tlen >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 3774 ssl->out_msg[9] = (unsigned char)( ( tlen ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 3775
Simon Cooksey 0:fb7af294d5d9 3776 ssl->out_msglen = 10 + tlen;
Simon Cooksey 0:fb7af294d5d9 3777
Simon Cooksey 0:fb7af294d5d9 3778 /*
Simon Cooksey 0:fb7af294d5d9 3779 * Morally equivalent to updating ssl->state, but NewSessionTicket and
Simon Cooksey 0:fb7af294d5d9 3780 * ChangeCipherSpec share the same state.
Simon Cooksey 0:fb7af294d5d9 3781 */
Simon Cooksey 0:fb7af294d5d9 3782 ssl->handshake->new_session_ticket = 0;
Simon Cooksey 0:fb7af294d5d9 3783
Simon Cooksey 0:fb7af294d5d9 3784 if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3785 {
Simon Cooksey 0:fb7af294d5d9 3786 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
Simon Cooksey 0:fb7af294d5d9 3787 return( ret );
Simon Cooksey 0:fb7af294d5d9 3788 }
Simon Cooksey 0:fb7af294d5d9 3789
Simon Cooksey 0:fb7af294d5d9 3790 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write new session ticket" ) );
Simon Cooksey 0:fb7af294d5d9 3791
Simon Cooksey 0:fb7af294d5d9 3792 return( 0 );
Simon Cooksey 0:fb7af294d5d9 3793 }
Simon Cooksey 0:fb7af294d5d9 3794 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
Simon Cooksey 0:fb7af294d5d9 3795
Simon Cooksey 0:fb7af294d5d9 3796 /*
Simon Cooksey 0:fb7af294d5d9 3797 * SSL handshake -- server side -- single step
Simon Cooksey 0:fb7af294d5d9 3798 */
Simon Cooksey 0:fb7af294d5d9 3799 int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 3800 {
Simon Cooksey 0:fb7af294d5d9 3801 int ret = 0;
Simon Cooksey 0:fb7af294d5d9 3802
Simon Cooksey 0:fb7af294d5d9 3803 if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL )
Simon Cooksey 0:fb7af294d5d9 3804 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
Simon Cooksey 0:fb7af294d5d9 3805
Simon Cooksey 0:fb7af294d5d9 3806 MBEDTLS_SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) );
Simon Cooksey 0:fb7af294d5d9 3807
Simon Cooksey 0:fb7af294d5d9 3808 if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3809 return( ret );
Simon Cooksey 0:fb7af294d5d9 3810
Simon Cooksey 0:fb7af294d5d9 3811 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 3812 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
Simon Cooksey 0:fb7af294d5d9 3813 ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
Simon Cooksey 0:fb7af294d5d9 3814 {
Simon Cooksey 0:fb7af294d5d9 3815 if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3816 return( ret );
Simon Cooksey 0:fb7af294d5d9 3817 }
Simon Cooksey 0:fb7af294d5d9 3818 #endif
Simon Cooksey 0:fb7af294d5d9 3819
Simon Cooksey 0:fb7af294d5d9 3820 switch( ssl->state )
Simon Cooksey 0:fb7af294d5d9 3821 {
Simon Cooksey 0:fb7af294d5d9 3822 case MBEDTLS_SSL_HELLO_REQUEST:
Simon Cooksey 0:fb7af294d5d9 3823 ssl->state = MBEDTLS_SSL_CLIENT_HELLO;
Simon Cooksey 0:fb7af294d5d9 3824 break;
Simon Cooksey 0:fb7af294d5d9 3825
Simon Cooksey 0:fb7af294d5d9 3826 /*
Simon Cooksey 0:fb7af294d5d9 3827 * <== ClientHello
Simon Cooksey 0:fb7af294d5d9 3828 */
Simon Cooksey 0:fb7af294d5d9 3829 case MBEDTLS_SSL_CLIENT_HELLO:
Simon Cooksey 0:fb7af294d5d9 3830 ret = ssl_parse_client_hello( ssl );
Simon Cooksey 0:fb7af294d5d9 3831 break;
Simon Cooksey 0:fb7af294d5d9 3832
Simon Cooksey 0:fb7af294d5d9 3833 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 3834 case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT:
Simon Cooksey 0:fb7af294d5d9 3835 return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED );
Simon Cooksey 0:fb7af294d5d9 3836 #endif
Simon Cooksey 0:fb7af294d5d9 3837
Simon Cooksey 0:fb7af294d5d9 3838 /*
Simon Cooksey 0:fb7af294d5d9 3839 * ==> ServerHello
Simon Cooksey 0:fb7af294d5d9 3840 * Certificate
Simon Cooksey 0:fb7af294d5d9 3841 * ( ServerKeyExchange )
Simon Cooksey 0:fb7af294d5d9 3842 * ( CertificateRequest )
Simon Cooksey 0:fb7af294d5d9 3843 * ServerHelloDone
Simon Cooksey 0:fb7af294d5d9 3844 */
Simon Cooksey 0:fb7af294d5d9 3845 case MBEDTLS_SSL_SERVER_HELLO:
Simon Cooksey 0:fb7af294d5d9 3846 ret = ssl_write_server_hello( ssl );
Simon Cooksey 0:fb7af294d5d9 3847 break;
Simon Cooksey 0:fb7af294d5d9 3848
Simon Cooksey 0:fb7af294d5d9 3849 case MBEDTLS_SSL_SERVER_CERTIFICATE:
Simon Cooksey 0:fb7af294d5d9 3850 ret = mbedtls_ssl_write_certificate( ssl );
Simon Cooksey 0:fb7af294d5d9 3851 break;
Simon Cooksey 0:fb7af294d5d9 3852
Simon Cooksey 0:fb7af294d5d9 3853 case MBEDTLS_SSL_SERVER_KEY_EXCHANGE:
Simon Cooksey 0:fb7af294d5d9 3854 ret = ssl_write_server_key_exchange( ssl );
Simon Cooksey 0:fb7af294d5d9 3855 break;
Simon Cooksey 0:fb7af294d5d9 3856
Simon Cooksey 0:fb7af294d5d9 3857 case MBEDTLS_SSL_CERTIFICATE_REQUEST:
Simon Cooksey 0:fb7af294d5d9 3858 ret = ssl_write_certificate_request( ssl );
Simon Cooksey 0:fb7af294d5d9 3859 break;
Simon Cooksey 0:fb7af294d5d9 3860
Simon Cooksey 0:fb7af294d5d9 3861 case MBEDTLS_SSL_SERVER_HELLO_DONE:
Simon Cooksey 0:fb7af294d5d9 3862 ret = ssl_write_server_hello_done( ssl );
Simon Cooksey 0:fb7af294d5d9 3863 break;
Simon Cooksey 0:fb7af294d5d9 3864
Simon Cooksey 0:fb7af294d5d9 3865 /*
Simon Cooksey 0:fb7af294d5d9 3866 * <== ( Certificate/Alert )
Simon Cooksey 0:fb7af294d5d9 3867 * ClientKeyExchange
Simon Cooksey 0:fb7af294d5d9 3868 * ( CertificateVerify )
Simon Cooksey 0:fb7af294d5d9 3869 * ChangeCipherSpec
Simon Cooksey 0:fb7af294d5d9 3870 * Finished
Simon Cooksey 0:fb7af294d5d9 3871 */
Simon Cooksey 0:fb7af294d5d9 3872 case MBEDTLS_SSL_CLIENT_CERTIFICATE:
Simon Cooksey 0:fb7af294d5d9 3873 ret = mbedtls_ssl_parse_certificate( ssl );
Simon Cooksey 0:fb7af294d5d9 3874 break;
Simon Cooksey 0:fb7af294d5d9 3875
Simon Cooksey 0:fb7af294d5d9 3876 case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:
Simon Cooksey 0:fb7af294d5d9 3877 ret = ssl_parse_client_key_exchange( ssl );
Simon Cooksey 0:fb7af294d5d9 3878 break;
Simon Cooksey 0:fb7af294d5d9 3879
Simon Cooksey 0:fb7af294d5d9 3880 case MBEDTLS_SSL_CERTIFICATE_VERIFY:
Simon Cooksey 0:fb7af294d5d9 3881 ret = ssl_parse_certificate_verify( ssl );
Simon Cooksey 0:fb7af294d5d9 3882 break;
Simon Cooksey 0:fb7af294d5d9 3883
Simon Cooksey 0:fb7af294d5d9 3884 case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC:
Simon Cooksey 0:fb7af294d5d9 3885 ret = mbedtls_ssl_parse_change_cipher_spec( ssl );
Simon Cooksey 0:fb7af294d5d9 3886 break;
Simon Cooksey 0:fb7af294d5d9 3887
Simon Cooksey 0:fb7af294d5d9 3888 case MBEDTLS_SSL_CLIENT_FINISHED:
Simon Cooksey 0:fb7af294d5d9 3889 ret = mbedtls_ssl_parse_finished( ssl );
Simon Cooksey 0:fb7af294d5d9 3890 break;
Simon Cooksey 0:fb7af294d5d9 3891
Simon Cooksey 0:fb7af294d5d9 3892 /*
Simon Cooksey 0:fb7af294d5d9 3893 * ==> ( NewSessionTicket )
Simon Cooksey 0:fb7af294d5d9 3894 * ChangeCipherSpec
Simon Cooksey 0:fb7af294d5d9 3895 * Finished
Simon Cooksey 0:fb7af294d5d9 3896 */
Simon Cooksey 0:fb7af294d5d9 3897 case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC:
Simon Cooksey 0:fb7af294d5d9 3898 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
Simon Cooksey 0:fb7af294d5d9 3899 if( ssl->handshake->new_session_ticket != 0 )
Simon Cooksey 0:fb7af294d5d9 3900 ret = ssl_write_new_session_ticket( ssl );
Simon Cooksey 0:fb7af294d5d9 3901 else
Simon Cooksey 0:fb7af294d5d9 3902 #endif
Simon Cooksey 0:fb7af294d5d9 3903 ret = mbedtls_ssl_write_change_cipher_spec( ssl );
Simon Cooksey 0:fb7af294d5d9 3904 break;
Simon Cooksey 0:fb7af294d5d9 3905
Simon Cooksey 0:fb7af294d5d9 3906 case MBEDTLS_SSL_SERVER_FINISHED:
Simon Cooksey 0:fb7af294d5d9 3907 ret = mbedtls_ssl_write_finished( ssl );
Simon Cooksey 0:fb7af294d5d9 3908 break;
Simon Cooksey 0:fb7af294d5d9 3909
Simon Cooksey 0:fb7af294d5d9 3910 case MBEDTLS_SSL_FLUSH_BUFFERS:
Simon Cooksey 0:fb7af294d5d9 3911 MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
Simon Cooksey 0:fb7af294d5d9 3912 ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP;
Simon Cooksey 0:fb7af294d5d9 3913 break;
Simon Cooksey 0:fb7af294d5d9 3914
Simon Cooksey 0:fb7af294d5d9 3915 case MBEDTLS_SSL_HANDSHAKE_WRAPUP:
Simon Cooksey 0:fb7af294d5d9 3916 mbedtls_ssl_handshake_wrapup( ssl );
Simon Cooksey 0:fb7af294d5d9 3917 break;
Simon Cooksey 0:fb7af294d5d9 3918
Simon Cooksey 0:fb7af294d5d9 3919 default:
Simon Cooksey 0:fb7af294d5d9 3920 MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
Simon Cooksey 0:fb7af294d5d9 3921 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
Simon Cooksey 0:fb7af294d5d9 3922 }
Simon Cooksey 0:fb7af294d5d9 3923
Simon Cooksey 0:fb7af294d5d9 3924 return( ret );
Simon Cooksey 0:fb7af294d5d9 3925 }
Simon Cooksey 0:fb7af294d5d9 3926 #endif /* MBEDTLS_SSL_SRV_C */