mbed os with nrf51 internal bandgap enabled to read battery level

Dependents:   BLE_file_test BLE_Blink ExternalEncoder

Committer:
elessair
Date:
Sun Oct 23 15:10:02 2016 +0000
Revision:
0:f269e3021894
Initial commit

Who changed what in which revision?

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