ssl_cli.c 97.8 KB
Newer Older
1 2 3
/*
 *  SSLv3/TLSv1 client-side functions
 *
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
4
 *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
Paul Bakker's avatar
Paul Bakker committed
5
 *
6
 *  This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker's avatar
Paul Bakker committed
7
 *
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
23
#if !defined(MBEDTLS_CONFIG_FILE)
24
#include "mbedtls/config.h"
25
#else
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
26
#include MBEDTLS_CONFIG_FILE
27
#endif
28

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
29
#if defined(MBEDTLS_SSL_CLI_C)
30

31 32
#include "mbedtls/debug.h"
#include "mbedtls/ssl.h"
33
#include "mbedtls/ssl_internal.h"
34

35 36
#include <string.h>

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
37
#if defined(MBEDTLS_PLATFORM_C)
38
#include "mbedtls/platform.h"
39
#else
40
#include <stdlib.h>
41
#define mbedtls_calloc    calloc
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
42
#define mbedtls_free       free
43 44
#endif

45
#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
46 47 48 49 50 51
#include <basetsd.h>
typedef UINT32 uint32_t;
#else
#include <inttypes.h>
#endif

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
52
#if defined(MBEDTLS_HAVE_TIME)
53
#include <time.h>
54
#endif
55

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
56
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
57
/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
58
static void mbedtls_zeroize( void *v, size_t n ) {
59 60 61 62
    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
}
#endif

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
63 64
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl,
65 66
                                    unsigned char *buf,
                                    size_t *olen )
67
{
68
    unsigned char *p = buf;
69
    size_t hostname_len;
70 71 72

    *olen = 0;

73
    if( ssl->hostname == NULL )
74 75
        return;

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
76
    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding server name extension: %s",
77 78
                   ssl->hostname ) );

79 80
    hostname_len = strlen( ssl->hostname );

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
    /*
     * struct {
     *     NameType name_type;
     *     select (name_type) {
     *         case host_name: HostName;
     *     } name;
     * } ServerName;
     *
     * enum {
     *     host_name(0), (255)
     * } NameType;
     *
     * opaque HostName<1..2^16-1>;
     *
     * struct {
     *     ServerName server_name_list<1..2^16-1>
     * } ServerNameList;
     */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
99 100
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME >> 8 ) & 0xFF );
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME      ) & 0xFF );
101

102 103
    *p++ = (unsigned char)( ( (hostname_len + 5) >> 8 ) & 0xFF );
    *p++ = (unsigned char)( ( (hostname_len + 5)      ) & 0xFF );
104

105 106
    *p++ = (unsigned char)( ( (hostname_len + 3) >> 8 ) & 0xFF );
    *p++ = (unsigned char)( ( (hostname_len + 3)      ) & 0xFF );
107

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
108
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) & 0xFF );
109 110
    *p++ = (unsigned char)( ( hostname_len >> 8 ) & 0xFF );
    *p++ = (unsigned char)( ( hostname_len      ) & 0xFF );
111

112
    memcpy( p, ssl->hostname, hostname_len );
113

114
    *olen = hostname_len + 9;
115
}
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
116
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
117

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
118 119
#if defined(MBEDTLS_SSL_RENEGOTIATION)
static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl,
120 121 122 123 124 125 126
                                         unsigned char *buf,
                                         size_t *olen )
{
    unsigned char *p = buf;

    *olen = 0;

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
127
    if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
128 129
        return;

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
130
    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding renegotiation extension" ) );
131 132 133 134

    /*
     * Secure renegotiation
     */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
135 136
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF );
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO      ) & 0xFF );
137 138 139 140 141 142 143 144 145

    *p++ = 0x00;
    *p++ = ( ssl->verify_data_len + 1 ) & 0xFF;
    *p++ = ssl->verify_data_len & 0xFF;

    memcpy( p, ssl->own_verify_data, ssl->verify_data_len );

    *olen = 5 + ssl->verify_data_len;
}
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
146
#endif /* MBEDTLS_SSL_RENEGOTIATION */
147

148 149 150
/*
 * Only if we handle at least one key exchange that needs signatures.
 */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
151 152 153
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
    defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl,
154 155 156 157
                                                unsigned char *buf,
                                                size_t *olen )
{
    unsigned char *p = buf;
158
    size_t sig_alg_len = 0;
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
159
#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C)
160 161
    unsigned char *sig_alg_list = buf + 6;
#endif
162 163 164

    *olen = 0;

165
    if( ssl->conf->max_minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 )
166 167
        return;

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
168
    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding signature_algorithms extension" ) );
169 170 171 172

    /*
     * Prepare signature_algorithms extension (TLS 1.2)
     */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
173 174 175 176 177 178
#if defined(MBEDTLS_RSA_C)
#if defined(MBEDTLS_SHA512_C)
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_SHA512;
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA;
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_SHA384;
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA;
179
#endif
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
180 181 182 183 184
#if defined(MBEDTLS_SHA256_C)
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_SHA256;
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA;
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_SHA224;
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA;
185
#endif
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
186 187 188
#if defined(MBEDTLS_SHA1_C)
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_SHA1;
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA;
189
#endif
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
190 191 192
#if defined(MBEDTLS_MD5_C)
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_MD5;
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA;
193
#endif
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
194 195 196 197 198 199 200
#endif /* MBEDTLS_RSA_C */
#if defined(MBEDTLS_ECDSA_C)
#if defined(MBEDTLS_SHA512_C)
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_SHA512;
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA;
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_SHA384;
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA;
201
#endif
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
202 203 204 205 206
#if defined(MBEDTLS_SHA256_C)
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_SHA256;
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA;
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_SHA224;
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA;
207
#endif
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
208 209 210
#if defined(MBEDTLS_SHA1_C)
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_SHA1;
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA;
211
#endif
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
212 213 214
#if defined(MBEDTLS_MD5_C)
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_HASH_MD5;
    sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA;
215
#endif
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
216
#endif /* MBEDTLS_ECDSA_C */
217 218 219

    /*
     * enum {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
220 221
     *     none(0), mbedtls_md5(1), mbedtls_sha1(2), sha224(3), mbedtls_sha256(4), sha384(5),
     *     mbedtls_sha512(6), (255)
222 223 224 225 226 227 228 229 230 231 232 233 234
     * } HashAlgorithm;
     *
     * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
     *   SignatureAlgorithm;
     *
     * struct {
     *     HashAlgorithm hash;
     *     SignatureAlgorithm signature;
     * } SignatureAndHashAlgorithm;
     *
     * SignatureAndHashAlgorithm
     *   supported_signature_algorithms<2..2^16-2>;
     */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
235 236
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG >> 8 ) & 0xFF );
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG      ) & 0xFF );
237 238 239 240 241 242 243 244 245

    *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) >> 8 ) & 0xFF );
    *p++ = (unsigned char)( ( ( sig_alg_len + 2 )      ) & 0xFF );

    *p++ = (unsigned char)( ( sig_alg_len >> 8 ) & 0xFF );
    *p++ = (unsigned char)( ( sig_alg_len      ) & 0xFF );

    *olen = 6 + sig_alg_len;
}
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
246 247
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 &&
          MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */
248

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
249 250
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)
static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl,
251 252 253 254
                                                     unsigned char *buf,
                                                     size_t *olen )
{
    unsigned char *p = buf;
255
    unsigned char *elliptic_curve_list = p + 6;
256
    size_t elliptic_curve_len = 0;
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
257 258 259
    const mbedtls_ecp_curve_info *info;
#if defined(MBEDTLS_SSL_SET_CURVES)
    const mbedtls_ecp_group_id *grp_id;
260 261
#else
    ((void) ssl);
262
#endif
263 264 265

    *olen = 0;

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
266
    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_elliptic_curves extension" ) );
267

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
268
#if defined(MBEDTLS_SSL_SET_CURVES)
269
    for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ )
270
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
271
        info = mbedtls_ecp_curve_info_from_grp_id( *grp_id );
272
#else
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
273
    for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ )
274
    {
275 276 277 278
#endif

        elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8;
        elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF;
279
    }
280 281 282

    if( elliptic_curve_len == 0 )
        return;
283

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
284 285
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES >> 8 ) & 0xFF );
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES      ) & 0xFF );
286 287 288 289 290 291 292 293 294 295

    *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) >> 8 ) & 0xFF );
    *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 )      ) & 0xFF );

    *p++ = (unsigned char)( ( ( elliptic_curve_len     ) >> 8 ) & 0xFF );
    *p++ = (unsigned char)( ( ( elliptic_curve_len     )      ) & 0xFF );

    *olen = 6 + elliptic_curve_len;
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
296
static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl,
297 298 299 300
                                                   unsigned char *buf,
                                                   size_t *olen )
{
    unsigned char *p = buf;
301
    ((void) ssl);
302 303 304

    *olen = 0;

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
305
    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_point_formats extension" ) );
306

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
307 308
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF );
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS      ) & 0xFF );
309 310 311

    *p++ = 0x00;
    *p++ = 2;
312 313

    *p++ = 1;
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
314
    *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED;
315

316
    *olen = 6;
317
}
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
318
#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */
319

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
320 321
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl,
322 323 324 325 326
                                               unsigned char *buf,
                                               size_t *olen )
{
    unsigned char *p = buf;

327
    if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) {
328 329 330 331
        *olen = 0;
        return;
    }

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
332
    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding max_fragment_length extension" ) );
333

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
334 335
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF );
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH      ) & 0xFF );
336 337 338 339

    *p++ = 0x00;
    *p++ = 1;

340
    *p++ = ssl->conf->mfl_code;
341 342 343

    *olen = 5;
}
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
344
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
345

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
346 347
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl,
348 349 350 351
                                          unsigned char *buf, size_t *olen )
{
    unsigned char *p = buf;

352
    if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED )
353 354 355 356 357
    {
        *olen = 0;
        return;
    }

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
358
    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding truncated_hmac extension" ) );
359

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
360 361
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF );
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC      ) & 0xFF );
362 363 364 365 366 367

    *p++ = 0x00;
    *p++ = 0x00;

    *olen = 4;
}
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
368
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
369

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
370 371
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
372 373 374 375
                                       unsigned char *buf, size_t *olen )
{
    unsigned char *p = buf;

376 377
    if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED ||
        ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
378 379 380 381 382
    {
        *olen = 0;
        return;
    }

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
383
    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding encrypt_then_mac "
384 385
                        "extension" ) );

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
386 387
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF );
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC      ) & 0xFF );
388 389 390 391 392 393

    *p++ = 0x00;
    *p++ = 0x00;

    *olen = 4;
}
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
394
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
395

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
396 397
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl,
398 399 400 401
                                       unsigned char *buf, size_t *olen )
{
    unsigned char *p = buf;

402 403
    if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED ||
        ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
404 405 406 407 408
    {
        *olen = 0;
        return;
    }

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
409
    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding extended_master_secret "
410 411
                        "extension" ) );

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
412 413
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF );
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET      ) & 0xFF );
414 415 416 417 418 419

    *p++ = 0x00;
    *p++ = 0x00;

    *olen = 4;
}
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
420
#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
421

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
422 423
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl,
424 425 426 427 428
                                          unsigned char *buf, size_t *olen )
{
    unsigned char *p = buf;
    size_t tlen = ssl->session_negotiate->ticket_len;

429
    if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED )
430 431 432 433 434
    {
        *olen = 0;
        return;
    }

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
435
    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding session ticket extension" ) );
436

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
437 438
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF );
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET      ) & 0xFF );
439 440 441 442 443 444 445 446 447 448 449 450

    *p++ = (unsigned char)( ( tlen >> 8 ) & 0xFF );
    *p++ = (unsigned char)( ( tlen      ) & 0xFF );

    *olen = 4;

    if( ssl->session_negotiate->ticket == NULL ||
        ssl->session_negotiate->ticket_len == 0 )
    {
        return;
    }

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
451
    MBEDTLS_SSL_DEBUG_MSG( 3, ( "sending session ticket of length %d", tlen ) );
452 453 454 455 456

    memcpy( p, ssl->session_negotiate->ticket, tlen );

    *olen += tlen;
}
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
457
#endif /* MBEDTLS_SSL_SESSION_TICKETS */
458

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
459 460
#if defined(MBEDTLS_SSL_ALPN)
static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl,
461 462 463 464 465
                                unsigned char *buf, size_t *olen )
{
    unsigned char *p = buf;
    const char **cur;

466
    if( ssl->conf->alpn_list == NULL )
467 468 469 470 471
    {
        *olen = 0;
        return;
    }

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
472
    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) );
473

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
474 475
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF );
    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN      ) & 0xFF );
476 477 478 479 480 481 482 483 484 485 486 487

    /*
     * opaque ProtocolName<1..2^8-1>;
     *
     * struct {
     *     ProtocolName protocol_name_list<2..2^16-1>
     * } ProtocolNameList;
     */

    /* Skip writing extension and list length for now */
    p += 4;

488
    for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ )
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
    {
        *p = (unsigned char)( strlen( *cur ) & 0xFF );
        memcpy( p + 1, *cur, *p );
        p += 1 + *p;
    }

    *olen = p - buf;

    /* List length = olen - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */
    buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF );
    buf[5] = (unsigned char)( ( ( *olen - 6 )      ) & 0xFF );

    /* Extension length = olen - 2 (ext_type) - 2 (ext_len) */
    buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF );
    buf[3] = (unsigned char)( ( ( *olen - 4 )      ) & 0xFF );
}
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
505
#endif /* MBEDTLS_SSL_ALPN */
506

507 508 509
/*
 * Generate random bytes for ClientHello
 */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
510
static int ssl_generate_random( mbedtls_ssl_context *ssl )
511 512 513
{
    int ret;
    unsigned char *p = ssl->handshake->randbytes;
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
514
#if defined(MBEDTLS_HAVE_TIME)
515 516 517
    time_t t;
#endif

518 519 520
    /*
     * When responding to a verify request, MUST reuse random (RFC 6347 4.2.1)
     */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
521
#if defined(MBEDTLS_SSL_PROTO_DTLS)
522
    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
523 524 525 526 527 528
        ssl->handshake->verify_cookie != NULL )
    {
        return( 0 );
    }
#endif

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
529
#if defined(MBEDTLS_HAVE_TIME)
530 531 532 533 534 535
    t = time( NULL );
    *p++ = (unsigned char)( t >> 24 );
    *p++ = (unsigned char)( t >> 16 );
    *p++ = (unsigned char)( t >>  8 );
    *p++ = (unsigned char)( t       );

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
536
    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, current time: %lu", t ) );
537
#else
538
    if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 )
539 540 541
        return( ret );

    p += 4;
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
542
#endif /* MBEDTLS_HAVE_TIME */
543

544
    if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 )
545 546 547 548 549
        return( ret );

    return( 0 );
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
550
static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
551 552 553 554
{
    int ret;
    size_t i, n, olen, ext_len = 0;
    unsigned char *buf;
555
    unsigned char *p, *q;
556
    unsigned char offer_compress;
557
    const int *ciphersuites;
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
558
    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
559

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
560
    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) );
561

562
    if( ssl->conf->f_rng == NULL )
563
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
564 565
        MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") );
        return( MBEDTLS_ERR_SSL_NO_RNG );
566 567
    }

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
568 569
#if defined(MBEDTLS_SSL_RENEGOTIATION)
    if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
570
#endif
571
    {
572 573
        ssl->major_ver = ssl->conf->min_major_ver;
        ssl->minor_ver = ssl->conf->min_minor_ver;
574
    }
575

576
    if( ssl->conf->max_major_ver == 0 )
577
    {
578 579 580
        MBEDTLS_SSL_DEBUG_MSG( 1, ( "configured max major version is invalid, "
                            "consider using mbedtls_ssl_config_defaults()" ) );
        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
581
    }
582 583 584 585 586 587 588 589 590 591 592

    /*
     *     0  .   0   handshake type
     *     1  .   3   handshake length
     *     4  .   5   highest version supported
     *     6  .   9   current UNIX time
     *    10  .  37   random bytes
     */
    buf = ssl->out_msg;
    p = buf + 4;

593 594
    mbedtls_ssl_write_version( ssl->conf->max_major_ver, ssl->conf->max_minor_ver,
                       ssl->conf->transport, p );
595
    p += 2;
596

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
597
    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]",
598 599
                   buf[4], buf[5] ) );

600 601
    if( ( ret = ssl_generate_random( ssl ) ) != 0 )
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
602
        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_generate_random", ret );
603
        return( ret );
604
    }
605

606
    memcpy( p, ssl->handshake->randbytes, 32 );
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
607
    MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", p, 32 );
608
    p += 32;
609 610 611 612

    /*
     *    38  .  38   session id length
     *    39  . 39+n  session id
613 614 615 616 617
     *   39+n . 39+n  DTLS only: cookie length (1 byte)
     *   40+n .  ..   DTSL only: cookie
     *   ..   . ..    ciphersuitelist length (2 bytes)
     *   ..   . ..    ciphersuitelist
     *   ..   . ..    compression methods length (1 byte)
618
     *   ..   . ..    compression methods
619
     *   ..   . ..    extensions length (2 bytes)
620
     *   ..   . ..    extensions
621
     */
622
    n = ssl->session_negotiate->length;
623

624
    if( n < 16 || n > 32 ||
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
625 626
#if defined(MBEDTLS_SSL_RENEGOTIATION)
        ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ||
627
#endif
628
        ssl->handshake->resume == 0 )
629
    {
630
        n = 0;
631 632
    }

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
633
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
634 635 636 637
    /*
     * RFC 5077 section 3.4: "When presenting a ticket, the client MAY
     * generate and include a Session ID in the TLS ClientHello."
     */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
638 639
#if defined(MBEDTLS_SSL_RENEGOTIATION)
    if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
640
#endif
641
    {
642 643 644
        if( ssl->session_negotiate->ticket != NULL &&
                ssl->session_negotiate->ticket_len != 0 )
        {
645
            ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id, 32 );
646

647 648
            if( ret != 0 )
                return( ret );
649

650 651
            ssl->session_negotiate->length = n = 32;
        }
652
    }
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
653
#endif /* MBEDTLS_SSL_SESSION_TICKETS */
654 655 656 657

    *p++ = (unsigned char) n;

    for( i = 0; i < n; i++ )
658
        *p++ = ssl->session_negotiate->id[i];
659

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
660 661
    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) );
    MBEDTLS_SSL_DEBUG_BUF( 3,   "client hello, session id", buf + 39, n );
662

663 664 665
    /*
     * DTLS cookie
     */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
666
#if defined(MBEDTLS_SSL_PROTO_DTLS)
667
    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
668
    {
669 670
        if( ssl->handshake->verify_cookie == NULL )
        {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
671
            MBEDTLS_SSL_DEBUG_MSG( 3, ( "no verify cookie to send" ) );
672 673 674 675
            *p++ = 0;
        }
        else
        {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
676
            MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie",
677 678 679 680 681 682 683 684
                              ssl->handshake->verify_cookie,
                              ssl->handshake->verify_cookie_len );

            *p++ = ssl->handshake->verify_cookie_len;
            memcpy( p, ssl->handshake->verify_cookie,
                       ssl->handshake->verify_cookie_len );
            p += ssl->handshake->verify_cookie_len;
        }
685 686 687 688 689 690
    }
#endif

    /*
     * Ciphersuite list
     */
691
    ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver];
692 693

    /* Skip writing ciphersuite length for now */
694 695 696
    n = 0;
    q = p;
    p += 2;
697

698
    for( i = 0; ciphersuites[i] != 0; i++ )
699
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
700
        ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuites[i] );
701 702 703 704

        if( ciphersuite_info == NULL )
            continue;

705 706
        if( ciphersuite_info->min_minor_ver > ssl->conf->max_minor_ver ||
            ciphersuite_info->max_minor_ver < ssl->conf->min_minor_ver )
707 708
            continue;

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
709
#if defined(MBEDTLS_SSL_PROTO_DTLS)
710
        if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
711
            ( ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) )
712 713 714
            continue;
#endif

715
#if defined(MBEDTLS_ARC4_C)
716
        if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED &&
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
717
            ciphersuite_info->cipher == MBEDTLS_CIPHER_ARC4_128 )
718
            continue;
719
#endif
720

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
721
        MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %2d",
722
                       ciphersuites[i] ) );
723

724
        n++;
725 726
        *p++ = (unsigned char)( ciphersuites[i] >> 8 );
        *p++ = (unsigned char)( ciphersuites[i]      );
727 728
    }

729 730 731
    /*
     * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV
     */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
732 733
#if defined(MBEDTLS_SSL_RENEGOTIATION)
    if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
734 735
#endif
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
736 737
        *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO >> 8 );
        *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO      );
738 739 740
        n++;
    }

741
    /* Some versions of OpenSSL don't handle it correctly if not at end */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
742
#if defined(MBEDTLS_SSL_FALLBACK_SCSV)
743
    if( ssl->conf->fallback == MBEDTLS_SSL_IS_FALLBACK )
744
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
745 746 747
        MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding FALLBACK_SCSV" ) );
        *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 );
        *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE      );
748 749 750 751
        n++;
    }
#endif

752 753 754
    *q++ = (unsigned char)( n >> 7 );
    *q++ = (unsigned char)( n << 1 );

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
755
    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites", n ) );
756

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
757
#if defined(MBEDTLS_ZLIB_SUPPORT)
758
    offer_compress = 1;
759
#else
760 761
    offer_compress = 0;
#endif
762

763 764 765 766 767 768
    /*
     * We don't support compression with DTLS right now: is many records come
     * in the same datagram, uncompressing one could overwrite the next one.
     * We don't want to add complexity for handling that case unless there is
     * an actual need for it.
     */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
769
#if defined(MBEDTLS_SSL_PROTO_DTLS)
770
    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
771 772 773 774 775
        offer_compress = 0;
#endif

    if( offer_compress )
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
776 777 778
        MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 2 ) );
        MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d %d",
                            MBEDTLS_SSL_COMPRESS_DEFLATE, MBEDTLS_SSL_COMPRESS_NULL ) );
779 780

        *p++ = 2;
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
781 782
        *p++ = MBEDTLS_SSL_COMPRESS_DEFLATE;
        *p++ = MBEDTLS_SSL_COMPRESS_NULL;
783 784 785
    }
    else
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
786 787 788
        MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) );
        MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d",
                            MBEDTLS_SSL_COMPRESS_NULL ) );
789 790

        *p++ = 1;
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
791
        *p++ = MBEDTLS_SSL_COMPRESS_NULL;
792
    }
793

794 795
    // First write extensions, then the total length
    //
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
796
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
797 798
    ssl_write_hostname_ext( ssl, p + 2 + ext_len, &olen );
    ext_len += olen;
799
#endif
800

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
801
#if defined(MBEDTLS_SSL_RENEGOTIATION)
802 803
    ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen );
    ext_len += olen;
804
#endif
805

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
806 807
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
    defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
808 809
    ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len, &olen );
    ext_len += olen;
810
#endif
811

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
812
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)
813 814
    ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen );
    ext_len += olen;
815

816 817
    ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
    ext_len += olen;
818 819
#endif

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
820
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
821 822
    ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen );
    ext_len += olen;
823
#endif
824

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
825
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
826 827
    ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen );
    ext_len += olen;
828
#endif
829

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
830
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
831 832 833 834
    ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen );
    ext_len += olen;
#endif

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
835
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
836 837 838 839
    ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen );
    ext_len += olen;
#endif

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
840
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
Manuel Pégourié-Gonnard's avatar