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 client-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_CLI_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 #include <stdint.h>
Simon Cooksey 0:fb7af294d5d9 45
Simon Cooksey 0:fb7af294d5d9 46 #if defined(MBEDTLS_HAVE_TIME)
Simon Cooksey 0:fb7af294d5d9 47 #include "mbedtls/platform_time.h"
Simon Cooksey 0:fb7af294d5d9 48 #endif
Simon Cooksey 0:fb7af294d5d9 49
Simon Cooksey 0:fb7af294d5d9 50 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
Simon Cooksey 0:fb7af294d5d9 51 /* Implementation that should never be optimized out by the compiler */
Simon Cooksey 0:fb7af294d5d9 52 static void mbedtls_zeroize( void *v, size_t n ) {
Simon Cooksey 0:fb7af294d5d9 53 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
Simon Cooksey 0:fb7af294d5d9 54 }
Simon Cooksey 0:fb7af294d5d9 55 #endif
Simon Cooksey 0:fb7af294d5d9 56
Simon Cooksey 0:fb7af294d5d9 57 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
Simon Cooksey 0:fb7af294d5d9 58 static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 59 unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 60 size_t *olen )
Simon Cooksey 0:fb7af294d5d9 61 {
Simon Cooksey 0:fb7af294d5d9 62 unsigned char *p = buf;
Simon Cooksey 0:fb7af294d5d9 63 const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
Simon Cooksey 0:fb7af294d5d9 64 size_t hostname_len;
Simon Cooksey 0:fb7af294d5d9 65
Simon Cooksey 0:fb7af294d5d9 66 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 67
Simon Cooksey 0:fb7af294d5d9 68 if( ssl->hostname == NULL )
Simon Cooksey 0:fb7af294d5d9 69 return;
Simon Cooksey 0:fb7af294d5d9 70
Simon Cooksey 0:fb7af294d5d9 71 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding server name extension: %s",
Simon Cooksey 0:fb7af294d5d9 72 ssl->hostname ) );
Simon Cooksey 0:fb7af294d5d9 73
Simon Cooksey 0:fb7af294d5d9 74 hostname_len = strlen( ssl->hostname );
Simon Cooksey 0:fb7af294d5d9 75
Simon Cooksey 0:fb7af294d5d9 76 if( end < p || (size_t)( end - p ) < hostname_len + 9 )
Simon Cooksey 0:fb7af294d5d9 77 {
Simon Cooksey 0:fb7af294d5d9 78 MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
Simon Cooksey 0:fb7af294d5d9 79 return;
Simon Cooksey 0:fb7af294d5d9 80 }
Simon Cooksey 0:fb7af294d5d9 81
Simon Cooksey 0:fb7af294d5d9 82 /*
Simon Cooksey 0:fb7af294d5d9 83 * struct {
Simon Cooksey 0:fb7af294d5d9 84 * NameType name_type;
Simon Cooksey 0:fb7af294d5d9 85 * select (name_type) {
Simon Cooksey 0:fb7af294d5d9 86 * case host_name: HostName;
Simon Cooksey 0:fb7af294d5d9 87 * } name;
Simon Cooksey 0:fb7af294d5d9 88 * } ServerName;
Simon Cooksey 0:fb7af294d5d9 89 *
Simon Cooksey 0:fb7af294d5d9 90 * enum {
Simon Cooksey 0:fb7af294d5d9 91 * host_name(0), (255)
Simon Cooksey 0:fb7af294d5d9 92 * } NameType;
Simon Cooksey 0:fb7af294d5d9 93 *
Simon Cooksey 0:fb7af294d5d9 94 * opaque HostName<1..2^16-1>;
Simon Cooksey 0:fb7af294d5d9 95 *
Simon Cooksey 0:fb7af294d5d9 96 * struct {
Simon Cooksey 0:fb7af294d5d9 97 * ServerName server_name_list<1..2^16-1>
Simon Cooksey 0:fb7af294d5d9 98 * } ServerNameList;
Simon Cooksey 0:fb7af294d5d9 99 */
Simon Cooksey 0:fb7af294d5d9 100 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 101 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 102
Simon Cooksey 0:fb7af294d5d9 103 *p++ = (unsigned char)( ( (hostname_len + 5) >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 104 *p++ = (unsigned char)( ( (hostname_len + 5) ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 105
Simon Cooksey 0:fb7af294d5d9 106 *p++ = (unsigned char)( ( (hostname_len + 3) >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 107 *p++ = (unsigned char)( ( (hostname_len + 3) ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 108
Simon Cooksey 0:fb7af294d5d9 109 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 110 *p++ = (unsigned char)( ( hostname_len >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 111 *p++ = (unsigned char)( ( hostname_len ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 112
Simon Cooksey 0:fb7af294d5d9 113 memcpy( p, ssl->hostname, hostname_len );
Simon Cooksey 0:fb7af294d5d9 114
Simon Cooksey 0:fb7af294d5d9 115 *olen = hostname_len + 9;
Simon Cooksey 0:fb7af294d5d9 116 }
Simon Cooksey 0:fb7af294d5d9 117 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
Simon Cooksey 0:fb7af294d5d9 118
Simon Cooksey 0:fb7af294d5d9 119 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 120 static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 121 unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 122 size_t *olen )
Simon Cooksey 0:fb7af294d5d9 123 {
Simon Cooksey 0:fb7af294d5d9 124 unsigned char *p = buf;
Simon Cooksey 0:fb7af294d5d9 125 const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
Simon Cooksey 0:fb7af294d5d9 126
Simon Cooksey 0:fb7af294d5d9 127 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 128
Simon Cooksey 0:fb7af294d5d9 129 if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
Simon Cooksey 0:fb7af294d5d9 130 return;
Simon Cooksey 0:fb7af294d5d9 131
Simon Cooksey 0:fb7af294d5d9 132 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding renegotiation extension" ) );
Simon Cooksey 0:fb7af294d5d9 133
Simon Cooksey 0:fb7af294d5d9 134 if( end < p || (size_t)( end - p ) < 5 + ssl->verify_data_len )
Simon Cooksey 0:fb7af294d5d9 135 {
Simon Cooksey 0:fb7af294d5d9 136 MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
Simon Cooksey 0:fb7af294d5d9 137 return;
Simon Cooksey 0:fb7af294d5d9 138 }
Simon Cooksey 0:fb7af294d5d9 139
Simon Cooksey 0:fb7af294d5d9 140 /*
Simon Cooksey 0:fb7af294d5d9 141 * Secure renegotiation
Simon Cooksey 0:fb7af294d5d9 142 */
Simon Cooksey 0:fb7af294d5d9 143 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 144 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 145
Simon Cooksey 0:fb7af294d5d9 146 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 147 *p++ = ( ssl->verify_data_len + 1 ) & 0xFF;
Simon Cooksey 0:fb7af294d5d9 148 *p++ = ssl->verify_data_len & 0xFF;
Simon Cooksey 0:fb7af294d5d9 149
Simon Cooksey 0:fb7af294d5d9 150 memcpy( p, ssl->own_verify_data, ssl->verify_data_len );
Simon Cooksey 0:fb7af294d5d9 151
Simon Cooksey 0:fb7af294d5d9 152 *olen = 5 + ssl->verify_data_len;
Simon Cooksey 0:fb7af294d5d9 153 }
Simon Cooksey 0:fb7af294d5d9 154 #endif /* MBEDTLS_SSL_RENEGOTIATION */
Simon Cooksey 0:fb7af294d5d9 155
Simon Cooksey 0:fb7af294d5d9 156 /*
Simon Cooksey 0:fb7af294d5d9 157 * Only if we handle at least one key exchange that needs signatures.
Simon Cooksey 0:fb7af294d5d9 158 */
Simon Cooksey 0:fb7af294d5d9 159 #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
Simon Cooksey 0:fb7af294d5d9 160 defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
Simon Cooksey 0:fb7af294d5d9 161 static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 162 unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 163 size_t *olen )
Simon Cooksey 0:fb7af294d5d9 164 {
Simon Cooksey 0:fb7af294d5d9 165 unsigned char *p = buf;
Simon Cooksey 0:fb7af294d5d9 166 const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
Simon Cooksey 0:fb7af294d5d9 167 size_t sig_alg_len = 0;
Simon Cooksey 0:fb7af294d5d9 168 const int *md;
Simon Cooksey 0:fb7af294d5d9 169 #if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C)
Simon Cooksey 0:fb7af294d5d9 170 unsigned char *sig_alg_list = buf + 6;
Simon Cooksey 0:fb7af294d5d9 171 #endif
Simon Cooksey 0:fb7af294d5d9 172
Simon Cooksey 0:fb7af294d5d9 173 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 174
Simon Cooksey 0:fb7af294d5d9 175 if( ssl->conf->max_minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 )
Simon Cooksey 0:fb7af294d5d9 176 return;
Simon Cooksey 0:fb7af294d5d9 177
Simon Cooksey 0:fb7af294d5d9 178 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding signature_algorithms extension" ) );
Simon Cooksey 0:fb7af294d5d9 179
Simon Cooksey 0:fb7af294d5d9 180 for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ )
Simon Cooksey 0:fb7af294d5d9 181 {
Simon Cooksey 0:fb7af294d5d9 182 #if defined(MBEDTLS_ECDSA_C)
Simon Cooksey 0:fb7af294d5d9 183 sig_alg_len += 2;
Simon Cooksey 0:fb7af294d5d9 184 #endif
Simon Cooksey 0:fb7af294d5d9 185 #if defined(MBEDTLS_RSA_C)
Simon Cooksey 0:fb7af294d5d9 186 sig_alg_len += 2;
Simon Cooksey 0:fb7af294d5d9 187 #endif
Simon Cooksey 0:fb7af294d5d9 188 }
Simon Cooksey 0:fb7af294d5d9 189
Simon Cooksey 0:fb7af294d5d9 190 if( end < p || (size_t)( end - p ) < sig_alg_len + 6 )
Simon Cooksey 0:fb7af294d5d9 191 {
Simon Cooksey 0:fb7af294d5d9 192 MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
Simon Cooksey 0:fb7af294d5d9 193 return;
Simon Cooksey 0:fb7af294d5d9 194 }
Simon Cooksey 0:fb7af294d5d9 195
Simon Cooksey 0:fb7af294d5d9 196 /*
Simon Cooksey 0:fb7af294d5d9 197 * Prepare signature_algorithms extension (TLS 1.2)
Simon Cooksey 0:fb7af294d5d9 198 */
Simon Cooksey 0:fb7af294d5d9 199 sig_alg_len = 0;
Simon Cooksey 0:fb7af294d5d9 200
Simon Cooksey 0:fb7af294d5d9 201 for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ )
Simon Cooksey 0:fb7af294d5d9 202 {
Simon Cooksey 0:fb7af294d5d9 203 #if defined(MBEDTLS_ECDSA_C)
Simon Cooksey 0:fb7af294d5d9 204 sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md );
Simon Cooksey 0:fb7af294d5d9 205 sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA;
Simon Cooksey 0:fb7af294d5d9 206 #endif
Simon Cooksey 0:fb7af294d5d9 207 #if defined(MBEDTLS_RSA_C)
Simon Cooksey 0:fb7af294d5d9 208 sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md );
Simon Cooksey 0:fb7af294d5d9 209 sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA;
Simon Cooksey 0:fb7af294d5d9 210 #endif
Simon Cooksey 0:fb7af294d5d9 211 }
Simon Cooksey 0:fb7af294d5d9 212
Simon Cooksey 0:fb7af294d5d9 213 /*
Simon Cooksey 0:fb7af294d5d9 214 * enum {
Simon Cooksey 0:fb7af294d5d9 215 * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
Simon Cooksey 0:fb7af294d5d9 216 * sha512(6), (255)
Simon Cooksey 0:fb7af294d5d9 217 * } HashAlgorithm;
Simon Cooksey 0:fb7af294d5d9 218 *
Simon Cooksey 0:fb7af294d5d9 219 * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
Simon Cooksey 0:fb7af294d5d9 220 * SignatureAlgorithm;
Simon Cooksey 0:fb7af294d5d9 221 *
Simon Cooksey 0:fb7af294d5d9 222 * struct {
Simon Cooksey 0:fb7af294d5d9 223 * HashAlgorithm hash;
Simon Cooksey 0:fb7af294d5d9 224 * SignatureAlgorithm signature;
Simon Cooksey 0:fb7af294d5d9 225 * } SignatureAndHashAlgorithm;
Simon Cooksey 0:fb7af294d5d9 226 *
Simon Cooksey 0:fb7af294d5d9 227 * SignatureAndHashAlgorithm
Simon Cooksey 0:fb7af294d5d9 228 * supported_signature_algorithms<2..2^16-2>;
Simon Cooksey 0:fb7af294d5d9 229 */
Simon Cooksey 0:fb7af294d5d9 230 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 231 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 232
Simon Cooksey 0:fb7af294d5d9 233 *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 234 *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 235
Simon Cooksey 0:fb7af294d5d9 236 *p++ = (unsigned char)( ( sig_alg_len >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 237 *p++ = (unsigned char)( ( sig_alg_len ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 238
Simon Cooksey 0:fb7af294d5d9 239 *olen = 6 + sig_alg_len;
Simon Cooksey 0:fb7af294d5d9 240 }
Simon Cooksey 0:fb7af294d5d9 241 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 &&
Simon Cooksey 0:fb7af294d5d9 242 MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */
Simon Cooksey 0:fb7af294d5d9 243
Simon Cooksey 0:fb7af294d5d9 244 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
Simon Cooksey 0:fb7af294d5d9 245 defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 246 static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 247 unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 248 size_t *olen )
Simon Cooksey 0:fb7af294d5d9 249 {
Simon Cooksey 0:fb7af294d5d9 250 unsigned char *p = buf;
Simon Cooksey 0:fb7af294d5d9 251 const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
Simon Cooksey 0:fb7af294d5d9 252 unsigned char *elliptic_curve_list = p + 6;
Simon Cooksey 0:fb7af294d5d9 253 size_t elliptic_curve_len = 0;
Simon Cooksey 0:fb7af294d5d9 254 const mbedtls_ecp_curve_info *info;
Simon Cooksey 0:fb7af294d5d9 255 #if defined(MBEDTLS_ECP_C)
Simon Cooksey 0:fb7af294d5d9 256 const mbedtls_ecp_group_id *grp_id;
Simon Cooksey 0:fb7af294d5d9 257 #else
Simon Cooksey 0:fb7af294d5d9 258 ((void) ssl);
Simon Cooksey 0:fb7af294d5d9 259 #endif
Simon Cooksey 0:fb7af294d5d9 260
Simon Cooksey 0:fb7af294d5d9 261 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 262
Simon Cooksey 0:fb7af294d5d9 263 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_elliptic_curves extension" ) );
Simon Cooksey 0:fb7af294d5d9 264
Simon Cooksey 0:fb7af294d5d9 265 #if defined(MBEDTLS_ECP_C)
Simon Cooksey 0:fb7af294d5d9 266 for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ )
Simon Cooksey 0:fb7af294d5d9 267 {
Simon Cooksey 0:fb7af294d5d9 268 info = mbedtls_ecp_curve_info_from_grp_id( *grp_id );
Simon Cooksey 0:fb7af294d5d9 269 #else
Simon Cooksey 0:fb7af294d5d9 270 for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ )
Simon Cooksey 0:fb7af294d5d9 271 {
Simon Cooksey 0:fb7af294d5d9 272 #endif
Simon Cooksey 0:fb7af294d5d9 273 if( info == NULL )
Simon Cooksey 0:fb7af294d5d9 274 {
Simon Cooksey 0:fb7af294d5d9 275 MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid curve in ssl configuration" ) );
Simon Cooksey 0:fb7af294d5d9 276 return;
Simon Cooksey 0:fb7af294d5d9 277 }
Simon Cooksey 0:fb7af294d5d9 278
Simon Cooksey 0:fb7af294d5d9 279 elliptic_curve_len += 2;
Simon Cooksey 0:fb7af294d5d9 280 }
Simon Cooksey 0:fb7af294d5d9 281
Simon Cooksey 0:fb7af294d5d9 282 if( end < p || (size_t)( end - p ) < 6 + elliptic_curve_len )
Simon Cooksey 0:fb7af294d5d9 283 {
Simon Cooksey 0:fb7af294d5d9 284 MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
Simon Cooksey 0:fb7af294d5d9 285 return;
Simon Cooksey 0:fb7af294d5d9 286 }
Simon Cooksey 0:fb7af294d5d9 287
Simon Cooksey 0:fb7af294d5d9 288 elliptic_curve_len = 0;
Simon Cooksey 0:fb7af294d5d9 289
Simon Cooksey 0:fb7af294d5d9 290 #if defined(MBEDTLS_ECP_C)
Simon Cooksey 0:fb7af294d5d9 291 for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ )
Simon Cooksey 0:fb7af294d5d9 292 {
Simon Cooksey 0:fb7af294d5d9 293 info = mbedtls_ecp_curve_info_from_grp_id( *grp_id );
Simon Cooksey 0:fb7af294d5d9 294 #else
Simon Cooksey 0:fb7af294d5d9 295 for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ )
Simon Cooksey 0:fb7af294d5d9 296 {
Simon Cooksey 0:fb7af294d5d9 297 #endif
Simon Cooksey 0:fb7af294d5d9 298 elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8;
Simon Cooksey 0:fb7af294d5d9 299 elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF;
Simon Cooksey 0:fb7af294d5d9 300 }
Simon Cooksey 0:fb7af294d5d9 301
Simon Cooksey 0:fb7af294d5d9 302 if( elliptic_curve_len == 0 )
Simon Cooksey 0:fb7af294d5d9 303 return;
Simon Cooksey 0:fb7af294d5d9 304
Simon Cooksey 0:fb7af294d5d9 305 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 306 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 307
Simon Cooksey 0:fb7af294d5d9 308 *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 309 *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 310
Simon Cooksey 0:fb7af294d5d9 311 *p++ = (unsigned char)( ( ( elliptic_curve_len ) >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 312 *p++ = (unsigned char)( ( ( elliptic_curve_len ) ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 313
Simon Cooksey 0:fb7af294d5d9 314 *olen = 6 + elliptic_curve_len;
Simon Cooksey 0:fb7af294d5d9 315 }
Simon Cooksey 0:fb7af294d5d9 316
Simon Cooksey 0:fb7af294d5d9 317 static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 318 unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 319 size_t *olen )
Simon Cooksey 0:fb7af294d5d9 320 {
Simon Cooksey 0:fb7af294d5d9 321 unsigned char *p = buf;
Simon Cooksey 0:fb7af294d5d9 322 const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
Simon Cooksey 0:fb7af294d5d9 323
Simon Cooksey 0:fb7af294d5d9 324 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 325
Simon Cooksey 0:fb7af294d5d9 326 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_point_formats extension" ) );
Simon Cooksey 0:fb7af294d5d9 327
Simon Cooksey 0:fb7af294d5d9 328 if( end < p || (size_t)( end - p ) < 6 )
Simon Cooksey 0:fb7af294d5d9 329 {
Simon Cooksey 0:fb7af294d5d9 330 MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
Simon Cooksey 0:fb7af294d5d9 331 return;
Simon Cooksey 0:fb7af294d5d9 332 }
Simon Cooksey 0:fb7af294d5d9 333
Simon Cooksey 0:fb7af294d5d9 334 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 335 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 336
Simon Cooksey 0:fb7af294d5d9 337 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 338 *p++ = 2;
Simon Cooksey 0:fb7af294d5d9 339
Simon Cooksey 0:fb7af294d5d9 340 *p++ = 1;
Simon Cooksey 0:fb7af294d5d9 341 *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED;
Simon Cooksey 0:fb7af294d5d9 342
Simon Cooksey 0:fb7af294d5d9 343 *olen = 6;
Simon Cooksey 0:fb7af294d5d9 344 }
Simon Cooksey 0:fb7af294d5d9 345 #endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
Simon Cooksey 0:fb7af294d5d9 346 MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
Simon Cooksey 0:fb7af294d5d9 347
Simon Cooksey 0:fb7af294d5d9 348 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 349 static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 350 unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 351 size_t *olen )
Simon Cooksey 0:fb7af294d5d9 352 {
Simon Cooksey 0:fb7af294d5d9 353 int ret;
Simon Cooksey 0:fb7af294d5d9 354 unsigned char *p = buf;
Simon Cooksey 0:fb7af294d5d9 355 const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
Simon Cooksey 0:fb7af294d5d9 356 size_t kkpp_len;
Simon Cooksey 0:fb7af294d5d9 357
Simon Cooksey 0:fb7af294d5d9 358 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 359
Simon Cooksey 0:fb7af294d5d9 360 /* Skip costly extension if we can't use EC J-PAKE anyway */
Simon Cooksey 0:fb7af294d5d9 361 if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 )
Simon Cooksey 0:fb7af294d5d9 362 return;
Simon Cooksey 0:fb7af294d5d9 363
Simon Cooksey 0:fb7af294d5d9 364 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding ecjpake_kkpp extension" ) );
Simon Cooksey 0:fb7af294d5d9 365
Simon Cooksey 0:fb7af294d5d9 366 if( end - p < 4 )
Simon Cooksey 0:fb7af294d5d9 367 {
Simon Cooksey 0:fb7af294d5d9 368 MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
Simon Cooksey 0:fb7af294d5d9 369 return;
Simon Cooksey 0:fb7af294d5d9 370 }
Simon Cooksey 0:fb7af294d5d9 371
Simon Cooksey 0:fb7af294d5d9 372 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 373 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 374
Simon Cooksey 0:fb7af294d5d9 375 /*
Simon Cooksey 0:fb7af294d5d9 376 * We may need to send ClientHello multiple times for Hello verification.
Simon Cooksey 0:fb7af294d5d9 377 * We don't want to compute fresh values every time (both for performance
Simon Cooksey 0:fb7af294d5d9 378 * and consistency reasons), so cache the extension content.
Simon Cooksey 0:fb7af294d5d9 379 */
Simon Cooksey 0:fb7af294d5d9 380 if( ssl->handshake->ecjpake_cache == NULL ||
Simon Cooksey 0:fb7af294d5d9 381 ssl->handshake->ecjpake_cache_len == 0 )
Simon Cooksey 0:fb7af294d5d9 382 {
Simon Cooksey 0:fb7af294d5d9 383 MBEDTLS_SSL_DEBUG_MSG( 3, ( "generating new ecjpake parameters" ) );
Simon Cooksey 0:fb7af294d5d9 384
Simon Cooksey 0:fb7af294d5d9 385 ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx,
Simon Cooksey 0:fb7af294d5d9 386 p + 2, end - p - 2, &kkpp_len,
Simon Cooksey 0:fb7af294d5d9 387 ssl->conf->f_rng, ssl->conf->p_rng );
Simon Cooksey 0:fb7af294d5d9 388 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 389 {
Simon Cooksey 0:fb7af294d5d9 390 MBEDTLS_SSL_DEBUG_RET( 1 , "mbedtls_ecjpake_write_round_one", ret );
Simon Cooksey 0:fb7af294d5d9 391 return;
Simon Cooksey 0:fb7af294d5d9 392 }
Simon Cooksey 0:fb7af294d5d9 393
Simon Cooksey 0:fb7af294d5d9 394 ssl->handshake->ecjpake_cache = mbedtls_calloc( 1, kkpp_len );
Simon Cooksey 0:fb7af294d5d9 395 if( ssl->handshake->ecjpake_cache == NULL )
Simon Cooksey 0:fb7af294d5d9 396 {
Simon Cooksey 0:fb7af294d5d9 397 MBEDTLS_SSL_DEBUG_MSG( 1, ( "allocation failed" ) );
Simon Cooksey 0:fb7af294d5d9 398 return;
Simon Cooksey 0:fb7af294d5d9 399 }
Simon Cooksey 0:fb7af294d5d9 400
Simon Cooksey 0:fb7af294d5d9 401 memcpy( ssl->handshake->ecjpake_cache, p + 2, kkpp_len );
Simon Cooksey 0:fb7af294d5d9 402 ssl->handshake->ecjpake_cache_len = kkpp_len;
Simon Cooksey 0:fb7af294d5d9 403 }
Simon Cooksey 0:fb7af294d5d9 404 else
Simon Cooksey 0:fb7af294d5d9 405 {
Simon Cooksey 0:fb7af294d5d9 406 MBEDTLS_SSL_DEBUG_MSG( 3, ( "re-using cached ecjpake parameters" ) );
Simon Cooksey 0:fb7af294d5d9 407
Simon Cooksey 0:fb7af294d5d9 408 kkpp_len = ssl->handshake->ecjpake_cache_len;
Simon Cooksey 0:fb7af294d5d9 409
Simon Cooksey 0:fb7af294d5d9 410 if( (size_t)( end - p - 2 ) < kkpp_len )
Simon Cooksey 0:fb7af294d5d9 411 {
Simon Cooksey 0:fb7af294d5d9 412 MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
Simon Cooksey 0:fb7af294d5d9 413 return;
Simon Cooksey 0:fb7af294d5d9 414 }
Simon Cooksey 0:fb7af294d5d9 415
Simon Cooksey 0:fb7af294d5d9 416 memcpy( p + 2, ssl->handshake->ecjpake_cache, kkpp_len );
Simon Cooksey 0:fb7af294d5d9 417 }
Simon Cooksey 0:fb7af294d5d9 418
Simon Cooksey 0:fb7af294d5d9 419 *p++ = (unsigned char)( ( kkpp_len >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 420 *p++ = (unsigned char)( ( kkpp_len ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 421
Simon Cooksey 0:fb7af294d5d9 422 *olen = kkpp_len + 4;
Simon Cooksey 0:fb7af294d5d9 423 }
Simon Cooksey 0:fb7af294d5d9 424 #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
Simon Cooksey 0:fb7af294d5d9 425
Simon Cooksey 0:fb7af294d5d9 426 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
Simon Cooksey 0:fb7af294d5d9 427 static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 428 unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 429 size_t *olen )
Simon Cooksey 0:fb7af294d5d9 430 {
Simon Cooksey 0:fb7af294d5d9 431 unsigned char *p = buf;
Simon Cooksey 0:fb7af294d5d9 432 const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
Simon Cooksey 0:fb7af294d5d9 433
Simon Cooksey 0:fb7af294d5d9 434 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 435
Simon Cooksey 0:fb7af294d5d9 436 if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) {
Simon Cooksey 0:fb7af294d5d9 437 return;
Simon Cooksey 0:fb7af294d5d9 438 }
Simon Cooksey 0:fb7af294d5d9 439
Simon Cooksey 0:fb7af294d5d9 440 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding max_fragment_length extension" ) );
Simon Cooksey 0:fb7af294d5d9 441
Simon Cooksey 0:fb7af294d5d9 442 if( end < p || (size_t)( end - p ) < 5 )
Simon Cooksey 0:fb7af294d5d9 443 {
Simon Cooksey 0:fb7af294d5d9 444 MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
Simon Cooksey 0:fb7af294d5d9 445 return;
Simon Cooksey 0:fb7af294d5d9 446 }
Simon Cooksey 0:fb7af294d5d9 447
Simon Cooksey 0:fb7af294d5d9 448 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 449 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 450
Simon Cooksey 0:fb7af294d5d9 451 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 452 *p++ = 1;
Simon Cooksey 0:fb7af294d5d9 453
Simon Cooksey 0:fb7af294d5d9 454 *p++ = ssl->conf->mfl_code;
Simon Cooksey 0:fb7af294d5d9 455
Simon Cooksey 0:fb7af294d5d9 456 *olen = 5;
Simon Cooksey 0:fb7af294d5d9 457 }
Simon Cooksey 0:fb7af294d5d9 458 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
Simon Cooksey 0:fb7af294d5d9 459
Simon Cooksey 0:fb7af294d5d9 460 #if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
Simon Cooksey 0:fb7af294d5d9 461 static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 462 unsigned char *buf, size_t *olen )
Simon Cooksey 0:fb7af294d5d9 463 {
Simon Cooksey 0:fb7af294d5d9 464 unsigned char *p = buf;
Simon Cooksey 0:fb7af294d5d9 465 const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
Simon Cooksey 0:fb7af294d5d9 466
Simon Cooksey 0:fb7af294d5d9 467 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 468
Simon Cooksey 0:fb7af294d5d9 469 if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED )
Simon Cooksey 0:fb7af294d5d9 470 {
Simon Cooksey 0:fb7af294d5d9 471 return;
Simon Cooksey 0:fb7af294d5d9 472 }
Simon Cooksey 0:fb7af294d5d9 473
Simon Cooksey 0:fb7af294d5d9 474 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding truncated_hmac extension" ) );
Simon Cooksey 0:fb7af294d5d9 475
Simon Cooksey 0:fb7af294d5d9 476 if( end < p || (size_t)( end - p ) < 4 )
Simon Cooksey 0:fb7af294d5d9 477 {
Simon Cooksey 0:fb7af294d5d9 478 MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
Simon Cooksey 0:fb7af294d5d9 479 return;
Simon Cooksey 0:fb7af294d5d9 480 }
Simon Cooksey 0:fb7af294d5d9 481
Simon Cooksey 0:fb7af294d5d9 482 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 483 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 484
Simon Cooksey 0:fb7af294d5d9 485 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 486 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 487
Simon Cooksey 0:fb7af294d5d9 488 *olen = 4;
Simon Cooksey 0:fb7af294d5d9 489 }
Simon Cooksey 0:fb7af294d5d9 490 #endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
Simon Cooksey 0:fb7af294d5d9 491
Simon Cooksey 0:fb7af294d5d9 492 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
Simon Cooksey 0:fb7af294d5d9 493 static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 494 unsigned char *buf, size_t *olen )
Simon Cooksey 0:fb7af294d5d9 495 {
Simon Cooksey 0:fb7af294d5d9 496 unsigned char *p = buf;
Simon Cooksey 0:fb7af294d5d9 497 const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
Simon Cooksey 0:fb7af294d5d9 498
Simon Cooksey 0:fb7af294d5d9 499 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 500
Simon Cooksey 0:fb7af294d5d9 501 if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED ||
Simon Cooksey 0:fb7af294d5d9 502 ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
Simon Cooksey 0:fb7af294d5d9 503 {
Simon Cooksey 0:fb7af294d5d9 504 return;
Simon Cooksey 0:fb7af294d5d9 505 }
Simon Cooksey 0:fb7af294d5d9 506
Simon Cooksey 0:fb7af294d5d9 507 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding encrypt_then_mac "
Simon Cooksey 0:fb7af294d5d9 508 "extension" ) );
Simon Cooksey 0:fb7af294d5d9 509
Simon Cooksey 0:fb7af294d5d9 510 if( end < p || (size_t)( end - p ) < 4 )
Simon Cooksey 0:fb7af294d5d9 511 {
Simon Cooksey 0:fb7af294d5d9 512 MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
Simon Cooksey 0:fb7af294d5d9 513 return;
Simon Cooksey 0:fb7af294d5d9 514 }
Simon Cooksey 0:fb7af294d5d9 515
Simon Cooksey 0:fb7af294d5d9 516 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 517 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 518
Simon Cooksey 0:fb7af294d5d9 519 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 520 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 521
Simon Cooksey 0:fb7af294d5d9 522 *olen = 4;
Simon Cooksey 0:fb7af294d5d9 523 }
Simon Cooksey 0:fb7af294d5d9 524 #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
Simon Cooksey 0:fb7af294d5d9 525
Simon Cooksey 0:fb7af294d5d9 526 #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
Simon Cooksey 0:fb7af294d5d9 527 static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 528 unsigned char *buf, size_t *olen )
Simon Cooksey 0:fb7af294d5d9 529 {
Simon Cooksey 0:fb7af294d5d9 530 unsigned char *p = buf;
Simon Cooksey 0:fb7af294d5d9 531 const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
Simon Cooksey 0:fb7af294d5d9 532
Simon Cooksey 0:fb7af294d5d9 533 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 534
Simon Cooksey 0:fb7af294d5d9 535 if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED ||
Simon Cooksey 0:fb7af294d5d9 536 ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
Simon Cooksey 0:fb7af294d5d9 537 {
Simon Cooksey 0:fb7af294d5d9 538 return;
Simon Cooksey 0:fb7af294d5d9 539 }
Simon Cooksey 0:fb7af294d5d9 540
Simon Cooksey 0:fb7af294d5d9 541 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding extended_master_secret "
Simon Cooksey 0:fb7af294d5d9 542 "extension" ) );
Simon Cooksey 0:fb7af294d5d9 543
Simon Cooksey 0:fb7af294d5d9 544 if( end < p || (size_t)( end - p ) < 4 )
Simon Cooksey 0:fb7af294d5d9 545 {
Simon Cooksey 0:fb7af294d5d9 546 MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
Simon Cooksey 0:fb7af294d5d9 547 return;
Simon Cooksey 0:fb7af294d5d9 548 }
Simon Cooksey 0:fb7af294d5d9 549
Simon Cooksey 0:fb7af294d5d9 550 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 551 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 552
Simon Cooksey 0:fb7af294d5d9 553 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 554 *p++ = 0x00;
Simon Cooksey 0:fb7af294d5d9 555
Simon Cooksey 0:fb7af294d5d9 556 *olen = 4;
Simon Cooksey 0:fb7af294d5d9 557 }
Simon Cooksey 0:fb7af294d5d9 558 #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
Simon Cooksey 0:fb7af294d5d9 559
Simon Cooksey 0:fb7af294d5d9 560 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
Simon Cooksey 0:fb7af294d5d9 561 static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 562 unsigned char *buf, size_t *olen )
Simon Cooksey 0:fb7af294d5d9 563 {
Simon Cooksey 0:fb7af294d5d9 564 unsigned char *p = buf;
Simon Cooksey 0:fb7af294d5d9 565 const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
Simon Cooksey 0:fb7af294d5d9 566 size_t tlen = ssl->session_negotiate->ticket_len;
Simon Cooksey 0:fb7af294d5d9 567
Simon Cooksey 0:fb7af294d5d9 568 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 569
Simon Cooksey 0:fb7af294d5d9 570 if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED )
Simon Cooksey 0:fb7af294d5d9 571 {
Simon Cooksey 0:fb7af294d5d9 572 return;
Simon Cooksey 0:fb7af294d5d9 573 }
Simon Cooksey 0:fb7af294d5d9 574
Simon Cooksey 0:fb7af294d5d9 575 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding session ticket extension" ) );
Simon Cooksey 0:fb7af294d5d9 576
Simon Cooksey 0:fb7af294d5d9 577 if( end < p || (size_t)( end - p ) < 4 + tlen )
Simon Cooksey 0:fb7af294d5d9 578 {
Simon Cooksey 0:fb7af294d5d9 579 MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
Simon Cooksey 0:fb7af294d5d9 580 return;
Simon Cooksey 0:fb7af294d5d9 581 }
Simon Cooksey 0:fb7af294d5d9 582
Simon Cooksey 0:fb7af294d5d9 583 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 584 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 585
Simon Cooksey 0:fb7af294d5d9 586 *p++ = (unsigned char)( ( tlen >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 587 *p++ = (unsigned char)( ( tlen ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 588
Simon Cooksey 0:fb7af294d5d9 589 *olen = 4;
Simon Cooksey 0:fb7af294d5d9 590
Simon Cooksey 0:fb7af294d5d9 591 if( ssl->session_negotiate->ticket == NULL || tlen == 0 )
Simon Cooksey 0:fb7af294d5d9 592 {
Simon Cooksey 0:fb7af294d5d9 593 return;
Simon Cooksey 0:fb7af294d5d9 594 }
Simon Cooksey 0:fb7af294d5d9 595
Simon Cooksey 0:fb7af294d5d9 596 MBEDTLS_SSL_DEBUG_MSG( 3, ( "sending session ticket of length %d", tlen ) );
Simon Cooksey 0:fb7af294d5d9 597
Simon Cooksey 0:fb7af294d5d9 598 memcpy( p, ssl->session_negotiate->ticket, tlen );
Simon Cooksey 0:fb7af294d5d9 599
Simon Cooksey 0:fb7af294d5d9 600 *olen += tlen;
Simon Cooksey 0:fb7af294d5d9 601 }
Simon Cooksey 0:fb7af294d5d9 602 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
Simon Cooksey 0:fb7af294d5d9 603
Simon Cooksey 0:fb7af294d5d9 604 #if defined(MBEDTLS_SSL_ALPN)
Simon Cooksey 0:fb7af294d5d9 605 static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 606 unsigned char *buf, size_t *olen )
Simon Cooksey 0:fb7af294d5d9 607 {
Simon Cooksey 0:fb7af294d5d9 608 unsigned char *p = buf;
Simon Cooksey 0:fb7af294d5d9 609 const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
Simon Cooksey 0:fb7af294d5d9 610 size_t alpnlen = 0;
Simon Cooksey 0:fb7af294d5d9 611 const char **cur;
Simon Cooksey 0:fb7af294d5d9 612
Simon Cooksey 0:fb7af294d5d9 613 *olen = 0;
Simon Cooksey 0:fb7af294d5d9 614
Simon Cooksey 0:fb7af294d5d9 615 if( ssl->conf->alpn_list == NULL )
Simon Cooksey 0:fb7af294d5d9 616 {
Simon Cooksey 0:fb7af294d5d9 617 return;
Simon Cooksey 0:fb7af294d5d9 618 }
Simon Cooksey 0:fb7af294d5d9 619
Simon Cooksey 0:fb7af294d5d9 620 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) );
Simon Cooksey 0:fb7af294d5d9 621
Simon Cooksey 0:fb7af294d5d9 622 for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ )
Simon Cooksey 0:fb7af294d5d9 623 alpnlen += (unsigned char)( strlen( *cur ) & 0xFF ) + 1;
Simon Cooksey 0:fb7af294d5d9 624
Simon Cooksey 0:fb7af294d5d9 625 if( end < p || (size_t)( end - p ) < 6 + alpnlen )
Simon Cooksey 0:fb7af294d5d9 626 {
Simon Cooksey 0:fb7af294d5d9 627 MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
Simon Cooksey 0:fb7af294d5d9 628 return;
Simon Cooksey 0:fb7af294d5d9 629 }
Simon Cooksey 0:fb7af294d5d9 630
Simon Cooksey 0:fb7af294d5d9 631 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 632 *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 633
Simon Cooksey 0:fb7af294d5d9 634 /*
Simon Cooksey 0:fb7af294d5d9 635 * opaque ProtocolName<1..2^8-1>;
Simon Cooksey 0:fb7af294d5d9 636 *
Simon Cooksey 0:fb7af294d5d9 637 * struct {
Simon Cooksey 0:fb7af294d5d9 638 * ProtocolName protocol_name_list<2..2^16-1>
Simon Cooksey 0:fb7af294d5d9 639 * } ProtocolNameList;
Simon Cooksey 0:fb7af294d5d9 640 */
Simon Cooksey 0:fb7af294d5d9 641
Simon Cooksey 0:fb7af294d5d9 642 /* Skip writing extension and list length for now */
Simon Cooksey 0:fb7af294d5d9 643 p += 4;
Simon Cooksey 0:fb7af294d5d9 644
Simon Cooksey 0:fb7af294d5d9 645 for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ )
Simon Cooksey 0:fb7af294d5d9 646 {
Simon Cooksey 0:fb7af294d5d9 647 *p = (unsigned char)( strlen( *cur ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 648 memcpy( p + 1, *cur, *p );
Simon Cooksey 0:fb7af294d5d9 649 p += 1 + *p;
Simon Cooksey 0:fb7af294d5d9 650 }
Simon Cooksey 0:fb7af294d5d9 651
Simon Cooksey 0:fb7af294d5d9 652 *olen = p - buf;
Simon Cooksey 0:fb7af294d5d9 653
Simon Cooksey 0:fb7af294d5d9 654 /* List length = olen - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */
Simon Cooksey 0:fb7af294d5d9 655 buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 656 buf[5] = (unsigned char)( ( ( *olen - 6 ) ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 657
Simon Cooksey 0:fb7af294d5d9 658 /* Extension length = olen - 2 (ext_type) - 2 (ext_len) */
Simon Cooksey 0:fb7af294d5d9 659 buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 660 buf[3] = (unsigned char)( ( ( *olen - 4 ) ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 661 }
Simon Cooksey 0:fb7af294d5d9 662 #endif /* MBEDTLS_SSL_ALPN */
Simon Cooksey 0:fb7af294d5d9 663
Simon Cooksey 0:fb7af294d5d9 664 /*
Simon Cooksey 0:fb7af294d5d9 665 * Generate random bytes for ClientHello
Simon Cooksey 0:fb7af294d5d9 666 */
Simon Cooksey 0:fb7af294d5d9 667 static int ssl_generate_random( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 668 {
Simon Cooksey 0:fb7af294d5d9 669 int ret;
Simon Cooksey 0:fb7af294d5d9 670 unsigned char *p = ssl->handshake->randbytes;
Simon Cooksey 0:fb7af294d5d9 671 #if defined(MBEDTLS_HAVE_TIME)
Simon Cooksey 0:fb7af294d5d9 672 mbedtls_time_t t;
Simon Cooksey 0:fb7af294d5d9 673 #endif
Simon Cooksey 0:fb7af294d5d9 674
Simon Cooksey 0:fb7af294d5d9 675 /*
Simon Cooksey 0:fb7af294d5d9 676 * When responding to a verify request, MUST reuse random (RFC 6347 4.2.1)
Simon Cooksey 0:fb7af294d5d9 677 */
Simon Cooksey 0:fb7af294d5d9 678 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 679 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
Simon Cooksey 0:fb7af294d5d9 680 ssl->handshake->verify_cookie != NULL )
Simon Cooksey 0:fb7af294d5d9 681 {
Simon Cooksey 0:fb7af294d5d9 682 return( 0 );
Simon Cooksey 0:fb7af294d5d9 683 }
Simon Cooksey 0:fb7af294d5d9 684 #endif
Simon Cooksey 0:fb7af294d5d9 685
Simon Cooksey 0:fb7af294d5d9 686 #if defined(MBEDTLS_HAVE_TIME)
Simon Cooksey 0:fb7af294d5d9 687 t = mbedtls_time( NULL );
Simon Cooksey 0:fb7af294d5d9 688 *p++ = (unsigned char)( t >> 24 );
Simon Cooksey 0:fb7af294d5d9 689 *p++ = (unsigned char)( t >> 16 );
Simon Cooksey 0:fb7af294d5d9 690 *p++ = (unsigned char)( t >> 8 );
Simon Cooksey 0:fb7af294d5d9 691 *p++ = (unsigned char)( t );
Simon Cooksey 0:fb7af294d5d9 692
Simon Cooksey 0:fb7af294d5d9 693 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, current time: %lu", t ) );
Simon Cooksey 0:fb7af294d5d9 694 #else
Simon Cooksey 0:fb7af294d5d9 695 if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 696 return( ret );
Simon Cooksey 0:fb7af294d5d9 697
Simon Cooksey 0:fb7af294d5d9 698 p += 4;
Simon Cooksey 0:fb7af294d5d9 699 #endif /* MBEDTLS_HAVE_TIME */
Simon Cooksey 0:fb7af294d5d9 700
Simon Cooksey 0:fb7af294d5d9 701 if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 702 return( ret );
Simon Cooksey 0:fb7af294d5d9 703
Simon Cooksey 0:fb7af294d5d9 704 return( 0 );
Simon Cooksey 0:fb7af294d5d9 705 }
Simon Cooksey 0:fb7af294d5d9 706
Simon Cooksey 0:fb7af294d5d9 707 static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 708 {
Simon Cooksey 0:fb7af294d5d9 709 int ret;
Simon Cooksey 0:fb7af294d5d9 710 size_t i, n, olen, ext_len = 0;
Simon Cooksey 0:fb7af294d5d9 711 unsigned char *buf;
Simon Cooksey 0:fb7af294d5d9 712 unsigned char *p, *q;
Simon Cooksey 0:fb7af294d5d9 713 unsigned char offer_compress;
Simon Cooksey 0:fb7af294d5d9 714 const int *ciphersuites;
Simon Cooksey 0:fb7af294d5d9 715 const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
Simon Cooksey 0:fb7af294d5d9 716
Simon Cooksey 0:fb7af294d5d9 717 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) );
Simon Cooksey 0:fb7af294d5d9 718
Simon Cooksey 0:fb7af294d5d9 719 if( ssl->conf->f_rng == NULL )
Simon Cooksey 0:fb7af294d5d9 720 {
Simon Cooksey 0:fb7af294d5d9 721 MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") );
Simon Cooksey 0:fb7af294d5d9 722 return( MBEDTLS_ERR_SSL_NO_RNG );
Simon Cooksey 0:fb7af294d5d9 723 }
Simon Cooksey 0:fb7af294d5d9 724
Simon Cooksey 0:fb7af294d5d9 725 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 726 if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
Simon Cooksey 0:fb7af294d5d9 727 #endif
Simon Cooksey 0:fb7af294d5d9 728 {
Simon Cooksey 0:fb7af294d5d9 729 ssl->major_ver = ssl->conf->min_major_ver;
Simon Cooksey 0:fb7af294d5d9 730 ssl->minor_ver = ssl->conf->min_minor_ver;
Simon Cooksey 0:fb7af294d5d9 731 }
Simon Cooksey 0:fb7af294d5d9 732
Simon Cooksey 0:fb7af294d5d9 733 if( ssl->conf->max_major_ver == 0 )
Simon Cooksey 0:fb7af294d5d9 734 {
Simon Cooksey 0:fb7af294d5d9 735 MBEDTLS_SSL_DEBUG_MSG( 1, ( "configured max major version is invalid, "
Simon Cooksey 0:fb7af294d5d9 736 "consider using mbedtls_ssl_config_defaults()" ) );
Simon Cooksey 0:fb7af294d5d9 737 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
Simon Cooksey 0:fb7af294d5d9 738 }
Simon Cooksey 0:fb7af294d5d9 739
Simon Cooksey 0:fb7af294d5d9 740 /*
Simon Cooksey 0:fb7af294d5d9 741 * 0 . 0 handshake type
Simon Cooksey 0:fb7af294d5d9 742 * 1 . 3 handshake length
Simon Cooksey 0:fb7af294d5d9 743 * 4 . 5 highest version supported
Simon Cooksey 0:fb7af294d5d9 744 * 6 . 9 current UNIX time
Simon Cooksey 0:fb7af294d5d9 745 * 10 . 37 random bytes
Simon Cooksey 0:fb7af294d5d9 746 */
Simon Cooksey 0:fb7af294d5d9 747 buf = ssl->out_msg;
Simon Cooksey 0:fb7af294d5d9 748 p = buf + 4;
Simon Cooksey 0:fb7af294d5d9 749
Simon Cooksey 0:fb7af294d5d9 750 mbedtls_ssl_write_version( ssl->conf->max_major_ver, ssl->conf->max_minor_ver,
Simon Cooksey 0:fb7af294d5d9 751 ssl->conf->transport, p );
Simon Cooksey 0:fb7af294d5d9 752 p += 2;
Simon Cooksey 0:fb7af294d5d9 753
Simon Cooksey 0:fb7af294d5d9 754 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]",
Simon Cooksey 0:fb7af294d5d9 755 buf[4], buf[5] ) );
Simon Cooksey 0:fb7af294d5d9 756
Simon Cooksey 0:fb7af294d5d9 757 if( ( ret = ssl_generate_random( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 758 {
Simon Cooksey 0:fb7af294d5d9 759 MBEDTLS_SSL_DEBUG_RET( 1, "ssl_generate_random", ret );
Simon Cooksey 0:fb7af294d5d9 760 return( ret );
Simon Cooksey 0:fb7af294d5d9 761 }
Simon Cooksey 0:fb7af294d5d9 762
Simon Cooksey 0:fb7af294d5d9 763 memcpy( p, ssl->handshake->randbytes, 32 );
Simon Cooksey 0:fb7af294d5d9 764 MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", p, 32 );
Simon Cooksey 0:fb7af294d5d9 765 p += 32;
Simon Cooksey 0:fb7af294d5d9 766
Simon Cooksey 0:fb7af294d5d9 767 /*
Simon Cooksey 0:fb7af294d5d9 768 * 38 . 38 session id length
Simon Cooksey 0:fb7af294d5d9 769 * 39 . 39+n session id
Simon Cooksey 0:fb7af294d5d9 770 * 39+n . 39+n DTLS only: cookie length (1 byte)
Simon Cooksey 0:fb7af294d5d9 771 * 40+n . .. DTSL only: cookie
Simon Cooksey 0:fb7af294d5d9 772 * .. . .. ciphersuitelist length (2 bytes)
Simon Cooksey 0:fb7af294d5d9 773 * .. . .. ciphersuitelist
Simon Cooksey 0:fb7af294d5d9 774 * .. . .. compression methods length (1 byte)
Simon Cooksey 0:fb7af294d5d9 775 * .. . .. compression methods
Simon Cooksey 0:fb7af294d5d9 776 * .. . .. extensions length (2 bytes)
Simon Cooksey 0:fb7af294d5d9 777 * .. . .. extensions
Simon Cooksey 0:fb7af294d5d9 778 */
Simon Cooksey 0:fb7af294d5d9 779 n = ssl->session_negotiate->id_len;
Simon Cooksey 0:fb7af294d5d9 780
Simon Cooksey 0:fb7af294d5d9 781 if( n < 16 || n > 32 ||
Simon Cooksey 0:fb7af294d5d9 782 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 783 ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ||
Simon Cooksey 0:fb7af294d5d9 784 #endif
Simon Cooksey 0:fb7af294d5d9 785 ssl->handshake->resume == 0 )
Simon Cooksey 0:fb7af294d5d9 786 {
Simon Cooksey 0:fb7af294d5d9 787 n = 0;
Simon Cooksey 0:fb7af294d5d9 788 }
Simon Cooksey 0:fb7af294d5d9 789
Simon Cooksey 0:fb7af294d5d9 790 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
Simon Cooksey 0:fb7af294d5d9 791 /*
Simon Cooksey 0:fb7af294d5d9 792 * RFC 5077 section 3.4: "When presenting a ticket, the client MAY
Simon Cooksey 0:fb7af294d5d9 793 * generate and include a Session ID in the TLS ClientHello."
Simon Cooksey 0:fb7af294d5d9 794 */
Simon Cooksey 0:fb7af294d5d9 795 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 796 if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
Simon Cooksey 0:fb7af294d5d9 797 #endif
Simon Cooksey 0:fb7af294d5d9 798 {
Simon Cooksey 0:fb7af294d5d9 799 if( ssl->session_negotiate->ticket != NULL &&
Simon Cooksey 0:fb7af294d5d9 800 ssl->session_negotiate->ticket_len != 0 )
Simon Cooksey 0:fb7af294d5d9 801 {
Simon Cooksey 0:fb7af294d5d9 802 ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id, 32 );
Simon Cooksey 0:fb7af294d5d9 803
Simon Cooksey 0:fb7af294d5d9 804 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 805 return( ret );
Simon Cooksey 0:fb7af294d5d9 806
Simon Cooksey 0:fb7af294d5d9 807 ssl->session_negotiate->id_len = n = 32;
Simon Cooksey 0:fb7af294d5d9 808 }
Simon Cooksey 0:fb7af294d5d9 809 }
Simon Cooksey 0:fb7af294d5d9 810 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
Simon Cooksey 0:fb7af294d5d9 811
Simon Cooksey 0:fb7af294d5d9 812 *p++ = (unsigned char) n;
Simon Cooksey 0:fb7af294d5d9 813
Simon Cooksey 0:fb7af294d5d9 814 for( i = 0; i < n; i++ )
Simon Cooksey 0:fb7af294d5d9 815 *p++ = ssl->session_negotiate->id[i];
Simon Cooksey 0:fb7af294d5d9 816
Simon Cooksey 0:fb7af294d5d9 817 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) );
Simon Cooksey 0:fb7af294d5d9 818 MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 39, n );
Simon Cooksey 0:fb7af294d5d9 819
Simon Cooksey 0:fb7af294d5d9 820 /*
Simon Cooksey 0:fb7af294d5d9 821 * DTLS cookie
Simon Cooksey 0:fb7af294d5d9 822 */
Simon Cooksey 0:fb7af294d5d9 823 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 824 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
Simon Cooksey 0:fb7af294d5d9 825 {
Simon Cooksey 0:fb7af294d5d9 826 if( ssl->handshake->verify_cookie == NULL )
Simon Cooksey 0:fb7af294d5d9 827 {
Simon Cooksey 0:fb7af294d5d9 828 MBEDTLS_SSL_DEBUG_MSG( 3, ( "no verify cookie to send" ) );
Simon Cooksey 0:fb7af294d5d9 829 *p++ = 0;
Simon Cooksey 0:fb7af294d5d9 830 }
Simon Cooksey 0:fb7af294d5d9 831 else
Simon Cooksey 0:fb7af294d5d9 832 {
Simon Cooksey 0:fb7af294d5d9 833 MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie",
Simon Cooksey 0:fb7af294d5d9 834 ssl->handshake->verify_cookie,
Simon Cooksey 0:fb7af294d5d9 835 ssl->handshake->verify_cookie_len );
Simon Cooksey 0:fb7af294d5d9 836
Simon Cooksey 0:fb7af294d5d9 837 *p++ = ssl->handshake->verify_cookie_len;
Simon Cooksey 0:fb7af294d5d9 838 memcpy( p, ssl->handshake->verify_cookie,
Simon Cooksey 0:fb7af294d5d9 839 ssl->handshake->verify_cookie_len );
Simon Cooksey 0:fb7af294d5d9 840 p += ssl->handshake->verify_cookie_len;
Simon Cooksey 0:fb7af294d5d9 841 }
Simon Cooksey 0:fb7af294d5d9 842 }
Simon Cooksey 0:fb7af294d5d9 843 #endif
Simon Cooksey 0:fb7af294d5d9 844
Simon Cooksey 0:fb7af294d5d9 845 /*
Simon Cooksey 0:fb7af294d5d9 846 * Ciphersuite list
Simon Cooksey 0:fb7af294d5d9 847 */
Simon Cooksey 0:fb7af294d5d9 848 ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver];
Simon Cooksey 0:fb7af294d5d9 849
Simon Cooksey 0:fb7af294d5d9 850 /* Skip writing ciphersuite length for now */
Simon Cooksey 0:fb7af294d5d9 851 n = 0;
Simon Cooksey 0:fb7af294d5d9 852 q = p;
Simon Cooksey 0:fb7af294d5d9 853 p += 2;
Simon Cooksey 0:fb7af294d5d9 854
Simon Cooksey 0:fb7af294d5d9 855 for( i = 0; ciphersuites[i] != 0; i++ )
Simon Cooksey 0:fb7af294d5d9 856 {
Simon Cooksey 0:fb7af294d5d9 857 ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuites[i] );
Simon Cooksey 0:fb7af294d5d9 858
Simon Cooksey 0:fb7af294d5d9 859 if( ciphersuite_info == NULL )
Simon Cooksey 0:fb7af294d5d9 860 continue;
Simon Cooksey 0:fb7af294d5d9 861
Simon Cooksey 0:fb7af294d5d9 862 if( ciphersuite_info->min_minor_ver > ssl->conf->max_minor_ver ||
Simon Cooksey 0:fb7af294d5d9 863 ciphersuite_info->max_minor_ver < ssl->conf->min_minor_ver )
Simon Cooksey 0:fb7af294d5d9 864 continue;
Simon Cooksey 0:fb7af294d5d9 865
Simon Cooksey 0:fb7af294d5d9 866 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 867 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
Simon Cooksey 0:fb7af294d5d9 868 ( ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) )
Simon Cooksey 0:fb7af294d5d9 869 continue;
Simon Cooksey 0:fb7af294d5d9 870 #endif
Simon Cooksey 0:fb7af294d5d9 871
Simon Cooksey 0:fb7af294d5d9 872 #if defined(MBEDTLS_ARC4_C)
Simon Cooksey 0:fb7af294d5d9 873 if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED &&
Simon Cooksey 0:fb7af294d5d9 874 ciphersuite_info->cipher == MBEDTLS_CIPHER_ARC4_128 )
Simon Cooksey 0:fb7af294d5d9 875 continue;
Simon Cooksey 0:fb7af294d5d9 876 #endif
Simon Cooksey 0:fb7af294d5d9 877
Simon Cooksey 0:fb7af294d5d9 878 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 879 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE &&
Simon Cooksey 0:fb7af294d5d9 880 mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 )
Simon Cooksey 0:fb7af294d5d9 881 continue;
Simon Cooksey 0:fb7af294d5d9 882 #endif
Simon Cooksey 0:fb7af294d5d9 883
Simon Cooksey 0:fb7af294d5d9 884 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x",
Simon Cooksey 0:fb7af294d5d9 885 ciphersuites[i] ) );
Simon Cooksey 0:fb7af294d5d9 886
Simon Cooksey 0:fb7af294d5d9 887 n++;
Simon Cooksey 0:fb7af294d5d9 888 *p++ = (unsigned char)( ciphersuites[i] >> 8 );
Simon Cooksey 0:fb7af294d5d9 889 *p++ = (unsigned char)( ciphersuites[i] );
Simon Cooksey 0:fb7af294d5d9 890 }
Simon Cooksey 0:fb7af294d5d9 891
Simon Cooksey 0:fb7af294d5d9 892 /*
Simon Cooksey 0:fb7af294d5d9 893 * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV
Simon Cooksey 0:fb7af294d5d9 894 */
Simon Cooksey 0:fb7af294d5d9 895 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 896 if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
Simon Cooksey 0:fb7af294d5d9 897 #endif
Simon Cooksey 0:fb7af294d5d9 898 {
Simon Cooksey 0:fb7af294d5d9 899 *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO >> 8 );
Simon Cooksey 0:fb7af294d5d9 900 *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO );
Simon Cooksey 0:fb7af294d5d9 901 n++;
Simon Cooksey 0:fb7af294d5d9 902 }
Simon Cooksey 0:fb7af294d5d9 903
Simon Cooksey 0:fb7af294d5d9 904 /* Some versions of OpenSSL don't handle it correctly if not at end */
Simon Cooksey 0:fb7af294d5d9 905 #if defined(MBEDTLS_SSL_FALLBACK_SCSV)
Simon Cooksey 0:fb7af294d5d9 906 if( ssl->conf->fallback == MBEDTLS_SSL_IS_FALLBACK )
Simon Cooksey 0:fb7af294d5d9 907 {
Simon Cooksey 0:fb7af294d5d9 908 MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding FALLBACK_SCSV" ) );
Simon Cooksey 0:fb7af294d5d9 909 *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 );
Simon Cooksey 0:fb7af294d5d9 910 *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE );
Simon Cooksey 0:fb7af294d5d9 911 n++;
Simon Cooksey 0:fb7af294d5d9 912 }
Simon Cooksey 0:fb7af294d5d9 913 #endif
Simon Cooksey 0:fb7af294d5d9 914
Simon Cooksey 0:fb7af294d5d9 915 *q++ = (unsigned char)( n >> 7 );
Simon Cooksey 0:fb7af294d5d9 916 *q++ = (unsigned char)( n << 1 );
Simon Cooksey 0:fb7af294d5d9 917
Simon Cooksey 0:fb7af294d5d9 918 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites", n ) );
Simon Cooksey 0:fb7af294d5d9 919
Simon Cooksey 0:fb7af294d5d9 920 #if defined(MBEDTLS_ZLIB_SUPPORT)
Simon Cooksey 0:fb7af294d5d9 921 offer_compress = 1;
Simon Cooksey 0:fb7af294d5d9 922 #else
Simon Cooksey 0:fb7af294d5d9 923 offer_compress = 0;
Simon Cooksey 0:fb7af294d5d9 924 #endif
Simon Cooksey 0:fb7af294d5d9 925
Simon Cooksey 0:fb7af294d5d9 926 /*
Simon Cooksey 0:fb7af294d5d9 927 * We don't support compression with DTLS right now: is many records come
Simon Cooksey 0:fb7af294d5d9 928 * in the same datagram, uncompressing one could overwrite the next one.
Simon Cooksey 0:fb7af294d5d9 929 * We don't want to add complexity for handling that case unless there is
Simon Cooksey 0:fb7af294d5d9 930 * an actual need for it.
Simon Cooksey 0:fb7af294d5d9 931 */
Simon Cooksey 0:fb7af294d5d9 932 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 933 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
Simon Cooksey 0:fb7af294d5d9 934 offer_compress = 0;
Simon Cooksey 0:fb7af294d5d9 935 #endif
Simon Cooksey 0:fb7af294d5d9 936
Simon Cooksey 0:fb7af294d5d9 937 if( offer_compress )
Simon Cooksey 0:fb7af294d5d9 938 {
Simon Cooksey 0:fb7af294d5d9 939 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 2 ) );
Simon Cooksey 0:fb7af294d5d9 940 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d %d",
Simon Cooksey 0:fb7af294d5d9 941 MBEDTLS_SSL_COMPRESS_DEFLATE, MBEDTLS_SSL_COMPRESS_NULL ) );
Simon Cooksey 0:fb7af294d5d9 942
Simon Cooksey 0:fb7af294d5d9 943 *p++ = 2;
Simon Cooksey 0:fb7af294d5d9 944 *p++ = MBEDTLS_SSL_COMPRESS_DEFLATE;
Simon Cooksey 0:fb7af294d5d9 945 *p++ = MBEDTLS_SSL_COMPRESS_NULL;
Simon Cooksey 0:fb7af294d5d9 946 }
Simon Cooksey 0:fb7af294d5d9 947 else
Simon Cooksey 0:fb7af294d5d9 948 {
Simon Cooksey 0:fb7af294d5d9 949 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) );
Simon Cooksey 0:fb7af294d5d9 950 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d",
Simon Cooksey 0:fb7af294d5d9 951 MBEDTLS_SSL_COMPRESS_NULL ) );
Simon Cooksey 0:fb7af294d5d9 952
Simon Cooksey 0:fb7af294d5d9 953 *p++ = 1;
Simon Cooksey 0:fb7af294d5d9 954 *p++ = MBEDTLS_SSL_COMPRESS_NULL;
Simon Cooksey 0:fb7af294d5d9 955 }
Simon Cooksey 0:fb7af294d5d9 956
Simon Cooksey 0:fb7af294d5d9 957 // First write extensions, then the total length
Simon Cooksey 0:fb7af294d5d9 958 //
Simon Cooksey 0:fb7af294d5d9 959 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
Simon Cooksey 0:fb7af294d5d9 960 ssl_write_hostname_ext( ssl, p + 2 + ext_len, &olen );
Simon Cooksey 0:fb7af294d5d9 961 ext_len += olen;
Simon Cooksey 0:fb7af294d5d9 962 #endif
Simon Cooksey 0:fb7af294d5d9 963
Simon Cooksey 0:fb7af294d5d9 964 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 965 ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen );
Simon Cooksey 0:fb7af294d5d9 966 ext_len += olen;
Simon Cooksey 0:fb7af294d5d9 967 #endif
Simon Cooksey 0:fb7af294d5d9 968
Simon Cooksey 0:fb7af294d5d9 969 #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
Simon Cooksey 0:fb7af294d5d9 970 defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
Simon Cooksey 0:fb7af294d5d9 971 ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len, &olen );
Simon Cooksey 0:fb7af294d5d9 972 ext_len += olen;
Simon Cooksey 0:fb7af294d5d9 973 #endif
Simon Cooksey 0:fb7af294d5d9 974
Simon Cooksey 0:fb7af294d5d9 975 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
Simon Cooksey 0:fb7af294d5d9 976 defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 977 ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen );
Simon Cooksey 0:fb7af294d5d9 978 ext_len += olen;
Simon Cooksey 0:fb7af294d5d9 979
Simon Cooksey 0:fb7af294d5d9 980 ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
Simon Cooksey 0:fb7af294d5d9 981 ext_len += olen;
Simon Cooksey 0:fb7af294d5d9 982 #endif
Simon Cooksey 0:fb7af294d5d9 983
Simon Cooksey 0:fb7af294d5d9 984 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 985 ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen );
Simon Cooksey 0:fb7af294d5d9 986 ext_len += olen;
Simon Cooksey 0:fb7af294d5d9 987 #endif
Simon Cooksey 0:fb7af294d5d9 988
Simon Cooksey 0:fb7af294d5d9 989 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
Simon Cooksey 0:fb7af294d5d9 990 ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen );
Simon Cooksey 0:fb7af294d5d9 991 ext_len += olen;
Simon Cooksey 0:fb7af294d5d9 992 #endif
Simon Cooksey 0:fb7af294d5d9 993
Simon Cooksey 0:fb7af294d5d9 994 #if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
Simon Cooksey 0:fb7af294d5d9 995 ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen );
Simon Cooksey 0:fb7af294d5d9 996 ext_len += olen;
Simon Cooksey 0:fb7af294d5d9 997 #endif
Simon Cooksey 0:fb7af294d5d9 998
Simon Cooksey 0:fb7af294d5d9 999 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
Simon Cooksey 0:fb7af294d5d9 1000 ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen );
Simon Cooksey 0:fb7af294d5d9 1001 ext_len += olen;
Simon Cooksey 0:fb7af294d5d9 1002 #endif
Simon Cooksey 0:fb7af294d5d9 1003
Simon Cooksey 0:fb7af294d5d9 1004 #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
Simon Cooksey 0:fb7af294d5d9 1005 ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen );
Simon Cooksey 0:fb7af294d5d9 1006 ext_len += olen;
Simon Cooksey 0:fb7af294d5d9 1007 #endif
Simon Cooksey 0:fb7af294d5d9 1008
Simon Cooksey 0:fb7af294d5d9 1009 #if defined(MBEDTLS_SSL_ALPN)
Simon Cooksey 0:fb7af294d5d9 1010 ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen );
Simon Cooksey 0:fb7af294d5d9 1011 ext_len += olen;
Simon Cooksey 0:fb7af294d5d9 1012 #endif
Simon Cooksey 0:fb7af294d5d9 1013
Simon Cooksey 0:fb7af294d5d9 1014 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
Simon Cooksey 0:fb7af294d5d9 1015 ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen );
Simon Cooksey 0:fb7af294d5d9 1016 ext_len += olen;
Simon Cooksey 0:fb7af294d5d9 1017 #endif
Simon Cooksey 0:fb7af294d5d9 1018
Simon Cooksey 0:fb7af294d5d9 1019 /* olen unused if all extensions are disabled */
Simon Cooksey 0:fb7af294d5d9 1020 ((void) olen);
Simon Cooksey 0:fb7af294d5d9 1021
Simon Cooksey 0:fb7af294d5d9 1022 MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d",
Simon Cooksey 0:fb7af294d5d9 1023 ext_len ) );
Simon Cooksey 0:fb7af294d5d9 1024
Simon Cooksey 0:fb7af294d5d9 1025 if( ext_len > 0 )
Simon Cooksey 0:fb7af294d5d9 1026 {
Simon Cooksey 0:fb7af294d5d9 1027 *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 1028 *p++ = (unsigned char)( ( ext_len ) & 0xFF );
Simon Cooksey 0:fb7af294d5d9 1029 p += ext_len;
Simon Cooksey 0:fb7af294d5d9 1030 }
Simon Cooksey 0:fb7af294d5d9 1031
Simon Cooksey 0:fb7af294d5d9 1032 ssl->out_msglen = p - buf;
Simon Cooksey 0:fb7af294d5d9 1033 ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
Simon Cooksey 0:fb7af294d5d9 1034 ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_HELLO;
Simon Cooksey 0:fb7af294d5d9 1035
Simon Cooksey 0:fb7af294d5d9 1036 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 1037
Simon Cooksey 0:fb7af294d5d9 1038 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 1039 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
Simon Cooksey 0:fb7af294d5d9 1040 mbedtls_ssl_send_flight_completed( ssl );
Simon Cooksey 0:fb7af294d5d9 1041 #endif
Simon Cooksey 0:fb7af294d5d9 1042
Simon Cooksey 0:fb7af294d5d9 1043 if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1044 {
Simon Cooksey 0:fb7af294d5d9 1045 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
Simon Cooksey 0:fb7af294d5d9 1046 return( ret );
Simon Cooksey 0:fb7af294d5d9 1047 }
Simon Cooksey 0:fb7af294d5d9 1048
Simon Cooksey 0:fb7af294d5d9 1049 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) );
Simon Cooksey 0:fb7af294d5d9 1050
Simon Cooksey 0:fb7af294d5d9 1051 return( 0 );
Simon Cooksey 0:fb7af294d5d9 1052 }
Simon Cooksey 0:fb7af294d5d9 1053
Simon Cooksey 0:fb7af294d5d9 1054 static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 1055 const unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 1056 size_t len )
Simon Cooksey 0:fb7af294d5d9 1057 {
Simon Cooksey 0:fb7af294d5d9 1058 int ret;
Simon Cooksey 0:fb7af294d5d9 1059
Simon Cooksey 0:fb7af294d5d9 1060 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 1061 if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
Simon Cooksey 0:fb7af294d5d9 1062 {
Simon Cooksey 0:fb7af294d5d9 1063 /* Check verify-data in constant-time. The length OTOH is no secret */
Simon Cooksey 0:fb7af294d5d9 1064 if( len != 1 + ssl->verify_data_len * 2 ||
Simon Cooksey 0:fb7af294d5d9 1065 buf[0] != ssl->verify_data_len * 2 ||
Simon Cooksey 0:fb7af294d5d9 1066 mbedtls_ssl_safer_memcmp( buf + 1,
Simon Cooksey 0:fb7af294d5d9 1067 ssl->own_verify_data, ssl->verify_data_len ) != 0 ||
Simon Cooksey 0:fb7af294d5d9 1068 mbedtls_ssl_safer_memcmp( buf + 1 + ssl->verify_data_len,
Simon Cooksey 0:fb7af294d5d9 1069 ssl->peer_verify_data, ssl->verify_data_len ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1070 {
Simon Cooksey 0:fb7af294d5d9 1071 MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) );
Simon Cooksey 0:fb7af294d5d9 1072
Simon Cooksey 0:fb7af294d5d9 1073 if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1074 return( ret );
Simon Cooksey 0:fb7af294d5d9 1075
Simon Cooksey 0:fb7af294d5d9 1076 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1077 }
Simon Cooksey 0:fb7af294d5d9 1078 }
Simon Cooksey 0:fb7af294d5d9 1079 else
Simon Cooksey 0:fb7af294d5d9 1080 #endif /* MBEDTLS_SSL_RENEGOTIATION */
Simon Cooksey 0:fb7af294d5d9 1081 {
Simon Cooksey 0:fb7af294d5d9 1082 if( len != 1 || buf[0] != 0x00 )
Simon Cooksey 0:fb7af294d5d9 1083 {
Simon Cooksey 0:fb7af294d5d9 1084 MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) );
Simon Cooksey 0:fb7af294d5d9 1085
Simon Cooksey 0:fb7af294d5d9 1086 if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1087 return( ret );
Simon Cooksey 0:fb7af294d5d9 1088
Simon Cooksey 0:fb7af294d5d9 1089 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1090 }
Simon Cooksey 0:fb7af294d5d9 1091
Simon Cooksey 0:fb7af294d5d9 1092 ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION;
Simon Cooksey 0:fb7af294d5d9 1093 }
Simon Cooksey 0:fb7af294d5d9 1094
Simon Cooksey 0:fb7af294d5d9 1095 return( 0 );
Simon Cooksey 0:fb7af294d5d9 1096 }
Simon Cooksey 0:fb7af294d5d9 1097
Simon Cooksey 0:fb7af294d5d9 1098 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
Simon Cooksey 0:fb7af294d5d9 1099 static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 1100 const unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 1101 size_t len )
Simon Cooksey 0:fb7af294d5d9 1102 {
Simon Cooksey 0:fb7af294d5d9 1103 /*
Simon Cooksey 0:fb7af294d5d9 1104 * server should use the extension only if we did,
Simon Cooksey 0:fb7af294d5d9 1105 * and if so the server's value should match ours (and len is always 1)
Simon Cooksey 0:fb7af294d5d9 1106 */
Simon Cooksey 0:fb7af294d5d9 1107 if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ||
Simon Cooksey 0:fb7af294d5d9 1108 len != 1 ||
Simon Cooksey 0:fb7af294d5d9 1109 buf[0] != ssl->conf->mfl_code )
Simon Cooksey 0:fb7af294d5d9 1110 {
Simon Cooksey 0:fb7af294d5d9 1111 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1112 }
Simon Cooksey 0:fb7af294d5d9 1113
Simon Cooksey 0:fb7af294d5d9 1114 return( 0 );
Simon Cooksey 0:fb7af294d5d9 1115 }
Simon Cooksey 0:fb7af294d5d9 1116 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
Simon Cooksey 0:fb7af294d5d9 1117
Simon Cooksey 0:fb7af294d5d9 1118 #if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
Simon Cooksey 0:fb7af294d5d9 1119 static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 1120 const unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 1121 size_t len )
Simon Cooksey 0:fb7af294d5d9 1122 {
Simon Cooksey 0:fb7af294d5d9 1123 if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ||
Simon Cooksey 0:fb7af294d5d9 1124 len != 0 )
Simon Cooksey 0:fb7af294d5d9 1125 {
Simon Cooksey 0:fb7af294d5d9 1126 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1127 }
Simon Cooksey 0:fb7af294d5d9 1128
Simon Cooksey 0:fb7af294d5d9 1129 ((void) buf);
Simon Cooksey 0:fb7af294d5d9 1130
Simon Cooksey 0:fb7af294d5d9 1131 ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED;
Simon Cooksey 0:fb7af294d5d9 1132
Simon Cooksey 0:fb7af294d5d9 1133 return( 0 );
Simon Cooksey 0:fb7af294d5d9 1134 }
Simon Cooksey 0:fb7af294d5d9 1135 #endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
Simon Cooksey 0:fb7af294d5d9 1136
Simon Cooksey 0:fb7af294d5d9 1137 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
Simon Cooksey 0:fb7af294d5d9 1138 static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 1139 const unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 1140 size_t len )
Simon Cooksey 0:fb7af294d5d9 1141 {
Simon Cooksey 0:fb7af294d5d9 1142 if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED ||
Simon Cooksey 0:fb7af294d5d9 1143 ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ||
Simon Cooksey 0:fb7af294d5d9 1144 len != 0 )
Simon Cooksey 0:fb7af294d5d9 1145 {
Simon Cooksey 0:fb7af294d5d9 1146 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1147 }
Simon Cooksey 0:fb7af294d5d9 1148
Simon Cooksey 0:fb7af294d5d9 1149 ((void) buf);
Simon Cooksey 0:fb7af294d5d9 1150
Simon Cooksey 0:fb7af294d5d9 1151 ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED;
Simon Cooksey 0:fb7af294d5d9 1152
Simon Cooksey 0:fb7af294d5d9 1153 return( 0 );
Simon Cooksey 0:fb7af294d5d9 1154 }
Simon Cooksey 0:fb7af294d5d9 1155 #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
Simon Cooksey 0:fb7af294d5d9 1156
Simon Cooksey 0:fb7af294d5d9 1157 #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
Simon Cooksey 0:fb7af294d5d9 1158 static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 1159 const unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 1160 size_t len )
Simon Cooksey 0:fb7af294d5d9 1161 {
Simon Cooksey 0:fb7af294d5d9 1162 if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED ||
Simon Cooksey 0:fb7af294d5d9 1163 ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ||
Simon Cooksey 0:fb7af294d5d9 1164 len != 0 )
Simon Cooksey 0:fb7af294d5d9 1165 {
Simon Cooksey 0:fb7af294d5d9 1166 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1167 }
Simon Cooksey 0:fb7af294d5d9 1168
Simon Cooksey 0:fb7af294d5d9 1169 ((void) buf);
Simon Cooksey 0:fb7af294d5d9 1170
Simon Cooksey 0:fb7af294d5d9 1171 ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED;
Simon Cooksey 0:fb7af294d5d9 1172
Simon Cooksey 0:fb7af294d5d9 1173 return( 0 );
Simon Cooksey 0:fb7af294d5d9 1174 }
Simon Cooksey 0:fb7af294d5d9 1175 #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
Simon Cooksey 0:fb7af294d5d9 1176
Simon Cooksey 0:fb7af294d5d9 1177 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
Simon Cooksey 0:fb7af294d5d9 1178 static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 1179 const unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 1180 size_t len )
Simon Cooksey 0:fb7af294d5d9 1181 {
Simon Cooksey 0:fb7af294d5d9 1182 if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED ||
Simon Cooksey 0:fb7af294d5d9 1183 len != 0 )
Simon Cooksey 0:fb7af294d5d9 1184 {
Simon Cooksey 0:fb7af294d5d9 1185 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1186 }
Simon Cooksey 0:fb7af294d5d9 1187
Simon Cooksey 0:fb7af294d5d9 1188 ((void) buf);
Simon Cooksey 0:fb7af294d5d9 1189
Simon Cooksey 0:fb7af294d5d9 1190 ssl->handshake->new_session_ticket = 1;
Simon Cooksey 0:fb7af294d5d9 1191
Simon Cooksey 0:fb7af294d5d9 1192 return( 0 );
Simon Cooksey 0:fb7af294d5d9 1193 }
Simon Cooksey 0:fb7af294d5d9 1194 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
Simon Cooksey 0:fb7af294d5d9 1195
Simon Cooksey 0:fb7af294d5d9 1196 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
Simon Cooksey 0:fb7af294d5d9 1197 defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 1198 static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 1199 const unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 1200 size_t len )
Simon Cooksey 0:fb7af294d5d9 1201 {
Simon Cooksey 0:fb7af294d5d9 1202 size_t list_size;
Simon Cooksey 0:fb7af294d5d9 1203 const unsigned char *p;
Simon Cooksey 0:fb7af294d5d9 1204
Simon Cooksey 0:fb7af294d5d9 1205 list_size = buf[0];
Simon Cooksey 0:fb7af294d5d9 1206 if( list_size + 1 != len )
Simon Cooksey 0:fb7af294d5d9 1207 {
Simon Cooksey 0:fb7af294d5d9 1208 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1209 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1210 }
Simon Cooksey 0:fb7af294d5d9 1211
Simon Cooksey 0:fb7af294d5d9 1212 p = buf + 1;
Simon Cooksey 0:fb7af294d5d9 1213 while( list_size > 0 )
Simon Cooksey 0:fb7af294d5d9 1214 {
Simon Cooksey 0:fb7af294d5d9 1215 if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED ||
Simon Cooksey 0:fb7af294d5d9 1216 p[0] == MBEDTLS_ECP_PF_COMPRESSED )
Simon Cooksey 0:fb7af294d5d9 1217 {
Simon Cooksey 0:fb7af294d5d9 1218 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)
Simon Cooksey 0:fb7af294d5d9 1219 ssl->handshake->ecdh_ctx.point_format = p[0];
Simon Cooksey 0:fb7af294d5d9 1220 #endif
Simon Cooksey 0:fb7af294d5d9 1221 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 1222 ssl->handshake->ecjpake_ctx.point_format = p[0];
Simon Cooksey 0:fb7af294d5d9 1223 #endif
Simon Cooksey 0:fb7af294d5d9 1224 MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) );
Simon Cooksey 0:fb7af294d5d9 1225 return( 0 );
Simon Cooksey 0:fb7af294d5d9 1226 }
Simon Cooksey 0:fb7af294d5d9 1227
Simon Cooksey 0:fb7af294d5d9 1228 list_size--;
Simon Cooksey 0:fb7af294d5d9 1229 p++;
Simon Cooksey 0:fb7af294d5d9 1230 }
Simon Cooksey 0:fb7af294d5d9 1231
Simon Cooksey 0:fb7af294d5d9 1232 MBEDTLS_SSL_DEBUG_MSG( 1, ( "no point format in common" ) );
Simon Cooksey 0:fb7af294d5d9 1233 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1234 }
Simon Cooksey 0:fb7af294d5d9 1235 #endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
Simon Cooksey 0:fb7af294d5d9 1236 MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
Simon Cooksey 0:fb7af294d5d9 1237
Simon Cooksey 0:fb7af294d5d9 1238 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 1239 static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 1240 const unsigned char *buf,
Simon Cooksey 0:fb7af294d5d9 1241 size_t len )
Simon Cooksey 0:fb7af294d5d9 1242 {
Simon Cooksey 0:fb7af294d5d9 1243 int ret;
Simon Cooksey 0:fb7af294d5d9 1244
Simon Cooksey 0:fb7af294d5d9 1245 if( ssl->transform_negotiate->ciphersuite_info->key_exchange !=
Simon Cooksey 0:fb7af294d5d9 1246 MBEDTLS_KEY_EXCHANGE_ECJPAKE )
Simon Cooksey 0:fb7af294d5d9 1247 {
Simon Cooksey 0:fb7af294d5d9 1248 MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) );
Simon Cooksey 0:fb7af294d5d9 1249 return( 0 );
Simon Cooksey 0:fb7af294d5d9 1250 }
Simon Cooksey 0:fb7af294d5d9 1251
Simon Cooksey 0:fb7af294d5d9 1252 /* If we got here, we no longer need our cached extension */
Simon Cooksey 0:fb7af294d5d9 1253 mbedtls_free( ssl->handshake->ecjpake_cache );
Simon Cooksey 0:fb7af294d5d9 1254 ssl->handshake->ecjpake_cache = NULL;
Simon Cooksey 0:fb7af294d5d9 1255 ssl->handshake->ecjpake_cache_len = 0;
Simon Cooksey 0:fb7af294d5d9 1256
Simon Cooksey 0:fb7af294d5d9 1257 if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx,
Simon Cooksey 0:fb7af294d5d9 1258 buf, len ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1259 {
Simon Cooksey 0:fb7af294d5d9 1260 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret );
Simon Cooksey 0:fb7af294d5d9 1261 return( ret );
Simon Cooksey 0:fb7af294d5d9 1262 }
Simon Cooksey 0:fb7af294d5d9 1263
Simon Cooksey 0:fb7af294d5d9 1264 return( 0 );
Simon Cooksey 0:fb7af294d5d9 1265 }
Simon Cooksey 0:fb7af294d5d9 1266 #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
Simon Cooksey 0:fb7af294d5d9 1267
Simon Cooksey 0:fb7af294d5d9 1268 #if defined(MBEDTLS_SSL_ALPN)
Simon Cooksey 0:fb7af294d5d9 1269 static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 1270 const unsigned char *buf, size_t len )
Simon Cooksey 0:fb7af294d5d9 1271 {
Simon Cooksey 0:fb7af294d5d9 1272 size_t list_len, name_len;
Simon Cooksey 0:fb7af294d5d9 1273 const char **p;
Simon Cooksey 0:fb7af294d5d9 1274
Simon Cooksey 0:fb7af294d5d9 1275 /* If we didn't send it, the server shouldn't send it */
Simon Cooksey 0:fb7af294d5d9 1276 if( ssl->conf->alpn_list == NULL )
Simon Cooksey 0:fb7af294d5d9 1277 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1278
Simon Cooksey 0:fb7af294d5d9 1279 /*
Simon Cooksey 0:fb7af294d5d9 1280 * opaque ProtocolName<1..2^8-1>;
Simon Cooksey 0:fb7af294d5d9 1281 *
Simon Cooksey 0:fb7af294d5d9 1282 * struct {
Simon Cooksey 0:fb7af294d5d9 1283 * ProtocolName protocol_name_list<2..2^16-1>
Simon Cooksey 0:fb7af294d5d9 1284 * } ProtocolNameList;
Simon Cooksey 0:fb7af294d5d9 1285 *
Simon Cooksey 0:fb7af294d5d9 1286 * the "ProtocolNameList" MUST contain exactly one "ProtocolName"
Simon Cooksey 0:fb7af294d5d9 1287 */
Simon Cooksey 0:fb7af294d5d9 1288
Simon Cooksey 0:fb7af294d5d9 1289 /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */
Simon Cooksey 0:fb7af294d5d9 1290 if( len < 4 )
Simon Cooksey 0:fb7af294d5d9 1291 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1292
Simon Cooksey 0:fb7af294d5d9 1293 list_len = ( buf[0] << 8 ) | buf[1];
Simon Cooksey 0:fb7af294d5d9 1294 if( list_len != len - 2 )
Simon Cooksey 0:fb7af294d5d9 1295 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1296
Simon Cooksey 0:fb7af294d5d9 1297 name_len = buf[2];
Simon Cooksey 0:fb7af294d5d9 1298 if( name_len != list_len - 1 )
Simon Cooksey 0:fb7af294d5d9 1299 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1300
Simon Cooksey 0:fb7af294d5d9 1301 /* Check that the server chosen protocol was in our list and save it */
Simon Cooksey 0:fb7af294d5d9 1302 for( p = ssl->conf->alpn_list; *p != NULL; p++ )
Simon Cooksey 0:fb7af294d5d9 1303 {
Simon Cooksey 0:fb7af294d5d9 1304 if( name_len == strlen( *p ) &&
Simon Cooksey 0:fb7af294d5d9 1305 memcmp( buf + 3, *p, name_len ) == 0 )
Simon Cooksey 0:fb7af294d5d9 1306 {
Simon Cooksey 0:fb7af294d5d9 1307 ssl->alpn_chosen = *p;
Simon Cooksey 0:fb7af294d5d9 1308 return( 0 );
Simon Cooksey 0:fb7af294d5d9 1309 }
Simon Cooksey 0:fb7af294d5d9 1310 }
Simon Cooksey 0:fb7af294d5d9 1311
Simon Cooksey 0:fb7af294d5d9 1312 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1313 }
Simon Cooksey 0:fb7af294d5d9 1314 #endif /* MBEDTLS_SSL_ALPN */
Simon Cooksey 0:fb7af294d5d9 1315
Simon Cooksey 0:fb7af294d5d9 1316 /*
Simon Cooksey 0:fb7af294d5d9 1317 * Parse HelloVerifyRequest. Only called after verifying the HS type.
Simon Cooksey 0:fb7af294d5d9 1318 */
Simon Cooksey 0:fb7af294d5d9 1319 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 1320 static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 1321 {
Simon Cooksey 0:fb7af294d5d9 1322 const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
Simon Cooksey 0:fb7af294d5d9 1323 int major_ver, minor_ver;
Simon Cooksey 0:fb7af294d5d9 1324 unsigned char cookie_len;
Simon Cooksey 0:fb7af294d5d9 1325
Simon Cooksey 0:fb7af294d5d9 1326 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse hello verify request" ) );
Simon Cooksey 0:fb7af294d5d9 1327
Simon Cooksey 0:fb7af294d5d9 1328 /*
Simon Cooksey 0:fb7af294d5d9 1329 * struct {
Simon Cooksey 0:fb7af294d5d9 1330 * ProtocolVersion server_version;
Simon Cooksey 0:fb7af294d5d9 1331 * opaque cookie<0..2^8-1>;
Simon Cooksey 0:fb7af294d5d9 1332 * } HelloVerifyRequest;
Simon Cooksey 0:fb7af294d5d9 1333 */
Simon Cooksey 0:fb7af294d5d9 1334 MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 );
Simon Cooksey 0:fb7af294d5d9 1335 mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, p );
Simon Cooksey 0:fb7af294d5d9 1336 p += 2;
Simon Cooksey 0:fb7af294d5d9 1337
Simon Cooksey 0:fb7af294d5d9 1338 /*
Simon Cooksey 0:fb7af294d5d9 1339 * Since the RFC is not clear on this point, accept DTLS 1.0 (TLS 1.1)
Simon Cooksey 0:fb7af294d5d9 1340 * even is lower than our min version.
Simon Cooksey 0:fb7af294d5d9 1341 */
Simon Cooksey 0:fb7af294d5d9 1342 if( major_ver < MBEDTLS_SSL_MAJOR_VERSION_3 ||
Simon Cooksey 0:fb7af294d5d9 1343 minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ||
Simon Cooksey 0:fb7af294d5d9 1344 major_ver > ssl->conf->max_major_ver ||
Simon Cooksey 0:fb7af294d5d9 1345 minor_ver > ssl->conf->max_minor_ver )
Simon Cooksey 0:fb7af294d5d9 1346 {
Simon Cooksey 0:fb7af294d5d9 1347 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server version" ) );
Simon Cooksey 0:fb7af294d5d9 1348
Simon Cooksey 0:fb7af294d5d9 1349 mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
Simon Cooksey 0:fb7af294d5d9 1350 MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION );
Simon Cooksey 0:fb7af294d5d9 1351
Simon Cooksey 0:fb7af294d5d9 1352 return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION );
Simon Cooksey 0:fb7af294d5d9 1353 }
Simon Cooksey 0:fb7af294d5d9 1354
Simon Cooksey 0:fb7af294d5d9 1355 cookie_len = *p++;
Simon Cooksey 0:fb7af294d5d9 1356 MBEDTLS_SSL_DEBUG_BUF( 3, "cookie", p, cookie_len );
Simon Cooksey 0:fb7af294d5d9 1357
Simon Cooksey 0:fb7af294d5d9 1358 if( ( ssl->in_msg + ssl->in_msglen ) - p < cookie_len )
Simon Cooksey 0:fb7af294d5d9 1359 {
Simon Cooksey 0:fb7af294d5d9 1360 MBEDTLS_SSL_DEBUG_MSG( 1,
Simon Cooksey 0:fb7af294d5d9 1361 ( "cookie length does not match incoming message size" ) );
Simon Cooksey 0:fb7af294d5d9 1362 mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
Simon Cooksey 0:fb7af294d5d9 1363 MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
Simon Cooksey 0:fb7af294d5d9 1364 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1365 }
Simon Cooksey 0:fb7af294d5d9 1366
Simon Cooksey 0:fb7af294d5d9 1367 mbedtls_free( ssl->handshake->verify_cookie );
Simon Cooksey 0:fb7af294d5d9 1368
Simon Cooksey 0:fb7af294d5d9 1369 ssl->handshake->verify_cookie = mbedtls_calloc( 1, cookie_len );
Simon Cooksey 0:fb7af294d5d9 1370 if( ssl->handshake->verify_cookie == NULL )
Simon Cooksey 0:fb7af294d5d9 1371 {
Simon Cooksey 0:fb7af294d5d9 1372 MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", cookie_len ) );
Simon Cooksey 0:fb7af294d5d9 1373 return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
Simon Cooksey 0:fb7af294d5d9 1374 }
Simon Cooksey 0:fb7af294d5d9 1375
Simon Cooksey 0:fb7af294d5d9 1376 memcpy( ssl->handshake->verify_cookie, p, cookie_len );
Simon Cooksey 0:fb7af294d5d9 1377 ssl->handshake->verify_cookie_len = cookie_len;
Simon Cooksey 0:fb7af294d5d9 1378
Simon Cooksey 0:fb7af294d5d9 1379 /* Start over at ClientHello */
Simon Cooksey 0:fb7af294d5d9 1380 ssl->state = MBEDTLS_SSL_CLIENT_HELLO;
Simon Cooksey 0:fb7af294d5d9 1381 mbedtls_ssl_reset_checksum( ssl );
Simon Cooksey 0:fb7af294d5d9 1382
Simon Cooksey 0:fb7af294d5d9 1383 mbedtls_ssl_recv_flight_completed( ssl );
Simon Cooksey 0:fb7af294d5d9 1384
Simon Cooksey 0:fb7af294d5d9 1385 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse hello verify request" ) );
Simon Cooksey 0:fb7af294d5d9 1386
Simon Cooksey 0:fb7af294d5d9 1387 return( 0 );
Simon Cooksey 0:fb7af294d5d9 1388 }
Simon Cooksey 0:fb7af294d5d9 1389 #endif /* MBEDTLS_SSL_PROTO_DTLS */
Simon Cooksey 0:fb7af294d5d9 1390
Simon Cooksey 0:fb7af294d5d9 1391 static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 1392 {
Simon Cooksey 0:fb7af294d5d9 1393 int ret, i;
Simon Cooksey 0:fb7af294d5d9 1394 size_t n;
Simon Cooksey 0:fb7af294d5d9 1395 size_t ext_len;
Simon Cooksey 0:fb7af294d5d9 1396 unsigned char *buf, *ext;
Simon Cooksey 0:fb7af294d5d9 1397 unsigned char comp;
Simon Cooksey 0:fb7af294d5d9 1398 #if defined(MBEDTLS_ZLIB_SUPPORT)
Simon Cooksey 0:fb7af294d5d9 1399 int accept_comp;
Simon Cooksey 0:fb7af294d5d9 1400 #endif
Simon Cooksey 0:fb7af294d5d9 1401 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 1402 int renegotiation_info_seen = 0;
Simon Cooksey 0:fb7af294d5d9 1403 #endif
Simon Cooksey 0:fb7af294d5d9 1404 int handshake_failure = 0;
Simon Cooksey 0:fb7af294d5d9 1405 const mbedtls_ssl_ciphersuite_t *suite_info;
Simon Cooksey 0:fb7af294d5d9 1406 #if defined(MBEDTLS_DEBUG_C)
Simon Cooksey 0:fb7af294d5d9 1407 uint32_t t;
Simon Cooksey 0:fb7af294d5d9 1408 #endif
Simon Cooksey 0:fb7af294d5d9 1409
Simon Cooksey 0:fb7af294d5d9 1410 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) );
Simon Cooksey 0:fb7af294d5d9 1411
Simon Cooksey 0:fb7af294d5d9 1412 buf = ssl->in_msg;
Simon Cooksey 0:fb7af294d5d9 1413
Simon Cooksey 0:fb7af294d5d9 1414 if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1415 {
Simon Cooksey 0:fb7af294d5d9 1416 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
Simon Cooksey 0:fb7af294d5d9 1417 return( ret );
Simon Cooksey 0:fb7af294d5d9 1418 }
Simon Cooksey 0:fb7af294d5d9 1419
Simon Cooksey 0:fb7af294d5d9 1420 if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
Simon Cooksey 0:fb7af294d5d9 1421 {
Simon Cooksey 0:fb7af294d5d9 1422 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 1423 if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
Simon Cooksey 0:fb7af294d5d9 1424 {
Simon Cooksey 0:fb7af294d5d9 1425 ssl->renego_records_seen++;
Simon Cooksey 0:fb7af294d5d9 1426
Simon Cooksey 0:fb7af294d5d9 1427 if( ssl->conf->renego_max_records >= 0 &&
Simon Cooksey 0:fb7af294d5d9 1428 ssl->renego_records_seen > ssl->conf->renego_max_records )
Simon Cooksey 0:fb7af294d5d9 1429 {
Simon Cooksey 0:fb7af294d5d9 1430 MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, "
Simon Cooksey 0:fb7af294d5d9 1431 "but not honored by server" ) );
Simon Cooksey 0:fb7af294d5d9 1432 return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
Simon Cooksey 0:fb7af294d5d9 1433 }
Simon Cooksey 0:fb7af294d5d9 1434
Simon Cooksey 0:fb7af294d5d9 1435 MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-handshake message during renego" ) );
Simon Cooksey 0:fb7af294d5d9 1436 return( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO );
Simon Cooksey 0:fb7af294d5d9 1437 }
Simon Cooksey 0:fb7af294d5d9 1438 #endif /* MBEDTLS_SSL_RENEGOTIATION */
Simon Cooksey 0:fb7af294d5d9 1439
Simon Cooksey 0:fb7af294d5d9 1440 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1441 return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
Simon Cooksey 0:fb7af294d5d9 1442 }
Simon Cooksey 0:fb7af294d5d9 1443
Simon Cooksey 0:fb7af294d5d9 1444 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 1445 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
Simon Cooksey 0:fb7af294d5d9 1446 {
Simon Cooksey 0:fb7af294d5d9 1447 if( buf[0] == MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST )
Simon Cooksey 0:fb7af294d5d9 1448 {
Simon Cooksey 0:fb7af294d5d9 1449 MBEDTLS_SSL_DEBUG_MSG( 2, ( "received hello verify request" ) );
Simon Cooksey 0:fb7af294d5d9 1450 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) );
Simon Cooksey 0:fb7af294d5d9 1451 return( ssl_parse_hello_verify_request( ssl ) );
Simon Cooksey 0:fb7af294d5d9 1452 }
Simon Cooksey 0:fb7af294d5d9 1453 else
Simon Cooksey 0:fb7af294d5d9 1454 {
Simon Cooksey 0:fb7af294d5d9 1455 /* We made it through the verification process */
Simon Cooksey 0:fb7af294d5d9 1456 mbedtls_free( ssl->handshake->verify_cookie );
Simon Cooksey 0:fb7af294d5d9 1457 ssl->handshake->verify_cookie = NULL;
Simon Cooksey 0:fb7af294d5d9 1458 ssl->handshake->verify_cookie_len = 0;
Simon Cooksey 0:fb7af294d5d9 1459 }
Simon Cooksey 0:fb7af294d5d9 1460 }
Simon Cooksey 0:fb7af294d5d9 1461 #endif /* MBEDTLS_SSL_PROTO_DTLS */
Simon Cooksey 0:fb7af294d5d9 1462
Simon Cooksey 0:fb7af294d5d9 1463 if( ssl->in_hslen < 38 + mbedtls_ssl_hs_hdr_len( ssl ) ||
Simon Cooksey 0:fb7af294d5d9 1464 buf[0] != MBEDTLS_SSL_HS_SERVER_HELLO )
Simon Cooksey 0:fb7af294d5d9 1465 {
Simon Cooksey 0:fb7af294d5d9 1466 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1467 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1468 }
Simon Cooksey 0:fb7af294d5d9 1469
Simon Cooksey 0:fb7af294d5d9 1470 /*
Simon Cooksey 0:fb7af294d5d9 1471 * 0 . 1 server_version
Simon Cooksey 0:fb7af294d5d9 1472 * 2 . 33 random (maybe including 4 bytes of Unix time)
Simon Cooksey 0:fb7af294d5d9 1473 * 34 . 34 session_id length = n
Simon Cooksey 0:fb7af294d5d9 1474 * 35 . 34+n session_id
Simon Cooksey 0:fb7af294d5d9 1475 * 35+n . 36+n cipher_suite
Simon Cooksey 0:fb7af294d5d9 1476 * 37+n . 37+n compression_method
Simon Cooksey 0:fb7af294d5d9 1477 *
Simon Cooksey 0:fb7af294d5d9 1478 * 38+n . 39+n extensions length (optional)
Simon Cooksey 0:fb7af294d5d9 1479 * 40+n . .. extensions
Simon Cooksey 0:fb7af294d5d9 1480 */
Simon Cooksey 0:fb7af294d5d9 1481 buf += mbedtls_ssl_hs_hdr_len( ssl );
Simon Cooksey 0:fb7af294d5d9 1482
Simon Cooksey 0:fb7af294d5d9 1483 MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, version", buf + 0, 2 );
Simon Cooksey 0:fb7af294d5d9 1484 mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver,
Simon Cooksey 0:fb7af294d5d9 1485 ssl->conf->transport, buf + 0 );
Simon Cooksey 0:fb7af294d5d9 1486
Simon Cooksey 0:fb7af294d5d9 1487 if( ssl->major_ver < ssl->conf->min_major_ver ||
Simon Cooksey 0:fb7af294d5d9 1488 ssl->minor_ver < ssl->conf->min_minor_ver ||
Simon Cooksey 0:fb7af294d5d9 1489 ssl->major_ver > ssl->conf->max_major_ver ||
Simon Cooksey 0:fb7af294d5d9 1490 ssl->minor_ver > ssl->conf->max_minor_ver )
Simon Cooksey 0:fb7af294d5d9 1491 {
Simon Cooksey 0:fb7af294d5d9 1492 MBEDTLS_SSL_DEBUG_MSG( 1, ( "server version out of bounds - "
Simon Cooksey 0:fb7af294d5d9 1493 " min: [%d:%d], server: [%d:%d], max: [%d:%d]",
Simon Cooksey 0:fb7af294d5d9 1494 ssl->conf->min_major_ver, ssl->conf->min_minor_ver,
Simon Cooksey 0:fb7af294d5d9 1495 ssl->major_ver, ssl->minor_ver,
Simon Cooksey 0:fb7af294d5d9 1496 ssl->conf->max_major_ver, ssl->conf->max_minor_ver ) );
Simon Cooksey 0:fb7af294d5d9 1497
Simon Cooksey 0:fb7af294d5d9 1498 mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
Simon Cooksey 0:fb7af294d5d9 1499 MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION );
Simon Cooksey 0:fb7af294d5d9 1500
Simon Cooksey 0:fb7af294d5d9 1501 return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION );
Simon Cooksey 0:fb7af294d5d9 1502 }
Simon Cooksey 0:fb7af294d5d9 1503
Simon Cooksey 0:fb7af294d5d9 1504 #if defined(MBEDTLS_DEBUG_C)
Simon Cooksey 0:fb7af294d5d9 1505 t = ( (uint32_t) buf[2] << 24 )
Simon Cooksey 0:fb7af294d5d9 1506 | ( (uint32_t) buf[3] << 16 )
Simon Cooksey 0:fb7af294d5d9 1507 | ( (uint32_t) buf[4] << 8 )
Simon Cooksey 0:fb7af294d5d9 1508 | ( (uint32_t) buf[5] );
Simon Cooksey 0:fb7af294d5d9 1509 MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) );
Simon Cooksey 0:fb7af294d5d9 1510 #endif
Simon Cooksey 0:fb7af294d5d9 1511
Simon Cooksey 0:fb7af294d5d9 1512 memcpy( ssl->handshake->randbytes + 32, buf + 2, 32 );
Simon Cooksey 0:fb7af294d5d9 1513
Simon Cooksey 0:fb7af294d5d9 1514 n = buf[34];
Simon Cooksey 0:fb7af294d5d9 1515
Simon Cooksey 0:fb7af294d5d9 1516 MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 2, 32 );
Simon Cooksey 0:fb7af294d5d9 1517
Simon Cooksey 0:fb7af294d5d9 1518 if( n > 32 )
Simon Cooksey 0:fb7af294d5d9 1519 {
Simon Cooksey 0:fb7af294d5d9 1520 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1521 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1522 }
Simon Cooksey 0:fb7af294d5d9 1523
Simon Cooksey 0:fb7af294d5d9 1524 if( ssl->in_hslen > mbedtls_ssl_hs_hdr_len( ssl ) + 39 + n )
Simon Cooksey 0:fb7af294d5d9 1525 {
Simon Cooksey 0:fb7af294d5d9 1526 ext_len = ( ( buf[38 + n] << 8 )
Simon Cooksey 0:fb7af294d5d9 1527 | ( buf[39 + n] ) );
Simon Cooksey 0:fb7af294d5d9 1528
Simon Cooksey 0:fb7af294d5d9 1529 if( ( ext_len > 0 && ext_len < 4 ) ||
Simon Cooksey 0:fb7af294d5d9 1530 ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 40 + n + ext_len )
Simon Cooksey 0:fb7af294d5d9 1531 {
Simon Cooksey 0:fb7af294d5d9 1532 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1533 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1534 }
Simon Cooksey 0:fb7af294d5d9 1535 }
Simon Cooksey 0:fb7af294d5d9 1536 else if( ssl->in_hslen == mbedtls_ssl_hs_hdr_len( ssl ) + 38 + n )
Simon Cooksey 0:fb7af294d5d9 1537 {
Simon Cooksey 0:fb7af294d5d9 1538 ext_len = 0;
Simon Cooksey 0:fb7af294d5d9 1539 }
Simon Cooksey 0:fb7af294d5d9 1540 else
Simon Cooksey 0:fb7af294d5d9 1541 {
Simon Cooksey 0:fb7af294d5d9 1542 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1543 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1544 }
Simon Cooksey 0:fb7af294d5d9 1545
Simon Cooksey 0:fb7af294d5d9 1546 /* ciphersuite (used later) */
Simon Cooksey 0:fb7af294d5d9 1547 i = ( buf[35 + n] << 8 ) | buf[36 + n];
Simon Cooksey 0:fb7af294d5d9 1548
Simon Cooksey 0:fb7af294d5d9 1549 /*
Simon Cooksey 0:fb7af294d5d9 1550 * Read and check compression
Simon Cooksey 0:fb7af294d5d9 1551 */
Simon Cooksey 0:fb7af294d5d9 1552 comp = buf[37 + n];
Simon Cooksey 0:fb7af294d5d9 1553
Simon Cooksey 0:fb7af294d5d9 1554 #if defined(MBEDTLS_ZLIB_SUPPORT)
Simon Cooksey 0:fb7af294d5d9 1555 /* See comments in ssl_write_client_hello() */
Simon Cooksey 0:fb7af294d5d9 1556 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 1557 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
Simon Cooksey 0:fb7af294d5d9 1558 accept_comp = 0;
Simon Cooksey 0:fb7af294d5d9 1559 else
Simon Cooksey 0:fb7af294d5d9 1560 #endif
Simon Cooksey 0:fb7af294d5d9 1561 accept_comp = 1;
Simon Cooksey 0:fb7af294d5d9 1562
Simon Cooksey 0:fb7af294d5d9 1563 if( comp != MBEDTLS_SSL_COMPRESS_NULL &&
Simon Cooksey 0:fb7af294d5d9 1564 ( comp != MBEDTLS_SSL_COMPRESS_DEFLATE || accept_comp == 0 ) )
Simon Cooksey 0:fb7af294d5d9 1565 #else /* MBEDTLS_ZLIB_SUPPORT */
Simon Cooksey 0:fb7af294d5d9 1566 if( comp != MBEDTLS_SSL_COMPRESS_NULL )
Simon Cooksey 0:fb7af294d5d9 1567 #endif/* MBEDTLS_ZLIB_SUPPORT */
Simon Cooksey 0:fb7af294d5d9 1568 {
Simon Cooksey 0:fb7af294d5d9 1569 MBEDTLS_SSL_DEBUG_MSG( 1, ( "server hello, bad compression: %d", comp ) );
Simon Cooksey 0:fb7af294d5d9 1570 return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
Simon Cooksey 0:fb7af294d5d9 1571 }
Simon Cooksey 0:fb7af294d5d9 1572
Simon Cooksey 0:fb7af294d5d9 1573 /*
Simon Cooksey 0:fb7af294d5d9 1574 * Initialize update checksum functions
Simon Cooksey 0:fb7af294d5d9 1575 */
Simon Cooksey 0:fb7af294d5d9 1576 ssl->transform_negotiate->ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( i );
Simon Cooksey 0:fb7af294d5d9 1577
Simon Cooksey 0:fb7af294d5d9 1578 if( ssl->transform_negotiate->ciphersuite_info == NULL )
Simon Cooksey 0:fb7af294d5d9 1579 {
Simon Cooksey 0:fb7af294d5d9 1580 MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", i ) );
Simon Cooksey 0:fb7af294d5d9 1581 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
Simon Cooksey 0:fb7af294d5d9 1582 }
Simon Cooksey 0:fb7af294d5d9 1583
Simon Cooksey 0:fb7af294d5d9 1584 mbedtls_ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info );
Simon Cooksey 0:fb7af294d5d9 1585
Simon Cooksey 0:fb7af294d5d9 1586 MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
Simon Cooksey 0:fb7af294d5d9 1587 MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 35, n );
Simon Cooksey 0:fb7af294d5d9 1588
Simon Cooksey 0:fb7af294d5d9 1589 /*
Simon Cooksey 0:fb7af294d5d9 1590 * Check if the session can be resumed
Simon Cooksey 0:fb7af294d5d9 1591 */
Simon Cooksey 0:fb7af294d5d9 1592 if( ssl->handshake->resume == 0 || n == 0 ||
Simon Cooksey 0:fb7af294d5d9 1593 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 1594 ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ||
Simon Cooksey 0:fb7af294d5d9 1595 #endif
Simon Cooksey 0:fb7af294d5d9 1596 ssl->session_negotiate->ciphersuite != i ||
Simon Cooksey 0:fb7af294d5d9 1597 ssl->session_negotiate->compression != comp ||
Simon Cooksey 0:fb7af294d5d9 1598 ssl->session_negotiate->id_len != n ||
Simon Cooksey 0:fb7af294d5d9 1599 memcmp( ssl->session_negotiate->id, buf + 35, n ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1600 {
Simon Cooksey 0:fb7af294d5d9 1601 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 1602 ssl->handshake->resume = 0;
Simon Cooksey 0:fb7af294d5d9 1603 #if defined(MBEDTLS_HAVE_TIME)
Simon Cooksey 0:fb7af294d5d9 1604 ssl->session_negotiate->start = mbedtls_time( NULL );
Simon Cooksey 0:fb7af294d5d9 1605 #endif
Simon Cooksey 0:fb7af294d5d9 1606 ssl->session_negotiate->ciphersuite = i;
Simon Cooksey 0:fb7af294d5d9 1607 ssl->session_negotiate->compression = comp;
Simon Cooksey 0:fb7af294d5d9 1608 ssl->session_negotiate->id_len = n;
Simon Cooksey 0:fb7af294d5d9 1609 memcpy( ssl->session_negotiate->id, buf + 35, n );
Simon Cooksey 0:fb7af294d5d9 1610 }
Simon Cooksey 0:fb7af294d5d9 1611 else
Simon Cooksey 0:fb7af294d5d9 1612 {
Simon Cooksey 0:fb7af294d5d9 1613 ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC;
Simon Cooksey 0:fb7af294d5d9 1614
Simon Cooksey 0:fb7af294d5d9 1615 if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1616 {
Simon Cooksey 0:fb7af294d5d9 1617 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
Simon Cooksey 0:fb7af294d5d9 1618 return( ret );
Simon Cooksey 0:fb7af294d5d9 1619 }
Simon Cooksey 0:fb7af294d5d9 1620 }
Simon Cooksey 0:fb7af294d5d9 1621
Simon Cooksey 0:fb7af294d5d9 1622 MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
Simon Cooksey 0:fb7af294d5d9 1623 ssl->handshake->resume ? "a" : "no" ) );
Simon Cooksey 0:fb7af294d5d9 1624
Simon Cooksey 0:fb7af294d5d9 1625 MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", i ) );
Simon Cooksey 0:fb7af294d5d9 1626 MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[37 + n] ) );
Simon Cooksey 0:fb7af294d5d9 1627
Simon Cooksey 0:fb7af294d5d9 1628 suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite );
Simon Cooksey 0:fb7af294d5d9 1629 if( suite_info == NULL
Simon Cooksey 0:fb7af294d5d9 1630 #if defined(MBEDTLS_ARC4_C)
Simon Cooksey 0:fb7af294d5d9 1631 || ( ssl->conf->arc4_disabled &&
Simon Cooksey 0:fb7af294d5d9 1632 suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 )
Simon Cooksey 0:fb7af294d5d9 1633 #endif
Simon Cooksey 0:fb7af294d5d9 1634 )
Simon Cooksey 0:fb7af294d5d9 1635 {
Simon Cooksey 0:fb7af294d5d9 1636 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1637 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1638 }
Simon Cooksey 0:fb7af294d5d9 1639
Simon Cooksey 0:fb7af294d5d9 1640 MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) );
Simon Cooksey 0:fb7af294d5d9 1641
Simon Cooksey 0:fb7af294d5d9 1642 i = 0;
Simon Cooksey 0:fb7af294d5d9 1643 while( 1 )
Simon Cooksey 0:fb7af294d5d9 1644 {
Simon Cooksey 0:fb7af294d5d9 1645 if( ssl->conf->ciphersuite_list[ssl->minor_ver][i] == 0 )
Simon Cooksey 0:fb7af294d5d9 1646 {
Simon Cooksey 0:fb7af294d5d9 1647 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1648 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1649 }
Simon Cooksey 0:fb7af294d5d9 1650
Simon Cooksey 0:fb7af294d5d9 1651 if( ssl->conf->ciphersuite_list[ssl->minor_ver][i++] ==
Simon Cooksey 0:fb7af294d5d9 1652 ssl->session_negotiate->ciphersuite )
Simon Cooksey 0:fb7af294d5d9 1653 {
Simon Cooksey 0:fb7af294d5d9 1654 break;
Simon Cooksey 0:fb7af294d5d9 1655 }
Simon Cooksey 0:fb7af294d5d9 1656 }
Simon Cooksey 0:fb7af294d5d9 1657
Simon Cooksey 0:fb7af294d5d9 1658 if( comp != MBEDTLS_SSL_COMPRESS_NULL
Simon Cooksey 0:fb7af294d5d9 1659 #if defined(MBEDTLS_ZLIB_SUPPORT)
Simon Cooksey 0:fb7af294d5d9 1660 && comp != MBEDTLS_SSL_COMPRESS_DEFLATE
Simon Cooksey 0:fb7af294d5d9 1661 #endif
Simon Cooksey 0:fb7af294d5d9 1662 )
Simon Cooksey 0:fb7af294d5d9 1663 {
Simon Cooksey 0:fb7af294d5d9 1664 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1665 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1666 }
Simon Cooksey 0:fb7af294d5d9 1667 ssl->session_negotiate->compression = comp;
Simon Cooksey 0:fb7af294d5d9 1668
Simon Cooksey 0:fb7af294d5d9 1669 ext = buf + 40 + n;
Simon Cooksey 0:fb7af294d5d9 1670
Simon Cooksey 0:fb7af294d5d9 1671 MBEDTLS_SSL_DEBUG_MSG( 2, ( "server hello, total extension length: %d", ext_len ) );
Simon Cooksey 0:fb7af294d5d9 1672
Simon Cooksey 0:fb7af294d5d9 1673 while( ext_len )
Simon Cooksey 0:fb7af294d5d9 1674 {
Simon Cooksey 0:fb7af294d5d9 1675 unsigned int ext_id = ( ( ext[0] << 8 )
Simon Cooksey 0:fb7af294d5d9 1676 | ( ext[1] ) );
Simon Cooksey 0:fb7af294d5d9 1677 unsigned int ext_size = ( ( ext[2] << 8 )
Simon Cooksey 0:fb7af294d5d9 1678 | ( ext[3] ) );
Simon Cooksey 0:fb7af294d5d9 1679
Simon Cooksey 0:fb7af294d5d9 1680 if( ext_size + 4 > ext_len )
Simon Cooksey 0:fb7af294d5d9 1681 {
Simon Cooksey 0:fb7af294d5d9 1682 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1683 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1684 }
Simon Cooksey 0:fb7af294d5d9 1685
Simon Cooksey 0:fb7af294d5d9 1686 switch( ext_id )
Simon Cooksey 0:fb7af294d5d9 1687 {
Simon Cooksey 0:fb7af294d5d9 1688 case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO:
Simon Cooksey 0:fb7af294d5d9 1689 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) );
Simon Cooksey 0:fb7af294d5d9 1690 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 1691 renegotiation_info_seen = 1;
Simon Cooksey 0:fb7af294d5d9 1692 #endif
Simon Cooksey 0:fb7af294d5d9 1693
Simon Cooksey 0:fb7af294d5d9 1694 if( ( ret = ssl_parse_renegotiation_info( ssl, ext + 4,
Simon Cooksey 0:fb7af294d5d9 1695 ext_size ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1696 return( ret );
Simon Cooksey 0:fb7af294d5d9 1697
Simon Cooksey 0:fb7af294d5d9 1698 break;
Simon Cooksey 0:fb7af294d5d9 1699
Simon Cooksey 0:fb7af294d5d9 1700 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
Simon Cooksey 0:fb7af294d5d9 1701 case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH:
Simon Cooksey 0:fb7af294d5d9 1702 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max_fragment_length extension" ) );
Simon Cooksey 0:fb7af294d5d9 1703
Simon Cooksey 0:fb7af294d5d9 1704 if( ( ret = ssl_parse_max_fragment_length_ext( ssl,
Simon Cooksey 0:fb7af294d5d9 1705 ext + 4, ext_size ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1706 {
Simon Cooksey 0:fb7af294d5d9 1707 return( ret );
Simon Cooksey 0:fb7af294d5d9 1708 }
Simon Cooksey 0:fb7af294d5d9 1709
Simon Cooksey 0:fb7af294d5d9 1710 break;
Simon Cooksey 0:fb7af294d5d9 1711 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
Simon Cooksey 0:fb7af294d5d9 1712
Simon Cooksey 0:fb7af294d5d9 1713 #if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
Simon Cooksey 0:fb7af294d5d9 1714 case MBEDTLS_TLS_EXT_TRUNCATED_HMAC:
Simon Cooksey 0:fb7af294d5d9 1715 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated_hmac extension" ) );
Simon Cooksey 0:fb7af294d5d9 1716
Simon Cooksey 0:fb7af294d5d9 1717 if( ( ret = ssl_parse_truncated_hmac_ext( ssl,
Simon Cooksey 0:fb7af294d5d9 1718 ext + 4, ext_size ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1719 {
Simon Cooksey 0:fb7af294d5d9 1720 return( ret );
Simon Cooksey 0:fb7af294d5d9 1721 }
Simon Cooksey 0:fb7af294d5d9 1722
Simon Cooksey 0:fb7af294d5d9 1723 break;
Simon Cooksey 0:fb7af294d5d9 1724 #endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
Simon Cooksey 0:fb7af294d5d9 1725
Simon Cooksey 0:fb7af294d5d9 1726 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
Simon Cooksey 0:fb7af294d5d9 1727 case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC:
Simon Cooksey 0:fb7af294d5d9 1728 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt_then_mac extension" ) );
Simon Cooksey 0:fb7af294d5d9 1729
Simon Cooksey 0:fb7af294d5d9 1730 if( ( ret = ssl_parse_encrypt_then_mac_ext( ssl,
Simon Cooksey 0:fb7af294d5d9 1731 ext + 4, ext_size ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1732 {
Simon Cooksey 0:fb7af294d5d9 1733 return( ret );
Simon Cooksey 0:fb7af294d5d9 1734 }
Simon Cooksey 0:fb7af294d5d9 1735
Simon Cooksey 0:fb7af294d5d9 1736 break;
Simon Cooksey 0:fb7af294d5d9 1737 #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
Simon Cooksey 0:fb7af294d5d9 1738
Simon Cooksey 0:fb7af294d5d9 1739 #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
Simon Cooksey 0:fb7af294d5d9 1740 case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET:
Simon Cooksey 0:fb7af294d5d9 1741 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended_master_secret extension" ) );
Simon Cooksey 0:fb7af294d5d9 1742
Simon Cooksey 0:fb7af294d5d9 1743 if( ( ret = ssl_parse_extended_ms_ext( ssl,
Simon Cooksey 0:fb7af294d5d9 1744 ext + 4, ext_size ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1745 {
Simon Cooksey 0:fb7af294d5d9 1746 return( ret );
Simon Cooksey 0:fb7af294d5d9 1747 }
Simon Cooksey 0:fb7af294d5d9 1748
Simon Cooksey 0:fb7af294d5d9 1749 break;
Simon Cooksey 0:fb7af294d5d9 1750 #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
Simon Cooksey 0:fb7af294d5d9 1751
Simon Cooksey 0:fb7af294d5d9 1752 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
Simon Cooksey 0:fb7af294d5d9 1753 case MBEDTLS_TLS_EXT_SESSION_TICKET:
Simon Cooksey 0:fb7af294d5d9 1754 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session_ticket extension" ) );
Simon Cooksey 0:fb7af294d5d9 1755
Simon Cooksey 0:fb7af294d5d9 1756 if( ( ret = ssl_parse_session_ticket_ext( ssl,
Simon Cooksey 0:fb7af294d5d9 1757 ext + 4, ext_size ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1758 {
Simon Cooksey 0:fb7af294d5d9 1759 return( ret );
Simon Cooksey 0:fb7af294d5d9 1760 }
Simon Cooksey 0:fb7af294d5d9 1761
Simon Cooksey 0:fb7af294d5d9 1762 break;
Simon Cooksey 0:fb7af294d5d9 1763 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
Simon Cooksey 0:fb7af294d5d9 1764
Simon Cooksey 0:fb7af294d5d9 1765 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
Simon Cooksey 0:fb7af294d5d9 1766 defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 1767 case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS:
Simon Cooksey 0:fb7af294d5d9 1768 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported_point_formats extension" ) );
Simon Cooksey 0:fb7af294d5d9 1769
Simon Cooksey 0:fb7af294d5d9 1770 if( ( ret = ssl_parse_supported_point_formats_ext( ssl,
Simon Cooksey 0:fb7af294d5d9 1771 ext + 4, ext_size ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1772 {
Simon Cooksey 0:fb7af294d5d9 1773 return( ret );
Simon Cooksey 0:fb7af294d5d9 1774 }
Simon Cooksey 0:fb7af294d5d9 1775
Simon Cooksey 0:fb7af294d5d9 1776 break;
Simon Cooksey 0:fb7af294d5d9 1777 #endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
Simon Cooksey 0:fb7af294d5d9 1778 MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
Simon Cooksey 0:fb7af294d5d9 1779
Simon Cooksey 0:fb7af294d5d9 1780 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 1781 case MBEDTLS_TLS_EXT_ECJPAKE_KKPP:
Simon Cooksey 0:fb7af294d5d9 1782 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake_kkpp extension" ) );
Simon Cooksey 0:fb7af294d5d9 1783
Simon Cooksey 0:fb7af294d5d9 1784 if( ( ret = ssl_parse_ecjpake_kkpp( ssl,
Simon Cooksey 0:fb7af294d5d9 1785 ext + 4, ext_size ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1786 {
Simon Cooksey 0:fb7af294d5d9 1787 return( ret );
Simon Cooksey 0:fb7af294d5d9 1788 }
Simon Cooksey 0:fb7af294d5d9 1789
Simon Cooksey 0:fb7af294d5d9 1790 break;
Simon Cooksey 0:fb7af294d5d9 1791 #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
Simon Cooksey 0:fb7af294d5d9 1792
Simon Cooksey 0:fb7af294d5d9 1793 #if defined(MBEDTLS_SSL_ALPN)
Simon Cooksey 0:fb7af294d5d9 1794 case MBEDTLS_TLS_EXT_ALPN:
Simon Cooksey 0:fb7af294d5d9 1795 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) );
Simon Cooksey 0:fb7af294d5d9 1796
Simon Cooksey 0:fb7af294d5d9 1797 if( ( ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1798 return( ret );
Simon Cooksey 0:fb7af294d5d9 1799
Simon Cooksey 0:fb7af294d5d9 1800 break;
Simon Cooksey 0:fb7af294d5d9 1801 #endif /* MBEDTLS_SSL_ALPN */
Simon Cooksey 0:fb7af294d5d9 1802
Simon Cooksey 0:fb7af294d5d9 1803 default:
Simon Cooksey 0:fb7af294d5d9 1804 MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)",
Simon Cooksey 0:fb7af294d5d9 1805 ext_id ) );
Simon Cooksey 0:fb7af294d5d9 1806 }
Simon Cooksey 0:fb7af294d5d9 1807
Simon Cooksey 0:fb7af294d5d9 1808 ext_len -= 4 + ext_size;
Simon Cooksey 0:fb7af294d5d9 1809 ext += 4 + ext_size;
Simon Cooksey 0:fb7af294d5d9 1810
Simon Cooksey 0:fb7af294d5d9 1811 if( ext_len > 0 && ext_len < 4 )
Simon Cooksey 0:fb7af294d5d9 1812 {
Simon Cooksey 0:fb7af294d5d9 1813 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
Simon Cooksey 0:fb7af294d5d9 1814 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1815 }
Simon Cooksey 0:fb7af294d5d9 1816 }
Simon Cooksey 0:fb7af294d5d9 1817
Simon Cooksey 0:fb7af294d5d9 1818 /*
Simon Cooksey 0:fb7af294d5d9 1819 * Renegotiation security checks
Simon Cooksey 0:fb7af294d5d9 1820 */
Simon Cooksey 0:fb7af294d5d9 1821 if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
Simon Cooksey 0:fb7af294d5d9 1822 ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE )
Simon Cooksey 0:fb7af294d5d9 1823 {
Simon Cooksey 0:fb7af294d5d9 1824 MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
Simon Cooksey 0:fb7af294d5d9 1825 handshake_failure = 1;
Simon Cooksey 0:fb7af294d5d9 1826 }
Simon Cooksey 0:fb7af294d5d9 1827 #if defined(MBEDTLS_SSL_RENEGOTIATION)
Simon Cooksey 0:fb7af294d5d9 1828 else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
Simon Cooksey 0:fb7af294d5d9 1829 ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION &&
Simon Cooksey 0:fb7af294d5d9 1830 renegotiation_info_seen == 0 )
Simon Cooksey 0:fb7af294d5d9 1831 {
Simon Cooksey 0:fb7af294d5d9 1832 MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) );
Simon Cooksey 0:fb7af294d5d9 1833 handshake_failure = 1;
Simon Cooksey 0:fb7af294d5d9 1834 }
Simon Cooksey 0:fb7af294d5d9 1835 else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
Simon Cooksey 0:fb7af294d5d9 1836 ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
Simon Cooksey 0:fb7af294d5d9 1837 ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION )
Simon Cooksey 0:fb7af294d5d9 1838 {
Simon Cooksey 0:fb7af294d5d9 1839 MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) );
Simon Cooksey 0:fb7af294d5d9 1840 handshake_failure = 1;
Simon Cooksey 0:fb7af294d5d9 1841 }
Simon Cooksey 0:fb7af294d5d9 1842 else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
Simon Cooksey 0:fb7af294d5d9 1843 ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
Simon Cooksey 0:fb7af294d5d9 1844 renegotiation_info_seen == 1 )
Simon Cooksey 0:fb7af294d5d9 1845 {
Simon Cooksey 0:fb7af294d5d9 1846 MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) );
Simon Cooksey 0:fb7af294d5d9 1847 handshake_failure = 1;
Simon Cooksey 0:fb7af294d5d9 1848 }
Simon Cooksey 0:fb7af294d5d9 1849 #endif /* MBEDTLS_SSL_RENEGOTIATION */
Simon Cooksey 0:fb7af294d5d9 1850
Simon Cooksey 0:fb7af294d5d9 1851 if( handshake_failure == 1 )
Simon Cooksey 0:fb7af294d5d9 1852 {
Simon Cooksey 0:fb7af294d5d9 1853 if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1854 return( ret );
Simon Cooksey 0:fb7af294d5d9 1855
Simon Cooksey 0:fb7af294d5d9 1856 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
Simon Cooksey 0:fb7af294d5d9 1857 }
Simon Cooksey 0:fb7af294d5d9 1858
Simon Cooksey 0:fb7af294d5d9 1859 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) );
Simon Cooksey 0:fb7af294d5d9 1860
Simon Cooksey 0:fb7af294d5d9 1861 return( 0 );
Simon Cooksey 0:fb7af294d5d9 1862 }
Simon Cooksey 0:fb7af294d5d9 1863
Simon Cooksey 0:fb7af294d5d9 1864 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 1865 defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 1866 static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, unsigned char **p,
Simon Cooksey 0:fb7af294d5d9 1867 unsigned char *end )
Simon Cooksey 0:fb7af294d5d9 1868 {
Simon Cooksey 0:fb7af294d5d9 1869 int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
Simon Cooksey 0:fb7af294d5d9 1870
Simon Cooksey 0:fb7af294d5d9 1871 /*
Simon Cooksey 0:fb7af294d5d9 1872 * Ephemeral DH parameters:
Simon Cooksey 0:fb7af294d5d9 1873 *
Simon Cooksey 0:fb7af294d5d9 1874 * struct {
Simon Cooksey 0:fb7af294d5d9 1875 * opaque dh_p<1..2^16-1>;
Simon Cooksey 0:fb7af294d5d9 1876 * opaque dh_g<1..2^16-1>;
Simon Cooksey 0:fb7af294d5d9 1877 * opaque dh_Ys<1..2^16-1>;
Simon Cooksey 0:fb7af294d5d9 1878 * } ServerDHParams;
Simon Cooksey 0:fb7af294d5d9 1879 */
Simon Cooksey 0:fb7af294d5d9 1880 if( ( ret = mbedtls_dhm_read_params( &ssl->handshake->dhm_ctx, p, end ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1881 {
Simon Cooksey 0:fb7af294d5d9 1882 MBEDTLS_SSL_DEBUG_RET( 2, ( "mbedtls_dhm_read_params" ), ret );
Simon Cooksey 0:fb7af294d5d9 1883 return( ret );
Simon Cooksey 0:fb7af294d5d9 1884 }
Simon Cooksey 0:fb7af294d5d9 1885
Simon Cooksey 0:fb7af294d5d9 1886 if( ssl->handshake->dhm_ctx.len * 8 < ssl->conf->dhm_min_bitlen )
Simon Cooksey 0:fb7af294d5d9 1887 {
Simon Cooksey 0:fb7af294d5d9 1888 MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHM prime too short: %d < %d",
Simon Cooksey 0:fb7af294d5d9 1889 ssl->handshake->dhm_ctx.len * 8,
Simon Cooksey 0:fb7af294d5d9 1890 ssl->conf->dhm_min_bitlen ) );
Simon Cooksey 0:fb7af294d5d9 1891 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 1892 }
Simon Cooksey 0:fb7af294d5d9 1893
Simon Cooksey 0:fb7af294d5d9 1894 MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P );
Simon Cooksey 0:fb7af294d5d9 1895 MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G );
Simon Cooksey 0:fb7af294d5d9 1896 MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY );
Simon Cooksey 0:fb7af294d5d9 1897
Simon Cooksey 0:fb7af294d5d9 1898 return( ret );
Simon Cooksey 0:fb7af294d5d9 1899 }
Simon Cooksey 0:fb7af294d5d9 1900 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 1901 MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
Simon Cooksey 0:fb7af294d5d9 1902
Simon Cooksey 0:fb7af294d5d9 1903 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 1904 defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 1905 defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 1906 defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 1907 defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 1908 static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 1909 {
Simon Cooksey 0:fb7af294d5d9 1910 const mbedtls_ecp_curve_info *curve_info;
Simon Cooksey 0:fb7af294d5d9 1911
Simon Cooksey 0:fb7af294d5d9 1912 curve_info = mbedtls_ecp_curve_info_from_grp_id( ssl->handshake->ecdh_ctx.grp.id );
Simon Cooksey 0:fb7af294d5d9 1913 if( curve_info == NULL )
Simon Cooksey 0:fb7af294d5d9 1914 {
Simon Cooksey 0:fb7af294d5d9 1915 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
Simon Cooksey 0:fb7af294d5d9 1916 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
Simon Cooksey 0:fb7af294d5d9 1917 }
Simon Cooksey 0:fb7af294d5d9 1918
Simon Cooksey 0:fb7af294d5d9 1919 MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) );
Simon Cooksey 0:fb7af294d5d9 1920
Simon Cooksey 0:fb7af294d5d9 1921 #if defined(MBEDTLS_ECP_C)
Simon Cooksey 0:fb7af294d5d9 1922 if( mbedtls_ssl_check_curve( ssl, ssl->handshake->ecdh_ctx.grp.id ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1923 #else
Simon Cooksey 0:fb7af294d5d9 1924 if( ssl->handshake->ecdh_ctx.grp.nbits < 163 ||
Simon Cooksey 0:fb7af294d5d9 1925 ssl->handshake->ecdh_ctx.grp.nbits > 521 )
Simon Cooksey 0:fb7af294d5d9 1926 #endif
Simon Cooksey 0:fb7af294d5d9 1927 return( -1 );
Simon Cooksey 0:fb7af294d5d9 1928
Simon Cooksey 0:fb7af294d5d9 1929 MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp", &ssl->handshake->ecdh_ctx.Qp );
Simon Cooksey 0:fb7af294d5d9 1930
Simon Cooksey 0:fb7af294d5d9 1931 return( 0 );
Simon Cooksey 0:fb7af294d5d9 1932 }
Simon Cooksey 0:fb7af294d5d9 1933 #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 1934 MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 1935 MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 1936 MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 1937 MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
Simon Cooksey 0:fb7af294d5d9 1938
Simon Cooksey 0:fb7af294d5d9 1939 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 1940 defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 1941 defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 1942 static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 1943 unsigned char **p,
Simon Cooksey 0:fb7af294d5d9 1944 unsigned char *end )
Simon Cooksey 0:fb7af294d5d9 1945 {
Simon Cooksey 0:fb7af294d5d9 1946 int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
Simon Cooksey 0:fb7af294d5d9 1947
Simon Cooksey 0:fb7af294d5d9 1948 /*
Simon Cooksey 0:fb7af294d5d9 1949 * Ephemeral ECDH parameters:
Simon Cooksey 0:fb7af294d5d9 1950 *
Simon Cooksey 0:fb7af294d5d9 1951 * struct {
Simon Cooksey 0:fb7af294d5d9 1952 * ECParameters curve_params;
Simon Cooksey 0:fb7af294d5d9 1953 * ECPoint public;
Simon Cooksey 0:fb7af294d5d9 1954 * } ServerECDHParams;
Simon Cooksey 0:fb7af294d5d9 1955 */
Simon Cooksey 0:fb7af294d5d9 1956 if( ( ret = mbedtls_ecdh_read_params( &ssl->handshake->ecdh_ctx,
Simon Cooksey 0:fb7af294d5d9 1957 (const unsigned char **) p, end ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1958 {
Simon Cooksey 0:fb7af294d5d9 1959 MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret );
Simon Cooksey 0:fb7af294d5d9 1960 return( ret );
Simon Cooksey 0:fb7af294d5d9 1961 }
Simon Cooksey 0:fb7af294d5d9 1962
Simon Cooksey 0:fb7af294d5d9 1963 if( ssl_check_server_ecdh_params( ssl ) != 0 )
Simon Cooksey 0:fb7af294d5d9 1964 {
Simon Cooksey 0:fb7af294d5d9 1965 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message (ECDHE curve)" ) );
Simon Cooksey 0:fb7af294d5d9 1966 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 1967 }
Simon Cooksey 0:fb7af294d5d9 1968
Simon Cooksey 0:fb7af294d5d9 1969 return( ret );
Simon Cooksey 0:fb7af294d5d9 1970 }
Simon Cooksey 0:fb7af294d5d9 1971 #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 1972 MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 1973 MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
Simon Cooksey 0:fb7af294d5d9 1974
Simon Cooksey 0:fb7af294d5d9 1975 #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 1976 static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 1977 unsigned char **p,
Simon Cooksey 0:fb7af294d5d9 1978 unsigned char *end )
Simon Cooksey 0:fb7af294d5d9 1979 {
Simon Cooksey 0:fb7af294d5d9 1980 int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
Simon Cooksey 0:fb7af294d5d9 1981 size_t len;
Simon Cooksey 0:fb7af294d5d9 1982 ((void) ssl);
Simon Cooksey 0:fb7af294d5d9 1983
Simon Cooksey 0:fb7af294d5d9 1984 /*
Simon Cooksey 0:fb7af294d5d9 1985 * PSK parameters:
Simon Cooksey 0:fb7af294d5d9 1986 *
Simon Cooksey 0:fb7af294d5d9 1987 * opaque psk_identity_hint<0..2^16-1>;
Simon Cooksey 0:fb7af294d5d9 1988 */
Simon Cooksey 0:fb7af294d5d9 1989 len = (*p)[0] << 8 | (*p)[1];
Simon Cooksey 0:fb7af294d5d9 1990 *p += 2;
Simon Cooksey 0:fb7af294d5d9 1991
Simon Cooksey 0:fb7af294d5d9 1992 if( (*p) + len > end )
Simon Cooksey 0:fb7af294d5d9 1993 {
Simon Cooksey 0:fb7af294d5d9 1994 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message (psk_identity_hint length)" ) );
Simon Cooksey 0:fb7af294d5d9 1995 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 1996 }
Simon Cooksey 0:fb7af294d5d9 1997
Simon Cooksey 0:fb7af294d5d9 1998 /*
Simon Cooksey 0:fb7af294d5d9 1999 * Note: we currently ignore the PKS identity hint, as we only allow one
Simon Cooksey 0:fb7af294d5d9 2000 * PSK to be provisionned on the client. This could be changed later if
Simon Cooksey 0:fb7af294d5d9 2001 * someone needs that feature.
Simon Cooksey 0:fb7af294d5d9 2002 */
Simon Cooksey 0:fb7af294d5d9 2003 *p += len;
Simon Cooksey 0:fb7af294d5d9 2004 ret = 0;
Simon Cooksey 0:fb7af294d5d9 2005
Simon Cooksey 0:fb7af294d5d9 2006 return( ret );
Simon Cooksey 0:fb7af294d5d9 2007 }
Simon Cooksey 0:fb7af294d5d9 2008 #endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2009
Simon Cooksey 0:fb7af294d5d9 2010 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2011 defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2012 /*
Simon Cooksey 0:fb7af294d5d9 2013 * Generate a pre-master secret and encrypt it with the server's RSA key
Simon Cooksey 0:fb7af294d5d9 2014 */
Simon Cooksey 0:fb7af294d5d9 2015 static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 2016 size_t offset, size_t *olen,
Simon Cooksey 0:fb7af294d5d9 2017 size_t pms_offset )
Simon Cooksey 0:fb7af294d5d9 2018 {
Simon Cooksey 0:fb7af294d5d9 2019 int ret;
Simon Cooksey 0:fb7af294d5d9 2020 size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2;
Simon Cooksey 0:fb7af294d5d9 2021 unsigned char *p = ssl->handshake->premaster + pms_offset;
Simon Cooksey 0:fb7af294d5d9 2022
Simon Cooksey 0:fb7af294d5d9 2023 if( offset + len_bytes > MBEDTLS_SSL_MAX_CONTENT_LEN )
Simon Cooksey 0:fb7af294d5d9 2024 {
Simon Cooksey 0:fb7af294d5d9 2025 MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small for encrypted pms" ) );
Simon Cooksey 0:fb7af294d5d9 2026 return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
Simon Cooksey 0:fb7af294d5d9 2027 }
Simon Cooksey 0:fb7af294d5d9 2028
Simon Cooksey 0:fb7af294d5d9 2029 /*
Simon Cooksey 0:fb7af294d5d9 2030 * Generate (part of) the pre-master as
Simon Cooksey 0:fb7af294d5d9 2031 * struct {
Simon Cooksey 0:fb7af294d5d9 2032 * ProtocolVersion client_version;
Simon Cooksey 0:fb7af294d5d9 2033 * opaque random[46];
Simon Cooksey 0:fb7af294d5d9 2034 * } PreMasterSecret;
Simon Cooksey 0:fb7af294d5d9 2035 */
Simon Cooksey 0:fb7af294d5d9 2036 mbedtls_ssl_write_version( ssl->conf->max_major_ver, ssl->conf->max_minor_ver,
Simon Cooksey 0:fb7af294d5d9 2037 ssl->conf->transport, p );
Simon Cooksey 0:fb7af294d5d9 2038
Simon Cooksey 0:fb7af294d5d9 2039 if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p + 2, 46 ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2040 {
Simon Cooksey 0:fb7af294d5d9 2041 MBEDTLS_SSL_DEBUG_RET( 1, "f_rng", ret );
Simon Cooksey 0:fb7af294d5d9 2042 return( ret );
Simon Cooksey 0:fb7af294d5d9 2043 }
Simon Cooksey 0:fb7af294d5d9 2044
Simon Cooksey 0:fb7af294d5d9 2045 ssl->handshake->pmslen = 48;
Simon Cooksey 0:fb7af294d5d9 2046
Simon Cooksey 0:fb7af294d5d9 2047 if( ssl->session_negotiate->peer_cert == NULL )
Simon Cooksey 0:fb7af294d5d9 2048 {
Simon Cooksey 0:fb7af294d5d9 2049 MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) );
Simon Cooksey 0:fb7af294d5d9 2050 return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
Simon Cooksey 0:fb7af294d5d9 2051 }
Simon Cooksey 0:fb7af294d5d9 2052
Simon Cooksey 0:fb7af294d5d9 2053 /*
Simon Cooksey 0:fb7af294d5d9 2054 * Now write it out, encrypted
Simon Cooksey 0:fb7af294d5d9 2055 */
Simon Cooksey 0:fb7af294d5d9 2056 if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk,
Simon Cooksey 0:fb7af294d5d9 2057 MBEDTLS_PK_RSA ) )
Simon Cooksey 0:fb7af294d5d9 2058 {
Simon Cooksey 0:fb7af294d5d9 2059 MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate key type mismatch" ) );
Simon Cooksey 0:fb7af294d5d9 2060 return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
Simon Cooksey 0:fb7af294d5d9 2061 }
Simon Cooksey 0:fb7af294d5d9 2062
Simon Cooksey 0:fb7af294d5d9 2063 if( ( ret = mbedtls_pk_encrypt( &ssl->session_negotiate->peer_cert->pk,
Simon Cooksey 0:fb7af294d5d9 2064 p, ssl->handshake->pmslen,
Simon Cooksey 0:fb7af294d5d9 2065 ssl->out_msg + offset + len_bytes, olen,
Simon Cooksey 0:fb7af294d5d9 2066 MBEDTLS_SSL_MAX_CONTENT_LEN - offset - len_bytes,
Simon Cooksey 0:fb7af294d5d9 2067 ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2068 {
Simon Cooksey 0:fb7af294d5d9 2069 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret );
Simon Cooksey 0:fb7af294d5d9 2070 return( ret );
Simon Cooksey 0:fb7af294d5d9 2071 }
Simon Cooksey 0:fb7af294d5d9 2072
Simon Cooksey 0:fb7af294d5d9 2073 #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
Simon Cooksey 0:fb7af294d5d9 2074 defined(MBEDTLS_SSL_PROTO_TLS1_2)
Simon Cooksey 0:fb7af294d5d9 2075 if( len_bytes == 2 )
Simon Cooksey 0:fb7af294d5d9 2076 {
Simon Cooksey 0:fb7af294d5d9 2077 ssl->out_msg[offset+0] = (unsigned char)( *olen >> 8 );
Simon Cooksey 0:fb7af294d5d9 2078 ssl->out_msg[offset+1] = (unsigned char)( *olen );
Simon Cooksey 0:fb7af294d5d9 2079 *olen += 2;
Simon Cooksey 0:fb7af294d5d9 2080 }
Simon Cooksey 0:fb7af294d5d9 2081 #endif
Simon Cooksey 0:fb7af294d5d9 2082
Simon Cooksey 0:fb7af294d5d9 2083 return( 0 );
Simon Cooksey 0:fb7af294d5d9 2084 }
Simon Cooksey 0:fb7af294d5d9 2085 #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 2086 MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2087
Simon Cooksey 0:fb7af294d5d9 2088 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
Simon Cooksey 0:fb7af294d5d9 2089 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2090 defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2091 defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2092 static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl,
Simon Cooksey 0:fb7af294d5d9 2093 unsigned char **p,
Simon Cooksey 0:fb7af294d5d9 2094 unsigned char *end,
Simon Cooksey 0:fb7af294d5d9 2095 mbedtls_md_type_t *md_alg,
Simon Cooksey 0:fb7af294d5d9 2096 mbedtls_pk_type_t *pk_alg )
Simon Cooksey 0:fb7af294d5d9 2097 {
Simon Cooksey 0:fb7af294d5d9 2098 ((void) ssl);
Simon Cooksey 0:fb7af294d5d9 2099 *md_alg = MBEDTLS_MD_NONE;
Simon Cooksey 0:fb7af294d5d9 2100 *pk_alg = MBEDTLS_PK_NONE;
Simon Cooksey 0:fb7af294d5d9 2101
Simon Cooksey 0:fb7af294d5d9 2102 /* Only in TLS 1.2 */
Simon Cooksey 0:fb7af294d5d9 2103 if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 )
Simon Cooksey 0:fb7af294d5d9 2104 {
Simon Cooksey 0:fb7af294d5d9 2105 return( 0 );
Simon Cooksey 0:fb7af294d5d9 2106 }
Simon Cooksey 0:fb7af294d5d9 2107
Simon Cooksey 0:fb7af294d5d9 2108 if( (*p) + 2 > end )
Simon Cooksey 0:fb7af294d5d9 2109 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 2110
Simon Cooksey 0:fb7af294d5d9 2111 /*
Simon Cooksey 0:fb7af294d5d9 2112 * Get hash algorithm
Simon Cooksey 0:fb7af294d5d9 2113 */
Simon Cooksey 0:fb7af294d5d9 2114 if( ( *md_alg = mbedtls_ssl_md_alg_from_hash( (*p)[0] ) ) == MBEDTLS_MD_NONE )
Simon Cooksey 0:fb7af294d5d9 2115 {
Simon Cooksey 0:fb7af294d5d9 2116 MBEDTLS_SSL_DEBUG_MSG( 1, ( "Server used unsupported "
Simon Cooksey 0:fb7af294d5d9 2117 "HashAlgorithm %d", *(p)[0] ) );
Simon Cooksey 0:fb7af294d5d9 2118 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 2119 }
Simon Cooksey 0:fb7af294d5d9 2120
Simon Cooksey 0:fb7af294d5d9 2121 /*
Simon Cooksey 0:fb7af294d5d9 2122 * Get signature algorithm
Simon Cooksey 0:fb7af294d5d9 2123 */
Simon Cooksey 0:fb7af294d5d9 2124 if( ( *pk_alg = mbedtls_ssl_pk_alg_from_sig( (*p)[1] ) ) == MBEDTLS_PK_NONE )
Simon Cooksey 0:fb7af294d5d9 2125 {
Simon Cooksey 0:fb7af294d5d9 2126 MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used unsupported "
Simon Cooksey 0:fb7af294d5d9 2127 "SignatureAlgorithm %d", (*p)[1] ) );
Simon Cooksey 0:fb7af294d5d9 2128 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 2129 }
Simon Cooksey 0:fb7af294d5d9 2130
Simon Cooksey 0:fb7af294d5d9 2131 /*
Simon Cooksey 0:fb7af294d5d9 2132 * Check if the hash is acceptable
Simon Cooksey 0:fb7af294d5d9 2133 */
Simon Cooksey 0:fb7af294d5d9 2134 if( mbedtls_ssl_check_sig_hash( ssl, *md_alg ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2135 {
Simon Cooksey 0:fb7af294d5d9 2136 MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used HashAlgorithm "
Simon Cooksey 0:fb7af294d5d9 2137 "that was not offered" ) );
Simon Cooksey 0:fb7af294d5d9 2138 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 2139 }
Simon Cooksey 0:fb7af294d5d9 2140
Simon Cooksey 0:fb7af294d5d9 2141 MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", (*p)[1] ) );
Simon Cooksey 0:fb7af294d5d9 2142 MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", (*p)[0] ) );
Simon Cooksey 0:fb7af294d5d9 2143 *p += 2;
Simon Cooksey 0:fb7af294d5d9 2144
Simon Cooksey 0:fb7af294d5d9 2145 return( 0 );
Simon Cooksey 0:fb7af294d5d9 2146 }
Simon Cooksey 0:fb7af294d5d9 2147 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 2148 MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 2149 MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2150 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
Simon Cooksey 0:fb7af294d5d9 2151
Simon Cooksey 0:fb7af294d5d9 2152 #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2153 defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2154 static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 2155 {
Simon Cooksey 0:fb7af294d5d9 2156 int ret;
Simon Cooksey 0:fb7af294d5d9 2157 const mbedtls_ecp_keypair *peer_key;
Simon Cooksey 0:fb7af294d5d9 2158
Simon Cooksey 0:fb7af294d5d9 2159 if( ssl->session_negotiate->peer_cert == NULL )
Simon Cooksey 0:fb7af294d5d9 2160 {
Simon Cooksey 0:fb7af294d5d9 2161 MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) );
Simon Cooksey 0:fb7af294d5d9 2162 return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
Simon Cooksey 0:fb7af294d5d9 2163 }
Simon Cooksey 0:fb7af294d5d9 2164
Simon Cooksey 0:fb7af294d5d9 2165 if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk,
Simon Cooksey 0:fb7af294d5d9 2166 MBEDTLS_PK_ECKEY ) )
Simon Cooksey 0:fb7af294d5d9 2167 {
Simon Cooksey 0:fb7af294d5d9 2168 MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) );
Simon Cooksey 0:fb7af294d5d9 2169 return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
Simon Cooksey 0:fb7af294d5d9 2170 }
Simon Cooksey 0:fb7af294d5d9 2171
Simon Cooksey 0:fb7af294d5d9 2172 peer_key = mbedtls_pk_ec( ssl->session_negotiate->peer_cert->pk );
Simon Cooksey 0:fb7af294d5d9 2173
Simon Cooksey 0:fb7af294d5d9 2174 if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, peer_key,
Simon Cooksey 0:fb7af294d5d9 2175 MBEDTLS_ECDH_THEIRS ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2176 {
Simon Cooksey 0:fb7af294d5d9 2177 MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret );
Simon Cooksey 0:fb7af294d5d9 2178 return( ret );
Simon Cooksey 0:fb7af294d5d9 2179 }
Simon Cooksey 0:fb7af294d5d9 2180
Simon Cooksey 0:fb7af294d5d9 2181 if( ssl_check_server_ecdh_params( ssl ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2182 {
Simon Cooksey 0:fb7af294d5d9 2183 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server certificate (ECDH curve)" ) );
Simon Cooksey 0:fb7af294d5d9 2184 return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
Simon Cooksey 0:fb7af294d5d9 2185 }
Simon Cooksey 0:fb7af294d5d9 2186
Simon Cooksey 0:fb7af294d5d9 2187 return( ret );
Simon Cooksey 0:fb7af294d5d9 2188 }
Simon Cooksey 0:fb7af294d5d9 2189 #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
Simon Cooksey 0:fb7af294d5d9 2190 MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2191
Simon Cooksey 0:fb7af294d5d9 2192 static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 2193 {
Simon Cooksey 0:fb7af294d5d9 2194 int ret;
Simon Cooksey 0:fb7af294d5d9 2195 const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
Simon Cooksey 0:fb7af294d5d9 2196 unsigned char *p, *end;
Simon Cooksey 0:fb7af294d5d9 2197
Simon Cooksey 0:fb7af294d5d9 2198 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) );
Simon Cooksey 0:fb7af294d5d9 2199
Simon Cooksey 0:fb7af294d5d9 2200 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2201 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA )
Simon Cooksey 0:fb7af294d5d9 2202 {
Simon Cooksey 0:fb7af294d5d9 2203 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) );
Simon Cooksey 0:fb7af294d5d9 2204 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 2205 return( 0 );
Simon Cooksey 0:fb7af294d5d9 2206 }
Simon Cooksey 0:fb7af294d5d9 2207 ((void) p);
Simon Cooksey 0:fb7af294d5d9 2208 ((void) end);
Simon Cooksey 0:fb7af294d5d9 2209 #endif
Simon Cooksey 0:fb7af294d5d9 2210
Simon Cooksey 0:fb7af294d5d9 2211 #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2212 defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2213 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA ||
Simon Cooksey 0:fb7af294d5d9 2214 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA )
Simon Cooksey 0:fb7af294d5d9 2215 {
Simon Cooksey 0:fb7af294d5d9 2216 if( ( ret = ssl_get_ecdh_params_from_cert( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2217 {
Simon Cooksey 0:fb7af294d5d9 2218 MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret );
Simon Cooksey 0:fb7af294d5d9 2219 return( ret );
Simon Cooksey 0:fb7af294d5d9 2220 }
Simon Cooksey 0:fb7af294d5d9 2221
Simon Cooksey 0:fb7af294d5d9 2222 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) );
Simon Cooksey 0:fb7af294d5d9 2223 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 2224 return( 0 );
Simon Cooksey 0:fb7af294d5d9 2225 }
Simon Cooksey 0:fb7af294d5d9 2226 ((void) p);
Simon Cooksey 0:fb7af294d5d9 2227 ((void) end);
Simon Cooksey 0:fb7af294d5d9 2228 #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 2229 MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2230
Simon Cooksey 0:fb7af294d5d9 2231 if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2232 {
Simon Cooksey 0:fb7af294d5d9 2233 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
Simon Cooksey 0:fb7af294d5d9 2234 return( ret );
Simon Cooksey 0:fb7af294d5d9 2235 }
Simon Cooksey 0:fb7af294d5d9 2236
Simon Cooksey 0:fb7af294d5d9 2237 if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
Simon Cooksey 0:fb7af294d5d9 2238 {
Simon Cooksey 0:fb7af294d5d9 2239 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
Simon Cooksey 0:fb7af294d5d9 2240 return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
Simon Cooksey 0:fb7af294d5d9 2241 }
Simon Cooksey 0:fb7af294d5d9 2242
Simon Cooksey 0:fb7af294d5d9 2243 /*
Simon Cooksey 0:fb7af294d5d9 2244 * ServerKeyExchange may be skipped with PSK and RSA-PSK when the server
Simon Cooksey 0:fb7af294d5d9 2245 * doesn't use a psk_identity_hint
Simon Cooksey 0:fb7af294d5d9 2246 */
Simon Cooksey 0:fb7af294d5d9 2247 if( ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE )
Simon Cooksey 0:fb7af294d5d9 2248 {
Simon Cooksey 0:fb7af294d5d9 2249 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
Simon Cooksey 0:fb7af294d5d9 2250 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
Simon Cooksey 0:fb7af294d5d9 2251 {
Simon Cooksey 0:fb7af294d5d9 2252 ssl->record_read = 1;
Simon Cooksey 0:fb7af294d5d9 2253 goto exit;
Simon Cooksey 0:fb7af294d5d9 2254 }
Simon Cooksey 0:fb7af294d5d9 2255
Simon Cooksey 0:fb7af294d5d9 2256 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
Simon Cooksey 0:fb7af294d5d9 2257 return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
Simon Cooksey 0:fb7af294d5d9 2258 }
Simon Cooksey 0:fb7af294d5d9 2259
Simon Cooksey 0:fb7af294d5d9 2260 p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
Simon Cooksey 0:fb7af294d5d9 2261 end = ssl->in_msg + ssl->in_hslen;
Simon Cooksey 0:fb7af294d5d9 2262 MBEDTLS_SSL_DEBUG_BUF( 3, "server key exchange", p, end - p );
Simon Cooksey 0:fb7af294d5d9 2263
Simon Cooksey 0:fb7af294d5d9 2264 #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2265 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
Simon Cooksey 0:fb7af294d5d9 2266 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
Simon Cooksey 0:fb7af294d5d9 2267 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
Simon Cooksey 0:fb7af294d5d9 2268 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
Simon Cooksey 0:fb7af294d5d9 2269 {
Simon Cooksey 0:fb7af294d5d9 2270 if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2271 {
Simon Cooksey 0:fb7af294d5d9 2272 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
Simon Cooksey 0:fb7af294d5d9 2273 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 2274 }
Simon Cooksey 0:fb7af294d5d9 2275 } /* FALLTROUGH */
Simon Cooksey 0:fb7af294d5d9 2276 #endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2277
Simon Cooksey 0:fb7af294d5d9 2278 #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2279 defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2280 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
Simon Cooksey 0:fb7af294d5d9 2281 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
Simon Cooksey 0:fb7af294d5d9 2282 ; /* nothing more to do */
Simon Cooksey 0:fb7af294d5d9 2283 else
Simon Cooksey 0:fb7af294d5d9 2284 #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 2285 MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2286 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2287 defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2288 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ||
Simon Cooksey 0:fb7af294d5d9 2289 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK )
Simon Cooksey 0:fb7af294d5d9 2290 {
Simon Cooksey 0:fb7af294d5d9 2291 if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2292 {
Simon Cooksey 0:fb7af294d5d9 2293 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
Simon Cooksey 0:fb7af294d5d9 2294 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 2295 }
Simon Cooksey 0:fb7af294d5d9 2296 }
Simon Cooksey 0:fb7af294d5d9 2297 else
Simon Cooksey 0:fb7af294d5d9 2298 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 2299 MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2300 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2301 defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2302 defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2303 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
Simon Cooksey 0:fb7af294d5d9 2304 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
Simon Cooksey 0:fb7af294d5d9 2305 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA )
Simon Cooksey 0:fb7af294d5d9 2306 {
Simon Cooksey 0:fb7af294d5d9 2307 if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2308 {
Simon Cooksey 0:fb7af294d5d9 2309 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
Simon Cooksey 0:fb7af294d5d9 2310 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 2311 }
Simon Cooksey 0:fb7af294d5d9 2312 }
Simon Cooksey 0:fb7af294d5d9 2313 else
Simon Cooksey 0:fb7af294d5d9 2314 #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 2315 MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 2316 MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2317 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2318 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
Simon Cooksey 0:fb7af294d5d9 2319 {
Simon Cooksey 0:fb7af294d5d9 2320 ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx,
Simon Cooksey 0:fb7af294d5d9 2321 p, end - p );
Simon Cooksey 0:fb7af294d5d9 2322 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 2323 {
Simon Cooksey 0:fb7af294d5d9 2324 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret );
Simon Cooksey 0:fb7af294d5d9 2325 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 2326 }
Simon Cooksey 0:fb7af294d5d9 2327 }
Simon Cooksey 0:fb7af294d5d9 2328 else
Simon Cooksey 0:fb7af294d5d9 2329 #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2330 {
Simon Cooksey 0:fb7af294d5d9 2331 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
Simon Cooksey 0:fb7af294d5d9 2332 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
Simon Cooksey 0:fb7af294d5d9 2333 }
Simon Cooksey 0:fb7af294d5d9 2334
Simon Cooksey 0:fb7af294d5d9 2335 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2336 defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2337 defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2338 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ||
Simon Cooksey 0:fb7af294d5d9 2339 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
Simon Cooksey 0:fb7af294d5d9 2340 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA )
Simon Cooksey 0:fb7af294d5d9 2341 {
Simon Cooksey 0:fb7af294d5d9 2342 size_t sig_len, hashlen;
Simon Cooksey 0:fb7af294d5d9 2343 unsigned char hash[64];
Simon Cooksey 0:fb7af294d5d9 2344 mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE;
Simon Cooksey 0:fb7af294d5d9 2345 mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
Simon Cooksey 0:fb7af294d5d9 2346 unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
Simon Cooksey 0:fb7af294d5d9 2347 size_t params_len = p - params;
Simon Cooksey 0:fb7af294d5d9 2348
Simon Cooksey 0:fb7af294d5d9 2349 /*
Simon Cooksey 0:fb7af294d5d9 2350 * Handle the digitally-signed structure
Simon Cooksey 0:fb7af294d5d9 2351 */
Simon Cooksey 0:fb7af294d5d9 2352 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
Simon Cooksey 0:fb7af294d5d9 2353 if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
Simon Cooksey 0:fb7af294d5d9 2354 {
Simon Cooksey 0:fb7af294d5d9 2355 if( ssl_parse_signature_algorithm( ssl, &p, end,
Simon Cooksey 0:fb7af294d5d9 2356 &md_alg, &pk_alg ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2357 {
Simon Cooksey 0:fb7af294d5d9 2358 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
Simon Cooksey 0:fb7af294d5d9 2359 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 2360 }
Simon Cooksey 0:fb7af294d5d9 2361
Simon Cooksey 0:fb7af294d5d9 2362 if( pk_alg != mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) )
Simon Cooksey 0:fb7af294d5d9 2363 {
Simon Cooksey 0:fb7af294d5d9 2364 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
Simon Cooksey 0:fb7af294d5d9 2365 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 2366 }
Simon Cooksey 0:fb7af294d5d9 2367 }
Simon Cooksey 0:fb7af294d5d9 2368 else
Simon Cooksey 0:fb7af294d5d9 2369 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
Simon Cooksey 0:fb7af294d5d9 2370 #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
Simon Cooksey 0:fb7af294d5d9 2371 defined(MBEDTLS_SSL_PROTO_TLS1_1)
Simon Cooksey 0:fb7af294d5d9 2372 if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 )
Simon Cooksey 0:fb7af294d5d9 2373 {
Simon Cooksey 0:fb7af294d5d9 2374 pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info );
Simon Cooksey 0:fb7af294d5d9 2375
Simon Cooksey 0:fb7af294d5d9 2376 /* Default hash for ECDSA is SHA-1 */
Simon Cooksey 0:fb7af294d5d9 2377 if( pk_alg == MBEDTLS_PK_ECDSA && md_alg == MBEDTLS_MD_NONE )
Simon Cooksey 0:fb7af294d5d9 2378 md_alg = MBEDTLS_MD_SHA1;
Simon Cooksey 0:fb7af294d5d9 2379 }
Simon Cooksey 0:fb7af294d5d9 2380 else
Simon Cooksey 0:fb7af294d5d9 2381 #endif
Simon Cooksey 0:fb7af294d5d9 2382 {
Simon Cooksey 0:fb7af294d5d9 2383 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
Simon Cooksey 0:fb7af294d5d9 2384 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
Simon Cooksey 0:fb7af294d5d9 2385 }
Simon Cooksey 0:fb7af294d5d9 2386
Simon Cooksey 0:fb7af294d5d9 2387 /*
Simon Cooksey 0:fb7af294d5d9 2388 * Read signature
Simon Cooksey 0:fb7af294d5d9 2389 */
Simon Cooksey 0:fb7af294d5d9 2390 sig_len = ( p[0] << 8 ) | p[1];
Simon Cooksey 0:fb7af294d5d9 2391 p += 2;
Simon Cooksey 0:fb7af294d5d9 2392
Simon Cooksey 0:fb7af294d5d9 2393 if( end != p + sig_len )
Simon Cooksey 0:fb7af294d5d9 2394 {
Simon Cooksey 0:fb7af294d5d9 2395 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
Simon Cooksey 0:fb7af294d5d9 2396 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
Simon Cooksey 0:fb7af294d5d9 2397 }
Simon Cooksey 0:fb7af294d5d9 2398
Simon Cooksey 0:fb7af294d5d9 2399 MBEDTLS_SSL_DEBUG_BUF( 3, "signature", p, sig_len );
Simon Cooksey 0:fb7af294d5d9 2400
Simon Cooksey 0:fb7af294d5d9 2401 /*
Simon Cooksey 0:fb7af294d5d9 2402 * Compute the hash that has been signed
Simon Cooksey 0:fb7af294d5d9 2403 */
Simon Cooksey 0:fb7af294d5d9 2404 #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
Simon Cooksey 0:fb7af294d5d9 2405 defined(MBEDTLS_SSL_PROTO_TLS1_1)
Simon Cooksey 0:fb7af294d5d9 2406 if( md_alg == MBEDTLS_MD_NONE )
Simon Cooksey 0:fb7af294d5d9 2407 {
Simon Cooksey 0:fb7af294d5d9 2408 mbedtls_md5_context mbedtls_md5;
Simon Cooksey 0:fb7af294d5d9 2409 mbedtls_sha1_context mbedtls_sha1;
Simon Cooksey 0:fb7af294d5d9 2410
Simon Cooksey 0:fb7af294d5d9 2411 mbedtls_md5_init( &mbedtls_md5 );
Simon Cooksey 0:fb7af294d5d9 2412 mbedtls_sha1_init( &mbedtls_sha1 );
Simon Cooksey 0:fb7af294d5d9 2413
Simon Cooksey 0:fb7af294d5d9 2414 hashlen = 36;
Simon Cooksey 0:fb7af294d5d9 2415
Simon Cooksey 0:fb7af294d5d9 2416 /*
Simon Cooksey 0:fb7af294d5d9 2417 * digitally-signed struct {
Simon Cooksey 0:fb7af294d5d9 2418 * opaque md5_hash[16];
Simon Cooksey 0:fb7af294d5d9 2419 * opaque sha_hash[20];
Simon Cooksey 0:fb7af294d5d9 2420 * };
Simon Cooksey 0:fb7af294d5d9 2421 *
Simon Cooksey 0:fb7af294d5d9 2422 * md5_hash
Simon Cooksey 0:fb7af294d5d9 2423 * MD5(ClientHello.random + ServerHello.random
Simon Cooksey 0:fb7af294d5d9 2424 * + ServerParams);
Simon Cooksey 0:fb7af294d5d9 2425 * sha_hash
Simon Cooksey 0:fb7af294d5d9 2426 * SHA(ClientHello.random + ServerHello.random
Simon Cooksey 0:fb7af294d5d9 2427 * + ServerParams);
Simon Cooksey 0:fb7af294d5d9 2428 */
Simon Cooksey 0:fb7af294d5d9 2429 mbedtls_md5_starts( &mbedtls_md5 );
Simon Cooksey 0:fb7af294d5d9 2430 mbedtls_md5_update( &mbedtls_md5, ssl->handshake->randbytes, 64 );
Simon Cooksey 0:fb7af294d5d9 2431 mbedtls_md5_update( &mbedtls_md5, params, params_len );
Simon Cooksey 0:fb7af294d5d9 2432 mbedtls_md5_finish( &mbedtls_md5, hash );
Simon Cooksey 0:fb7af294d5d9 2433
Simon Cooksey 0:fb7af294d5d9 2434 mbedtls_sha1_starts( &mbedtls_sha1 );
Simon Cooksey 0:fb7af294d5d9 2435 mbedtls_sha1_update( &mbedtls_sha1, ssl->handshake->randbytes, 64 );
Simon Cooksey 0:fb7af294d5d9 2436 mbedtls_sha1_update( &mbedtls_sha1, params, params_len );
Simon Cooksey 0:fb7af294d5d9 2437 mbedtls_sha1_finish( &mbedtls_sha1, hash + 16 );
Simon Cooksey 0:fb7af294d5d9 2438
Simon Cooksey 0:fb7af294d5d9 2439 mbedtls_md5_free( &mbedtls_md5 );
Simon Cooksey 0:fb7af294d5d9 2440 mbedtls_sha1_free( &mbedtls_sha1 );
Simon Cooksey 0:fb7af294d5d9 2441 }
Simon Cooksey 0:fb7af294d5d9 2442 else
Simon Cooksey 0:fb7af294d5d9 2443 #endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \
Simon Cooksey 0:fb7af294d5d9 2444 MBEDTLS_SSL_PROTO_TLS1_1 */
Simon Cooksey 0:fb7af294d5d9 2445 #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
Simon Cooksey 0:fb7af294d5d9 2446 defined(MBEDTLS_SSL_PROTO_TLS1_2)
Simon Cooksey 0:fb7af294d5d9 2447 if( md_alg != MBEDTLS_MD_NONE )
Simon Cooksey 0:fb7af294d5d9 2448 {
Simon Cooksey 0:fb7af294d5d9 2449 mbedtls_md_context_t ctx;
Simon Cooksey 0:fb7af294d5d9 2450
Simon Cooksey 0:fb7af294d5d9 2451 mbedtls_md_init( &ctx );
Simon Cooksey 0:fb7af294d5d9 2452
Simon Cooksey 0:fb7af294d5d9 2453 /* Info from md_alg will be used instead */
Simon Cooksey 0:fb7af294d5d9 2454 hashlen = 0;
Simon Cooksey 0:fb7af294d5d9 2455
Simon Cooksey 0:fb7af294d5d9 2456 /*
Simon Cooksey 0:fb7af294d5d9 2457 * digitally-signed struct {
Simon Cooksey 0:fb7af294d5d9 2458 * opaque client_random[32];
Simon Cooksey 0:fb7af294d5d9 2459 * opaque server_random[32];
Simon Cooksey 0:fb7af294d5d9 2460 * ServerDHParams params;
Simon Cooksey 0:fb7af294d5d9 2461 * };
Simon Cooksey 0:fb7af294d5d9 2462 */
Simon Cooksey 0:fb7af294d5d9 2463 if( ( ret = mbedtls_md_setup( &ctx,
Simon Cooksey 0:fb7af294d5d9 2464 mbedtls_md_info_from_type( md_alg ), 0 ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2465 {
Simon Cooksey 0:fb7af294d5d9 2466 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret );
Simon Cooksey 0:fb7af294d5d9 2467 return( ret );
Simon Cooksey 0:fb7af294d5d9 2468 }
Simon Cooksey 0:fb7af294d5d9 2469
Simon Cooksey 0:fb7af294d5d9 2470 mbedtls_md_starts( &ctx );
Simon Cooksey 0:fb7af294d5d9 2471 mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 );
Simon Cooksey 0:fb7af294d5d9 2472 mbedtls_md_update( &ctx, params, params_len );
Simon Cooksey 0:fb7af294d5d9 2473 mbedtls_md_finish( &ctx, hash );
Simon Cooksey 0:fb7af294d5d9 2474 mbedtls_md_free( &ctx );
Simon Cooksey 0:fb7af294d5d9 2475 }
Simon Cooksey 0:fb7af294d5d9 2476 else
Simon Cooksey 0:fb7af294d5d9 2477 #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
Simon Cooksey 0:fb7af294d5d9 2478 MBEDTLS_SSL_PROTO_TLS1_2 */
Simon Cooksey 0:fb7af294d5d9 2479 {
Simon Cooksey 0:fb7af294d5d9 2480 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
Simon Cooksey 0:fb7af294d5d9 2481 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
Simon Cooksey 0:fb7af294d5d9 2482 }
Simon Cooksey 0:fb7af294d5d9 2483
Simon Cooksey 0:fb7af294d5d9 2484 MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen :
Simon Cooksey 0:fb7af294d5d9 2485 (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) );
Simon Cooksey 0:fb7af294d5d9 2486
Simon Cooksey 0:fb7af294d5d9 2487 if( ssl->session_negotiate->peer_cert == NULL )
Simon Cooksey 0:fb7af294d5d9 2488 {
Simon Cooksey 0:fb7af294d5d9 2489 MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) );
Simon Cooksey 0:fb7af294d5d9 2490 return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
Simon Cooksey 0:fb7af294d5d9 2491 }
Simon Cooksey 0:fb7af294d5d9 2492
Simon Cooksey 0:fb7af294d5d9 2493 /*
Simon Cooksey 0:fb7af294d5d9 2494 * Verify signature
Simon Cooksey 0:fb7af294d5d9 2495 */
Simon Cooksey 0:fb7af294d5d9 2496 if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) )
Simon Cooksey 0:fb7af294d5d9 2497 {
Simon Cooksey 0:fb7af294d5d9 2498 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
Simon Cooksey 0:fb7af294d5d9 2499 return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
Simon Cooksey 0:fb7af294d5d9 2500 }
Simon Cooksey 0:fb7af294d5d9 2501
Simon Cooksey 0:fb7af294d5d9 2502 if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk,
Simon Cooksey 0:fb7af294d5d9 2503 md_alg, hash, hashlen, p, sig_len ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2504 {
Simon Cooksey 0:fb7af294d5d9 2505 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret );
Simon Cooksey 0:fb7af294d5d9 2506 return( ret );
Simon Cooksey 0:fb7af294d5d9 2507 }
Simon Cooksey 0:fb7af294d5d9 2508 }
Simon Cooksey 0:fb7af294d5d9 2509 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 2510 MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 2511 MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2512
Simon Cooksey 0:fb7af294d5d9 2513 exit:
Simon Cooksey 0:fb7af294d5d9 2514 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 2515
Simon Cooksey 0:fb7af294d5d9 2516 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) );
Simon Cooksey 0:fb7af294d5d9 2517
Simon Cooksey 0:fb7af294d5d9 2518 return( 0 );
Simon Cooksey 0:fb7af294d5d9 2519 }
Simon Cooksey 0:fb7af294d5d9 2520
Simon Cooksey 0:fb7af294d5d9 2521 #if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \
Simon Cooksey 0:fb7af294d5d9 2522 !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \
Simon Cooksey 0:fb7af294d5d9 2523 !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \
Simon Cooksey 0:fb7af294d5d9 2524 !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
Simon Cooksey 0:fb7af294d5d9 2525 !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \
Simon Cooksey 0:fb7af294d5d9 2526 !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2527 static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 2528 {
Simon Cooksey 0:fb7af294d5d9 2529 const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
Simon Cooksey 0:fb7af294d5d9 2530
Simon Cooksey 0:fb7af294d5d9 2531 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) );
Simon Cooksey 0:fb7af294d5d9 2532
Simon Cooksey 0:fb7af294d5d9 2533 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
Simon Cooksey 0:fb7af294d5d9 2534 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
Simon Cooksey 0:fb7af294d5d9 2535 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
Simon Cooksey 0:fb7af294d5d9 2536 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
Simon Cooksey 0:fb7af294d5d9 2537 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
Simon Cooksey 0:fb7af294d5d9 2538 {
Simon Cooksey 0:fb7af294d5d9 2539 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) );
Simon Cooksey 0:fb7af294d5d9 2540 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 2541 return( 0 );
Simon Cooksey 0:fb7af294d5d9 2542 }
Simon Cooksey 0:fb7af294d5d9 2543
Simon Cooksey 0:fb7af294d5d9 2544 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
Simon Cooksey 0:fb7af294d5d9 2545 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
Simon Cooksey 0:fb7af294d5d9 2546 }
Simon Cooksey 0:fb7af294d5d9 2547 #else
Simon Cooksey 0:fb7af294d5d9 2548 static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 2549 {
Simon Cooksey 0:fb7af294d5d9 2550 int ret;
Simon Cooksey 0:fb7af294d5d9 2551 unsigned char *buf;
Simon Cooksey 0:fb7af294d5d9 2552 size_t n = 0;
Simon Cooksey 0:fb7af294d5d9 2553 size_t cert_type_len = 0, dn_len = 0;
Simon Cooksey 0:fb7af294d5d9 2554 const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
Simon Cooksey 0:fb7af294d5d9 2555
Simon Cooksey 0:fb7af294d5d9 2556 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) );
Simon Cooksey 0:fb7af294d5d9 2557
Simon Cooksey 0:fb7af294d5d9 2558 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
Simon Cooksey 0:fb7af294d5d9 2559 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
Simon Cooksey 0:fb7af294d5d9 2560 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
Simon Cooksey 0:fb7af294d5d9 2561 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
Simon Cooksey 0:fb7af294d5d9 2562 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
Simon Cooksey 0:fb7af294d5d9 2563 {
Simon Cooksey 0:fb7af294d5d9 2564 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) );
Simon Cooksey 0:fb7af294d5d9 2565 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 2566 return( 0 );
Simon Cooksey 0:fb7af294d5d9 2567 }
Simon Cooksey 0:fb7af294d5d9 2568
Simon Cooksey 0:fb7af294d5d9 2569 if( ssl->record_read == 0 )
Simon Cooksey 0:fb7af294d5d9 2570 {
Simon Cooksey 0:fb7af294d5d9 2571 if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2572 {
Simon Cooksey 0:fb7af294d5d9 2573 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
Simon Cooksey 0:fb7af294d5d9 2574 return( ret );
Simon Cooksey 0:fb7af294d5d9 2575 }
Simon Cooksey 0:fb7af294d5d9 2576
Simon Cooksey 0:fb7af294d5d9 2577 if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
Simon Cooksey 0:fb7af294d5d9 2578 {
Simon Cooksey 0:fb7af294d5d9 2579 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
Simon Cooksey 0:fb7af294d5d9 2580 return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
Simon Cooksey 0:fb7af294d5d9 2581 }
Simon Cooksey 0:fb7af294d5d9 2582
Simon Cooksey 0:fb7af294d5d9 2583 ssl->record_read = 1;
Simon Cooksey 0:fb7af294d5d9 2584 }
Simon Cooksey 0:fb7af294d5d9 2585
Simon Cooksey 0:fb7af294d5d9 2586 ssl->client_auth = 0;
Simon Cooksey 0:fb7af294d5d9 2587 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 2588
Simon Cooksey 0:fb7af294d5d9 2589 if( ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST )
Simon Cooksey 0:fb7af294d5d9 2590 ssl->client_auth++;
Simon Cooksey 0:fb7af294d5d9 2591
Simon Cooksey 0:fb7af294d5d9 2592 MBEDTLS_SSL_DEBUG_MSG( 3, ( "got %s certificate request",
Simon Cooksey 0:fb7af294d5d9 2593 ssl->client_auth ? "a" : "no" ) );
Simon Cooksey 0:fb7af294d5d9 2594
Simon Cooksey 0:fb7af294d5d9 2595 if( ssl->client_auth == 0 )
Simon Cooksey 0:fb7af294d5d9 2596 goto exit;
Simon Cooksey 0:fb7af294d5d9 2597
Simon Cooksey 0:fb7af294d5d9 2598 ssl->record_read = 0;
Simon Cooksey 0:fb7af294d5d9 2599
Simon Cooksey 0:fb7af294d5d9 2600 /*
Simon Cooksey 0:fb7af294d5d9 2601 * struct {
Simon Cooksey 0:fb7af294d5d9 2602 * ClientCertificateType certificate_types<1..2^8-1>;
Simon Cooksey 0:fb7af294d5d9 2603 * SignatureAndHashAlgorithm
Simon Cooksey 0:fb7af294d5d9 2604 * supported_signature_algorithms<2^16-1>; -- TLS 1.2 only
Simon Cooksey 0:fb7af294d5d9 2605 * DistinguishedName certificate_authorities<0..2^16-1>;
Simon Cooksey 0:fb7af294d5d9 2606 * } CertificateRequest;
Simon Cooksey 0:fb7af294d5d9 2607 *
Simon Cooksey 0:fb7af294d5d9 2608 * Since we only support a single certificate on clients, let's just
Simon Cooksey 0:fb7af294d5d9 2609 * ignore all the information that's supposed to help us pick a
Simon Cooksey 0:fb7af294d5d9 2610 * certificate.
Simon Cooksey 0:fb7af294d5d9 2611 *
Simon Cooksey 0:fb7af294d5d9 2612 * We could check that our certificate matches the request, and bail out
Simon Cooksey 0:fb7af294d5d9 2613 * if it doesn't, but it's simpler to just send the certificate anyway,
Simon Cooksey 0:fb7af294d5d9 2614 * and give the server the opportunity to decide if it should terminate
Simon Cooksey 0:fb7af294d5d9 2615 * the connection when it doesn't like our certificate.
Simon Cooksey 0:fb7af294d5d9 2616 *
Simon Cooksey 0:fb7af294d5d9 2617 * Same goes for the hash in TLS 1.2's signature_algorithms: at this
Simon Cooksey 0:fb7af294d5d9 2618 * point we only have one hash available (see comments in
Simon Cooksey 0:fb7af294d5d9 2619 * write_certificate_verify), so let's just use what we have.
Simon Cooksey 0:fb7af294d5d9 2620 *
Simon Cooksey 0:fb7af294d5d9 2621 * However, we still minimally parse the message to check it is at least
Simon Cooksey 0:fb7af294d5d9 2622 * superficially sane.
Simon Cooksey 0:fb7af294d5d9 2623 */
Simon Cooksey 0:fb7af294d5d9 2624 buf = ssl->in_msg;
Simon Cooksey 0:fb7af294d5d9 2625
Simon Cooksey 0:fb7af294d5d9 2626 /* certificate_types */
Simon Cooksey 0:fb7af294d5d9 2627 cert_type_len = buf[mbedtls_ssl_hs_hdr_len( ssl )];
Simon Cooksey 0:fb7af294d5d9 2628 n = cert_type_len;
Simon Cooksey 0:fb7af294d5d9 2629
Simon Cooksey 0:fb7af294d5d9 2630 if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n )
Simon Cooksey 0:fb7af294d5d9 2631 {
Simon Cooksey 0:fb7af294d5d9 2632 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
Simon Cooksey 0:fb7af294d5d9 2633 return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
Simon Cooksey 0:fb7af294d5d9 2634 }
Simon Cooksey 0:fb7af294d5d9 2635
Simon Cooksey 0:fb7af294d5d9 2636 /* supported_signature_algorithms */
Simon Cooksey 0:fb7af294d5d9 2637 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
Simon Cooksey 0:fb7af294d5d9 2638 if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
Simon Cooksey 0:fb7af294d5d9 2639 {
Simon Cooksey 0:fb7af294d5d9 2640 size_t sig_alg_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 )
Simon Cooksey 0:fb7af294d5d9 2641 | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) );
Simon Cooksey 0:fb7af294d5d9 2642 #if defined(MBEDTLS_DEBUG_C)
Simon Cooksey 0:fb7af294d5d9 2643 unsigned char* sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n;
Simon Cooksey 0:fb7af294d5d9 2644 size_t i;
Simon Cooksey 0:fb7af294d5d9 2645
Simon Cooksey 0:fb7af294d5d9 2646 for( i = 0; i < sig_alg_len; i += 2 )
Simon Cooksey 0:fb7af294d5d9 2647 {
Simon Cooksey 0:fb7af294d5d9 2648 MBEDTLS_SSL_DEBUG_MSG( 3, ( "Supported Signature Algorithm found: %d,%d", sig_alg[i], sig_alg[i + 1] ) );
Simon Cooksey 0:fb7af294d5d9 2649 }
Simon Cooksey 0:fb7af294d5d9 2650 #endif
Simon Cooksey 0:fb7af294d5d9 2651
Simon Cooksey 0:fb7af294d5d9 2652 n += 2 + sig_alg_len;
Simon Cooksey 0:fb7af294d5d9 2653
Simon Cooksey 0:fb7af294d5d9 2654 if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n )
Simon Cooksey 0:fb7af294d5d9 2655 {
Simon Cooksey 0:fb7af294d5d9 2656 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
Simon Cooksey 0:fb7af294d5d9 2657 return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
Simon Cooksey 0:fb7af294d5d9 2658 }
Simon Cooksey 0:fb7af294d5d9 2659 }
Simon Cooksey 0:fb7af294d5d9 2660 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
Simon Cooksey 0:fb7af294d5d9 2661
Simon Cooksey 0:fb7af294d5d9 2662 /* certificate_authorities */
Simon Cooksey 0:fb7af294d5d9 2663 dn_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 )
Simon Cooksey 0:fb7af294d5d9 2664 | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) );
Simon Cooksey 0:fb7af294d5d9 2665
Simon Cooksey 0:fb7af294d5d9 2666 n += dn_len;
Simon Cooksey 0:fb7af294d5d9 2667 if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n )
Simon Cooksey 0:fb7af294d5d9 2668 {
Simon Cooksey 0:fb7af294d5d9 2669 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
Simon Cooksey 0:fb7af294d5d9 2670 return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
Simon Cooksey 0:fb7af294d5d9 2671 }
Simon Cooksey 0:fb7af294d5d9 2672
Simon Cooksey 0:fb7af294d5d9 2673 exit:
Simon Cooksey 0:fb7af294d5d9 2674 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) );
Simon Cooksey 0:fb7af294d5d9 2675
Simon Cooksey 0:fb7af294d5d9 2676 return( 0 );
Simon Cooksey 0:fb7af294d5d9 2677 }
Simon Cooksey 0:fb7af294d5d9 2678 #endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 2679 !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 2680 !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 2681 !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 2682 !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 2683 !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2684
Simon Cooksey 0:fb7af294d5d9 2685 static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 2686 {
Simon Cooksey 0:fb7af294d5d9 2687 int ret;
Simon Cooksey 0:fb7af294d5d9 2688
Simon Cooksey 0:fb7af294d5d9 2689 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) );
Simon Cooksey 0:fb7af294d5d9 2690
Simon Cooksey 0:fb7af294d5d9 2691 if( ssl->record_read == 0 )
Simon Cooksey 0:fb7af294d5d9 2692 {
Simon Cooksey 0:fb7af294d5d9 2693 if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2694 {
Simon Cooksey 0:fb7af294d5d9 2695 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
Simon Cooksey 0:fb7af294d5d9 2696 return( ret );
Simon Cooksey 0:fb7af294d5d9 2697 }
Simon Cooksey 0:fb7af294d5d9 2698
Simon Cooksey 0:fb7af294d5d9 2699 if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
Simon Cooksey 0:fb7af294d5d9 2700 {
Simon Cooksey 0:fb7af294d5d9 2701 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) );
Simon Cooksey 0:fb7af294d5d9 2702 return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
Simon Cooksey 0:fb7af294d5d9 2703 }
Simon Cooksey 0:fb7af294d5d9 2704 }
Simon Cooksey 0:fb7af294d5d9 2705 ssl->record_read = 0;
Simon Cooksey 0:fb7af294d5d9 2706
Simon Cooksey 0:fb7af294d5d9 2707 if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ||
Simon Cooksey 0:fb7af294d5d9 2708 ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO_DONE )
Simon Cooksey 0:fb7af294d5d9 2709 {
Simon Cooksey 0:fb7af294d5d9 2710 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) );
Simon Cooksey 0:fb7af294d5d9 2711 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE );
Simon Cooksey 0:fb7af294d5d9 2712 }
Simon Cooksey 0:fb7af294d5d9 2713
Simon Cooksey 0:fb7af294d5d9 2714 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 2715
Simon Cooksey 0:fb7af294d5d9 2716 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 2717 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
Simon Cooksey 0:fb7af294d5d9 2718 mbedtls_ssl_recv_flight_completed( ssl );
Simon Cooksey 0:fb7af294d5d9 2719 #endif
Simon Cooksey 0:fb7af294d5d9 2720
Simon Cooksey 0:fb7af294d5d9 2721 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello done" ) );
Simon Cooksey 0:fb7af294d5d9 2722
Simon Cooksey 0:fb7af294d5d9 2723 return( 0 );
Simon Cooksey 0:fb7af294d5d9 2724 }
Simon Cooksey 0:fb7af294d5d9 2725
Simon Cooksey 0:fb7af294d5d9 2726 static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 2727 {
Simon Cooksey 0:fb7af294d5d9 2728 int ret;
Simon Cooksey 0:fb7af294d5d9 2729 size_t i, n;
Simon Cooksey 0:fb7af294d5d9 2730 const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
Simon Cooksey 0:fb7af294d5d9 2731
Simon Cooksey 0:fb7af294d5d9 2732 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) );
Simon Cooksey 0:fb7af294d5d9 2733
Simon Cooksey 0:fb7af294d5d9 2734 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2735 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA )
Simon Cooksey 0:fb7af294d5d9 2736 {
Simon Cooksey 0:fb7af294d5d9 2737 /*
Simon Cooksey 0:fb7af294d5d9 2738 * DHM key exchange -- send G^X mod P
Simon Cooksey 0:fb7af294d5d9 2739 */
Simon Cooksey 0:fb7af294d5d9 2740 n = ssl->handshake->dhm_ctx.len;
Simon Cooksey 0:fb7af294d5d9 2741
Simon Cooksey 0:fb7af294d5d9 2742 ssl->out_msg[4] = (unsigned char)( n >> 8 );
Simon Cooksey 0:fb7af294d5d9 2743 ssl->out_msg[5] = (unsigned char)( n );
Simon Cooksey 0:fb7af294d5d9 2744 i = 6;
Simon Cooksey 0:fb7af294d5d9 2745
Simon Cooksey 0:fb7af294d5d9 2746 ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx,
Simon Cooksey 0:fb7af294d5d9 2747 (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ),
Simon Cooksey 0:fb7af294d5d9 2748 &ssl->out_msg[i], n,
Simon Cooksey 0:fb7af294d5d9 2749 ssl->conf->f_rng, ssl->conf->p_rng );
Simon Cooksey 0:fb7af294d5d9 2750 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 2751 {
Simon Cooksey 0:fb7af294d5d9 2752 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret );
Simon Cooksey 0:fb7af294d5d9 2753 return( ret );
Simon Cooksey 0:fb7af294d5d9 2754 }
Simon Cooksey 0:fb7af294d5d9 2755
Simon Cooksey 0:fb7af294d5d9 2756 MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X );
Simon Cooksey 0:fb7af294d5d9 2757 MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX );
Simon Cooksey 0:fb7af294d5d9 2758
Simon Cooksey 0:fb7af294d5d9 2759 if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx,
Simon Cooksey 0:fb7af294d5d9 2760 ssl->handshake->premaster,
Simon Cooksey 0:fb7af294d5d9 2761 MBEDTLS_PREMASTER_SIZE,
Simon Cooksey 0:fb7af294d5d9 2762 &ssl->handshake->pmslen,
Simon Cooksey 0:fb7af294d5d9 2763 ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2764 {
Simon Cooksey 0:fb7af294d5d9 2765 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret );
Simon Cooksey 0:fb7af294d5d9 2766 return( ret );
Simon Cooksey 0:fb7af294d5d9 2767 }
Simon Cooksey 0:fb7af294d5d9 2768
Simon Cooksey 0:fb7af294d5d9 2769 MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K );
Simon Cooksey 0:fb7af294d5d9 2770 }
Simon Cooksey 0:fb7af294d5d9 2771 else
Simon Cooksey 0:fb7af294d5d9 2772 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2773 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2774 defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2775 defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
Simon Cooksey 0:fb7af294d5d9 2776 defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2777 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
Simon Cooksey 0:fb7af294d5d9 2778 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ||
Simon Cooksey 0:fb7af294d5d9 2779 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA ||
Simon Cooksey 0:fb7af294d5d9 2780 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA )
Simon Cooksey 0:fb7af294d5d9 2781 {
Simon Cooksey 0:fb7af294d5d9 2782 /*
Simon Cooksey 0:fb7af294d5d9 2783 * ECDH key exchange -- send client public value
Simon Cooksey 0:fb7af294d5d9 2784 */
Simon Cooksey 0:fb7af294d5d9 2785 i = 4;
Simon Cooksey 0:fb7af294d5d9 2786
Simon Cooksey 0:fb7af294d5d9 2787 ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx,
Simon Cooksey 0:fb7af294d5d9 2788 &n,
Simon Cooksey 0:fb7af294d5d9 2789 &ssl->out_msg[i], 1000,
Simon Cooksey 0:fb7af294d5d9 2790 ssl->conf->f_rng, ssl->conf->p_rng );
Simon Cooksey 0:fb7af294d5d9 2791 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 2792 {
Simon Cooksey 0:fb7af294d5d9 2793 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret );
Simon Cooksey 0:fb7af294d5d9 2794 return( ret );
Simon Cooksey 0:fb7af294d5d9 2795 }
Simon Cooksey 0:fb7af294d5d9 2796
Simon Cooksey 0:fb7af294d5d9 2797 MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q );
Simon Cooksey 0:fb7af294d5d9 2798
Simon Cooksey 0:fb7af294d5d9 2799 if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx,
Simon Cooksey 0:fb7af294d5d9 2800 &ssl->handshake->pmslen,
Simon Cooksey 0:fb7af294d5d9 2801 ssl->handshake->premaster,
Simon Cooksey 0:fb7af294d5d9 2802 MBEDTLS_MPI_MAX_SIZE,
Simon Cooksey 0:fb7af294d5d9 2803 ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2804 {
Simon Cooksey 0:fb7af294d5d9 2805 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret );
Simon Cooksey 0:fb7af294d5d9 2806 return( ret );
Simon Cooksey 0:fb7af294d5d9 2807 }
Simon Cooksey 0:fb7af294d5d9 2808
Simon Cooksey 0:fb7af294d5d9 2809 MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z );
Simon Cooksey 0:fb7af294d5d9 2810 }
Simon Cooksey 0:fb7af294d5d9 2811 else
Simon Cooksey 0:fb7af294d5d9 2812 #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 2813 MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 2814 MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
Simon Cooksey 0:fb7af294d5d9 2815 MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2816 #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2817 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
Simon Cooksey 0:fb7af294d5d9 2818 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
Simon Cooksey 0:fb7af294d5d9 2819 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
Simon Cooksey 0:fb7af294d5d9 2820 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
Simon Cooksey 0:fb7af294d5d9 2821 {
Simon Cooksey 0:fb7af294d5d9 2822 /*
Simon Cooksey 0:fb7af294d5d9 2823 * opaque psk_identity<0..2^16-1>;
Simon Cooksey 0:fb7af294d5d9 2824 */
Simon Cooksey 0:fb7af294d5d9 2825 if( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL )
Simon Cooksey 0:fb7af294d5d9 2826 {
Simon Cooksey 0:fb7af294d5d9 2827 MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for PSK" ) );
Simon Cooksey 0:fb7af294d5d9 2828 return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
Simon Cooksey 0:fb7af294d5d9 2829 }
Simon Cooksey 0:fb7af294d5d9 2830
Simon Cooksey 0:fb7af294d5d9 2831 i = 4;
Simon Cooksey 0:fb7af294d5d9 2832 n = ssl->conf->psk_identity_len;
Simon Cooksey 0:fb7af294d5d9 2833
Simon Cooksey 0:fb7af294d5d9 2834 if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN )
Simon Cooksey 0:fb7af294d5d9 2835 {
Simon Cooksey 0:fb7af294d5d9 2836 MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity too long or "
Simon Cooksey 0:fb7af294d5d9 2837 "SSL buffer too short" ) );
Simon Cooksey 0:fb7af294d5d9 2838 return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
Simon Cooksey 0:fb7af294d5d9 2839 }
Simon Cooksey 0:fb7af294d5d9 2840
Simon Cooksey 0:fb7af294d5d9 2841 ssl->out_msg[i++] = (unsigned char)( n >> 8 );
Simon Cooksey 0:fb7af294d5d9 2842 ssl->out_msg[i++] = (unsigned char)( n );
Simon Cooksey 0:fb7af294d5d9 2843
Simon Cooksey 0:fb7af294d5d9 2844 memcpy( ssl->out_msg + i, ssl->conf->psk_identity, ssl->conf->psk_identity_len );
Simon Cooksey 0:fb7af294d5d9 2845 i += ssl->conf->psk_identity_len;
Simon Cooksey 0:fb7af294d5d9 2846
Simon Cooksey 0:fb7af294d5d9 2847 #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2848 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK )
Simon Cooksey 0:fb7af294d5d9 2849 {
Simon Cooksey 0:fb7af294d5d9 2850 n = 0;
Simon Cooksey 0:fb7af294d5d9 2851 }
Simon Cooksey 0:fb7af294d5d9 2852 else
Simon Cooksey 0:fb7af294d5d9 2853 #endif
Simon Cooksey 0:fb7af294d5d9 2854 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2855 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
Simon Cooksey 0:fb7af294d5d9 2856 {
Simon Cooksey 0:fb7af294d5d9 2857 if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 2 ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2858 return( ret );
Simon Cooksey 0:fb7af294d5d9 2859 }
Simon Cooksey 0:fb7af294d5d9 2860 else
Simon Cooksey 0:fb7af294d5d9 2861 #endif
Simon Cooksey 0:fb7af294d5d9 2862 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2863 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK )
Simon Cooksey 0:fb7af294d5d9 2864 {
Simon Cooksey 0:fb7af294d5d9 2865 /*
Simon Cooksey 0:fb7af294d5d9 2866 * ClientDiffieHellmanPublic public (DHM send G^X mod P)
Simon Cooksey 0:fb7af294d5d9 2867 */
Simon Cooksey 0:fb7af294d5d9 2868 n = ssl->handshake->dhm_ctx.len;
Simon Cooksey 0:fb7af294d5d9 2869
Simon Cooksey 0:fb7af294d5d9 2870 if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN )
Simon Cooksey 0:fb7af294d5d9 2871 {
Simon Cooksey 0:fb7af294d5d9 2872 MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity or DHM size too long"
Simon Cooksey 0:fb7af294d5d9 2873 " or SSL buffer too short" ) );
Simon Cooksey 0:fb7af294d5d9 2874 return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
Simon Cooksey 0:fb7af294d5d9 2875 }
Simon Cooksey 0:fb7af294d5d9 2876
Simon Cooksey 0:fb7af294d5d9 2877 ssl->out_msg[i++] = (unsigned char)( n >> 8 );
Simon Cooksey 0:fb7af294d5d9 2878 ssl->out_msg[i++] = (unsigned char)( n );
Simon Cooksey 0:fb7af294d5d9 2879
Simon Cooksey 0:fb7af294d5d9 2880 ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx,
Simon Cooksey 0:fb7af294d5d9 2881 (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ),
Simon Cooksey 0:fb7af294d5d9 2882 &ssl->out_msg[i], n,
Simon Cooksey 0:fb7af294d5d9 2883 ssl->conf->f_rng, ssl->conf->p_rng );
Simon Cooksey 0:fb7af294d5d9 2884 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 2885 {
Simon Cooksey 0:fb7af294d5d9 2886 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret );
Simon Cooksey 0:fb7af294d5d9 2887 return( ret );
Simon Cooksey 0:fb7af294d5d9 2888 }
Simon Cooksey 0:fb7af294d5d9 2889 }
Simon Cooksey 0:fb7af294d5d9 2890 else
Simon Cooksey 0:fb7af294d5d9 2891 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2892 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2893 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
Simon Cooksey 0:fb7af294d5d9 2894 {
Simon Cooksey 0:fb7af294d5d9 2895 /*
Simon Cooksey 0:fb7af294d5d9 2896 * ClientECDiffieHellmanPublic public;
Simon Cooksey 0:fb7af294d5d9 2897 */
Simon Cooksey 0:fb7af294d5d9 2898 ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, &n,
Simon Cooksey 0:fb7af294d5d9 2899 &ssl->out_msg[i], MBEDTLS_SSL_MAX_CONTENT_LEN - i,
Simon Cooksey 0:fb7af294d5d9 2900 ssl->conf->f_rng, ssl->conf->p_rng );
Simon Cooksey 0:fb7af294d5d9 2901 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 2902 {
Simon Cooksey 0:fb7af294d5d9 2903 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret );
Simon Cooksey 0:fb7af294d5d9 2904 return( ret );
Simon Cooksey 0:fb7af294d5d9 2905 }
Simon Cooksey 0:fb7af294d5d9 2906
Simon Cooksey 0:fb7af294d5d9 2907 MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q );
Simon Cooksey 0:fb7af294d5d9 2908 }
Simon Cooksey 0:fb7af294d5d9 2909 else
Simon Cooksey 0:fb7af294d5d9 2910 #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2911 {
Simon Cooksey 0:fb7af294d5d9 2912 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
Simon Cooksey 0:fb7af294d5d9 2913 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
Simon Cooksey 0:fb7af294d5d9 2914 }
Simon Cooksey 0:fb7af294d5d9 2915
Simon Cooksey 0:fb7af294d5d9 2916 if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl,
Simon Cooksey 0:fb7af294d5d9 2917 ciphersuite_info->key_exchange ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2918 {
Simon Cooksey 0:fb7af294d5d9 2919 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret );
Simon Cooksey 0:fb7af294d5d9 2920 return( ret );
Simon Cooksey 0:fb7af294d5d9 2921 }
Simon Cooksey 0:fb7af294d5d9 2922 }
Simon Cooksey 0:fb7af294d5d9 2923 else
Simon Cooksey 0:fb7af294d5d9 2924 #endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2925 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2926 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA )
Simon Cooksey 0:fb7af294d5d9 2927 {
Simon Cooksey 0:fb7af294d5d9 2928 i = 4;
Simon Cooksey 0:fb7af294d5d9 2929 if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 0 ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2930 return( ret );
Simon Cooksey 0:fb7af294d5d9 2931 }
Simon Cooksey 0:fb7af294d5d9 2932 else
Simon Cooksey 0:fb7af294d5d9 2933 #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2934 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2935 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
Simon Cooksey 0:fb7af294d5d9 2936 {
Simon Cooksey 0:fb7af294d5d9 2937 i = 4;
Simon Cooksey 0:fb7af294d5d9 2938
Simon Cooksey 0:fb7af294d5d9 2939 ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx,
Simon Cooksey 0:fb7af294d5d9 2940 ssl->out_msg + i, MBEDTLS_SSL_MAX_CONTENT_LEN - i, &n,
Simon Cooksey 0:fb7af294d5d9 2941 ssl->conf->f_rng, ssl->conf->p_rng );
Simon Cooksey 0:fb7af294d5d9 2942 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 2943 {
Simon Cooksey 0:fb7af294d5d9 2944 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret );
Simon Cooksey 0:fb7af294d5d9 2945 return( ret );
Simon Cooksey 0:fb7af294d5d9 2946 }
Simon Cooksey 0:fb7af294d5d9 2947
Simon Cooksey 0:fb7af294d5d9 2948 ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx,
Simon Cooksey 0:fb7af294d5d9 2949 ssl->handshake->premaster, 32, &ssl->handshake->pmslen,
Simon Cooksey 0:fb7af294d5d9 2950 ssl->conf->f_rng, ssl->conf->p_rng );
Simon Cooksey 0:fb7af294d5d9 2951 if( ret != 0 )
Simon Cooksey 0:fb7af294d5d9 2952 {
Simon Cooksey 0:fb7af294d5d9 2953 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret );
Simon Cooksey 0:fb7af294d5d9 2954 return( ret );
Simon Cooksey 0:fb7af294d5d9 2955 }
Simon Cooksey 0:fb7af294d5d9 2956 }
Simon Cooksey 0:fb7af294d5d9 2957 else
Simon Cooksey 0:fb7af294d5d9 2958 #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */
Simon Cooksey 0:fb7af294d5d9 2959 {
Simon Cooksey 0:fb7af294d5d9 2960 ((void) ciphersuite_info);
Simon Cooksey 0:fb7af294d5d9 2961 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
Simon Cooksey 0:fb7af294d5d9 2962 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
Simon Cooksey 0:fb7af294d5d9 2963 }
Simon Cooksey 0:fb7af294d5d9 2964
Simon Cooksey 0:fb7af294d5d9 2965 ssl->out_msglen = i + n;
Simon Cooksey 0:fb7af294d5d9 2966 ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
Simon Cooksey 0:fb7af294d5d9 2967 ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE;
Simon Cooksey 0:fb7af294d5d9 2968
Simon Cooksey 0:fb7af294d5d9 2969 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 2970
Simon Cooksey 0:fb7af294d5d9 2971 if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2972 {
Simon Cooksey 0:fb7af294d5d9 2973 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
Simon Cooksey 0:fb7af294d5d9 2974 return( ret );
Simon Cooksey 0:fb7af294d5d9 2975 }
Simon Cooksey 0:fb7af294d5d9 2976
Simon Cooksey 0:fb7af294d5d9 2977 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client key exchange" ) );
Simon Cooksey 0:fb7af294d5d9 2978
Simon Cooksey 0:fb7af294d5d9 2979 return( 0 );
Simon Cooksey 0:fb7af294d5d9 2980 }
Simon Cooksey 0:fb7af294d5d9 2981
Simon Cooksey 0:fb7af294d5d9 2982 #if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \
Simon Cooksey 0:fb7af294d5d9 2983 !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \
Simon Cooksey 0:fb7af294d5d9 2984 !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \
Simon Cooksey 0:fb7af294d5d9 2985 !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
Simon Cooksey 0:fb7af294d5d9 2986 !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \
Simon Cooksey 0:fb7af294d5d9 2987 !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 2988 static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 2989 {
Simon Cooksey 0:fb7af294d5d9 2990 const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
Simon Cooksey 0:fb7af294d5d9 2991 int ret;
Simon Cooksey 0:fb7af294d5d9 2992
Simon Cooksey 0:fb7af294d5d9 2993 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
Simon Cooksey 0:fb7af294d5d9 2994
Simon Cooksey 0:fb7af294d5d9 2995 if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 2996 {
Simon Cooksey 0:fb7af294d5d9 2997 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
Simon Cooksey 0:fb7af294d5d9 2998 return( ret );
Simon Cooksey 0:fb7af294d5d9 2999 }
Simon Cooksey 0:fb7af294d5d9 3000
Simon Cooksey 0:fb7af294d5d9 3001 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
Simon Cooksey 0:fb7af294d5d9 3002 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
Simon Cooksey 0:fb7af294d5d9 3003 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
Simon Cooksey 0:fb7af294d5d9 3004 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
Simon Cooksey 0:fb7af294d5d9 3005 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
Simon Cooksey 0:fb7af294d5d9 3006 {
Simon Cooksey 0:fb7af294d5d9 3007 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) );
Simon Cooksey 0:fb7af294d5d9 3008 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 3009 return( 0 );
Simon Cooksey 0:fb7af294d5d9 3010 }
Simon Cooksey 0:fb7af294d5d9 3011
Simon Cooksey 0:fb7af294d5d9 3012 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
Simon Cooksey 0:fb7af294d5d9 3013 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
Simon Cooksey 0:fb7af294d5d9 3014 }
Simon Cooksey 0:fb7af294d5d9 3015 #else
Simon Cooksey 0:fb7af294d5d9 3016 static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 3017 {
Simon Cooksey 0:fb7af294d5d9 3018 int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
Simon Cooksey 0:fb7af294d5d9 3019 const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
Simon Cooksey 0:fb7af294d5d9 3020 size_t n = 0, offset = 0;
Simon Cooksey 0:fb7af294d5d9 3021 unsigned char hash[48];
Simon Cooksey 0:fb7af294d5d9 3022 unsigned char *hash_start = hash;
Simon Cooksey 0:fb7af294d5d9 3023 mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE;
Simon Cooksey 0:fb7af294d5d9 3024 unsigned int hashlen;
Simon Cooksey 0:fb7af294d5d9 3025
Simon Cooksey 0:fb7af294d5d9 3026 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
Simon Cooksey 0:fb7af294d5d9 3027
Simon Cooksey 0:fb7af294d5d9 3028 if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3029 {
Simon Cooksey 0:fb7af294d5d9 3030 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
Simon Cooksey 0:fb7af294d5d9 3031 return( ret );
Simon Cooksey 0:fb7af294d5d9 3032 }
Simon Cooksey 0:fb7af294d5d9 3033
Simon Cooksey 0:fb7af294d5d9 3034 if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
Simon Cooksey 0:fb7af294d5d9 3035 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
Simon Cooksey 0:fb7af294d5d9 3036 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
Simon Cooksey 0:fb7af294d5d9 3037 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
Simon Cooksey 0:fb7af294d5d9 3038 ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
Simon Cooksey 0:fb7af294d5d9 3039 {
Simon Cooksey 0:fb7af294d5d9 3040 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) );
Simon Cooksey 0:fb7af294d5d9 3041 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 3042 return( 0 );
Simon Cooksey 0:fb7af294d5d9 3043 }
Simon Cooksey 0:fb7af294d5d9 3044
Simon Cooksey 0:fb7af294d5d9 3045 if( ssl->client_auth == 0 || mbedtls_ssl_own_cert( ssl ) == NULL )
Simon Cooksey 0:fb7af294d5d9 3046 {
Simon Cooksey 0:fb7af294d5d9 3047 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) );
Simon Cooksey 0:fb7af294d5d9 3048 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 3049 return( 0 );
Simon Cooksey 0:fb7af294d5d9 3050 }
Simon Cooksey 0:fb7af294d5d9 3051
Simon Cooksey 0:fb7af294d5d9 3052 if( mbedtls_ssl_own_key( ssl ) == NULL )
Simon Cooksey 0:fb7af294d5d9 3053 {
Simon Cooksey 0:fb7af294d5d9 3054 MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for certificate" ) );
Simon Cooksey 0:fb7af294d5d9 3055 return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
Simon Cooksey 0:fb7af294d5d9 3056 }
Simon Cooksey 0:fb7af294d5d9 3057
Simon Cooksey 0:fb7af294d5d9 3058 /*
Simon Cooksey 0:fb7af294d5d9 3059 * Make an RSA signature of the handshake digests
Simon Cooksey 0:fb7af294d5d9 3060 */
Simon Cooksey 0:fb7af294d5d9 3061 ssl->handshake->calc_verify( ssl, hash );
Simon Cooksey 0:fb7af294d5d9 3062
Simon Cooksey 0:fb7af294d5d9 3063 #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
Simon Cooksey 0:fb7af294d5d9 3064 defined(MBEDTLS_SSL_PROTO_TLS1_1)
Simon Cooksey 0:fb7af294d5d9 3065 if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 )
Simon Cooksey 0:fb7af294d5d9 3066 {
Simon Cooksey 0:fb7af294d5d9 3067 /*
Simon Cooksey 0:fb7af294d5d9 3068 * digitally-signed struct {
Simon Cooksey 0:fb7af294d5d9 3069 * opaque md5_hash[16];
Simon Cooksey 0:fb7af294d5d9 3070 * opaque sha_hash[20];
Simon Cooksey 0:fb7af294d5d9 3071 * };
Simon Cooksey 0:fb7af294d5d9 3072 *
Simon Cooksey 0:fb7af294d5d9 3073 * md5_hash
Simon Cooksey 0:fb7af294d5d9 3074 * MD5(handshake_messages);
Simon Cooksey 0:fb7af294d5d9 3075 *
Simon Cooksey 0:fb7af294d5d9 3076 * sha_hash
Simon Cooksey 0:fb7af294d5d9 3077 * SHA(handshake_messages);
Simon Cooksey 0:fb7af294d5d9 3078 */
Simon Cooksey 0:fb7af294d5d9 3079 hashlen = 36;
Simon Cooksey 0:fb7af294d5d9 3080 md_alg = MBEDTLS_MD_NONE;
Simon Cooksey 0:fb7af294d5d9 3081
Simon Cooksey 0:fb7af294d5d9 3082 /*
Simon Cooksey 0:fb7af294d5d9 3083 * For ECDSA, default hash is SHA-1 only
Simon Cooksey 0:fb7af294d5d9 3084 */
Simon Cooksey 0:fb7af294d5d9 3085 if( mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECDSA ) )
Simon Cooksey 0:fb7af294d5d9 3086 {
Simon Cooksey 0:fb7af294d5d9 3087 hash_start += 16;
Simon Cooksey 0:fb7af294d5d9 3088 hashlen -= 16;
Simon Cooksey 0:fb7af294d5d9 3089 md_alg = MBEDTLS_MD_SHA1;
Simon Cooksey 0:fb7af294d5d9 3090 }
Simon Cooksey 0:fb7af294d5d9 3091 }
Simon Cooksey 0:fb7af294d5d9 3092 else
Simon Cooksey 0:fb7af294d5d9 3093 #endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \
Simon Cooksey 0:fb7af294d5d9 3094 MBEDTLS_SSL_PROTO_TLS1_1 */
Simon Cooksey 0:fb7af294d5d9 3095 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
Simon Cooksey 0:fb7af294d5d9 3096 if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
Simon Cooksey 0:fb7af294d5d9 3097 {
Simon Cooksey 0:fb7af294d5d9 3098 /*
Simon Cooksey 0:fb7af294d5d9 3099 * digitally-signed struct {
Simon Cooksey 0:fb7af294d5d9 3100 * opaque handshake_messages[handshake_messages_length];
Simon Cooksey 0:fb7af294d5d9 3101 * };
Simon Cooksey 0:fb7af294d5d9 3102 *
Simon Cooksey 0:fb7af294d5d9 3103 * Taking shortcut here. We assume that the server always allows the
Simon Cooksey 0:fb7af294d5d9 3104 * PRF Hash function and has sent it in the allowed signature
Simon Cooksey 0:fb7af294d5d9 3105 * algorithms list received in the Certificate Request message.
Simon Cooksey 0:fb7af294d5d9 3106 *
Simon Cooksey 0:fb7af294d5d9 3107 * Until we encounter a server that does not, we will take this
Simon Cooksey 0:fb7af294d5d9 3108 * shortcut.
Simon Cooksey 0:fb7af294d5d9 3109 *
Simon Cooksey 0:fb7af294d5d9 3110 * Reason: Otherwise we should have running hashes for SHA512 and SHA224
Simon Cooksey 0:fb7af294d5d9 3111 * in order to satisfy 'weird' needs from the server side.
Simon Cooksey 0:fb7af294d5d9 3112 */
Simon Cooksey 0:fb7af294d5d9 3113 if( ssl->transform_negotiate->ciphersuite_info->mac ==
Simon Cooksey 0:fb7af294d5d9 3114 MBEDTLS_MD_SHA384 )
Simon Cooksey 0:fb7af294d5d9 3115 {
Simon Cooksey 0:fb7af294d5d9 3116 md_alg = MBEDTLS_MD_SHA384;
Simon Cooksey 0:fb7af294d5d9 3117 ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA384;
Simon Cooksey 0:fb7af294d5d9 3118 }
Simon Cooksey 0:fb7af294d5d9 3119 else
Simon Cooksey 0:fb7af294d5d9 3120 {
Simon Cooksey 0:fb7af294d5d9 3121 md_alg = MBEDTLS_MD_SHA256;
Simon Cooksey 0:fb7af294d5d9 3122 ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA256;
Simon Cooksey 0:fb7af294d5d9 3123 }
Simon Cooksey 0:fb7af294d5d9 3124 ssl->out_msg[5] = mbedtls_ssl_sig_from_pk( mbedtls_ssl_own_key( ssl ) );
Simon Cooksey 0:fb7af294d5d9 3125
Simon Cooksey 0:fb7af294d5d9 3126 /* Info from md_alg will be used instead */
Simon Cooksey 0:fb7af294d5d9 3127 hashlen = 0;
Simon Cooksey 0:fb7af294d5d9 3128 offset = 2;
Simon Cooksey 0:fb7af294d5d9 3129 }
Simon Cooksey 0:fb7af294d5d9 3130 else
Simon Cooksey 0:fb7af294d5d9 3131 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
Simon Cooksey 0:fb7af294d5d9 3132 {
Simon Cooksey 0:fb7af294d5d9 3133 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
Simon Cooksey 0:fb7af294d5d9 3134 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
Simon Cooksey 0:fb7af294d5d9 3135 }
Simon Cooksey 0:fb7af294d5d9 3136
Simon Cooksey 0:fb7af294d5d9 3137 if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash_start, hashlen,
Simon Cooksey 0:fb7af294d5d9 3138 ssl->out_msg + 6 + offset, &n,
Simon Cooksey 0:fb7af294d5d9 3139 ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3140 {
Simon Cooksey 0:fb7af294d5d9 3141 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret );
Simon Cooksey 0:fb7af294d5d9 3142 return( ret );
Simon Cooksey 0:fb7af294d5d9 3143 }
Simon Cooksey 0:fb7af294d5d9 3144
Simon Cooksey 0:fb7af294d5d9 3145 ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 );
Simon Cooksey 0:fb7af294d5d9 3146 ssl->out_msg[5 + offset] = (unsigned char)( n );
Simon Cooksey 0:fb7af294d5d9 3147
Simon Cooksey 0:fb7af294d5d9 3148 ssl->out_msglen = 6 + n + offset;
Simon Cooksey 0:fb7af294d5d9 3149 ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
Simon Cooksey 0:fb7af294d5d9 3150 ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_VERIFY;
Simon Cooksey 0:fb7af294d5d9 3151
Simon Cooksey 0:fb7af294d5d9 3152 ssl->state++;
Simon Cooksey 0:fb7af294d5d9 3153
Simon Cooksey 0:fb7af294d5d9 3154 if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3155 {
Simon Cooksey 0:fb7af294d5d9 3156 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
Simon Cooksey 0:fb7af294d5d9 3157 return( ret );
Simon Cooksey 0:fb7af294d5d9 3158 }
Simon Cooksey 0:fb7af294d5d9 3159
Simon Cooksey 0:fb7af294d5d9 3160 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate verify" ) );
Simon Cooksey 0:fb7af294d5d9 3161
Simon Cooksey 0:fb7af294d5d9 3162 return( ret );
Simon Cooksey 0:fb7af294d5d9 3163 }
Simon Cooksey 0:fb7af294d5d9 3164 #endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 3165 !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 3166 !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 3167 !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 3168 !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED &&
Simon Cooksey 0:fb7af294d5d9 3169 !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
Simon Cooksey 0:fb7af294d5d9 3170
Simon Cooksey 0:fb7af294d5d9 3171 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
Simon Cooksey 0:fb7af294d5d9 3172 static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 3173 {
Simon Cooksey 0:fb7af294d5d9 3174 int ret;
Simon Cooksey 0:fb7af294d5d9 3175 uint32_t lifetime;
Simon Cooksey 0:fb7af294d5d9 3176 size_t ticket_len;
Simon Cooksey 0:fb7af294d5d9 3177 unsigned char *ticket;
Simon Cooksey 0:fb7af294d5d9 3178 const unsigned char *msg;
Simon Cooksey 0:fb7af294d5d9 3179
Simon Cooksey 0:fb7af294d5d9 3180 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) );
Simon Cooksey 0:fb7af294d5d9 3181
Simon Cooksey 0:fb7af294d5d9 3182 if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3183 {
Simon Cooksey 0:fb7af294d5d9 3184 MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
Simon Cooksey 0:fb7af294d5d9 3185 return( ret );
Simon Cooksey 0:fb7af294d5d9 3186 }
Simon Cooksey 0:fb7af294d5d9 3187
Simon Cooksey 0:fb7af294d5d9 3188 if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
Simon Cooksey 0:fb7af294d5d9 3189 {
Simon Cooksey 0:fb7af294d5d9 3190 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) );
Simon Cooksey 0:fb7af294d5d9 3191 return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
Simon Cooksey 0:fb7af294d5d9 3192 }
Simon Cooksey 0:fb7af294d5d9 3193
Simon Cooksey 0:fb7af294d5d9 3194 /*
Simon Cooksey 0:fb7af294d5d9 3195 * struct {
Simon Cooksey 0:fb7af294d5d9 3196 * uint32 ticket_lifetime_hint;
Simon Cooksey 0:fb7af294d5d9 3197 * opaque ticket<0..2^16-1>;
Simon Cooksey 0:fb7af294d5d9 3198 * } NewSessionTicket;
Simon Cooksey 0:fb7af294d5d9 3199 *
Simon Cooksey 0:fb7af294d5d9 3200 * 0 . 3 ticket_lifetime_hint
Simon Cooksey 0:fb7af294d5d9 3201 * 4 . 5 ticket_len (n)
Simon Cooksey 0:fb7af294d5d9 3202 * 6 . 5+n ticket content
Simon Cooksey 0:fb7af294d5d9 3203 */
Simon Cooksey 0:fb7af294d5d9 3204 if( ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET ||
Simon Cooksey 0:fb7af294d5d9 3205 ssl->in_hslen < 6 + mbedtls_ssl_hs_hdr_len( ssl ) )
Simon Cooksey 0:fb7af294d5d9 3206 {
Simon Cooksey 0:fb7af294d5d9 3207 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) );
Simon Cooksey 0:fb7af294d5d9 3208 return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET );
Simon Cooksey 0:fb7af294d5d9 3209 }
Simon Cooksey 0:fb7af294d5d9 3210
Simon Cooksey 0:fb7af294d5d9 3211 msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
Simon Cooksey 0:fb7af294d5d9 3212
Simon Cooksey 0:fb7af294d5d9 3213 lifetime = ( msg[0] << 24 ) | ( msg[1] << 16 ) |
Simon Cooksey 0:fb7af294d5d9 3214 ( msg[2] << 8 ) | ( msg[3] );
Simon Cooksey 0:fb7af294d5d9 3215
Simon Cooksey 0:fb7af294d5d9 3216 ticket_len = ( msg[4] << 8 ) | ( msg[5] );
Simon Cooksey 0:fb7af294d5d9 3217
Simon Cooksey 0:fb7af294d5d9 3218 if( ticket_len + 6 + mbedtls_ssl_hs_hdr_len( ssl ) != ssl->in_hslen )
Simon Cooksey 0:fb7af294d5d9 3219 {
Simon Cooksey 0:fb7af294d5d9 3220 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) );
Simon Cooksey 0:fb7af294d5d9 3221 return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET );
Simon Cooksey 0:fb7af294d5d9 3222 }
Simon Cooksey 0:fb7af294d5d9 3223
Simon Cooksey 0:fb7af294d5d9 3224 MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", ticket_len ) );
Simon Cooksey 0:fb7af294d5d9 3225
Simon Cooksey 0:fb7af294d5d9 3226 /* We're not waiting for a NewSessionTicket message any more */
Simon Cooksey 0:fb7af294d5d9 3227 ssl->handshake->new_session_ticket = 0;
Simon Cooksey 0:fb7af294d5d9 3228 ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC;
Simon Cooksey 0:fb7af294d5d9 3229
Simon Cooksey 0:fb7af294d5d9 3230 /*
Simon Cooksey 0:fb7af294d5d9 3231 * Zero-length ticket means the server changed his mind and doesn't want
Simon Cooksey 0:fb7af294d5d9 3232 * to send a ticket after all, so just forget it
Simon Cooksey 0:fb7af294d5d9 3233 */
Simon Cooksey 0:fb7af294d5d9 3234 if( ticket_len == 0 )
Simon Cooksey 0:fb7af294d5d9 3235 return( 0 );
Simon Cooksey 0:fb7af294d5d9 3236
Simon Cooksey 0:fb7af294d5d9 3237 mbedtls_zeroize( ssl->session_negotiate->ticket,
Simon Cooksey 0:fb7af294d5d9 3238 ssl->session_negotiate->ticket_len );
Simon Cooksey 0:fb7af294d5d9 3239 mbedtls_free( ssl->session_negotiate->ticket );
Simon Cooksey 0:fb7af294d5d9 3240 ssl->session_negotiate->ticket = NULL;
Simon Cooksey 0:fb7af294d5d9 3241 ssl->session_negotiate->ticket_len = 0;
Simon Cooksey 0:fb7af294d5d9 3242
Simon Cooksey 0:fb7af294d5d9 3243 if( ( ticket = mbedtls_calloc( 1, ticket_len ) ) == NULL )
Simon Cooksey 0:fb7af294d5d9 3244 {
Simon Cooksey 0:fb7af294d5d9 3245 MBEDTLS_SSL_DEBUG_MSG( 1, ( "ticket alloc failed" ) );
Simon Cooksey 0:fb7af294d5d9 3246 return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
Simon Cooksey 0:fb7af294d5d9 3247 }
Simon Cooksey 0:fb7af294d5d9 3248
Simon Cooksey 0:fb7af294d5d9 3249 memcpy( ticket, msg + 6, ticket_len );
Simon Cooksey 0:fb7af294d5d9 3250
Simon Cooksey 0:fb7af294d5d9 3251 ssl->session_negotiate->ticket = ticket;
Simon Cooksey 0:fb7af294d5d9 3252 ssl->session_negotiate->ticket_len = ticket_len;
Simon Cooksey 0:fb7af294d5d9 3253 ssl->session_negotiate->ticket_lifetime = lifetime;
Simon Cooksey 0:fb7af294d5d9 3254
Simon Cooksey 0:fb7af294d5d9 3255 /*
Simon Cooksey 0:fb7af294d5d9 3256 * RFC 5077 section 3.4:
Simon Cooksey 0:fb7af294d5d9 3257 * "If the client receives a session ticket from the server, then it
Simon Cooksey 0:fb7af294d5d9 3258 * discards any Session ID that was sent in the ServerHello."
Simon Cooksey 0:fb7af294d5d9 3259 */
Simon Cooksey 0:fb7af294d5d9 3260 MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket in use, discarding session id" ) );
Simon Cooksey 0:fb7af294d5d9 3261 ssl->session_negotiate->id_len = 0;
Simon Cooksey 0:fb7af294d5d9 3262
Simon Cooksey 0:fb7af294d5d9 3263 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse new session ticket" ) );
Simon Cooksey 0:fb7af294d5d9 3264
Simon Cooksey 0:fb7af294d5d9 3265 return( 0 );
Simon Cooksey 0:fb7af294d5d9 3266 }
Simon Cooksey 0:fb7af294d5d9 3267 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
Simon Cooksey 0:fb7af294d5d9 3268
Simon Cooksey 0:fb7af294d5d9 3269 /*
Simon Cooksey 0:fb7af294d5d9 3270 * SSL handshake -- client side -- single step
Simon Cooksey 0:fb7af294d5d9 3271 */
Simon Cooksey 0:fb7af294d5d9 3272 int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl )
Simon Cooksey 0:fb7af294d5d9 3273 {
Simon Cooksey 0:fb7af294d5d9 3274 int ret = 0;
Simon Cooksey 0:fb7af294d5d9 3275
Simon Cooksey 0:fb7af294d5d9 3276 if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL )
Simon Cooksey 0:fb7af294d5d9 3277 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
Simon Cooksey 0:fb7af294d5d9 3278
Simon Cooksey 0:fb7af294d5d9 3279 MBEDTLS_SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) );
Simon Cooksey 0:fb7af294d5d9 3280
Simon Cooksey 0:fb7af294d5d9 3281 if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3282 return( ret );
Simon Cooksey 0:fb7af294d5d9 3283
Simon Cooksey 0:fb7af294d5d9 3284 #if defined(MBEDTLS_SSL_PROTO_DTLS)
Simon Cooksey 0:fb7af294d5d9 3285 if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
Simon Cooksey 0:fb7af294d5d9 3286 ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
Simon Cooksey 0:fb7af294d5d9 3287 {
Simon Cooksey 0:fb7af294d5d9 3288 if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
Simon Cooksey 0:fb7af294d5d9 3289 return( ret );
Simon Cooksey 0:fb7af294d5d9 3290 }
Simon Cooksey 0:fb7af294d5d9 3291 #endif
Simon Cooksey 0:fb7af294d5d9 3292
Simon Cooksey 0:fb7af294d5d9 3293 /* Change state now, so that it is right in mbedtls_ssl_read_record(), used
Simon Cooksey 0:fb7af294d5d9 3294 * by DTLS for dropping out-of-sequence ChangeCipherSpec records */
Simon Cooksey 0:fb7af294d5d9 3295 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
Simon Cooksey 0:fb7af294d5d9 3296 if( ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC &&
Simon Cooksey 0:fb7af294d5d9 3297 ssl->handshake->new_session_ticket != 0 )
Simon Cooksey 0:fb7af294d5d9 3298 {
Simon Cooksey 0:fb7af294d5d9 3299 ssl->state = MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET;
Simon Cooksey 0:fb7af294d5d9 3300 }
Simon Cooksey 0:fb7af294d5d9 3301 #endif
Simon Cooksey 0:fb7af294d5d9 3302
Simon Cooksey 0:fb7af294d5d9 3303 switch( ssl->state )
Simon Cooksey 0:fb7af294d5d9 3304 {
Simon Cooksey 0:fb7af294d5d9 3305 case MBEDTLS_SSL_HELLO_REQUEST:
Simon Cooksey 0:fb7af294d5d9 3306 ssl->state = MBEDTLS_SSL_CLIENT_HELLO;
Simon Cooksey 0:fb7af294d5d9 3307 break;
Simon Cooksey 0:fb7af294d5d9 3308
Simon Cooksey 0:fb7af294d5d9 3309 /*
Simon Cooksey 0:fb7af294d5d9 3310 * ==> ClientHello
Simon Cooksey 0:fb7af294d5d9 3311 */
Simon Cooksey 0:fb7af294d5d9 3312 case MBEDTLS_SSL_CLIENT_HELLO:
Simon Cooksey 0:fb7af294d5d9 3313 ret = ssl_write_client_hello( ssl );
Simon Cooksey 0:fb7af294d5d9 3314 break;
Simon Cooksey 0:fb7af294d5d9 3315
Simon Cooksey 0:fb7af294d5d9 3316 /*
Simon Cooksey 0:fb7af294d5d9 3317 * <== ServerHello
Simon Cooksey 0:fb7af294d5d9 3318 * Certificate
Simon Cooksey 0:fb7af294d5d9 3319 * ( ServerKeyExchange )
Simon Cooksey 0:fb7af294d5d9 3320 * ( CertificateRequest )
Simon Cooksey 0:fb7af294d5d9 3321 * ServerHelloDone
Simon Cooksey 0:fb7af294d5d9 3322 */
Simon Cooksey 0:fb7af294d5d9 3323 case MBEDTLS_SSL_SERVER_HELLO:
Simon Cooksey 0:fb7af294d5d9 3324 ret = ssl_parse_server_hello( ssl );
Simon Cooksey 0:fb7af294d5d9 3325 break;
Simon Cooksey 0:fb7af294d5d9 3326
Simon Cooksey 0:fb7af294d5d9 3327 case MBEDTLS_SSL_SERVER_CERTIFICATE:
Simon Cooksey 0:fb7af294d5d9 3328 ret = mbedtls_ssl_parse_certificate( ssl );
Simon Cooksey 0:fb7af294d5d9 3329 break;
Simon Cooksey 0:fb7af294d5d9 3330
Simon Cooksey 0:fb7af294d5d9 3331 case MBEDTLS_SSL_SERVER_KEY_EXCHANGE:
Simon Cooksey 0:fb7af294d5d9 3332 ret = ssl_parse_server_key_exchange( ssl );
Simon Cooksey 0:fb7af294d5d9 3333 break;
Simon Cooksey 0:fb7af294d5d9 3334
Simon Cooksey 0:fb7af294d5d9 3335 case MBEDTLS_SSL_CERTIFICATE_REQUEST:
Simon Cooksey 0:fb7af294d5d9 3336 ret = ssl_parse_certificate_request( ssl );
Simon Cooksey 0:fb7af294d5d9 3337 break;
Simon Cooksey 0:fb7af294d5d9 3338
Simon Cooksey 0:fb7af294d5d9 3339 case MBEDTLS_SSL_SERVER_HELLO_DONE:
Simon Cooksey 0:fb7af294d5d9 3340 ret = ssl_parse_server_hello_done( ssl );
Simon Cooksey 0:fb7af294d5d9 3341 break;
Simon Cooksey 0:fb7af294d5d9 3342
Simon Cooksey 0:fb7af294d5d9 3343 /*
Simon Cooksey 0:fb7af294d5d9 3344 * ==> ( Certificate/Alert )
Simon Cooksey 0:fb7af294d5d9 3345 * ClientKeyExchange
Simon Cooksey 0:fb7af294d5d9 3346 * ( CertificateVerify )
Simon Cooksey 0:fb7af294d5d9 3347 * ChangeCipherSpec
Simon Cooksey 0:fb7af294d5d9 3348 * Finished
Simon Cooksey 0:fb7af294d5d9 3349 */
Simon Cooksey 0:fb7af294d5d9 3350 case MBEDTLS_SSL_CLIENT_CERTIFICATE:
Simon Cooksey 0:fb7af294d5d9 3351 ret = mbedtls_ssl_write_certificate( ssl );
Simon Cooksey 0:fb7af294d5d9 3352 break;
Simon Cooksey 0:fb7af294d5d9 3353
Simon Cooksey 0:fb7af294d5d9 3354 case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:
Simon Cooksey 0:fb7af294d5d9 3355 ret = ssl_write_client_key_exchange( ssl );
Simon Cooksey 0:fb7af294d5d9 3356 break;
Simon Cooksey 0:fb7af294d5d9 3357
Simon Cooksey 0:fb7af294d5d9 3358 case MBEDTLS_SSL_CERTIFICATE_VERIFY:
Simon Cooksey 0:fb7af294d5d9 3359 ret = ssl_write_certificate_verify( ssl );
Simon Cooksey 0:fb7af294d5d9 3360 break;
Simon Cooksey 0:fb7af294d5d9 3361
Simon Cooksey 0:fb7af294d5d9 3362 case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC:
Simon Cooksey 0:fb7af294d5d9 3363 ret = mbedtls_ssl_write_change_cipher_spec( ssl );
Simon Cooksey 0:fb7af294d5d9 3364 break;
Simon Cooksey 0:fb7af294d5d9 3365
Simon Cooksey 0:fb7af294d5d9 3366 case MBEDTLS_SSL_CLIENT_FINISHED:
Simon Cooksey 0:fb7af294d5d9 3367 ret = mbedtls_ssl_write_finished( ssl );
Simon Cooksey 0:fb7af294d5d9 3368 break;
Simon Cooksey 0:fb7af294d5d9 3369
Simon Cooksey 0:fb7af294d5d9 3370 /*
Simon Cooksey 0:fb7af294d5d9 3371 * <== ( NewSessionTicket )
Simon Cooksey 0:fb7af294d5d9 3372 * ChangeCipherSpec
Simon Cooksey 0:fb7af294d5d9 3373 * Finished
Simon Cooksey 0:fb7af294d5d9 3374 */
Simon Cooksey 0:fb7af294d5d9 3375 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
Simon Cooksey 0:fb7af294d5d9 3376 case MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET:
Simon Cooksey 0:fb7af294d5d9 3377 ret = ssl_parse_new_session_ticket( ssl );
Simon Cooksey 0:fb7af294d5d9 3378 break;
Simon Cooksey 0:fb7af294d5d9 3379 #endif
Simon Cooksey 0:fb7af294d5d9 3380
Simon Cooksey 0:fb7af294d5d9 3381 case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC:
Simon Cooksey 0:fb7af294d5d9 3382 ret = mbedtls_ssl_parse_change_cipher_spec( ssl );
Simon Cooksey 0:fb7af294d5d9 3383 break;
Simon Cooksey 0:fb7af294d5d9 3384
Simon Cooksey 0:fb7af294d5d9 3385 case MBEDTLS_SSL_SERVER_FINISHED:
Simon Cooksey 0:fb7af294d5d9 3386 ret = mbedtls_ssl_parse_finished( ssl );
Simon Cooksey 0:fb7af294d5d9 3387 break;
Simon Cooksey 0:fb7af294d5d9 3388
Simon Cooksey 0:fb7af294d5d9 3389 case MBEDTLS_SSL_FLUSH_BUFFERS:
Simon Cooksey 0:fb7af294d5d9 3390 MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
Simon Cooksey 0:fb7af294d5d9 3391 ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP;
Simon Cooksey 0:fb7af294d5d9 3392 break;
Simon Cooksey 0:fb7af294d5d9 3393
Simon Cooksey 0:fb7af294d5d9 3394 case MBEDTLS_SSL_HANDSHAKE_WRAPUP:
Simon Cooksey 0:fb7af294d5d9 3395 mbedtls_ssl_handshake_wrapup( ssl );
Simon Cooksey 0:fb7af294d5d9 3396 break;
Simon Cooksey 0:fb7af294d5d9 3397
Simon Cooksey 0:fb7af294d5d9 3398 default:
Simon Cooksey 0:fb7af294d5d9 3399 MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
Simon Cooksey 0:fb7af294d5d9 3400 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
Simon Cooksey 0:fb7af294d5d9 3401 }
Simon Cooksey 0:fb7af294d5d9 3402
Simon Cooksey 0:fb7af294d5d9 3403 return( ret );
Simon Cooksey 0:fb7af294d5d9 3404 }
Simon Cooksey 0:fb7af294d5d9 3405 #endif /* MBEDTLS_SSL_CLI_C */