1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci * Copyright 2017 BaishanCloud. All rights reserved.
4e1051a39Sopenharmony_ci *
5e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
6e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
7e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
8e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
9e1051a39Sopenharmony_ci */
10e1051a39Sopenharmony_ci
11e1051a39Sopenharmony_ci#include <string.h>
12e1051a39Sopenharmony_ci
13e1051a39Sopenharmony_ci#include <openssl/opensslconf.h>
14e1051a39Sopenharmony_ci#include <openssl/bio.h>
15e1051a39Sopenharmony_ci#include <openssl/crypto.h>
16e1051a39Sopenharmony_ci#include <openssl/evp.h>
17e1051a39Sopenharmony_ci#include <openssl/ssl.h>
18e1051a39Sopenharmony_ci#include <openssl/err.h>
19e1051a39Sopenharmony_ci#include <time.h>
20e1051a39Sopenharmony_ci
21e1051a39Sopenharmony_ci#include "internal/packet.h"
22e1051a39Sopenharmony_ci
23e1051a39Sopenharmony_ci#include "testutil.h"
24e1051a39Sopenharmony_ci#include "internal/nelem.h"
25e1051a39Sopenharmony_ci#include "helpers/ssltestlib.h"
26e1051a39Sopenharmony_ci
27e1051a39Sopenharmony_ci#define CLIENT_VERSION_LEN      2
28e1051a39Sopenharmony_ci
29e1051a39Sopenharmony_cistatic const char *host = "dummy-host";
30e1051a39Sopenharmony_ci
31e1051a39Sopenharmony_cistatic char *cert = NULL;
32e1051a39Sopenharmony_cistatic char *privkey = NULL;
33e1051a39Sopenharmony_ci
34e1051a39Sopenharmony_ci#if defined(OPENSSL_NO_TLS1_3) || \
35e1051a39Sopenharmony_ci    (defined(OPENSSL_NO_EC) && defined(OPENSSL_NO_DH))
36e1051a39Sopenharmony_cistatic int maxversion = TLS1_2_VERSION;
37e1051a39Sopenharmony_ci#else
38e1051a39Sopenharmony_cistatic int maxversion = 0;
39e1051a39Sopenharmony_ci#endif
40e1051a39Sopenharmony_ci
41e1051a39Sopenharmony_cistatic int get_sni_from_client_hello(BIO *bio, char **sni)
42e1051a39Sopenharmony_ci{
43e1051a39Sopenharmony_ci    long len;
44e1051a39Sopenharmony_ci    unsigned char *data;
45e1051a39Sopenharmony_ci    PACKET pkt, pkt2, pkt3, pkt4, pkt5;
46e1051a39Sopenharmony_ci    unsigned int servname_type = 0, type = 0;
47e1051a39Sopenharmony_ci    int ret = 0;
48e1051a39Sopenharmony_ci
49e1051a39Sopenharmony_ci    memset(&pkt, 0, sizeof(pkt));
50e1051a39Sopenharmony_ci    memset(&pkt2, 0, sizeof(pkt2));
51e1051a39Sopenharmony_ci    memset(&pkt3, 0, sizeof(pkt3));
52e1051a39Sopenharmony_ci    memset(&pkt4, 0, sizeof(pkt4));
53e1051a39Sopenharmony_ci    memset(&pkt5, 0, sizeof(pkt5));
54e1051a39Sopenharmony_ci
55e1051a39Sopenharmony_ci    if (!TEST_long_ge(len = BIO_get_mem_data(bio, (char **)&data), 0)
56e1051a39Sopenharmony_ci            || !TEST_true(PACKET_buf_init(&pkt, data, len))
57e1051a39Sopenharmony_ci               /* Skip the record header */
58e1051a39Sopenharmony_ci            || !PACKET_forward(&pkt, SSL3_RT_HEADER_LENGTH)
59e1051a39Sopenharmony_ci               /* Skip the handshake message header */
60e1051a39Sopenharmony_ci            || !TEST_true(PACKET_forward(&pkt, SSL3_HM_HEADER_LENGTH))
61e1051a39Sopenharmony_ci               /* Skip client version and random */
62e1051a39Sopenharmony_ci            || !TEST_true(PACKET_forward(&pkt, CLIENT_VERSION_LEN
63e1051a39Sopenharmony_ci                                               + SSL3_RANDOM_SIZE))
64e1051a39Sopenharmony_ci               /* Skip session id */
65e1051a39Sopenharmony_ci            || !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2))
66e1051a39Sopenharmony_ci               /* Skip ciphers */
67e1051a39Sopenharmony_ci            || !TEST_true(PACKET_get_length_prefixed_2(&pkt, &pkt2))
68e1051a39Sopenharmony_ci               /* Skip compression */
69e1051a39Sopenharmony_ci            || !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2))
70e1051a39Sopenharmony_ci               /* Extensions len */
71e1051a39Sopenharmony_ci            || !TEST_true(PACKET_as_length_prefixed_2(&pkt, &pkt2)))
72e1051a39Sopenharmony_ci        goto end;
73e1051a39Sopenharmony_ci
74e1051a39Sopenharmony_ci    /* Loop through all extensions for SNI */
75e1051a39Sopenharmony_ci    while (PACKET_remaining(&pkt2)) {
76e1051a39Sopenharmony_ci        if (!TEST_true(PACKET_get_net_2(&pkt2, &type))
77e1051a39Sopenharmony_ci                || !TEST_true(PACKET_get_length_prefixed_2(&pkt2, &pkt3)))
78e1051a39Sopenharmony_ci            goto end;
79e1051a39Sopenharmony_ci        if (type == TLSEXT_TYPE_server_name) {
80e1051a39Sopenharmony_ci            if (!TEST_true(PACKET_get_length_prefixed_2(&pkt3, &pkt4))
81e1051a39Sopenharmony_ci                    || !TEST_uint_ne(PACKET_remaining(&pkt4), 0)
82e1051a39Sopenharmony_ci                    || !TEST_true(PACKET_get_1(&pkt4, &servname_type))
83e1051a39Sopenharmony_ci                    || !TEST_uint_eq(servname_type, TLSEXT_NAMETYPE_host_name)
84e1051a39Sopenharmony_ci                    || !TEST_true(PACKET_get_length_prefixed_2(&pkt4, &pkt5))
85e1051a39Sopenharmony_ci                    || !TEST_uint_le(PACKET_remaining(&pkt5), TLSEXT_MAXLEN_host_name)
86e1051a39Sopenharmony_ci                    || !TEST_false(PACKET_contains_zero_byte(&pkt5))
87e1051a39Sopenharmony_ci                    || !TEST_true(PACKET_strndup(&pkt5, sni)))
88e1051a39Sopenharmony_ci                goto end;
89e1051a39Sopenharmony_ci            ret = 1;
90e1051a39Sopenharmony_ci            goto end;
91e1051a39Sopenharmony_ci        }
92e1051a39Sopenharmony_ci    }
93e1051a39Sopenharmony_ciend:
94e1051a39Sopenharmony_ci    return ret;
95e1051a39Sopenharmony_ci}
96e1051a39Sopenharmony_ci
97e1051a39Sopenharmony_cistatic int client_setup_sni_before_state(void)
98e1051a39Sopenharmony_ci{
99e1051a39Sopenharmony_ci    SSL_CTX *ctx;
100e1051a39Sopenharmony_ci    SSL *con = NULL;
101e1051a39Sopenharmony_ci    BIO *rbio;
102e1051a39Sopenharmony_ci    BIO *wbio;
103e1051a39Sopenharmony_ci    char *hostname = NULL;
104e1051a39Sopenharmony_ci    int ret = 0;
105e1051a39Sopenharmony_ci
106e1051a39Sopenharmony_ci    /* use TLS_method to blur 'side' */
107e1051a39Sopenharmony_ci    ctx = SSL_CTX_new(TLS_method());
108e1051a39Sopenharmony_ci    if (!TEST_ptr(ctx))
109e1051a39Sopenharmony_ci        goto end;
110e1051a39Sopenharmony_ci
111e1051a39Sopenharmony_ci    if (maxversion > 0
112e1051a39Sopenharmony_ci            && !TEST_true(SSL_CTX_set_max_proto_version(ctx, maxversion)))
113e1051a39Sopenharmony_ci        goto end;
114e1051a39Sopenharmony_ci
115e1051a39Sopenharmony_ci    con = SSL_new(ctx);
116e1051a39Sopenharmony_ci    if (!TEST_ptr(con))
117e1051a39Sopenharmony_ci        goto end;
118e1051a39Sopenharmony_ci
119e1051a39Sopenharmony_ci    /* set SNI before 'client side' is set */
120e1051a39Sopenharmony_ci    SSL_set_tlsext_host_name(con, host);
121e1051a39Sopenharmony_ci
122e1051a39Sopenharmony_ci    rbio = BIO_new(BIO_s_mem());
123e1051a39Sopenharmony_ci    wbio = BIO_new(BIO_s_mem());
124e1051a39Sopenharmony_ci    if (!TEST_ptr(rbio)|| !TEST_ptr(wbio)) {
125e1051a39Sopenharmony_ci        BIO_free(rbio);
126e1051a39Sopenharmony_ci        BIO_free(wbio);
127e1051a39Sopenharmony_ci        goto end;
128e1051a39Sopenharmony_ci    }
129e1051a39Sopenharmony_ci
130e1051a39Sopenharmony_ci    SSL_set_bio(con, rbio, wbio);
131e1051a39Sopenharmony_ci
132e1051a39Sopenharmony_ci    if (!TEST_int_le(SSL_connect(con), 0))
133e1051a39Sopenharmony_ci        /* This shouldn't succeed because we don't have a server! */
134e1051a39Sopenharmony_ci        goto end;
135e1051a39Sopenharmony_ci    if (!TEST_true(get_sni_from_client_hello(wbio, &hostname)))
136e1051a39Sopenharmony_ci        /* no SNI in client hello */
137e1051a39Sopenharmony_ci        goto end;
138e1051a39Sopenharmony_ci    if (!TEST_str_eq(hostname, host))
139e1051a39Sopenharmony_ci        /* incorrect SNI value */
140e1051a39Sopenharmony_ci        goto end;
141e1051a39Sopenharmony_ci    ret = 1;
142e1051a39Sopenharmony_ciend:
143e1051a39Sopenharmony_ci    OPENSSL_free(hostname);
144e1051a39Sopenharmony_ci    SSL_free(con);
145e1051a39Sopenharmony_ci    SSL_CTX_free(ctx);
146e1051a39Sopenharmony_ci    return ret;
147e1051a39Sopenharmony_ci}
148e1051a39Sopenharmony_ci
149e1051a39Sopenharmony_cistatic int client_setup_sni_after_state(void)
150e1051a39Sopenharmony_ci{
151e1051a39Sopenharmony_ci    SSL_CTX *ctx;
152e1051a39Sopenharmony_ci    SSL *con = NULL;
153e1051a39Sopenharmony_ci    BIO *rbio;
154e1051a39Sopenharmony_ci    BIO *wbio;
155e1051a39Sopenharmony_ci    char *hostname = NULL;
156e1051a39Sopenharmony_ci    int ret = 0;
157e1051a39Sopenharmony_ci
158e1051a39Sopenharmony_ci    /* use TLS_method to blur 'side' */
159e1051a39Sopenharmony_ci    ctx = SSL_CTX_new(TLS_method());
160e1051a39Sopenharmony_ci    if (!TEST_ptr(ctx))
161e1051a39Sopenharmony_ci        goto end;
162e1051a39Sopenharmony_ci
163e1051a39Sopenharmony_ci    if (maxversion > 0
164e1051a39Sopenharmony_ci            && !TEST_true(SSL_CTX_set_max_proto_version(ctx, maxversion)))
165e1051a39Sopenharmony_ci        goto end;
166e1051a39Sopenharmony_ci
167e1051a39Sopenharmony_ci    con = SSL_new(ctx);
168e1051a39Sopenharmony_ci    if (!TEST_ptr(con))
169e1051a39Sopenharmony_ci        goto end;
170e1051a39Sopenharmony_ci
171e1051a39Sopenharmony_ci    rbio = BIO_new(BIO_s_mem());
172e1051a39Sopenharmony_ci    wbio = BIO_new(BIO_s_mem());
173e1051a39Sopenharmony_ci    if (!TEST_ptr(rbio)|| !TEST_ptr(wbio)) {
174e1051a39Sopenharmony_ci        BIO_free(rbio);
175e1051a39Sopenharmony_ci        BIO_free(wbio);
176e1051a39Sopenharmony_ci        goto end;
177e1051a39Sopenharmony_ci    }
178e1051a39Sopenharmony_ci
179e1051a39Sopenharmony_ci    SSL_set_bio(con, rbio, wbio);
180e1051a39Sopenharmony_ci    SSL_set_connect_state(con);
181e1051a39Sopenharmony_ci
182e1051a39Sopenharmony_ci    /* set SNI after 'client side' is set */
183e1051a39Sopenharmony_ci    SSL_set_tlsext_host_name(con, host);
184e1051a39Sopenharmony_ci
185e1051a39Sopenharmony_ci    if (!TEST_int_le(SSL_connect(con), 0))
186e1051a39Sopenharmony_ci        /* This shouldn't succeed because we don't have a server! */
187e1051a39Sopenharmony_ci        goto end;
188e1051a39Sopenharmony_ci    if (!TEST_true(get_sni_from_client_hello(wbio, &hostname)))
189e1051a39Sopenharmony_ci        /* no SNI in client hello */
190e1051a39Sopenharmony_ci        goto end;
191e1051a39Sopenharmony_ci    if (!TEST_str_eq(hostname, host))
192e1051a39Sopenharmony_ci        /* incorrect SNI value */
193e1051a39Sopenharmony_ci        goto end;
194e1051a39Sopenharmony_ci    ret = 1;
195e1051a39Sopenharmony_ciend:
196e1051a39Sopenharmony_ci    OPENSSL_free(hostname);
197e1051a39Sopenharmony_ci    SSL_free(con);
198e1051a39Sopenharmony_ci    SSL_CTX_free(ctx);
199e1051a39Sopenharmony_ci    return ret;
200e1051a39Sopenharmony_ci}
201e1051a39Sopenharmony_ci
202e1051a39Sopenharmony_cistatic int server_setup_sni(void)
203e1051a39Sopenharmony_ci{
204e1051a39Sopenharmony_ci    SSL_CTX *cctx = NULL, *sctx = NULL;
205e1051a39Sopenharmony_ci    SSL *clientssl = NULL, *serverssl = NULL;
206e1051a39Sopenharmony_ci    int testresult = 0;
207e1051a39Sopenharmony_ci
208e1051a39Sopenharmony_ci    if (!TEST_true(create_ssl_ctx_pair(NULL, TLS_server_method(),
209e1051a39Sopenharmony_ci                                       TLS_client_method(),
210e1051a39Sopenharmony_ci                                       TLS1_VERSION, 0,
211e1051a39Sopenharmony_ci                                       &sctx, &cctx, cert, privkey))
212e1051a39Sopenharmony_ci            || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
213e1051a39Sopenharmony_ci                                             NULL, NULL)))
214e1051a39Sopenharmony_ci        goto end;
215e1051a39Sopenharmony_ci
216e1051a39Sopenharmony_ci    /* set SNI at server side */
217e1051a39Sopenharmony_ci    SSL_set_tlsext_host_name(serverssl, host);
218e1051a39Sopenharmony_ci
219e1051a39Sopenharmony_ci    if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
220e1051a39Sopenharmony_ci        goto end;
221e1051a39Sopenharmony_ci
222e1051a39Sopenharmony_ci    if (!TEST_ptr_null(SSL_get_servername(serverssl,
223e1051a39Sopenharmony_ci                                          TLSEXT_NAMETYPE_host_name))) {
224e1051a39Sopenharmony_ci        /* SNI should have been cleared during handshake */
225e1051a39Sopenharmony_ci        goto end;
226e1051a39Sopenharmony_ci    }
227e1051a39Sopenharmony_ci
228e1051a39Sopenharmony_ci    testresult = 1;
229e1051a39Sopenharmony_ciend:
230e1051a39Sopenharmony_ci    SSL_free(serverssl);
231e1051a39Sopenharmony_ci    SSL_free(clientssl);
232e1051a39Sopenharmony_ci    SSL_CTX_free(sctx);
233e1051a39Sopenharmony_ci    SSL_CTX_free(cctx);
234e1051a39Sopenharmony_ci
235e1051a39Sopenharmony_ci    return testresult;
236e1051a39Sopenharmony_ci}
237e1051a39Sopenharmony_ci
238e1051a39Sopenharmony_citypedef int (*sni_test_fn)(void);
239e1051a39Sopenharmony_ci
240e1051a39Sopenharmony_cistatic sni_test_fn sni_test_fns[3] = {
241e1051a39Sopenharmony_ci    client_setup_sni_before_state,
242e1051a39Sopenharmony_ci    client_setup_sni_after_state,
243e1051a39Sopenharmony_ci    server_setup_sni
244e1051a39Sopenharmony_ci};
245e1051a39Sopenharmony_ci
246e1051a39Sopenharmony_cistatic int test_servername(int test)
247e1051a39Sopenharmony_ci{
248e1051a39Sopenharmony_ci    /*
249e1051a39Sopenharmony_ci     * For each test set up an SSL_CTX and SSL and see
250e1051a39Sopenharmony_ci     * what SNI behaves.
251e1051a39Sopenharmony_ci     */
252e1051a39Sopenharmony_ci    return sni_test_fns[test]();
253e1051a39Sopenharmony_ci}
254e1051a39Sopenharmony_ci
255e1051a39Sopenharmony_ciint setup_tests(void)
256e1051a39Sopenharmony_ci{
257e1051a39Sopenharmony_ci    if (!test_skip_common_options()) {
258e1051a39Sopenharmony_ci        TEST_error("Error parsing test options\n");
259e1051a39Sopenharmony_ci        return 0;
260e1051a39Sopenharmony_ci    }
261e1051a39Sopenharmony_ci
262e1051a39Sopenharmony_ci    if (!TEST_ptr(cert = test_get_argument(0))
263e1051a39Sopenharmony_ci            || !TEST_ptr(privkey = test_get_argument(1)))
264e1051a39Sopenharmony_ci        return 0;
265e1051a39Sopenharmony_ci
266e1051a39Sopenharmony_ci    ADD_ALL_TESTS(test_servername, OSSL_NELEM(sni_test_fns));
267e1051a39Sopenharmony_ci    return 1;
268e1051a39Sopenharmony_ci}
269