From 5ff3b86c112e0fb390c759ef6fb52a95c866ba37 Mon Sep 17 00:00:00 2001 From: Chenglong Zhang Date: Wed, 19 May 2021 17:52:43 +0800 Subject: [PATCH] babassl 8.2.0 Support NTLS; Support delegated credential; Update BoringSSL QUIC API; Fix some CVE; --- CHANGES.BabaSSL | 16 + Configure | 3 +- README.md | 3 +- apps/build.info | 4 + apps/delecred.c | 213 + apps/s_apps.h | 5 +- apps/s_cb.c | 28 + apps/s_client.c | 82 +- apps/s_server.c | 84 +- crypto/asn1/asn1_err.c | 5 +- crypto/asn1/build.info | 2 +- crypto/asn1/charmap.h | 2 +- crypto/asn1/x_delegated_credential.c | 207 + crypto/async/async_err.c | 2 +- crypto/bio/bio_err.c | 2 +- crypto/bn/bn_err.c | 2 +- crypto/bn/bn_prime.h | 2 +- crypto/buffer/buf_err.c | 2 +- crypto/cms/cms_err.c | 2 +- crypto/comp/comp_err.c | 2 +- crypto/conf/conf_def.h | 2 +- crypto/conf/conf_err.c | 2 +- crypto/cpt_err.c | 2 +- crypto/ct/ct_err.c | 2 +- crypto/cversion.c | 4 + crypto/dh/dh_err.c | 2 +- crypto/dsa/dsa_err.c | 2 +- crypto/dso/dso_err.c | 2 +- crypto/ec/ec_err.c | 2 +- crypto/engine/eng_err.c | 2 +- crypto/err/openssl.txt | 73 +- crypto/evp/e_sm4.c | 87 + crypto/kdf/kdf_err.c | 2 +- crypto/objects/obj_dat.h | 17 +- crypto/objects/obj_err.c | 2 +- crypto/objects/obj_mac.num | 1 + crypto/objects/obj_xref.h | 2 +- crypto/objects/objects.txt | 2 + crypto/ocsp/ocsp_err.c | 2 +- crypto/pem/pem_err.c | 2 +- crypto/pkcs12/pk12err.c | 2 +- crypto/pkcs7/pkcs7err.c | 2 +- crypto/rand/rand_err.c | 2 +- crypto/rsa/rsa_err.c | 2 +- crypto/sm2/sm2_err.c | 2 +- crypto/store/store_err.c | 2 +- crypto/ts/ts_err.c | 2 +- crypto/ui/ui_err.c | 2 +- crypto/x509/x509_cmp.c | 257 ++ crypto/x509/x509_err.c | 4 +- crypto/x509v3/ext_dat.h | 3 + crypto/x509v3/standard_exts.h | 5 +- crypto/x509v3/v3_bitst.c | 12 + crypto/x509v3/v3err.c | 2 +- doc/man3/SSL_CTX_set_quic_method.pod | 163 +- engines/e_afalg.txt | 2 +- engines/e_afalg_err.c | 2 +- engines/e_afalg_err.h | 8 +- engines/e_capi.txt | 2 +- engines/e_capi_err.c | 2 +- engines/e_capi_err.h | 8 +- engines/e_dasync.txt | 2 +- engines/e_dasync_err.c | 2 +- engines/e_dasync_err.h | 8 +- engines/e_ossltest.txt | 2 +- engines/e_ossltest_err.c | 2 +- engines/e_ossltest_err.h | 8 +- fuzz/oids.txt | 1 + include/crypto/sm2err.h | 6 +- include/crypto/x509.h | 17 + include/internal/dsoerr.h | 19 +- include/openssl/asn1err.h | 8 +- include/openssl/asyncerr.h | 6 +- include/openssl/bioerr.h | 6 +- include/openssl/bnerr.h | 6 +- include/openssl/buffererr.h | 6 +- include/openssl/cmserr.h | 6 +- include/openssl/comperr.h | 6 +- include/openssl/conferr.h | 6 +- include/openssl/crypto.h | 3 + include/openssl/cryptoerr.h | 6 +- include/openssl/cterr.h | 6 +- include/openssl/dherr.h | 6 +- include/openssl/dsaerr.h | 6 +- include/openssl/ecerr.h | 6 +- include/openssl/engineerr.h | 6 +- include/openssl/evperr.h | 1 + include/openssl/kdferr.h | 6 +- include/openssl/ntls.h | 70 +- include/openssl/obj_mac.h | 7 +- include/openssl/objectserr.h | 6 +- include/openssl/ocsperr.h | 6 +- include/openssl/opensslv.h | 4 +- include/openssl/ossl_typ.h | 3 + include/openssl/pemerr.h | 6 +- include/openssl/pkcs12err.h | 6 +- include/openssl/pkcs7err.h | 6 +- include/openssl/randerr.h | 2 +- include/openssl/rsaerr.h | 8 +- include/openssl/ssl.h | 70 +- include/openssl/sslerr.h | 58 +- include/openssl/storeerr.h | 6 +- include/openssl/tls1.h | 8 +- include/openssl/tserr.h | 6 +- include/openssl/uierr.h | 6 +- include/openssl/x509.h | 40 + include/openssl/x509err.h | 3 +- include/openssl/x509v3err.h | 6 +- ssl/build.info | 13 +- ssl/s3_lib.c | 64 +- ssl/s3_msg.c | 2 +- ssl/ssl_asn1.c | 39 +- ssl/ssl_cert.c | 26 + ssl/ssl_ciph.c | 2 + ssl/ssl_conf.c | 70 + ssl/ssl_dc.c | 553 +++ ssl/ssl_err.c | 66 +- ssl/ssl_lib.c | 38 +- ssl/ssl_local.h | 92 +- ssl/ssl_quic.c | 279 +- ssl/ssl_rsa.c | 353 +- ssl/ssl_sess.c | 46 + ssl/ssl_txt.c | 12 + ssl/statem/extensions.c | 206 +- ssl/statem/extensions_clnt.c | 81 +- ssl/statem/extensions_srvr.c | 132 +- ssl/statem/statem_clnt.c | 30 + ssl/statem/statem_lib.c | 97 +- ssl/statem/statem_local.h | 46 + ssl/statem/statem_quic.c | 29 +- ssl/statem/statem_srvr.c | 31 +- ssl/statem_ntls/extensions.c | 1509 ++++++++ ssl/statem_ntls/extensions_clnt.c | 1909 +++++++++ ssl/statem_ntls/extensions_cust.c | 531 +++ ssl/statem_ntls/extensions_srvr.c | 1874 +++++++++ ssl/statem_ntls/ssl_local_ntls.h | 79 + ssl/statem_ntls/statem.c | 1004 +++++ ssl/statem_ntls/statem.h | 157 + ssl/statem_ntls/statem_clnt.c | 2927 ++++++++++++++ ssl/statem_ntls/statem_lib.c | 2060 ++++++++++ ssl/statem_ntls/statem_local_ntls.h | 479 +++ ssl/statem_ntls/statem_ntls.c | 541 +++ ssl/statem_ntls/statem_ntls_clnt.c | 882 +++++ ssl/statem_ntls/statem_ntls_srvr.c | 1327 +++++++ ssl/statem_ntls/statem_srvr.c | 3442 +++++++++++++++++ ssl/t1_lib.c | 288 +- test/build.info | 3 +- test/certs/test_rsa_crt.pem | 37 +- test/certs/test_rsa_key.pem | 53 +- test/ciphername_test.c | 2 +- test/handshake_helper.c | 29 + test/handshake_helper.h | 4 + test/recipes/80-test_dc_sign.t | 72 + test/recipes/80-test_dc_sign_data/openssl.cnf | 144 + .../80-test_dc_sign_data/openssl_middleca.cnf | 146 + test/recipes/80-test_dc_sign_data/sign_dc.sh | 73 + test/recipes/80-test_ssl_new.t | 9 +- test/recipes/88-test_ssl_ntls_api.t | 18 + test/ssl-tests/31-ntls.conf | 135 +- test/ssl-tests/31-ntls.conf.in | 63 +- test/ssl-tests/32-keyless-normal.conf | 84 - test/ssl-tests/32-keyless-normal.conf.in | 59 - test/ssl-tests/33-keyless-tls13-sm.conf | 36 - test/ssl-tests/33-keyless-tls13-sm.conf.in | 31 - test/ssl-tests/34-keyless-ntls.conf | 105 - test/ssl-tests/34-keyless-ntls.conf.in | 79 - test/ssl-tests/35-lurk-normal.conf | 143 - test/ssl-tests/35-lurk-normal.conf.in | 98 - test/ssl-tests/36-lurk-tls13-sm.conf | 36 - test/ssl-tests/36-lurk-tls13-sm.conf.in | 31 - test/ssl-tests/37-lurk-ntls.conf | 107 - test/ssl-tests/37-lurk-ntls.conf.in | 81 - test/ssl-tests/38-delegated-credential.conf | 122 + .../ssl-tests/38-delegated-credential.conf.in | 89 + test/ssl_ntls_api_test.c | 93 + test/ssl_test.c | 44 + test/ssl_test_ctx.c | 42 + test/ssl_test_ctx.h | 16 + test/sslapitest.c | 549 ++- test/tls13secretstest.c | 2 +- util/libcrypto.num | 35 + util/libssl.num | 49 +- util/mktar.sh | 36 + 183 files changed, 24320 insertions(+), 1607 deletions(-) create mode 100644 apps/delecred.c create mode 100644 crypto/asn1/x_delegated_credential.c create mode 100644 ssl/ssl_dc.c create mode 100644 ssl/statem_ntls/extensions.c create mode 100644 ssl/statem_ntls/extensions_clnt.c create mode 100644 ssl/statem_ntls/extensions_cust.c create mode 100644 ssl/statem_ntls/extensions_srvr.c create mode 100644 ssl/statem_ntls/ssl_local_ntls.h create mode 100644 ssl/statem_ntls/statem.c create mode 100644 ssl/statem_ntls/statem.h create mode 100644 ssl/statem_ntls/statem_clnt.c create mode 100644 ssl/statem_ntls/statem_lib.c create mode 100644 ssl/statem_ntls/statem_local_ntls.h create mode 100644 ssl/statem_ntls/statem_ntls.c create mode 100644 ssl/statem_ntls/statem_ntls_clnt.c create mode 100644 ssl/statem_ntls/statem_ntls_srvr.c create mode 100644 ssl/statem_ntls/statem_srvr.c create mode 100644 test/recipes/80-test_dc_sign.t create mode 100644 test/recipes/80-test_dc_sign_data/openssl.cnf create mode 100644 test/recipes/80-test_dc_sign_data/openssl_middleca.cnf create mode 100644 test/recipes/80-test_dc_sign_data/sign_dc.sh create mode 100644 test/recipes/88-test_ssl_ntls_api.t delete mode 100644 test/ssl-tests/32-keyless-normal.conf delete mode 100644 test/ssl-tests/32-keyless-normal.conf.in delete mode 100644 test/ssl-tests/33-keyless-tls13-sm.conf delete mode 100644 test/ssl-tests/33-keyless-tls13-sm.conf.in delete mode 100644 test/ssl-tests/34-keyless-ntls.conf delete mode 100644 test/ssl-tests/34-keyless-ntls.conf.in delete mode 100644 test/ssl-tests/35-lurk-normal.conf delete mode 100644 test/ssl-tests/35-lurk-normal.conf.in delete mode 100644 test/ssl-tests/36-lurk-tls13-sm.conf delete mode 100644 test/ssl-tests/36-lurk-tls13-sm.conf.in delete mode 100644 test/ssl-tests/37-lurk-ntls.conf delete mode 100644 test/ssl-tests/37-lurk-ntls.conf.in create mode 100644 test/ssl-tests/38-delegated-credential.conf create mode 100644 test/ssl-tests/38-delegated-credential.conf.in create mode 100755 util/mktar.sh diff --git a/CHANGES.BabaSSL b/CHANGES.BabaSSL index 5b8040437..12431633b 100644 --- a/CHANGES.BabaSSL +++ b/CHANGES.BabaSSL @@ -5,6 +5,22 @@ This is a high-level summary of the most important changes. For a full list of changes, see the git commit log. + Changes between 8.2.0 and 8.3.0 [xx XXX xxxx] + + *) + + Changes between 8.1.3 and 8.2.0 [19 May 2021] + + *) Support NTLS(formal GM double cert) handshake processing, GB/T 38636-2020 TLCP + + *) Support delegated credential + + *) Update BoringSSL QUIC API + + *) Fix CVE-2021-3449 + + *) Fix CVE-2021-23840 and CVE-2021-23841 + Changes with 8.1.3 [15 Jan 2021] *) Support more QUIC related APIs diff --git a/Configure b/Configure index cfaf0aa8b..5ed6bfb27 100755 --- a/Configure +++ b/Configure @@ -445,7 +445,8 @@ my @disablables = ( "status", "req-status", "dycert-ocsp", - "options2" + "options2", + "delegated-credential" ); foreach my $proto ((@tls, @dtls)) { diff --git a/README.md b/README.md index 58c9dabe4..426b0cc6f 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,10 @@ BabaSSL is a modern cryptographic and secure protocol library developed by the a # Feature BabaSSL provides the following major features: - * Support [RFC 8998](https://tools.ietf.org/html/rfc8998), Chinese SM cipher suites in TLS 1.3 protocol + * Support NTLS(formal GM double cert) handshake processing, according to GB/T 38636-2020 TLCP * QUIC API support + * Support delegated credentials, according to [draft-ietf-tls-subcerts-10](https://www.ietf.org/archive/id/draft-ietf-tls-subcerts-10.txt) * ... # Reporting Security Bugs diff --git a/apps/build.info b/apps/build.info index 015373618..9785ae47c 100644 --- a/apps/build.info +++ b/apps/build.info @@ -47,6 +47,10 @@ IF[{- !$disabled{apps} -}] SOURCE[openssl]=dhparam.c DEPEND[dhparam.o]=progs.h ENDIF + IF[{- !$disabled{'delegated-credential'} -}] + SOURCE[openssl]=delecred.c + DEPEND[delecred.o]=progs.h + ENDIF IF[{- !$disabled{'dsa'} -}] SOURCE[openssl]=dsa.c dsaparam.c gendsa.c DEPEND[dsa.o]=progs.h diff --git a/apps/delecred.c b/apps/delecred.c new file mode 100644 index 000000000..8bd440710 --- /dev/null +++ b/apps/delecred.c @@ -0,0 +1,213 @@ +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include +#include +#include "../ssl/ssl_local.h" + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_IN, OPT_OUT, + OPT_NEW, OPT_DC_KEY, + OPT_EE_CERT, OPT_EE_KEY, + OPT_SEC, OPT_MD, + OPT_EXPECT_VERIFY_MD, OPT_CLIENT, OPT_SERVER, + OPT_TEXT, OPT_NOOUT +} OPTION_CHOICE; + +const OPTIONS delecred_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"in", OPT_IN, '<', "input file"}, + {"out", OPT_OUT, '>', "output file"}, + {"new", OPT_NEW, '-', "generate a new delegated credential"}, + {"dc_key", OPT_DC_KEY, 's', "private key of delegated credential"}, + {"parent_cert", OPT_EE_CERT, 's', "end-entity certificate used to sign the dc"}, + {"parent_key", OPT_EE_KEY, 's', "private key of the end-entity certificate"}, + {"sec", OPT_SEC, 'p', "dc valid time, default is 604800 seconds(7 days)"}, + {"expect_verify_md", OPT_EXPECT_VERIFY_MD, 's', "expected message digest of signature algorithm of dc key pair"}, + {"", OPT_MD, '-', "Any supported digest"}, + {"client", OPT_CLIENT, '-', "client DC"}, + {"server", OPT_SERVER, '-', "server DC"}, + {"text", OPT_TEXT, '-', "print the dc in text form"}, + {"noout", OPT_NOOUT, '-', "no dc output"}, + {NULL} +}; + +int delecred_main(int argc, char **argv) +{ + int ret = 1; + int res; + char *prog; + size_t i; + OPTION_CHOICE o; + char *infile = NULL, *outfile = NULL; + BIO *in = NULL, *out = NULL; + int text = 0; + int noout = 0; + int new_flag = 0; + char *dc_key = NULL; + char *ee_cert_file = NULL, *ee_key_file = NULL; + char *expect_verify_hash = NULL; + const EVP_MD *expect_verify_md = EVP_md_null(); + const EVP_MD *sign_md = EVP_md_null(); + int is_server = 1; + int valid_time = 7 * 24 * 3600; + DELEGATED_CREDENTIAL *dc = NULL; + ENGINE *e = NULL; + EVP_PKEY *dc_pkey = NULL; + X509 *ee_cert = NULL; + EVP_PKEY *ee_pkey = NULL; + unsigned char *dc_raw = NULL; + unsigned long dc_raw_len = 0; + + prog = opt_init(argc, argv, delecred_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: +opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(delecred_options); + ret = 0; + goto end; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_NEW: + new_flag = 1; + break; + case OPT_DC_KEY: + dc_key = opt_arg(); + break; + case OPT_EE_CERT: + ee_cert_file = opt_arg(); + break; + case OPT_EE_KEY: + ee_key_file = opt_arg(); + break; + case OPT_SEC: + opt_int(opt_arg(), &valid_time); + break; + case OPT_EXPECT_VERIFY_MD: + expect_verify_hash = opt_arg(); + if (!opt_md(expect_verify_hash, &expect_verify_md)) + goto opthelp; + break; + case OPT_MD: + if (!opt_md(opt_unknown(), &sign_md)) + goto opthelp; + break; + case OPT_CLIENT: + is_server = 0; + break; + case OPT_SERVER: + is_server = 1; + break; + case OPT_TEXT: + text = 1; + break; + case OPT_NOOUT: + noout = 1; + break; + } + } + + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + if (infile) { + dc = DC_load_from_file(infile); + + if (dc == NULL) { + goto end; + } + + if (text) { + if (!DC_print(bio_out, dc)) + goto end; + } + } else if (new_flag) { + dc_pkey = load_key(dc_key, FORMAT_PEM, 1, NULL, e, "key"); + if (dc_pkey == NULL) { + goto end; + } + + ee_cert = load_cert(ee_cert_file, FORMAT_PEM, "end-entity cert"); + if (ee_cert == NULL) { + goto end; + } + + ee_pkey = load_key(ee_key_file, FORMAT_PEM, 1, NULL, e, "end-entity key"); + if (ee_pkey == NULL) { + goto end; + } + + dc = DC_new(); + if (dc == NULL) { + BIO_printf(bio_err, "failed to new DC\n"); + goto end; + } + + if (!DC_sign(dc, dc_pkey, valid_time, EVP_MD_type(expect_verify_md), + ee_cert, ee_pkey, sign_md, is_server)) { + BIO_printf(bio_err, "failed to sign DC\n"); + goto end; + } + } else { + goto opthelp; + } + + if (!noout) { + dc_raw = DC_get0_raw_byte(dc); + dc_raw_len = DC_get_raw_byte_len(dc); + + if (dc_raw == NULL || dc_raw_len <= 0) { + BIO_printf(bio_err, "Invalid DC raw\n"); + goto end; + } + + if (outfile) { + out = BIO_new_file(outfile, "w"); + if (out == NULL) + goto end; + } else { + out = dup_bio_out(FORMAT_TEXT); + } + + for (i = 0; i < dc_raw_len; i++) { + res = BIO_printf(out, "%02x", dc_raw[i]); + if (res <= 0) { + BIO_printf(bio_out, "output dc error"); + goto end; + } + } + } + + ret = 0; + +end: + if (ret != 0) + ERR_print_errors(bio_err); + + release_engine(e); + EVP_PKEY_free(ee_pkey); + X509_free(ee_cert); + EVP_PKEY_free(dc_pkey); + DC_free(dc); + BIO_free(out); + BIO_free(in); + + return ret; +} + diff --git a/apps/s_apps.h b/apps/s_apps.h index 257f5d0f9..fbb9fbb96 100644 --- a/apps/s_apps.h +++ b/apps/s_apps.h @@ -20,7 +20,10 @@ int do_server(int *accept_sock, const char *host, const char *port, unsigned char *context, int naccept, BIO *bio_s_out); int verify_callback(int ok, X509_STORE_CTX *ctx); - +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +int set_dc_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key, + DELEGATED_CREDENTIAL *dc, int is_server); +#endif int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file); int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key, STACK_OF(X509) *chain, int build_chain); diff --git a/apps/s_cb.c b/apps/s_cb.c index 49aa8e013..028ebe5cf 100644 --- a/apps/s_cb.c +++ b/apps/s_cb.c @@ -179,6 +179,34 @@ int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key, return 1; } +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +int set_dc_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key, + DELEGATED_CREDENTIAL *dc, int is_server) +{ + if (SSL_CTX_use_certificate(ctx, cert) <= 0) { + BIO_printf(bio_err, "error setting certificate\n"); + ERR_print_errors(bio_err); + return 0; + } + + if (!SSL_CTX_use_dc(ctx, dc)) { + BIO_printf(bio_err, "error setting dc\n"); + ERR_print_errors(bio_err); + return 0; + } + + if (!SSL_CTX_use_dc_PrivateKey(ctx, key)) { + BIO_printf(bio_err, "error setting dc key\n"); + ERR_print_errors(bio_err); + return 0; + } + + SSL_CTX_enable_sign_by_dc(ctx); + + return 1; +} +#endif + #if (!defined OPENSSL_NO_NTLS) && (!defined OPENSSL_NO_SM2) \ && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) int set_sign_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key, diff --git a/apps/s_client.c b/apps/s_client.c index 002f6b8d6..4d2d9cd34 100644 --- a/apps/s_client.c +++ b/apps/s_client.c @@ -590,6 +590,10 @@ typedef enum OPTION_choice { #endif #ifndef OPENSSL_NO_SM2 OPT_ENABLE_SM_TLS13_STRICT, +#endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + OPT_ENABLE_VERIFY_PEER_BY_DC, OPT_ENABLE_SIGN_BY_DC, + OPT_DELEGATED_CREDENTIAL, OPT_DELEGATED_CREDENTIAL_PRIVATE_KEY, #endif OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_KEYFORM, OPT_PASS, OPT_CERT_CHAIN, OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH, @@ -772,6 +776,12 @@ const OPTIONS s_client_options[] = { #ifndef OPENSSL_NO_SM2 {"enable_sm_tls13_strict", OPT_ENABLE_SM_TLS13_STRICT, '-', "enable sm tls13 strict"}, #endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + {"dc", OPT_DELEGATED_CREDENTIAL, 's', "delegated crential path"}, + {"dc_pkey", OPT_DELEGATED_CREDENTIAL_PRIVATE_KEY, 's', "c private key path"}, + {"enable_verify_peer_by_dc", OPT_ENABLE_VERIFY_PEER_BY_DC, '-', "enable verify server by delegated crential"}, + {"enable_sign_by_dc", OPT_ENABLE_SIGN_BY_DC, '-', "enable sign by delegated crential"}, +#endif #ifndef OPENSSL_NO_DTLS {"dtls", OPT_DTLS, '-', "Use any version of DTLS"}, {"timeout", OPT_TIMEOUT, '-', @@ -959,6 +969,14 @@ int s_client_main(int argc, char **argv) #endif #ifndef OPENSSL_NO_SM2 int enable_sm_tls13_strict = 0; +#endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + DELEGATED_CREDENTIAL *dc = NULL; + EVP_PKEY *dc_pkey = NULL; + int enable_verify_peer_by_dc = 0; + int enable_sign_by_dc = 0; + const char *s_delegated_credential_file = NULL; + const char *s_delegated_credential_pkey_file = NULL; #endif char *chCApath = NULL, *chCAfile = NULL, *host = NULL; char *port = OPENSSL_strdup(PORT); @@ -1382,6 +1400,20 @@ int s_client_main(int argc, char **argv) case OPT_ENABLE_SM_TLS13_STRICT: enable_sm_tls13_strict = 1; break; +#endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + case OPT_ENABLE_VERIFY_PEER_BY_DC: + enable_verify_peer_by_dc = 1; + break; + case OPT_ENABLE_SIGN_BY_DC: + enable_sign_by_dc = 1; + break; + case OPT_DELEGATED_CREDENTIAL: + s_delegated_credential_file = opt_arg(); + break; + case OPT_DELEGATED_CREDENTIAL_PRIVATE_KEY: + s_delegated_credential_pkey_file = opt_arg(); + break; #endif case OPT_DTLS: #ifndef OPENSSL_NO_DTLS @@ -1733,7 +1765,11 @@ int s_client_main(int argc, char **argv) if (key_file != NULL) { key = load_key(key_file, key_format, 0, pass, e, "client certificate private key file"); - if (key == NULL) { + if (key == NULL +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + && !enable_sign_by_dc +#endif + ) { ERR_print_errors(bio_err); goto end; } @@ -1747,6 +1783,23 @@ int s_client_main(int argc, char **argv) } } +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + if (enable_sign_by_dc) { + dc = DC_load_from_file(s_delegated_credential_file); + if (dc == NULL) { + ERR_print_errors(bio_err); + goto end; + } + + dc_pkey = load_key(s_delegated_credential_pkey_file, key_format, + 0, pass, e, "server dc private key file"); + if (dc_pkey == NULL) { + ERR_print_errors(bio_err); + goto end; + } + } +#endif + #if (!defined OPENSSL_NO_NTLS) && (!defined OPENSSL_NO_SM2) \ && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) /* XXX: don't support cert-key bundle at current stage */ @@ -1847,6 +1900,12 @@ int s_client_main(int argc, char **argv) } #endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + if (enable_verify_peer_by_dc) { + SSL_CTX_enable_verify_peer_by_dc(ctx); + } +#endif + SSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY); if (sdebug) @@ -2055,6 +2114,23 @@ int s_client_main(int argc, char **argv) ssl_ctx_add_crls(ctx, crls, crl_download); +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + if (enable_sign_by_dc) { + if(!set_dc_cert_key_stuff(ctx, cert, dc_pkey, dc, 0)) { + BIO_printf(bio_err, "error setting delegated credential to context\n"); + ERR_print_errors(bio_err); + goto end; + } + + if (key != NULL) { + if (SSL_CTX_use_PrivateKey(ctx, key) <= 0) { + BIO_printf(bio_err, "error setting private key\n"); + ERR_print_errors(bio_err); + return 0; + } + } + } else +#endif if (!set_cert_key_stuff(ctx, cert, key, chain, build_chain)) goto end; @@ -3316,6 +3392,10 @@ int s_client_main(int argc, char **argv) bio_c_out = NULL; BIO_free(bio_c_msg); bio_c_msg = NULL; +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + DC_free(dc); + EVP_PKEY_free(dc_pkey); +#endif return ret; } diff --git a/apps/s_server.c b/apps/s_server.c index c6f14d4df..7860e3fa0 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -750,6 +750,10 @@ typedef enum OPTION_choice { #endif #ifndef OPENSSL_NO_SM2 OPT_ENABLE_SM_TLS13_STRICT, +#endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + OPT_DELEGATED_CREDENTIAL, OPT_DELEGATED_CREDENTIAL_PRIVATE_KEY, + OPT_ENABLE_SIGN_BY_DC, OPT_ENABLE_VERIFY_PEER_BY_DC, #endif OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_LISTEN, OPT_STATELESS, OPT_ID_PREFIX, OPT_SERVERNAME, OPT_SERVERNAME_FATAL, @@ -944,6 +948,12 @@ const OPTIONS s_server_options[] = { #ifndef OPENSSL_NO_SM2 {"enable_sm_tls13_strict", OPT_ENABLE_SM_TLS13_STRICT, '-', "enable sm tls13 strict"}, #endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + {"dc", OPT_DELEGATED_CREDENTIAL, 's', "delegated crential path"}, + {"dc_pkey", OPT_DELEGATED_CREDENTIAL_PRIVATE_KEY, 's', "delegated crential private key path"}, + {"enable_sign_by_dc", OPT_ENABLE_SIGN_BY_DC, '-', "enable sign by delegated crential"}, + {"enable_verify_peer_by_dc", OPT_ENABLE_VERIFY_PEER_BY_DC, '-', "enable verify peer by delegated crential"}, +#endif #ifndef OPENSSL_NO_DTLS {"dtls", OPT_DTLS, '-', "Use any DTLS version"}, {"timeout", OPT_TIMEOUT, '-', "Enable timeouts"}, @@ -1093,6 +1103,14 @@ int s_server_main(int argc, char *argv[]) #ifndef OPENSSL_NO_SCTP int sctp_label_bug = 0; #endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + DELEGATED_CREDENTIAL *dc = NULL; + EVP_PKEY *dc_pkey = NULL; + int enable_sign_by_dc = 0; + int enable_verify_peer_by_dc = 0; + const char *s_delegated_credential_file = NULL; + const char *s_delegated_credential_pkey_file = NULL; +#endif /* Init of few remaining global variables */ local_argc = argc; @@ -1555,6 +1573,20 @@ int s_server_main(int argc, char *argv[]) enable_ntls = 1; break; #endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + case OPT_ENABLE_SIGN_BY_DC: + enable_sign_by_dc = 1; + break; + case OPT_ENABLE_VERIFY_PEER_BY_DC: + enable_verify_peer_by_dc = 1; + break; + case OPT_DELEGATED_CREDENTIAL: + s_delegated_credential_file = opt_arg(); + break; + case OPT_DELEGATED_CREDENTIAL_PRIVATE_KEY: + s_delegated_credential_pkey_file = opt_arg(); + break; +#endif #ifndef OPENSSL_NO_SM2 case OPT_ENABLE_SM_TLS13_STRICT: enable_sm_tls13_strict = 1; @@ -1740,10 +1772,13 @@ int s_server_main(int argc, char *argv[]) goto skip; } #endif - s_key = load_key(s_key_file, s_key_format, 0, pass, engine, "server certificate private key file"); - if (s_key == NULL) { + if (s_key == NULL +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + && !enable_sign_by_dc +#endif + ) { ERR_print_errors(bio_err); goto end; } @@ -1755,6 +1790,23 @@ int s_server_main(int argc, char *argv[]) ERR_print_errors(bio_err); goto end; } +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + if (enable_sign_by_dc) { + dc = DC_load_from_file(s_delegated_credential_file); + if (dc == NULL) { + ERR_print_errors(bio_err); + goto end; + } + + dc_pkey = load_key(s_delegated_credential_pkey_file, s_key_format, + 0, pass, engine, "server dc private key file"); + if (dc_pkey == NULL) { + ERR_print_errors(bio_err); + goto end; + } + } +#endif + if (s_chain_file != NULL) { if (!load_certs(s_chain_file, &s_chain, FORMAT_PEM, NULL, "server certificate chain")) @@ -2143,7 +2195,26 @@ int s_server_main(int argc, char *argv[]) DH_free(dh); } #endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + if (enable_verify_peer_by_dc) + SSL_CTX_enable_verify_peer_by_dc(ctx); + + if (enable_sign_by_dc) { + if(!set_dc_cert_key_stuff(ctx, s_cert, dc_pkey, dc, 1)) { + BIO_printf(bio_err, "error setting delegated credential to context\n"); + ERR_print_errors(bio_err); + goto end; + } + if (s_key != NULL) { + if (SSL_CTX_use_PrivateKey(ctx, s_key) <= 0) { + BIO_printf(bio_err, "error setting private key\n"); + ERR_print_errors(bio_err); + return 0; + } + } + } else +#endif if (!set_cert_key_stuff(ctx, s_cert, s_key, s_chain, build_chain)) goto end; @@ -2348,6 +2419,10 @@ int s_server_main(int argc, char *argv[]) bio_s_msg = NULL; #ifdef CHARSET_EBCDIC BIO_meth_free(methods_ebcdic); +#endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + DC_free(dc); + EVP_PKEY_free(dc_pkey); #endif return ret; } @@ -3332,6 +3407,11 @@ static int www_body(int s, int stype, int prot, unsigned char *context) SSL_SESSION_print(io, SSL_get_session(con)); BIO_printf(io, "---\n"); print_stats(io, SSL_get_SSL_CTX(con)); +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + BIO_printf(io, "---\n"); + BIO_printf(io, "DC tag: %d\n", + SSL_get_delegated_credential_tag(con)); +#endif BIO_printf(io, "---\n"); peer = SSL_get_peer_certificate(con); if (peer != NULL) { diff --git a/crypto/asn1/asn1_err.c b/crypto/asn1/asn1_err.c index 613f9ae71..144c6b01b 100644 --- a/crypto/asn1/asn1_err.c +++ b/crypto/asn1/asn1_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -109,6 +109,9 @@ static const ERR_STRING_DATA ASN1_str_functs[] = { "d2i_AutoPrivateKey"}, {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_PRIVATEKEY, 0), "d2i_PrivateKey"}, {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_PUBLICKEY, 0), "d2i_PublicKey"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DC_NEW, 0), "DC_new"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DC_NEW_FROM_RAW_BYTE, 0), + "DC_new_from_raw_byte"}, {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_BUF, 0), "do_buf"}, {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_CREATE, 0), "do_create"}, {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_DUMP, 0), "do_dump"}, diff --git a/crypto/asn1/build.info b/crypto/asn1/build.info index d3e92c81a..725137d6b 100644 --- a/crypto/asn1/build.info +++ b/crypto/asn1/build.info @@ -3,7 +3,7 @@ SOURCE[../../libcrypto]=\ a_object.c a_bitstr.c a_utctm.c a_gentm.c a_time.c a_int.c a_octet.c \ a_print.c a_type.c a_dup.c a_d2i_fp.c a_i2d_fp.c \ a_utf8.c a_sign.c a_digest.c a_verify.c a_mbstr.c a_strex.c \ - x_algor.c x_val.c x_sig.c x_bignum.c \ + x_algor.c x_val.c x_sig.c x_bignum.c x_delegated_credential.c\ x_long.c x_int64.c x_info.c x_spki.c nsseq.c \ d2i_pu.c d2i_pr.c i2d_pu.c i2d_pr.c\ t_pkey.c t_spki.c t_bitst.c \ diff --git a/crypto/asn1/charmap.h b/crypto/asn1/charmap.h index f15d72d73..e234c9e61 100644 --- a/crypto/asn1/charmap.h +++ b/crypto/asn1/charmap.h @@ -2,7 +2,7 @@ * WARNING: do not edit! * Generated by crypto/asn1/charmap.pl * - * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/asn1/x_delegated_credential.c b/crypto/asn1/x_delegated_credential.c new file mode 100644 index 000000000..0c6ab0bac --- /dev/null +++ b/crypto/asn1/x_delegated_credential.c @@ -0,0 +1,207 @@ +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "crypto/x509.h" +#include "../../ssl/packet_local.h" +#include "../../ssl/ssl_local.h" +#include "internal/refcount.h" + +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +#define MAX_SIGNATURE_LEN 65535 + + + +DELEGATED_CREDENTIAL *DC_new(void) +{ + DELEGATED_CREDENTIAL *dc; + + dc = OPENSSL_zalloc(sizeof(DELEGATED_CREDENTIAL)); + + if (dc == NULL) { + ASN1err(ASN1_F_DC_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + dc->references = 1; + dc->lock = CRYPTO_THREAD_lock_new(); + if (dc->lock == NULL) { + ASN1err(ASN1_F_DC_NEW, ERR_R_MALLOC_FAILURE); + OPENSSL_free(dc); + return NULL; + } + return dc; +} + +void DC_free(DELEGATED_CREDENTIAL *dc) +{ + int i; + + if (dc == NULL) + return; + + CRYPTO_DOWN_REF(&dc->references, &i, dc->lock); + REF_PRINT_COUNT("DC", dc); + if (i > 0) + return; + REF_ASSERT_ISNT(i < 0); + CRYPTO_THREAD_lock_free(dc->lock); + + OPENSSL_free(dc->dc_publickey_raw); + OPENSSL_free(dc->dc_signature); + EVP_PKEY_free(dc->pkey); + OPENSSL_free(dc->raw_byte); + OPENSSL_free(dc); +} + +int DC_up_ref(DELEGATED_CREDENTIAL *dc) +{ + int i; + + if (CRYPTO_UP_REF(&dc->references, &i, dc->lock) <= 0) + return 0; + + REF_PRINT_COUNT("DC", dc); + REF_ASSERT_ISNT(i < 2); + return ((i > 1) ? 1 : 0); +} + + +DELEGATED_CREDENTIAL *DC_new_from_raw_byte(const unsigned char *byte, + unsigned long len) +{ + unsigned long valid_time; + unsigned int expected_cert_verify_algorithm; + unsigned long dc_publickey_raw_len; + unsigned char *dc_publickey_raw = NULL; + unsigned int signature_sign_algorithm; + unsigned int dc_signature_len; + unsigned char *dc_signature = NULL; + PACKET pkt; + DELEGATED_CREDENTIAL *dc = NULL; + EVP_PKEY *pkey = NULL; + + dc = DC_new(); + + if (dc == NULL) { + ASN1err(ASN1_F_DC_NEW_FROM_RAW_BYTE, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if(!DC_set1_raw_byte(dc, byte, len)) { + ASN1err(ASN1_F_DC_NEW_FROM_RAW_BYTE, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (!PACKET_buf_init(&pkt, dc->raw_byte, dc->raw_byte_len)) + goto err; + + if (PACKET_remaining(&pkt) <= 0) { + ASN1err(ASN1_F_DC_NEW_FROM_RAW_BYTE, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!PACKET_get_net_4(&pkt, &valid_time) + || !PACKET_get_net_2(&pkt, &expected_cert_verify_algorithm) + || !PACKET_get_net_3(&pkt, &dc_publickey_raw_len)) { + ASN1err(ASN1_F_DC_NEW_FROM_RAW_BYTE, SSL_R_BAD_PACKET); + goto err; + } + dc->valid_time = valid_time; + dc->expected_cert_verify_algorithm = expected_cert_verify_algorithm; + dc->dc_publickey_raw_len = dc_publickey_raw_len; + + if (dc_publickey_raw_len > pkt.remaining) { + ASN1err(ASN1_F_DC_NEW_FROM_RAW_BYTE, SSL_R_BAD_PACKET); + goto err; + } + dc_publickey_raw = OPENSSL_malloc(dc_publickey_raw_len); + if (dc_publickey_raw == NULL) { + ASN1err(ASN1_F_DC_NEW_FROM_RAW_BYTE, ERR_R_MALLOC_FAILURE); + goto err; + } + + dc->dc_publickey_raw = dc_publickey_raw; + + if (!PACKET_copy_bytes(&pkt, dc_publickey_raw, dc_publickey_raw_len)) { + ASN1err(ASN1_F_DC_NEW_FROM_RAW_BYTE, SSL_R_BAD_PACKET); + goto err; + } + + pkey = d2i_PUBKEY(NULL, (const unsigned char **)&dc_publickey_raw, + dc_publickey_raw_len); + if (pkey == NULL) { + ASN1err(ASN1_F_DC_NEW_FROM_RAW_BYTE, SSL_R_BAD_PACKET); + goto err; + } + dc->pkey = pkey; + + if (!PACKET_get_net_2(&pkt, &signature_sign_algorithm) + || !PACKET_get_net_2(&pkt, &dc_signature_len)) { + ASN1err(ASN1_F_DC_NEW_FROM_RAW_BYTE, SSL_R_BAD_PACKET); + goto err; + } + dc->signature_sign_algorithm = signature_sign_algorithm; + + if (dc_signature_len > pkt.remaining) { + ASN1err(ASN1_F_DC_NEW_FROM_RAW_BYTE, SSL_R_BAD_PACKET); + goto err; + } + dc->dc_signature_len = dc_signature_len; + dc_signature = OPENSSL_malloc(dc_signature_len); + if (dc_signature == NULL) { + ASN1err(ASN1_F_DC_NEW_FROM_RAW_BYTE, SSL_R_BAD_PACKET); + goto err; + } + dc->dc_signature = dc_signature; + + if (!PACKET_copy_bytes(&pkt, dc_signature, dc_signature_len)) { + ASN1err(ASN1_F_DC_NEW_FROM_RAW_BYTE, SSL_R_BAD_PACKET); + goto err; + } + + return dc; +err: + DC_free(dc); + return NULL; +} + +DELEGATED_CREDENTIAL *DC_load_from_file(const char *file) +{ + DELEGATED_CREDENTIAL *dc = NULL; + BIO *bio_dc = NULL; + unsigned char dc_buf[MAX_SIGNATURE_LEN] = {0}; + unsigned char *dc_hex_byte = NULL; + long dc_len = 0; + + bio_dc = BIO_new_file(file, "r"); + if (bio_dc == NULL) { + goto err; + } + + dc_len = BIO_read(bio_dc, dc_buf, 4096); + if (dc_len <= 0) { + goto err; + } + if (dc_buf[dc_len-1] == '\n') + dc_buf[dc_len-1] = 0; + + /* + * parse from hex byte, just for tmp, because there is no + * standard dc format define + */ + dc_hex_byte = OPENSSL_hexstr2buf((const char *)dc_buf, &dc_len); + if (dc_hex_byte == NULL) + goto err; + + dc = DC_new_from_raw_byte(dc_hex_byte, dc_len); + if (dc == NULL) + goto err; + +err: + OPENSSL_free(dc_hex_byte); + BIO_free(bio_dc); + return dc; +} +#endif diff --git a/crypto/async/async_err.c b/crypto/async/async_err.c index fd5527aae..4adce3bb6 100644 --- a/crypto/async/async_err.c +++ b/crypto/async/async_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/bio/bio_err.c b/crypto/bio/bio_err.c index 7aa9dabb2..78d890c6b 100644 --- a/crypto/bio/bio_err.c +++ b/crypto/bio/bio_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/bn/bn_err.c b/crypto/bn/bn_err.c index dd87c152c..398e75b43 100644 --- a/crypto/bn/bn_err.c +++ b/crypto/bn/bn_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/bn/bn_prime.h b/crypto/bn/bn_prime.h index 2eb7b52f7..1a25c2857 100644 --- a/crypto/bn/bn_prime.h +++ b/crypto/bn/bn_prime.h @@ -2,7 +2,7 @@ * WARNING: do not edit! * Generated by crypto/bn/bn_prime.pl * - * Copyright 1998-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/buffer/buf_err.c b/crypto/buffer/buf_err.c index 7e6e53226..dcf927c0d 100644 --- a/crypto/buffer/buf_err.c +++ b/crypto/buffer/buf_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/cms/cms_err.c b/crypto/cms/cms_err.c index a211f4954..fce05485c 100644 --- a/crypto/cms/cms_err.c +++ b/crypto/cms/cms_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/comp/comp_err.c b/crypto/comp/comp_err.c index 2dca315cf..4a95376a8 100644 --- a/crypto/comp/comp_err.c +++ b/crypto/comp/comp_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/conf/conf_def.h b/crypto/conf/conf_def.h index 2016d31b8..1e4a03e10 100644 --- a/crypto/conf/conf_def.h +++ b/crypto/conf/conf_def.h @@ -2,7 +2,7 @@ * WARNING: do not edit! * Generated by crypto/conf/keysets.pl * - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at diff --git a/crypto/conf/conf_err.c b/crypto/conf/conf_err.c index f7613584e..2b024d5d1 100644 --- a/crypto/conf/conf_err.c +++ b/crypto/conf/conf_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/cpt_err.c b/crypto/cpt_err.c index 4147b1cb9..04367b7bf 100644 --- a/crypto/cpt_err.c +++ b/crypto/cpt_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/ct/ct_err.c b/crypto/ct/ct_err.c index c0c62fee6..a5078ac0a 100644 --- a/crypto/ct/ct_err.c +++ b/crypto/ct/ct_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/cversion.c b/crypto/cversion.c index 9d6f50531..75e973d6a 100644 --- a/crypto/cversion.c +++ b/crypto/cversion.c @@ -45,6 +45,10 @@ const char *OpenSSL_version(int t) return "ENGINESDIR: \"" ENGINESDIR "\""; #else return "ENGINESDIR: N/A"; +#endif +#ifndef OPENSSL_NO_QUIC + case OPENSSL_INFO_QUIC: + return "QUIC"; #endif } return "not available"; diff --git a/crypto/dh/dh_err.c b/crypto/dh/dh_err.c index 7285587b4..3a454c74d 100644 --- a/crypto/dh/dh_err.c +++ b/crypto/dh/dh_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/dsa/dsa_err.c b/crypto/dsa/dsa_err.c index 8dcf0548a..b399c0799 100644 --- a/crypto/dsa/dsa_err.c +++ b/crypto/dsa/dsa_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/dso/dso_err.c b/crypto/dso/dso_err.c index 613072a8d..76663a7a2 100644 --- a/crypto/dso/dso_err.c +++ b/crypto/dso/dso_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c index ce3493823..b7de21e73 100644 --- a/crypto/ec/ec_err.c +++ b/crypto/ec/ec_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/engine/eng_err.c b/crypto/engine/eng_err.c index bd1aefa18..01cc43186 100644 --- a/crypto/engine/eng_err.c +++ b/crypto/engine/eng_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 87762f658..c46bc73f2 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -82,6 +82,8 @@ ASN1_F_D2I_ASN1_UINTEGER:150:d2i_ASN1_UINTEGER ASN1_F_D2I_AUTOPRIVATEKEY:207:d2i_AutoPrivateKey ASN1_F_D2I_PRIVATEKEY:154:d2i_PrivateKey ASN1_F_D2I_PUBLICKEY:155:d2i_PublicKey +ASN1_F_DC_NEW:144:DC_new +ASN1_F_DC_NEW_FROM_RAW_BYTE:145:DC_new_from_raw_byte ASN1_F_DO_BUF:142:do_buf ASN1_F_DO_CREATE:124:do_create ASN1_F_DO_DUMP:125:do_dump @@ -814,7 +816,6 @@ EVP_F_RC2_MAGIC_TO_METH:109:rc2_magic_to_meth EVP_F_RC5_CTRL:125:rc5_ctrl EVP_F_R_32_12_16_INIT_KEY:242:r_32_12_16_init_key EVP_F_S390X_AES_GCM_CTRL:201:s390x_aes_gcm_ctrl -EVP_F_SM4_GCM_CTRL:220:sm4_gcm_ctrl EVP_F_UPDATE:173:update KDF_F_PKEY_HKDF_CTRL_STR:103:pkey_hkdf_ctrl_str KDF_F_PKEY_HKDF_DERIVE:102:pkey_hkdf_derive @@ -1134,6 +1135,7 @@ SSL_F_D2I_SSL_SESSION:103:d2i_SSL_SESSION SSL_F_DANE_CTX_ENABLE:347:dane_ctx_enable SSL_F_DANE_MTYPE_SET:393:dane_mtype_set SSL_F_DANE_TLSA_ADD:394:dane_tlsa_add +SSL_F_DC_SIGN:836:DC_sign SSL_F_DERIVE_SECRET_KEY_AND_IV:514:derive_secret_key_and_iv SSL_F_DO_DTLS1_WRITE:245:do_dtls1_write SSL_F_DO_SSL3_WRITE:104:do_ssl3_write @@ -1171,6 +1173,7 @@ SSL_F_FINAL_EC_PT_FORMATS:485:final_ec_pt_formats SSL_F_FINAL_EMS:486:final_ems SSL_F_FINAL_KEY_SHARE:503:final_key_share SSL_F_FINAL_MAXFRAGMENTLEN:557:final_maxfragmentlen +SSL_F_FINAL_QUIC_TRANSPORT_PARAMS:3012:final_quic_transport_params SSL_F_FINAL_RENEGOTIATE:483:final_renegotiate SSL_F_FINAL_SERVER_NAME:558:final_server_name SSL_F_FINAL_SIG_ALGS:497:final_sig_algs @@ -1266,9 +1269,9 @@ SSL_F_PARSE_CA_NAMES_NTLS:702:parse_ca_names_ntls SSL_F_PITEM_NEW:624:pitem_new SSL_F_PQUEUE_NEW:625:pqueue_new SSL_F_PROCESS_KEY_SHARE_EXT:439:* -SSL_F_QUIC_CHANGE_CIPHER_STATE:836:quic_change_cipher_state -SSL_F_QUIC_GET_MESSAGE:837:quic_get_message -SSL_F_QUIC_SET_ENCRYPTION_SECRETS:838:quic_set_encryption_secrets +SSL_F_QUIC_CHANGE_CIPHER_STATE:3000:quic_change_cipher_state +SSL_F_QUIC_GET_MESSAGE:3001:quic_get_message +SSL_F_QUIC_SET_ENCRYPTION_SECRETS:3002:quic_set_encryption_secrets SSL_F_READ_STATE_MACHINE:352:read_state_machine SSL_F_READ_STATE_MACHINE_NTLS:703:read_state_machine_ntls SSL_F_SET_CLIENT_CIPHERSUITE:540:set_client_ciphersuite @@ -1355,6 +1358,10 @@ SSL_F_SSL_CTX_SET_TLSEXT_MAX_FRAGMENT_LENGTH:551:\ SSL_F_SSL_CTX_USE_CERTIFICATE:171:SSL_CTX_use_certificate SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1:172:SSL_CTX_use_certificate_ASN1 SSL_F_SSL_CTX_USE_CERTIFICATE_FILE:173:SSL_CTX_use_certificate_file +SSL_F_SSL_CTX_USE_DC:880:SSL_CTX_use_dc +SSL_F_SSL_CTX_USE_DC_FILE:881:SSL_CTX_use_dc_file +SSL_F_SSL_CTX_USE_DC_PRIVATEKEY:882:SSL_CTX_use_dc +SSL_F_SSL_CTX_USE_DC_PRIVATEKEY_FILE:883:SSL_CTX_use_dc_file SSL_F_SSL_CTX_USE_ENC_CERTIFICATE:661:SSL_CTX_use_enc_certificate SSL_F_SSL_CTX_USE_ENC_CERTIFICATE_FILE:662:SSL_CTX_use_enc_certificate_file SSL_F_SSL_CTX_USE_ENC_PRIVATEKEY:663:SSL_CTX_use_enc_PrivateKey @@ -1375,6 +1382,7 @@ SSL_F_SSL_CTX_USE_SIGN_PRIVATEKEY:667:SSL_CTX_use_sign_PrivateKey SSL_F_SSL_CTX_USE_SIGN_PRIVATEKEY_FILE:668:SSL_CTX_use_sign_PrivateKey_file SSL_F_SSL_DANE_DUP:403:ssl_dane_dup SSL_F_SSL_DANE_ENABLE:395:SSL_dane_enable +SSL_F_SSL_DC_TBS_DATA:855:ssl_dc_tbs_data SSL_F_SSL_DERIVE:590:ssl_derive SSL_F_SSL_DO_CONFIG:391:ssl_do_config SSL_F_SSL_DO_HANDSHAKE:180:SSL_do_handshake @@ -1404,8 +1412,8 @@ SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT:311:* SSL_F_SSL_PEEK:270:SSL_peek SSL_F_SSL_PEEK_EX:432:SSL_peek_ex SSL_F_SSL_PEEK_INTERNAL:522:ssl_peek_internal -SSL_F_SSL_PROCESS_QUIC_POST_HANDSHAKE:841:SSL_process_quic_post_handshake -SSL_F_SSL_PROVIDE_QUIC_DATA:842:SSL_provide_quic_data +SSL_F_SSL_PROCESS_QUIC_POST_HANDSHAKE:3005:SSL_process_quic_post_handshake +SSL_F_SSL_PROVIDE_QUIC_DATA:3006:SSL_provide_quic_data SSL_F_SSL_READ:223:SSL_read SSL_F_SSL_READ_EARLY_DATA:529:SSL_read_early_data SSL_F_SSL_READ_EX:434:SSL_read_ex @@ -1425,6 +1433,8 @@ SSL_F_SSL_SET_CERT_AND_KEY:621:ssl_set_cert_and_key SSL_F_SSL_SET_CERT_IDX:669:ssl_set_cert_idx SSL_F_SSL_SET_CIPHER_LIST:271:SSL_set_cipher_list SSL_F_SSL_SET_CT_VALIDATION_CALLBACK:399:SSL_set_ct_validation_callback +SSL_F_SSL_SET_DC:884:ssl_set_dc +SSL_F_SSL_SET_DC_PKEY:861:ssl_set_dc_pkey SSL_F_SSL_SET_FD:192:SSL_set_fd SSL_F_SSL_SET_PKEY:193:ssl_set_pkey SSL_F_SSL_SET_PKEY_IDX:670:ssl_set_pkey_idx @@ -1444,6 +1454,10 @@ SSL_F_SSL_USE_CERTIFICATE_ASN1:199:SSL_use_certificate_ASN1 SSL_F_SSL_USE_CERTIFICATE_FILE:200:SSL_use_certificate_file SSL_F_SSL_USE_CERTIFICATE_FILE_IDX:848:ssl_use_certificate_file_idx SSL_F_SSL_USE_CERTIFICATE_IDX:849:ssl_use_certificate_idx +SSL_F_SSL_USE_DC:885:SSL_use_dc +SSL_F_SSL_USE_DC_FILE:886:SSL_use_dc_file +SSL_F_SSL_USE_DC_PRIVATEKEY:869:SSL_use_dc_PrivateKey +SSL_F_SSL_USE_DC_PRIVATEKEY_FILE:873:SSL_use_dc_PrivateKey_file SSL_F_SSL_USE_PRIVATEKEY:201:SSL_use_PrivateKey SSL_F_SSL_USE_PRIVATEKEY_ASN1:202:SSL_use_PrivateKey_ASN1 SSL_F_SSL_USE_PRIVATEKEY_FILE:203:SSL_use_PrivateKey_file @@ -1456,6 +1470,8 @@ SSL_F_SSL_USE_RSAPRIVATEKEY_FILE:206:SSL_use_RSAPrivateKey_file SSL_F_SSL_VALIDATE_CT:400:ssl_validate_ct SSL_F_SSL_VERIFY_CERT_CHAIN:207:ssl_verify_cert_chain SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE:616:SSL_verify_client_post_handshake +SSL_F_SSL_VERIFY_DELEGATED_CREDENTIAL_SIGNATURE:856:\ + SSL_verify_delegated_credential_signature SSL_F_SSL_WRITE:208:SSL_write SSL_F_SSL_WRITE_EARLY_DATA:526:SSL_write_early_data SSL_F_SSL_WRITE_EARLY_FINISH:527:* @@ -1492,6 +1508,7 @@ SSL_F_TLS1_SETUP_KEY_BLOCK:211:tls1_setup_key_block SSL_F_TLS1_SET_GROUPS:629:tls1_set_groups SSL_F_TLS1_SET_RAW_SIGALGS:630:tls1_set_raw_sigalgs SSL_F_TLS1_SET_SERVER_SIGALGS:335:tls1_set_server_sigalgs +SSL_F_TLS1_SET_SHARED_DC_SIGALGS:858:tls1_set_shared_dc_sigalgs SSL_F_TLS1_SET_SHARED_SIGALGS:631:tls1_set_shared_sigalgs SSL_F_TLS1_SET_SIGALGS:632:tls1_set_sigalgs SSL_F_TLS_CHOOSE_SIGALG:513:tls_choose_sigalg @@ -1534,6 +1551,8 @@ SSL_F_TLS_CONSTRUCT_CTOS_ALPN_NTLS:721:tls_construct_ctos_alpn_ntls SSL_F_TLS_CONSTRUCT_CTOS_CERTIFICATE:355:* SSL_F_TLS_CONSTRUCT_CTOS_COOKIE:535:tls_construct_ctos_cookie SSL_F_TLS_CONSTRUCT_CTOS_COOKIE_NTLS:722:tls_construct_ctos_cookie_ntls +SSL_F_TLS_CONSTRUCT_CTOS_DELEGATED_CREDENTIAL:853:\ + tls_construct_ctos_delegated_credential SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA:530:tls_construct_ctos_early_data SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA_NTLS:723:tls_construct_ctos_early_data_ntls SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS:467:tls_construct_ctos_ec_pt_formats @@ -1563,8 +1582,10 @@ SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES:509:tls_construct_ctos_psk_kex_modes SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES_NTLS:733:\ tls_construct_ctos_psk_kex_modes_ntls SSL_F_TLS_CONSTRUCT_CTOS_PSK_NTLS:732:tls_construct_ctos_psk_ntls -SSL_F_TLS_CONSTRUCT_CTOS_QUIC_TRANSPORT_PARAMS:844:\ +SSL_F_TLS_CONSTRUCT_CTOS_QUIC_TRANSPORT_PARAMS:3008:\ tls_construct_ctos_quic_transport_params +SSL_F_TLS_CONSTRUCT_CTOS_QUIC_TRANSPORT_PARAMS_DRAFT:3013:\ + tls_construct_ctos_quic_transport_params_draft SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE:473:tls_construct_ctos_renegotiate SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE_NTLS:734:\ tls_construct_ctos_renegotiate_ntls @@ -1594,6 +1615,10 @@ SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS_NTLS:742:\ SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP:482:tls_construct_ctos_use_srtp SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP_NTLS:743:tls_construct_ctos_use_srtp_ntls SSL_F_TLS_CONSTRUCT_CTOS_VERIFY:358:* +SSL_F_TLS_CONSTRUCT_DELEGATED_CREDENTIAL_RAW:866:\ + tls_construct_delegated_credential_raw +SSL_F_TLS_CONSTRUCT_DELEGATED_CREDENTIAL_REQUEST:867:\ + tls_construct_delegated_credential_request SSL_F_TLS_CONSTRUCT_ENCRYPTED_EXTENSIONS:443:tls_construct_encrypted_extensions SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA:536:tls_construct_end_of_early_data SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA_NTLS:744:\ @@ -1627,6 +1652,8 @@ SSL_F_TLS_CONSTRUCT_STOC_COOKIE_NTLS:754:tls_construct_stoc_cookie_ntls SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG:452:tls_construct_stoc_cryptopro_bug SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG_NTLS:755:\ tls_construct_stoc_cryptopro_bug_ntls +SSL_F_TLS_CONSTRUCT_STOC_DELEGATED_CREDENTIAL:863:\ + tls_construct_stoc_delegated_credential SSL_F_TLS_CONSTRUCT_STOC_DONE:375:* SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA:531:tls_construct_stoc_early_data SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA_INFO:525:* @@ -1650,8 +1677,10 @@ SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG_NTLS:762:\ tls_construct_stoc_next_proto_neg_ntls SSL_F_TLS_CONSTRUCT_STOC_PSK:504:tls_construct_stoc_psk SSL_F_TLS_CONSTRUCT_STOC_PSK_NTLS:763:tls_construct_stoc_psk_ntls -SSL_F_TLS_CONSTRUCT_STOC_QUIC_TRANSPORT_PARAMS:845:\ +SSL_F_TLS_CONSTRUCT_STOC_QUIC_TRANSPORT_PARAMS:3009:\ tls_construct_stoc_quic_transport_params +SSL_F_TLS_CONSTRUCT_STOC_QUIC_TRANSPORT_PARAMS_DRAFT:3014:\ + tls_construct_stoc_quic_transport_params_draft SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE:458:tls_construct_stoc_renegotiate SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE_NTLS:764:\ tls_construct_stoc_renegotiate_ntls @@ -1674,6 +1703,8 @@ SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS_NTLS:769:\ tls_construct_stoc_supported_versions_ntls SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP:462:tls_construct_stoc_use_srtp SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP_NTLS:770:tls_construct_stoc_use_srtp_ntls +SSL_F_TLS_DETERMINE_IF_USE_DC_FROM_EXTENSION:865:\ + tls_determine_if_use_dc_from_extension SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO:521:\ tls_early_post_process_client_hello SSL_F_TLS_FINISH_HANDSHAKE:597:tls_finish_handshake @@ -1690,6 +1721,8 @@ SSL_F_TLS_PARSE_CTOS_ALPN:567:tls_parse_ctos_alpn SSL_F_TLS_PARSE_CTOS_ALPN_NTLS:774:tls_parse_ctos_alpn_ntls SSL_F_TLS_PARSE_CTOS_COOKIE:614:tls_parse_ctos_cookie SSL_F_TLS_PARSE_CTOS_COOKIE_NTLS:775:tls_parse_ctos_cookie_ntls +SSL_F_TLS_PARSE_CTOS_DELEGATED_CREDENTIAL:862:\ + tls_parse_ctos_delegated_credential SSL_F_TLS_PARSE_CTOS_EARLY_DATA:568:tls_parse_ctos_early_data SSL_F_TLS_PARSE_CTOS_EARLY_DATA_NTLS:776:tls_parse_ctos_early_data_ntls SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS:569:tls_parse_ctos_ec_pt_formats @@ -1707,8 +1740,10 @@ SSL_F_TLS_PARSE_CTOS_PSK:505:tls_parse_ctos_psk SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES:572:tls_parse_ctos_psk_kex_modes SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES_NTLS:783:tls_parse_ctos_psk_kex_modes_ntls SSL_F_TLS_PARSE_CTOS_PSK_NTLS:782:tls_parse_ctos_psk_ntls -SSL_F_TLS_PARSE_CTOS_QUIC_TRANSPORT_PARAMS:846:\ +SSL_F_TLS_PARSE_CTOS_QUIC_TRANSPORT_PARAMS:3010:\ tls_parse_ctos_quic_transport_params +SSL_F_TLS_PARSE_CTOS_QUIC_TRANSPORT_PARAMS_DRAFT:3015:\ + tls_parse_ctos_quic_transport_params_draft SSL_F_TLS_PARSE_CTOS_RENEGOTIATE:464:tls_parse_ctos_renegotiate SSL_F_TLS_PARSE_CTOS_RENEGOTIATE_NTLS:784:tls_parse_ctos_renegotiate_ntls SSL_F_TLS_PARSE_CTOS_SERVER_NAME:573:tls_parse_ctos_server_name @@ -1728,10 +1763,13 @@ SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS_NTLS:791:\ tls_parse_ctos_supported_groups_ntls SSL_F_TLS_PARSE_CTOS_USE_SRTP:465:tls_parse_ctos_use_srtp SSL_F_TLS_PARSE_CTOS_USE_SRTP_NTLS:792:tls_parse_ctos_use_srtp_ntls +SSL_F_TLS_PARSE_DC_FROM_EXTENSION:864:tls_parse_dc_from_extension SSL_F_TLS_PARSE_STOC_ALPN:579:tls_parse_stoc_alpn SSL_F_TLS_PARSE_STOC_ALPN_NTLS:793:tls_parse_stoc_alpn_ntls SSL_F_TLS_PARSE_STOC_COOKIE:534:tls_parse_stoc_cookie SSL_F_TLS_PARSE_STOC_COOKIE_NTLS:794:tls_parse_stoc_cookie_ntls +SSL_F_TLS_PARSE_STOC_DELEGATED_CREDENTIAL:854:\ + tls_parse_stoc_delegated_credential SSL_F_TLS_PARSE_STOC_EARLY_DATA:538:tls_parse_stoc_early_data SSL_F_TLS_PARSE_STOC_EARLY_DATA_INFO:528:* SSL_F_TLS_PARSE_STOC_EARLY_DATA_NTLS:795:tls_parse_stoc_early_data_ntls @@ -1745,8 +1783,10 @@ SSL_F_TLS_PARSE_STOC_NPN:582:tls_parse_stoc_npn SSL_F_TLS_PARSE_STOC_NPN_NTLS:799:tls_parse_stoc_npn_ntls SSL_F_TLS_PARSE_STOC_PSK:502:tls_parse_stoc_psk SSL_F_TLS_PARSE_STOC_PSK_NTLS:800:tls_parse_stoc_psk_ntls -SSL_F_TLS_PARSE_STOC_QUIC_TRANSPORT_PARAMS:847:\ +SSL_F_TLS_PARSE_STOC_QUIC_TRANSPORT_PARAMS:3011:\ tls_parse_stoc_quic_transport_params +SSL_F_TLS_PARSE_STOC_QUIC_TRANSPORT_PARAMS_DRAFT:3016:\ + tls_parse_stoc_quic_transport_params_draft SSL_F_TLS_PARSE_STOC_RENEGOTIATE:448:tls_parse_stoc_renegotiate SSL_F_TLS_PARSE_STOC_RENEGOTIATE_NTLS:801:tls_parse_stoc_renegotiate_ntls SSL_F_TLS_PARSE_STOC_SCT:564:tls_parse_stoc_sct @@ -1797,6 +1837,7 @@ SSL_F_TLS_PROCESS_CLIENT_HELLO_NTLS:816:tls_process_client_hello_ntls SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE:382:tls_process_client_key_exchange SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE_NTLS:817:\ tls_process_client_key_exchange_ntls +SSL_F_TLS_PROCESS_DC_REQUEST:868:tls_process_dc_request SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS:444:tls_process_encrypted_extensions SSL_F_TLS_PROCESS_END_OF_EARLY_DATA:537:tls_process_end_of_early_data SSL_F_TLS_PROCESS_END_OF_EARLY_DATA_NTLS:818:tls_process_end_of_early_data_ntls @@ -1989,6 +2030,7 @@ X509_F_CHECK_NAME_CONSTRAINTS:149:check_name_constraints X509_F_CHECK_POLICY:145:check_policy X509_F_COMMON_VERIFY_SM2:161:common_verify_sm2 X509_F_DANE_I2D:107:dane_i2d +X509_F_DC_CHECK_PRIVATE_KEY:164:DC_check_private_key X509_F_DIR_CTRL:102:dir_ctrl X509_F_GET_CERT_BY_SUBJECT:103:get_cert_by_subject X509_F_I2D_X509_AUX:151:i2d_X509_AUX @@ -2962,6 +3004,8 @@ SSL_R_DANE_TLSA_BAD_SELECTOR:202:dane tlsa bad selector SSL_R_DANE_TLSA_NULL_DATA:203:dane tlsa null data SSL_R_DATA_BETWEEN_CCS_AND_FINISHED:145:data between ccs and finished SSL_R_DATA_LENGTH_TOO_LONG:146:data length too long +SSL_R_DC_LOAD_FAILED:457:failed to load delegated credential +SSL_R_DC_VALID_TIME_TOO_LARGE:346:DC valid time too large SSL_R_DECRYPTION_FAILED:147:decryption failed SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC:281:\ decryption failed or bad record mac @@ -2972,6 +3016,7 @@ SSL_R_DTLS_MESSAGE_TOO_BIG:334:dtls message too big SSL_R_DUPLICATE_COMPRESSION_ID:309:duplicate compression id SSL_R_ECC_CERT_NOT_FOR_SIGNING:318:ecc cert not for signing SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE:374:ecdh required for suiteb mode +SSL_R_EE_CERT_NOT_FOUND:393:ee cert not found SSL_R_EE_KEY_TOO_SMALL:399:ee key too small SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST:354:empty srtp protection profile list SSL_R_ENCRYPTED_LENGTH_TOO_LONG:150:encrypted length too long @@ -2983,7 +3028,9 @@ SSL_R_EXTENSION_NOT_RECEIVED:279:extension not received SSL_R_EXTRA_DATA_IN_MESSAGE:153:extra data in message SSL_R_EXT_LENGTH_MISMATCH:163:ext length mismatch SSL_R_FAILED_TO_INIT_ASYNC:405:failed to init async +SSL_R_FAILED_TO_VERIFY_DC_SIGNATURE:453:failed to verify dc signature SSL_R_FRAGMENTED_CLIENT_HELLO:401:fragmented client hello +SSL_R_GET_SIG_AND_HASH_ERR:450:unable to get sig and hash SSL_R_GOT_A_FIN_BEFORE_A_CCS:154:got a fin before a ccs SSL_R_HTTPS_PROXY_REQUEST:155:https proxy request SSL_R_HTTP_REQUEST:156:http request @@ -3023,6 +3070,8 @@ SSL_R_MISSING_DSA_SIGNING_CERT:165:missing dsa signing cert SSL_R_MISSING_ECDSA_SIGNING_CERT:381:missing ecdsa signing cert SSL_R_MISSING_FATAL:256:missing fatal SSL_R_MISSING_PARAMETERS:290:missing parameters +SSL_R_MISSING_QUIC_TRANSPORT_PARAMETERS_EXTENSION:801:\ + missing quic transport parameters extension SSL_R_MISSING_RSA_CERTIFICATE:168:missing rsa certificate SSL_R_MISSING_RSA_ENCRYPTING_CERT:169:missing rsa encrypting cert SSL_R_MISSING_RSA_SIGNING_CERT:170:missing rsa signing cert @@ -3081,6 +3130,7 @@ SSL_R_PEM_NAME_BAD_PREFIX:391:pem name bad prefix SSL_R_PEM_NAME_TOO_SHORT:392:pem name too short SSL_R_PIPELINE_FAILURE:406:pipeline failure SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR:278:post handshake auth encoding err +SSL_R_PRIVATE_KEY_DOES_NOT_MATCH_DC:454:private key does not match dc SSL_R_PRIVATE_KEY_MISMATCH:288:private key mismatch SSL_R_PROTOCOL_IS_SHUTDOWN:207:protocol is shutdown SSL_R_PSK_IDENTITY_NOT_FOUND:223:psk identity not found @@ -3143,6 +3193,7 @@ SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS:239:\ unable to find public key parameters SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES:242:unable to load ssl3 md5 routines SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES:243:unable to load ssl3 sha1 routines +SSL_R_UNABLE_TO_LOOKUP_CERT:451:unable to lookup cert SSL_R_UNEXPECTED_CCS_MESSAGE:262:unexpected ccs message SSL_R_UNEXPECTED_END_OF_EARLY_DATA:178:unexpected end of early data SSL_R_UNEXPECTED_MESSAGE:244:unexpected message @@ -3174,7 +3225,7 @@ SSL_R_VERSION_TOO_LOW:396:version too low SSL_R_WRONG_CERTIFICATE_TYPE:383:wrong certificate type SSL_R_WRONG_CIPHER_RETURNED:261:wrong cipher returned SSL_R_WRONG_CURVE:378:wrong curve -SSL_R_WRONG_ENCRYPTION_LEVEL_RECEIVED:316:wrong encryption level received +SSL_R_WRONG_ENCRYPTION_LEVEL_RECEIVED:800:wrong encryption level received SSL_R_WRONG_SIGNATURE_LENGTH:264:wrong signature length SSL_R_WRONG_SIGNATURE_SIZE:265:wrong signature size SSL_R_WRONG_SIGNATURE_TYPE:370:wrong signature type diff --git a/crypto/evp/e_sm4.c b/crypto/evp/e_sm4.c index 78a6bb0df..3036a924c 100644 --- a/crypto/evp/e_sm4.c +++ b/crypto/evp/e_sm4.c @@ -348,6 +348,9 @@ int sm4_gcm_ctrl (EVP_CIPHER_CTX *c, int type, int arg, void *ptr) } return 1; } + case EVP_CTRL_AEAD_SET_MAC_KEY: + /* no-op */ + return 1; default: return -1; } @@ -387,6 +390,87 @@ static int sm4_gcm_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, return 1; } +/* + * Handle TLS GCM packet format. This consists of the last portion of the IV + * followed by the payload and finally the tag. On encrypt generate IV, + * encrypt payload and write the tag. On verify retrieve IV, decrypt payload + * and verify tag. + */ + +static int sm4_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_SM4_GCM_CTX *gctx = EVP_C_DATA(EVP_SM4_GCM_CTX,ctx); + int rv = -1; + /* Encrypt/decrypt must be performed in place */ + if (out != in + || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN)) + return -1; + /* + * Set IV from start of buffer or generate IV and write to start of + * buffer. + */ + if (EVP_CIPHER_CTX_ctrl(ctx, ctx->encrypt ? EVP_CTRL_GCM_IV_GEN + : EVP_CTRL_GCM_SET_IV_INV, + EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0) + goto err; + /* Use saved AAD */ + if (CRYPTO_gcm128_aad(&gctx->gcm, ctx->buf, gctx->tls_aad_len)) + goto err; + /* Fix buffer and length to point to payload */ + in += EVP_GCM_TLS_EXPLICIT_IV_LEN; + out += EVP_GCM_TLS_EXPLICIT_IV_LEN; + len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; + if (ctx->encrypt) { + /* Encrypt payload */ + if (gctx->ctr) { + size_t bulk = 0; + if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, + in + bulk, + out + bulk, + len - bulk, gctx->ctr)) + goto err; + } else { + size_t bulk = 0; + if (CRYPTO_gcm128_encrypt(&gctx->gcm, + in + bulk, out + bulk, len - bulk)) + goto err; + } + out += len; + /* Finally write tag */ + CRYPTO_gcm128_tag(&gctx->gcm, out, EVP_GCM_TLS_TAG_LEN); + rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; + } else { + /* Decrypt */ + if (gctx->ctr) { + size_t bulk = 0; + if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, + in + bulk, + out + bulk, + len - bulk, gctx->ctr)) + goto err; + } else { + size_t bulk = 0; + if (CRYPTO_gcm128_decrypt(&gctx->gcm, + in + bulk, out + bulk, len - bulk)) + goto err; + } + /* Retrieve tag */ + CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, EVP_GCM_TLS_TAG_LEN); + /* If tag mismatch wipe buffer */ + if (CRYPTO_memcmp(ctx->buf, in + len, EVP_GCM_TLS_TAG_LEN)) { + OPENSSL_cleanse(out, len); + goto err; + } + rv = len; + } + + err: + gctx->iv_set = 0; + gctx->tls_aad_len = -1; + return rv; +} + static int sm4_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t len) { @@ -396,6 +480,9 @@ static int sm4_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, if (!gctx->key_set) return -1; + if (gctx->tls_aad_len >= 0) + return sm4_gcm_tls_cipher(ctx, out, in, len); + if (!gctx->iv_set) return -1; diff --git a/crypto/kdf/kdf_err.c b/crypto/kdf/kdf_err.c index 1627c0a39..c1c09c7ea 100644 --- a/crypto/kdf/kdf_err.c +++ b/crypto/kdf/kdf_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h index c09519af8..274a112fb 100644 --- a/crypto/objects/obj_dat.h +++ b/crypto/objects/obj_dat.h @@ -2,7 +2,7 @@ * WARNING: do not edit! * Generated by crypto/objects/obj_dat.pl * - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at @@ -10,7 +10,7 @@ */ /* Serialized OID's */ -static const unsigned char so[7786] = { +static const unsigned char so[7795] = { 0x2A,0x86,0x48,0x86,0xF7,0x0D, /* [ 0] OBJ_rsadsi */ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, /* [ 6] OBJ_pkcs */ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x02, /* [ 13] OBJ_md2 */ @@ -1079,9 +1079,10 @@ static const unsigned char so[7786] = { 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x08, /* [ 7761] OBJ_sm4_gcm */ 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x09, /* [ 7769] OBJ_sm4_ccm */ 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x75, /* [ 7777] OBJ_SM2_with_SM3 */ + 0x2B,0x06,0x01,0x04,0x01,0x82,0xDA,0x4B,0x2C, /* [ 7785] OBJ_delegation_usage */ }; -#define NUM_NID 1201 +#define NUM_NID 1202 static const ASN1_OBJECT nid_objs[NUM_NID] = { {"UNDEF", "undefined", NID_undef}, {"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]}, @@ -2284,9 +2285,10 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = { {"KxSM2", "kx-sm2", NID_kx_sm2}, {"KxSM2DHE", "kx-sm2dhe", NID_kx_sm2dhe}, {"AuthSM2", "auth-sm2", NID_auth_sm2}, + {"delegationUsage", "X509v3 Delegation Usage", NID_delegation_usage, 9, &so[7785]}, }; -#define NUM_SN 1192 +#define NUM_SN 1193 static const unsigned int sn_objs[NUM_SN] = { 364, /* "AD_DVCS" */ 419, /* "AES-128-CBC" */ @@ -2679,6 +2681,7 @@ static const unsigned int sn_objs[NUM_SN] = { 495, /* "dSAQuality" */ 434, /* "data" */ 390, /* "dcobject" */ + 1201, /* "delegationUsage" */ 140, /* "deltaCRL" */ 891, /* "deltaRevocationList" */ 107, /* "description" */ @@ -3482,7 +3485,7 @@ static const unsigned int sn_objs[NUM_SN] = { 1093, /* "x509ExtAdmission" */ }; -#define NUM_LN 1192 +#define NUM_LN 1193 static const unsigned int ln_objs[NUM_LN] = { 363, /* "AD Time Stamping" */ 405, /* "ANSI X9.62" */ @@ -3672,6 +3675,7 @@ static const unsigned int ln_objs[NUM_LN] = { 141, /* "X509v3 CRL Reason Code" */ 771, /* "X509v3 Certificate Issuer" */ 89, /* "X509v3 Certificate Policies" */ + 1201, /* "X509v3 Delegation Usage" */ 140, /* "X509v3 Delta CRL Indicator" */ 126, /* "X509v3 Extended Key Usage" */ 857, /* "X509v3 Freshest CRL" */ @@ -4678,7 +4682,7 @@ static const unsigned int ln_objs[NUM_LN] = { 125, /* "zlib compression" */ }; -#define NUM_OBJ 1074 +#define NUM_OBJ 1075 static const unsigned int obj_objs[NUM_OBJ] = { 0, /* OBJ_undef 0 */ 181, /* OBJ_iso 1 */ @@ -5453,6 +5457,7 @@ static const unsigned int obj_objs[NUM_OBJ] = { 683, /* OBJ_X9_62_ppBasis 1 2 840 10045 1 2 3 3 */ 417, /* OBJ_ms_csp_name 1 3 6 1 4 1 311 17 1 */ 856, /* OBJ_LocalKeySet 1 3 6 1 4 1 311 17 2 */ + 1201, /* OBJ_delegation_usage 1 3 6 1 4 1 44363 44 */ 390, /* OBJ_dcObject 1 3 6 1 4 1 1466 344 */ 91, /* OBJ_bf_cbc 1 3 6 1 4 1 3029 1 2 */ 973, /* OBJ_id_scrypt 1 3 6 1 4 1 11591 4 11 */ diff --git a/crypto/objects/obj_err.c b/crypto/objects/obj_err.c index be4f11ca2..91b8ab3b4 100644 --- a/crypto/objects/obj_err.c +++ b/crypto/objects/obj_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num index 85825b09d..7fa750392 100644 --- a/crypto/objects/obj_mac.num +++ b/crypto/objects/obj_mac.num @@ -1198,3 +1198,4 @@ SM2_with_SM3 1197 kx_sm2 1198 kx_sm2dhe 1199 auth_sm2 1200 +delegation_usage 1201 diff --git a/crypto/objects/obj_xref.h b/crypto/objects/obj_xref.h index df8bba111..5c15ccc9f 100644 --- a/crypto/objects/obj_xref.h +++ b/crypto/objects/obj_xref.h @@ -2,7 +2,7 @@ * WARNING: do not edit! * Generated by objxref.pl * - * Copyright 1998-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt index 32df2d6d8..25b383076 100644 --- a/crypto/objects/objects.txt +++ b/crypto/objects/objects.txt @@ -816,6 +816,8 @@ id-ce 35 : authorityKeyIdentifier : X509v3 Authority Key Identifier id-ce 36 : policyConstraints : X509v3 Policy Constraints !Cname ext-key-usage id-ce 37 : extendedKeyUsage : X509v3 Extended Key Usage +!Cname delegation-usage +1 3 6 1 4 1 44363 44 : delegationUsage : X509v3 Delegation Usage !Cname freshest-crl id-ce 46 : freshestCRL : X509v3 Freshest CRL !Cname inhibit-any-policy diff --git a/crypto/ocsp/ocsp_err.c b/crypto/ocsp/ocsp_err.c index 660e19366..8a73d61e2 100644 --- a/crypto/ocsp/ocsp_err.c +++ b/crypto/ocsp/ocsp_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/pem/pem_err.c b/crypto/pem/pem_err.c index f642030aa..efce1b8e8 100644 --- a/crypto/pem/pem_err.c +++ b/crypto/pem/pem_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/pkcs12/pk12err.c b/crypto/pkcs12/pk12err.c index 38ce5197e..638f794a3 100644 --- a/crypto/pkcs12/pk12err.c +++ b/crypto/pkcs12/pk12err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/pkcs7/pkcs7err.c b/crypto/pkcs7/pkcs7err.c index 07490c1a5..ea35b4c6e 100644 --- a/crypto/pkcs7/pkcs7err.c +++ b/crypto/pkcs7/pkcs7err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/rand/rand_err.c b/crypto/rand/rand_err.c index a3ae5f53c..f65ac3d20 100644 --- a/crypto/rand/rand_err.c +++ b/crypto/rand/rand_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/rsa/rsa_err.c b/crypto/rsa/rsa_err.c index 0687c1e62..44583d019 100644 --- a/crypto/rsa/rsa_err.c +++ b/crypto/rsa/rsa_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/sm2/sm2_err.c b/crypto/sm2/sm2_err.c index dbf734e07..3f5d916d2 100644 --- a/crypto/sm2/sm2_err.c +++ b/crypto/sm2/sm2_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/store/store_err.c b/crypto/store/store_err.c index 5a8a8404d..0e0698016 100644 --- a/crypto/store/store_err.c +++ b/crypto/store/store_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/ts/ts_err.c b/crypto/ts/ts_err.c index 1f3854d84..fb5c0470b 100644 --- a/crypto/ts/ts_err.c +++ b/crypto/ts/ts_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/ui/ui_err.c b/crypto/ui/ui_err.c index b806872c3..9016e66a0 100644 --- a/crypto/ui/ui_err.c +++ b/crypto/ui/ui_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c index 99920e299..c4b849256 100644 --- a/crypto/x509/x509_cmp.c +++ b/crypto/x509/x509_cmp.c @@ -469,3 +469,260 @@ STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain) sk_X509_free(ret); return NULL; } + +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +int DC_check_private_key(DELEGATED_CREDENTIAL *dc, EVP_PKEY *pkey) +{ + EVP_PKEY *pub_key; + int ret; + + pub_key = dc->pkey; + + if (pub_key) + ret = EVP_PKEY_cmp(pub_key, pkey); + else + ret = -2; + + switch (ret) { + case 1: + break; + case 0: + X509err(X509_F_DC_CHECK_PRIVATE_KEY, X509_R_KEY_VALUES_MISMATCH); + break; + case -1: + X509err(X509_F_DC_CHECK_PRIVATE_KEY, X509_R_KEY_TYPE_MISMATCH); + break; + case -2: + X509err(X509_F_DC_CHECK_PRIVATE_KEY, X509_R_UNKNOWN_KEY_TYPE); + } + if (ret > 0) + return 1; + return 0; +} + +int DC_check_valid(X509 *parent_cert, DELEGATED_CREDENTIAL *dc) +{ + /* + * check if dc time expire + */ + if (!DC_check_time_valid(parent_cert, dc)) + return 0; + /* + * check dc parent_cert has DelegationUsage extension. + * check dc parent_cert has the digitalSignature KeyUsage + * see https://tools.ietf.org/html/draft-ietf-tls-subcerts-07#section-4.2 + */ + if (!DC_check_parent_cert_valid(parent_cert)) + return 0; + + return 1; +} + +int DC_check_time_valid(X509 *parent_cert, DELEGATED_CREDENTIAL *dc) +{ + ASN1_TIME *time; + struct tm tm; + int ret = 0; + + time = ASN1_STRING_dup(X509_get0_notBefore(parent_cert)); + if (time == NULL) + goto err; + if (!ASN1_TIME_to_tm(time, &tm)) + goto err; + if (ASN1_TIME_adj(time, mktime(&tm), 0, DC_get_valid_time(dc)) == NULL) + goto err; + if (X509_cmp_time(time, NULL) <= 0) + goto err; + + ret = 1; +err: + ASN1_STRING_clear_free(time); + return ret; +} + +int DC_check_parent_cert_valid(X509 *parent_cert) +{ + const STACK_OF(X509_EXTENSION) *exts; + int i; + + if ((X509_get_key_usage(parent_cert) & X509v3_KU_DIGITAL_SIGNATURE) == 0) + return 0; + + exts = X509_get0_extensions(parent_cert); + for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { + ASN1_OBJECT *obj; + X509_EXTENSION *ex; + + ex = sk_X509_EXTENSION_value(exts, i); + obj = X509_EXTENSION_get_object(ex); + if (OBJ_obj2nid(obj) == NID_delegation_usage) { + int critical; + + critical = X509_EXTENSION_get_critical(ex); + if (critical == 1) + return 0; + + return 1; + } + } + + return 0; +} + +unsigned long DC_get_valid_time(DELEGATED_CREDENTIAL *dc) +{ + return dc->valid_time; +} + +unsigned int DC_get_expected_cert_verify_algorithm(DELEGATED_CREDENTIAL *dc) +{ + return dc->expected_cert_verify_algorithm; +} + +unsigned long DC_get_dc_publickey_raw_len(DELEGATED_CREDENTIAL *dc) +{ + return dc->dc_publickey_raw_len; +} + +unsigned char *DC_get0_dc_publickey_raw(DELEGATED_CREDENTIAL *dc) +{ + return dc->dc_publickey_raw; +} + +unsigned int DC_get_signature_sign_algorithm(DELEGATED_CREDENTIAL *dc) +{ + return dc->signature_sign_algorithm; +} + +unsigned int DC_get_dc_signature_len(DELEGATED_CREDENTIAL *dc) +{ + return dc->dc_signature_len; +} + +unsigned char *DC_get0_dc_signature(DELEGATED_CREDENTIAL *dc) +{ + return dc->dc_signature; +} + +EVP_PKEY *DC_get0_publickey(DELEGATED_CREDENTIAL *dc) +{ + return dc->pkey; +} + +unsigned char *DC_get0_raw_byte(DELEGATED_CREDENTIAL *dc) +{ + return dc->raw_byte; +} + +unsigned long DC_get_raw_byte_len(DELEGATED_CREDENTIAL *dc) +{ + return dc->raw_byte_len; +} + +int DC_set_valid_time(DELEGATED_CREDENTIAL *dc, unsigned long valid_time) +{ + if (dc == NULL) + return 0; + dc->valid_time = valid_time; + return 1; +} + +int DC_set_expected_cert_verify_algorithm(DELEGATED_CREDENTIAL *dc, unsigned int alg) +{ + if (dc == NULL) + return 0; + dc->expected_cert_verify_algorithm = alg; + return 1; +} + +int DC_set_dc_publickey_len(DELEGATED_CREDENTIAL *dc, unsigned long len) +{ + if (dc == NULL) + return 0; + dc->dc_publickey_raw_len = len; + return 1; +} + +int DC_set0_dc_publickey(DELEGATED_CREDENTIAL *dc, unsigned char *pub_key) +{ + if (dc == NULL) + return 0; + dc->dc_publickey_raw = pub_key; + return 1; +} + +int DC_set_signature_sign_algorithm(DELEGATED_CREDENTIAL *dc, unsigned int alg) +{ + if (dc == NULL) + return 0; + dc->signature_sign_algorithm = alg; + return 1; +} + +int DC_set_dc_signature_len(DELEGATED_CREDENTIAL *dc, unsigned int len) +{ + if (dc == NULL) + return 0; + dc->dc_signature_len = len; + return 1; +} + +int DC_set0_dc_signature(DELEGATED_CREDENTIAL *dc, unsigned char *sig) +{ + if (dc == NULL) + return 0; + dc->dc_signature = sig; + return 1; +} + +int DC_set0_publickey(DELEGATED_CREDENTIAL *dc, EVP_PKEY *pkey) +{ + if (dc == NULL) + return 0; + dc->pkey = pkey; + return 1; +} + +int DC_set0_raw_byte(DELEGATED_CREDENTIAL *dc, unsigned char *byte, + unsigned long len) +{ + if (dc == NULL) + return 0; + + if (dc->raw_byte && dc->raw_byte != byte) + OPENSSL_free(dc->raw_byte); + + dc->raw_byte = byte; + dc->raw_byte_len = len; + + return 1; +} + +int DC_set1_raw_byte(DELEGATED_CREDENTIAL *dc, const unsigned char *byte, + unsigned long len) +{ + unsigned char *raw_byte = NULL; + + if (dc == NULL || byte == NULL || len <= 0) + return 0; + + if (dc->raw_byte == byte) { + dc->raw_byte_len = len; + return 1; + } + + raw_byte = OPENSSL_malloc(len); + if (raw_byte == NULL) + return 0; + + if (dc->raw_byte) { + OPENSSL_free(dc->raw_byte); + } + + memcpy(raw_byte, byte, len); + dc->raw_byte = raw_byte; + dc->raw_byte_len = len; + return 1; +} + +#endif diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c index 0df5cace1..f218ad04b 100644 --- a/crypto/x509/x509_err.c +++ b/crypto/x509/x509_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -22,6 +22,8 @@ static const ERR_STRING_DATA X509_str_functs[] = { {ERR_PACK(ERR_LIB_X509, X509_F_CHECK_POLICY, 0), "check_policy"}, {ERR_PACK(ERR_LIB_X509, X509_F_COMMON_VERIFY_SM2, 0), "common_verify_sm2"}, {ERR_PACK(ERR_LIB_X509, X509_F_DANE_I2D, 0), "dane_i2d"}, + {ERR_PACK(ERR_LIB_X509, X509_F_DC_CHECK_PRIVATE_KEY, 0), + "DC_check_private_key"}, {ERR_PACK(ERR_LIB_X509, X509_F_DIR_CTRL, 0), "dir_ctrl"}, {ERR_PACK(ERR_LIB_X509, X509_F_GET_CERT_BY_SUBJECT, 0), "get_cert_by_subject"}, diff --git a/crypto/x509v3/ext_dat.h b/crypto/x509v3/ext_dat.h index 762e264bb..cb1d4669f 100644 --- a/crypto/x509v3/ext_dat.h +++ b/crypto/x509v3/ext_dat.h @@ -10,6 +10,9 @@ int name_cmp(const char *name, const char *cmp); extern const X509V3_EXT_METHOD v3_bcons, v3_nscert, v3_key_usage, v3_ext_ku; +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +extern const X509V3_EXT_METHOD v3_dc_usage; +#endif extern const X509V3_EXT_METHOD v3_pkey_usage_period, v3_sxnet, v3_info, v3_sinfo; extern const X509V3_EXT_METHOD v3_ns_ia5_list[8], v3_alt[3], v3_skey_id, v3_akey_id; extern const X509V3_EXT_METHOD v3_crl_num, v3_crl_reason, v3_crl_invdate; diff --git a/crypto/x509v3/standard_exts.h b/crypto/x509v3/standard_exts.h index 944f4de02..eb0461c41 100644 --- a/crypto/x509v3/standard_exts.h +++ b/crypto/x509v3/standard_exts.h @@ -69,7 +69,10 @@ static const X509V3_EXT_METHOD *standard_exts[] = { &v3_ct_scts[2], #endif &v3_tls_feature, - &v3_ext_admission + &v3_ext_admission, +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + &v3_dc_usage +#endif }; /* Number of standard extensions */ diff --git a/crypto/x509v3/v3_bitst.c b/crypto/x509v3/v3_bitst.c index 4802116ba..dda0c55b3 100644 --- a/crypto/x509v3/v3_bitst.c +++ b/crypto/x509v3/v3_bitst.c @@ -38,10 +38,22 @@ static BIT_STRING_BITNAME key_usage_type_table[] = { {-1, NULL, NULL} }; +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +static BIT_STRING_BITNAME dc_usage_type_table[] = { + {0, "Server Delegation", "serverDelegation"}, + {1, "Client Delegation", "clientDelegation"}, + {-1, NULL, NULL} +}; +#endif + const X509V3_EXT_METHOD v3_nscert = EXT_BITSTRING(NID_netscape_cert_type, ns_cert_type_table); const X509V3_EXT_METHOD v3_key_usage = EXT_BITSTRING(NID_key_usage, key_usage_type_table); +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +const X509V3_EXT_METHOD v3_dc_usage = +EXT_BITSTRING(NID_delegation_usage, dc_usage_type_table); +#endif STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, ASN1_BIT_STRING *bits, diff --git a/crypto/x509v3/v3err.c b/crypto/x509v3/v3err.c index 4f2ea52a4..64b816658 100644 --- a/crypto/x509v3/v3err.c +++ b/crypto/x509v3/v3err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_CTX_set_quic_method.pod b/doc/man3/SSL_CTX_set_quic_method.pod index 60bf70494..546830005 100644 --- a/doc/man3/SSL_CTX_set_quic_method.pod +++ b/doc/man3/SSL_CTX_set_quic_method.pod @@ -13,7 +13,13 @@ SSL_quic_read_level, SSL_quic_write_level, SSL_provide_quic_data, SSL_process_quic_post_handshake, -SSL_is_quic +SSL_is_quic, +SSL_get_peer_quic_transport_version, +SSL_get_quic_transport_version, +SSL_set_quic_transport_version, +SSL_set_quic_use_legacy_codepoint, +SSL_set_quic_early_data_enabled, +SSL_set_quic_early_data_context - QUIC support =head1 SYNOPSIS @@ -39,6 +45,15 @@ SSL_is_quic int SSL_process_quic_post_handshake(SSL *ssl); int SSL_is_quic(SSL *ssl); + void SSL_set_quic_use_legacy_codepoint(SSL *ssl, int use_legacy); + void SSL_set_quic_transport_version(SSL *ssl, int version); + int SSL_get_quic_transport_version(const SSL *ssl); + int SSL_get_peer_quic_transport_version(const SSL *ssl); + void SSL_set_quic_early_data_enabled(SSL *ssl, int enabled); + int SSL_set_quic_early_data_context(SSL *ssl, + const uint8_t *context, + size_t context_len); + =head1 DESCRIPTION SSL_CTX_set_quic_method() and SSL_set_quic_method() configures the QUIC methods. @@ -63,23 +78,56 @@ SSL_quic_max_handshake_flight_len() returns the maximum number of bytes that may be received at the given encryption level. This function should be used to limit buffering in the QUIC implementation. -See https://tools.ietf.org/html/draft-ietf-quic-transport-16#section-4.4. +See https://tools.ietf.org/html/draft-ietf-quic-transport-27#section-4. SSL_quic_read_level() returns the current read encryption level. SSL_quic_write_level() returns the current write encryption level. -SSL_provide_quic_data() provides data from QUIC at a particular encryption -level B. It is an error to call this function outside of the handshake -or with an encryption level other than the current read level. It returns one -on success and zero on error. +SSL_provide_quic_data() is used to provide data from QUIC CRYPTO frames to the +state machine, at a particular encryption level B. It is an error to +call this function outside of the handshake or with an encryption level other +than the current read level. The application must buffer and consolidate any +frames with less than four bytes of content. It returns one on success and +zero on error. SSL_process_quic_post_handshake() processes any data that QUIC has provided after the handshake has completed. This includes NewSessionTicket messages sent by the server. -SSL_is_quic() indicates whether a connection uses QUIC. - +SSL_is_quic() indicates whether a connection uses QUIC. A given B +or B can only be used with QUIC or TLS, but not both. + +SSL_set_quic_use_legacy_codepoint() specifies the legacy extension codepoint +in manner compatible with some versions of BoringSSL. + +SSL_set_quic_transport_version() specifies the quic transport version that +allows for backwards and forwards compatibility. If set to 0 (default) the +server will use the highest version the client sent. If set to 0 (default) +the client will send both extensions. + +SSL_get_quic_transport_version() returns the value set by +SSL_set_quic_transport_version(). + +SSL_get_peer_quic_transport_version() returns the version the that was +negotiated. + +SSL_set_quic_early_data_enabled() enables QUIC early data if a nonzero +value is passed. Clients must set a resumed session before calling this +function. Servers must additionally call SSL_CTX_set_max_early_data() or +SSL_set_max_early_data() with 0xffffffffu as the argument, so that any +issued session tickets indicate that server is able to accept early data. + +SSL_set_quic_early_data_context configures a context string in QUIC servers +for accepting early data. If a resumption connection offers early data, the +server will check if the value matches that of the connection which minted +the ticket. If not, resumption still succeeds but early data is rejected. +This should include all QUIC Transport Parameters except ones specified that +the client MUST NOT remember. This should also include any application +protocol-specific state. For HTTP/3, this should be the serialized server +SETTINGS frame and the QUIC Transport Parameters (except the stateless reset +token). This function may be called before SSL_do_handshake or during server +certificate selection. =head1 NOTES These APIs are implementations of BoringSSL's QUIC APIs. @@ -89,11 +137,11 @@ functions allow a QUIC implementation to serve as the underlying transport as described in draft-ietf-quic-tls. When configured for QUIC, SSL_do_handshake() will drive the handshake as -before, but it will not use the configured B. It will call functions on -B to configure secrets and send data. If data is needed from -the peer, it will return B. When received, the caller -should call SSL_provide_quic_data() and then SSL_do_handshake() to continue -the handshake. After the handshake is complete, the caller should call +before, but it will not use the configured B. It will call functions from +the configured B to configure secrets and send data. If data +is needed from the peer, it will return B. When received, +the caller should call SSL_provide_quic_data() and then SSL_do_handshake() to +continue the handshake. After the handshake is complete, the caller should call SSL_provide_quic_data() for any post-handshake data, followed by SSL_process_quic_post_handshake() to process it. It is an error to call SSL_read()/SSL_read_ex() and SSL_write()/SSL_write_ex() in QUIC. @@ -105,7 +153,7 @@ pass the active write level to add_handshake_data() when writing data. Callers can use SSL_quic_write_level() to query the active write level when generating their own errors. -See https://tools.ietf.org/html/draft-ietf-quic-tls-15#section-4.1 for more +See https://tools.ietf.org/html/draft-ietf-quic-tls-27#section-4.1 for more details. To avoid DoS attacks, the QUIC implementation must limit the amount of data @@ -113,11 +161,12 @@ being queued up. The implementation can call SSL_quic_max_handshake_flight_len() to get the maximum buffer length at each encryption level. -draft-ietf-quic-tls defines a new TLS extension quic_transport_parameters +draft-ietf-quic-tls defines a new TLS extension "quic_transport_parameters" used by QUIC for each endpoint to unilaterally declare its supported -transport parameters. draft-ietf-quic-transport (section 7.4) defines the -contents of that extension (a TransportParameters struct) and describes how -to handle it and its semantic meaning. +transport parameters. The contents of the extension are specified in +https://tools.ietf.org/html/draft-ietf-quic-transport-27#section-18 (as +a sequence of tag/length/value parameters) along with the interpretation of the +various parameters and the rules for their processing. OpenSSL handles this extension as an opaque byte string. The caller is responsible for serializing and parsing it. @@ -154,31 +203,59 @@ The B (B) describes the QUIC methods. struct ssl_quic_method_st { - int (*set_encryption_secrets)(SSL *ssl, OSSL_ENCRYPTION_LEVEL level, - const uint8_t *read_secret, - const uint8_t *write_secret, size_t secret_len); - int (*add_handshake_data)(SSL *ssl, OSSL_ENCRYPTION_LEVEL level, + int (*set_read_secret)(SSL *ssl, enum ssl_encryption_level_t level, + const SSL_CIPHER *cipher, const uint8_t *secret, + size_t secret_len); + int (*set_write_secret)(SSL *ssl, enum ssl_encryption_level_t level, + const SSL_CIPHER *cipher, const uint8_t *secret, + size_t secret_len); + int (*add_handshake_data)(SSL *ssl, enum ssl_encryption_level_t level, const uint8_t *data, size_t len); int (*flush_flight)(SSL *ssl); int (*send_alert)(SSL *ssl, enum ssl_encryption_level_t level, uint8_t alert); }; typedef struct ssl_quic_method_st SSL_QUIC_METHOD; -set_encryption_secrets() configures the read and write secrets for the given -encryption level. This function will always be called before an encryption -level other than B is used. Note, however, that -secrets for a level may be configured before TLS is ready to send or accept -data at that level. - -When reading packets at a given level, the QUIC implementation must send -ACKs at the same level, so this function provides read and write secrets -together. The exception is B, where secrets are -only available in the client to server direction. The other secret will be -NULL. The server acknowledges such data at B, -which will be configured in the same SSL_do_handshake() call. - -This function should use SSL_get_current_cipher() to determine the TLS -cipher suite. +set_read_secret() configures the read secret and cipher suite for the given +encryption level. It returns one on success and zero to terminate the +handshake with an error. It will be called at most once per encryption +level. + +BoringSSL will not release read keys before QUIC may use them. Once a level +has been initialized, QUIC may begin processing data from it. Handshake +data should be passed to B and application data (if +B is B or B) may +be processed according to the rules of the QUIC protocol. + +QUIC ACKs packets at the same encryption level they were received at, +except that client B (0-RTT) packets trigger +server B (1-RTT) ACKs. BoringSSL will always +install ACK-writing keys with B before the packet-reading +keys with B. This ensures the caller can always ACK any +packet it decrypts. Note this means the server installs 1-RTT write keys +before 0-RTT read keys. + +The converse is not true. An encryption level may be configured with write +secrets a roundtrip before the corresponding secrets for reading ACKs is +available. + +set_write_secret behaves like B but configures the write +secret and cipher suite for the given encryption level. It will be called +at most once per encryption level. + +BoringSSL will not release write keys before QUIC may use them. If B +is B or B, QUIC may +begin sending application data at B. However, note that BoringSSL +configures server B write keys before the client +Finished. This allows QUIC to send half-RTT data, but the handshake is not +confirmed at this point and, if requesting client certificates, the client +is not yet authenticated. + +See B for additional invariants between packets and their +ACKs. + +Note that, on 0-RTT reject, the B write secret +may use a different cipher suite from the other keys. add_handshake_data() adds handshake data to the current flight at the given encryption level. It returns one on success and zero on error. @@ -200,15 +277,17 @@ All QUIC methods return 1 on success and 0 on error. SSL_CTX_set_quic_method(), SSL_set_quic_method(), -SSL_set_quic_transport_params(), and -SSL_process_quic_post_handshake() +SSL_set_quic_transport_params(), +SSL_process_quic_post_handshake(), and +SSL_set_quic_early_data_context() return 1 on success, and 0 on error. SSL_quic_read_level() and SSL_quic_write_level() return the current -encryption level as B (B). +encryption level as an B +(B). -SSL_quic_max_handshake_flight_len() returns the maximum length of a flight -for a given encryption level. +SSL_quic_max_handshake_flight_len() returns the maximum length in bytes of a +flight for a given encryption level. SSL_is_quic() returns 1 if QUIC is being used, 0 if not. diff --git a/engines/e_afalg.txt b/engines/e_afalg.txt index 3b79305ac..e08b34f5f 100644 --- a/engines/e_afalg.txt +++ b/engines/e_afalg.txt @@ -1,4 +1,4 @@ -# Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the OpenSSL license (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy diff --git a/engines/e_afalg_err.c b/engines/e_afalg_err.c index 18fe9c34e..73c27b3a9 100644 --- a/engines/e_afalg_err.c +++ b/engines/e_afalg_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/engines/e_afalg_err.h b/engines/e_afalg_err.h index 3036443f4..9709fc9f4 100644 --- a/engines/e_afalg_err.h +++ b/engines/e_afalg_err.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -8,8 +8,10 @@ * https://www.openssl.org/source/license.html */ -#ifndef OSSL_ENGINES_E_AFALG_ERR_H -# define OSSL_ENGINES_E_AFALG_ERR_H +#ifndef HEADER_AFALGERR_H +# define HEADER_AFALGERR_H + +# include # define AFALGerr(f, r) ERR_AFALG_error((f), (r), OPENSSL_FILE, OPENSSL_LINE) diff --git a/engines/e_capi.txt b/engines/e_capi.txt index 3f34cdf6b..955dd3d43 100644 --- a/engines/e_capi.txt +++ b/engines/e_capi.txt @@ -1,4 +1,4 @@ -# Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the OpenSSL license (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy diff --git a/engines/e_capi_err.c b/engines/e_capi_err.c index b72bc51a8..5f79cd902 100644 --- a/engines/e_capi_err.c +++ b/engines/e_capi_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/engines/e_capi_err.h b/engines/e_capi_err.h index e3a927aa7..faf00b974 100644 --- a/engines/e_capi_err.h +++ b/engines/e_capi_err.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -8,8 +8,10 @@ * https://www.openssl.org/source/license.html */ -#ifndef OSSL_ENGINES_E_CAPI_ERR_H -# define OSSL_ENGINES_E_CAPI_ERR_H +#ifndef HEADER_CAPIERR_H +# define HEADER_CAPIERR_H + +# include # define CAPIerr(f, r) ERR_CAPI_error((f), (r), OPENSSL_FILE, OPENSSL_LINE) diff --git a/engines/e_dasync.txt b/engines/e_dasync.txt index bff64bcf2..17b0a3eb7 100644 --- a/engines/e_dasync.txt +++ b/engines/e_dasync.txt @@ -1,4 +1,4 @@ -# Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the OpenSSL license (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy diff --git a/engines/e_dasync_err.c b/engines/e_dasync_err.c index 794fb710c..062640500 100644 --- a/engines/e_dasync_err.c +++ b/engines/e_dasync_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/engines/e_dasync_err.h b/engines/e_dasync_err.h index 5b74d8be2..c57bbc547 100644 --- a/engines/e_dasync_err.h +++ b/engines/e_dasync_err.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -8,8 +8,10 @@ * https://www.openssl.org/source/license.html */ -#ifndef OSSL_ENGINES_E_DASYNC_ERR_H -# define OSSL_ENGINES_E_DASYNC_ERR_H +#ifndef HEADER_DASYNCERR_H +# define HEADER_DASYNCERR_H + +# include # define DASYNCerr(f, r) ERR_DASYNC_error((f), (r), OPENSSL_FILE, OPENSSL_LINE) diff --git a/engines/e_ossltest.txt b/engines/e_ossltest.txt index 2b2e31a07..d78c9b85e 100644 --- a/engines/e_ossltest.txt +++ b/engines/e_ossltest.txt @@ -1,4 +1,4 @@ -# Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the OpenSSL license (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy diff --git a/engines/e_ossltest_err.c b/engines/e_ossltest_err.c index 920a13a69..56f733397 100644 --- a/engines/e_ossltest_err.c +++ b/engines/e_ossltest_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/engines/e_ossltest_err.h b/engines/e_ossltest_err.h index 8e6535b76..9cfee6876 100644 --- a/engines/e_ossltest_err.h +++ b/engines/e_ossltest_err.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -8,8 +8,10 @@ * https://www.openssl.org/source/license.html */ -#ifndef OSSL_ENGINES_E_OSSLTEST_ERR_H -# define OSSL_ENGINES_E_OSSLTEST_ERR_H +#ifndef HEADER_OSSLTESTERR_H +# define HEADER_OSSLTESTERR_H + +# include # define OSSLTESTerr(f, r) ERR_OSSLTEST_error((f), (r), OPENSSL_FILE, OPENSSL_LINE) diff --git a/fuzz/oids.txt b/fuzz/oids.txt index 6111b20f4..23efe11ea 100644 --- a/fuzz/oids.txt +++ b/fuzz/oids.txt @@ -1066,3 +1066,4 @@ OBJ_hmacWithSHA512_256="\x2A\x86\x48\x86\xF7\x0D\x02\x0D" OBJ_sm4_gcm="\x2A\x81\x1C\xCF\x55\x01\x68\x08" OBJ_sm4_ccm="\x2A\x81\x1C\xCF\x55\x01\x68\x09" OBJ_SM2_with_SM3="\x2A\x81\x1C\xCF\x55\x01\x83\x75" +OBJ_delegation_usage="\x2B\x06\x01\x04\x01\x82\xDA\x4B\x2C" diff --git a/include/crypto/sm2err.h b/include/crypto/sm2err.h index a91338a95..acef9eef8 100644 --- a/include/crypto/sm2err.h +++ b/include/crypto/sm2err.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -8,8 +8,8 @@ * https://www.openssl.org/source/license.html */ -#ifndef OPENSSL_SM2ERR_H -# define OPENSSL_SM2ERR_H +#ifndef HEADER_SM2ERR_H +# define HEADER_SM2ERR_H # include diff --git a/include/crypto/x509.h b/include/crypto/x509.h index 139ba4a70..87f882e79 100644 --- a/include/crypto/x509.h +++ b/include/crypto/x509.h @@ -191,6 +191,23 @@ struct x509_st { # endif } /* X509 */ ; +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +struct delegated_credential_st{ + unsigned long valid_time; + unsigned int expected_cert_verify_algorithm; + unsigned long dc_publickey_raw_len; + unsigned char *dc_publickey_raw; + unsigned int signature_sign_algorithm; + unsigned int dc_signature_len; + unsigned char *dc_signature; + EVP_PKEY *pkey; + unsigned char *raw_byte; + unsigned long raw_byte_len; + CRYPTO_REF_COUNT references; + CRYPTO_RWLOCK *lock; +} /* DC */; +#endif + /* * This is a used when verifying cert chains. Since the gathering of the * cert chain can take some time (and have to be 'retried', this needs to be diff --git a/include/internal/dsoerr.h b/include/internal/dsoerr.h index 94d642a22..859f92ff5 100644 --- a/include/internal/dsoerr.h +++ b/include/internal/dsoerr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -8,16 +8,18 @@ * https://www.openssl.org/source/license.html */ -#ifndef OSSL_INTERNAL_DSOERR_H -# define OSSL_INTERNAL_DSOERR_H +#ifndef HEADER_DSOERR_H +# define HEADER_DSOERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include + +# include + +# ifndef OPENSSL_NO_DSO -# ifdef __cplusplus +# ifdef __cplusplus extern "C" -# endif +# endif int ERR_load_DSO_strings(void); /* @@ -79,4 +81,5 @@ int ERR_load_DSO_strings(void); # define DSO_R_UNLOAD_FAILED 107 # define DSO_R_UNSUPPORTED 108 +# endif #endif diff --git a/include/openssl/asn1err.h b/include/openssl/asn1err.h index faed5a551..dad3b8343 100644 --- a/include/openssl/asn1err.h +++ b/include/openssl/asn1err.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_ASN1ERR_H # define HEADER_ASN1ERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # ifdef __cplusplus extern "C" @@ -99,6 +97,8 @@ int ERR_load_ASN1_strings(void); # define ASN1_F_D2I_AUTOPRIVATEKEY 207 # define ASN1_F_D2I_PRIVATEKEY 154 # define ASN1_F_D2I_PUBLICKEY 155 +# define ASN1_F_DC_NEW 144 +# define ASN1_F_DC_NEW_FROM_RAW_BYTE 145 # define ASN1_F_DO_BUF 142 # define ASN1_F_DO_CREATE 124 # define ASN1_F_DO_DUMP 125 diff --git a/include/openssl/asyncerr.h b/include/openssl/asyncerr.h index 91afbbb2f..1ecb078f3 100644 --- a/include/openssl/asyncerr.h +++ b/include/openssl/asyncerr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_ASYNCERR_H # define HEADER_ASYNCERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # ifdef __cplusplus extern "C" diff --git a/include/openssl/bioerr.h b/include/openssl/bioerr.h index 46e2c96ee..0b410c6d5 100644 --- a/include/openssl/bioerr.h +++ b/include/openssl/bioerr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_BIOERR_H # define HEADER_BIOERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # ifdef __cplusplus extern "C" diff --git a/include/openssl/bnerr.h b/include/openssl/bnerr.h index 9f3c7cfaa..92e5296b2 100644 --- a/include/openssl/bnerr.h +++ b/include/openssl/bnerr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_BNERR_H # define HEADER_BNERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # ifdef __cplusplus extern "C" diff --git a/include/openssl/buffererr.h b/include/openssl/buffererr.h index 04f6ff7a8..29f9ac1ae 100644 --- a/include/openssl/buffererr.h +++ b/include/openssl/buffererr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_BUFERR_H # define HEADER_BUFERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # ifdef __cplusplus extern "C" diff --git a/include/openssl/cmserr.h b/include/openssl/cmserr.h index 7dbc13dc9..3273e165d 100644 --- a/include/openssl/cmserr.h +++ b/include/openssl/cmserr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_CMSERR_H # define HEADER_CMSERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # include diff --git a/include/openssl/comperr.h b/include/openssl/comperr.h index 90231e9aa..442a3d3eb 100644 --- a/include/openssl/comperr.h +++ b/include/openssl/comperr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_COMPERR_H # define HEADER_COMPERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # include diff --git a/include/openssl/conferr.h b/include/openssl/conferr.h index 32b922918..f2aa77973 100644 --- a/include/openssl/conferr.h +++ b/include/openssl/conferr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_CONFERR_H # define HEADER_CONFERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # ifdef __cplusplus extern "C" diff --git a/include/openssl/crypto.h b/include/openssl/crypto.h index 747a117d9..b661817bf 100644 --- a/include/openssl/crypto.h +++ b/include/openssl/crypto.h @@ -162,6 +162,9 @@ unsigned long BabaSSL_version_num(void); # define OPENSSL_DIR 4 # define OPENSSL_ENGINES_DIR 5 # define BABASSL_VERSION 6 +# ifndef OPENSSL_NO_QUIC +# define OPENSSL_INFO_QUIC 2000 +# endif int OPENSSL_issetugid(void); diff --git a/include/openssl/cryptoerr.h b/include/openssl/cryptoerr.h index 3db5a4ee9..9ca2365bd 100644 --- a/include/openssl/cryptoerr.h +++ b/include/openssl/cryptoerr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_CRYPTOERR_H # define HEADER_CRYPTOERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # ifdef __cplusplus extern "C" diff --git a/include/openssl/cterr.h b/include/openssl/cterr.h index feb7bc566..ea4fb1119 100644 --- a/include/openssl/cterr.h +++ b/include/openssl/cterr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_CTERR_H # define HEADER_CTERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # include diff --git a/include/openssl/dherr.h b/include/openssl/dherr.h index 916b3bed0..3e8f3b40c 100644 --- a/include/openssl/dherr.h +++ b/include/openssl/dherr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_DHERR_H # define HEADER_DHERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # include diff --git a/include/openssl/dsaerr.h b/include/openssl/dsaerr.h index 495a1ac89..552f81b6b 100644 --- a/include/openssl/dsaerr.h +++ b/include/openssl/dsaerr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_DSAERR_H # define HEADER_DSAERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # include diff --git a/include/openssl/ecerr.h b/include/openssl/ecerr.h index f7b918345..1cf9053cc 100644 --- a/include/openssl/ecerr.h +++ b/include/openssl/ecerr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_ECERR_H # define HEADER_ECERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # include diff --git a/include/openssl/engineerr.h b/include/openssl/engineerr.h index 05e84bd2a..edc20f2e0 100644 --- a/include/openssl/engineerr.h +++ b/include/openssl/engineerr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_ENGINEERR_H # define HEADER_ENGINEERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # include diff --git a/include/openssl/evperr.h b/include/openssl/evperr.h index eb8e0f6c5..b4ea90ae9 100644 --- a/include/openssl/evperr.h +++ b/include/openssl/evperr.h @@ -123,6 +123,7 @@ int ERR_load_EVP_strings(void); # define EVP_F_R_32_12_16_INIT_KEY 242 # define EVP_F_S390X_AES_GCM_CTRL 201 # define EVP_F_UPDATE 173 + /* * EVP reason codes. */ diff --git a/include/openssl/kdferr.h b/include/openssl/kdferr.h index 3f51bd022..3fff39178 100644 --- a/include/openssl/kdferr.h +++ b/include/openssl/kdferr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_KDFERR_H # define HEADER_KDFERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # ifdef __cplusplus extern "C" diff --git a/include/openssl/ntls.h b/include/openssl/ntls.h index f7d1ec128..d9f387c54 100644 --- a/include/openssl/ntls.h +++ b/include/openssl/ntls.h @@ -20,50 +20,38 @@ */ # define MIN_VERSION_WITH_NTLS 0x0100 -/* GM/T 0024-2014 cipher suites */ -/* - * XXX: - * - * We currently ignore all SM1 and SM9 related ciphers, the reasons are: - * - * 1. SM1 is not public usable, the specification is credential; - * 2. OpenSSL currently doesn't support SM9 yet. - * - * Fortunately, major NTLS implementations mostly support 0xe011 and 0xe013 - * only. - */ -/* -# define NTLS_CK_SM2DHE_WITH_SM1_SM3 0x0300E001 -# define NTLS_CK_SM2_WITH_SM1_SM3 0x0300E003 -# define NTLS_CK_SM9DHE_WITH_SM1_SM3 0x0300E005 -# define NTLS_CK_SM9_WITH_SM1_SM3 0x0300E007 -# define NTLS_CK_RSA_WITH_SM1_SM3 0x0300E009 -# define NTLS_CK_RSA_WITH_SM1_SHA1 0x0300E00A -# define NTLS_CK_SM9DHE_WITH_SM4_SM3 0x0300E015 -# define NTLS_CK_SM9_WITH_SM4_SM3 0x0300E017 -*/ -# define NTLS_CK_SM2DHE_WITH_SM4_SM3 0x0300E011 -# define NTLS_CK_SM2_WITH_SM4_SM3 0x0300E013 -# define NTLS_CK_RSA_WITH_SM4_SM3 0x0300E019 -# define NTLS_CK_RSA_WITH_SM4_SHA1 0x0300E01A - -/* GM/T 0024-2014 Cipher Suites Text */ -/* -# define NTLS_TXT_SM2DHE_WITH_SM1_SM3 "SM2DHE-WITH-SM1-SM3" -# define NTLS_TXT_SM2_WITH_SM1_SM3 "SM2-WITH-SM1-SM3" -# define NTLS_TXT_SM9DHE_WITH_SM1_SM3 "SM9DHE-WITH-SM1-SM3" -# define NTLS_TXT_SM9_WITH_SM1_SM3 "SM9-WITH-SM1-SM3" -# define NTLS_TXT_RSA_WITH_SM1_SM3 "RSA-WITH-SM1-SM3" -# define NTLS_TXT_RSA_WITH_SM1_SHA1 "RSA-WITH-SM1-SHA1" -# define NTLS_TXT_SM9DHE_WITH_SMS4_SM3 "SM9DHE-WITH-SMS4-SM3" -# define NTLS_TXT_SM9_WITH_SMS4_SM3 "SM9-WITH-SMS4-SM3" -*/ +/* Compatible with GM/T 0024-2014 cipher suites name */ # define NTLS_TXT_SM2DHE_WITH_SM4_SM3 "ECDHE-SM2-WITH-SM4-SM3" # define NTLS_TXT_SM2_WITH_SM4_SM3 "ECC-SM2-WITH-SM4-SM3" -# define NTLS_TXT_RSA_WITH_SM4_SM3 "RSA-WITH-SM4-SM3" -# define NTLS_TXT_RSA_WITH_SM4_SHA1 "RSA-WITH-SM4-SHA1" -/* GM/T 0024-2014 */ +/* GB/T 38636-2020 TLCP, cipher suites */ +# define NTLS_TXT_ECDHE_SM2_SM4_CBC_SM3 "ECDHE-SM2-SM4-CBC-SM3" +# define NTLS_TXT_ECDHE_SM2_SM4_GCM_SM3 "ECDHE-SM2-SM4-GCM-SM3" +# define NTLS_TXT_ECC_SM2_SM4_CBC_SM3 "ECC-SM2-SM4-CBC-SM3" +# define NTLS_TXT_ECC_SM2_SM4_GCM_SM3 "ECC-SM2-SM4-GCM-SM3" +# define NTLS_TXT_IBSDH_SM9_SM4_CBC_SM3 "IBSDH-SM9-SM4-CBC-SM3" +# define NTLS_TXT_IBSDH_SM9_SM4_GCM_SM3 "IBSDH-SM9-SM4-GCM-SM3" +# define NTLS_TXT_IBC_SM9_SM4_CBC_SM3 "IBC-SM9-SM4-CBC-SM3" +# define NTLS_TXT_IBC_SM9_SM4_GCM_SM3 "IBC-SM9-SM4-GCM-SM3" +# define NTLS_TXT_RSA_SM4_CBC_SM3 "RSA-SM4-CBC-SM3" +# define NTLS_TXT_RSA_SM4_GCM_SM3 "RSA-SM4-GCM-SM3" +# define NTLS_TXT_RSA_SM4_CBC_SHA256 "RSA-SM4-CBC-SHA256" +# define NTLS_TXT_RSA_SM4_GCM_SHA256 "RSA-SM4-GCM-SHA256" + +# define NTLS_CK_ECDHE_SM2_SM4_CBC_SM3 0x0300E011 +# define NTLS_CK_ECDHE_SM2_SM4_GCM_SM3 0x0300E051 +# define NTLS_CK_ECC_SM2_SM4_CBC_SM3 0x0300E013 +# define NTLS_CK_ECC_SM2_SM4_GCM_SM3 0x0300E053 +# define NTLS_CK_IBSDH_SM9_SM4_CBC_SM3 0x0300E015 +# define NTLS_CK_IBSDH_SM9_SM4_GCM_SM3 0x0300E055 +# define NTLS_CK_IBC_SM9_SM4_CBC_SM3 0x0300E017 +# define NTLS_CK_IBC_SM9_SM4_GCM_SM3 0x0300E057 +# define NTLS_CK_RSA_SM4_CBC_SM3 0x0300E019 +# define NTLS_CK_RSA_SM4_GCM_SM3 0x0300E059 +# define NTLS_CK_RSA_SM4_CBC_SHA256 0x0300E01C +# define NTLS_CK_RSA_SM4_GCM_SHA256 0x0300E05a + + #define NTLS_AD_UNSUPPORTED_SITE2SITE 200 #define NTLS_AD_NO_AREA 201 #define NTLS_AD_UNSUPPORTED_AREATYPE 202 diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h index 9e2c93a24..7bdd0bb5b 100644 --- a/include/openssl/obj_mac.h +++ b/include/openssl/obj_mac.h @@ -2,7 +2,7 @@ * WARNING: do not edit! * Generated by crypto/objects/objects.pl * - * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at @@ -2519,6 +2519,11 @@ #define NID_ext_key_usage 126 #define OBJ_ext_key_usage OBJ_id_ce,37L +#define SN_delegation_usage "delegationUsage" +#define LN_delegation_usage "X509v3 Delegation Usage" +#define NID_delegation_usage 1201 +#define OBJ_delegation_usage 1L,3L,6L,1L,4L,1L,44363L,44L + #define SN_freshest_crl "freshestCRL" #define LN_freshest_crl "X509v3 Freshest CRL" #define NID_freshest_crl 857 diff --git a/include/openssl/objectserr.h b/include/openssl/objectserr.h index 02e166f1a..9840ae155 100644 --- a/include/openssl/objectserr.h +++ b/include/openssl/objectserr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_OBJERR_H # define HEADER_OBJERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # ifdef __cplusplus extern "C" diff --git a/include/openssl/ocsperr.h b/include/openssl/ocsperr.h index 8dd9e01a1..f48879685 100644 --- a/include/openssl/ocsperr.h +++ b/include/openssl/ocsperr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_OCSPERR_H # define HEADER_OCSPERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # include diff --git a/include/openssl/opensslv.h b/include/openssl/opensslv.h index c779ed0e4..0571293f9 100644 --- a/include/openssl/opensslv.h +++ b/include/openssl/opensslv.h @@ -108,8 +108,8 @@ extern "C" { * 1.9.5 0x1090500f */ -# define BABASSL_VERSION_NUMBER 0x8010300fL -# define BABASSL_VERSION_TEXT "BabaSSL 8.1.3" +# define BABASSL_VERSION_NUMBER 0x80200000L +# define BABASSL_VERSION_TEXT "BabaSSL 8.2.0-dev" #ifdef __cplusplus } diff --git a/include/openssl/ossl_typ.h b/include/openssl/ossl_typ.h index 0370f5f89..038aaefc5 100644 --- a/include/openssl/ossl_typ.h +++ b/include/openssl/ossl_typ.h @@ -126,6 +126,9 @@ typedef struct x509_revoked_st X509_REVOKED; typedef struct X509_name_st X509_NAME; typedef struct X509_pubkey_st X509_PUBKEY; typedef struct x509_store_st X509_STORE; +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +typedef struct delegated_credential_st DELEGATED_CREDENTIAL; +#endif typedef struct x509_store_ctx_st X509_STORE_CTX; typedef struct x509_object_st X509_OBJECT; diff --git a/include/openssl/pemerr.h b/include/openssl/pemerr.h index 0c45918f3..c6148d3c1 100644 --- a/include/openssl/pemerr.h +++ b/include/openssl/pemerr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_PEMERR_H # define HEADER_PEMERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # ifdef __cplusplus extern "C" diff --git a/include/openssl/pkcs12err.h b/include/openssl/pkcs12err.h index eff5eb260..796c0ab03 100644 --- a/include/openssl/pkcs12err.h +++ b/include/openssl/pkcs12err.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_PKCS12ERR_H # define HEADER_PKCS12ERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # ifdef __cplusplus extern "C" diff --git a/include/openssl/pkcs7err.h b/include/openssl/pkcs7err.h index 02e0299a3..55b8f0902 100644 --- a/include/openssl/pkcs7err.h +++ b/include/openssl/pkcs7err.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_PKCS7ERR_H # define HEADER_PKCS7ERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # ifdef __cplusplus extern "C" diff --git a/include/openssl/randerr.h b/include/openssl/randerr.h index 79d57905e..24a90a601 100644 --- a/include/openssl/randerr.h +++ b/include/openssl/randerr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/include/openssl/rsaerr.h b/include/openssl/rsaerr.h index 59b15e13e..915c40408 100644 --- a/include/openssl/rsaerr.h +++ b/include/openssl/rsaerr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_RSAERR_H # define HEADER_RSAERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # ifdef __cplusplus extern "C" @@ -130,8 +128,8 @@ int ERR_load_RSA_strings(void); # define RSA_R_KEY_PRIME_NUM_INVALID 165 # define RSA_R_KEY_SIZE_TOO_SMALL 120 # define RSA_R_LAST_OCTET_INVALID 134 -# define RSA_R_MISSING_PRIVATE_KEY 179 # define RSA_R_MGF1_DIGEST_NOT_ALLOWED 152 +# define RSA_R_MISSING_PRIVATE_KEY 179 # define RSA_R_MODULUS_TOO_LARGE 105 # define RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R 168 # define RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D 169 diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index fe3665d55..da655b0c7 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -306,10 +306,6 @@ typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, #define SSL_EXT_TLS1_3_NEW_SESSION_TICKET 0x2000 #define SSL_EXT_TLS1_3_CERTIFICATE_REQUEST 0x4000 -#ifndef OPENSSL_NO_NTLS -#define SSL_EXT_NTLS_IMCOMPATIBLE 0x8000 -#endif - /* Typedefs for handling custom extensions */ typedef int (*custom_ext_add_cb)(SSL *s, unsigned int ext_type, @@ -438,7 +434,8 @@ typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx); # if (!defined OPENSSL_NO_NTLS) && (!defined OPENSSL_NO_SM2) \ && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) -# define SSL_OP_NO_NTLS 0x10000000U +/* Just use a reserved value, don't conflict with OP TLS */ +# define SSL_OP_NO_NTLS 0x00000080U # endif # define SSL_OP_NO_SSL_MASK (SSL_OP_NO_SSLv3|\ @@ -1260,7 +1257,6 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) # define SSL_AD_NO_APPLICATION_PROTOCOL TLS1_AD_NO_APPLICATION_PROTOCOL # if (!defined OPENSSL_NO_NTLS) && (!defined OPENSSL_NO_SM2) \ && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) -/* NTLS GM/T 0024-2014 alert codes */ # define SSL_AD_UNSUPPORTED_SITE2SITE NTLS_AD_UNSUPPORTED_SITE2SITE # define SSL_AD_NO_AREA NTLS_AD_NO_AREA # define SSL_AD_UNSUPPORTED_AREATYPE NTLS_AD_UNSUPPORTED_AREATYPE @@ -1853,6 +1849,37 @@ void SSL_enable_sm_tls13_strict(SSL *s); void SSL_disable_sm_tls13_strict(SSL *s); # endif +# ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + +# define DC_REQ_HAS_BEEN_SEND_TO_PEER 0x01 +# define DC_HAS_BEEN_USED_FOR_VERIFY_PEER 0x02 +# define DC_HAS_BEEN_USED_FOR_SIGN 0x04 + +void SSL_CTX_enable_verify_peer_by_dc(SSL_CTX *ctx); +void SSL_CTX_disable_verify_peer_by_dc(SSL_CTX *ctx); +void SSL_enable_verify_peer_by_dc(SSL *s); +void SSL_disable_verify_peer_by_dc(SSL *s); +void SSL_CTX_enable_sign_by_dc(SSL_CTX *ctx); +void SSL_CTX_disable_sign_by_dc(SSL_CTX *ctx); +void SSL_enable_sign_by_dc(SSL *s); +void SSL_disable_sign_by_dc(SSL *s); +int SSL_get_delegated_credential_tag(SSL *s); +int SSL_verify_delegated_credential_signature(X509 *parent_cert, DELEGATED_CREDENTIAL *dc, + int is_server); +int DC_print(BIO *bp, DELEGATED_CREDENTIAL *dc); +int DC_sign(DELEGATED_CREDENTIAL *dc, EVP_PKEY *dc_pkey, + unsigned int valid_time, int expect_verify_hash, + X509 *ee_cert, EVP_PKEY *ee_pkey, const EVP_MD *md, int is_server); +int SSL_use_dc(SSL *ssl, DELEGATED_CREDENTIAL *dc); +int SSL_use_dc_file(SSL *ssl, const char *file, int type); +int SSL_use_dc_PrivateKey(SSL *ssl, EVP_PKEY *pkey); +int SSL_use_dc_PrivateKey_file(SSL *ssl, const char *file, int type); +int SSL_CTX_use_dc(SSL_CTX *ctx, DELEGATED_CREDENTIAL *dc); +int SSL_CTX_use_dc_file(SSL_CTX *ctx, const char *file, int type); +int SSL_CTX_use_dc_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey); +int SSL_CTX_use_dc_PrivateKey_file(SSL_CTX *ctx, const char *file, int type); +# endif + __owur int SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx, const unsigned char *d, long len); __owur int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x); @@ -2750,10 +2777,13 @@ typedef enum ssl_encryption_level_t { } OSSL_ENCRYPTION_LEVEL; struct ssl_quic_method_st { - int (*set_encryption_secrets)(SSL *ssl, OSSL_ENCRYPTION_LEVEL level, - const uint8_t *read_secret, - const uint8_t *write_secret, size_t secret_len); - int (*add_handshake_data)(SSL *ssl, OSSL_ENCRYPTION_LEVEL level, + int (*set_read_secret)(SSL *ssl, enum ssl_encryption_level_t level, + const SSL_CIPHER *cipher, const uint8_t *secret, + size_t secret_len); + int (*set_write_secret)(SSL *ssl, enum ssl_encryption_level_t level, + const SSL_CIPHER *cipher, const uint8_t *secret, + size_t secret_len); + int (*add_handshake_data)(SSL *ssl, enum ssl_encryption_level_t level, const uint8_t *data, size_t len); int (*flush_flight)(SSL *ssl); int (*send_alert)(SSL *ssl, enum ssl_encryption_level_t level, uint8_t alert); @@ -2776,7 +2806,25 @@ __owur int SSL_process_quic_post_handshake(SSL *ssl); __owur int SSL_is_quic(SSL *ssl); +/* BoringSSL API */ +void SSL_set_quic_use_legacy_codepoint(SSL *ssl, int use_legacy); + +/* + * Set an explicit value that you want to use + * If 0 (default) the server will use the highest extenstion the client sent + * If 0 (default) the client will send both extensions + */ +void SSL_set_quic_transport_version(SSL *ssl, int version); +__owur int SSL_get_quic_transport_version(const SSL *ssl); +/* Returns the negotiated version, or -1 on error */ +__owur int SSL_get_peer_quic_transport_version(const SSL *ssl); + +int SSL_CIPHER_get_prf_nid(const SSL_CIPHER *c); + void SSL_set_quic_early_data_enabled(SSL *ssl, int enabled); +__owur int SSL_set_quic_early_data_context(SSL *ssl, + const uint8_t *context, + size_t context_len); # endif @@ -2793,8 +2841,6 @@ __owur int SSL_use_sign_PrivateKey_file(SSL *ssl, const char *file, int type); # endif # endif -int SSL_CIPHER_get_prf_nid(const SSL_CIPHER *c); - # ifdef __cplusplus } # endif diff --git a/include/openssl/sslerr.h b/include/openssl/sslerr.h index f65501216..385a02f00 100644 --- a/include/openssl/sslerr.h +++ b/include/openssl/sslerr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -44,6 +44,7 @@ int ERR_load_SSL_strings(void); # define SSL_F_DANE_CTX_ENABLE 347 # define SSL_F_DANE_MTYPE_SET 393 # define SSL_F_DANE_TLSA_ADD 394 +# define SSL_F_DC_SIGN 836 # define SSL_F_DERIVE_SECRET_KEY_AND_IV 514 # define SSL_F_DO_DTLS1_WRITE 245 # define SSL_F_DO_SSL3_WRITE 104 @@ -78,6 +79,7 @@ int ERR_load_SSL_strings(void); # define SSL_F_FINAL_EMS 486 # define SSL_F_FINAL_KEY_SHARE 503 # define SSL_F_FINAL_MAXFRAGMENTLEN 557 +# define SSL_F_FINAL_QUIC_TRANSPORT_PARAMS 3012 # define SSL_F_FINAL_RENEGOTIATE 483 # define SSL_F_FINAL_SERVER_NAME 558 # define SSL_F_FINAL_SIG_ALGS 497 @@ -150,9 +152,9 @@ int ERR_load_SSL_strings(void); # define SSL_F_PITEM_NEW 624 # define SSL_F_PQUEUE_NEW 625 # define SSL_F_PROCESS_KEY_SHARE_EXT 439 -# define SSL_F_QUIC_CHANGE_CIPHER_STATE 836 -# define SSL_F_QUIC_GET_MESSAGE 837 -# define SSL_F_QUIC_SET_ENCRYPTION_SECRETS 838 +# define SSL_F_QUIC_CHANGE_CIPHER_STATE 3000 +# define SSL_F_QUIC_GET_MESSAGE 3001 +# define SSL_F_QUIC_SET_ENCRYPTION_SECRETS 3002 # define SSL_F_READ_STATE_MACHINE 352 # define SSL_F_READ_STATE_MACHINE_NTLS 703 # define SSL_F_SET_CLIENT_CIPHERSUITE 540 @@ -236,6 +238,10 @@ int ERR_load_SSL_strings(void); # define SSL_F_SSL_CTX_USE_CERTIFICATE 171 # define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1 172 # define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE 173 +# define SSL_F_SSL_CTX_USE_DC 880 +# define SSL_F_SSL_CTX_USE_DC_FILE 881 +# define SSL_F_SSL_CTX_USE_DC_PRIVATEKEY 882 +# define SSL_F_SSL_CTX_USE_DC_PRIVATEKEY_FILE 883 # define SSL_F_SSL_CTX_USE_ENC_CERTIFICATE 661 # define SSL_F_SSL_CTX_USE_ENC_CERTIFICATE_FILE 662 # define SSL_F_SSL_CTX_USE_ENC_PRIVATEKEY 663 @@ -256,6 +262,7 @@ int ERR_load_SSL_strings(void); # define SSL_F_SSL_CTX_USE_SIGN_PRIVATEKEY_FILE 668 # define SSL_F_SSL_DANE_DUP 403 # define SSL_F_SSL_DANE_ENABLE 395 +# define SSL_F_SSL_DC_TBS_DATA 855 # define SSL_F_SSL_DERIVE 590 # define SSL_F_SSL_DO_CONFIG 391 # define SSL_F_SSL_DO_HANDSHAKE 180 @@ -285,8 +292,8 @@ int ERR_load_SSL_strings(void); # define SSL_F_SSL_PEEK 270 # define SSL_F_SSL_PEEK_EX 432 # define SSL_F_SSL_PEEK_INTERNAL 522 -# define SSL_F_SSL_PROCESS_QUIC_POST_HANDSHAKE 841 -# define SSL_F_SSL_PROVIDE_QUIC_DATA 842 +# define SSL_F_SSL_PROCESS_QUIC_POST_HANDSHAKE 3005 +# define SSL_F_SSL_PROVIDE_QUIC_DATA 3006 # define SSL_F_SSL_READ 223 # define SSL_F_SSL_READ_EARLY_DATA 529 # define SSL_F_SSL_READ_EX 434 @@ -306,6 +313,8 @@ int ERR_load_SSL_strings(void); # define SSL_F_SSL_SET_CERT_IDX 669 # define SSL_F_SSL_SET_CIPHER_LIST 271 # define SSL_F_SSL_SET_CT_VALIDATION_CALLBACK 399 +# define SSL_F_SSL_SET_DC 884 +# define SSL_F_SSL_SET_DC_PKEY 861 # define SSL_F_SSL_SET_FD 192 # define SSL_F_SSL_SET_PKEY 193 # define SSL_F_SSL_SET_PKEY_IDX 670 @@ -325,6 +334,10 @@ int ERR_load_SSL_strings(void); # define SSL_F_SSL_USE_CERTIFICATE_FILE 200 # define SSL_F_SSL_USE_CERTIFICATE_FILE_IDX 848 # define SSL_F_SSL_USE_CERTIFICATE_IDX 849 +# define SSL_F_SSL_USE_DC 885 +# define SSL_F_SSL_USE_DC_FILE 886 +# define SSL_F_SSL_USE_DC_PRIVATEKEY 869 +# define SSL_F_SSL_USE_DC_PRIVATEKEY_FILE 873 # define SSL_F_SSL_USE_PRIVATEKEY 201 # define SSL_F_SSL_USE_PRIVATEKEY_ASN1 202 # define SSL_F_SSL_USE_PRIVATEKEY_FILE 203 @@ -337,6 +350,7 @@ int ERR_load_SSL_strings(void); # define SSL_F_SSL_VALIDATE_CT 400 # define SSL_F_SSL_VERIFY_CERT_CHAIN 207 # define SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE 616 +# define SSL_F_SSL_VERIFY_DELEGATED_CREDENTIAL_SIGNATURE 856 # define SSL_F_SSL_WRITE 208 # define SSL_F_SSL_WRITE_EARLY_DATA 526 # define SSL_F_SSL_WRITE_EARLY_FINISH 527 @@ -369,6 +383,7 @@ int ERR_load_SSL_strings(void); # define SSL_F_TLS1_SET_GROUPS 629 # define SSL_F_TLS1_SET_RAW_SIGALGS 630 # define SSL_F_TLS1_SET_SERVER_SIGALGS 335 +# define SSL_F_TLS1_SET_SHARED_DC_SIGALGS 858 # define SSL_F_TLS1_SET_SHARED_SIGALGS 631 # define SSL_F_TLS1_SET_SIGALGS 632 # define SSL_F_TLS_CHOOSE_SIGALG 513 @@ -404,6 +419,7 @@ int ERR_load_SSL_strings(void); # define SSL_F_TLS_CONSTRUCT_CTOS_CERTIFICATE 355 # define SSL_F_TLS_CONSTRUCT_CTOS_COOKIE 535 # define SSL_F_TLS_CONSTRUCT_CTOS_COOKIE_NTLS 722 +# define SSL_F_TLS_CONSTRUCT_CTOS_DELEGATED_CREDENTIAL 853 # define SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA 530 # define SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA_NTLS 723 # define SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS 467 @@ -428,7 +444,8 @@ int ERR_load_SSL_strings(void); # define SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES 509 # define SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES_NTLS 733 # define SSL_F_TLS_CONSTRUCT_CTOS_PSK_NTLS 732 -# define SSL_F_TLS_CONSTRUCT_CTOS_QUIC_TRANSPORT_PARAMS 844 +# define SSL_F_TLS_CONSTRUCT_CTOS_QUIC_TRANSPORT_PARAMS 3008 +# define SSL_F_TLS_CONSTRUCT_CTOS_QUIC_TRANSPORT_PARAMS_DRAFT 3013 # define SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE 473 # define SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE_NTLS 734 # define SSL_F_TLS_CONSTRUCT_CTOS_SCT 474 @@ -450,6 +467,8 @@ int ERR_load_SSL_strings(void); # define SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP 482 # define SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP_NTLS 743 # define SSL_F_TLS_CONSTRUCT_CTOS_VERIFY 358 +# define SSL_F_TLS_CONSTRUCT_DELEGATED_CREDENTIAL_RAW 866 +# define SSL_F_TLS_CONSTRUCT_DELEGATED_CREDENTIAL_REQUEST 867 # define SSL_F_TLS_CONSTRUCT_ENCRYPTED_EXTENSIONS 443 # define SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA 536 # define SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA_NTLS 744 @@ -478,6 +497,7 @@ int ERR_load_SSL_strings(void); # define SSL_F_TLS_CONSTRUCT_STOC_COOKIE_NTLS 754 # define SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG 452 # define SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG_NTLS 755 +# define SSL_F_TLS_CONSTRUCT_STOC_DELEGATED_CREDENTIAL 863 # define SSL_F_TLS_CONSTRUCT_STOC_DONE 375 # define SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA 531 # define SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA_INFO 525 @@ -498,7 +518,8 @@ int ERR_load_SSL_strings(void); # define SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG_NTLS 762 # define SSL_F_TLS_CONSTRUCT_STOC_PSK 504 # define SSL_F_TLS_CONSTRUCT_STOC_PSK_NTLS 763 -# define SSL_F_TLS_CONSTRUCT_STOC_QUIC_TRANSPORT_PARAMS 845 +# define SSL_F_TLS_CONSTRUCT_STOC_QUIC_TRANSPORT_PARAMS 3009 +# define SSL_F_TLS_CONSTRUCT_STOC_QUIC_TRANSPORT_PARAMS_DRAFT 3014 # define SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE 458 # define SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE_NTLS 764 # define SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME 459 @@ -513,6 +534,7 @@ int ERR_load_SSL_strings(void); # define SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS_NTLS 769 # define SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP 462 # define SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP_NTLS 770 +# define SSL_F_TLS_DETERMINE_IF_USE_DC_FROM_EXTENSION 865 # define SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO 521 # define SSL_F_TLS_FINISH_HANDSHAKE 597 # define SSL_F_TLS_FINISH_HANDSHAKE_NTLS 771 @@ -528,6 +550,7 @@ int ERR_load_SSL_strings(void); # define SSL_F_TLS_PARSE_CTOS_ALPN_NTLS 774 # define SSL_F_TLS_PARSE_CTOS_COOKIE 614 # define SSL_F_TLS_PARSE_CTOS_COOKIE_NTLS 775 +# define SSL_F_TLS_PARSE_CTOS_DELEGATED_CREDENTIAL 862 # define SSL_F_TLS_PARSE_CTOS_EARLY_DATA 568 # define SSL_F_TLS_PARSE_CTOS_EARLY_DATA_NTLS 776 # define SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS 569 @@ -544,7 +567,8 @@ int ERR_load_SSL_strings(void); # define SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES 572 # define SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES_NTLS 783 # define SSL_F_TLS_PARSE_CTOS_PSK_NTLS 782 -# define SSL_F_TLS_PARSE_CTOS_QUIC_TRANSPORT_PARAMS 846 +# define SSL_F_TLS_PARSE_CTOS_QUIC_TRANSPORT_PARAMS 3010 +# define SSL_F_TLS_PARSE_CTOS_QUIC_TRANSPORT_PARAMS_DRAFT 3015 # define SSL_F_TLS_PARSE_CTOS_RENEGOTIATE 464 # define SSL_F_TLS_PARSE_CTOS_RENEGOTIATE_NTLS 784 # define SSL_F_TLS_PARSE_CTOS_SERVER_NAME 573 @@ -563,10 +587,12 @@ int ERR_load_SSL_strings(void); # define SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS_NTLS 791 # define SSL_F_TLS_PARSE_CTOS_USE_SRTP 465 # define SSL_F_TLS_PARSE_CTOS_USE_SRTP_NTLS 792 +# define SSL_F_TLS_PARSE_DC_FROM_EXTENSION 864 # define SSL_F_TLS_PARSE_STOC_ALPN 579 # define SSL_F_TLS_PARSE_STOC_ALPN_NTLS 793 # define SSL_F_TLS_PARSE_STOC_COOKIE 534 # define SSL_F_TLS_PARSE_STOC_COOKIE_NTLS 794 +# define SSL_F_TLS_PARSE_STOC_DELEGATED_CREDENTIAL 854 # define SSL_F_TLS_PARSE_STOC_EARLY_DATA 538 # define SSL_F_TLS_PARSE_STOC_EARLY_DATA_INFO 528 # define SSL_F_TLS_PARSE_STOC_EARLY_DATA_NTLS 795 @@ -580,7 +606,8 @@ int ERR_load_SSL_strings(void); # define SSL_F_TLS_PARSE_STOC_NPN_NTLS 799 # define SSL_F_TLS_PARSE_STOC_PSK 502 # define SSL_F_TLS_PARSE_STOC_PSK_NTLS 800 -# define SSL_F_TLS_PARSE_STOC_QUIC_TRANSPORT_PARAMS 847 +# define SSL_F_TLS_PARSE_STOC_QUIC_TRANSPORT_PARAMS 3011 +# define SSL_F_TLS_PARSE_STOC_QUIC_TRANSPORT_PARAMS_DRAFT 3016 # define SSL_F_TLS_PARSE_STOC_RENEGOTIATE 448 # define SSL_F_TLS_PARSE_STOC_RENEGOTIATE_NTLS 801 # define SSL_F_TLS_PARSE_STOC_SCT 564 @@ -623,6 +650,7 @@ int ERR_load_SSL_strings(void); # define SSL_F_TLS_PROCESS_CLIENT_HELLO_NTLS 816 # define SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE 382 # define SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE_NTLS 817 +# define SSL_F_TLS_PROCESS_DC_REQUEST 868 # define SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS 444 # define SSL_F_TLS_PROCESS_END_OF_EARLY_DATA 537 # define SSL_F_TLS_PROCESS_END_OF_EARLY_DATA_NTLS 818 @@ -746,6 +774,8 @@ int ERR_load_SSL_strings(void); # define SSL_R_DANE_TLSA_NULL_DATA 203 # define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED 145 # define SSL_R_DATA_LENGTH_TOO_LONG 146 +# define SSL_R_DC_LOAD_FAILED 457 +# define SSL_R_DC_VALID_TIME_TOO_LARGE 346 # define SSL_R_DECRYPTION_FAILED 147 # define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC 281 # define SSL_R_DH_KEY_TOO_SMALL 394 @@ -755,6 +785,7 @@ int ERR_load_SSL_strings(void); # define SSL_R_DUPLICATE_COMPRESSION_ID 309 # define SSL_R_ECC_CERT_NOT_FOR_SIGNING 318 # define SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE 374 +# define SSL_R_EE_CERT_NOT_FOUND 393 # define SSL_R_EE_KEY_TOO_SMALL 399 # define SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST 354 # define SSL_R_ENCRYPTED_LENGTH_TOO_LONG 150 @@ -766,7 +797,9 @@ int ERR_load_SSL_strings(void); # define SSL_R_EXTRA_DATA_IN_MESSAGE 153 # define SSL_R_EXT_LENGTH_MISMATCH 163 # define SSL_R_FAILED_TO_INIT_ASYNC 405 +# define SSL_R_FAILED_TO_VERIFY_DC_SIGNATURE 453 # define SSL_R_FRAGMENTED_CLIENT_HELLO 401 +# define SSL_R_GET_SIG_AND_HASH_ERR 450 # define SSL_R_GOT_A_FIN_BEFORE_A_CCS 154 # define SSL_R_HTTPS_PROXY_REQUEST 155 # define SSL_R_HTTP_REQUEST 156 @@ -806,6 +839,7 @@ int ERR_load_SSL_strings(void); # define SSL_R_MISSING_ECDSA_SIGNING_CERT 381 # define SSL_R_MISSING_FATAL 256 # define SSL_R_MISSING_PARAMETERS 290 +# define SSL_R_MISSING_QUIC_TRANSPORT_PARAMETERS_EXTENSION 801 # define SSL_R_MISSING_RSA_CERTIFICATE 168 # define SSL_R_MISSING_RSA_ENCRYPTING_CERT 169 # define SSL_R_MISSING_RSA_SIGNING_CERT 170 @@ -861,6 +895,7 @@ int ERR_load_SSL_strings(void); # define SSL_R_PEM_NAME_TOO_SHORT 392 # define SSL_R_PIPELINE_FAILURE 406 # define SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR 278 +# define SSL_R_PRIVATE_KEY_DOES_NOT_MATCH_DC 454 # define SSL_R_PRIVATE_KEY_MISMATCH 288 # define SSL_R_PROTOCOL_IS_SHUTDOWN 207 # define SSL_R_PSK_IDENTITY_NOT_FOUND 223 @@ -949,6 +984,7 @@ int ERR_load_SSL_strings(void); # define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS 239 # define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES 242 # define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES 243 +# define SSL_R_UNABLE_TO_LOOKUP_CERT 451 # define SSL_R_UNEXPECTED_CCS_MESSAGE 262 # define SSL_R_UNEXPECTED_END_OF_EARLY_DATA 178 # define SSL_R_UNEXPECTED_MESSAGE 244 @@ -979,7 +1015,7 @@ int ERR_load_SSL_strings(void); # define SSL_R_WRONG_CERTIFICATE_TYPE 383 # define SSL_R_WRONG_CIPHER_RETURNED 261 # define SSL_R_WRONG_CURVE 378 -# define SSL_R_WRONG_ENCRYPTION_LEVEL_RECEIVED 316 +# define SSL_R_WRONG_ENCRYPTION_LEVEL_RECEIVED 800 # define SSL_R_WRONG_SIGNATURE_LENGTH 264 # define SSL_R_WRONG_SIGNATURE_SIZE 265 # define SSL_R_WRONG_SIGNATURE_TYPE 370 diff --git a/include/openssl/storeerr.h b/include/openssl/storeerr.h index 190eab07f..1a666a3d8 100644 --- a/include/openssl/storeerr.h +++ b/include/openssl/storeerr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_OSSL_STOREERR_H # define HEADER_OSSL_STOREERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # ifdef __cplusplus extern "C" diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h index ca604f5a7..ce1aef4af 100644 --- a/include/openssl/tls1.h +++ b/include/openssl/tls1.h @@ -131,6 +131,9 @@ extern "C" { /* ExtensionType value from RFC7627 */ # define TLSEXT_TYPE_extended_master_secret 23 +/* ExtensionType value from draft-ietf-tls-subcerts-07 */ +# define TLSEXT_TYPE_delegated_credential 34 + /* ExtensionType value from RFC4507 */ # define TLSEXT_TYPE_session_ticket 35 @@ -148,8 +151,9 @@ extern "C" { /* Temporary extension type */ # define TLSEXT_TYPE_renegotiate 0xff01 -/* ExtensionType value from draft-ietf-quic-tls-13 */ -# define TLSEXT_TYPE_quic_transport_parameters 0xffa5 +/* ExtensionType value from draft-ietf-quic-tls-27 */ +# define TLSEXT_TYPE_quic_transport_parameters_draft 0xffa5 +# define TLSEXT_TYPE_quic_transport_parameters 0x0039 # ifndef OPENSSL_NO_NEXTPROTONEG /* This is not an IANA defined extension number */ diff --git a/include/openssl/tserr.h b/include/openssl/tserr.h index 07f23339c..dfde03782 100644 --- a/include/openssl/tserr.h +++ b/include/openssl/tserr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_TSERR_H # define HEADER_TSERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # include diff --git a/include/openssl/uierr.h b/include/openssl/uierr.h index bd68864d0..78c018112 100644 --- a/include/openssl/uierr.h +++ b/include/openssl/uierr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_UIERR_H # define HEADER_UIERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # ifdef __cplusplus extern "C" diff --git a/include/openssl/x509.h b/include/openssl/x509.h index b02bc18d2..7f671a13a 100644 --- a/include/openssl/x509.h +++ b/include/openssl/x509.h @@ -389,6 +389,46 @@ int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type, int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type, unsigned char *md, unsigned int *len); +# ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +# define DC_FILETYPE_RAW 0 + +void DC_free(DELEGATED_CREDENTIAL *dc); +DELEGATED_CREDENTIAL *DC_new(void); +DELEGATED_CREDENTIAL *DC_new_from_raw_byte(const unsigned char *byte, + unsigned long len); +int DC_check_valid(X509 *parent_cert, DELEGATED_CREDENTIAL *dc); +int DC_check_time_valid(X509 *parent_cert, DELEGATED_CREDENTIAL *dc); +int DC_check_parent_cert_valid(X509 *parent_cert); +unsigned long DC_get_valid_time(DELEGATED_CREDENTIAL *dc); +unsigned int DC_get_expected_cert_verify_algorithm(DELEGATED_CREDENTIAL *dc); +unsigned long DC_get_dc_publickey_raw_len(DELEGATED_CREDENTIAL *dc); +unsigned char *DC_get0_dc_publickey_raw(DELEGATED_CREDENTIAL *dc); +unsigned int DC_get_signature_sign_algorithm(DELEGATED_CREDENTIAL *dc); +unsigned int DC_get_dc_signature_len(DELEGATED_CREDENTIAL *dc); +unsigned char *DC_get0_dc_signature(DELEGATED_CREDENTIAL *dc); +EVP_PKEY *DC_get0_publickey(DELEGATED_CREDENTIAL *dc); +unsigned char *DC_get0_raw_byte(DELEGATED_CREDENTIAL *dc); +unsigned long DC_get_raw_byte_len(DELEGATED_CREDENTIAL *dc); +int DC_set_valid_time(DELEGATED_CREDENTIAL *dc, unsigned long valid_time); +int DC_set_expected_cert_verify_algorithm(DELEGATED_CREDENTIAL *dc, unsigned int alg); +int DC_set_dc_publickey_len(DELEGATED_CREDENTIAL *dc, unsigned long len); +int DC_set0_dc_publickey(DELEGATED_CREDENTIAL *dc, unsigned char *pub_key); +int DC_set_signature_sign_algorithm(DELEGATED_CREDENTIAL *dc, unsigned int alg); +int DC_set_dc_signature_len(DELEGATED_CREDENTIAL *dc, unsigned int len); +int DC_set0_dc_signature(DELEGATED_CREDENTIAL *dc, unsigned char *sig); +int DC_set0_raw_byte(DELEGATED_CREDENTIAL *dc, unsigned char *byte, + unsigned long len); +int DC_set1_raw_byte(DELEGATED_CREDENTIAL *dc, const unsigned char *byte, + unsigned long len); +int DC_set0_publickey(DELEGATED_CREDENTIAL *dc, EVP_PKEY *pkey); + + +int DC_check_private_key(DELEGATED_CREDENTIAL *dc, EVP_PKEY *pkey); + +int DC_up_ref(DELEGATED_CREDENTIAL *dc); +DELEGATED_CREDENTIAL *DC_load_from_file(const char *file); +# endif + # ifndef OPENSSL_NO_STDIO X509 *d2i_X509_fp(FILE *fp, X509 **x509); int i2d_X509_fp(FILE *fp, X509 *x509); diff --git a/include/openssl/x509err.h b/include/openssl/x509err.h index 9a957a7c0..1fe123882 100644 --- a/include/openssl/x509err.h +++ b/include/openssl/x509err.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -28,6 +28,7 @@ int ERR_load_X509_strings(void); # define X509_F_CHECK_POLICY 145 # define X509_F_COMMON_VERIFY_SM2 161 # define X509_F_DANE_I2D 107 +# define X509_F_DC_CHECK_PRIVATE_KEY 164 # define X509_F_DIR_CTRL 102 # define X509_F_GET_CERT_BY_SUBJECT 103 # define X509_F_I2D_X509_AUX 151 diff --git a/include/openssl/x509v3err.h b/include/openssl/x509v3err.h index 5f25442f1..73179a9ba 100644 --- a/include/openssl/x509v3err.h +++ b/include/openssl/x509v3err.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,7 @@ #ifndef HEADER_X509V3ERR_H # define HEADER_X509V3ERR_H -# ifndef HEADER_SYMHACKS_H -# include -# endif +# include # ifdef __cplusplus extern "C" diff --git a/ssl/build.info b/ssl/build.info index eec0d14f2..b7b136c83 100644 --- a/ssl/build.info +++ b/ssl/build.info @@ -13,4 +13,15 @@ SOURCE[../libssl]=\ bio_ssl.c ssl_err.c tls_srp.c t1_trce.c ssl_utst.c \ record/ssl3_buffer.c record/ssl3_record.c record/dtls1_bitmap.c \ statem/statem.c record/ssl3_record_tls13.c \ - ssl_quic.c statem/statem_quic.c + statem_ntls/statem_srvr.c statem_ntls/statem_clnt.c statem_ntls/extensions_cust.c \ + statem_ntls/statem_lib.c statem_ntls/extensions.c statem_ntls/extensions_srvr.c \ + statem_ntls/extensions_clnt.c statem_ntls/statem.c \ + statem_ntls/statem_ntls.c statem_ntls/statem_ntls_clnt.c statem_ntls/statem_ntls_srvr.c + +IF[{- !$disabled{quic} -}] + SOURCE[../libssl]=ssl_quic.c statem/statem_quic.c +ENDIF + +IF[{- !$disabled{'delegated-credential'} -}] + SOURCE[../libssl]=ssl_dc.c +ENDIF \ No newline at end of file diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 146e0a289..f35d758ab 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -3211,12 +3211,12 @@ static SSL_CIPHER ssl3_ciphers[] = { #endif /* OPENSSL_NO_ARIA */ #if (!defined OPENSSL_NO_NTLS) && (!defined OPENSSL_NO_SM2) \ && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) - /* GM/T 0024-2014 cipher suites */ + /* BEGIN GM/T 0024-2014 cipher suites */ { 1, NTLS_TXT_SM2DHE_WITH_SM4_SM3, NULL, - NTLS_CK_SM2DHE_WITH_SM4_SM3, + NTLS_CK_ECDHE_SM2_SM4_CBC_SM3, SSL_kSM2DHE, SSL_aSM2, SSL_SM4, @@ -3232,7 +3232,7 @@ static SSL_CIPHER ssl3_ciphers[] = { 1, NTLS_TXT_SM2_WITH_SM4_SM3, NULL, - NTLS_CK_SM2_WITH_SM4_SM3, + NTLS_CK_ECC_SM2_SM4_CBC_SM3, SSL_kSM2, SSL_aSM2, SSL_SM4, @@ -3244,13 +3244,14 @@ static SSL_CIPHER ssl3_ciphers[] = { 128, 128, }, + /* END GM/T 0024-2014 cipher suites */ { 1, - NTLS_TXT_RSA_WITH_SM4_SM3, + NTLS_TXT_ECDHE_SM2_SM4_CBC_SM3, NULL, - NTLS_CK_RSA_WITH_SM4_SM3, - SSL_kRSA, - SSL_aRSA, + NTLS_CK_ECDHE_SM2_SM4_CBC_SM3, + SSL_kSM2DHE, + SSL_aSM2, SSL_SM4, SSL_SM3, NTLS_VERSION, NTLS_VERSION, @@ -3262,20 +3263,52 @@ static SSL_CIPHER ssl3_ciphers[] = { }, { 1, - NTLS_TXT_RSA_WITH_SM4_SHA1, + NTLS_TXT_ECDHE_SM2_SM4_GCM_SM3, NULL, - NTLS_CK_RSA_WITH_SM4_SHA1, - SSL_kRSA, - SSL_aRSA, + NTLS_CK_ECDHE_SM2_SM4_GCM_SM3, + SSL_kSM2DHE, + SSL_aSM2, + SSL_SM4GCM, + SSL_AEAD, + NTLS_VERSION, NTLS_VERSION, + 0, 0, + SSL_HIGH, + SSL_HANDSHAKE_MAC_SM3 | TLS1_PRF_SM3, + 128, + 128, + }, + { + 1, + NTLS_TXT_ECC_SM2_SM4_CBC_SM3, + NULL, + NTLS_CK_ECC_SM2_SM4_CBC_SM3, + SSL_kSM2, + SSL_aSM2, SSL_SM4, - SSL_SHA1, + SSL_SM3, NTLS_VERSION, NTLS_VERSION, 0, 0, SSL_HIGH, - SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + SSL_HANDSHAKE_MAC_SM3 | TLS1_PRF_SM3, + 128, + 128, + }, + { + 1, + NTLS_TXT_ECC_SM2_SM4_GCM_SM3, + NULL, + NTLS_CK_ECC_SM2_SM4_GCM_SM3, + SSL_kSM2, + SSL_aSM2, + SSL_SM4GCM, + SSL_AEAD, + NTLS_VERSION, NTLS_VERSION, + 0, 0, + SSL_HIGH, + SSL_HANDSHAKE_MAC_SM3 | TLS1_PRF_SM3, 128, 128, - } + } #endif }; @@ -3433,6 +3466,9 @@ void ssl3_free(SSL *s) OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen); OPENSSL_free(s->s3->tmp.peer_sigalgs); OPENSSL_free(s->s3->tmp.peer_cert_sigalgs); +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + OPENSSL_free(s->s3->tmp.peer_dc_sigalgs); +#endif ssl3_free_digest_list(s); OPENSSL_free(s->s3->alpn_selected); OPENSSL_free(s->s3->alpn_proposed); diff --git a/ssl/s3_msg.c b/ssl/s3_msg.c index 8d3cd442a..7c3829122 100644 --- a/ssl/s3_msg.c +++ b/ssl/s3_msg.c @@ -79,7 +79,7 @@ int ssl3_dispatch_alert(SSL *s) if (SSL_IS_QUIC(s)) { if (!s->quic_method->send_alert(s, s->quic_write_level, s->s3->send_alert[1])) { - SSLerr(SSL_F_SSL3_DISPATCH_ALERT, SSL_R_INTERNAL_ERROR); + SSLerr(SSL_F_SSL3_DISPATCH_ALERT, ERR_R_INTERNAL_ERROR); return 0; } i = 1; diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c index 539da1a5b..e42fcda84 100644 --- a/ssl/ssl_asn1.c +++ b/ssl/ssl_asn1.c @@ -47,6 +47,10 @@ typedef struct { && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) X509 *peer_extra; #endif +#ifndef OPENSSL_NO_QUIC + uint32_t is_quic; + ASN1_OCTET_STRING *quic_early_data_context; +#endif } SSL_SESSION_ASN1; ASN1_SEQUENCE(SSL_SESSION_ASN1) = { @@ -80,7 +84,11 @@ ASN1_SEQUENCE(SSL_SESSION_ASN1) = { ASN1_EXP_OPT(SSL_SESSION_ASN1, ticket_appdata, ASN1_OCTET_STRING, 18), #if (!defined OPENSSL_NO_NTLS) && (!defined OPENSSL_NO_SM2) \ && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) - ASN1_EXP_OPT(SSL_SESSION_ASN1, peer_extra, X509, 19) + ASN1_EXP_OPT(SSL_SESSION_ASN1, peer_extra, X509, 19), +#endif +#ifndef OPENSSL_NO_QUIC + ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, is_quic, ZUINT32, 20), + ASN1_EXP_OPT(SSL_SESSION_ASN1, quic_early_data_context, ASN1_OCTET_STRING, 21), #endif } static_ASN1_SEQUENCE_END(SSL_SESSION_ASN1) @@ -131,7 +139,9 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp) #endif ASN1_OCTET_STRING alpn_selected; ASN1_OCTET_STRING ticket_appdata; - +#ifndef OPENSSL_NO_QUIC + ASN1_OCTET_STRING quic_early_data_context; +#endif long l; if ((in == NULL) || ((in->cipher == NULL) && (in->cipher_id == 0))) @@ -211,6 +221,17 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp) && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) as.peer_extra = in->peer_extra; #endif + +#ifndef OPENSSL_NO_QUIC + as.is_quic = in->is_quic; + + if (in->quic_early_data_context == NULL) + as.quic_early_data_context = NULL; + else + ssl_session_oinit(&as.quic_early_data_context, &quic_early_data_context, + in->quic_early_data_context, in->quic_early_data_context_len); +#endif + return i2d_SSL_SESSION_ASN1(&as, pp); } @@ -400,6 +421,20 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, as->peer_extra = NULL; #endif +#ifndef OPENSSL_NO_QUIC + ret->is_quic = as->is_quic; + + OPENSSL_free(ret->quic_early_data_context); + if (as->quic_early_data_context != NULL) { + ret->quic_early_data_context = as->quic_early_data_context->data; + ret->quic_early_data_context_len = as->quic_early_data_context->length; + as->quic_early_data_context->data = NULL; + } else { + ret->quic_early_data_context = NULL; + ret->quic_early_data_context_len = 0; + } +#endif + M_ASN1_free_of(as, SSL_SESSION_ASN1); if ((a != NULL) && (*a == NULL)) diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index 54b682b36..2380032b8 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -111,6 +111,22 @@ CERT *ssl_cert_dup(CERT *cert) EVP_PKEY_up_ref(cpk->privatekey); } +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + if (cert->dc_pkeys[i].dc) { + DC_up_ref(cert->dc_pkeys[i].dc); + ret->dc_pkeys[i].dc = cert->dc_pkeys[i].dc; + ret->dc_pkeys[i].parent = cert->dc_pkeys[i].parent; + } + + if (cert->dc_pkeys[i].privatekey) { + EVP_PKEY_up_ref(cert->dc_pkeys[i].privatekey); + ret->dc_pkeys[i].privatekey = cert->dc_pkeys[i].privatekey; + } + + rpk->dc = cpk->dc; + rpk->dc_privatekey = cpk->dc_privatekey; +#endif + if (cpk->chain) { rpk->chain = X509_chain_up_ref(cpk->chain); if (!rpk->chain) { @@ -216,6 +232,16 @@ void ssl_cert_clear_certs(CERT *c) OPENSSL_free(cpk->serverinfo); cpk->serverinfo = NULL; cpk->serverinfo_length = 0; +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + DC_free(c->dc_pkeys[i].dc); + c->dc_pkeys[i].dc = NULL; + c->dc_pkeys[i].parent = NULL; + EVP_PKEY_free(c->dc_pkeys[i].privatekey); + c->dc_pkeys[i].privatekey = NULL; + + cpk->dc = NULL; + cpk->dc_privatekey = NULL; +#endif } } diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c index 4d83c7516..cfc822a59 100644 --- a/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c @@ -2258,6 +2258,7 @@ unsigned long BABASSL_CIPHER_get_mac(const SSL_CIPHER *c) return c->algorithm_mac; } +#ifndef OPENSSL_NO_QUIC int SSL_CIPHER_get_prf_nid(const SSL_CIPHER *c) { switch (c->algorithm2 & (0xFF << TLS1_PRF_DGST_SHIFT)) { @@ -2289,3 +2290,4 @@ int SSL_CIPHER_get_prf_nid(const SSL_CIPHER *c) } return NID_undef; } +#endif diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c index c1e955bab..80a60dfdc 100644 --- a/ssl/ssl_conf.c +++ b/ssl/ssl_conf.c @@ -711,6 +711,69 @@ static int cmd_Enable_sm_tls13_strict(SSL_CONF_CTX *cctx, const char *value) } #endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +static int cmd_DC(SSL_CONF_CTX *cctx, const char *value) +{ + int rv = 1; + + if (cctx->ctx != NULL) + rv = SSL_CTX_use_dc_file(cctx->ctx, value, 0); + + if (cctx->ssl != NULL) + rv = SSL_use_dc_file(cctx->ssl, value, 0); + + return rv > 0; +} + +static int cmd_DCKey(SSL_CONF_CTX *cctx, const char *value) +{ + int rv = 1; + if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE)) + return -2; + + if (cctx->ctx != NULL) + rv = SSL_CTX_use_dc_PrivateKey_file(cctx->ctx, value, SSL_FILETYPE_PEM); + + if (cctx->ssl != NULL) + rv = SSL_use_dc_PrivateKey_file(cctx->ssl, value, SSL_FILETYPE_PEM); + + return rv > 0; +} + +static int cmd_Enable_verify_peer_by_dc(SSL_CONF_CTX *cctx, const char *value) +{ + if (strcmp(value, "on") == 0) { + if (cctx->ctx != NULL) + SSL_CTX_enable_verify_peer_by_dc(cctx->ctx); + if (cctx->ssl != NULL) + SSL_enable_verify_peer_by_dc(cctx->ssl); + } else { + if (cctx->ctx != NULL) + SSL_CTX_disable_verify_peer_by_dc(cctx->ctx); + if (cctx->ssl != NULL) + SSL_disable_verify_peer_by_dc(cctx->ssl); + } + return 1; +} + +static int cmd_Enable_sign_by_dc(SSL_CONF_CTX *cctx, const char *value) +{ + if (strcmp(value, "on") == 0) { + if (cctx->ctx != NULL) + SSL_CTX_enable_sign_by_dc(cctx->ctx); + if (cctx->ssl != NULL) + SSL_enable_sign_by_dc(cctx->ssl); + } else { + if (cctx->ctx != NULL) + SSL_CTX_disable_sign_by_dc(cctx->ctx); + if (cctx->ssl != NULL) + SSL_disable_sign_by_dc(cctx->ssl); + } + return 1; +} + +#endif + typedef struct { int (*cmd) (SSL_CONF_CTX *cctx, const char *value); const char *str_file; @@ -819,6 +882,13 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = { #ifndef OPENSSL_NO_SM2 SSL_CONF_CMD_STRING(Enable_sm_tls13_strict, "Enable_sm_tls13_strict", 0), #endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + SSL_CONF_CMD(DC, "dc", SSL_CONF_FLAG_CERTIFICATE, SSL_CONF_TYPE_FILE), + SSL_CONF_CMD(DCKey, "dc_key", SSL_CONF_FLAG_CERTIFICATE, + SSL_CONF_TYPE_FILE), + SSL_CONF_CMD_STRING(Enable_verify_peer_by_dc, "Enable_verify_peer_by_dc", 0), + SSL_CONF_CMD_STRING(Enable_sign_by_dc, "Enable_sign_by_dc", 0), +#endif }; /* Supported switches: must match order of switches in ssl_conf_cmds */ diff --git a/ssl/ssl_dc.c b/ssl/ssl_dc.c new file mode 100644 index 000000000..d6986ad7e --- /dev/null +++ b/ssl/ssl_dc.c @@ -0,0 +1,553 @@ +#include +#include +#include +#include +#include +#include +#include "ssl_local.h" + +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + +# define DELEGATED_CREDENTIAL_CLIENT_LABEL "TLS, client delegated credentials" +# define DELEGATED_CREDENTIAL_SERVER_LABEL "TLS, server delegated credentials" +# define DELEGATED_CREDENTIAL_SIGN_START_SIZE 64 + +# define W16(buf, value) {put_value(buf, value, 2); buf += 2;} +# define W24(buf, value) {put_value(buf, value, 3); buf += 3;} +# define W32(buf, value) {put_value(buf, value, 4); buf += 4;} + +static void put_value(unsigned char *buf, size_t value, size_t len) +{ + for (buf += len - 1; len > 0; len--) { + *buf = (unsigned char)(value & 0xff); + buf--; + value >>= 8; + } +} + +void SSL_CTX_enable_verify_peer_by_dc(SSL_CTX *ctx) +{ + ctx->enable_verify_peer_by_dc = 1; +} + +void SSL_CTX_disable_verify_peer_by_dc(SSL_CTX *ctx) +{ + ctx->enable_verify_peer_by_dc = 0; +} + +void SSL_enable_verify_peer_by_dc(SSL *s) +{ + s->enable_verify_peer_by_dc = 1; +} + +void SSL_disable_verify_peer_by_dc(SSL *s) +{ + s->enable_verify_peer_by_dc = 0; +} + +void SSL_CTX_enable_sign_by_dc(SSL_CTX *ctx) +{ + ctx->enable_sign_by_dc = 1; +} + +void SSL_CTX_disable_sign_by_dc(SSL_CTX *ctx) +{ + ctx->enable_sign_by_dc = 0; +} + +void SSL_enable_sign_by_dc(SSL *s) +{ + s->enable_sign_by_dc = 1; +} + +void SSL_disable_sign_by_dc(SSL *s) +{ + s->enable_sign_by_dc = 0; +} + +int SSL_get_delegated_credential_tag(SSL *s) +{ + return s->delegated_credential_tag; +} + +static int ssl_dc_tbs_data(unsigned char *parent_cert_raw, + long parent_cert_len, + DELEGATED_CREDENTIAL *dc, int is_server, + unsigned char **tbs, unsigned int *tbs_len) +{ + unsigned int sign_data_len; + unsigned int dc_cred_and_alg_len = 0; + unsigned char *index; + + if (dc == NULL) { + SSLerr(SSL_F_SSL_DC_TBS_DATA, ERR_R_INTERNAL_ERROR); + return 0; + } + + dc_cred_and_alg_len = DC_get_raw_byte_len(dc) - 2 - DC_get_dc_signature_len(dc); + + /* length of dc client label is equal to server label */ + sign_data_len = DELEGATED_CREDENTIAL_SIGN_START_SIZE + + sizeof(DELEGATED_CREDENTIAL_SERVER_LABEL) + + parent_cert_len + + dc_cred_and_alg_len; + + *tbs = OPENSSL_malloc(sign_data_len); + index = *tbs; + if (*tbs == NULL) { + SSLerr(SSL_F_SSL_DC_TBS_DATA, ERR_R_MALLOC_FAILURE); + return 0; + } + /* + * First part is a string that consists of octet 32 (0x20) repeated 64 times. + */ + memset(index, 32, DELEGATED_CREDENTIAL_SIGN_START_SIZE); + index += DELEGATED_CREDENTIAL_SIGN_START_SIZE; + + /* + * Second part is a context string "TLS, server delegated credentials" for + * servers and "TLS, client delegated credentials" for clients. + * Third part is a single 0 byte, which serves as the separator. + * '0' exists in DELEGATED_CREDENTIAL_SERVER_LABEL default terminator + */ + if (is_server) { + strcpy((char *)index, DELEGATED_CREDENTIAL_SERVER_LABEL); + index += sizeof(DELEGATED_CREDENTIAL_SERVER_LABEL); + } else { + strcpy((char *)index, DELEGATED_CREDENTIAL_CLIENT_LABEL); + index += sizeof(DELEGATED_CREDENTIAL_CLIENT_LABEL); + } + + /* + * Fourth part is the DER-encoded X.509 end-entity certificate used to sign the + * DelegatedCredential. + */ + memcpy(index, parent_cert_raw, parent_cert_len); + index += parent_cert_len; + + /* + * Fifth part is Credential in DelegatedCredential + * Sixth part is DelegatedCredential.algorithm. + * We can make a one-time copy from dc raw byte + */ + memcpy(index, DC_get0_raw_byte(dc), dc_cred_and_alg_len); + index += dc_cred_and_alg_len; + + if ((index - *tbs) != sign_data_len) { + SSLerr(SSL_F_SSL_DC_TBS_DATA, ERR_R_INTERNAL_ERROR); + return 0; + } + + *tbs_len = sign_data_len; + return 1; +} + +int SSL_verify_delegated_credential_signature(X509 *parent_cert, + DELEGATED_CREDENTIAL *dc, + int is_server) +{ + unsigned char *tbs = NULL; + unsigned int tbs_len; + int sig; + int hash; + int ret = 0; + EVP_MD_CTX *mctx = NULL; + EVP_PKEY_CTX *pctx = NULL; + int dc_sign_algo = 0; + unsigned char *parent_cert_raw = NULL; + unsigned char *parent_cert_raw_index = NULL; + long parent_cert_len; + const EVP_MD *md = NULL; + EVP_PKEY *pkey = NULL; + + if (parent_cert == NULL || dc == NULL) { + SSLerr(SSL_F_SSL_VERIFY_DELEGATED_CREDENTIAL_SIGNATURE, + ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + + pkey = X509_get0_pubkey(parent_cert); + if (pkey == NULL) { + SSLerr(SSL_F_SSL_VERIFY_DELEGATED_CREDENTIAL_SIGNATURE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + dc_sign_algo = DC_get_signature_sign_algorithm(dc); + + if (!tls1_get_sig_and_hash(dc_sign_algo, &sig, &hash)) { + SSLerr(SSL_F_SSL_VERIFY_DELEGATED_CREDENTIAL_SIGNATURE, + SSL_R_SIGNATURE_ALGORITHMS_ERROR); + goto err; + } + + md = EVP_get_digestbynid(hash); + + parent_cert_len = i2d_X509_AUX(parent_cert, NULL); + if (parent_cert_len <= 0) { + SSLerr(SSL_F_SSL_VERIFY_DELEGATED_CREDENTIAL_SIGNATURE, + ERR_R_INTERNAL_ERROR); + goto err; + } + if ((parent_cert_raw = OPENSSL_malloc(parent_cert_len)) == NULL) { + SSLerr(SSL_F_SSL_VERIFY_DELEGATED_CREDENTIAL_SIGNATURE, + ERR_R_MALLOC_FAILURE); + goto err; + } + + parent_cert_raw_index = parent_cert_raw; + parent_cert_len = i2d_X509_AUX(parent_cert, &parent_cert_raw_index); + + if (!ssl_dc_tbs_data(parent_cert_raw, parent_cert_len, + dc, is_server, &tbs, &tbs_len)) { + goto err; + } + + mctx = EVP_MD_CTX_new(); + if (mctx == NULL) { + SSLerr(SSL_F_SSL_VERIFY_DELEGATED_CREDENTIAL_SIGNATURE, + ERR_R_MALLOC_FAILURE); + goto err; + } + +#ifndef OPENSSL_NO_SM2 + if (EVP_PKEY_is_sm2(pkey)) { + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (pctx == NULL) { + SSLerr(SSL_F_SSL_VERIFY_DELEGATED_CREDENTIAL_SIGNATURE, + ERR_R_MALLOC_FAILURE); + goto err; + } + /* + * Thus there is no standard for SM-delegated_credential, so + * we choose default sm2-id for dc, which has been set default + */ + EVP_MD_CTX_set_pkey_ctx(mctx, pctx); + } +#endif + + if (EVP_DigestVerifyInit(mctx, &pctx, md, NULL, pkey) <= 0) { + SSLerr(SSL_F_SSL_VERIFY_DELEGATED_CREDENTIAL_SIGNATURE, ERR_R_EVP_LIB); + goto err; + } + + if (sig == EVP_PKEY_RSA_PSS) { + if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0 + || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, + RSA_PSS_SALTLEN_DIGEST) <= 0) { + SSLerr(SSL_F_SSL_VERIFY_DELEGATED_CREDENTIAL_SIGNATURE, ERR_R_EVP_LIB); + goto err; + } + } + + ret = EVP_DigestVerify(mctx, DC_get0_dc_signature(dc), DC_get_dc_signature_len(dc), + (const unsigned char *)tbs, tbs_len); + +err: +#ifndef OPENSSL_NO_SM2 + if (pkey != NULL && EVP_PKEY_is_sm2(pkey)) { + /*other sig call EVP_PKEY_CTX_free there may cause segfault */ + EVP_PKEY_CTX_free(pctx); + } +#endif + EVP_MD_CTX_free(mctx); + OPENSSL_free(tbs); + OPENSSL_free(parent_cert_raw); + return ret; +} + +int DC_sign(DELEGATED_CREDENTIAL *dc, EVP_PKEY *dc_pkey, + unsigned int valid_time, int expect_verify_hash, + X509 *ee_cert, EVP_PKEY *ee_pkey, const EVP_MD *md, int is_server) +{ + int ret = 0; + int day, sec; + int sig; + unsigned char *dc_pkey_raw_index = NULL; + uint32_t max_valid_time = 7 * 24 * 3600; + unsigned char *dc_buf, *index; + int dc_raw_len = 0; + unsigned char *tbs = NULL; + unsigned int tbs_len; + int res = 0; + EVP_MD_CTX *mctx = NULL; + EVP_PKEY_CTX *pctx = NULL; + ASN1_TIME *ee_cert_time = NULL, *curr_time = NULL; + uint16_t expected_cert_verify_algorithm; + uint32_t dc_pkey_raw_len; + unsigned char *dc_pkey_raw = NULL; + uint16_t sign_algorithm = 0; + size_t dc_sign_len, dc_sign_result_len; + unsigned char *parent_cert_raw = NULL, *parent_cert_raw_index = NULL; + int ee_cert_len; + + if (dc == NULL || dc_pkey == NULL + || ee_cert == NULL || ee_pkey == NULL) { + SSLerr(SSL_F_DC_SIGN, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!DC_check_parent_cert_valid(ee_cert)) { + goto end; + } + + dc_pkey_raw_len = i2d_PUBKEY(dc_pkey, NULL); + if (dc_pkey_raw_len <= 0) { + SSLerr(SSL_F_DC_SIGN, ERR_R_INTERNAL_ERROR); + goto end; + } + + if ((dc_pkey_raw = OPENSSL_malloc(dc_pkey_raw_len)) == NULL) { + SSLerr(SSL_F_DC_SIGN, ERR_R_MALLOC_FAILURE); + goto end; + } + + dc_pkey_raw_index = dc_pkey_raw; + dc_pkey_raw_len = i2d_PUBKEY(dc_pkey, &dc_pkey_raw_index); + + if (!tls1_lookup_sigalg_by_pkey_and_hash( + dc_pkey, expect_verify_hash, + 1, &expected_cert_verify_algorithm)) { + goto end; + } + + if (!tls1_lookup_sigalg_by_pkey_and_hash(ee_pkey, EVP_MD_type(md), + 0, &sign_algorithm)) { + goto end; + } + + if (valid_time > max_valid_time) { + SSLerr(SSL_F_DC_SIGN, SSL_R_DC_VALID_TIME_TOO_LARGE); + goto end; + } + + ee_cert_time = ASN1_STRING_dup(X509_get0_notBefore(ee_cert)); + if (ee_cert_time == NULL) { + SSLerr(SSL_F_DC_SIGN, ERR_R_INTERNAL_ERROR); + goto end; + } + + curr_time = X509_time_adj(NULL, 0, NULL); + if (curr_time == NULL) { + goto end; + } + + if (!ASN1_TIME_diff(&day, &sec, ee_cert_time, curr_time)) { + goto end; + } + + if (day < 0 || sec < 0 ) { + goto end; + } + + valid_time += day * 24 * 3600 + sec; + + dc_sign_len = EVP_PKEY_size(ee_pkey); + + dc_raw_len = sizeof(uint32_t) + sizeof(uint16_t) + 3 + dc_pkey_raw_len + + sizeof(uint16_t) + 2 + dc_sign_len; + + dc_buf = OPENSSL_malloc(dc_raw_len); + if (!dc_buf) { + SSLerr(SSL_F_DC_SIGN, ERR_R_MALLOC_FAILURE); + goto end; + } + + index = dc_buf; + + /* uint32 valid_time */ + W32(index, valid_time); + + /* SignatureScheme expected_cert_verify_algorithm */ + W16(index, expected_cert_verify_algorithm); + + /* opaque ASN1_subjectPublicKeyInfo<1..2^24-1> */ + W24(index, dc_pkey_raw_len); + memcpy(index, dc_pkey_raw, dc_pkey_raw_len); + index += dc_pkey_raw_len; + + /* SignatureScheme algorithm */ + W16(index, sign_algorithm); + + /* + * Actualy dc_sign_len is not the real sign result len, but function + * ssl_dc_tbs_data only need credential and sign + * algorithm. So we can get right result even if using a wrong + * dc_sign_len + */ + W16(index, dc_sign_len); + + DC_set_dc_signature_len(dc, dc_sign_len); + DC_set0_raw_byte(dc, dc_buf, dc_raw_len); + + ee_cert_len = i2d_X509_AUX(ee_cert, NULL); + if (ee_cert_len <= 0) { + goto end; + } + if ((parent_cert_raw = OPENSSL_malloc(ee_cert_len)) == NULL) { + goto end; + } + + parent_cert_raw_index = parent_cert_raw; + ee_cert_len = i2d_X509_AUX(ee_cert, &parent_cert_raw_index); + + res = ssl_dc_tbs_data(parent_cert_raw, ee_cert_len, + dc, is_server, &tbs, &tbs_len); + if (res <= 0) { + goto end; + } + + mctx = EVP_MD_CTX_new(); + if (mctx == NULL) { + SSLerr(SSL_F_DC_SIGN, ERR_R_MALLOC_FAILURE); + goto end; + } + +#ifndef OPENSSL_NO_SM2 + if (EVP_PKEY_is_sm2(ee_pkey)) { + pctx = EVP_PKEY_CTX_new(ee_pkey, NULL); + if (pctx == NULL) { + SSLerr(SSL_F_DC_SIGN, ERR_R_MALLOC_FAILURE); + goto end; + } + /* + * Thus there is no standard for SM-delegated_credential, so + * we choose default sm2-id for dc, which has been set default + */ + EVP_MD_CTX_set_pkey_ctx(mctx, pctx); + } +#endif + if (EVP_DigestSignInit(mctx, &pctx, EVP_get_digestbynid(sign_algorithm), + NULL, ee_pkey) <= 0) { + SSLerr(SSL_F_DC_SIGN, ERR_R_EVP_LIB); + goto end; + } + + if (!tls1_get_sig_and_hash(sign_algorithm, &sig, NULL)) { + SSLerr(SSL_F_DC_SIGN, ERR_R_INTERNAL_ERROR); + goto end; + } + + if (sig == EVP_PKEY_RSA_PSS) { + if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0 + || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, + RSA_PSS_SALTLEN_DIGEST) <= 0) { + SSLerr(SSL_F_DC_SIGN, ERR_R_EVP_LIB); + goto end; + } + } + + dc_sign_result_len = dc_sign_len; + res = EVP_DigestSign(mctx, index, &dc_sign_result_len, + (const unsigned char *)tbs, tbs_len); + if (res <= 0) { + SSLerr(SSL_F_DC_SIGN, ERR_R_EVP_LIB); + goto end; + } + + index -= 2; + W16(index, dc_sign_result_len); + DC_set_dc_signature_len(dc, dc_sign_result_len); + + dc_raw_len = dc_raw_len - dc_sign_len + dc_sign_result_len; + DC_set0_raw_byte(dc, DC_get0_raw_byte(dc), dc_raw_len); + + ret = 1; +end: + OPENSSL_free(tbs); + EVP_MD_CTX_free(mctx); +#ifndef OPENSSL_NO_SM2 + if (EVP_PKEY_is_sm2(ee_pkey)) + EVP_PKEY_CTX_free(pctx); +#endif + OPENSSL_free(dc_pkey_raw); + OPENSSL_free(parent_cert_raw); + ASN1_STRING_clear_free(ee_cert_time); + ASN1_STRING_clear_free(curr_time); + + return ret; +} + +int DC_print(BIO *bp, DELEGATED_CREDENTIAL *dc) +{ + int ret = 0; + int indent = 0; + unsigned int i, siglen; + unsigned char *sig; + const SIGALG_LOOKUP *lu = NULL; + + if (BIO_printf(bp, "DelegatedCredential:\n") <= 0) + goto end; + + indent += 4; + if (BIO_printf(bp, "%*sCredential:\n", indent, "") <= 0) + goto end; + + indent += 4; + if (BIO_printf(bp, "%*svalid_time: %lu\n", + indent, "", DC_get_valid_time(dc)) <= 0) + goto end; + + lu = tls1_lookup_sigalg(DC_get_expected_cert_verify_algorithm(dc)); + + if (BIO_printf(bp, "%*sexpected_cert_verify_algorithm: %s (0x%04x)\n", + indent, "", lu ? lu->name : "unknown", + DC_get_expected_cert_verify_algorithm(dc)) <= 0) + goto end; + + if (BIO_printf(bp, "%*sSubject Public Key Info:\n", indent, "") <= 0) + goto end; + + indent += 4; + if (BIO_printf(bp, "%*sPublic Key Algorithm: ", indent, "") <= 0) + goto end; + + if (i2a_ASN1_OBJECT(bp, OBJ_nid2obj( + EVP_PKEY_id(DC_get0_publickey(dc)))) <= 0) + goto end; + + if (BIO_puts(bp, "\n") <= 0) + goto end; + + indent += 4; + if (EVP_PKEY_print_public(bp, DC_get0_publickey(dc), indent, NULL) <= 0) + goto end; + + indent = 4; + lu = tls1_lookup_sigalg(DC_get_signature_sign_algorithm(dc)); + if (BIO_printf(bp, "%*sSignature Algorithm: %s (0x%04x)", + indent, "", lu ? lu->name : "unknown", + DC_get_signature_sign_algorithm(dc)) <= 0) + goto end; + + + if (BIO_printf(bp, "\n%*sSignature:", indent, "") <= 0) + goto end; + + indent += 4; + + sig = DC_get0_dc_signature(dc); + siglen = DC_get_dc_signature_len(dc); + + for (i = 0; i < siglen; i++) { + if ((i % 18) == 0) { + if (BIO_write(bp, "\n", 1) <= 0) + goto end; + if (BIO_indent(bp, indent, indent) <= 0) + goto end; + } + + if (BIO_printf(bp, "%02x%s", sig[i], + ((i + 1) == siglen) ? "" : ":") <= 0) + goto end; + } + + if (BIO_write(bp, "\n", 1) <= 0) + goto end; + + ret = 1; + +end: + return ret; +} +#endif \ No newline at end of file diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index 480d58f49..68e0b1ec7 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -48,6 +48,7 @@ static const ERR_STRING_DATA SSL_str_functs[] = { {ERR_PACK(ERR_LIB_SSL, SSL_F_DANE_CTX_ENABLE, 0), "dane_ctx_enable"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_DANE_MTYPE_SET, 0), "dane_mtype_set"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_DANE_TLSA_ADD, 0), "dane_tlsa_add"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DC_SIGN, 0), "DC_sign"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_DERIVE_SECRET_KEY_AND_IV, 0), "derive_secret_key_and_iv"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_DO_DTLS1_WRITE, 0), "do_dtls1_write"}, @@ -105,6 +106,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = { {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_KEY_SHARE, 0), "final_key_share"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_MAXFRAGMENTLEN, 0), "final_maxfragmentlen"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_QUIC_TRANSPORT_PARAMS, 0), + "final_quic_transport_params"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_RENEGOTIATE, 0), "final_renegotiate"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_SERVER_NAME, 0), "final_server_name"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_SIG_ALGS, 0), "final_sig_algs"}, @@ -376,6 +379,13 @@ static const ERR_STRING_DATA SSL_str_functs[] = { "SSL_CTX_use_certificate_ASN1"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, 0), "SSL_CTX_use_certificate_file"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_DC, 0), "SSL_CTX_use_dc"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_DC_FILE, 0), + "SSL_CTX_use_dc_file"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_DC_PRIVATEKEY, 0), + "SSL_CTX_use_dc"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_DC_PRIVATEKEY_FILE, 0), + "SSL_CTX_use_dc_file"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_ENC_CERTIFICATE, 0), "SSL_CTX_use_enc_certificate"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_ENC_CERTIFICATE_FILE, 0), @@ -414,6 +424,7 @@ static const ERR_STRING_DATA SSL_str_functs[] = { "SSL_CTX_use_sign_PrivateKey_file"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DANE_DUP, 0), "ssl_dane_dup"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DANE_ENABLE, 0), "SSL_dane_enable"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DC_TBS_DATA, 0), "ssl_dc_tbs_data"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DERIVE, 0), "ssl_derive"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DO_CONFIG, 0), "ssl_do_config"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DO_HANDSHAKE, 0), "SSL_do_handshake"}, @@ -483,6 +494,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = { "SSL_set_cipher_list"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_CT_VALIDATION_CALLBACK, 0), "SSL_set_ct_validation_callback"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_DC, 0), "ssl_set_dc"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_DC_PKEY, 0), "ssl_set_dc_pkey"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_FD, 0), "SSL_set_fd"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_PKEY, 0), "ssl_set_pkey"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_PKEY_IDX, 0), "ssl_set_pkey_idx"}, @@ -513,6 +526,12 @@ static const ERR_STRING_DATA SSL_str_functs[] = { "ssl_use_certificate_file_idx"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_CERTIFICATE_IDX, 0), "ssl_use_certificate_idx"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_DC, 0), "SSL_use_dc"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_DC_FILE, 0), "SSL_use_dc_file"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_DC_PRIVATEKEY, 0), + "SSL_use_dc_PrivateKey"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_DC_PRIVATEKEY_FILE, 0), + "SSL_use_dc_PrivateKey_file"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_PRIVATEKEY, 0), "SSL_use_PrivateKey"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_PRIVATEKEY_ASN1, 0), "SSL_use_PrivateKey_ASN1"}, @@ -535,6 +554,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = { "ssl_verify_cert_chain"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, 0), "SSL_verify_client_post_handshake"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_VERIFY_DELEGATED_CREDENTIAL_SIGNATURE, 0), + "SSL_verify_delegated_credential_signature"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_WRITE, 0), "SSL_write"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_WRITE_EARLY_DATA, 0), "SSL_write_early_data"}, @@ -583,6 +604,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = { "tls1_set_raw_sigalgs"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_SET_SERVER_SIGALGS, 0), "tls1_set_server_sigalgs"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_SET_SHARED_DC_SIGALGS, 0), + "tls1_set_shared_dc_sigalgs"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_SET_SHARED_SIGALGS, 0), "tls1_set_shared_sigalgs"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_SET_SIGALGS, 0), "tls1_set_sigalgs"}, @@ -648,6 +671,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = { "tls_construct_ctos_cookie"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_COOKIE_NTLS, 0), "tls_construct_ctos_cookie_ntls"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_DELEGATED_CREDENTIAL, 0), + "tls_construct_ctos_delegated_credential"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, 0), "tls_construct_ctos_early_data"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA_NTLS, 0), @@ -696,6 +721,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = { "tls_construct_ctos_psk_ntls"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_QUIC_TRANSPORT_PARAMS, 0), "tls_construct_ctos_quic_transport_params"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_QUIC_TRANSPORT_PARAMS_DRAFT, 0), + "tls_construct_ctos_quic_transport_params_draft"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE, 0), "tls_construct_ctos_renegotiate"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE_NTLS, 0), @@ -737,6 +764,10 @@ static const ERR_STRING_DATA SSL_str_functs[] = { {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP_NTLS, 0), "tls_construct_ctos_use_srtp_ntls"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_VERIFY, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_DELEGATED_CREDENTIAL_RAW, 0), + "tls_construct_delegated_credential_raw"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_DELEGATED_CREDENTIAL_REQUEST, 0), + "tls_construct_delegated_credential_request"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_ENCRYPTED_EXTENSIONS, 0), "tls_construct_encrypted_extensions"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA, 0), @@ -791,6 +822,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = { "tls_construct_stoc_cryptopro_bug"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG_NTLS, 0), "tls_construct_stoc_cryptopro_bug_ntls"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_DELEGATED_CREDENTIAL, 0), + "tls_construct_stoc_delegated_credential"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_DONE, 0), ""}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA, 0), "tls_construct_stoc_early_data"}, @@ -829,6 +862,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = { "tls_construct_stoc_psk_ntls"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_QUIC_TRANSPORT_PARAMS, 0), "tls_construct_stoc_quic_transport_params"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_QUIC_TRANSPORT_PARAMS_DRAFT, 0), + "tls_construct_stoc_quic_transport_params_draft"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE, 0), "tls_construct_stoc_renegotiate"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE_NTLS, 0), @@ -857,6 +892,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = { "tls_construct_stoc_use_srtp"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP_NTLS, 0), "tls_construct_stoc_use_srtp_ntls"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_DETERMINE_IF_USE_DC_FROM_EXTENSION, 0), + "tls_determine_if_use_dc_from_extension"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, 0), "tls_early_post_process_client_hello"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_FINISH_HANDSHAKE, 0), @@ -885,6 +922,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = { "tls_parse_ctos_cookie"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_COOKIE_NTLS, 0), "tls_parse_ctos_cookie_ntls"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_DELEGATED_CREDENTIAL, 0), + "tls_parse_ctos_delegated_credential"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_EARLY_DATA, 0), "tls_parse_ctos_early_data"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_EARLY_DATA_NTLS, 0), @@ -917,6 +956,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = { "tls_parse_ctos_psk_ntls"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_QUIC_TRANSPORT_PARAMS, 0), "tls_parse_ctos_quic_transport_params"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_QUIC_TRANSPORT_PARAMS_DRAFT, 0), + "tls_parse_ctos_quic_transport_params_draft"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE, 0), "tls_parse_ctos_renegotiate"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE_NTLS, 0), @@ -952,6 +993,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = { "tls_parse_ctos_use_srtp"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_USE_SRTP_NTLS, 0), "tls_parse_ctos_use_srtp_ntls"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_DC_FROM_EXTENSION, 0), + "tls_parse_dc_from_extension"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_ALPN, 0), "tls_parse_stoc_alpn"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_ALPN_NTLS, 0), @@ -960,6 +1003,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = { "tls_parse_stoc_cookie"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_COOKIE_NTLS, 0), "tls_parse_stoc_cookie_ntls"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_DELEGATED_CREDENTIAL, 0), + "tls_parse_stoc_delegated_credential"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_EARLY_DATA, 0), "tls_parse_stoc_early_data"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_EARLY_DATA_INFO, 0), ""}, @@ -985,6 +1030,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = { "tls_parse_stoc_psk_ntls"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_QUIC_TRANSPORT_PARAMS, 0), "tls_parse_stoc_quic_transport_params"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_QUIC_TRANSPORT_PARAMS_DRAFT, 0), + "tls_parse_stoc_quic_transport_params_draft"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_RENEGOTIATE, 0), "tls_parse_stoc_renegotiate"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_RENEGOTIATE_NTLS, 0), @@ -1067,6 +1114,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = { "tls_process_client_key_exchange"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE_NTLS, 0), "tls_process_client_key_exchange_ntls"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_DC_REQUEST, 0), + "tls_process_dc_request"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS, 0), "tls_process_encrypted_extensions"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_END_OF_EARLY_DATA, 0), @@ -1267,6 +1316,10 @@ static const ERR_STRING_DATA SSL_str_reasons[] = { "data between ccs and finished"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DATA_LENGTH_TOO_LONG), "data length too long"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DC_LOAD_FAILED), + "failed to load delegated credential"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DC_VALID_TIME_TOO_LARGE), + "DC valid time too large"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DECRYPTION_FAILED), "decryption failed"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC), "decryption failed or bad record mac"}, @@ -1283,6 +1336,7 @@ static const ERR_STRING_DATA SSL_str_reasons[] = { "ecc cert not for signing"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE), "ecdh required for suiteb mode"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EE_CERT_NOT_FOUND), "ee cert not found"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EE_KEY_TOO_SMALL), "ee key too small"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST), "empty srtp protection profile list"}, @@ -1304,8 +1358,12 @@ static const ERR_STRING_DATA SSL_str_reasons[] = { "ext length mismatch"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_FAILED_TO_INIT_ASYNC), "failed to init async"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_FAILED_TO_VERIFY_DC_SIGNATURE), + "failed to verify dc signature"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_FRAGMENTED_CLIENT_HELLO), "fragmented client hello"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_GET_SIG_AND_HASH_ERR), + "unable to get sig and hash"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_GOT_A_FIN_BEFORE_A_CCS), "got a fin before a ccs"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_HTTPS_PROXY_REQUEST), @@ -1370,6 +1428,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = { "missing ecdsa signing cert"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_FATAL), "missing fatal"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_PARAMETERS), "missing parameters"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_QUIC_TRANSPORT_PARAMETERS_EXTENSION), + "missing quic transport parameters extension"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_RSA_CERTIFICATE), "missing rsa certificate"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_RSA_ENCRYPTING_CERT), @@ -1462,6 +1522,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = { {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PIPELINE_FAILURE), "pipeline failure"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR), "post handshake auth encoding err"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PRIVATE_KEY_DOES_NOT_MATCH_DC), + "private key does not match dc"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PRIVATE_KEY_MISMATCH), "private key mismatch"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PROTOCOL_IS_SHUTDOWN), @@ -1628,6 +1690,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = { "unable to load ssl3 md5 routines"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES), "unable to load ssl3 sha1 routines"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNABLE_TO_LOOKUP_CERT), + "unable to lookup cert"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_CCS_MESSAGE), "unexpected ccs message"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_END_OF_EARLY_DATA), diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 3e8b24db8..4d84b9b23 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -641,7 +641,11 @@ int SSL_clear(SSL *s) OPENSSL_free(s->shared_sigalgs); s->shared_sigalgs = NULL; s->shared_sigalgslen = 0; - +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + OPENSSL_free(s->shared_dc_sigalgs); + s->shared_dc_sigalgs = NULL; + s->shared_dc_sigalgslen = 0; +#endif /* * Check to see if we were changed into a different method, if so, revert * back. @@ -727,7 +731,11 @@ SSL *SSL_new(SSL_CTX *ctx) #ifndef OPENSSL_NO_SM2 s->enable_sm_tls13_strict = ctx->enable_sm_tls13_strict; #endif - +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + s->enable_verify_peer_by_dc = ctx->enable_verify_peer_by_dc; + s->enable_sign_by_dc = ctx->enable_sign_by_dc; + s->delegated_credential_tag = 0; +#endif /* Shallow copy of the ciphersuites stack */ s->tls13_ciphersuites = sk_SSL_CIPHER_dup(ctx->tls13_ciphersuites); if (s->tls13_ciphersuites == NULL) @@ -1205,8 +1213,9 @@ void SSL_free(SSL *s) ssl_cert_free(s->cert); OPENSSL_free(s->shared_sigalgs); - /* Free up if allocated */ - +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + OPENSSL_free(s->shared_dc_sigalgs); +#endif OPENSSL_free(s->ext.hostname); SSL_CTX_free(s->session_ctx); #ifndef OPENSSL_NO_EC @@ -1232,7 +1241,10 @@ void SSL_free(SSL *s) #ifndef OPENSSL_NO_QUIC OPENSSL_free(s->ext.quic_transport_params); + OPENSSL_free(s->ext.peer_quic_transport_params_draft); OPENSSL_free(s->ext.peer_quic_transport_params); + BUF_MEM_free(s->quic_buf); + OPENSSL_free(s->quic_early_data_context); while (s->quic_input_data_head != NULL) { QUIC_DATA *qd; @@ -3044,6 +3056,10 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) #endif #ifndef OPENSSL_NO_SM2 ret->enable_sm_tls13_strict = 0; +#endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + ret->enable_verify_peer_by_dc = 0; + ret->enable_sign_by_dc = 0; #endif ret->method = meth; ret->min_proto_version = 0; @@ -3826,7 +3842,7 @@ int SSL_do_handshake(SSL *s) ret = s->handshake_func(s); } } - +#ifndef OPENSSL_NO_QUIC if (SSL_IS_QUIC(s) && ret == 1) { if (s->server) { if (s->early_data_state == SSL_EARLY_DATA_ACCEPTING) { @@ -3834,15 +3850,13 @@ int SSL_do_handshake(SSL *s) s->rwstate = SSL_READING; ret = 0; } - } else { - if (s->early_data_state == SSL_EARLY_DATA_CONNECTING) { - s->early_data_state = SSL_EARLY_DATA_WRITE_RETRY; - s->rwstate = SSL_READING; - ret = 0; - } + } else if (s->early_data_state == SSL_EARLY_DATA_CONNECTING) { + s->early_data_state = SSL_EARLY_DATA_WRITE_RETRY; + s->rwstate = SSL_READING; + ret = 0; } } - +#endif return ret; } diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h index 6d5baa381..30a140bf4 100644 --- a/ssl/ssl_local.h +++ b/ssl/ssl_local.h @@ -594,6 +594,9 @@ struct ssl_session_st { int not_resumable; /* This is the cert and type for the other end. */ X509 *peer; +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + DELEGATED_CREDENTIAL *peer_dc; +#endif int peer_type; /* Certificate chain peer sent. */ STACK_OF(X509) *peer_chain; @@ -649,6 +652,12 @@ struct ssl_session_st { size_t ticket_appdata_len; uint32_t flags; CRYPTO_RWLOCK *lock; +# ifndef OPENSSL_NO_QUIC + unsigned int is_quic : 1; + + uint8_t *quic_early_data_context; + size_t quic_early_data_context_len; +# endif }; /* Extended master secret support */ @@ -770,6 +779,7 @@ typedef enum tlsext_index_en { TLSEXT_IDX_use_srtp, TLSEXT_IDX_encrypt_then_mac, TLSEXT_IDX_signed_certificate_timestamp, + TLSEXT_IDX_delegated_credential, TLSEXT_IDX_extended_master_secret, TLSEXT_IDX_signature_algorithms_cert, TLSEXT_IDX_post_handshake_auth, @@ -781,6 +791,7 @@ typedef enum tlsext_index_en { TLSEXT_IDX_cryptopro_bug, TLSEXT_IDX_early_data, TLSEXT_IDX_certificate_authorities, + TLSEXT_IDX_quic_transport_params_draft, TLSEXT_IDX_quic_transport_params, TLSEXT_IDX_padding, TLSEXT_IDX_psk, @@ -1144,23 +1155,31 @@ struct ssl_ctx_st { */ int enable_sm_tls13_strict; #endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + int enable_verify_peer_by_dc; + int enable_sign_by_dc; +#endif #ifndef OPENSSL_NO_QUIC const SSL_QUIC_METHOD *quic_method; #endif }; +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +typedef struct dc_pkey_st DC_PKEY; +#endif + typedef struct cert_pkey_st CERT_PKEY; #ifndef OPENSSL_NO_QUIC struct quic_data_st { struct quic_data_st *next; OSSL_ENCRYPTION_LEVEL level; - size_t offset; + size_t start; /* offset into quic_buf->data */ size_t length; }; typedef struct quic_data_st QUIC_DATA; -int quic_set_encryption_secrets(SSL *ssl, OSSL_ENCRYPTION_LEVEL level); +int quic_set_encryption_secrets(SSL *s, OSSL_ENCRYPTION_LEVEL level); #endif struct ssl_st { @@ -1471,6 +1490,8 @@ struct ssl_st { #ifndef OPENSSL_NO_QUIC uint8_t *quic_transport_params; size_t quic_transport_params_len; + uint8_t *peer_quic_transport_params_draft; + size_t peer_quic_transport_params_draft_len; uint8_t *peer_quic_transport_params; size_t peer_quic_transport_params_len; #endif @@ -1479,9 +1500,22 @@ struct ssl_st { #ifndef OPENSSL_NO_QUIC OSSL_ENCRYPTION_LEVEL quic_read_level; OSSL_ENCRYPTION_LEVEL quic_write_level; + OSSL_ENCRYPTION_LEVEL quic_latest_level_received; + /* + * defaults to 0, but can be set to: + * - TLSEXT_TYPE_quic_transport_parameters_draft + * - TLSEXT_TYPE_quic_transport_parameters + * Client: if 0, send both + * Server: if 0, use same version as client sent + */ + int quic_transport_version; + BUF_MEM *quic_buf; /* buffer incoming handshake messages */ QUIC_DATA *quic_input_data_head; QUIC_DATA *quic_input_data_tail; + size_t quic_next_record_start; const SSL_QUIC_METHOD *quic_method; + uint8_t *quic_early_data_context; + size_t quic_early_data_context_len; #endif /* * Parsed form of the ClientHello, kept around across client_hello_cb @@ -1601,6 +1635,20 @@ struct ssl_st { * without sm2 cert at server. This tag set to 0 default */ int enable_sm_tls13_strict; +#endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + int enable_verify_peer_by_dc; + int enable_sign_by_dc; + /* + * delegated_credential_tag is used to illustrate whether client/server has send + * a delegated_credential extension or used it for handshake, If the client receives + * a delegated credential without sending this extension, then the client MUST abort + * with an "unexpected_message" alert. + */ + int delegated_credential_tag; + + const struct sigalg_lookup_st **shared_dc_sigalgs; + size_t shared_dc_sigalgslen; #endif /* * Signature algorithms shared by client and server: cached because these @@ -1775,6 +1823,10 @@ typedef struct ssl3_state_st { /* Size of above arrays */ size_t peer_sigalgslen; size_t peer_cert_sigalgslen; +# ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + uint16_t *peer_dc_sigalgs; + size_t peer_dc_sigalgslen; +# endif /* Sigalg peer actually uses */ const SIGALG_LOOKUP *peer_sigalg; /* @@ -1962,6 +2014,15 @@ typedef struct dtls1_state_st { # define NAMED_CURVE_TYPE 3 # endif /* OPENSSL_NO_EC */ +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +struct dc_pkey_st { + DELEGATED_CREDENTIAL *dc; + EVP_PKEY *privatekey; + + CERT_PKEY *parent; +}; +#endif + struct cert_pkey_st { X509 *x509; EVP_PKEY *privatekey; @@ -1976,6 +2037,10 @@ struct cert_pkey_st { */ unsigned char *serverinfo; size_t serverinfo_length; +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + DELEGATED_CREDENTIAL *dc; + EVP_PKEY *dc_privatekey; +#endif }; /* Retrieve Suite B flags */ # define tls1_suiteb(s) (s->cert->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS) @@ -2041,6 +2106,9 @@ typedef struct cert_st { /* Flags related to certificates */ uint32_t cert_flags; CERT_PKEY pkeys[SSL_PKEY_NUM]; +# ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + DC_PKEY dc_pkeys[SSL_PKEY_NUM]; +# endif /* Custom certificate types sent in certificate request message. */ uint8_t *ctype; size_t ctype_len; @@ -2392,6 +2460,17 @@ struct openssl_ssl_test_functions { const char *ssl_protocol_to_string(int version); +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +static ossl_inline int ssl_has_dc(const SSL *s, int idx) +{ + if (idx < 0 || idx >= SSL_PKEY_NUM) + return 0; + + return s->cert->dc_pkeys[idx].dc != NULL + && s->cert->dc_pkeys[idx].privatekey != NULL; +} +#endif + /* Returns true if certificate and private key for 'idx' are present */ static ossl_inline int ssl_has_cert(const SSL *s, int idx) { @@ -2742,7 +2821,10 @@ __owur int tls1_save_sigalgs(SSL *s, PACKET *pkt, int cert); __owur int tls1_process_sigalgs(SSL *s); __owur int tls1_set_peer_legacy_sigalg(SSL *s, const EVP_PKEY *pkey); __owur int tls1_lookup_md(const SIGALG_LOOKUP *lu, const EVP_MD **pmd); +__owur int tls1_get_sig_and_hash(uint16_t sigalg, int *psig, int *phash); __owur size_t tls12_get_psigalgs(SSL *s, int sent, const uint16_t **psigs); +__owur int tls1_lookup_sigalg_by_pkey_and_hash(EVP_PKEY *pkey, int hash, + int is_tls13, uint16_t *psigalg); # ifndef OPENSSL_NO_EC __owur int tls_check_sigalg_curve(const SSL *s, int curve); # endif @@ -2830,6 +2912,12 @@ void ssl_comp_free_compression_methods_int(void); /* ssl_mcnf.c */ void ssl_ctx_system_config(SSL_CTX *ctx); +# ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +int tls1_set_shared_dc_sigalgs(SSL *s); +# endif + +__owur const SIGALG_LOOKUP *tls1_lookup_sigalg(uint16_t sigalg); + # else /* OPENSSL_UNIT_TEST */ # define ssl_init_wbio_buffer SSL_test_functions()->p_ssl_init_wbio_buffer diff --git a/ssl/ssl_quic.c b/ssl/ssl_quic.c index 5e2147758..0bd9b28a1 100644 --- a/ssl/ssl_quic.c +++ b/ssl/ssl_quic.c @@ -39,8 +39,45 @@ void SSL_get_peer_quic_transport_params(const SSL *ssl, const uint8_t **out_params, size_t *out_params_len) { - *out_params = ssl->ext.peer_quic_transport_params; - *out_params_len = ssl->ext.peer_quic_transport_params_len; + if (ssl->ext.peer_quic_transport_params_len) { + *out_params = ssl->ext.peer_quic_transport_params; + *out_params_len = ssl->ext.peer_quic_transport_params_len; + } else { + *out_params = ssl->ext.peer_quic_transport_params_draft; + *out_params_len = ssl->ext.peer_quic_transport_params_draft_len; + } +} + +/* Returns the negotiated version, or -1 on error */ +int SSL_get_peer_quic_transport_version(const SSL *ssl) +{ + if (ssl->ext.peer_quic_transport_params_len != 0 + && ssl->ext.peer_quic_transport_params_draft_len != 0) + return -1; + if (ssl->ext.peer_quic_transport_params_len != 0) + return TLSEXT_TYPE_quic_transport_parameters; + if (ssl->ext.peer_quic_transport_params_draft_len != 0) + return TLSEXT_TYPE_quic_transport_parameters_draft; + + return -1; +} + +void SSL_set_quic_use_legacy_codepoint(SSL *ssl, int use_legacy) +{ + if (use_legacy) + ssl->quic_transport_version = TLSEXT_TYPE_quic_transport_parameters_draft; + else + ssl->quic_transport_version = TLSEXT_TYPE_quic_transport_parameters; +} + +void SSL_set_quic_transport_version(SSL *ssl, int version) +{ + ssl->quic_transport_version = version; +} + +int SSL_get_quic_transport_version(const SSL *ssl) +{ + return ssl->quic_transport_version; } size_t SSL_quic_max_handshake_flight_len(const SSL *ssl, OSSL_ENCRYPTION_LEVEL level) @@ -95,7 +132,7 @@ OSSL_ENCRYPTION_LEVEL SSL_quic_write_level(const SSL *ssl) int SSL_provide_quic_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL level, const uint8_t *data, size_t len) { - size_t l; + size_t l, offset; if (!SSL_IS_QUIC(ssl)) { SSLerr(SSL_F_SSL_PROVIDE_QUIC_DATA, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); @@ -104,58 +141,80 @@ int SSL_provide_quic_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL level, /* Level can be different than the current read, but not less */ if (level < ssl->quic_read_level - || (ssl->quic_input_data_tail != NULL && level < ssl->quic_input_data_tail->level)) { + || (ssl->quic_input_data_tail != NULL && level < ssl->quic_input_data_tail->level) + || level < ssl->quic_latest_level_received) { SSLerr(SSL_F_SSL_PROVIDE_QUIC_DATA, SSL_R_WRONG_ENCRYPTION_LEVEL_RECEIVED); return 0; } - /* Split the QUIC messages up, if necessary */ - while (len > 0) { - QUIC_DATA *qd; - const uint8_t *p = data + 1; - - /* Check for an incomplete block */ - qd = ssl->quic_input_data_tail; - if (qd != NULL) { - l = qd->length - qd->offset; - if (l != 0) { - /* we still need to copy `l` bytes into the last data block */ - if (l > len) - l = len; - memcpy((char*)(qd+1) + qd->offset, data, l); - qd->offset += l; - len -= l; - data += l; - continue; - } + if (len == 0) + return 1; + + if (ssl->quic_buf == NULL) { + BUF_MEM *buf; + if ((buf = BUF_MEM_new()) == NULL) { + SSLerr(SSL_F_SSL_PROVIDE_QUIC_DATA, ERR_R_INTERNAL_ERROR); + return 0; + } + if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { + SSLerr(SSL_F_SSL_PROVIDE_QUIC_DATA, ERR_R_INTERNAL_ERROR); + BUF_MEM_free(buf); + return 0; } + ssl->quic_buf = buf; + /* We preallocated storage, but there's still no *data*. */ + ssl->quic_buf->length = 0; + buf = NULL; + } + + /* A TLS message must not cross an encryption level boundary */ + if (ssl->quic_buf->length != ssl->quic_next_record_start + && level != ssl->quic_latest_level_received) { + SSLerr(SSL_F_SSL_PROVIDE_QUIC_DATA, + SSL_R_WRONG_ENCRYPTION_LEVEL_RECEIVED); + return 0; + } + ssl->quic_latest_level_received = level; + + offset = ssl->quic_buf->length; + if (!BUF_MEM_grow(ssl->quic_buf, offset + len)) { + SSLerr(SSL_F_SSL_PROVIDE_QUIC_DATA, ERR_R_INTERNAL_ERROR); + return 0; + } + memcpy(ssl->quic_buf->data + offset, data, len); + /* Split on handshake message boundaries */ + while (ssl->quic_buf->length > ssl->quic_next_record_start + + SSL3_HM_HEADER_LENGTH) { + QUIC_DATA *qd; + const uint8_t *p; + + /* TLS Handshake message header has 1-byte type and 3-byte length */ + p = (const uint8_t *)ssl->quic_buf->data + + ssl->quic_next_record_start + 1; n2l3(p, l); l += SSL3_HM_HEADER_LENGTH; + /* Don't allocate a QUIC_DATA if we don't have a full record */ + if (l > ssl->quic_buf->length - ssl->quic_next_record_start) + break; - qd = OPENSSL_zalloc(sizeof(QUIC_DATA) + l); + qd = OPENSSL_zalloc(sizeof(*qd)); if (qd == NULL) { - SSLerr(SSL_F_SSL_PROVIDE_QUIC_DATA, SSL_R_INTERNAL_ERROR); + SSLerr(SSL_F_SSL_PROVIDE_QUIC_DATA, ERR_R_INTERNAL_ERROR); return 0; } qd->next = NULL; qd->length = l; + qd->start = ssl->quic_next_record_start; qd->level = level; - /* partial data received? */ - if (l > len) - l = len; - qd->offset = l; - memcpy((void*)(qd + 1), data, l); if (ssl->quic_input_data_tail != NULL) ssl->quic_input_data_tail->next = qd; else ssl->quic_input_data_head = qd; ssl->quic_input_data_tail = qd; - - data += l; - len -= l; + ssl->quic_next_record_start += l; } return 1; @@ -163,15 +222,8 @@ int SSL_provide_quic_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL level, int SSL_CTX_set_quic_method(SSL_CTX *ctx, const SSL_QUIC_METHOD *quic_method) { - switch (ctx->method->version) { - case DTLS1_VERSION: - case DTLS1_2_VERSION: - case DTLS_ANY_VERSION: - case DTLS1_BAD_VER: + if (ctx->method->version != TLS_ANY_VERSION) return 0; - default: - break; - } ctx->quic_method = quic_method; ctx->options &= ~SSL_OP_ENABLE_MIDDLEBOX_COMPAT; return 1; @@ -179,81 +231,94 @@ int SSL_CTX_set_quic_method(SSL_CTX *ctx, const SSL_QUIC_METHOD *quic_method) int SSL_set_quic_method(SSL *ssl, const SSL_QUIC_METHOD *quic_method) { - switch (ssl->method->version) { - case DTLS1_VERSION: - case DTLS1_2_VERSION: - case DTLS_ANY_VERSION: - case DTLS1_BAD_VER: + if (ssl->method->version != TLS_ANY_VERSION) return 0; - default: - break; - } ssl->quic_method = quic_method; ssl->options &= ~SSL_OP_ENABLE_MIDDLEBOX_COMPAT; return 1; } -int quic_set_encryption_secrets(SSL *ssl, OSSL_ENCRYPTION_LEVEL level) +int quic_set_encryption_secrets(SSL *s, OSSL_ENCRYPTION_LEVEL level) { uint8_t *c2s_secret = NULL; uint8_t *s2c_secret = NULL; + uint8_t *read_secret = NULL; + uint8_t *write_secret = NULL; size_t len; const EVP_MD *md; + const SSL_CIPHER *c = NULL; - if (!SSL_IS_QUIC(ssl)) + if (!SSL_IS_QUIC(s)) return 1; /* secrets from the POV of the client */ switch (level) { case ssl_encryption_early_data: - c2s_secret = ssl->client_early_traffic_secret; + c2s_secret = s->client_early_traffic_secret; break; case ssl_encryption_handshake: - c2s_secret = ssl->client_hand_traffic_secret; - s2c_secret = ssl->server_hand_traffic_secret; + c2s_secret = s->client_hand_traffic_secret; + s2c_secret = s->server_hand_traffic_secret; break; case ssl_encryption_application: - c2s_secret = ssl->client_app_traffic_secret; - s2c_secret = ssl->server_app_traffic_secret; + c2s_secret = s->client_app_traffic_secret; + s2c_secret = s->server_app_traffic_secret; break; default: return 1; } - md = ssl_handshake_md(ssl); - if (md == NULL) { - /* May not have selected cipher, yet */ - const SSL_CIPHER *c = NULL; + c = SSL_SESSION_get0_cipher(s->session); + + if (s->early_data_state == SSL_EARLY_DATA_CONNECTING + && s->max_early_data > 0 && s->session->ext.max_early_data == 0) { + /* + * If we are attempting to send early data, and we've decided to + * actually do it but max_early_data in s->session is 0 then we + * must be using an external PSK. + */ + if (!ossl_assert(s->psksession != NULL + && s->max_early_data + == s->psksession->ext.max_early_data)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_QUIC_SET_ENCRYPTION_SECRETS, ERR_R_INTERNAL_ERROR); + return 0; + } + c = SSL_SESSION_get0_cipher(s->psksession); + } - if (ssl->session != NULL) - c = SSL_SESSION_get0_cipher(ssl->session); - else if (ssl->psksession != NULL) - c = SSL_SESSION_get0_cipher(ssl->psksession); + if (c == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_SET_ENCRYPTION_SECRETS, + ERR_R_INTERNAL_ERROR); + return 0; + } - if (c != NULL) - md = SSL_CIPHER_get_handshake_digest(c); + md = ssl_handshake_md(s); + if (md == NULL) { + md = SSL_CIPHER_get_handshake_digest(c); } if ((len = EVP_MD_size(md)) <= 0) { - SSLfatal(ssl, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_SET_ENCRYPTION_SECRETS, + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_SET_ENCRYPTION_SECRETS, ERR_R_INTERNAL_ERROR); return 0; } - if (ssl->server) { - if (!ssl->quic_method->set_encryption_secrets(ssl, level, c2s_secret, - s2c_secret, len)) { - SSLfatal(ssl, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_SET_ENCRYPTION_SECRETS, - ERR_R_INTERNAL_ERROR); - return 0; - } - } else { - if (!ssl->quic_method->set_encryption_secrets(ssl, level, s2c_secret, - c2s_secret, len)) { - SSLfatal(ssl, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_SET_ENCRYPTION_SECRETS, - ERR_R_INTERNAL_ERROR); - return 0; - } + read_secret = s->server ? c2s_secret : s2c_secret; + write_secret = s->server ? s2c_secret : c2s_secret; + + if (read_secret && + !s->quic_method->set_read_secret(s, level, c, read_secret, len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_SET_ENCRYPTION_SECRETS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (write_secret && + !s->quic_method->set_write_secret(s, level, c, write_secret, len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_SET_ENCRYPTION_SECRETS, + ERR_R_INTERNAL_ERROR); + return 0; } return 1; @@ -268,16 +333,24 @@ int SSL_process_quic_post_handshake(SSL *ssl) return 0; } - ossl_statem_set_in_init(ssl, 1); - ret = ssl->handshake_func(ssl); - ossl_statem_set_in_init(ssl, 0); - - if (ret <= 0) - return 0; + /* if there is no data, return success as BoringSSL */ + while (ssl->quic_input_data_head != NULL) { + /* + * This is always safe (we are sure to be at a record boundary) because + * SSL_read()/SSL_write() are never used for QUIC connections -- the + * application data is handled at the QUIC layer instead. + */ + ossl_statem_set_in_init(ssl, 1); + ret = ssl->handshake_func(ssl); + ossl_statem_set_in_init(ssl, 0); + + if (ret <= 0) + return 0; + } return 1; } -int SSL_is_quic(SSL* ssl) +int SSL_is_quic(SSL *ssl) { return SSL_IS_QUIC(ssl); } @@ -287,16 +360,42 @@ void SSL_set_quic_early_data_enabled(SSL *ssl, int enabled) if (!SSL_is_quic(ssl) || !SSL_in_before(ssl)) return; + if (!enabled) { + ssl->early_data_state = SSL_EARLY_DATA_NONE; + return; + } + if (ssl->server) { ssl->early_data_state = SSL_EARLY_DATA_ACCEPTING; return; } - if (((ssl->session == NULL || ssl->session->ext.max_early_data == 0) - && (ssl->psk_use_session_cb == NULL))) + if ((ssl->session == NULL || ssl->session->ext.max_early_data == 0) + && ssl->psk_use_session_cb == NULL) return; ssl->early_data_state = SSL_EARLY_DATA_CONNECTING; } +int SSL_set_quic_early_data_context(SSL *ssl, const uint8_t *context, + size_t context_len) + +{ + uint8_t *tmp; + + if (context == NULL || context_len == 0) { + tmp = NULL; + context_len = 0; + } else { + tmp = OPENSSL_memdup(context, context_len); + if (tmp == NULL) + return 0; + } + + OPENSSL_free(ssl->quic_early_data_context); + ssl->quic_early_data_context = tmp; + ssl->quic_early_data_context_len = context_len; + return 1; +} + #endif diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c index cd3f79724..d3fd136c4 100644 --- a/ssl/ssl_rsa.c +++ b/ssl/ssl_rsa.c @@ -343,7 +343,6 @@ static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) return 0; } } - EVP_PKEY_free(c->pkeys[i].privatekey); EVP_PKEY_up_ref(pkey); c->pkeys[i].privatekey = pkey; @@ -1690,3 +1689,355 @@ int SSL_CTX_use_sign_certificate_file(SSL_CTX *ctx, const char *file, int type) } #endif + +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +static int ssl_set_dc(CERT *c, DELEGATED_CREDENTIAL *dc, int is_server) +{ + EVP_PKEY *pkey; + uint16_t sigalg; + int sig; + size_t sig_idx; + size_t i; + + sigalg = DC_get_signature_sign_algorithm(dc); + + if (!tls1_get_sig_and_hash(sigalg, &sig, NULL)) { + SSLerr(SSL_F_SSL_SET_DC, SSL_R_GET_SIG_AND_HASH_ERR); + return 0; + } + + if (!ssl_cert_lookup_by_nid(sig, &sig_idx)) { + SSLerr(SSL_F_SSL_SET_DC, SSL_R_UNABLE_TO_LOOKUP_CERT); + return 0; + } + + if (c->pkeys[sig_idx].x509 == NULL) { + SSLerr(SSL_F_SSL_SET_DC, SSL_R_EE_CERT_NOT_FOUND); + return 0; + } + + if (!DC_check_valid(c->pkeys[sig_idx].x509 , dc)) { + SSLerr(SSL_F_SSL_SET_DC, SSL_R_CERTIFICATE_VERIFY_FAILED); + return 0; + } + + if (SSL_verify_delegated_credential_signature(c->pkeys[sig_idx].x509, dc, is_server) <= 0) { + SSLerr(SSL_F_SSL_SET_DC, SSL_R_FAILED_TO_VERIFY_DC_SIGNATURE); + return 0; + } + + pkey = DC_get0_publickey(dc); + if (pkey == NULL) { + SSLerr(SSL_F_SSL_SET_DC, SSL_R_X509_LIB); + return 0; + } + +# ifndef OPENSSL_NO_SM2 + if (EVP_PKEY_is_sm2(pkey)) { + if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) { + SSLerr(SSL_F_SSL_SET_DC, SSL_R_UNKNOWN_CERTIFICATE_TYPE); + return 0; + } + } +# endif + + if (ssl_cert_lookup_by_pkey(pkey, &i) == NULL) { + SSLerr(SSL_F_SSL_SET_DC, SSL_R_UNKNOWN_CERTIFICATE_TYPE); + return 0; + } +# ifndef OPENSSL_NO_EC + if (i == SSL_PKEY_ECC && !EC_KEY_can_sign(EVP_PKEY_get0_EC_KEY(pkey))) { + SSLerr(SSL_F_SSL_SET_DC, SSL_R_ECC_CERT_NOT_FOR_SIGNING); + return 0; + } +# endif + if (c->dc_pkeys[i].privatekey != NULL) { + /* + * The return code from EVP_PKEY_copy_parameters is deliberately + * ignored. Some EVP_PKEY types cannot do this. + */ + EVP_PKEY_copy_parameters(pkey, c->dc_pkeys[i].privatekey); + ERR_clear_error(); + +# ifndef OPENSSL_NO_RSA + /* + * Don't check the public/private key, this is mostly for smart + * cards. + */ + if (EVP_PKEY_id(c->dc_pkeys[i].privatekey) == EVP_PKEY_RSA + && RSA_flags(EVP_PKEY_get0_RSA(c->dc_pkeys[i].privatekey)) & + RSA_METHOD_FLAG_NO_CHECK) ; + else +# endif /* OPENSSL_NO_RSA */ + if (!DC_check_private_key(dc, c->dc_pkeys[i].privatekey)) { + /* + * don't fail for a dc/key mismatch, just free current private + * key (when switching to a different dc & key, first this + * function should be used, then ssl_set_pkey + */ + EVP_PKEY_free(c->dc_pkeys[i].privatekey); + c->dc_pkeys[i].privatekey = NULL; + /* clear error queue */ + ERR_clear_error(); + } + } + + DC_free(c->dc_pkeys[i].dc); + DC_up_ref(dc); + c->dc_pkeys[i].dc = dc; + c->dc_pkeys[i].parent = &c->pkeys[sig_idx]; + + c->pkeys[sig_idx].dc = dc; + c->pkeys[sig_idx].dc_privatekey = c->dc_pkeys[i].privatekey; + + return 1; +} + +static int ssl_set_dc_pkey(CERT *c, EVP_PKEY *pkey) +{ + size_t i; + +# ifndef OPENSSL_NO_SM2 + if (EVP_PKEY_is_sm2(pkey)) { + if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) { + SSLerr(SSL_F_SSL_SET_DC_PKEY, SSL_R_UNKNOWN_CERTIFICATE_TYPE); + return 0; + } + } +# endif + + if (ssl_cert_lookup_by_pkey(pkey, &i) == NULL) { + SSLerr(SSL_F_SSL_SET_DC_PKEY, SSL_R_UNKNOWN_CERTIFICATE_TYPE); + return 0; + } + + if (c->dc_pkeys[i].dc != NULL) { + EVP_PKEY *pktmp; + pktmp = DC_get0_publickey(c->dc_pkeys[i].dc); + if (pktmp == NULL) { + SSLerr(SSL_F_SSL_SET_DC_PKEY, ERR_R_MALLOC_FAILURE); + return 0; + } + /* + * The return code from EVP_PKEY_copy_parameters is deliberately + * ignored. Some EVP_PKEY types cannot do this. + */ + EVP_PKEY_copy_parameters(pktmp, pkey); + ERR_clear_error(); + +# ifndef OPENSSL_NO_RSA + /* + * Don't check the public/private key, this is mostly for smart + * cards. + */ + if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA + && RSA_flags(EVP_PKEY_get0_RSA(pkey)) & RSA_METHOD_FLAG_NO_CHECK) ; + else +# endif + if (!DC_check_private_key(c->dc_pkeys[i].dc, pkey)) { + DC_free(c->dc_pkeys[i].dc); + c->dc_pkeys[i].dc = NULL; + return 0; + } + } + EVP_PKEY_free(c->dc_pkeys[i].privatekey); + EVP_PKEY_up_ref(pkey); + c->dc_pkeys[i].privatekey = pkey; + + if (c->dc_pkeys[i].parent) { + c->dc_pkeys[i].parent->dc = c->dc_pkeys[i].dc; + c->dc_pkeys[i].parent->dc_privatekey = pkey; + } + + return 1; +} + +int SSL_use_dc(SSL *ssl, DELEGATED_CREDENTIAL *dc) +{ + if (ssl == NULL || dc == NULL) { + SSLerr(SSL_F_SSL_USE_DC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + return ssl_set_dc(ssl->cert, dc, SSL_is_server(ssl)); +} + +int SSL_use_dc_file(SSL *ssl, const char *file, int type) +{ + DELEGATED_CREDENTIAL *dc = NULL; + int ret = 0; + + if (ssl == NULL || file == NULL) { + SSLerr(SSL_F_SSL_USE_DC_FILE, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (type == DC_FILETYPE_RAW) { + dc = DC_load_from_file(file); + } else { + SSLerr(SSL_F_SSL_USE_DC_FILE, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (dc == NULL) { + SSLerr(SSL_F_SSL_USE_DC_FILE, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + ret = ssl_set_dc(ssl->cert, dc, SSL_is_server(ssl)); +end: + DC_free(dc); + return ret; +} + +int SSL_CTX_use_dc(SSL_CTX *ctx, DELEGATED_CREDENTIAL *dc) +{ + int is_server; + + if (ctx == NULL || dc == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_DC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (ctx->method == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_DC, + SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION); + return 0; + } + + is_server = (ctx->method->ssl_accept == ssl_undefined_function) ? 0 : 1; + + return ssl_set_dc(ctx->cert, dc, is_server); +} + +int SSL_CTX_use_dc_file(SSL_CTX *ctx, const char *file, int type) +{ + int ret = 0; + int is_server; + DELEGATED_CREDENTIAL *dc = NULL; + + if (ctx == NULL || file == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_DC_FILE, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (type == DC_FILETYPE_RAW) { + dc = DC_load_from_file(file); + } else { + SSLerr(SSL_F_SSL_CTX_USE_DC_FILE, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (dc == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_DC_FILE, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + is_server = (ctx->method->ssl_accept == ssl_undefined_function) ? 0 : 1; + + ret = ssl_set_dc(ctx->cert, dc, is_server); +end: + DC_free(dc); + return ret; +} + +int SSL_use_dc_PrivateKey(SSL *ssl, EVP_PKEY *pkey) +{ + if (ssl == NULL || pkey == NULL) { + SSLerr(SSL_F_SSL_USE_DC_PRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + return ssl_set_dc_pkey(ssl->cert, pkey); +} + +int SSL_use_dc_PrivateKey_file(SSL *ssl, const char *file, int type) +{ + BIO *in; + int j, ret = 0; + EVP_PKEY *pkey = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + SSLerr(SSL_F_SSL_USE_DC_PRIVATEKEY_FILE, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + SSLerr(SSL_F_SSL_USE_DC_PRIVATEKEY_FILE, ERR_R_SYS_LIB); + goto end; + } + if (type == SSL_FILETYPE_PEM) { + j = ERR_R_PEM_LIB; + pkey = PEM_read_bio_PrivateKey(in, NULL, + ssl->default_passwd_callback, + ssl->default_passwd_callback_userdata); + } else if (type == SSL_FILETYPE_ASN1) { + j = ERR_R_ASN1_LIB; + pkey = d2i_PrivateKey_bio(in, NULL); + } else { + SSLerr(SSL_F_SSL_USE_DC_PRIVATEKEY_FILE, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + if (pkey == NULL) { + SSLerr(SSL_F_SSL_USE_DC_PRIVATEKEY_FILE, j); + goto end; + } + + ret = ssl_set_dc_pkey(ssl->cert, pkey); + EVP_PKEY_free(pkey); +end: + BIO_free(in); + return ret; +} + +int SSL_CTX_use_dc_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) +{ + if (ctx == NULL || pkey == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_DC_PRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + return ssl_set_dc_pkey(ctx->cert, pkey); +} + +int SSL_CTX_use_dc_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) +{ + BIO *in; + int j, ret = 0; + EVP_PKEY *pkey = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_DC_PRIVATEKEY_FILE, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + SSLerr(SSL_F_SSL_CTX_USE_DC_PRIVATEKEY_FILE, ERR_R_SYS_LIB); + goto end; + } + if (type == SSL_FILETYPE_PEM) { + j = ERR_R_PEM_LIB; + pkey = PEM_read_bio_PrivateKey(in, NULL, + ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata); + } else if (type == SSL_FILETYPE_ASN1) { + j = ERR_R_ASN1_LIB; + pkey = d2i_PrivateKey_bio(in, NULL); + } else { + SSLerr(SSL_F_SSL_CTX_USE_DC_PRIVATEKEY_FILE, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + if (pkey == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_DC_PRIVATEKEY_FILE, j); + goto end; + } + + ret = ssl_set_dc_pkey(ctx->cert, pkey); + EVP_PKEY_free(pkey); +end: + BIO_free(in); + return ret; +} +#endif diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index 4bbf59822..385f62c18 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c @@ -136,6 +136,10 @@ SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket) dest->ticket_appdata = NULL; memset(&dest->ex_data, 0, sizeof(dest->ex_data)); +#ifndef OPENSSL_NO_QUIC + dest->quic_early_data_context = NULL; + dest->quic_early_data_context_len = 0; +#endif /* We deliberately don't copy the prev and next pointers */ dest->prev = NULL; dest->next = NULL; @@ -149,6 +153,14 @@ SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket) if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, dest, &dest->ex_data)) goto err; +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + if (src->peer_dc != NULL) { + if (!DC_up_ref(src->peer_dc)) + goto err; + dest->peer_dc = src->peer_dc; + } +#endif + if (src->peer != NULL) { if (!X509_up_ref(src->peer)) goto err; @@ -229,6 +241,18 @@ SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket) goto err; } +#ifndef OPENSSL_NO_QUIC + if (src->quic_early_data_context) { + dest->quic_early_data_context = + OPENSSL_memdup(src->quic_early_data_context, + src->quic_early_data_context_len); + if (dest->quic_early_data_context == NULL) + goto err; + + dest->quic_early_data_context_len = src->quic_early_data_context_len; + } +#endif + return dest; err: SSLerr(SSL_F_SSL_SESSION_DUP, ERR_R_MALLOC_FAILURE); @@ -425,7 +449,23 @@ int ssl_get_new_session(SSL *s, int session) s->session = ss; ss->ssl_version = s->version; ss->verify_result = X509_V_OK; +#ifndef OPENSSL_NO_QUIC + ss->is_quic = (s->quic_method != NULL); + + if (s->quic_early_data_context) { + ss->quic_early_data_context = + OPENSSL_memdup(s->quic_early_data_context, + s->quic_early_data_context_len); + if (ss->quic_early_data_context == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_NEW_SESSION, + ERR_R_MALLOC_FAILURE); + SSL_SESSION_free(ss); + return 0; + } + ss->quic_early_data_context_len = s->quic_early_data_context_len; + } +#endif /* If client supports extended master secret set it in session */ if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) ss->flags |= SSL_SESS_FLAG_EXTMS; @@ -829,6 +869,9 @@ void SSL_SESSION_free(SSL_SESSION *ss) #if (!defined OPENSSL_NO_NTLS) && (!defined OPENSSL_NO_SM2) \ && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) X509_free(ss->peer_extra); +#endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + DC_free(ss->peer_dc); #endif sk_X509_pop_free(ss->peer_chain, X509_free); OPENSSL_free(ss->ext.hostname); @@ -839,6 +882,9 @@ void SSL_SESSION_free(SSL_SESSION *ss) #endif #ifndef OPENSSL_NO_SRP OPENSSL_free(ss->srp_username); +#endif +#ifndef OPENSSL_NO_QUIC + OPENSSL_free(ss->quic_early_data_context); #endif OPENSSL_free(ss->ext.alpn_selected); OPENSSL_free(ss->ticket_appdata); diff --git a/ssl/ssl_txt.c b/ssl/ssl_txt.c index 457bc8b3c..0139e80dc 100644 --- a/ssl/ssl_txt.c +++ b/ssl/ssl_txt.c @@ -155,6 +155,18 @@ int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x) x->ext.max_early_data) <= 0) goto err; } +#ifndef OPENSSL_NO_QUIC + if (BIO_printf(bp, " QUIC: %s\n", x->is_quic ? "yes" : "no") <= 0) + goto err; + + if (x->quic_early_data_context) { + if (BIO_puts(bp, " QUIC early data ctx:\n") <= 0) + goto err; + if (BIO_dump_indent(bp, (const char *)x->quic_early_data_context, + (int)x->quic_early_data_context_len, 4) <= 0) + goto err; + } +#endif return 1; err: diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c index be09afbe7..b0afed407 100644 --- a/ssl/statem/extensions.c +++ b/ssl/statem/extensions.c @@ -58,9 +58,9 @@ static int final_maxfragmentlen(SSL *s, unsigned int context, int sent); static int init_post_handshake_auth(SSL *s, unsigned int context); #ifndef OPENSSL_NO_QUIC static int init_quic_transport_params(SSL *s, unsigned int context); +static int final_quic_transport_params_draft(SSL *s, unsigned int context, int sent); static int final_quic_transport_params(SSL *s, unsigned int context, int sent); #endif - /* Structure to define a built-in extension */ typedef struct extensions_definition_st { /* The defined type for the extension */ @@ -278,6 +278,19 @@ static const EXTENSION_DEFINITION ext_defs[] = { }, #else INVALID_EXTENSION, +#endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + { + TLSEXT_TYPE_delegated_credential, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST + | SSL_EXT_TLS1_3_ONLY | SSL_EXT_TLS1_3_CERTIFICATE, + NULL, + tls_parse_ctos_delegated_credential, tls_parse_stoc_delegated_credential, + tls_construct_stoc_delegated_credential, tls_construct_ctos_delegated_credential, + NULL + }, +#else + INVALID_EXTENSION, #endif { TLSEXT_TYPE_extended_master_secret, @@ -340,6 +353,8 @@ static const EXTENSION_DEFINITION ext_defs[] = { tls_construct_stoc_key_share, tls_construct_ctos_key_share, final_key_share }, +#else + INVALID_EXTENSION, #endif { /* Must be after key_share */ @@ -378,6 +393,15 @@ static const EXTENSION_DEFINITION ext_defs[] = { tls_construct_certificate_authorities, NULL, }, #ifndef OPENSSL_NO_QUIC + { + TLSEXT_TYPE_quic_transport_parameters_draft, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS + | SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY, + init_quic_transport_params, + tls_parse_ctos_quic_transport_params_draft, tls_parse_stoc_quic_transport_params_draft, + tls_construct_stoc_quic_transport_params_draft, tls_construct_ctos_quic_transport_params_draft, + final_quic_transport_params_draft, + }, { TLSEXT_TYPE_quic_transport_parameters, SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS @@ -389,6 +413,7 @@ static const EXTENSION_DEFINITION ext_defs[] = { }, #else INVALID_EXTENSION, + INVALID_EXTENSION, #endif { /* Must be immediately before pre_shared_key */ @@ -1153,6 +1178,7 @@ static int init_sig_algs(SSL *s, unsigned int context) /* Clear any signature algorithms extension received */ OPENSSL_free(s->s3->tmp.peer_sigalgs); s->s3->tmp.peer_sigalgs = NULL; + s->s3->tmp.peer_sigalgslen = 0; return 1; } @@ -1725,8 +1751,186 @@ static int init_quic_transport_params(SSL *s, unsigned int context) return 1; } +static int final_quic_transport_params_draft(SSL *s, unsigned int context, + int sent) +{ + return 1; +} + static int final_quic_transport_params(SSL *s, unsigned int context, int sent) { + /* called after final_quic_transport_params_draft */ + if (SSL_IS_QUIC(s)) { + if (s->ext.peer_quic_transport_params_len == 0 + && s->ext.peer_quic_transport_params_draft_len == 0) { + SSLfatal(s, SSL_AD_MISSING_EXTENSION, + SSL_F_FINAL_QUIC_TRANSPORT_PARAMS, + SSL_R_MISSING_QUIC_TRANSPORT_PARAMETERS_EXTENSION); + return 0; + } + /* if we got both, discard the one we can't use */ + if (s->ext.peer_quic_transport_params_len != 0 + && s->ext.peer_quic_transport_params_draft_len != 0) { + if (s->quic_transport_version == TLSEXT_TYPE_quic_transport_parameters_draft) { + OPENSSL_free(s->ext.peer_quic_transport_params); + s->ext.peer_quic_transport_params = NULL; + s->ext.peer_quic_transport_params_len = 0; + } else { + OPENSSL_free(s->ext.peer_quic_transport_params_draft); + s->ext.peer_quic_transport_params_draft = NULL; + s->ext.peer_quic_transport_params_draft_len = 0; + } + } + } + + return 1; +} +#endif + +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +int tls_parse_dc_from_extension(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (!s->enable_verify_peer_by_dc) + return 1; + /* + * If the client receives a delegated credential without sending this extension, then the + * client MUST abort with an "unexpected_message" alert. + */ + if (!(s->delegated_credential_tag & DC_REQ_HAS_BEEN_SEND_TO_PEER)) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PARSE_DC_FROM_EXTENSION, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (s->session == NULL) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PARSE_DC_FROM_EXTENSION, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (PACKET_remaining(pkt) <= 0) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PARSE_DC_FROM_EXTENSION, + ERR_R_INTERNAL_ERROR); + return 0; + } + + s->session->peer_dc = DC_new_from_raw_byte(PACKET_data(pkt),PACKET_remaining(pkt)); + if (s->session->peer_dc == NULL) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PARSE_DC_FROM_EXTENSION, + ERR_R_INTERNAL_ERROR); + return 0; + } + + s->delegated_credential_tag |= DC_HAS_BEEN_USED_FOR_VERIFY_PEER; + return 1; +} + +int tls_process_dc_request(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + PACKET supported_sig_algs; + + if (!s->enable_sign_by_dc) + return 1; + + if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs) + || PACKET_remaining(&supported_sig_algs) == 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_DC_REQUEST, SSL_R_BAD_EXTENSION); + return 0; + } + + OPENSSL_free(s->s3->tmp.peer_dc_sigalgs); + s->s3->tmp.peer_dc_sigalgs = NULL; + s->s3->tmp.peer_dc_sigalgslen = 0; + + if (!tls1_save_u16(&supported_sig_algs, &s->s3->tmp.peer_dc_sigalgs, + &s->s3->tmp.peer_dc_sigalgslen)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_DC_REQUEST, SSL_R_BAD_EXTENSION); + return 0; + } + + if (!tls1_set_shared_dc_sigalgs(s)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_DC_REQUEST, ERR_R_INTERNAL_ERROR); + return 0; + } + return 1; } + +EXT_RETURN tls_construct_delegated_credential_raw(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (!s->enable_sign_by_dc) + return EXT_RETURN_NOT_SENT; + + if (s->delegated_credential_tag & DC_HAS_BEEN_USED_FOR_SIGN) { + DELEGATED_CREDENTIAL *dc; + unsigned char *dc_raw = NULL; + unsigned long dc_raw_len = 0; + + dc = s->s3->tmp.cert->dc; + if (dc == NULL) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_CONSTRUCT_DELEGATED_CREDENTIAL_RAW, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + dc_raw = DC_get0_raw_byte(dc); + if (dc_raw == NULL) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_CONSTRUCT_DELEGATED_CREDENTIAL_RAW, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + dc_raw_len = DC_get_raw_byte_len(dc); + if (dc_raw_len <= 0) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_CONSTRUCT_DELEGATED_CREDENTIAL_RAW, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_delegated_credential) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_memcpy(pkt, dc_raw, dc_raw_len) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_CONSTRUCT_DELEGATED_CREDENTIAL_RAW, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + return EXT_RETURN_SENT; + } + return EXT_RETURN_NOT_SENT; +} + +EXT_RETURN tls_construct_delegated_credential_request(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + size_t salglen; + const uint16_t *salg; + + if (!s->enable_verify_peer_by_dc) + return EXT_RETURN_NOT_SENT; + + salglen = tls12_get_psigalgs(s, 1, &salg); + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_delegated_credential) + /* Sub-packet for sig-algs extension */ + || !WPACKET_start_sub_packet_u16(pkt) + /* Sub-packet for the actual list */ + || !WPACKET_start_sub_packet_u16(pkt) + || !tls12_copy_sigalgs(s, pkt, salg, salglen) + || !WPACKET_close(pkt) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_CONSTRUCT_DELEGATED_CREDENTIAL_REQUEST, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + s->delegated_credential_tag |= DC_REQ_HAS_BEEN_SEND_TO_PEER; + return EXT_RETURN_SENT; +} + #endif diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c index a9f73f07d..3c42df9e9 100644 --- a/ssl/statem/extensions_clnt.c +++ b/ssl/statem/extensions_clnt.c @@ -491,6 +491,22 @@ EXT_RETURN tls_construct_ctos_sct(SSL *s, WPACKET *pkt, unsigned int context, } #endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +EXT_RETURN tls_construct_ctos_delegated_credential(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (s->statem.hand_state == TLS_ST_CW_CLNT_HELLO) { + return tls_construct_delegated_credential_request(s, pkt, context, x, chainidx); + } + + if (s->statem.hand_state == TLS_ST_CW_CERT) { + return tls_construct_delegated_credential_raw(s, pkt, context, x, chainidx); + } + + return EXT_RETURN_NOT_SENT; +} +#endif + EXT_RETURN tls_construct_ctos_ems(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { @@ -1215,13 +1231,34 @@ EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt, } #ifndef OPENSSL_NO_QUIC -/* SAME AS tls_construct_stoc_quic_transport_params() */ +EXT_RETURN tls_construct_ctos_quic_transport_params_draft(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + if (s->quic_transport_version == TLSEXT_TYPE_quic_transport_parameters + || s->ext.quic_transport_params == NULL + || s->ext.quic_transport_params_len == 0) { + return EXT_RETURN_NOT_SENT; + } + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_quic_transport_parameters_draft) + || !WPACKET_sub_memcpy_u16(pkt, s->ext.quic_transport_params, + s->ext.quic_transport_params_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_QUIC_TRANSPORT_PARAMS_DRAFT, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + EXT_RETURN tls_construct_ctos_quic_transport_params(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { - if (s->ext.quic_transport_params == NULL - || s->ext.quic_transport_params_len == 0) { + if (s->quic_transport_version == TLSEXT_TYPE_quic_transport_parameters_draft + || s->ext.quic_transport_params == NULL + || s->ext.quic_transport_params_len == 0) { return EXT_RETURN_NOT_SENT; } @@ -1549,6 +1586,20 @@ int tls_parse_stoc_sct(SSL *s, PACKET *pkt, unsigned int context, X509 *x, } #endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +int tls_parse_stoc_delegated_credential(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (s->statem.hand_state == TLS_ST_CR_CERT_REQ) { + return tls_process_dc_request(s, pkt, context, x, chainidx); + } + + if (s->statem.hand_state == TLS_ST_CR_CERT) { + return tls_parse_dc_from_extension(s, pkt, context, x, chainidx); + } + return 0; +} +#endif #ifndef OPENSSL_NO_NEXTPROTONEG /* @@ -1936,7 +1987,7 @@ int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context, #ifndef OPENSSL_NO_QUIC /* * QUIC server must send 0xFFFFFFFF or it's a PROTOCOL_VIOLATION - * per draft-ietf-quic-tls-24 S4.5 + * per draft-ietf-quic-tls-27 S4.5 */ if (s->quic_method != NULL && max_early_data != 0xFFFFFFFF) { SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_EARLY_DATA, @@ -2033,7 +2084,24 @@ int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, return 1; } #ifndef OPENSSL_NO_QUIC -/* SAME AS tls_parse_ctos_quic_transport_params() */ +int tls_parse_stoc_quic_transport_params_draft(SSL *s, PACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + OPENSSL_free(s->ext.peer_quic_transport_params_draft); + s->ext.peer_quic_transport_params_draft = NULL; + s->ext.peer_quic_transport_params_draft_len = 0; + + if (!PACKET_memdup(pkt, + &s->ext.peer_quic_transport_params_draft, + &s->ext.peer_quic_transport_params_draft_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_STOC_QUIC_TRANSPORT_PARAMS_DRAFT, ERR_R_INTERNAL_ERROR); + return 0; + } + return 1; +} + int tls_parse_stoc_quic_transport_params(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { @@ -2045,7 +2113,8 @@ int tls_parse_stoc_quic_transport_params(SSL *s, PACKET *pkt, unsigned int conte &s->ext.peer_quic_transport_params, &s->ext.peer_quic_transport_params_len)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, - SSL_F_TLS_PARSE_STOC_QUIC_TRANSPORT_PARAMS, ERR_R_INTERNAL_ERROR); + SSL_F_TLS_PARSE_STOC_QUIC_TRANSPORT_PARAMS, + ERR_R_INTERNAL_ERROR); return 0; } return 1; diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c index e63dde9f0..5b1b0cc7f 100644 --- a/ssl/statem/extensions_srvr.c +++ b/ssl/statem/extensions_srvr.c @@ -35,6 +35,10 @@ + SSL_MAX_SSL_SESSION_ID_LENGTH + 2 + 1 + 2 + 6 + 4 \ + MAX_COOKIE_SIZE) +#ifndef OPENSSL_NO_QUIC +static int quic_ticket_compatible(const SSL_SESSION *session, const SSL *s); +#endif + /* * Parse the client's renegotiation binding and abort if it's not right */ @@ -996,6 +1000,22 @@ int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context, } #endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +int tls_parse_ctos_delegated_credential(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (s->statem.hand_state == TLS_ST_SR_CLNT_HELLO) { + return tls_process_dc_request(s, pkt, context, x, chainidx); + } + + if (s->statem.hand_state == TLS_ST_SR_CERT) { + return tls_parse_dc_from_extension(s, pkt, context, x, chainidx); + } + return 0; + +} +#endif + int tls_parse_ctos_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { @@ -1163,7 +1183,7 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, if (sesstmp == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK, ERR_R_INTERNAL_ERROR); - return 0; + goto err; } SSL_SESSION_free(sess); sess = sesstmp; @@ -1245,6 +1265,12 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, */ s->ext.early_data_ok = 1; } +#ifndef OPENSSL_NO_QUIC + if (SSL_is_quic(s)) { + if (!quic_ticket_compatible(sess, s)) + s->ext.early_data_ok = 0; + } +#endif } md = ssl_md(sess->cipher->algorithm2); @@ -1316,7 +1342,41 @@ int tls_parse_ctos_post_handshake_auth(SSL *s, PACKET *pkt, unsigned int context } #ifndef OPENSSL_NO_QUIC -/* SAME AS tls_parse_stoc_quic_transport_params() */ +static int quic_ticket_compatible(const SSL_SESSION *session, const SSL *s) +{ + if (!session->is_quic) { + return 0; + } + + if (session->quic_early_data_context == NULL || + s->quic_early_data_context_len != + session->quic_early_data_context_len || + CRYPTO_memcmp(s->quic_early_data_context, + session->quic_early_data_context, + session->quic_early_data_context_len) != 0) { + return 0; + } + + return 1; +} + +int tls_parse_ctos_quic_transport_params_draft(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + OPENSSL_free(s->ext.peer_quic_transport_params_draft); + s->ext.peer_quic_transport_params_draft = NULL; + s->ext.peer_quic_transport_params_draft_len = 0; + + if (!PACKET_memdup(pkt, + &s->ext.peer_quic_transport_params_draft, + &s->ext.peer_quic_transport_params_draft_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_CTOS_QUIC_TRANSPORT_PARAMS_DRAFT, ERR_R_INTERNAL_ERROR); + return 0; + } + return 1; +} + int tls_parse_ctos_quic_transport_params(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { @@ -1328,7 +1388,8 @@ int tls_parse_ctos_quic_transport_params(SSL *s, PACKET *pkt, unsigned int conte &s->ext.peer_quic_transport_params, &s->ext.peer_quic_transport_params_len)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, - SSL_F_TLS_PARSE_CTOS_QUIC_TRANSPORT_PARAMS, ERR_R_INTERNAL_ERROR); + SSL_F_TLS_PARSE_CTOS_QUIC_TRANSPORT_PARAMS, + ERR_R_INTERNAL_ERROR); return 0; } return 1; @@ -1670,6 +1731,21 @@ EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context, return EXT_RETURN_SENT; } +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +EXT_RETURN tls_construct_stoc_delegated_credential(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (s->statem.hand_state == TLS_ST_SW_CERT) { + return tls_construct_delegated_credential_raw(s, pkt, context, x, chainidx); + } + + if (s->statem.hand_state == TLS_ST_SW_CERT_REQ) { + return tls_construct_delegated_credential_request(s, pkt, context, x, chainidx); + } + return EXT_RETURN_NOT_SENT; +} +#endif + EXT_RETURN tls_construct_stoc_ems(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { @@ -1964,9 +2040,20 @@ EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt, return EXT_RETURN_NOT_SENT; #ifndef OPENSSL_NO_QUIC - /* QUIC server must always send 0xFFFFFFFF, per draft-ietf-quic-tls-24 S4.5 */ - if (s->quic_method != NULL) - max_early_data = 0xFFFFFFFF; + if (s->quic_method != NULL) { + if (s->quic_early_data_context == NULL) { + /* if the server is to support 0-RTT in QUIC, + * SSL_set_quic_early_data_context must be called on the server + * with a non-empty context + */ + return EXT_RETURN_NOT_SENT; + } else { + /* QUIC does not use the max_early_data_size parameter and + * always sets it to a fixed value. See draft-ietf-quic-tls-22. + */ + max_early_data = 0xFFFFFFFF; + } + } #endif if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data) @@ -2014,13 +2101,37 @@ EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context, } #ifndef OPENSSL_NO_QUIC -/* SAME AS tls_construct_ctos_quic_transport_params() */ +EXT_RETURN tls_construct_stoc_quic_transport_params_draft(SSL *s, WPACKET *pkt, + unsigned int context, + X509 *x, + size_t chainidx) +{ + if (s->quic_transport_version == TLSEXT_TYPE_quic_transport_parameters + || s->ext.peer_quic_transport_params_draft_len == 0 + || s->ext.quic_transport_params == NULL + || s->ext.quic_transport_params_len == 0) { + return EXT_RETURN_NOT_SENT; + } + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_quic_transport_parameters_draft) + || !WPACKET_sub_memcpy_u16(pkt, s->ext.quic_transport_params, + s->ext.quic_transport_params_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_QUIC_TRANSPORT_PARAMS_DRAFT, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + EXT_RETURN tls_construct_stoc_quic_transport_params(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { - if (s->ext.quic_transport_params == NULL - || s->ext.quic_transport_params_len == 0) { + if (s->quic_transport_version == TLSEXT_TYPE_quic_transport_parameters_draft + || s->ext.peer_quic_transport_params_len == 0 + || s->ext.quic_transport_params == NULL + || s->ext.quic_transport_params_len == 0) { return EXT_RETURN_NOT_SENT; } @@ -2028,7 +2139,8 @@ EXT_RETURN tls_construct_stoc_quic_transport_params(SSL *s, WPACKET *pkt, || !WPACKET_sub_memcpy_u16(pkt, s->ext.quic_transport_params, s->ext.quic_transport_params_len)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, - SSL_F_TLS_CONSTRUCT_STOC_QUIC_TRANSPORT_PARAMS, ERR_R_INTERNAL_ERROR); + SSL_F_TLS_CONSTRUCT_STOC_QUIC_TRANSPORT_PARAMS, + ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c index 718584258..2f927d3cd 100644 --- a/ssl/statem/statem_clnt.c +++ b/ssl/statem/statem_clnt.c @@ -2010,6 +2010,36 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt) X509_up_ref(x); s->session->peer = x; s->session->verify_result = s->verify_result; +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + if (s->delegated_credential_tag & DC_HAS_BEEN_USED_FOR_VERIFY_PEER) { + if (!SSL_IS_TLS13(s)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, + SSL_R_UNKNOWN_CERTIFICATE_TYPE); + /* x will free later, so set x to NULL now */ + x = NULL; + goto err; + } + + if (!DC_check_valid(x, s->session->peer_dc)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, + SSL_R_CERTIFICATE_VERIFY_FAILED); + /* x will free later, so set x to NULL now */ + x = NULL; + goto err; + } + + if (SSL_verify_delegated_credential_signature(x, s->session->peer_dc, 1) <= 0) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, + SSL_R_CERTIFICATE_VERIFY_FAILED); + /* x will free later, so set x to NULL now */ + x = NULL; + goto err; + } + } +#endif x = NULL; /* Save the current hash state for when we receive the CertificateVerify */ diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c index 841a17084..915f5ddb6 100644 --- a/ssl/statem/statem_lib.c +++ b/ssl/statem/statem_lib.c @@ -42,17 +42,24 @@ int ssl3_do_write(SSL *s, int type) { int ret; size_t written = 0; + #ifndef OPENSSL_NO_QUIC - if (SSL_IS_QUIC(s) && type == SSL3_RT_HANDSHAKE) { - ret = s->quic_method->add_handshake_data(s, s->quic_write_level, - (const uint8_t*)&s->init_buf->data[s->init_off], - s->init_num); - if (!ret) { - ret = -1; - /* QUIC can't sent anything out sice the above failed */ - SSLerr(SSL_F_SSL3_DO_WRITE, SSL_R_INTERNAL_ERROR); + if (SSL_IS_QUIC(s)) { + if (type == SSL3_RT_HANDSHAKE) { + ret = s->quic_method->add_handshake_data(s, s->quic_write_level, + (const uint8_t*)&s->init_buf->data[s->init_off], + s->init_num); + if (!ret) { + ret = -1; + /* QUIC can't sent anything out sice the above failed */ + SSLerr(SSL_F_SSL3_DO_WRITE, ERR_R_INTERNAL_ERROR); + } else { + written = s->init_num; + } } else { - written = s->init_num; + /* QUIC doesn't use ChangeCipherSpec */ + ret = -1; + SSLerr(SSL_F_SSL3_DO_WRITE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); } } else #endif @@ -259,7 +266,12 @@ int tls_construct_cert_verify(SSL *s, WPACKET *pkt) goto err; } - pkey = s->s3->tmp.cert->privatekey; +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + if (s->delegated_credential_tag & DC_HAS_BEEN_USED_FOR_SIGN) + pkey = s->s3->tmp.cert->dc_privatekey; + else +#endif + pkey = s->s3->tmp.cert->privatekey; if (pkey == NULL || !tls1_lookup_md(lu, &md)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY, @@ -414,6 +426,16 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt) peer = s->session->peer; pkey = X509_get0_pubkey(peer); +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + if (s->delegated_credential_tag & DC_HAS_BEEN_USED_FOR_VERIFY_PEER) { + if (s->session->peer_dc == NULL) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_CERT_VERIFY, + ERR_R_INTERNAL_ERROR); + goto err; + } + pkey = DC_get0_publickey(s->session->peer_dc); + } +#endif if (pkey == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_INTERNAL_ERROR); @@ -448,10 +470,29 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt) /* SSLfatal() already called */ goto err; } +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + /* + * Verify that dc expected_cert_verify_algorithm matches the scheme + * indicated in the server's CertificateVerify message. + */ + if (s->delegated_credential_tag & DC_HAS_BEEN_USED_FOR_VERIFY_PEER) { + if (s->session->peer_dc == NULL) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_CERT_VERIFY, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (DC_get_expected_cert_verify_algorithm(s->session->peer_dc) != sigalg) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_CERT_VERIFY, + ERR_R_INTERNAL_ERROR); + goto err; + } + } +#endif } else if (!tls1_set_peer_legacy_sigalg(s, pkey)) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY, - ERR_R_INTERNAL_ERROR); - goto err; + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY, + ERR_R_INTERNAL_ERROR); + goto err; } if (!tls1_lookup_md(s->s3->tmp.peer_sigalg, &md)) { @@ -687,6 +728,14 @@ int tls_construct_finished(SSL *s, WPACKET *pkt) int tls_construct_key_update(SSL *s, WPACKET *pkt) { +#ifndef OPENSSL_NO_QUIC + if (SSL_IS_QUIC(s)) { + /* TLS KeyUpdate is not used for QUIC, so this is an error. */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_KEY_UPDATE, + ERR_R_INTERNAL_ERROR); + return 0; + } +#endif if (!WPACKET_put_bytes_u8(pkt, s->key_update)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_KEY_UPDATE, ERR_R_INTERNAL_ERROR); @@ -711,6 +760,14 @@ MSG_PROCESS_RETURN tls_process_key_update(SSL *s, PACKET *pkt) return MSG_PROCESS_ERROR; } +#ifndef OPENSSL_NO_QUIC + if (SSL_is_quic(s)) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_KEY_UPDATE, + SSL_R_UNEXPECTED_MESSAGE); + return MSG_PROCESS_ERROR; + } +#endif + if (!PACKET_get_1(pkt, &updatetype) || PACKET_remaining(pkt) != 0) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_UPDATE, @@ -1627,6 +1684,12 @@ static int is_tls13_capable(const SSL *s) default: break; } +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + if (s->enable_sign_by_dc + && ssl_has_dc(s, i)) { + /* nothing */ + } else +#endif if (!ssl_has_cert(s, i)) continue; #ifndef OPENSSL_NO_EC @@ -1637,7 +1700,13 @@ static int is_tls13_capable(const SSL *s) * more restrictive so check that our sig algs are consistent with this * EC cert. See section 4.2.3 of RFC8446. */ - eckey = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[SSL_PKEY_ECC].privatekey); +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + if (s->enable_sign_by_dc + && ssl_has_dc(s, SSL_PKEY_ECC)) { + eckey = EVP_PKEY_get0_EC_KEY(s->cert->dc_pkeys[SSL_PKEY_ECC].privatekey); + } else +#endif + eckey = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[SSL_PKEY_ECC].privatekey); if (eckey == NULL) continue; curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)); diff --git a/ssl/statem/statem_local.h b/ssl/statem/statem_local.h index af3ad055d..c34e18508 100644 --- a/ssl/statem/statem_local.h +++ b/ssl/statem/statem_local.h @@ -105,7 +105,9 @@ WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst); __owur int tls_get_message_header(SSL *s, int *mt); __owur int tls_get_message_body(SSL *s, size_t *len); __owur int dtls_get_message(SSL *s, int *mt, size_t *len); +#ifndef OPENSSL_NO_QUIC __owur int quic_get_message(SSL *s, int *mt, size_t *len); +#endif /* Message construction and processing functions */ __owur int tls_process_initial_server_flight(SSL *s); @@ -241,6 +243,10 @@ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +int tls_parse_ctos_delegated_credential(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#endif int tls_parse_ctos_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, unsigned int context, @@ -250,6 +256,10 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, int tls_parse_ctos_post_handshake_auth(SSL *, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); #ifndef OPENSSL_NO_QUIC +int tls_parse_ctos_quic_transport_params_draft(SSL *s, PACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); + int tls_parse_ctos_quic_transport_params(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); #endif @@ -295,6 +305,10 @@ EXT_RETURN tls_construct_stoc_use_srtp(SSL *s, WPACKET *pkt, unsigned int contex #endif EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx); +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +EXT_RETURN tls_construct_stoc_delegated_credential(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#endif EXT_RETURN tls_construct_stoc_ems(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx); EXT_RETURN tls_construct_stoc_supported_versions(SSL *s, WPACKET *pkt, @@ -316,6 +330,11 @@ EXT_RETURN tls_construct_stoc_cryptopro_bug(SSL *s, WPACKET *pkt, EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx); #ifndef OPENSSL_NO_QUIC +EXT_RETURN tls_construct_stoc_quic_transport_params_draft(SSL *s, WPACKET *pkt, + unsigned int context, + X509 *x, + size_t chainidx); + EXT_RETURN tls_construct_stoc_quic_transport_params(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx); @@ -370,6 +389,10 @@ EXT_RETURN tls_construct_ctos_etm(SSL *s, WPACKET *pkt, unsigned int context, EXT_RETURN tls_construct_ctos_sct(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx); #endif +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +EXT_RETURN tls_construct_ctos_delegated_credential(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#endif EXT_RETURN tls_construct_ctos_ems(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx); EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt, @@ -391,6 +414,10 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx); #ifndef OPENSSL_NO_QUIC +EXT_RETURN tls_construct_ctos_quic_transport_params_draft(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); + EXT_RETURN tls_construct_ctos_quic_transport_params(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx); @@ -430,6 +457,10 @@ int tls_parse_stoc_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x, #endif int tls_parse_stoc_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +int tls_parse_stoc_delegated_credential(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +#endif int tls_parse_stoc_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context, @@ -441,6 +472,10 @@ int tls_parse_stoc_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x, int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); #ifndef OPENSSL_NO_QUIC +int tls_parse_stoc_quic_transport_params_draft(SSL *s, PACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); + int tls_parse_stoc_quic_transport_params(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx); #endif @@ -449,3 +484,14 @@ int tls_handle_alpn(SSL *s); int tls13_save_handshake_digest_for_pha(SSL *s); int tls13_restore_handshake_digest_for_pha(SSL *s); + +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +int tls_parse_dc_from_extension(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_process_dc_request(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +EXT_RETURN tls_construct_delegated_credential_raw(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +EXT_RETURN tls_construct_delegated_credential_request(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#endif diff --git a/ssl/statem/statem_quic.c b/ssl/statem/statem_quic.c index eb1a76ec9..212d43851 100644 --- a/ssl/statem/statem_quic.c +++ b/ssl/statem/statem_quic.c @@ -21,9 +21,16 @@ int quic_get_message(SSL *s, int *mt, size_t *len) QUIC_DATA *qd = s->quic_input_data_head; uint8_t *p; - if (qd == NULL || (qd->length - qd->offset) != 0) { + if (qd == NULL) { s->rwstate = SSL_READING; - *len = 0; + *mt = *len = 0; + return 0; + } + + if (!ossl_assert(qd->length >= SSL3_HM_HEADER_LENGTH)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_GET_MESSAGE, + SSL_R_BAD_LENGTH); + *mt = *len = 0; return 0; } @@ -31,19 +38,19 @@ int quic_get_message(SSL *s, int *mt, size_t *len) if (qd->level != s->quic_read_level) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_GET_MESSAGE, SSL_R_WRONG_ENCRYPTION_LEVEL_RECEIVED); - *len = 0; + *mt = *len = 0; return 0; } if (!BUF_MEM_grow_clean(s->init_buf, (int)qd->length)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_GET_MESSAGE, ERR_R_BUF_LIB); - *len = 0; + *mt = *len = 0; return 0; } /* Copy buffered data */ - memcpy(s->init_buf->data, (void*)(qd + 1), qd->length); + memcpy(s->init_buf->data, s->quic_buf->data + qd->start, qd->length); s->init_buf->length = qd->length; s->quic_input_data_head = qd->next; if (s->quic_input_data_head == NULL) @@ -64,6 +71,14 @@ int quic_get_message(SSL *s, int *mt, size_t *len) *len = 0; return 0; } + /* No KeyUpdate in QUIC */ + if (*mt == SSL3_MT_KEY_UPDATE) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_QUIC_GET_MESSAGE, + SSL_R_UNEXPECTED_MESSAGE); + *len = 0; + return 0; + } + /* * If receiving Finished, record MAC of prior handshake messages for @@ -83,8 +98,8 @@ int quic_get_message(SSL *s, int *mt, size_t *len) */ #define SERVER_HELLO_RANDOM_OFFSET (SSL3_HM_HEADER_LENGTH + 2) /* KeyUpdate and NewSessionTicket do not need to be added */ - if (!SSL_IS_TLS13(s) || (s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET - && s->s3->tmp.message_type != SSL3_MT_KEY_UPDATE)) { + if (s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET + && s->s3->tmp.message_type != SSL3_MT_KEY_UPDATE) { if (s->s3->tmp.message_type != SSL3_MT_SERVER_HELLO || s->init_num < SERVER_HELLO_RANDOM_OFFSET + SSL3_RANDOM_SIZE || memcmp(hrrrandom, diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index b2364b3d4..77deb3009 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -967,6 +967,7 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst) /* SSLfatal() already called */ return WORK_ERROR; +#ifndef OPENSSL_NO_QUIC if (SSL_IS_QUIC(s) && s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) { s->early_data_state = SSL_EARLY_DATA_FINISHED_READING; @@ -975,6 +976,7 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst) /* SSLfatal() already called */ return WORK_ERROR; } +#endif } break; @@ -3908,6 +3910,8 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt) } } else { EVP_PKEY *pkey; + X509 *peer_cert; + i = ssl_verify_cert_chain(s, sk); if (i <= 0) { @@ -3921,13 +3925,38 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt) SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, i); goto err; } - pkey = X509_get0_pubkey(sk_X509_value(sk, 0)); + peer_cert = sk_X509_value(sk, 0); + pkey = X509_get0_pubkey(peer_cert); if (pkey == NULL) { SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, SSL_R_UNKNOWN_CERTIFICATE_TYPE); goto err; } +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + if (s->delegated_credential_tag & DC_HAS_BEEN_USED_FOR_VERIFY_PEER) { + if (!SSL_IS_TLS13(s)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, + SSL_R_UNKNOWN_CERTIFICATE_TYPE); + goto err; + } + + if (!DC_check_valid(peer_cert, s->session->peer_dc)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, + SSL_R_CERTIFICATE_VERIFY_FAILED); + goto err; + } + + if (SSL_verify_delegated_credential_signature(peer_cert, s->session->peer_dc, 0) <= 0) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, + SSL_R_CERTIFICATE_VERIFY_FAILED); + goto err; + } + } +#endif } /* diff --git a/ssl/statem_ntls/extensions.c b/ssl/statem_ntls/extensions.c new file mode 100644 index 000000000..308cd0555 --- /dev/null +++ b/ssl/statem_ntls/extensions.c @@ -0,0 +1,1509 @@ +/* + * Copyright 2019 The BabaSSL Project Authors. All Rights Reserved. + */ + + +#include +#include "internal/nelem.h" +#include "internal/cryptlib.h" +#include "ssl_local_ntls.h" +#include "statem_local_ntls.h" +#include "internal/cryptlib.h" + +# if (!defined OPENSSL_NO_NTLS) && (!defined OPENSSL_NO_SM2) \ + && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) +static int final_renegotiate(SSL *s, unsigned int context, int sent); +static int init_server_name(SSL *s, unsigned int context); +static int final_server_name(SSL *s, unsigned int context, int sent); +# ifndef OPENSSL_NO_EC +static int final_ec_pt_formats(SSL *s, unsigned int context, int sent); +# endif +static int init_session_ticket(SSL *s, unsigned int context); +# ifndef OPENSSL_NO_OCSP +static int init_status_request(SSL *s, unsigned int context); +# endif +# ifndef OPENSSL_NO_NEXTPROTONEG +static int init_npn(SSL *s, unsigned int context); +# endif +static int init_alpn(SSL *s, unsigned int context); +static int final_alpn(SSL *s, unsigned int context, int sent); +static int init_sig_algs_cert(SSL *s, unsigned int context); +static int init_sig_algs(SSL *s, unsigned int context); +static int init_certificate_authorities(SSL *s, unsigned int context); +static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt, + unsigned int context, + X509 *x, + size_t chainidx); +static int tls_parse_certificate_authorities(SSL *s, PACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); + +static int init_etm(SSL *s, unsigned int context); +static int init_ems(SSL *s, unsigned int context); +static int final_ems(SSL *s, unsigned int context, int sent); +static int init_psk_kex_modes(SSL *s, unsigned int context); +# ifndef OPENSSL_NO_EC +static int final_key_share(SSL *s, unsigned int context, int sent); +# endif +# ifndef OPENSSL_NO_SRTP +static int init_srtp(SSL *s, unsigned int context); +# endif +static int final_sig_algs(SSL *s, unsigned int context, int sent); +static int final_early_data(SSL *s, unsigned int context, int sent); +static int final_maxfragmentlen(SSL *s, unsigned int context, int sent); +static int init_post_handshake_auth(SSL *s, unsigned int context); + +/* Structure to define a built-in extension */ +typedef struct extensions_definition_st { + /* The defined type for the extension */ + unsigned int type; + /* + * The context that this extension applies to, e.g. what messages and + * protocol versions + */ + unsigned int context; + /* + * Initialise extension before parsing. Always called for relevant contexts + * even if extension not present + */ + int (*init)(SSL *s, unsigned int context); + /* Parse extension sent from client to server */ + int (*parse_ctos)(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); + /* Parse extension send from server to client */ + int (*parse_stoc)(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); + /* Construct extension sent from server to client */ + EXT_RETURN (*construct_stoc)(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); + /* Construct extension sent from client to server */ + EXT_RETURN (*construct_ctos)(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); + /* + * Finalise extension after parsing. Always called where an extensions was + * initialised even if the extension was not present. |sent| is set to 1 if + * the extension was seen, or 0 otherwise. + */ + int (*final)(SSL *s, unsigned int context, int sent); +} EXTENSION_DEFINITION; + +/* + * Definitions of all built-in extensions. NOTE: Changes in the number or order + * of these extensions should be mirrored with equivalent changes to the + * indexes ( TLSEXT_IDX_* ) defined in ssl_local.h. + * Each extension has an initialiser, a client and + * server side parser and a finaliser. The initialiser is called (if the + * extension is relevant to the given context) even if we did not see the + * extension in the message that we received. The parser functions are only + * called if we see the extension in the message. The finalisers are always + * called if the initialiser was called. + * There are also server and client side constructor functions which are always + * called during message construction if the extension is relevant for the + * given context. + * The initialisation, parsing, finalisation and construction functions are + * always called in the order defined in this list. Some extensions may depend + * on others having been processed first, so the order of this list is + * significant. + * The extension context is defined by a series of flags which specify which + * messages the extension is relevant to. These flags also specify whether the + * extension is relevant to a particular protocol or protocol version. + * + * TODO(TLS1.3): Make sure we have a test to check the consistency of these + * + * NOTE: WebSphere Application Server 7+ cannot handle empty extensions at + * the end, keep these extensions before signature_algorithm. + */ +# define INVALID_EXTENSION { 0x10000, 0, NULL, NULL, NULL, NULL, NULL, NULL } +static const EXTENSION_DEFINITION ext_defs[] = { + { + TLSEXT_TYPE_renegotiate, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_SSL3_ALLOWED | SSL_EXT_TLS1_2_AND_BELOW_ONLY, + NULL, tls_parse_ctos_renegotiate_ntls, tls_parse_stoc_renegotiate_ntls, + tls_construct_stoc_renegotiate_ntls, tls_construct_ctos_renegotiate_ntls, + final_renegotiate + }, + { + TLSEXT_TYPE_server_name, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, + init_server_name, + tls_parse_ctos_server_name_ntls, tls_parse_stoc_server_name_ntls, + tls_construct_stoc_server_name_ntls, tls_construct_ctos_server_name_ntls, + final_server_name + }, + { + TLSEXT_TYPE_max_fragment_length, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, + NULL, tls_parse_ctos_maxfragmentlen_ntls, tls_parse_stoc_maxfragmentlen_ntls, + tls_construct_stoc_maxfragmentlen_ntls, tls_construct_ctos_maxfragmentlen_ntls, + final_maxfragmentlen + }, + INVALID_EXTENSION, +# ifndef OPENSSL_NO_EC + { + TLSEXT_TYPE_ec_point_formats, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_2_AND_BELOW_ONLY, + NULL, tls_parse_ctos_ec_pt_formats_ntls, tls_parse_stoc_ec_pt_formats_ntls, + tls_construct_stoc_ec_pt_formats_ntls, tls_construct_ctos_ec_pt_formats_ntls, + final_ec_pt_formats + }, + { + /* + * "supported_groups" is spread across several specifications. + * It was originally specified as "elliptic_curves" in RFC 4492, + * and broadened to include named FFDH groups by RFC 7919. + * Both RFCs 4492 and 7919 do not include a provision for the server + * to indicate to the client the complete list of groups supported + * by the server, with the server instead just indicating the + * selected group for this connection in the ServerKeyExchange + * message. TLS 1.3 adds a scheme for the server to indicate + * to the client its list of supported groups in the + * EncryptedExtensions message, but none of the relevant + * specifications permit sending supported_groups in the ServerHello. + * Nonetheless (possibly due to the close proximity to the + * "ec_point_formats" extension, which is allowed in the ServerHello), + * there are several servers that send this extension in the + * ServerHello anyway. Up to and including the 1.1.0 release, + * we did not check for the presence of nonpermitted extensions, + * so to avoid a regression, we must permit this extension in the + * TLS 1.2 ServerHello as well. + * + * Note that there is no tls_parse_stoc_supported_groups function, + * so we do not perform any additional parsing, validation, or + * processing on the server's group list -- this is just a minimal + * change to preserve compatibility with these misbehaving servers. + */ + TLSEXT_TYPE_supported_groups, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS + | SSL_EXT_TLS1_2_SERVER_HELLO, + NULL, tls_parse_ctos_supported_groups_ntls, NULL, + tls_construct_stoc_supported_groups_ntls, + tls_construct_ctos_supported_groups_ntls, NULL + }, +# else + INVALID_EXTENSION, + INVALID_EXTENSION, +# endif + { + TLSEXT_TYPE_session_ticket, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_2_AND_BELOW_ONLY, + init_session_ticket, tls_parse_ctos_session_ticket_ntls, + tls_parse_stoc_session_ticket_ntls, tls_construct_stoc_session_ticket_ntls, + tls_construct_ctos_session_ticket_ntls, NULL + }, +# ifndef OPENSSL_NO_OCSP + { + TLSEXT_TYPE_status_request, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_CERTIFICATE | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST, + init_status_request, tls_parse_ctos_status_request_ntls, + tls_parse_stoc_status_request_ntls, tls_construct_stoc_status_request_ntls, + tls_construct_ctos_status_request_ntls, NULL + }, +# else + INVALID_EXTENSION, +# endif +# ifndef OPENSSL_NO_NEXTPROTONEG + { + TLSEXT_TYPE_next_proto_neg, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_2_AND_BELOW_ONLY, + init_npn, tls_parse_ctos_npn_ntls, tls_parse_stoc_npn_ntls, + tls_construct_stoc_next_proto_neg_ntls, tls_construct_ctos_npn_ntls, NULL + }, +# else + INVALID_EXTENSION, +# endif + { + /* + * Must appear in this list after server_name so that finalisation + * happens after server_name callbacks + */ + TLSEXT_TYPE_application_layer_protocol_negotiation, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, + init_alpn, tls_parse_ctos_alpn_ntls, tls_parse_stoc_alpn_ntls, + tls_construct_stoc_alpn_ntls, tls_construct_ctos_alpn_ntls, final_alpn + }, +# ifndef OPENSSL_NO_SRTP + { + TLSEXT_TYPE_use_srtp, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS | SSL_EXT_DTLS_ONLY, + init_srtp, tls_parse_ctos_use_srtp_ntls, tls_parse_stoc_use_srtp_ntls, + tls_construct_stoc_use_srtp_ntls, tls_construct_ctos_use_srtp_ntls, NULL + }, +# else + INVALID_EXTENSION, +# endif + { + TLSEXT_TYPE_encrypt_then_mac, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_2_AND_BELOW_ONLY, + init_etm, tls_parse_ctos_etm_ntls, tls_parse_stoc_etm_ntls, + tls_construct_stoc_etm_ntls, tls_construct_ctos_etm_ntls, NULL + }, +# ifndef OPENSSL_NO_CT + { + TLSEXT_TYPE_signed_certificate_timestamp, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_CERTIFICATE | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST, + NULL, + /* + * No server side support for this, but can be provided by a custom + * extension. This is an exception to the rule that custom extensions + * cannot override built in ones. + */ + NULL, tls_parse_stoc_sct_ntls, NULL, tls_construct_ctos_sct_ntls, NULL + }, +# else + INVALID_EXTENSION, +# endif + { + TLSEXT_TYPE_extended_master_secret, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_2_AND_BELOW_ONLY, + init_ems, tls_parse_ctos_ems_ntls, tls_parse_stoc_ems_ntls, + tls_construct_stoc_ems_ntls, tls_construct_ctos_ems_ntls, final_ems + }, + { + TLSEXT_TYPE_signature_algorithms_cert, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST, + init_sig_algs_cert, tls_parse_ctos_sig_algs_cert_ntls, + tls_parse_ctos_sig_algs_cert_ntls, + /* We do not generate signature_algorithms_cert at present. */ + NULL, NULL, NULL + }, + { + TLSEXT_TYPE_post_handshake_auth, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ONLY, + init_post_handshake_auth, + tls_parse_ctos_post_handshake_auth_ntls, NULL, + NULL, tls_construct_ctos_post_handshake_auth_ntls, + NULL, + }, + { + TLSEXT_TYPE_signature_algorithms, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST, + init_sig_algs, tls_parse_ctos_sig_algs_ntls, + tls_parse_ctos_sig_algs_ntls, tls_construct_ctos_sig_algs_ntls, + tls_construct_ctos_sig_algs_ntls, final_sig_algs + }, + { + TLSEXT_TYPE_supported_versions, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO + | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST | SSL_EXT_TLS_IMPLEMENTATION_ONLY, + NULL, + /* Processed inline as part of version selection */ + NULL, tls_parse_stoc_supported_versions_ntls, + tls_construct_stoc_supported_versions_ntls, + tls_construct_ctos_supported_versions_ntls, NULL + }, + { + TLSEXT_TYPE_psk_kex_modes, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS_IMPLEMENTATION_ONLY + | SSL_EXT_TLS1_3_ONLY, + init_psk_kex_modes, tls_parse_ctos_psk_kex_modes_ntls, NULL, NULL, + tls_construct_ctos_psk_kex_modes_ntls, NULL + }, +# ifndef OPENSSL_NO_EC + { + /* + * Must be in this list after supported_groups. We need that to have + * been parsed before we do this one. + */ + TLSEXT_TYPE_key_share, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO + | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST | SSL_EXT_TLS_IMPLEMENTATION_ONLY + | SSL_EXT_TLS1_3_ONLY, + NULL, tls_parse_ctos_key_share_ntls, tls_parse_stoc_key_share_ntls, + tls_construct_stoc_key_share_ntls, tls_construct_ctos_key_share_ntls, + final_key_share + }, +# endif + { + /* Must be after key_share */ + TLSEXT_TYPE_cookie, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST + | SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY, + NULL, tls_parse_ctos_cookie_ntls, tls_parse_stoc_cookie_ntls, + tls_construct_stoc_cookie_ntls, tls_construct_ctos_cookie_ntls, NULL + }, + { + /* + * Special unsolicited ServerHello extension only used when + * SSL_OP_CRYPTOPRO_TLSEXT_BUG is set. We allow it in a ClientHello but + * ignore it. + */ + TLSEXT_TYPE_cryptopro_bug, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_2_AND_BELOW_ONLY, + NULL, NULL, NULL, tls_construct_stoc_cryptopro_bug_ntls, NULL, NULL + }, + { + TLSEXT_TYPE_early_data, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS + | SSL_EXT_TLS1_3_NEW_SESSION_TICKET | SSL_EXT_TLS1_3_ONLY, + NULL, tls_parse_ctos_early_data_ntls, tls_parse_stoc_early_data_ntls, + tls_construct_stoc_early_data_ntls, tls_construct_ctos_early_data_ntls, + final_early_data + }, + { + TLSEXT_TYPE_certificate_authorities, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST + | SSL_EXT_TLS1_3_ONLY, + init_certificate_authorities, + tls_parse_certificate_authorities, tls_parse_certificate_authorities, + tls_construct_certificate_authorities, + tls_construct_certificate_authorities, NULL, + }, + { + /* Must be immediately before pre_shared_key */ + TLSEXT_TYPE_padding, + SSL_EXT_CLIENT_HELLO, + NULL, + /* We send this, but don't read it */ + NULL, NULL, NULL, tls_construct_ctos_padding_ntls, NULL + }, + { + /* Required by the TLSv1.3 spec to always be the last extension */ + TLSEXT_TYPE_psk, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO + | SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY, + NULL, tls_parse_ctos_psk_ntls, tls_parse_stoc_psk_ntls, tls_construct_stoc_psk_ntls, + tls_construct_ctos_psk_ntls, NULL + } +}; + +/* Check whether an extension's context matches the current context */ +static int validate_context(SSL *s, unsigned int extctx, unsigned int thisctx) +{ + /* Check we're allowed to use this extension in this context */ + if ((thisctx & extctx) == 0) + return 0; + + if (SSL_IS_DTLS(s)) { + if ((extctx & SSL_EXT_TLS_ONLY) != 0) + return 0; + } else if ((extctx & SSL_EXT_DTLS_ONLY) != 0) { + return 0; + } + + return 1; +} + +int tls_validate_all_contexts_ntls(SSL *s, unsigned int thisctx, RAW_EXTENSION *exts) +{ + size_t i, num_exts, builtin_num = OSSL_NELEM(ext_defs), offset; + RAW_EXTENSION *thisext; + unsigned int context; + ENDPOINT role = ENDPOINT_BOTH; + + if ((thisctx & SSL_EXT_CLIENT_HELLO) != 0) + role = ENDPOINT_SERVER; + else if ((thisctx & SSL_EXT_TLS1_2_SERVER_HELLO) != 0) + role = ENDPOINT_CLIENT; + + /* Calculate the number of extensions in the extensions list */ + num_exts = builtin_num + s->cert->custext.meths_count; + + for (thisext = exts, i = 0; i < num_exts; i++, thisext++) { + if (!thisext->present) + continue; + + if (i < builtin_num) { + context = ext_defs[i].context; + } else { + custom_ext_method *meth = NULL; + + meth = custom_ext_find_ntls(&s->cert->custext, role, thisext->type, + &offset); + if (!ossl_assert(meth != NULL)) + return 0; + context = meth->context; + } + + if (!validate_context(s, context, thisctx)) + return 0; + } + + return 1; +} + +/* + * Verify whether we are allowed to use the extension |type| in the current + * |context|. Returns 1 to indicate the extension is allowed or unknown or 0 to + * indicate the extension is not allowed. If returning 1 then |*found| is set to + * the definition for the extension we found. + */ +static int verify_extension(SSL *s, unsigned int context, unsigned int type, + custom_ext_methods *meths, RAW_EXTENSION *rawexlist, + RAW_EXTENSION **found) +{ + size_t i; + size_t builtin_num = OSSL_NELEM(ext_defs); + const EXTENSION_DEFINITION *thisext; + + for (i = 0, thisext = ext_defs; i < builtin_num; i++, thisext++) { + if (type == thisext->type) { + if (!validate_context(s, thisext->context, context)) + return 0; + + *found = &rawexlist[i]; + return 1; + } + } + + /* Check the custom extensions */ + if (meths != NULL) { + size_t offset = 0; + ENDPOINT role = ENDPOINT_BOTH; + custom_ext_method *meth = NULL; + + if ((context & SSL_EXT_CLIENT_HELLO) != 0) + role = ENDPOINT_SERVER; + else if ((context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0) + role = ENDPOINT_CLIENT; + + meth = custom_ext_find_ntls(meths, role, type, &offset); + if (meth != NULL) { + if (!validate_context(s, meth->context, context)) + return 0; + *found = &rawexlist[offset + builtin_num]; + return 1; + } + } + + /* Unknown extension. We allow it */ + *found = NULL; + return 1; +} + +/* + * Check whether the context defined for an extension |extctx| means whether + * the extension is relevant for the current context |thisctx| or not. Returns + * 1 if the extension is relevant for this context, and 0 otherwise + */ +int extension_is_relevant_ntls(SSL *s, unsigned int extctx, unsigned int thisctx) +{ + int is_tls13; + + /* + * For HRR we haven't selected the version yet but we know it will be + * TLSv1.3 + */ + is_tls13 = 0; + + if ((s->version == SSL3_VERSION + && (extctx & SSL_EXT_SSL3_ALLOWED) == 0) + /* + * However, version negotiation *has* occurred by the time the + * ClientHello extensions are being parsed. + * Be careful to allow TLS 1.3-only extensions when generating + * the ClientHello. + */ + || (is_tls13 && (extctx & SSL_EXT_TLS1_2_AND_BELOW_ONLY) != 0) + || (!is_tls13 && (extctx & SSL_EXT_TLS1_3_ONLY) != 0 + && (thisctx & SSL_EXT_CLIENT_HELLO) == 0) + || (s->server && !is_tls13 && (extctx & SSL_EXT_TLS1_3_ONLY) != 0) + || (s->hit && (extctx & SSL_EXT_IGNORE_ON_RESUMPTION) != 0)) + return 0; + return 1; +} + +/* + * Gather a list of all the extensions from the data in |packet]. |context| + * tells us which message this extension is for. The raw extension data is + * stored in |*res| on success. We don't actually process the content of the + * extensions yet, except to check their types. This function also runs the + * initialiser functions for all known extensions if |init| is nonzero (whether + * we have collected them or not). If successful the caller is responsible for + * freeing the contents of |*res|. + * + * Per http://tools.ietf.org/html/rfc5246# section-7.4.1.4, there may not be + * more than one extension of the same type in a ClientHello or ServerHello. + * This function returns 1 if all extensions are unique and we have parsed their + * types, and 0 if the extensions contain duplicates, could not be successfully + * found, or an internal error occurred. We only check duplicates for + * extensions that we know about. We ignore others. + */ +int tls_collect_extensions_ntls(SSL *s, PACKET *packet, unsigned int context, + RAW_EXTENSION **res, size_t *len, int init) +{ + PACKET extensions = *packet; + size_t i = 0; + size_t num_exts; + custom_ext_methods *exts = &s->cert->custext; + RAW_EXTENSION *raw_extensions = NULL; + const EXTENSION_DEFINITION *thisexd; + + *res = NULL; + + /* + * Initialise server side custom extensions. Client side is done during + * construction of extensions for the ClientHello. + */ + if ((context & SSL_EXT_CLIENT_HELLO) != 0) + custom_ext_init_ntls(&s->cert->custext); + + num_exts = OSSL_NELEM(ext_defs) + (exts != NULL ? exts->meths_count : 0); + raw_extensions = OPENSSL_zalloc(num_exts * sizeof(*raw_extensions)); + if (raw_extensions == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_COLLECT_EXTENSIONS_NTLS, + ERR_R_MALLOC_FAILURE); + return 0; + } + + i = 0; + while (PACKET_remaining(&extensions) > 0) { + unsigned int type, idx; + PACKET extension; + RAW_EXTENSION *thisex; + + if (!PACKET_get_net_2(&extensions, &type) || + !PACKET_get_length_prefixed_2(&extensions, &extension)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_COLLECT_EXTENSIONS_NTLS, + SSL_R_BAD_EXTENSION); + goto err; + } + /* + * Verify this extension is allowed. We only check duplicates for + * extensions that we recognise. We also have a special case for the + * PSK extension, which must be the last one in the ClientHello. + */ + if (!verify_extension(s, context, type, exts, raw_extensions, &thisex) + || (thisex != NULL && thisex->present == 1) + || (type == TLSEXT_TYPE_psk + && (context & SSL_EXT_CLIENT_HELLO) != 0 + && PACKET_remaining(&extensions) != 0)) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_COLLECT_EXTENSIONS_NTLS, + SSL_R_BAD_EXTENSION); + goto err; + } + idx = thisex - raw_extensions; + /*- + * Check that we requested this extension (if appropriate). Requests can + * be sent in the ClientHello and CertificateRequest. Unsolicited + * extensions can be sent in the NewSessionTicket. We only do this for + * the built-in extensions. Custom extensions have a different but + * similar check elsewhere. + * Special cases: + * - The HRR cookie extension is unsolicited + * - The renegotiate extension is unsolicited (the client signals + * support via an SCSV) + * - The signed_certificate_timestamp extension can be provided by a + * custom extension or by the built-in version. We let the extension + * itself handle unsolicited response checks. + */ + if (idx < OSSL_NELEM(ext_defs) + && (context & (SSL_EXT_CLIENT_HELLO + | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST + | SSL_EXT_TLS1_3_NEW_SESSION_TICKET)) == 0 + && type != TLSEXT_TYPE_cookie + && type != TLSEXT_TYPE_renegotiate + && type != TLSEXT_TYPE_signed_certificate_timestamp + && (s->ext.extflags[idx] & SSL_EXT_FLAG_SENT) == 0 +# ifndef OPENSSL_NO_GOST + && !((context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0 + && type == TLSEXT_TYPE_cryptopro_bug) +# endif + ) { + SSLfatal_ntls(s, SSL_AD_UNSUPPORTED_EXTENSION, + SSL_F_TLS_COLLECT_EXTENSIONS_NTLS, SSL_R_UNSOLICITED_EXTENSION); + goto err; + } + if (thisex != NULL) { + thisex->data = extension; + thisex->present = 1; + thisex->type = type; + thisex->received_order = i++; + if (s->ext.debug_cb) + s->ext.debug_cb(s, !s->server, thisex->type, + PACKET_data(&thisex->data), + PACKET_remaining(&thisex->data), + s->ext.debug_arg); + } + } + + if (init) { + /* + * Initialise all known extensions relevant to this context, + * whether we have found them or not + */ + for (thisexd = ext_defs, i = 0; i < OSSL_NELEM(ext_defs); + i++, thisexd++) { + if (thisexd->init != NULL && (thisexd->context & context) != 0 + && extension_is_relevant_ntls(s, thisexd->context, context) + && !thisexd->init(s, context)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } + } + + *res = raw_extensions; + if (len != NULL) + *len = num_exts; + return 1; + + err: + OPENSSL_free(raw_extensions); + return 0; +} + +/* + * Runs the parser for a given extension with index |idx|. |exts| contains the + * list of all parsed extensions previously collected by + * tls_collect_extensions_ntls(). The parser is only run if it is applicable for the + * given |context| and the parser has not already been run. If this is for a + * Certificate message, then we also provide the parser with the relevant + * Certificate |x| and its position in the |chainidx| with 0 being the first + * Certificate. Returns 1 on success or 0 on failure. If an extension is not + * present this counted as success. + */ +int tls_parse_extension_ntls(SSL *s, TLSEXT_INDEX idx, int context, + RAW_EXTENSION *exts, X509 *x, size_t chainidx) +{ + RAW_EXTENSION *currext = &exts[idx]; + int (*parser)(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) = NULL; + + /* Skip if the extension is not present */ + if (!currext->present) + return 1; + + /* Skip if we've already parsed this extension */ + if (currext->parsed) + return 1; + + currext->parsed = 1; + + if (idx < OSSL_NELEM(ext_defs)) { + /* We are handling a built-in extension */ + const EXTENSION_DEFINITION *extdef = &ext_defs[idx]; + + /* Check if extension is defined for our protocol. If not, skip */ + if (!extension_is_relevant_ntls(s, extdef->context, context)) + return 1; + + parser = s->server ? extdef->parse_ctos : extdef->parse_stoc; + + if (parser != NULL) + return parser(s, &currext->data, context, x, chainidx); + + /* + * If the parser is NULL we fall through to the custom extension + * processing + */ + } + + /* Parse custom extensions */ + return custom_ext_parse_ntls(s, context, currext->type, + PACKET_data(&currext->data), + PACKET_remaining(&currext->data), + x, chainidx); +} + +/* + * Parse all remaining extensions that have not yet been parsed. Also calls the + * finalisation for all extensions at the end if |fin| is nonzero, whether we + * collected them or not. Returns 1 for success or 0 for failure. If we are + * working on a Certificate message then we also pass the Certificate |x| and + * its position in the |chainidx|, with 0 being the first certificate. + */ +int tls_parse_all_extensions_ntls(SSL *s, int context, RAW_EXTENSION *exts, X509 *x, + size_t chainidx, int fin) +{ + size_t i, numexts = OSSL_NELEM(ext_defs); + const EXTENSION_DEFINITION *thisexd; + + /* Calculate the number of extensions in the extensions list */ + numexts += s->cert->custext.meths_count; + + /* Parse each extension in turn */ + for (i = 0; i < numexts; i++) { + if (!tls_parse_extension_ntls(s, i, context, exts, x, chainidx)) { + /* SSLfatal_ntls() already called */ + return 0; + } + } + + if (fin) { + /* + * Finalise all known extensions relevant to this context, + * whether we have found them or not + */ + for (i = 0, thisexd = ext_defs; i < OSSL_NELEM(ext_defs); + i++, thisexd++) { + if (thisexd->final != NULL && (thisexd->context & context) != 0 + && !thisexd->final(s, context, exts[i].present)) { + /* SSLfatal_ntls() already called */ + return 0; + } + } + } + + return 1; +} + +int should_add_extension_ntls(SSL *s, unsigned int extctx, unsigned int thisctx, + int max_version) +{ + /* Skip if not relevant for our context */ + if ((extctx & thisctx) == 0) + return 0; + + /* Check if this extension is defined for our protocol. If not, skip */ + if (!extension_is_relevant_ntls(s, extctx, thisctx) + || ((extctx & SSL_EXT_TLS1_3_ONLY) != 0 + && (thisctx & SSL_EXT_CLIENT_HELLO) != 0 + && (SSL_IS_DTLS(s) || max_version < TLS1_3_VERSION))) + return 0; + + return 1; +} + +/* + * Construct all the extensions relevant to the current |context| and write + * them to |pkt|. If this is an extension for a Certificate in a Certificate + * message, then |x| will be set to the Certificate we are handling, and + * |chainidx| will indicate the position in the chainidx we are processing (with + * 0 being the first in the chain). Returns 1 on success or 0 on failure. On a + * failure construction stops at the first extension to fail to construct. + */ +int tls_construct_extensions_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + size_t i; + int min_version, max_version = 0, reason; + const EXTENSION_DEFINITION *thisexd; + + if (!WPACKET_start_sub_packet_u16(pkt) + /* + * If extensions are of zero length then we don't even add the + * extensions length bytes to a ClientHello/ServerHello + * (for non-TLSv1.3). + */ + || ((context & + (SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO)) != 0 + && !WPACKET_set_flags(pkt, + WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH))) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if ((context & SSL_EXT_CLIENT_HELLO) != 0) { + reason = ssl_get_min_max_version_ntls(s, &min_version, &max_version, NULL); + if (reason != 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS_NTLS, + reason); + return 0; + } + } + + /* Add custom extensions first */ + if ((context & SSL_EXT_CLIENT_HELLO) != 0) { + /* On the server side with initialise during ClientHello parsing */ + custom_ext_init_ntls(&s->cert->custext); + } + if (!custom_ext_add_ntls(s, context, pkt, x, chainidx, max_version)) { + /* SSLfatal_ntls() already called */ + return 0; + } + + for (i = 0, thisexd = ext_defs; i < OSSL_NELEM(ext_defs); i++, thisexd++) { + EXT_RETURN (*construct)(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); + EXT_RETURN ret; + + /* Skip if not relevant for our context */ + if (!should_add_extension_ntls(s, thisexd->context, context, max_version)) + continue; + + construct = s->server ? thisexd->construct_stoc + : thisexd->construct_ctos; + + if (construct == NULL) + continue; + + ret = construct(s, pkt, context, x, chainidx); + if (ret == EXT_RETURN_FAIL) { + /* SSLfatal_ntls() already called */ + return 0; + } + if (ret == EXT_RETURN_SENT + && (context & (SSL_EXT_CLIENT_HELLO + | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST + | SSL_EXT_TLS1_3_NEW_SESSION_TICKET)) != 0) + s->ext.extflags[i] |= SSL_EXT_FLAG_SENT; + } + + if (!WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +/* + * Built in extension finalisation and initialisation functions. All initialise + * or finalise the associated extension type for the given |context|. For + * finalisers |sent| is set to 1 if we saw the extension during parsing, and 0 + * otherwise. These functions return 1 on success or 0 on failure. + */ + +static int final_renegotiate(SSL *s, unsigned int context, int sent) +{ + if (!s->server) { + /* + * Check if we can connect to a server that doesn't support safe + * renegotiation + */ + if (!(s->options & SSL_OP_LEGACY_SERVER_CONNECT) + && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) + && !sent) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_RENEGOTIATE, + SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); + return 0; + } + + return 1; + } + + /* Need RI if renegotiating */ + if (s->renegotiate + && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) + && !sent) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_RENEGOTIATE, + SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); + return 0; + } + + + return 1; +} + +static int init_server_name(SSL *s, unsigned int context) +{ + if (s->server) { + s->servername_done = 0; + + OPENSSL_free(s->ext.hostname); + s->ext.hostname = NULL; + } + + return 1; +} + +static int final_server_name(SSL *s, unsigned int context, int sent) +{ + int ret = SSL_TLSEXT_ERR_NOACK; + int altmp = SSL_AD_UNRECOGNIZED_NAME; + int was_ticket = (SSL_get_options(s) & SSL_OP_NO_TICKET) == 0; + + if (!ossl_assert(s->ctx != NULL) || !ossl_assert(s->session_ctx != NULL)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (s->ctx->ext.servername_cb != NULL) + ret = s->ctx->ext.servername_cb(s, &altmp, + s->ctx->ext.servername_arg); + else if (s->session_ctx->ext.servername_cb != NULL) + ret = s->session_ctx->ext.servername_cb(s, &altmp, + s->session_ctx->ext.servername_arg); + + /* + * For servers, propagate the SNI hostname from the temporary + * storage in the SSL to the persistent SSL_SESSION, now that we + * know we accepted it. + * Clients make this copy when parsing the server's response to + * the extension, which is when they find out that the negotiation + * was successful. + */ + if (s->server) { + /* TODO(OpenSSL1.2) revisit !sent case */ + if (sent && ret == SSL_TLSEXT_ERR_OK && (!s->hit)) { + /* Only store the hostname in the session if we accepted it. */ + OPENSSL_free(s->session->ext.hostname); + s->session->ext.hostname = OPENSSL_strdup(s->ext.hostname); + if (s->session->ext.hostname == NULL && s->ext.hostname != NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME, + ERR_R_INTERNAL_ERROR); + } + } + } + + /* + * If we switched contexts (whether here or in the client_hello callback), + * move the sess_accept increment from the session_ctx to the new + * context, to avoid the confusing situation of having sess_accept_good + * exceed sess_accept (zero) for the new context. + */ + if (SSL_IS_FIRST_HANDSHAKE(s) && s->ctx != s->session_ctx) { + tsan_counter(&s->ctx->stats.sess_accept); + tsan_decr(&s->session_ctx->stats.sess_accept); + } + + /* + * If we're expecting to send a ticket, and tickets were previously enabled, + * and now tickets are disabled, then turn off expected ticket. + * Also, if this is not a resumption, create a new session ID + */ + if (ret == SSL_TLSEXT_ERR_OK && s->ext.ticket_expected + && was_ticket && (SSL_get_options(s) & SSL_OP_NO_TICKET) != 0) { + s->ext.ticket_expected = 0; + if (!s->hit) { + SSL_SESSION* ss = SSL_get_session(s); + + if (ss != NULL) { + OPENSSL_free(ss->ext.tick); + ss->ext.tick = NULL; + ss->ext.ticklen = 0; + ss->ext.tick_lifetime_hint = 0; + ss->ext.tick_age_add = 0; + if (!ssl_generate_session_id(s, ss)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME, + ERR_R_INTERNAL_ERROR); + return 0; + } + } else { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + } + + switch (ret) { + case SSL_TLSEXT_ERR_ALERT_FATAL: + SSLfatal_ntls(s, altmp, SSL_F_FINAL_SERVER_NAME, SSL_R_CALLBACK_FAILED); + return 0; + + case SSL_TLSEXT_ERR_ALERT_WARNING: + /* TLSv1.3 doesn't have warning alerts so we suppress this */ + ssl3_send_alert(s, SSL3_AL_WARNING, altmp); + return 1; + + case SSL_TLSEXT_ERR_NOACK: + s->servername_done = 0; + return 1; + + default: + return 1; + } +} + +# ifndef OPENSSL_NO_EC +static int final_ec_pt_formats(SSL *s, unsigned int context, int sent) +{ + unsigned long alg_k, alg_a; + + if (s->server) + return 1; + + alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + alg_a = s->s3->tmp.new_cipher->algorithm_auth; + + /* + * If we are client and using an elliptic curve cryptography cipher + * suite, then if server returns an EC point formats lists extension it + * must contain uncompressed. + */ + if (s->ext.ecpointformats != NULL + && s->ext.ecpointformats_len > 0 + && s->ext.peer_ecpointformats != NULL + && s->ext.peer_ecpointformats_len > 0 + && ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA))) { + /* we are using an ECC cipher */ + size_t i; + unsigned char *list = s->ext.peer_ecpointformats; + + for (i = 0; i < s->ext.peer_ecpointformats_len; i++) { + if (*list++ == TLSEXT_ECPOINTFORMAT_uncompressed) + break; + } + if (i == s->ext.peer_ecpointformats_len) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_FINAL_EC_PT_FORMATS, + SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST); + return 0; + } + } + + return 1; +} +# endif + +static int init_session_ticket(SSL *s, unsigned int context) +{ + if (!s->server) + s->ext.ticket_expected = 0; + + return 1; +} + +# ifndef OPENSSL_NO_OCSP +static int init_status_request(SSL *s, unsigned int context) +{ + if (s->server) { + s->ext.status_type = TLSEXT_STATUSTYPE_nothing; + } else { + /* + * Ensure we get sensible values passed to tlsext_status_cb in the event + * that we don't receive a status message + */ + OPENSSL_free(s->ext.ocsp.resp); + s->ext.ocsp.resp = NULL; + s->ext.ocsp.resp_len = 0; + } + + return 1; +} +# endif + +# ifndef OPENSSL_NO_NEXTPROTONEG +static int init_npn(SSL *s, unsigned int context) +{ + s->s3->npn_seen = 0; + + return 1; +} +# endif + +static int init_alpn(SSL *s, unsigned int context) +{ + OPENSSL_free(s->s3->alpn_selected); + s->s3->alpn_selected = NULL; + s->s3->alpn_selected_len = 0; + if (s->server) { + OPENSSL_free(s->s3->alpn_proposed); + s->s3->alpn_proposed = NULL; + s->s3->alpn_proposed_len = 0; + } + return 1; +} + +static int final_alpn(SSL *s, unsigned int context, int sent) +{ + if (!s->server && !sent && s->session->ext.alpn_selected != NULL) + s->ext.early_data_ok = 0; + return 1; + + /* + * Call alpn_select callback if needed. Has to be done after SNI and + * cipher negotiation (HTTP/2 restricts permitted ciphers). In TLSv1.3 + * we also have to do this before we decide whether to accept early_data. + * In TLSv1.3 we've already negotiated our cipher so we do this call now. + * For < TLSv1.3 we defer it until after cipher negotiation. + * + * On failure SSLfatal_ntls() already called. + */ + return tls_handle_alpn_ntls(s); +} + +static int init_sig_algs(SSL *s, unsigned int context) +{ + /* Clear any signature algorithms extension received */ + OPENSSL_free(s->s3->tmp.peer_sigalgs); + s->s3->tmp.peer_sigalgs = NULL; + + return 1; +} + +static int init_sig_algs_cert(SSL *s, unsigned int context) +{ + /* Clear any signature algorithms extension received */ + OPENSSL_free(s->s3->tmp.peer_cert_sigalgs); + s->s3->tmp.peer_cert_sigalgs = NULL; + + return 1; +} + +static int init_etm(SSL *s, unsigned int context) +{ + s->ext.use_etm = 0; + + return 1; +} + +static int init_ems(SSL *s, unsigned int context) +{ + if (!s->server) + s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS; + + return 1; +} + +static int final_ems(SSL *s, unsigned int context, int sent) +{ + if (!s->server && s->hit) { + /* + * Check extended master secret extension is consistent with + * original session. + */ + if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) != + !(s->session->flags & SSL_SESS_FLAG_EXTMS)) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_EMS, + SSL_R_INCONSISTENT_EXTMS); + return 0; + } + } + + return 1; +} + +static int init_certificate_authorities(SSL *s, unsigned int context) +{ + sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free); + s->s3->tmp.peer_ca_names = NULL; + return 1; +} + +static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt, + unsigned int context, + X509 *x, + size_t chainidx) +{ + const STACK_OF(X509_NAME) *ca_sk = get_ca_names_ntls(s); + + if (ca_sk == NULL || sk_X509_NAME_num(ca_sk) == 0) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_certificate_authorities) + || !WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + if (!construct_ca_names_ntls(s, ca_sk, pkt)) { + /* SSLfatal_ntls() already called */ + return EXT_RETURN_FAIL; + } + + if (!WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +static int tls_parse_certificate_authorities(SSL *s, PACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + if (!parse_ca_names_ntls(s, pkt)) + return 0; + if (PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CERTIFICATE_AUTHORITIES, SSL_R_BAD_EXTENSION); + return 0; + } + return 1; +} + +# ifndef OPENSSL_NO_SRTP +static int init_srtp(SSL *s, unsigned int context) +{ + if (s->server) + s->srtp_profile = NULL; + + return 1; +} +# endif + +static int final_sig_algs(SSL *s, unsigned int context, int sent) +{ + return 1; +} + +# ifndef OPENSSL_NO_EC +static int final_key_share(SSL *s, unsigned int context, int sent) +{ + return 1; +} +# endif + +static int init_psk_kex_modes(SSL *s, unsigned int context) +{ + s->ext.psk_kex_mode = TLSEXT_KEX_MODE_FLAG_NONE; + return 1; +} + +int tls_psk_do_binder_ntls(SSL *s, const EVP_MD *md, const unsigned char *msgstart, + size_t binderoffset, const unsigned char *binderin, + unsigned char *binderout, SSL_SESSION *sess, int sign, + int external) +{ + EVP_PKEY *mackey = NULL; + EVP_MD_CTX *mctx = NULL; + unsigned char hash[EVP_MAX_MD_SIZE], binderkey[EVP_MAX_MD_SIZE]; + unsigned char finishedkey[EVP_MAX_MD_SIZE], tmpbinder[EVP_MAX_MD_SIZE]; + unsigned char *early_secret; +# ifdef CHARSET_EBCDIC + static const unsigned char resumption_label[] = { 0x72, 0x65, 0x64, 0x20, 0x62, 0x69, 0x6E, 0x64, 0x65, 0x72, 0x00 }; + static const unsigned char external_label[] = { 0x65, 0x78, 0x74, 0x20, 0x62, 0x69, 0x6E, 0x64, 0x65, 0x72, 0x00 }; +# else + static const unsigned char resumption_label[] = "res binder"; + static const unsigned char external_label[] = "ext binder"; +# endif + const unsigned char *label; + size_t bindersize, labelsize, hashsize; + int hashsizei = EVP_MD_size(md); + int ret = -1; + int usepskfored = 0; + + /* Ensure cast to size_t is safe */ + if (!ossl_assert(hashsizei >= 0)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + hashsize = (size_t)hashsizei; + + if (external + && s->early_data_state == SSL_EARLY_DATA_CONNECTING + && s->session->ext.max_early_data == 0 + && sess->ext.max_early_data > 0) + usepskfored = 1; + + if (external) { + label = external_label; + labelsize = sizeof(external_label) - 1; + } else { + label = resumption_label; + labelsize = sizeof(resumption_label) - 1; + } + + /* + * Generate the early_secret. On the server side we've selected a PSK to + * resume with (internal or external) so we always do this. On the client + * side we do this for a non-external (i.e. resumption) PSK or external PSK + * that will be used for early_data so that it is in place for sending early + * data. For client side external PSK not being used for early_data we + * generate it but store it away for later use. + */ + if (s->server || !external || usepskfored) + early_secret = (unsigned char *)s->early_secret; + else + early_secret = (unsigned char *)sess->early_secret; + + if (!tls13_generate_secret(s, md, NULL, sess->master_key, + sess->master_key_length, early_secret)) { + /* SSLfatal_ntls() already called */ + goto err; + } + + /* + * Create the handshake hash for the binder key...the messages so far are + * empty! + */ + mctx = EVP_MD_CTX_new(); + if (mctx == NULL + || EVP_DigestInit_ex(mctx, md, NULL) <= 0 + || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* Generate the binder key */ + if (!tls13_hkdf_expand(s, md, early_secret, label, labelsize, hash, + hashsize, binderkey, hashsize, 1)) { + /* SSLfatal_ntls() already called */ + goto err; + } + + /* Generate the finished key */ + if (!tls13_derive_finishedkey(s, md, binderkey, finishedkey, hashsize)) { + /* SSLfatal_ntls() already called */ + goto err; + } + + if (EVP_DigestInit_ex(mctx, md, NULL) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * Get a hash of the ClientHello up to the start of the binders. If we are + * following a HelloRetryRequest then this includes the hash of the first + * ClientHello and the HelloRetryRequest itself. + */ + if (s->hello_retry_request == SSL_HRR_PENDING) { + size_t hdatalen; + long hdatalen_l; + void *hdata; + + hdatalen = hdatalen_l = + BIO_get_mem_data(s->s3->handshake_buffer, &hdata); + if (hdatalen_l <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER_NTLS, + SSL_R_BAD_HANDSHAKE_LENGTH); + goto err; + } + + /* + * For servers the handshake buffer data will include the second + * ClientHello - which we don't want - so we need to take that bit off. + */ + if (s->server) { + PACKET hashprefix, msg; + + /* Find how many bytes are left after the first two messages */ + if (!PACKET_buf_init(&hashprefix, hdata, hdatalen) + || !PACKET_forward(&hashprefix, 1) + || !PACKET_get_length_prefixed_3(&hashprefix, &msg) + || !PACKET_forward(&hashprefix, 1) + || !PACKET_get_length_prefixed_3(&hashprefix, &msg)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + hdatalen -= PACKET_remaining(&hashprefix); + } + + if (EVP_DigestUpdate(mctx, hdata, hdatalen) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (EVP_DigestUpdate(mctx, msgstart, binderoffset) <= 0 + || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + mackey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, finishedkey, + hashsize); + if (mackey == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!sign) + binderout = tmpbinder; + + bindersize = hashsize; + if (EVP_DigestSignInit(mctx, NULL, md, NULL, mackey) <= 0 + || EVP_DigestSignUpdate(mctx, hash, hashsize) <= 0 + || EVP_DigestSignFinal(mctx, binderout, &bindersize) <= 0 + || bindersize != hashsize) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (sign) { + ret = 1; + } else { + /* HMAC keys can't do EVP_DigestVerify* - use CRYPTO_memcmp instead */ + ret = (CRYPTO_memcmp(binderin, binderout, hashsize) == 0); + if (!ret) + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PSK_DO_BINDER_NTLS, + SSL_R_BINDER_DOES_NOT_VERIFY); + } + + err: + OPENSSL_cleanse(binderkey, sizeof(binderkey)); + OPENSSL_cleanse(finishedkey, sizeof(finishedkey)); + EVP_PKEY_free(mackey); + EVP_MD_CTX_free(mctx); + + return ret; +} + +static int final_early_data(SSL *s, unsigned int context, int sent) +{ + if (!sent) + return 1; + + if (!s->server) { + if (context == SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS + && sent + && !s->ext.early_data_ok) { + /* + * If we get here then the server accepted our early_data but we + * later realised that it shouldn't have done (e.g. inconsistent + * ALPN) + */ + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_FINAL_EARLY_DATA, + SSL_R_BAD_EARLY_DATA); + return 0; + } + + return 1; + } + + if (s->max_early_data == 0 + || !s->hit + || s->early_data_state != SSL_EARLY_DATA_ACCEPTING + || !s->ext.early_data_ok + || s->hello_retry_request != SSL_HRR_NONE + || (s->allow_early_data_cb != NULL + && !s->allow_early_data_cb(s, + s->allow_early_data_cb_data))) { + s->ext.early_data = SSL_EARLY_DATA_REJECTED; + } else { + s->ext.early_data = SSL_EARLY_DATA_ACCEPTED; + + if (!tls13_change_cipher_state(s, + SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_SERVER_READ)) { + /* SSLfatal_ntls() already called */ + return 0; + } + } + + return 1; +} + +static int final_maxfragmentlen(SSL *s, unsigned int context, int sent) +{ + /* + * Session resumption on server-side with MFL extension active + * BUT MFL extension packet was not resent (i.e. sent == 0) + */ + if (s->server && s->hit && USE_MAX_FRAGMENT_LENGTH_EXT(s->session) + && !sent ) { + SSLfatal_ntls(s, SSL_AD_MISSING_EXTENSION, SSL_F_FINAL_MAXFRAGMENTLEN, + SSL_R_BAD_EXTENSION); + return 0; + } + + /* Current SSL buffer is lower than requested MFL */ + if (s->session && USE_MAX_FRAGMENT_LENGTH_EXT(s->session) + && s->max_send_fragment < GET_MAX_FRAGMENT_LENGTH(s->session)) + /* trigger a larger buffer reallocation */ + if (!ssl3_setup_buffers(s)) { + /* SSLfatal_ntls() already called */ + return 0; + } + + return 1; +} + +static int init_post_handshake_auth(SSL *s, unsigned int context) +{ + s->post_handshake_auth = SSL_PHA_NONE; + + return 1; +} + +#endif diff --git a/ssl/statem_ntls/extensions_clnt.c b/ssl/statem_ntls/extensions_clnt.c new file mode 100644 index 000000000..be7721075 --- /dev/null +++ b/ssl/statem_ntls/extensions_clnt.c @@ -0,0 +1,1909 @@ +/* + * Copyright 2019 The BabaSSL Project Authors. All Rights Reserved. + */ + +# include +# include "ssl_local_ntls.h" +# include "internal/cryptlib.h" +# include "statem_local_ntls.h" + +#if (!defined OPENSSL_NO_NTLS) && (!defined OPENSSL_NO_SM2) \ + && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) +EXT_RETURN tls_construct_ctos_renegotiate_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + /* Add RI if renegotiating */ + if (!s->renegotiate) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_sub_memcpy_u8(pkt, s->s3->previous_client_finished, + s->s3->previous_client_finished_len) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +EXT_RETURN tls_construct_ctos_server_name_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + if (s->ext.hostname == NULL) + return EXT_RETURN_NOT_SENT; + + /* Add TLS extension servername to the Client Hello message */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name) + /* Sub-packet for server_name extension */ + || !WPACKET_start_sub_packet_u16(pkt) + /* Sub-packet for servername list (always 1 hostname)*/ + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_put_bytes_u8(pkt, TLSEXT_NAMETYPE_host_name) + || !WPACKET_sub_memcpy_u16(pkt, s->ext.hostname, + strlen(s->ext.hostname)) + || !WPACKET_close(pkt) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SERVER_NAME_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +/* Push a Max Fragment Len extension into ClientHello */ +EXT_RETURN tls_construct_ctos_maxfragmentlen_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + if (s->ext.max_fragment_len_mode == TLSEXT_max_fragment_length_DISABLED) + return EXT_RETURN_NOT_SENT; + + /* Add Max Fragment Length extension if client enabled it. */ + /*- + * 4 bytes for this extension type and extension length + * 1 byte for the Max Fragment Length code value. + */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_max_fragment_length) + /* Sub-packet for Max Fragment Length extension (1 byte) */ + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_put_bytes_u8(pkt, s->ext.max_fragment_len_mode) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +# ifndef OPENSSL_NO_EC +static int use_ecc(SSL *s) +{ + int i, end, ret = 0; + unsigned long alg_k, alg_a; + STACK_OF(SSL_CIPHER) *cipher_stack = NULL; + + /* See if we support any ECC ciphersuites */ + if (s->version == SSL3_VERSION) + return 0; + + cipher_stack = SSL_get1_supported_ciphers(s); + end = sk_SSL_CIPHER_num(cipher_stack); + for (i = 0; i < end; i++) { + const SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i); + + alg_k = c->algorithm_mkey; + alg_a = c->algorithm_auth; + if ((alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) + || (alg_a & SSL_aECDSA) + || c->min_tls >= TLS1_3_VERSION) { + ret = 1; + break; + } + } + + sk_SSL_CIPHER_free(cipher_stack); + return ret; +} + +EXT_RETURN tls_construct_ctos_ec_pt_formats_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + const unsigned char *pformats; + size_t num_formats; + + if (!use_ecc(s)) + return EXT_RETURN_NOT_SENT; + + /* Add TLS extension ECPointFormats to the ClientHello message */ + tls1_get_formatlist(s, &pformats, &num_formats); + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats) + /* Sub-packet for formats extension */ + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_sub_memcpy_u8(pkt, pformats, num_formats) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +EXT_RETURN tls_construct_ctos_supported_groups_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + const uint16_t *pgroups = NULL; + size_t num_groups = 0, i; + + if (!use_ecc(s)) + return EXT_RETURN_NOT_SENT; + + /* + * Add TLS extension supported_groups to the ClientHello message + */ + /* TODO(TLS1.3): Add support for DHE groups */ + tls1_get_supported_groups(s, &pgroups, &num_groups); + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_groups) + /* Sub-packet for supported_groups extension */ + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + /* Copy curve ID if supported */ + for (i = 0; i < num_groups; i++) { + uint16_t ctmp = pgroups[i]; + + if (tls_curve_allowed(s, ctmp, SSL_SECOP_CURVE_SUPPORTED)) { + if (!WPACKET_put_bytes_u16(pkt, ctmp)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + } + } + if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} +# endif + +EXT_RETURN tls_construct_ctos_session_ticket_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + size_t ticklen; + + if (!tls_use_ticket(s)) + return EXT_RETURN_NOT_SENT; + + if (!s->new_session && s->session != NULL + && s->session->ext.tick != NULL + && s->session->ssl_version != TLS1_3_VERSION) { + ticklen = s->session->ext.ticklen; + } else if (s->session && s->ext.session_ticket != NULL + && s->ext.session_ticket->data != NULL) { + ticklen = s->ext.session_ticket->length; + s->session->ext.tick = OPENSSL_malloc(ticklen); + if (s->session->ext.tick == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + memcpy(s->session->ext.tick, + s->ext.session_ticket->data, ticklen); + s->session->ext.ticklen = ticklen; + } else { + ticklen = 0; + } + + if (ticklen == 0 && s->ext.session_ticket != NULL && + s->ext.session_ticket->data == NULL) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket) + || !WPACKET_sub_memcpy_u16(pkt, s->session->ext.tick, ticklen)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +EXT_RETURN tls_construct_ctos_sig_algs_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + size_t salglen; + const uint16_t *salg; + + if (!SSL_CLIENT_USE_SIGALGS_NTLS(s)) + return EXT_RETURN_NOT_SENT; + + salglen = tls12_get_psigalgs(s, 1, &salg); + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signature_algorithms) + /* Sub-packet for sig-algs extension */ + || !WPACKET_start_sub_packet_u16(pkt) + /* Sub-packet for the actual list */ + || !WPACKET_start_sub_packet_u16(pkt) + || !tls12_copy_sigalgs(s, pkt, salg, salglen) + || !WPACKET_close(pkt) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SIG_ALGS_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +# ifndef OPENSSL_NO_OCSP +EXT_RETURN tls_construct_ctos_status_request_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + int i; + + /* This extension isn't defined for client Certificates */ + if (x != NULL) + return EXT_RETURN_NOT_SENT; + + if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request) + /* Sub-packet for status request extension */ + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_put_bytes_u8(pkt, TLSEXT_STATUSTYPE_ocsp) + /* Sub-packet for the ids */ + || !WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + for (i = 0; i < sk_OCSP_RESPID_num(s->ext.ocsp.ids); i++) { + unsigned char *idbytes; + OCSP_RESPID *id = sk_OCSP_RESPID_value(s->ext.ocsp.ids, i); + int idlen = i2d_OCSP_RESPID(id, NULL); + + if (idlen <= 0 + /* Sub-packet for an individual id */ + || !WPACKET_sub_allocate_bytes_u16(pkt, idlen, &idbytes) + || i2d_OCSP_RESPID(id, &idbytes) != idlen) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + } + if (!WPACKET_close(pkt) + || !WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + if (s->ext.ocsp.exts) { + unsigned char *extbytes; + int extlen = i2d_X509_EXTENSIONS(s->ext.ocsp.exts, NULL); + + if (extlen < 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + if (!WPACKET_allocate_bytes(pkt, extlen, &extbytes) + || i2d_X509_EXTENSIONS(s->ext.ocsp.exts, &extbytes) + != extlen) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + } + if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} +# endif + +# ifndef OPENSSL_NO_NEXTPROTONEG +EXT_RETURN tls_construct_ctos_npn_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (s->ctx->ext.npn_select_cb == NULL || !SSL_IS_FIRST_HANDSHAKE(s)) + return EXT_RETURN_NOT_SENT; + + /* + * The client advertises an empty extension to indicate its support + * for Next Protocol Negotiation + */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg) + || !WPACKET_put_bytes_u16(pkt, 0)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_NPN_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} +# endif + +EXT_RETURN tls_construct_ctos_alpn_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + s->s3->alpn_sent = 0; + + if (s->ext.alpn == NULL || !SSL_IS_FIRST_HANDSHAKE(s)) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, + TLSEXT_TYPE_application_layer_protocol_negotiation) + /* Sub-packet ALPN extension */ + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_sub_memcpy_u16(pkt, s->ext.alpn, s->ext.alpn_len) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_ALPN_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + s->s3->alpn_sent = 1; + + return EXT_RETURN_SENT; +} + + +# ifndef OPENSSL_NO_SRTP +EXT_RETURN tls_construct_ctos_use_srtp_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + STACK_OF(SRTP_PROTECTION_PROFILE) *clnt = SSL_get_srtp_profiles(s); + int i, end; + + if (clnt == NULL) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_use_srtp) + /* Sub-packet for SRTP extension */ + || !WPACKET_start_sub_packet_u16(pkt) + /* Sub-packet for the protection profile list */ + || !WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + end = sk_SRTP_PROTECTION_PROFILE_num(clnt); + for (i = 0; i < end; i++) { + const SRTP_PROTECTION_PROFILE *prof = + sk_SRTP_PROTECTION_PROFILE_value(clnt, i); + + if (prof == NULL || !WPACKET_put_bytes_u16(pkt, prof->id)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + } + if (!WPACKET_close(pkt) + /* Add an empty use_mki value */ + || !WPACKET_put_bytes_u8(pkt, 0) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} +# endif + +EXT_RETURN tls_construct_ctos_etm_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (s->options & SSL_OP_NO_ENCRYPT_THEN_MAC) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac) + || !WPACKET_put_bytes_u16(pkt, 0)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_ETM_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +# ifndef OPENSSL_NO_CT +EXT_RETURN tls_construct_ctos_sct_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (s->ct_validation_callback == NULL) + return EXT_RETURN_NOT_SENT; + + /* Not defined for client Certificates */ + if (x != NULL) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signed_certificate_timestamp) + || !WPACKET_put_bytes_u16(pkt, 0)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SCT_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} +# endif + +EXT_RETURN tls_construct_ctos_ems_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret) + || !WPACKET_put_bytes_u16(pkt, 0)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EMS_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +EXT_RETURN tls_construct_ctos_supported_versions_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + int currv, min_version, max_version, reason; + + reason = ssl_get_min_max_version_ntls(s, &min_version, &max_version, NULL); + if (reason != 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS_NTLS, reason); + return EXT_RETURN_FAIL; + } + + if (min_version == NTLS_VERSION) { + min_version = SSL3_VERSION; + } + + /* + * Don't include this if we can't negotiate TLSv1.3. We can do a straight + * comparison here because we will never be called in DTLS. + */ + if (max_version < TLS1_3_VERSION) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_start_sub_packet_u8(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + for (currv = max_version; currv >= min_version; currv--) { + if (!WPACKET_put_bytes_u16(pkt, currv)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + } + if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +/* + * Construct a psk_kex_modes extension. + */ +EXT_RETURN tls_construct_ctos_psk_kex_modes_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ +# ifndef OPENSSL_NO_TLS1_3 + int nodhe = s->options & SSL_OP_ALLOW_NO_DHE_KEX; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk_kex_modes) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_start_sub_packet_u8(pkt) + || !WPACKET_put_bytes_u8(pkt, TLSEXT_KEX_MODE_KE_DHE) + || (nodhe && !WPACKET_put_bytes_u8(pkt, TLSEXT_KEX_MODE_KE)) + || !WPACKET_close(pkt) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + s->ext.psk_kex_mode = TLSEXT_KEX_MODE_FLAG_KE_DHE; + if (nodhe) + s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE; +# endif + + return EXT_RETURN_SENT; +} + +# ifndef OPENSSL_NO_TLS1_3 +static int add_key_share(SSL *s, WPACKET *pkt, unsigned int curve_id) +{ + unsigned char *encoded_point = NULL; + EVP_PKEY *key_share_key = NULL; + size_t encodedlen; + + if (s->s3->tmp.pkey != NULL) { + if (!ossl_assert(s->hello_retry_request == SSL_HRR_PENDING)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE, + ERR_R_INTERNAL_ERROR); + return 0; + } + /* + * Could happen if we got an HRR that wasn't requesting a new key_share + */ + key_share_key = s->s3->tmp.pkey; + } else { + key_share_key = ssl_generate_pkey_group(s, curve_id); + if (key_share_key == NULL) { + /* SSLfatal_ntls() already called */ + return 0; + } + } + + /* Encode the public key. */ + encodedlen = EVP_PKEY_get1_tls_encodedpoint(key_share_key, + &encoded_point); + if (encodedlen == 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE, ERR_R_EC_LIB); + goto err; + } + + /* Create KeyShareEntry */ + if (!WPACKET_put_bytes_u16(pkt, curve_id) + || !WPACKET_sub_memcpy_u16(pkt, encoded_point, encodedlen)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * TODO(TLS1.3): When changing to send more than one key_share we're + * going to need to be able to save more than one EVP_PKEY. For now + * we reuse the existing tmp.pkey + */ + s->s3->tmp.pkey = key_share_key; + s->s3->group_id = curve_id; + OPENSSL_free(encoded_point); + + return 1; + err: + if (s->s3->tmp.pkey == NULL) + EVP_PKEY_free(key_share_key); + OPENSSL_free(encoded_point); + return 0; +} +# endif + +EXT_RETURN tls_construct_ctos_key_share_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ +# ifndef OPENSSL_NO_TLS1_3 + size_t i, num_groups = 0; + const uint16_t *pgroups = NULL; + uint16_t curve_id = 0; + + /* key_share extension */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share) + /* Extension data sub-packet */ + || !WPACKET_start_sub_packet_u16(pkt) + /* KeyShare list sub-packet */ + || !WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + tls1_get_supported_groups(s, &pgroups, &num_groups); + + /* + * TODO(TLS1.3): Make the number of key_shares sent configurable. For + * now, just send one + */ + if (s->s3->group_id != 0) { + curve_id = s->s3->group_id; + } else { + for (i = 0; i < num_groups; i++) { + + if (!tls_curve_allowed(s, pgroups[i], SSL_SECOP_CURVE_SUPPORTED)) + continue; + + curve_id = pgroups[i]; + break; + } + } + + if (curve_id == 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE_NTLS, + SSL_R_NO_SUITABLE_KEY_SHARE); + return EXT_RETURN_FAIL; + } + + if (!add_key_share(s, pkt, curve_id)) { + /* SSLfatal_ntls() already called */ + return EXT_RETURN_FAIL; + } + + if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + return EXT_RETURN_SENT; +# else + return EXT_RETURN_NOT_SENT; +# endif +} + +EXT_RETURN tls_construct_ctos_cookie_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + EXT_RETURN ret = EXT_RETURN_FAIL; + + /* Should only be set if we've had an HRR */ + if (s->ext.tls13_cookie_len == 0) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_cookie) + /* Extension data sub-packet */ + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_sub_memcpy_u16(pkt, s->ext.tls13_cookie, + s->ext.tls13_cookie_len) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_COOKIE_NTLS, + ERR_R_INTERNAL_ERROR); + goto end; + } + + ret = EXT_RETURN_SENT; + end: + OPENSSL_free(s->ext.tls13_cookie); + s->ext.tls13_cookie = NULL; + s->ext.tls13_cookie_len = 0; + + return ret; +} + +EXT_RETURN tls_construct_ctos_early_data_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + const unsigned char *id = NULL; + size_t idlen = 0; + SSL_SESSION *psksess = NULL; + SSL_SESSION *edsess = NULL; + const EVP_MD *handmd = NULL; + + if (s->hello_retry_request == SSL_HRR_PENDING) + handmd = ssl_handshake_md(s); + + if (s->psk_use_session_cb != NULL + && (!s->psk_use_session_cb(s, handmd, &id, &idlen, &psksess) + || (psksess != NULL + && psksess->ssl_version != TLS1_3_VERSION))) { + SSL_SESSION_free(psksess); + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA_NTLS, + SSL_R_BAD_PSK); + return EXT_RETURN_FAIL; + } + + SSL_SESSION_free(s->psksession); + s->psksession = psksess; + if (psksess != NULL) { + OPENSSL_free(s->psksession_id); + s->psksession_id = OPENSSL_memdup(id, idlen); + if (s->psksession_id == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + s->psksession_id_len = idlen; + } + + if (s->early_data_state != SSL_EARLY_DATA_CONNECTING + || (s->session->ext.max_early_data == 0 + && (psksess == NULL || psksess->ext.max_early_data == 0))) { + s->max_early_data = 0; + return EXT_RETURN_NOT_SENT; + } + edsess = s->session->ext.max_early_data != 0 ? s->session : psksess; + s->max_early_data = edsess->ext.max_early_data; + + if (edsess->ext.hostname != NULL) { + if (s->ext.hostname == NULL + || (s->ext.hostname != NULL + && strcmp(s->ext.hostname, edsess->ext.hostname) != 0)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA_NTLS, + SSL_R_INCONSISTENT_EARLY_DATA_SNI); + return EXT_RETURN_FAIL; + } + } + + if ((s->ext.alpn == NULL && edsess->ext.alpn_selected != NULL)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA_NTLS, + SSL_R_INCONSISTENT_EARLY_DATA_ALPN); + return EXT_RETURN_FAIL; + } + + /* + * Verify that we are offering an ALPN protocol consistent with the early + * data. + */ + if (edsess->ext.alpn_selected != NULL) { + PACKET prots, alpnpkt; + int found = 0; + + if (!PACKET_buf_init(&prots, s->ext.alpn, s->ext.alpn_len)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + while (PACKET_get_length_prefixed_1(&prots, &alpnpkt)) { + if (PACKET_equal(&alpnpkt, edsess->ext.alpn_selected, + edsess->ext.alpn_selected_len)) { + found = 1; + break; + } + } + if (!found) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA_NTLS, + SSL_R_INCONSISTENT_EARLY_DATA_ALPN); + return EXT_RETURN_FAIL; + } + } + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + /* + * We set this to rejected here. Later, if the server acknowledges the + * extension, we set it to accepted. + */ + s->ext.early_data = SSL_EARLY_DATA_REJECTED; + s->ext.early_data_ok = 1; + + return EXT_RETURN_SENT; +} + +# define F5_WORKAROUND_MIN_MSG_LEN 0xff +# define F5_WORKAROUND_MAX_MSG_LEN 0x200 + +/* + * PSK pre binder overhead = + * 2 bytes for TLSEXT_TYPE_psk + * 2 bytes for extension length + * 2 bytes for identities list length + * 2 bytes for identity length + * 4 bytes for obfuscated_ticket_age + * 2 bytes for binder list length + * 1 byte for binder length + * The above excludes the number of bytes for the identity itself and the + * subsequent binder bytes + */ +# define PSK_PRE_BINDER_OVERHEAD (2 + 2 + 2 + 2 + 4 + 2 + 1) + +EXT_RETURN tls_construct_ctos_padding_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + unsigned char *padbytes; + size_t hlen; + + if ((s->options & SSL_OP_TLSEXT_PADDING) == 0) + return EXT_RETURN_NOT_SENT; + + /* + * Add padding to workaround bugs in F5 terminators. See RFC7685. + * This code calculates the length of all extensions added so far but + * excludes the PSK extension (because that MUST be written last). Therefore + * this extension MUST always appear second to last. + */ + if (!WPACKET_get_total_written(pkt, &hlen)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PADDING_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + /* + * If we're going to send a PSK then that will be written out after this + * extension, so we need to calculate how long it is going to be. + */ + if (s->session->ssl_version == TLS1_3_VERSION + && s->session->ext.ticklen != 0 + && s->session->cipher != NULL) { + const EVP_MD *md = ssl_md(s->session->cipher->algorithm2); + + if (md != NULL) { + /* + * Add the fixed PSK overhead, the identity length and the binder + * length. + */ + hlen += PSK_PRE_BINDER_OVERHEAD + s->session->ext.ticklen + + EVP_MD_size(md); + } + } + + if (hlen > F5_WORKAROUND_MIN_MSG_LEN && hlen < F5_WORKAROUND_MAX_MSG_LEN) { + /* Calculate the amount of padding we need to add */ + hlen = F5_WORKAROUND_MAX_MSG_LEN - hlen; + + /* + * Take off the size of extension header itself (2 bytes for type and + * 2 bytes for length bytes), but ensure that the extension is at least + * 1 byte long so as not to have an empty extension last (WebSphere 7.x, + * 8.x are intolerant of that condition) + */ + if (hlen > 4) + hlen -= 4; + else + hlen = 1; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_padding) + || !WPACKET_sub_allocate_bytes_u16(pkt, hlen, &padbytes)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PADDING_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + memset(padbytes, 0, hlen); + } + + return EXT_RETURN_SENT; +} + +/* + * Construct the pre_shared_key extension + */ +EXT_RETURN tls_construct_ctos_psk_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ +# ifndef OPENSSL_NO_TLS1_3 + uint32_t now, agesec, agems = 0; + size_t reshashsize = 0, pskhashsize = 0, binderoffset, msglen; + unsigned char *resbinder = NULL, *pskbinder = NULL, *msgstart = NULL; + const EVP_MD *handmd = NULL, *mdres = NULL, *mdpsk = NULL; + int dores = 0; + + s->ext.tick_identity = 0; + + /* + * Note: At this stage of the code we only support adding a single + * resumption PSK. If we add support for multiple PSKs then the length + * calculations in the padding extension will need to be adjusted. + */ + + /* + * If this is an incompatible or new session then we have nothing to resume + * so don't add this extension. + */ + if (s->session->ssl_version != TLS1_3_VERSION + || (s->session->ext.ticklen == 0 && s->psksession == NULL)) + return EXT_RETURN_NOT_SENT; + + if (s->hello_retry_request == SSL_HRR_PENDING) + handmd = ssl_handshake_md(s); + + if (s->session->ext.ticklen != 0) { + /* Get the digest associated with the ciphersuite in the session */ + if (s->session->cipher == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + mdres = ssl_md(s->session->cipher->algorithm2); + if (mdres == NULL) { + /* + * Don't recognize this cipher so we can't use the session. + * Ignore it + */ + goto dopsksess; + } + + if (s->hello_retry_request == SSL_HRR_PENDING && mdres != handmd) { + /* + * Selected ciphersuite hash does not match the hash for the session + * so we can't use it. + */ + goto dopsksess; + } + + /* + * Technically the C standard just says time() returns a time_t and says + * nothing about the encoding of that type. In practice most + * implementations follow POSIX which holds it as an integral type in + * seconds since epoch. We've already made the assumption that we can do + * this in multiple places in the code, so portability shouldn't be an + * issue. + */ + now = (uint32_t)time(NULL); + agesec = now - (uint32_t)s->session->time; + /* + * We calculate the age in seconds but the server may work in ms. Due to + * rounding errors we could overestimate the age by up to 1s. It is + * better to underestimate it. Otherwise, if the RTT is very short, when + * the server calculates the age reported by the client it could be + * bigger than the age calculated on the server - which should never + * happen. + */ + if (agesec > 0) + agesec--; + + if (s->session->ext.tick_lifetime_hint < agesec) { + /* Ticket is too old. Ignore it. */ + goto dopsksess; + } + + /* + * Calculate age in ms. We're just doing it to nearest second. Should be + * good enough. + */ + agems = agesec * (uint32_t)1000; + + if (agesec != 0 && agems / (uint32_t)1000 != agesec) { + /* + * Overflow. Shouldn't happen unless this is a *really* old session. + * If so we just ignore it. + */ + goto dopsksess; + } + + /* + * Obfuscate the age. Overflow here is fine, this addition is supposed + * to be mod 2^32. + */ + agems += s->session->ext.tick_age_add; + + reshashsize = EVP_MD_size(mdres); + s->ext.tick_identity++; + dores = 1; + } + + dopsksess: + if (!dores && s->psksession == NULL) + return EXT_RETURN_NOT_SENT; + + if (s->psksession != NULL) { + mdpsk = ssl_md(s->psksession->cipher->algorithm2); + if (mdpsk == NULL) { + /* + * Don't recognize this cipher so we can't use the session. + * If this happens it's an application bug. + */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK_NTLS, + SSL_R_BAD_PSK); + return EXT_RETURN_FAIL; + } + + if (s->hello_retry_request == SSL_HRR_PENDING && mdpsk != handmd) { + /* + * Selected ciphersuite hash does not match the hash for the PSK + * session. This is an application bug. + */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK_NTLS, + SSL_R_BAD_PSK); + return EXT_RETURN_FAIL; + } + + pskhashsize = EVP_MD_size(mdpsk); + } + + /* Create the extension, but skip over the binder for now */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + if (dores) { + if (!WPACKET_sub_memcpy_u16(pkt, s->session->ext.tick, + s->session->ext.ticklen) + || !WPACKET_put_bytes_u32(pkt, agems)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + } + + if (s->psksession != NULL) { + if (!WPACKET_sub_memcpy_u16(pkt, s->psksession_id, + s->psksession_id_len) + || !WPACKET_put_bytes_u32(pkt, 0)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + s->ext.tick_identity++; + } + + if (!WPACKET_close(pkt) + || !WPACKET_get_total_written(pkt, &binderoffset) + || !WPACKET_start_sub_packet_u16(pkt) + || (dores + && !WPACKET_sub_allocate_bytes_u8(pkt, reshashsize, &resbinder)) + || (s->psksession != NULL + && !WPACKET_sub_allocate_bytes_u8(pkt, pskhashsize, &pskbinder)) + || !WPACKET_close(pkt) + || !WPACKET_close(pkt) + || !WPACKET_get_total_written(pkt, &msglen) + /* + * We need to fill in all the sub-packet lengths now so we can + * calculate the HMAC of the message up to the binders + */ + || !WPACKET_fill_lengths(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + msgstart = WPACKET_get_curr(pkt) - msglen; + + if (dores + && tls_psk_do_binder_ntls(s, mdres, msgstart, binderoffset, NULL, + resbinder, s->session, 1, 0) != 1) { + /* SSLfatal_ntls() already called */ + return EXT_RETURN_FAIL; + } + + if (s->psksession != NULL + && tls_psk_do_binder_ntls(s, mdpsk, msgstart, binderoffset, NULL, + pskbinder, s->psksession, 1, 1) != 1) { + /* SSLfatal_ntls() already called */ + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +# else + return EXT_RETURN_NOT_SENT; +# endif +} + +EXT_RETURN tls_construct_ctos_post_handshake_auth_ntls(SSL *s, WPACKET *pkt, + unsigned int context, + X509 *x, size_t chainidx) +{ +# ifndef OPENSSL_NO_TLS1_3 + if (!s->pha_enabled) + return EXT_RETURN_NOT_SENT; + + /* construct extension - 0 length, no contents */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_post_handshake_auth) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + s->post_handshake_auth = SSL_PHA_EXT_SENT; + + return EXT_RETURN_SENT; +# else + return EXT_RETURN_NOT_SENT; +# endif +} + + +/* + * Parse the server's renegotiation binding and abort if it's not right + */ +int tls_parse_stoc_renegotiate_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + size_t expected_len = s->s3->previous_client_finished_len + + s->s3->previous_server_finished_len; + size_t ilen; + const unsigned char *data; + + /* Check for logic errors */ + if (!ossl_assert(expected_len == 0 + || s->s3->previous_client_finished_len != 0) + || !ossl_assert(expected_len == 0 + || s->s3->previous_server_finished_len != 0)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* Parse the length byte */ + if (!PACKET_get_1_len(pkt, &ilen)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE_NTLS, + SSL_R_RENEGOTIATION_ENCODING_ERR); + return 0; + } + + /* Consistency check */ + if (PACKET_remaining(pkt) != ilen) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE_NTLS, + SSL_R_RENEGOTIATION_ENCODING_ERR); + return 0; + } + + /* Check that the extension matches */ + if (ilen != expected_len) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE_NTLS, + SSL_R_RENEGOTIATION_MISMATCH); + return 0; + } + + if (!PACKET_get_bytes(pkt, &data, s->s3->previous_client_finished_len) + || memcmp(data, s->s3->previous_client_finished, + s->s3->previous_client_finished_len) != 0) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE_NTLS, + SSL_R_RENEGOTIATION_MISMATCH); + return 0; + } + + if (!PACKET_get_bytes(pkt, &data, s->s3->previous_server_finished_len) + || memcmp(data, s->s3->previous_server_finished, + s->s3->previous_server_finished_len) != 0) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE_NTLS, + SSL_R_RENEGOTIATION_MISMATCH); + return 0; + } + s->s3->send_connection_binding = 1; + + return 1; +} + +/* Parse the server's max fragment len extension packet */ +int tls_parse_stoc_maxfragmentlen_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + unsigned int value; + + if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + + /* |value| should contains a valid max-fragment-length code. */ + if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN_NTLS, + SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH); + return 0; + } + + /* Must be the same value as client-configured one who was sent to server */ + /*- + * RFC 6066: if a client receives a maximum fragment length negotiation + * response that differs from the length it requested, ... + * It must abort with SSL_AD_ILLEGAL_PARAMETER alert + */ + if (value != s->ext.max_fragment_len_mode) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN_NTLS, + SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH); + return 0; + } + + /* + * Maximum Fragment Length Negotiation succeeded. + * The negotiated Maximum Fragment Length is binding now. + */ + s->session->ext.max_fragment_len_mode = value; + + return 1; +} + +int tls_parse_stoc_server_name_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (s->ext.hostname == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (PACKET_remaining(pkt) > 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + + if (!s->hit) { + if (s->session->ext.hostname != NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + s->session->ext.hostname = OPENSSL_strdup(s->ext.hostname); + if (s->session->ext.hostname == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + + return 1; +} + +# ifndef OPENSSL_NO_EC +int tls_parse_stoc_ec_pt_formats_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + size_t ecpointformats_len; + PACKET ecptformatlist; + + if (!PACKET_as_length_prefixed_1(pkt, &ecptformatlist)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + if (!s->hit) { + ecpointformats_len = PACKET_remaining(&ecptformatlist); + if (ecpointformats_len == 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS_NTLS, SSL_R_BAD_LENGTH); + return 0; + } + + s->ext.peer_ecpointformats_len = 0; + OPENSSL_free(s->ext.peer_ecpointformats); + s->ext.peer_ecpointformats = OPENSSL_malloc(ecpointformats_len); + if (s->ext.peer_ecpointformats == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS_NTLS, ERR_R_INTERNAL_ERROR); + return 0; + } + + s->ext.peer_ecpointformats_len = ecpointformats_len; + + if (!PACKET_copy_bytes(&ecptformatlist, + s->ext.peer_ecpointformats, + ecpointformats_len)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS_NTLS, ERR_R_INTERNAL_ERROR); + return 0; + } + } + + return 1; +} +# endif + +int tls_parse_stoc_session_ticket_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (s->ext.session_ticket_cb != NULL && + !s->ext.session_ticket_cb(s, PACKET_data(pkt), + PACKET_remaining(pkt), + s->ext.session_ticket_cb_arg)) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_PARSE_STOC_SESSION_TICKET_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + + if (!tls_use_ticket(s)) { + SSLfatal_ntls(s, SSL_AD_UNSUPPORTED_EXTENSION, + SSL_F_TLS_PARSE_STOC_SESSION_TICKET_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + if (PACKET_remaining(pkt) > 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_STOC_SESSION_TICKET_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + + s->ext.ticket_expected = 1; + + return 1; +} + +# ifndef OPENSSL_NO_OCSP +int tls_parse_stoc_status_request_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (context == SSL_EXT_TLS1_3_CERTIFICATE_REQUEST) { + /* We ignore this if the server sends a CertificateRequest */ + /* TODO(TLS1.3): Add support for this */ + return 1; + } + + /* + * MUST only be sent if we've requested a status + * request message. In TLS <= 1.2 it must also be empty. + */ + if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp) { + SSLfatal_ntls(s, SSL_AD_UNSUPPORTED_EXTENSION, + SSL_F_TLS_PARSE_STOC_STATUS_REQUEST_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + if (PACKET_remaining(pkt) > 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_STOC_STATUS_REQUEST_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + + /* Set flag to expect CertificateStatus message */ + s->ext.status_expected = 1; + + return 1; +} +# endif + + +# ifndef OPENSSL_NO_CT +int tls_parse_stoc_sct_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + if (context == SSL_EXT_TLS1_3_CERTIFICATE_REQUEST) { + /* We ignore this if the server sends it in a CertificateRequest */ + /* TODO(TLS1.3): Add support for this */ + return 1; + } + + /* + * Only take it if we asked for it - i.e if there is no CT validation + * callback set, then a custom extension MAY be processing it, so we + * need to let control continue to flow to that. + */ + if (s->ct_validation_callback != NULL) { + size_t size = PACKET_remaining(pkt); + + /* Simply copy it off for later processing */ + OPENSSL_free(s->ext.scts); + s->ext.scts = NULL; + + s->ext.scts_len = (uint16_t)size; + if (size > 0) { + s->ext.scts = OPENSSL_malloc(size); + if (s->ext.scts == NULL + || !PACKET_copy_bytes(pkt, s->ext.scts, size)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SCT_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + } else { + ENDPOINT role = (context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0 + ? ENDPOINT_CLIENT : ENDPOINT_BOTH; + + /* + * If we didn't ask for it then there must be a custom extension, + * otherwise this is unsolicited. + */ + if (custom_ext_find_ntls(&s->cert->custext, role, + TLSEXT_TYPE_signed_certificate_timestamp, + NULL) == NULL) { + SSLfatal_ntls(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_SCT_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + + if (!custom_ext_parse_ntls(s, context, + TLSEXT_TYPE_signed_certificate_timestamp, + PACKET_data(pkt), PACKET_remaining(pkt), + x, chainidx)) { + /* SSLfatal_ntls already called */ + return 0; + } + } + + return 1; +} +# endif + + +# ifndef OPENSSL_NO_NEXTPROTONEG +/* + * ssl_next_proto_validate validates a Next Protocol Negotiation block. No + * elements of zero length are allowed and the set of elements must exactly + * fill the length of the block. Returns 1 on success or 0 on failure. + */ +static int ssl_next_proto_validate(SSL *s, PACKET *pkt) +{ + PACKET tmp_protocol; + + while (PACKET_remaining(pkt)) { + if (!PACKET_get_length_prefixed_1(pkt, &tmp_protocol) + || PACKET_remaining(&tmp_protocol) == 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_SSL_NEXT_PROTO_VALIDATE, + SSL_R_BAD_EXTENSION); + return 0; + } + } + + return 1; +} + +int tls_parse_stoc_npn_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + unsigned char *selected; + unsigned char selected_len; + PACKET tmppkt; + + /* Check if we are in a renegotiation. If so ignore this extension */ + if (!SSL_IS_FIRST_HANDSHAKE(s)) + return 1; + + /* We must have requested it. */ + if (s->ctx->ext.npn_select_cb == NULL) { + SSLfatal_ntls(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_NPN_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + + /* The data must be valid */ + tmppkt = *pkt; + if (!ssl_next_proto_validate(s, &tmppkt)) { + /* SSLfatal_ntls() already called */ + return 0; + } + if (s->ctx->ext.npn_select_cb(s, &selected, &selected_len, + PACKET_data(pkt), + PACKET_remaining(pkt), + s->ctx->ext.npn_select_cb_arg) != + SSL_TLSEXT_ERR_OK) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_STOC_NPN_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + + /* + * Could be non-NULL if server has sent multiple NPN extensions in + * a single Serverhello + */ + OPENSSL_free(s->ext.npn); + s->ext.npn = OPENSSL_malloc(selected_len); + if (s->ext.npn == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_NPN_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + memcpy(s->ext.npn, selected, selected_len); + s->ext.npn_len = selected_len; + s->s3->npn_seen = 1; + + return 1; +} +# endif + +int tls_parse_stoc_alpn_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + size_t len; + + /* We must have requested it. */ + if (!s->s3->alpn_sent) { + SSLfatal_ntls(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_ALPN_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + /*- + * The extension data consists of: + * uint16 list_length + * uint8 proto_length; + * uint8 proto[proto_length]; + */ + if (!PACKET_get_net_2_len(pkt, &len) + || PACKET_remaining(pkt) != len || !PACKET_get_1_len(pkt, &len) + || PACKET_remaining(pkt) != len) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_ALPN_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + OPENSSL_free(s->s3->alpn_selected); + s->s3->alpn_selected = OPENSSL_malloc(len); + if (s->s3->alpn_selected == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + if (!PACKET_copy_bytes(pkt, s->s3->alpn_selected, len)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_ALPN_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + s->s3->alpn_selected_len = len; + + if (s->session->ext.alpn_selected == NULL + || s->session->ext.alpn_selected_len != len + || memcmp(s->session->ext.alpn_selected, s->s3->alpn_selected, len) + != 0) { + /* ALPN not consistent with the old session so cannot use early_data */ + s->ext.early_data_ok = 0; + } + if (!s->hit) { + /* + * This is a new session and so alpn_selected should have been + * initialised to NULL. We should update it with the selected ALPN. + */ + if (!ossl_assert(s->session->ext.alpn_selected == NULL)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + s->session->ext.alpn_selected = + OPENSSL_memdup(s->s3->alpn_selected, s->s3->alpn_selected_len); + if (s->session->ext.alpn_selected == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + s->session->ext.alpn_selected_len = s->s3->alpn_selected_len; + } + + return 1; +} + +# ifndef OPENSSL_NO_SRTP +int tls_parse_stoc_use_srtp_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + unsigned int id, ct, mki; + int i; + STACK_OF(SRTP_PROTECTION_PROFILE) *clnt; + SRTP_PROTECTION_PROFILE *prof; + + if (!PACKET_get_net_2(pkt, &ct) || ct != 2 + || !PACKET_get_net_2(pkt, &id) + || !PACKET_get_1(pkt, &mki) + || PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP_NTLS, + SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + return 0; + } + + if (mki != 0) { + /* Must be no MKI, since we never offer one */ + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_USE_SRTP_NTLS, + SSL_R_BAD_SRTP_MKI_VALUE); + return 0; + } + + /* Throw an error if the server gave us an unsolicited extension */ + clnt = SSL_get_srtp_profiles(s); + if (clnt == NULL) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP_NTLS, + SSL_R_NO_SRTP_PROFILES); + return 0; + } + + /* + * Check to see if the server gave us something we support (and + * presumably offered) + */ + for (i = 0; i < sk_SRTP_PROTECTION_PROFILE_num(clnt); i++) { + prof = sk_SRTP_PROTECTION_PROFILE_value(clnt, i); + + if (prof->id == id) { + s->srtp_profile = prof; + return 1; + } + } + + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP_NTLS, + SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + return 0; +} +# endif + +int tls_parse_stoc_etm_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + /* Ignore if inappropriate ciphersuite */ + if (!(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC) + && s->s3->tmp.new_cipher->algorithm_mac != SSL_AEAD + && s->s3->tmp.new_cipher->algorithm_enc != SSL_RC4) + s->ext.use_etm = 1; + + return 1; +} + +int tls_parse_stoc_ems_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS; + if (!s->hit) + s->session->flags |= SSL_SESS_FLAG_EXTMS; + + return 1; +} + +int tls_parse_stoc_supported_versions_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + unsigned int version; + + if (!PACKET_get_net_2(pkt, &version) + || PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS_NTLS, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + /* + * The only protocol version we support which is valid in this extension in + * a ServerHello is TLSv1.3 therefore we shouldn't be getting anything else. + */ + if (version != TLS1_3_VERSION) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS_NTLS, + SSL_R_BAD_PROTOCOL_VERSION_NUMBER); + return 0; + } + + /* We ignore this extension for HRRs except to sanity check it */ + if (context == SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) + return 1; + + /* We just set it here. We validate it in ssl_choose_client_version_ntls */ + s->version = version; + + return 1; +} + +int tls_parse_stoc_key_share_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ +# ifndef OPENSSL_NO_TLS1_3 + unsigned int group_id; + PACKET encoded_pt; + EVP_PKEY *ckey = s->s3->tmp.pkey, *skey = NULL; + + /* Sanity check */ + if (ckey == NULL || s->s3->peer_tmp != NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!PACKET_get_net_2(pkt, &group_id)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE_NTLS, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + if ((context & SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0) { + const uint16_t *pgroups = NULL; + size_t i, num_groups; + + if (PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE_NTLS, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + /* + * It is an error if the HelloRetryRequest wants a key_share that we + * already sent in the first ClientHello + */ + if (group_id == s->s3->group_id) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_STOC_KEY_SHARE_NTLS, SSL_R_BAD_KEY_SHARE); + return 0; + } + + /* Validate the selected group is one we support */ + tls1_get_supported_groups(s, &pgroups, &num_groups); + for (i = 0; i < num_groups; i++) { + if (group_id == pgroups[i]) + break; + } + if (i >= num_groups + || !tls_curve_allowed(s, group_id, SSL_SECOP_CURVE_SUPPORTED)) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_STOC_KEY_SHARE_NTLS, SSL_R_BAD_KEY_SHARE); + return 0; + } + + s->s3->group_id = group_id; + EVP_PKEY_free(s->s3->tmp.pkey); + s->s3->tmp.pkey = NULL; + return 1; + } + + if (group_id != s->s3->group_id) { + /* + * This isn't for the group that we sent in the original + * key_share! + */ + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_KEY_SHARE_NTLS, + SSL_R_BAD_KEY_SHARE); + return 0; + } + + if (!PACKET_as_length_prefixed_2(pkt, &encoded_pt) + || PACKET_remaining(&encoded_pt) == 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE_NTLS, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + skey = EVP_PKEY_new(); + if (skey == NULL || EVP_PKEY_copy_parameters(skey, ckey) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE_NTLS, + ERR_R_MALLOC_FAILURE); + return 0; + } + if (!EVP_PKEY_set1_tls_encodedpoint(skey, PACKET_data(&encoded_pt), + PACKET_remaining(&encoded_pt))) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_KEY_SHARE_NTLS, + SSL_R_BAD_ECPOINT); + EVP_PKEY_free(skey); + return 0; + } + + if (ssl_derive(s, ckey, skey, 1) == 0) { + /* SSLfatal_ntls() already called */ + EVP_PKEY_free(skey); + return 0; + } + s->s3->peer_tmp = skey; +# endif + + return 1; +} + +int tls_parse_stoc_cookie_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + PACKET cookie; + + if (!PACKET_as_length_prefixed_2(pkt, &cookie) + || !PACKET_memdup(&cookie, &s->ext.tls13_cookie, + &s->ext.tls13_cookie_len)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_COOKIE_NTLS, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + return 1; +} + +int tls_parse_stoc_early_data_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (context == SSL_EXT_TLS1_3_NEW_SESSION_TICKET) { + unsigned long max_early_data; + + if (!PACKET_get_net_4(pkt, &max_early_data) + || PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EARLY_DATA_NTLS, + SSL_R_INVALID_MAX_EARLY_DATA); + return 0; + } + + s->session->ext.max_early_data = max_early_data; + + return 1; + } + + if (PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EARLY_DATA_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + + if (!s->ext.early_data_ok + || !s->hit) { + /* + * If we get here then we didn't send early data, or we didn't resume + * using the first identity, or the SNI/ALPN is not consistent so the + * server should not be accepting it. + */ + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_EARLY_DATA_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + + s->ext.early_data = SSL_EARLY_DATA_ACCEPTED; + + return 1; +} + +int tls_parse_stoc_psk_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ +# ifndef OPENSSL_NO_TLS1_3 + unsigned int identity; + + if (!PACKET_get_net_2(pkt, &identity) || PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_PSK_NTLS, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + if (identity >= (unsigned int)s->ext.tick_identity) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_PSK_NTLS, + SSL_R_BAD_PSK_IDENTITY); + return 0; + } + + /* + * Session resumption tickets are always sent before PSK tickets. If the + * ticket index is 0 then it must be for a session resumption ticket if we + * sent two tickets, or if we didn't send a PSK ticket. + */ + if (identity == 0 && (s->psksession == NULL || s->ext.tick_identity == 2)) { + s->hit = 1; + SSL_SESSION_free(s->psksession); + s->psksession = NULL; + return 1; + } + + if (s->psksession == NULL) { + /* Should never happen */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_PSK_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* + * If we used the external PSK for sending early_data then s->early_secret + * is already set up, so don't overwrite it. Otherwise we copy the + * early_secret across that we generated earlier. + */ + if ((s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY + && s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING) + || s->session->ext.max_early_data > 0 + || s->psksession->ext.max_early_data == 0) + memcpy(s->early_secret, s->psksession->early_secret, EVP_MAX_MD_SIZE); + + SSL_SESSION_free(s->session); + s->session = s->psksession; + s->psksession = NULL; + s->hit = 1; + /* Early data is only allowed if we used the first ticket */ + if (identity != 0) + s->ext.early_data_ok = 0; +# endif + + return 1; +} + +#endif diff --git a/ssl/statem_ntls/extensions_cust.c b/ssl/statem_ntls/extensions_cust.c new file mode 100644 index 000000000..4bff74166 --- /dev/null +++ b/ssl/statem_ntls/extensions_cust.c @@ -0,0 +1,531 @@ +/* + * Copyright 2019 The BabaSSL Project Authors. All Rights Reserved. + */ + +/* Custom extension utility functions */ + +#include +#include "ssl_local_ntls.h" +#include "internal/cryptlib.h" +#include "statem_local_ntls.h" + +#if (!defined OPENSSL_NO_NTLS) && (!defined OPENSSL_NO_SM2) \ + && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) + +typedef struct { + void *add_arg; + custom_ext_add_cb add_cb; + custom_ext_free_cb free_cb; +} custom_ext_add_cb_wrap; + +typedef struct { + void *parse_arg; + custom_ext_parse_cb parse_cb; +} custom_ext_parse_cb_wrap; + +/* + * Provide thin wrapper callbacks which convert new style arguments to old style + */ +static int custom_ext_add_ntls_old_cb_wrap(SSL *s, unsigned int ext_type, + unsigned int context, + const unsigned char **out, + size_t *outlen, X509 *x, size_t chainidx, + int *al, void *add_arg) +{ + custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg; + + if (add_cb_wrap->add_cb == NULL) + return 1; + + return add_cb_wrap->add_cb(s, ext_type, out, outlen, al, + add_cb_wrap->add_arg); +} + +static void custom_ext_free_old_cb_wrap(SSL *s, unsigned int ext_type, + unsigned int context, + const unsigned char *out, void *add_arg) +{ + custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg; + + if (add_cb_wrap->free_cb == NULL) + return; + + add_cb_wrap->free_cb(s, ext_type, out, add_cb_wrap->add_arg); +} + +static int custom_ext_parse_ntls_old_cb_wrap(SSL *s, unsigned int ext_type, + unsigned int context, + const unsigned char *in, + size_t inlen, X509 *x, size_t chainidx, + int *al, void *parse_arg) +{ + custom_ext_parse_cb_wrap *parse_cb_wrap = + (custom_ext_parse_cb_wrap *)parse_arg; + + if (parse_cb_wrap->parse_cb == NULL) + return 1; + + return parse_cb_wrap->parse_cb(s, ext_type, in, inlen, al, + parse_cb_wrap->parse_arg); +} + +/* + * Find a custom extension from the list. The |role| param is there to + * support the legacy API where custom extensions for client and server could + * be set independently on the same SSL_CTX. It is set to ENDPOINT_SERVER if we + * are trying to find a method relevant to the server, ENDPOINT_CLIENT for the + * client, or ENDPOINT_BOTH for either + */ +custom_ext_method *custom_ext_find_ntls(const custom_ext_methods *exts, + ENDPOINT role, unsigned int ext_type, + size_t *idx) +{ + size_t i; + custom_ext_method *meth = exts->meths; + + for (i = 0; i < exts->meths_count; i++, meth++) { + if (ext_type == meth->ext_type + && (role == ENDPOINT_BOTH || role == meth->role + || meth->role == ENDPOINT_BOTH)) { + if (idx != NULL) + *idx = i; + return meth; + } + } + return NULL; +} + +/* + * Initialise custom extensions flags to indicate neither sent nor received. + */ +void custom_ext_init_ntls(custom_ext_methods *exts) +{ + size_t i; + custom_ext_method *meth = exts->meths; + + for (i = 0; i < exts->meths_count; i++, meth++) + meth->ext_flags = 0; +} + +/* Pass received custom extension data to the application for parsing. */ +int custom_ext_parse_ntls(SSL *s, unsigned int context, unsigned int ext_type, + const unsigned char *ext_data, size_t ext_size, X509 *x, + size_t chainidx) +{ + int al; + custom_ext_methods *exts = &s->cert->custext; + custom_ext_method *meth; + ENDPOINT role = ENDPOINT_BOTH; + + if ((context & (SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO)) != 0) + role = s->server ? ENDPOINT_SERVER : ENDPOINT_CLIENT; + + meth = custom_ext_find_ntls(exts, role, ext_type, NULL); + /* If not found return success */ + if (!meth) + return 1; + + /* Check if extension is defined for our protocol. If not, skip */ + if (!extension_is_relevant_ntls(s, meth->context, context)) + return 1; + + if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_SERVER_HELLO + | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS)) != 0) { + /* + * If it's ServerHello or EncryptedExtensions we can't have any + * extensions not sent in ClientHello. + */ + if ((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0) { + SSLfatal_ntls(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_F_CUSTOM_EXT_PARSE_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + } + + /* + * Extensions received in the ClientHello are marked with the + * SSL_EXT_FLAG_RECEIVED. This is so we know to add the equivalent + * extensions in the ServerHello/EncryptedExtensions message + */ + if ((context & SSL_EXT_CLIENT_HELLO) != 0) + meth->ext_flags |= SSL_EXT_FLAG_RECEIVED; + + /* If no parse function set return success */ + if (!meth->parse_cb) + return 1; + + if (meth->parse_cb(s, ext_type, context, ext_data, ext_size, x, chainidx, + &al, meth->parse_arg) <= 0) { + SSLfatal_ntls(s, al, SSL_F_CUSTOM_EXT_PARSE_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + + return 1; +} + +/* + * Request custom extension data from the application and add to the return + * buffer. + */ +int custom_ext_add_ntls(SSL *s, int context, WPACKET *pkt, X509 *x, size_t chainidx, + int maxversion) +{ + custom_ext_methods *exts = &s->cert->custext; + custom_ext_method *meth; + size_t i; + int al; + + for (i = 0; i < exts->meths_count; i++) { + const unsigned char *out = NULL; + size_t outlen = 0; + + meth = exts->meths + i; + + if (!should_add_extension_ntls(s, meth->context, context, maxversion)) + continue; + + if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_SERVER_HELLO + | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS + | SSL_EXT_TLS1_3_CERTIFICATE + | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST)) != 0) { + /* Only send extensions present in ClientHello. */ + if (!(meth->ext_flags & SSL_EXT_FLAG_RECEIVED)) + continue; + } + /* + * We skip it if the callback is absent - except for a ClientHello where + * we add an empty extension. + */ + if ((context & SSL_EXT_CLIENT_HELLO) == 0 && meth->add_cb == NULL) + continue; + + if (meth->add_cb != NULL) { + int cb_retval = meth->add_cb(s, meth->ext_type, context, &out, + &outlen, x, chainidx, &al, + meth->add_arg); + + if (cb_retval < 0) { + SSLfatal_ntls(s, al, SSL_F_CUSTOM_EXT_ADD_NTLS, SSL_R_CALLBACK_FAILED); + return 0; /* error */ + } + if (cb_retval == 0) + continue; /* skip this extension */ + } + + if (!WPACKET_put_bytes_u16(pkt, meth->ext_type) + || !WPACKET_start_sub_packet_u16(pkt) + || (outlen > 0 && !WPACKET_memcpy(pkt, out, outlen)) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_CUSTOM_EXT_ADD_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + if ((context & SSL_EXT_CLIENT_HELLO) != 0) { + /* + * We can't send duplicates: code logic should prevent this. + */ + if (!ossl_assert((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_CUSTOM_EXT_ADD_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + /* + * Indicate extension has been sent: this is both a sanity check to + * ensure we don't send duplicate extensions and indicates that it + * is not an error if the extension is present in ServerHello. + */ + meth->ext_flags |= SSL_EXT_FLAG_SENT; + } + if (meth->free_cb != NULL) + meth->free_cb(s, meth->ext_type, context, out, meth->add_arg); + } + return 1; +} + +/* Copy the flags from src to dst for any extensions that exist in both */ +int custom_exts_copy_flags_ntls(custom_ext_methods *dst, + const custom_ext_methods *src) +{ + size_t i; + custom_ext_method *methsrc = src->meths; + + for (i = 0; i < src->meths_count; i++, methsrc++) { + custom_ext_method *methdst = custom_ext_find_ntls(dst, methsrc->role, + methsrc->ext_type, NULL); + + if (methdst == NULL) + continue; + + methdst->ext_flags = methsrc->ext_flags; + } + + return 1; +} + +/* Copy table of custom extensions */ +int custom_exts_copy_ntls(custom_ext_methods *dst, const custom_ext_methods *src) +{ + size_t i; + int err = 0; + + if (src->meths_count > 0) { + dst->meths = + OPENSSL_memdup(src->meths, + sizeof(*src->meths) * src->meths_count); + if (dst->meths == NULL) + return 0; + dst->meths_count = src->meths_count; + + for (i = 0; i < src->meths_count; i++) { + custom_ext_method *methsrc = src->meths + i; + custom_ext_method *methdst = dst->meths + i; + + if (methsrc->add_cb != custom_ext_add_ntls_old_cb_wrap) + continue; + + /* + * We have found an old style API wrapper. We need to copy the + * arguments too. + */ + + if (err) { + methdst->add_arg = NULL; + methdst->parse_arg = NULL; + continue; + } + + methdst->add_arg = OPENSSL_memdup(methsrc->add_arg, + sizeof(custom_ext_add_cb_wrap)); + methdst->parse_arg = OPENSSL_memdup(methsrc->parse_arg, + sizeof(custom_ext_parse_cb_wrap)); + + if (methdst->add_arg == NULL || methdst->parse_arg == NULL) + err = 1; + } + } + + if (err) { + custom_exts_free_ntls(dst); + return 0; + } + + return 1; +} + +void custom_exts_free_ntls(custom_ext_methods *exts) +{ + size_t i; + custom_ext_method *meth; + + for (i = 0, meth = exts->meths; i < exts->meths_count; i++, meth++) { + if (meth->add_cb != custom_ext_add_ntls_old_cb_wrap) + continue; + + /* Old style API wrapper. Need to free the arguments too */ + OPENSSL_free(meth->add_arg); + OPENSSL_free(meth->parse_arg); + } + OPENSSL_free(exts->meths); +} + +/* Return true if a client custom extension exists, false otherwise */ +int SSL_CTX_has_client_custom_ext_ntls(const SSL_CTX *ctx, unsigned int ext_type) +{ + return custom_ext_find_ntls(&ctx->cert->custext, ENDPOINT_CLIENT, ext_type, + NULL) != NULL; +} + +static int add_custom_ext_intern(SSL_CTX *ctx, ENDPOINT role, + unsigned int ext_type, + unsigned int context, + SSL_custom_ext_add_cb_ex add_cb, + SSL_custom_ext_free_cb_ex free_cb, + void *add_arg, + SSL_custom_ext_parse_cb_ex parse_cb, + void *parse_arg) +{ + custom_ext_methods *exts = &ctx->cert->custext; + custom_ext_method *meth, *tmp; + + /* + * Check application error: if add_cb is not set free_cb will never be + * called. + */ + if (add_cb == NULL && free_cb != NULL) + return 0; + +# ifndef OPENSSL_NO_CT + /* + * We don't want applications registering callbacks for SCT extensions + * whilst simultaneously using the built-in SCT validation features, as + * these two things may not play well together. + */ + if (ext_type == TLSEXT_TYPE_signed_certificate_timestamp + && (context & SSL_EXT_CLIENT_HELLO) != 0 + && SSL_CTX_ct_is_enabled(ctx)) + return 0; +# endif + + /* + * Don't add if extension supported internally, but make exception + * for extension types that previously were not supported, but now are. + */ + if (SSL_extension_supported_ntls(ext_type) + && ext_type != TLSEXT_TYPE_signed_certificate_timestamp) + return 0; + + /* Extension type must fit in 16 bits */ + if (ext_type > 0xffff) + return 0; + /* Search for duplicate */ + if (custom_ext_find_ntls(exts, role, ext_type, NULL)) + return 0; + tmp = OPENSSL_realloc(exts->meths, + (exts->meths_count + 1) * sizeof(custom_ext_method)); + if (tmp == NULL) + return 0; + + exts->meths = tmp; + meth = exts->meths + exts->meths_count; + memset(meth, 0, sizeof(*meth)); + meth->role = role; + meth->context = context; + meth->parse_cb = parse_cb; + meth->add_cb = add_cb; + meth->free_cb = free_cb; + meth->ext_type = ext_type; + meth->add_arg = add_arg; + meth->parse_arg = parse_arg; + exts->meths_count++; + return 1; +} + +static int add_old_custom_ext(SSL_CTX *ctx, ENDPOINT role, + unsigned int ext_type, + unsigned int context, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, void *parse_arg) +{ + custom_ext_add_cb_wrap *add_cb_wrap + = OPENSSL_malloc(sizeof(*add_cb_wrap)); + custom_ext_parse_cb_wrap *parse_cb_wrap + = OPENSSL_malloc(sizeof(*parse_cb_wrap)); + int ret; + + if (add_cb_wrap == NULL || parse_cb_wrap == NULL) { + OPENSSL_free(add_cb_wrap); + OPENSSL_free(parse_cb_wrap); + return 0; + } + + add_cb_wrap->add_arg = add_arg; + add_cb_wrap->add_cb = add_cb; + add_cb_wrap->free_cb = free_cb; + parse_cb_wrap->parse_arg = parse_arg; + parse_cb_wrap->parse_cb = parse_cb; + + ret = add_custom_ext_intern(ctx, role, ext_type, + context, + custom_ext_add_ntls_old_cb_wrap, + custom_ext_free_old_cb_wrap, + add_cb_wrap, + custom_ext_parse_ntls_old_cb_wrap, + parse_cb_wrap); + + if (!ret) { + OPENSSL_free(add_cb_wrap); + OPENSSL_free(parse_cb_wrap); + } + + return ret; +} + +/* Application level functions to add the old custom extension callbacks */ +int SSL_CTX_add_client_custom_ext_ntls(SSL_CTX *ctx, unsigned int ext_type, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, void *parse_arg) +{ + return add_old_custom_ext(ctx, ENDPOINT_CLIENT, ext_type, + SSL_EXT_TLS1_2_AND_BELOW_ONLY + | SSL_EXT_CLIENT_HELLO + | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_IGNORE_ON_RESUMPTION, + add_cb, free_cb, add_arg, parse_cb, parse_arg); +} + +int SSL_CTX_add_server_custom_ext_ntls(SSL_CTX *ctx, unsigned int ext_type, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, void *parse_arg) +{ + return add_old_custom_ext(ctx, ENDPOINT_SERVER, ext_type, + SSL_EXT_TLS1_2_AND_BELOW_ONLY + | SSL_EXT_CLIENT_HELLO + | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_IGNORE_ON_RESUMPTION, + add_cb, free_cb, add_arg, parse_cb, parse_arg); +} + +int SSL_CTX_add_custom_ext_ntls(SSL_CTX *ctx, unsigned int ext_type, + unsigned int context, + SSL_custom_ext_add_cb_ex add_cb, + SSL_custom_ext_free_cb_ex free_cb, + void *add_arg, + SSL_custom_ext_parse_cb_ex parse_cb, void *parse_arg) +{ + return add_custom_ext_intern(ctx, ENDPOINT_BOTH, ext_type, context, add_cb, + free_cb, add_arg, parse_cb, parse_arg); +} + +int SSL_extension_supported_ntls(unsigned int ext_type) +{ + switch (ext_type) { + /* Internally supported extensions. */ + case TLSEXT_TYPE_application_layer_protocol_negotiation: +# ifndef OPENSSL_NO_EC + case TLSEXT_TYPE_ec_point_formats: + case TLSEXT_TYPE_supported_groups: + case TLSEXT_TYPE_key_share: +# endif +# ifndef OPENSSL_NO_NEXTPROTONEG + case TLSEXT_TYPE_next_proto_neg: +# endif + case TLSEXT_TYPE_padding: + case TLSEXT_TYPE_renegotiate: + case TLSEXT_TYPE_max_fragment_length: + case TLSEXT_TYPE_server_name: + case TLSEXT_TYPE_session_ticket: + case TLSEXT_TYPE_signature_algorithms: + +# ifndef OPENSSL_NO_OCSP + case TLSEXT_TYPE_status_request: +# endif +# ifndef OPENSSL_NO_CT + case TLSEXT_TYPE_signed_certificate_timestamp: +# endif +# ifndef OPENSSL_NO_SRTP + case TLSEXT_TYPE_use_srtp: +# endif + case TLSEXT_TYPE_encrypt_then_mac: + case TLSEXT_TYPE_supported_versions: + case TLSEXT_TYPE_extended_master_secret: + case TLSEXT_TYPE_psk_kex_modes: + case TLSEXT_TYPE_cookie: + case TLSEXT_TYPE_early_data: + case TLSEXT_TYPE_certificate_authorities: + case TLSEXT_TYPE_psk: + case TLSEXT_TYPE_post_handshake_auth: + return 1; + default: + return 0; + } +} + +#endif diff --git a/ssl/statem_ntls/extensions_srvr.c b/ssl/statem_ntls/extensions_srvr.c new file mode 100644 index 000000000..63e8eae17 --- /dev/null +++ b/ssl/statem_ntls/extensions_srvr.c @@ -0,0 +1,1874 @@ +/* + * Copyright 2019 The BabaSSL Project Authors. All Rights Reserved. + */ + +#include +#include "ssl_local_ntls.h" +#include "statem_local_ntls.h" +#include "internal/cryptlib.h" + +#if (!defined OPENSSL_NO_NTLS) && (!defined OPENSSL_NO_SM2) \ + && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) + +# define COOKIE_STATE_FORMAT_VERSION 0 + +/* + * 2 bytes for packet length, 2 bytes for format version, 2 bytes for + * protocol version, 2 bytes for group id, 2 bytes for cipher id, 1 byte for + * key_share present flag, 4 bytes for timestamp, 2 bytes for the hashlen, + * EVP_MAX_MD_SIZE for transcript hash, 1 byte for app cookie length, app cookie + * length bytes, SHA256_DIGEST_LENGTH bytes for the HMAC of the whole thing. + */ +# define MAX_COOKIE_SIZE (2 + 2 + 2 + 2 + 2 + 1 + 4 + 2 + EVP_MAX_MD_SIZE + 1 \ + + SSL_COOKIE_LENGTH + SHA256_DIGEST_LENGTH) + +/* + * Message header + 2 bytes for protocol version + number of random bytes + + * + 1 byte for legacy session id length + number of bytes in legacy session id + * + 2 bytes for ciphersuite + 1 byte for legacy compression + * + 2 bytes for extension block length + 6 bytes for key_share extension + * + 4 bytes for cookie extension header + the number of bytes in the cookie + */ +# define MAX_HRR_SIZE (SSL3_HM_HEADER_LENGTH + 2 + SSL3_RANDOM_SIZE + 1 \ + + SSL_MAX_SSL_SESSION_ID_LENGTH + 2 + 1 + 2 + 6 + 4 \ + + MAX_COOKIE_SIZE) + +/* + * Parse the client's renegotiation binding and abort if it's not right + */ +int tls_parse_ctos_renegotiate_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + unsigned int ilen; + const unsigned char *data; + + /* Parse the length byte */ + if (!PACKET_get_1(pkt, &ilen) + || !PACKET_get_bytes(pkt, &data, ilen)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE_NTLS, + SSL_R_RENEGOTIATION_ENCODING_ERR); + return 0; + } + + /* Check that the extension matches */ + if (ilen != s->s3->previous_client_finished_len) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE_NTLS, + SSL_R_RENEGOTIATION_MISMATCH); + return 0; + } + + if (memcmp(data, s->s3->previous_client_finished, + s->s3->previous_client_finished_len)) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE_NTLS, + SSL_R_RENEGOTIATION_MISMATCH); + return 0; + } + + s->s3->send_connection_binding = 1; + + return 1; +} + +/*- + * The servername extension is treated as follows: + * + * - Only the hostname type is supported with a maximum length of 255. + * - The servername is rejected if too long or if it contains zeros, + * in which case an fatal alert is generated. + * - The servername field is maintained together with the session cache. + * - When a session is resumed, the servername call back invoked in order + * to allow the application to position itself to the right context. + * - The servername is acknowledged if it is new for a session or when + * it is identical to a previously used for the same session. + * Applications can control the behaviour. They can at any time + * set a 'desirable' servername for a new SSL object. This can be the + * case for example with HTTPS when a Host: header field is received and + * a renegotiation is requested. In this case, a possible servername + * presented in the new client hello is only acknowledged if it matches + * the value of the Host: field. + * - Applications must use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION + * if they provide for changing an explicit servername context for the + * session, i.e. when the session has been established with a servername + * extension. + * - On session reconnect, the servername extension may be absent. + */ +int tls_parse_ctos_server_name_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + unsigned int servname_type; + PACKET sni, hostname; + + if (!PACKET_as_length_prefixed_2(pkt, &sni) + /* ServerNameList must be at least 1 byte long. */ + || PACKET_remaining(&sni) == 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + + /* + * Although the intent was for server_name to be extensible, RFC 4366 + * was not clear about it; and so OpenSSL among other implementations, + * always and only allows a 'host_name' name types. + * RFC 6066 corrected the mistake but adding new name types + * is nevertheless no longer feasible, so act as if no other + * SNI types can exist, to simplify parsing. + * + * Also note that the RFC permits only one SNI value per type, + * i.e., we can only have a single hostname. + */ + if (!PACKET_get_1(&sni, &servname_type) + || servname_type != TLSEXT_NAMETYPE_host_name + || !PACKET_as_length_prefixed_2(&sni, &hostname)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + + if (!s->hit) { + if (PACKET_remaining(&hostname) > TLSEXT_MAXLEN_host_name) { + SSLfatal_ntls(s, SSL_AD_UNRECOGNIZED_NAME, + SSL_F_TLS_PARSE_CTOS_SERVER_NAME_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + + if (PACKET_contains_zero_byte(&hostname)) { + SSLfatal_ntls(s, SSL_AD_UNRECOGNIZED_NAME, + SSL_F_TLS_PARSE_CTOS_SERVER_NAME_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + + /* + * Store the requested SNI in the SSL as temporary storage. + * If we accept it, it will get stored in the SSL_SESSION as well. + */ + OPENSSL_free(s->ext.hostname); + s->ext.hostname = NULL; + if (!PACKET_strndup(&hostname, &s->ext.hostname)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + s->servername_done = 1; + } + if (s->hit) { + /* + * TODO(openssl-team): if the SNI doesn't match, we MUST + * fall back to a full handshake. + */ + s->servername_done = (s->session->ext.hostname != NULL) + && PACKET_equal(&hostname, s->session->ext.hostname, + strlen(s->session->ext.hostname)); + + if (!s->servername_done && s->session->ext.hostname != NULL) + s->ext.early_data_ok = 0; + } + + return 1; +} + +int tls_parse_ctos_maxfragmentlen_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + unsigned int value; + + if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + + /* Received |value| should be a valid max-fragment-length code. */ + if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN_NTLS, + SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH); + return 0; + } + + /* + * RFC 6066: The negotiated length applies for the duration of the session + * including session resumptions. + * We should receive the same code as in resumed session ! + */ + if (s->hit && s->session->ext.max_fragment_len_mode != value) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN_NTLS, + SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH); + return 0; + } + + /* + * Store it in session, so it'll become binding for us + * and we'll include it in a next Server Hello. + */ + s->session->ext.max_fragment_len_mode = value; + return 1; +} + +# ifndef OPENSSL_NO_EC +int tls_parse_ctos_ec_pt_formats_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + PACKET ec_point_format_list; + + if (!PACKET_as_length_prefixed_1(pkt, &ec_point_format_list) + || PACKET_remaining(&ec_point_format_list) == 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + + if (!s->hit) { + if (!PACKET_memdup(&ec_point_format_list, + &s->ext.peer_ecpointformats, + &s->ext.peer_ecpointformats_len)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS_NTLS, ERR_R_INTERNAL_ERROR); + return 0; + } + } + + return 1; +} +# endif /* OPENSSL_NO_EC */ + +int tls_parse_ctos_session_ticket_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (s->ext.session_ticket_cb && + !s->ext.session_ticket_cb(s, PACKET_data(pkt), + PACKET_remaining(pkt), + s->ext.session_ticket_cb_arg)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_CTOS_SESSION_TICKET_NTLS, ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +int tls_parse_ctos_sig_algs_cert_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + PACKET supported_sig_algs; + + if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs) + || PACKET_remaining(&supported_sig_algs) == 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + + if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs, 1)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + + return 1; +} + +int tls_parse_ctos_sig_algs_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + PACKET supported_sig_algs; + + if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs) + || PACKET_remaining(&supported_sig_algs) == 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_SIG_ALGS_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + + if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs, 0)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_SIG_ALGS_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + + return 1; +} + +# ifndef OPENSSL_NO_OCSP +int tls_parse_ctos_status_request_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + PACKET responder_id_list, exts; + + /* We ignore this in a resumption handshake */ + if (s->hit) + return 1; + + /* Not defined if we get one of these in a client Certificate */ + if (x != NULL) + return 1; + + if (!PACKET_get_1(pkt, (unsigned int *)&s->ext.status_type)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + + if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp) { + /* + * We don't know what to do with any other type so ignore it. + */ + s->ext.status_type = TLSEXT_STATUSTYPE_nothing; + return 1; + } + + if (!PACKET_get_length_prefixed_2 (pkt, &responder_id_list)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + + /* + * We remove any OCSP_RESPIDs from a previous handshake + * to prevent unbounded memory growth - CVE-2016-6304 + */ + sk_OCSP_RESPID_pop_free(s->ext.ocsp.ids, OCSP_RESPID_free); + if (PACKET_remaining(&responder_id_list) > 0) { + s->ext.ocsp.ids = sk_OCSP_RESPID_new_null(); + if (s->ext.ocsp.ids == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST_NTLS, ERR_R_MALLOC_FAILURE); + return 0; + } + } else { + s->ext.ocsp.ids = NULL; + } + + while (PACKET_remaining(&responder_id_list) > 0) { + OCSP_RESPID *id; + PACKET responder_id; + const unsigned char *id_data; + + if (!PACKET_get_length_prefixed_2(&responder_id_list, &responder_id) + || PACKET_remaining(&responder_id) == 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + + id_data = PACKET_data(&responder_id); + /* TODO(size_t): Convert d2i_* to size_t */ + id = d2i_OCSP_RESPID(NULL, &id_data, + (int)PACKET_remaining(&responder_id)); + if (id == NULL) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + + if (id_data != PACKET_end(&responder_id)) { + OCSP_RESPID_free(id); + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST_NTLS, SSL_R_BAD_EXTENSION); + + return 0; + } + + if (!sk_OCSP_RESPID_push(s->ext.ocsp.ids, id)) { + OCSP_RESPID_free(id); + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST_NTLS, ERR_R_INTERNAL_ERROR); + + return 0; + } + } + + /* Read in request_extensions */ + if (!PACKET_as_length_prefixed_2(pkt, &exts)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + + if (PACKET_remaining(&exts) > 0) { + const unsigned char *ext_data = PACKET_data(&exts); + + sk_X509_EXTENSION_pop_free(s->ext.ocsp.exts, + X509_EXTENSION_free); + s->ext.ocsp.exts = + d2i_X509_EXTENSIONS(NULL, &ext_data, (int)PACKET_remaining(&exts)); + if (s->ext.ocsp.exts == NULL || ext_data != PACKET_end(&exts)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + } + + return 1; +} +# endif + +# ifndef OPENSSL_NO_NEXTPROTONEG +int tls_parse_ctos_npn_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + /* + * We shouldn't accept this extension on a + * renegotiation. + */ + if (SSL_IS_FIRST_HANDSHAKE(s)) + s->s3->npn_seen = 1; + + return 1; +} +# endif + +/* + * Save the ALPN extension in a ClientHello.|pkt| holds the contents of the ALPN + * extension, not including type and length. Returns: 1 on success, 0 on error. + */ +int tls_parse_ctos_alpn_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + PACKET protocol_list, save_protocol_list, protocol; + + if (!SSL_IS_FIRST_HANDSHAKE(s)) + return 1; + + if (!PACKET_as_length_prefixed_2(pkt, &protocol_list) + || PACKET_remaining(&protocol_list) < 2) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + + save_protocol_list = protocol_list; + do { + /* Protocol names can't be empty. */ + if (!PACKET_get_length_prefixed_1(&protocol_list, &protocol) + || PACKET_remaining(&protocol) == 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + } while (PACKET_remaining(&protocol_list) != 0); + + OPENSSL_free(s->s3->alpn_proposed); + s->s3->alpn_proposed = NULL; + s->s3->alpn_proposed_len = 0; + if (!PACKET_memdup(&save_protocol_list, + &s->s3->alpn_proposed, &s->s3->alpn_proposed_len)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +# ifndef OPENSSL_NO_SRTP +int tls_parse_ctos_use_srtp_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + STACK_OF(SRTP_PROTECTION_PROFILE) *srvr; + unsigned int ct, mki_len, id; + int i, srtp_pref; + PACKET subpkt; + + /* Ignore this if we have no SRTP profiles */ + if (SSL_get_srtp_profiles(s) == NULL) + return 1; + + /* Pull off the length of the cipher suite list and check it is even */ + if (!PACKET_get_net_2(pkt, &ct) || (ct & 1) != 0 + || !PACKET_get_sub_packet(pkt, &subpkt, ct)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP_NTLS, + SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + return 0; + } + + srvr = SSL_get_srtp_profiles(s); + s->srtp_profile = NULL; + /* Search all profiles for a match initially */ + srtp_pref = sk_SRTP_PROTECTION_PROFILE_num(srvr); + + while (PACKET_remaining(&subpkt)) { + if (!PACKET_get_net_2(&subpkt, &id)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP_NTLS, + SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + return 0; + } + + /* + * Only look for match in profiles of higher preference than + * current match. + * If no profiles have been have been configured then this + * does nothing. + */ + for (i = 0; i < srtp_pref; i++) { + SRTP_PROTECTION_PROFILE *sprof = + sk_SRTP_PROTECTION_PROFILE_value(srvr, i); + + if (sprof->id == id) { + s->srtp_profile = sprof; + srtp_pref = i; + break; + } + } + } + + /* Now extract the MKI value as a sanity check, but discard it for now */ + if (!PACKET_get_1(pkt, &mki_len)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP_NTLS, + SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + return 0; + } + + if (!PACKET_forward(pkt, mki_len) + || PACKET_remaining(pkt)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP_NTLS, + SSL_R_BAD_SRTP_MKI_VALUE); + return 0; + } + + return 1; +} +# endif + +int tls_parse_ctos_etm_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + if (!(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)) + s->ext.use_etm = 1; + + return 1; +} + +/* + * Process a psk_kex_modes extension received in the ClientHello. |pkt| contains + * the raw PACKET data for the extension. Returns 1 on success or 0 on failure. + */ +int tls_parse_ctos_psk_kex_modes_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ +# ifndef OPENSSL_NO_TLS1_3 + PACKET psk_kex_modes; + unsigned int mode; + + if (!PACKET_as_length_prefixed_1(pkt, &psk_kex_modes) + || PACKET_remaining(&psk_kex_modes) == 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + + while (PACKET_get_1(&psk_kex_modes, &mode)) { + if (mode == TLSEXT_KEX_MODE_KE_DHE) + s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE_DHE; + else if (mode == TLSEXT_KEX_MODE_KE + && (s->options & SSL_OP_ALLOW_NO_DHE_KEX) != 0) + s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE; + } +# endif + + return 1; +} + +/* + * Process a key_share extension received in the ClientHello. |pkt| contains + * the raw PACKET data for the extension. Returns 1 on success or 0 on failure. + */ +int tls_parse_ctos_key_share_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ +# ifndef OPENSSL_NO_TLS1_3 + unsigned int group_id; + PACKET key_share_list, encoded_pt; + const uint16_t *clntgroups, *srvrgroups; + size_t clnt_num_groups, srvr_num_groups; + int found = 0; + + if (s->hit && (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) == 0) + return 1; + + /* Sanity check */ + if (s->s3->peer_tmp != NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!PACKET_as_length_prefixed_2(pkt, &key_share_list)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE_NTLS, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + /* Get our list of supported groups */ + tls1_get_supported_groups(s, &srvrgroups, &srvr_num_groups); + /* Get the clients list of supported groups. */ + tls1_get_peer_groups(s, &clntgroups, &clnt_num_groups); + if (clnt_num_groups == 0) { + /* + * This can only happen if the supported_groups extension was not sent, + * because we verify that the length is non-zero when we process that + * extension. + */ + SSLfatal_ntls(s, SSL_AD_MISSING_EXTENSION, SSL_F_TLS_PARSE_CTOS_KEY_SHARE_NTLS, + SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION); + return 0; + } + + if (s->s3->group_id != 0 && PACKET_remaining(&key_share_list) == 0) { + /* + * If we set a group_id already, then we must have sent an HRR + * requesting a new key_share. If we haven't got one then that is an + * error + */ + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_KEY_SHARE_NTLS, + SSL_R_BAD_KEY_SHARE); + return 0; + } + + while (PACKET_remaining(&key_share_list) > 0) { + if (!PACKET_get_net_2(&key_share_list, &group_id) + || !PACKET_get_length_prefixed_2(&key_share_list, &encoded_pt) + || PACKET_remaining(&encoded_pt) == 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE_NTLS, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + /* + * If we already found a suitable key_share we loop through the + * rest to verify the structure, but don't process them. + */ + if (found) + continue; + + /* + * If we sent an HRR then the key_share sent back MUST be for the group + * we requested, and must be the only key_share sent. + */ + if (s->s3->group_id != 0 + && (group_id != s->s3->group_id + || PACKET_remaining(&key_share_list) != 0)) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_CTOS_KEY_SHARE_NTLS, SSL_R_BAD_KEY_SHARE); + return 0; + } + + /* Check if this share is in supported_groups sent from client */ + if (!check_in_list_ntls(s, group_id, clntgroups, clnt_num_groups, 0)) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_CTOS_KEY_SHARE_NTLS, SSL_R_BAD_KEY_SHARE); + return 0; + } + + /* Check if this share is for a group we can use */ + if (!check_in_list_ntls(s, group_id, srvrgroups, srvr_num_groups, 1)) { + /* Share not suitable */ + continue; + } + + if ((s->s3->peer_tmp = ssl_generate_param_group(group_id)) == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE_NTLS, + SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); + return 0; + } + + s->s3->group_id = group_id; + + if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp, + PACKET_data(&encoded_pt), + PACKET_remaining(&encoded_pt))) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_CTOS_KEY_SHARE_NTLS, SSL_R_BAD_ECPOINT); + return 0; + } + + found = 1; + } +# endif + + return 1; +} + +int tls_parse_ctos_cookie_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ +# ifndef OPENSSL_NO_TLS1_3 + unsigned int format, version, key_share, group_id; + EVP_MD_CTX *hctx; + EVP_PKEY *pkey; + PACKET cookie, raw, chhash, appcookie; + WPACKET hrrpkt; + const unsigned char *data, *mdin, *ciphdata; + unsigned char hmac[SHA256_DIGEST_LENGTH]; + unsigned char hrr[MAX_HRR_SIZE]; + size_t rawlen, hmaclen, hrrlen, ciphlen; + unsigned long tm, now; + + /* Ignore any cookie if we're not set up to verify it */ + if (s->ctx->verify_stateless_cookie_cb == NULL + || (s->s3->flags & TLS1_FLAGS_STATELESS) == 0) + return 1; + + if (!PACKET_as_length_prefixed_2(pkt, &cookie)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE_NTLS, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + raw = cookie; + data = PACKET_data(&raw); + rawlen = PACKET_remaining(&raw); + if (rawlen < SHA256_DIGEST_LENGTH + || !PACKET_forward(&raw, rawlen - SHA256_DIGEST_LENGTH)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE_NTLS, + SSL_R_LENGTH_MISMATCH); + return 0; + } + mdin = PACKET_data(&raw); + + /* Verify the HMAC of the cookie */ + hctx = EVP_MD_CTX_create(); + pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, + s->session_ctx->ext.cookie_hmac_key, + sizeof(s->session_ctx->ext + .cookie_hmac_key)); + if (hctx == NULL || pkey == NULL) { + EVP_MD_CTX_free(hctx); + EVP_PKEY_free(pkey); + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE_NTLS, + ERR_R_MALLOC_FAILURE); + return 0; + } + + hmaclen = SHA256_DIGEST_LENGTH; + if (EVP_DigestSignInit(hctx, NULL, EVP_sha256(), NULL, pkey) <= 0 + || EVP_DigestSign(hctx, hmac, &hmaclen, data, + rawlen - SHA256_DIGEST_LENGTH) <= 0 + || hmaclen != SHA256_DIGEST_LENGTH) { + EVP_MD_CTX_free(hctx); + EVP_PKEY_free(pkey); + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + EVP_MD_CTX_free(hctx); + EVP_PKEY_free(pkey); + + if (CRYPTO_memcmp(hmac, mdin, SHA256_DIGEST_LENGTH) != 0) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE_NTLS, + SSL_R_COOKIE_MISMATCH); + return 0; + } + + if (!PACKET_get_net_2(&cookie, &format)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE_NTLS, + SSL_R_LENGTH_MISMATCH); + return 0; + } + /* Check the cookie format is something we recognise. Ignore it if not */ + if (format != COOKIE_STATE_FORMAT_VERSION) + return 1; + + /* + * The rest of these checks really shouldn't fail since we have verified the + * HMAC above. + */ + + /* Check the version number is sane */ + if (!PACKET_get_net_2(&cookie, &version)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE_NTLS, + SSL_R_LENGTH_MISMATCH); + return 0; + } + if (version != TLS1_3_VERSION) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE_NTLS, + SSL_R_BAD_PROTOCOL_VERSION_NUMBER); + return 0; + } + + if (!PACKET_get_net_2(&cookie, &group_id)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE_NTLS, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + ciphdata = PACKET_data(&cookie); + if (!PACKET_forward(&cookie, 2)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE_NTLS, + SSL_R_LENGTH_MISMATCH); + return 0; + } + if (group_id != s->s3->group_id + || s->s3->tmp.new_cipher + != ssl_get_cipher_by_char(s, ciphdata, 0)) { + /* + * We chose a different cipher or group id this time around to what is + * in the cookie. Something must have changed. + */ + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE_NTLS, + SSL_R_BAD_CIPHER); + return 0; + } + + if (!PACKET_get_1(&cookie, &key_share) + || !PACKET_get_net_4(&cookie, &tm) + || !PACKET_get_length_prefixed_2(&cookie, &chhash) + || !PACKET_get_length_prefixed_1(&cookie, &appcookie) + || PACKET_remaining(&cookie) != SHA256_DIGEST_LENGTH) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE_NTLS, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + /* We tolerate a cookie age of up to 10 minutes (= 60 * 10 seconds) */ + now = (unsigned long)time(NULL); + if (tm > now || (now - tm) > 600) { + /* Cookie is stale. Ignore it */ + return 1; + } + + /* Verify the app cookie */ + if (s->ctx->verify_stateless_cookie_cb(s, PACKET_data(&appcookie), + PACKET_remaining(&appcookie)) == 0) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE_NTLS, + SSL_R_COOKIE_MISMATCH); + return 0; + } + + /* + * Reconstruct the HRR that we would have sent in response to the original + * ClientHello so we can add it to the transcript hash. + * Note: This won't work with custom HRR extensions + */ + if (!WPACKET_init_static_len(&hrrpkt, hrr, sizeof(hrr), 0)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + if (!WPACKET_put_bytes_u8(&hrrpkt, SSL3_MT_SERVER_HELLO) + || !WPACKET_start_sub_packet_u24(&hrrpkt) + || !WPACKET_put_bytes_u16(&hrrpkt, TLS1_2_VERSION) + || !WPACKET_memcpy(&hrrpkt, hrrrandom_ntls, SSL3_RANDOM_SIZE) + || !WPACKET_sub_memcpy_u8(&hrrpkt, s->tmp_session_id, + s->tmp_session_id_len) + || !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, &hrrpkt, + &ciphlen) + || !WPACKET_put_bytes_u8(&hrrpkt, 0) + || !WPACKET_start_sub_packet_u16(&hrrpkt)) { + WPACKET_cleanup(&hrrpkt); + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_supported_versions) + || !WPACKET_start_sub_packet_u16(&hrrpkt) + || !WPACKET_put_bytes_u16(&hrrpkt, s->version) + || !WPACKET_close(&hrrpkt)) { + WPACKET_cleanup(&hrrpkt); + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + if (key_share) { + if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_key_share) + || !WPACKET_start_sub_packet_u16(&hrrpkt) + || !WPACKET_put_bytes_u16(&hrrpkt, s->s3->group_id) + || !WPACKET_close(&hrrpkt)) { + WPACKET_cleanup(&hrrpkt); + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_cookie) + || !WPACKET_start_sub_packet_u16(&hrrpkt) + || !WPACKET_sub_memcpy_u16(&hrrpkt, data, rawlen) + || !WPACKET_close(&hrrpkt) /* cookie extension */ + || !WPACKET_close(&hrrpkt) /* extension block */ + || !WPACKET_close(&hrrpkt) /* message */ + || !WPACKET_get_total_written(&hrrpkt, &hrrlen) + || !WPACKET_finish(&hrrpkt)) { + WPACKET_cleanup(&hrrpkt); + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* Reconstruct the transcript hash */ + if (!create_synthetic_message_hash_ntls(s, PACKET_data(&chhash), + PACKET_remaining(&chhash), hrr, + hrrlen)) { + /* SSLfatal_ntls() already called */ + return 0; + } + + /* Act as if this ClientHello came after a HelloRetryRequest */ + s->hello_retry_request = 1; + + s->ext.cookieok = 1; +# endif + return 1; +} + +# ifndef OPENSSL_NO_EC +int tls_parse_ctos_supported_groups_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + PACKET supported_groups_list; + + /* Each group is 2 bytes and we must have at least 1. */ + if (!PACKET_as_length_prefixed_2(pkt, &supported_groups_list) + || PACKET_remaining(&supported_groups_list) == 0 + || (PACKET_remaining(&supported_groups_list) % 2) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + + if (!s->hit) { + OPENSSL_free(s->ext.peer_supportedgroups); + s->ext.peer_supportedgroups = NULL; + s->ext.peer_supportedgroups_len = 0; + if (!tls1_save_u16(&supported_groups_list, + &s->ext.peer_supportedgroups, + &s->ext.peer_supportedgroups_len)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + + return 1; +} +# endif + +int tls_parse_ctos_ems_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + /* The extension must always be empty */ + if (PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_EMS_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + + s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS; + + return 1; +} + + +int tls_parse_ctos_early_data_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_EARLY_DATA_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + + if (s->hello_retry_request != SSL_HRR_NONE) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_CTOS_EARLY_DATA_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + + return 1; +} + +static SSL_TICKET_STATUS tls_get_stateful_ticket(SSL *s, PACKET *tick, + SSL_SESSION **sess) +{ + SSL_SESSION *tmpsess = NULL; + + s->ext.ticket_expected = 1; + + switch (PACKET_remaining(tick)) { + case 0: + return SSL_TICKET_EMPTY; + + case SSL_MAX_SSL_SESSION_ID_LENGTH: + break; + + default: + return SSL_TICKET_NO_DECRYPT; + } + + tmpsess = lookup_sess_in_cache(s, PACKET_data(tick), + SSL_MAX_SSL_SESSION_ID_LENGTH); + + if (tmpsess == NULL) + return SSL_TICKET_NO_DECRYPT; + + *sess = tmpsess; + return SSL_TICKET_SUCCESS; +} + +int tls_parse_ctos_psk_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + PACKET identities, binders, binder; + size_t binderoffset, hashsize; + SSL_SESSION *sess = NULL; + unsigned int id, i, ext = 0; + const EVP_MD *md = NULL; + + /* + * If we have no PSK kex mode that we recognise then we can't resume so + * ignore this extension + */ + if ((s->ext.psk_kex_mode + & (TLSEXT_KEX_MODE_FLAG_KE | TLSEXT_KEX_MODE_FLAG_KE_DHE)) == 0) + return 1; + + if (!PACKET_get_length_prefixed_2(pkt, &identities)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_PSK_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + + s->ext.ticket_expected = 0; + for (id = 0; PACKET_remaining(&identities) != 0; id++) { + PACKET identity; + unsigned long ticket_agel; + size_t idlen; + + if (!PACKET_get_length_prefixed_2(&identities, &identity) + || !PACKET_get_net_4(&identities, &ticket_agel)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_PSK_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + + idlen = PACKET_remaining(&identity); + if (s->psk_find_session_cb != NULL + && !s->psk_find_session_cb(s, PACKET_data(&identity), idlen, + &sess)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_CTOS_PSK_NTLS, SSL_R_BAD_EXTENSION); + return 0; + } + + if (sess != NULL) { + /* We found a PSK */ + SSL_SESSION *sesstmp = ssl_session_dup(sess, 0); + + if (sesstmp == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_CTOS_PSK_NTLS, ERR_R_INTERNAL_ERROR); + return 0; + } + SSL_SESSION_free(sess); + sess = sesstmp; + + /* + * We've just been told to use this session for this context so + * make sure the sid_ctx matches up. + */ + memcpy(sess->sid_ctx, s->sid_ctx, s->sid_ctx_length); + sess->sid_ctx_length = s->sid_ctx_length; + ext = 1; + if (id == 0) + s->ext.early_data_ok = 1; + s->ext.ticket_expected = 1; + } else { + uint32_t ticket_age = 0, now, agesec, agems; + int ret; + + /* + * If we are using anti-replay protection then we behave as if + * SSL_OP_NO_TICKET is set - we are caching tickets anyway so there + * is no point in using full stateless tickets. + */ + if ((s->options & SSL_OP_NO_TICKET) != 0 + || (s->max_early_data > 0 + && (s->options & SSL_OP_NO_ANTI_REPLAY) == 0)) + ret = tls_get_stateful_ticket(s, &identity, &sess); + else + ret = tls_decrypt_ticket(s, PACKET_data(&identity), + PACKET_remaining(&identity), NULL, 0, + &sess); + + if (ret == SSL_TICKET_EMPTY) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK_NTLS, + SSL_R_BAD_EXTENSION); + return 0; + } + + if (ret == SSL_TICKET_FATAL_ERR_MALLOC + || ret == SSL_TICKET_FATAL_ERR_OTHER) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_CTOS_PSK_NTLS, ERR_R_INTERNAL_ERROR); + return 0; + } + if (ret == SSL_TICKET_NONE || ret == SSL_TICKET_NO_DECRYPT) + continue; + + /* Check for replay */ + if (s->max_early_data > 0 + && (s->options & SSL_OP_NO_ANTI_REPLAY) == 0 + && !SSL_CTX_remove_session(s->session_ctx, sess)) { + SSL_SESSION_free(sess); + sess = NULL; + continue; + } + + ticket_age = (uint32_t)ticket_agel; + now = (uint32_t)time(NULL); + agesec = now - (uint32_t)sess->time; + agems = agesec * (uint32_t)1000; + ticket_age -= sess->ext.tick_age_add; + + /* + * For simplicity we do our age calculations in seconds. If the + * client does it in ms then it could appear that their ticket age + * is longer than ours (our ticket age calculation should always be + * slightly longer than the client's due to the network latency). + * Therefore we add 1000ms to our age calculation to adjust for + * rounding errors. + */ + if (id == 0 + && sess->timeout >= (long)agesec + && agems / (uint32_t)1000 == agesec + && ticket_age <= agems + 1000 + && ticket_age + TICKET_AGE_ALLOWANCE >= agems + 1000) { + /* + * Ticket age is within tolerance and not expired. We allow it + * for early data + */ + s->ext.early_data_ok = 1; + } + } + + md = ssl_md(sess->cipher->algorithm2); + if (md != ssl_md(s->s3->tmp.new_cipher->algorithm2)) { + /* The ciphersuite is not compatible with this session. */ + SSL_SESSION_free(sess); + sess = NULL; + s->ext.early_data_ok = 0; + s->ext.ticket_expected = 0; + continue; + } + break; + } + + if (sess == NULL) + return 1; + + binderoffset = PACKET_data(pkt) - (const unsigned char *)s->init_buf->data; + hashsize = EVP_MD_size(md); + + if (!PACKET_get_length_prefixed_2(pkt, &binders)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK_NTLS, + SSL_R_BAD_EXTENSION); + goto err; + } + + for (i = 0; i <= id; i++) { + if (!PACKET_get_length_prefixed_1(&binders, &binder)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK_NTLS, + SSL_R_BAD_EXTENSION); + goto err; + } + } + + if (PACKET_remaining(&binder) != hashsize) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK_NTLS, + SSL_R_BAD_EXTENSION); + goto err; + } + if (tls_psk_do_binder_ntls(s, md, (const unsigned char *)s->init_buf->data, + binderoffset, PACKET_data(&binder), NULL, sess, 0, + ext) != 1) { + /* SSLfatal_ntls() already called */ + goto err; + } + + s->ext.tick_identity = id; + + SSL_SESSION_free(s->session); + s->session = sess; + return 1; +err: + SSL_SESSION_free(sess); + return 0; +} + +int tls_parse_ctos_post_handshake_auth_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH_NTLS, + SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR); + return 0; + } + + s->post_handshake_auth = SSL_PHA_EXT_RECEIVED; + + return 1; +} + +/* + * Add the server's renegotiation binding + */ +EXT_RETURN tls_construct_stoc_renegotiate_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + if (!s->s3->send_connection_binding) + return EXT_RETURN_NOT_SENT; + + /* Still add this even if SSL_OP_NO_RENEGOTIATION is set */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_start_sub_packet_u8(pkt) + || !WPACKET_memcpy(pkt, s->s3->previous_client_finished, + s->s3->previous_client_finished_len) + || !WPACKET_memcpy(pkt, s->s3->previous_server_finished, + s->s3->previous_server_finished_len) + || !WPACKET_close(pkt) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +EXT_RETURN tls_construct_stoc_server_name_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + if (s->hit || s->servername_done != 1 + || s->ext.hostname == NULL) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name) + || !WPACKET_put_bytes_u16(pkt, 0)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +/* Add/include the server's max fragment len extension into ServerHello */ +EXT_RETURN tls_construct_stoc_maxfragmentlen_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + if (!USE_MAX_FRAGMENT_LENGTH_EXT(s->session)) + return EXT_RETURN_NOT_SENT; + + /*- + * 4 bytes for this extension type and extension length + * 1 byte for the Max Fragment Length code value. + */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_max_fragment_length) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_put_bytes_u8(pkt, s->session->ext.max_fragment_len_mode) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +# ifndef OPENSSL_NO_EC +EXT_RETURN tls_construct_stoc_ec_pt_formats_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth; + int using_ecc = ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA)) + && (s->ext.peer_ecpointformats != NULL); + const unsigned char *plist; + size_t plistlen; + + if (!using_ecc) + return EXT_RETURN_NOT_SENT; + + tls1_get_formatlist(s, &plist, &plistlen); + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_sub_memcpy_u8(pkt, plist, plistlen) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} +# endif + +# ifndef OPENSSL_NO_EC +EXT_RETURN tls_construct_stoc_supported_groups_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + const uint16_t *groups; + size_t numgroups, i, first = 1; + + /* s->s3->group_id is non zero if we accepted a key_share */ + if (s->s3->group_id == 0) + return EXT_RETURN_NOT_SENT; + + /* Get our list of supported groups */ + tls1_get_supported_groups(s, &groups, &numgroups); + if (numgroups == 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + /* Copy group ID if supported */ + for (i = 0; i < numgroups; i++) { + uint16_t group = groups[i]; + + if (tls_curve_allowed(s, group, SSL_SECOP_CURVE_SUPPORTED)) { + if (first) { + /* + * Check if the client is already using our preferred group. If + * so we don't need to add this extension + */ + if (s->s3->group_id == group) + return EXT_RETURN_NOT_SENT; + + /* Add extension header */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_groups) + /* Sub-packet for supported_groups extension */ + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + first = 0; + } + if (!WPACKET_put_bytes_u16(pkt, group)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + } + } + + if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} +# endif + +EXT_RETURN tls_construct_stoc_session_ticket_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + if (!s->ext.ticket_expected || !tls_use_ticket(s)) { + s->ext.ticket_expected = 0; + return EXT_RETURN_NOT_SENT; + } + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket) + || !WPACKET_put_bytes_u16(pkt, 0)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +# ifndef OPENSSL_NO_OCSP +EXT_RETURN tls_construct_stoc_status_request_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + /* We don't currently support this extension inside a CertificateRequest */ + if (context == SSL_EXT_TLS1_3_CERTIFICATE_REQUEST) + return EXT_RETURN_NOT_SENT; + + if (!s->ext.status_expected) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request) + || !WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + /* + * In TLSv1.3 we include the certificate status itself. In <= TLSv1.2 we + * send back an empty extension, with the certificate status appearing as a + * separate message + */ + if (!WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} +# endif + +# ifndef OPENSSL_NO_NEXTPROTONEG +EXT_RETURN tls_construct_stoc_next_proto_neg_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + const unsigned char *npa; + unsigned int npalen; + int ret; + int npn_seen = s->s3->npn_seen; + + s->s3->npn_seen = 0; + if (!npn_seen || s->ctx->ext.npn_advertised_cb == NULL) + return EXT_RETURN_NOT_SENT; + + ret = s->ctx->ext.npn_advertised_cb(s, &npa, &npalen, + s->ctx->ext.npn_advertised_cb_arg); + if (ret == SSL_TLSEXT_ERR_OK) { + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg) + || !WPACKET_sub_memcpy_u16(pkt, npa, npalen)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + s->s3->npn_seen = 1; + } + + return EXT_RETURN_SENT; +} +# endif + +EXT_RETURN tls_construct_stoc_alpn_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (s->s3->alpn_selected == NULL) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, + TLSEXT_TYPE_application_layer_protocol_negotiation) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_sub_memcpy_u8(pkt, s->s3->alpn_selected, + s->s3->alpn_selected_len) + || !WPACKET_close(pkt) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_ALPN_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +# ifndef OPENSSL_NO_SRTP +EXT_RETURN tls_construct_stoc_use_srtp_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + if (s->srtp_profile == NULL) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_use_srtp) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_put_bytes_u16(pkt, 2) + || !WPACKET_put_bytes_u16(pkt, s->srtp_profile->id) + || !WPACKET_put_bytes_u8(pkt, 0) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} +# endif + +EXT_RETURN tls_construct_stoc_etm_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (!s->ext.use_etm) + return EXT_RETURN_NOT_SENT; + + /* + * Don't use encrypt_then_mac if AEAD or RC4 might want to disable + * for other cases too. + */ + if (s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD + || s->s3->tmp.new_cipher->algorithm_enc == SSL_RC4 + || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT + || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12) { + s->ext.use_etm = 0; + return EXT_RETURN_NOT_SENT; + } + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac) + || !WPACKET_put_bytes_u16(pkt, 0)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_ETM_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +EXT_RETURN tls_construct_stoc_ems_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if ((s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) == 0) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret) + || !WPACKET_put_bytes_u16(pkt, 0)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_EMS_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +EXT_RETURN tls_construct_stoc_supported_versions_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_put_bytes_u16(pkt, s->version) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +EXT_RETURN tls_construct_stoc_key_share_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ +# ifndef OPENSSL_NO_TLS1_3 + unsigned char *encodedPoint; + size_t encoded_pt_len = 0; + EVP_PKEY *ckey = s->s3->peer_tmp, *skey = NULL; + + if (s->hello_retry_request == SSL_HRR_PENDING) { + if (ckey != NULL) { + /* Original key_share was acceptable so don't ask for another one */ + return EXT_RETURN_NOT_SENT; + } + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_put_bytes_u16(pkt, s->s3->group_id) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; + } + + if (ckey == NULL) { + /* No key_share received from client - must be resuming */ + if (!s->hit || !tls13_generate_handshake_secret(s, NULL, 0)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + return EXT_RETURN_NOT_SENT; + } + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_put_bytes_u16(pkt, s->s3->group_id)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + skey = ssl_generate_pkey(ckey); + if (skey == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE_NTLS, + ERR_R_MALLOC_FAILURE); + return EXT_RETURN_FAIL; + } + + /* Generate encoding of server key */ + encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(skey, &encodedPoint); + if (encoded_pt_len == 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE_NTLS, + ERR_R_EC_LIB); + EVP_PKEY_free(skey); + return EXT_RETURN_FAIL; + } + + if (!WPACKET_sub_memcpy_u16(pkt, encodedPoint, encoded_pt_len) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE_NTLS, + ERR_R_INTERNAL_ERROR); + EVP_PKEY_free(skey); + OPENSSL_free(encodedPoint); + return EXT_RETURN_FAIL; + } + OPENSSL_free(encodedPoint); + + /* This causes the crypto state to be updated based on the derived keys */ + s->s3->tmp.pkey = skey; + if (ssl_derive(s, skey, ckey, 1) == 0) { + /* SSLfatal_ntls() already called */ + return EXT_RETURN_FAIL; + } + return EXT_RETURN_SENT; +# else + return EXT_RETURN_FAIL; +# endif +} + +EXT_RETURN tls_construct_stoc_cookie_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ +# ifndef OPENSSL_NO_TLS1_3 + unsigned char *hashval1, *hashval2, *appcookie1, *appcookie2, *cookie; + unsigned char *hmac, *hmac2; + size_t startlen, ciphlen, totcookielen, hashlen, hmaclen, appcookielen; + EVP_MD_CTX *hctx; + EVP_PKEY *pkey; + int ret = EXT_RETURN_FAIL; + + if ((s->s3->flags & TLS1_FLAGS_STATELESS) == 0) + return EXT_RETURN_NOT_SENT; + + if (s->ctx->gen_stateless_cookie_cb == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE_NTLS, + SSL_R_NO_COOKIE_CALLBACK_SET); + return EXT_RETURN_FAIL; + } + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_cookie) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_get_total_written(pkt, &startlen) + || !WPACKET_reserve_bytes(pkt, MAX_COOKIE_SIZE, &cookie) + || !WPACKET_put_bytes_u16(pkt, COOKIE_STATE_FORMAT_VERSION) + || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION) + || !WPACKET_put_bytes_u16(pkt, s->s3->group_id) + || !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt, + &ciphlen) + /* Is there a key_share extension present in this HRR? */ + || !WPACKET_put_bytes_u8(pkt, s->s3->peer_tmp == NULL) + || !WPACKET_put_bytes_u32(pkt, (unsigned int)time(NULL)) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &hashval1)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + /* + * Get the hash of the initial ClientHello. ssl_handshake_hash() operates + * on raw buffers, so we first reserve sufficient bytes (above) and then + * subsequently allocate them (below) + */ + if (!ssl3_digest_cached_records(s, 0) + || !ssl_handshake_hash(s, hashval1, EVP_MAX_MD_SIZE, &hashlen)) { + /* SSLfatal_ntls() already called */ + return EXT_RETURN_FAIL; + } + + if (!WPACKET_allocate_bytes(pkt, hashlen, &hashval2) + || !ossl_assert(hashval1 == hashval2) + || !WPACKET_close(pkt) + || !WPACKET_start_sub_packet_u8(pkt) + || !WPACKET_reserve_bytes(pkt, SSL_COOKIE_LENGTH, &appcookie1)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + /* Generate the application cookie */ + if (s->ctx->gen_stateless_cookie_cb(s, appcookie1, &appcookielen) == 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE_NTLS, + SSL_R_COOKIE_GEN_CALLBACK_FAILURE); + return EXT_RETURN_FAIL; + } + + if (!WPACKET_allocate_bytes(pkt, appcookielen, &appcookie2) + || !ossl_assert(appcookie1 == appcookie2) + || !WPACKET_close(pkt) + || !WPACKET_get_total_written(pkt, &totcookielen) + || !WPACKET_reserve_bytes(pkt, SHA256_DIGEST_LENGTH, &hmac)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + hmaclen = SHA256_DIGEST_LENGTH; + + totcookielen -= startlen; + if (!ossl_assert(totcookielen <= MAX_COOKIE_SIZE - SHA256_DIGEST_LENGTH)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + /* HMAC the cookie */ + hctx = EVP_MD_CTX_create(); + pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, + s->session_ctx->ext.cookie_hmac_key, + sizeof(s->session_ctx->ext + .cookie_hmac_key)); + if (hctx == NULL || pkey == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE_NTLS, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if (EVP_DigestSignInit(hctx, NULL, EVP_sha256(), NULL, pkey) <= 0 + || EVP_DigestSign(hctx, hmac, &hmaclen, cookie, + totcookielen) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!ossl_assert(totcookielen + hmaclen <= MAX_COOKIE_SIZE)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!WPACKET_allocate_bytes(pkt, hmaclen, &hmac2) + || !ossl_assert(hmac == hmac2) + || !ossl_assert(cookie == hmac - totcookielen) + || !WPACKET_close(pkt) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + ret = EXT_RETURN_SENT; + + err: + EVP_MD_CTX_free(hctx); + EVP_PKEY_free(pkey); + return ret; +# else + return EXT_RETURN_FAIL; +# endif +} + +EXT_RETURN tls_construct_stoc_cryptopro_bug_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + const unsigned char cryptopro_ext[36] = { + 0xfd, 0xe8, /* 65000 */ + 0x00, 0x20, /* 32 bytes length */ + 0x30, 0x1e, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85, + 0x03, 0x02, 0x02, 0x09, 0x30, 0x08, 0x06, 0x06, + 0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08, + 0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17 + }; + + if (((s->s3->tmp.new_cipher->id & 0xFFFF) != 0x80 + && (s->s3->tmp.new_cipher->id & 0xFFFF) != 0x81) + || (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG) == 0) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_memcpy(pkt, cryptopro_ext, sizeof(cryptopro_ext))) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +EXT_RETURN tls_construct_stoc_early_data_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + if (context == SSL_EXT_TLS1_3_NEW_SESSION_TICKET) { + if (s->max_early_data == 0) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_put_bytes_u32(pkt, s->max_early_data) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; + } + + if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA_NTLS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +EXT_RETURN tls_construct_stoc_psk_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (!s->hit) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_put_bytes_u16(pkt, s->ext.tick_identity) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_PSK_NTLS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +#endif diff --git a/ssl/statem_ntls/ssl_local_ntls.h b/ssl/statem_ntls/ssl_local_ntls.h new file mode 100644 index 000000000..414c5a61c --- /dev/null +++ b/ssl/statem_ntls/ssl_local_ntls.h @@ -0,0 +1,79 @@ +/* + * Copyright 2019 The BabaSSL Project Authors. All Rights Reserved. + */ + +#ifndef OSSL_SSL_LOCAL_NTLS_H +# define OSSL_SSL_LOCAL_NTLS_H + + +# include "../ssl_local.h" +# include "statem.h" + +# define SSL_IS_NTLS(s) (s->version == NTLS_VERSION) + +# define SSL_CLIENT_USE_SIGALGS_NTLS(s) \ + (SSL_CLIENT_USE_TLS1_2_CIPHERS(s) || (s->client_version == NTLS_VERSION)) + +/* + *optimize later + *This is the default ID for NTLS context + */ +# define SM2_DEFAULT_ID "1234567812345678" +# define SM2_DEFAULT_ID_LEN (sizeof(SM2_DEFAULT_ID) - 1) + +__owur const SSL_METHOD *ntls_method(void); +__owur const SSL_METHOD *ntls_server_method(void); +__owur const SSL_METHOD *ntls_client_method(void); + +extern const SSL3_ENC_METHOD NTLS_enc_data; +__owur int ssl_x509err2alert_ntls(int type); +__owur int ssl3_do_write_ntls(SSL *s, int type); +__owur unsigned long ssl3_output_cert_chain_ntls(SSL *s, WPACKET *pkt, + CERT_PKEY *cpk); +__owur int tls_close_construct_packet_ntls(SSL *s, WPACKET *pkt, int htype); +__owur int tls_setup_handshake_ntls(SSL *s); + +__owur int ssl_allow_compression_ntls(SSL *s); + +__owur int ssl_version_supported_ntls(const SSL *s, int version, + const SSL_METHOD **meth); + +__owur int ssl_set_client_hello_version_ntls(SSL *s); +__owur int ssl_check_version_downgrade_ntls(SSL *s); +__owur int ssl_set_version_bound_ntls(int method_version, int version, int *bound); +__owur int ssl_choose_server_version_ntls(SSL *s, CLIENTHELLO_MSG *hello, + DOWNGRADE *dgrd); +__owur int ssl_choose_client_version_ntls(SSL *s, int version, + RAW_EXTENSION *extensions); +__owur int ssl_get_min_max_version_ntls(const SSL *s, int *min_version, + int *max_version, int *real_max); + +__owur int ntls_alert_code(int code); +__owur int send_certificate_request_ntls(SSL *s); + +/* statem/extensions_cust.c */ + +custom_ext_method *custom_ext_find_ntls(const custom_ext_methods *exts, + ENDPOINT role, unsigned int ext_type, + size_t *idx); + +void custom_ext_init_ntls(custom_ext_methods *meths); + +__owur int custom_ext_parse_ntls(SSL *s, unsigned int context, unsigned int ext_type, + const unsigned char *ext_data, size_t ext_size, + X509 *x, size_t chainidx); +__owur int custom_ext_add_ntls(SSL *s, int context, WPACKET *pkt, X509 *x, + size_t chainidx, int maxversion); + +__owur int custom_exts_copy_ntls(custom_ext_methods *dst, + const custom_ext_methods *src); +__owur int custom_exts_copy_flags_ntls(custom_ext_methods *dst, + const custom_ext_methods *src); +void custom_exts_free_ntls(custom_ext_methods *exts); + +void ssl_comp_free_compression_methods_int(void); + +/* ssl_mcnf.c */ +void ssl_ctx_system_config(SSL_CTX *ctx); + +#endif diff --git a/ssl/statem_ntls/statem.c b/ssl/statem_ntls/statem.c new file mode 100644 index 000000000..414ab30c3 --- /dev/null +++ b/ssl/statem_ntls/statem.c @@ -0,0 +1,1004 @@ +/* + * Copyright 2019 The BabaSSL Project Authors. All Rights Reserved. + */ + +#include "internal/cryptlib.h" +#include +#include "ssl_local_ntls.h" +#include "statem_local_ntls.h" +#include + +/* + * This file implements the SSL/TLS state machines. + * + * There are two primary state machines: + * + * 1) Message flow state machine + * 2) Handshake state machine + * + * The Message flow state machine controls the reading and sending of messages + * including handling of non-blocking IO events, flushing of the underlying + * write BIO, handling unexpected messages, etc. It is itself broken into two + * separate sub-state machines which control reading and writing respectively. + * + * The Handshake state machine keeps track of the current SSL/TLS handshake + * state. Transitions of the handshake state are the result of events that + * occur within the Message flow state machine. + * + * Overall it looks like this: + * + * --------------------------------------------- ------------------- + * | | | | + * | Message flow state machine | | | + * | | | | + * | -------------------- -------------------- | Transition | Handshake state | + * | | MSG_FLOW_READING | | MSG_FLOW_WRITING | | Event | machine | + * | | sub-state | | sub-state | |----------->| | + * | | machine for | | machine for | | | | + * | | reading messages | | writing messages | | | | + * | -------------------- -------------------- | | | + * | | | | + * --------------------------------------------- ------------------- + * + */ +#if (!defined OPENSSL_NO_NTLS) && (!defined OPENSSL_NO_SM2) \ + && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) + +/* Sub state machine return values */ +typedef enum { + /* Something bad happened or NBIO */ + SUB_STATE_ERROR, + /* Sub state finished go to the next sub state */ + SUB_STATE_FINISHED, + /* Sub state finished and handshake was completed */ + SUB_STATE_END_HANDSHAKE +} SUB_STATE_RETURN; + +static void init_read_state_machine_ntls(SSL *s); +static SUB_STATE_RETURN read_state_machine_ntls(SSL *s); +static void init_write_state_machine_ntls(SSL *s); +static SUB_STATE_RETURN write_state_machine_ntls(SSL *s); + +OSSL_HANDSHAKE_STATE SSL_get_state_ntls(const SSL *ssl) +{ + return ssl->statem.hand_state; +} + +int SSL_in_init_ntls(const SSL *s) +{ + return s->statem.in_init; +} + +int SSL_is_init_finished_ntls(const SSL *s) +{ + return !(s->statem.in_init) && (s->statem.hand_state == TLS_ST_OK); +} + +int SSL_in_before_ntls(const SSL *s) +{ + /* + * Historically being "in before" meant before anything had happened. In the + * current code though we remain in the "before" state for a while after we + * have started the handshake process (e.g. as a server waiting for the + * first message to arrive). There "in before" is taken to mean "in before" + * and not started any handshake process yet. + */ + return (s->statem.hand_state == TLS_ST_BEFORE) + && (s->statem.state == MSG_FLOW_UNINITED); +} + +/* + * Clear the state machine state and reset back to MSG_FLOW_UNINITED + */ +void ossl_statem_clear_ntls(SSL *s) +{ + s->statem.state = MSG_FLOW_UNINITED; + s->statem.hand_state = TLS_ST_BEFORE; + s->statem.in_init = 1; + s->statem.no_cert_verify = 0; +} + +/* + * Set the state machine up ready for a renegotiation handshake + */ +void ossl_statem_set_renegotiate_ntls(SSL *s) +{ + s->statem.in_init = 1; + s->statem.request_state = TLS_ST_SW_HELLO_REQ; +} + +/* + * Put the state machine into an error state and send an alert if appropriate. + * This is a permanent error for the current connection. + */ +void ossl_statem_fatal_ntls(SSL *s, int al, int func, int reason, const char *file, + int line) +{ + ERR_put_error(ERR_LIB_SSL, func, reason, file, line); + /* We shouldn't call SSLfatal_ntls() twice. Once is enough */ + if (s->statem.in_init && s->statem.state == MSG_FLOW_ERROR) + return; + s->statem.in_init = 1; + s->statem.state = MSG_FLOW_ERROR; + if (al != SSL_AD_NO_ALERT + && s->statem.enc_write_state != ENC_WRITE_STATE_INVALID) + ssl3_send_alert(s, SSL3_AL_FATAL, al); +} + +/* + * This macro should only be called if we are already expecting to be in + * a fatal error state. We verify that we are, and set it if not (this would + * indicate a bug). + */ +# define check_fatal(s, f) \ + do { \ + if (!ossl_assert((s)->statem.in_init \ + && (s)->statem.state == MSG_FLOW_ERROR)) \ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, (f), \ + SSL_R_MISSING_FATAL); \ + } while (0) + +/* + * Discover whether the current connection is in the error state. + * + * Valid return values are: + * 1: Yes + * 0: No + */ +int ossl_statem_in_error_ntls(const SSL *s) +{ + if (s->statem.state == MSG_FLOW_ERROR) + return 1; + + return 0; +} + +void ossl_statem_set_in_init_ntls(SSL *s, int init) +{ + s->statem.in_init = init; +} + +int ossl_statem_get_in_handshake_ntls(SSL *s) +{ + return s->statem.in_handshake; +} + +void ossl_statem_set_in_handshake_ntls(SSL *s, int inhand) +{ + if (inhand) + s->statem.in_handshake++; + else + s->statem.in_handshake--; +} + +/* Are we in a sensible state to skip over unreadable early data? */ +int ossl_statem_skip_early_data_ntls(SSL *s) +{ + if (s->ext.early_data != SSL_EARLY_DATA_REJECTED) + return 0; + + if (!s->server + || s->statem.hand_state != TLS_ST_EARLY_DATA + || s->hello_retry_request == SSL_HRR_COMPLETE) + return 0; + + return 1; +} + +/* + * Called when we are in SSL_read*(), SSL_write*(), or SSL_accept() + * /SSL_connect()/SSL_do_handshake(). Used to test whether we are in an early + * data state and whether we should attempt to move the handshake on if so. + * |sending| is 1 if we are attempting to send data (SSL_write*()), 0 if we are + * attempting to read data (SSL_read*()), or -1 if we are in SSL_do_handshake() + * or similar. + */ +void ossl_statem_check_finish_init_ntls(SSL *s, int sending) +{ + if (sending == -1) { + if (s->statem.hand_state == TLS_ST_PENDING_EARLY_DATA_END + || s->statem.hand_state == TLS_ST_EARLY_DATA) { + ossl_statem_set_in_init_ntls(s, 1); + if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) { + /* + * SSL_connect() or SSL_do_handshake() has been called directly. + * We don't allow any more writing of early data. + */ + s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING; + } + } + } else if (!s->server) { + if ((sending && (s->statem.hand_state == TLS_ST_PENDING_EARLY_DATA_END + || s->statem.hand_state == TLS_ST_EARLY_DATA) + && s->early_data_state != SSL_EARLY_DATA_WRITING) + || (!sending && s->statem.hand_state == TLS_ST_EARLY_DATA)) { + ossl_statem_set_in_init_ntls(s, 1); + /* + * SSL_write() has been called directly. We don't allow any more + * writing of early data. + */ + if (sending && s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) + s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING; + } + } else { + if (s->early_data_state == SSL_EARLY_DATA_FINISHED_READING + && s->statem.hand_state == TLS_ST_EARLY_DATA) + ossl_statem_set_in_init_ntls(s, 1); + } +} + +void ossl_statem_set_hello_verify_done_ntls(SSL *s) +{ + s->statem.state = MSG_FLOW_UNINITED; + s->statem.in_init = 1; + /* + * This will get reset (briefly) back to TLS_ST_BEFORE when we enter + * state_machine() because |state| is MSG_FLOW_UNINITED, but until then any + * calls to SSL_in_before_ntls() will return false. Also calls to + * SSL_state_string() and SSL_state_string_long() will return something + * sensible. + */ + s->statem.hand_state = TLS_ST_SR_CLNT_HELLO; +} + +int ossl_statem_connect_ntls(SSL *s) +{ + return state_machine_ntls(s, 0); +} + +int ossl_statem_accept_ntls(SSL *s) +{ + return state_machine_ntls(s, 1); +} + +typedef void (*info_cb) (const SSL *, int, int); + +static info_cb get_callback(SSL *s) +{ + if (s->info_callback != NULL) + return s->info_callback; + else if (s->ctx->info_callback != NULL) + return s->ctx->info_callback; + + return NULL; +} + +/* + * The main message flow state machine. We start in the MSG_FLOW_UNINITED or + * MSG_FLOW_FINISHED state and finish in MSG_FLOW_FINISHED. Valid states and + * transitions are as follows: + * + * MSG_FLOW_UNINITED MSG_FLOW_FINISHED + * | | + * +-----------------------+ + * v + * MSG_FLOW_WRITING <---> MSG_FLOW_READING + * | + * V + * MSG_FLOW_FINISHED + * | + * V + * [SUCCESS] + * + * We may exit at any point due to an error or NBIO event. If an NBIO event + * occurs then we restart at the point we left off when we are recalled. + * MSG_FLOW_WRITING and MSG_FLOW_READING have sub-state machines associated with them. + * + * In addition to the above there is also the MSG_FLOW_ERROR state. We can move + * into that state at any point in the event that an irrecoverable error occurs. + * + * Valid return values are: + * 1: Success + * <=0: NBIO or error + */ +int state_machine_ntls(SSL *s, int server) +{ + BUF_MEM *buf = NULL; + void (*cb) (const SSL *ssl, int type, int val) = NULL; + OSSL_STATEM *st = &s->statem; + int ret = -1; + int ssret; + + if (st->state == MSG_FLOW_ERROR) { + /* Shouldn't have been called if we're already in the error state */ + return -1; + } + + ERR_clear_error(); + clear_sys_error(); + + cb = get_callback(s); + +# ifndef OPENSSL_NO_KEYLESS + if (s->keyless_ntls && s->keyless_again) + goto keyless_recover; +# endif +# ifndef OPENSSL_NO_LURK + if (s->lurk_ntls && s->lurk_again) + goto keyless_recover; +# endif + + st->in_handshake++; + if (!SSL_in_init_ntls(s) || SSL_in_before_ntls(s)) { + /* + * If we are stateless then we already called SSL_clear() - don't do + * it again and clear the STATELESS flag itself. + */ + if ((s->s3->flags & TLS1_FLAGS_STATELESS) == 0 && !SSL_clear(s)) + return -1; + } + + /* Initialise state machine */ + if (st->state == MSG_FLOW_UNINITED + || st->state == MSG_FLOW_FINISHED) { + if (st->state == MSG_FLOW_UNINITED) { + st->hand_state = TLS_ST_BEFORE; + st->request_state = TLS_ST_BEFORE; + } + + s->server = server; + if (cb != NULL) { + cb(s, SSL_CB_HANDSHAKE_START, 1); + } + + if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) { + SSLfatal_ntls(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE_NTLS, + ERR_R_INTERNAL_ERROR); + goto end; + } + + if (s->init_buf == NULL) { + if ((buf = BUF_MEM_new()) == NULL) { + SSLfatal_ntls(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE_NTLS, + ERR_R_INTERNAL_ERROR); + goto end; + } + if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { + SSLfatal_ntls(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE_NTLS, + ERR_R_INTERNAL_ERROR); + goto end; + } + s->init_buf = buf; + buf = NULL; + } + + if (!ssl3_setup_buffers(s)) { + SSLfatal_ntls(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE_NTLS, + ERR_R_INTERNAL_ERROR); + goto end; + } + s->init_num = 0; + + /* + * Should have been reset by tls_process_finished_ntls, too. + */ + s->s3->change_cipher_spec = 0; + + /* + * Ok, we now need to push on a buffering BIO ...but not with + * SCTP + */ +# ifndef OPENSSL_NO_SCTP + if ( !BIO_dgram_is_sctp(SSL_get_wbio(s))) +# endif + if (!ssl_init_wbio_buffer(s)) { + SSLfatal_ntls(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE_NTLS, + ERR_R_INTERNAL_ERROR); + goto end; + } + + if ((SSL_in_before_ntls(s)) + || s->renegotiate) { + if (!tls_setup_handshake_ntls(s)) { + /* SSLfatal_ntls() already called */ + goto end; + } + + if (SSL_IS_FIRST_HANDSHAKE(s)) + st->read_state_first_init = 1; + } + + st->state = MSG_FLOW_WRITING; + init_write_state_machine_ntls(s); + } + + while (st->state != MSG_FLOW_FINISHED) { +# if !(defined(OPENSSL_NO_KEYLESS) && defined(OPENSSL_NO_LURK)) +keyless_recover: +# endif + if (st->state == MSG_FLOW_READING) { + ssret = read_state_machine_ntls(s); + if (ssret == SUB_STATE_FINISHED) { + st->state = MSG_FLOW_WRITING; + init_write_state_machine_ntls(s); +# if !(defined(OPENSSL_NO_KEYLESS) && defined(OPENSSL_NO_LURK)) + } else if (ssret == SSL_ERROR_WANT_KEYLESS_RESULT) { + s->rwstate = SSL_KEYLESS_CB; + return -1; +# endif + } else { + /* NBIO or error */ + goto end; + } + } else if (st->state == MSG_FLOW_WRITING) { + ssret = write_state_machine_ntls(s); + if (ssret == SUB_STATE_FINISHED) { + st->state = MSG_FLOW_READING; + init_read_state_machine_ntls(s); + } else if (ssret == SUB_STATE_END_HANDSHAKE) { + st->state = MSG_FLOW_FINISHED; +# if !(defined(OPENSSL_NO_KEYLESS) && defined(OPENSSL_NO_LURK)) + } else if (ssret == SSL_ERROR_WANT_KEYLESS_RESULT) { + s->rwstate = SSL_KEYLESS_CB; + return -1; +# endif + } else { + /* NBIO or error */ + goto end; + } + } else { + /* Error */ + check_fatal(s, SSL_F_STATE_MACHINE_NTLS); + SSLerr(SSL_F_STATE_MACHINE_NTLS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + goto end; + } + } + + ret = 1; + + end: + st->in_handshake--; + + BUF_MEM_free(buf); + if (cb != NULL) { + if (server) + cb(s, SSL_CB_ACCEPT_EXIT, ret); + else + cb(s, SSL_CB_CONNECT_EXIT, ret); + } + return ret; +} + +/* + * Initialise the MSG_FLOW_READING sub-state machine + */ +static void init_read_state_machine_ntls(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + + st->read_state = READ_STATE_HEADER; +} + +static int grow_init_buf(SSL *s, size_t size) { + + size_t msg_offset = (char *)s->init_msg - s->init_buf->data; + + if (!BUF_MEM_grow_clean(s->init_buf, (int)size)) + return 0; + + if (size < msg_offset) + return 0; + + s->init_msg = s->init_buf->data + msg_offset; + + return 1; +} + +/* + * This function implements the sub-state machine when the message flow is in + * MSG_FLOW_READING. The valid sub-states and transitions are: + * + * READ_STATE_HEADER <--+<-------------+ + * | | | + * v | | + * READ_STATE_BODY -----+-->READ_STATE_POST_PROCESS + * | | + * +----------------------------+ + * v + * [SUB_STATE_FINISHED] + * + * READ_STATE_HEADER has the responsibility for reading in the message header + * and transitioning the state of the handshake state machine. + * + * READ_STATE_BODY reads in the rest of the message and then subsequently + * processes it. + * + * READ_STATE_POST_PROCESS is an optional step that may occur if some post + * processing activity performed on the message may block. + * + * Any of the above states could result in an NBIO event occurring in which case + * control returns to the calling application. When this function is recalled we + * will resume in the same state where we left off. + */ +static SUB_STATE_RETURN read_state_machine_ntls(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + int ret, mt; + size_t len = 0; + int (*transition) (SSL *s, int mt); + PACKET pkt; + MSG_PROCESS_RETURN(*process_message) (SSL *s, PACKET *pkt); + WORK_STATE(*post_process_message) (SSL *s, WORK_STATE wst); + size_t (*max_message_size) (SSL *s); + void (*cb) (const SSL *ssl, int type, int val) = NULL; + + cb = get_callback(s); + + if (s->server) { + transition = ossl_statem_server_read_transition_ntls; + process_message = ossl_statem_server_process_message_ntls; + max_message_size = ossl_statem_server_max_message_size_ntls; + post_process_message = ossl_statem_server_post_process_message_ntls; + } else { + transition = ossl_statem_client_read_transition_ntls; + process_message = ossl_statem_client_process_message_ntls; + max_message_size = ossl_statem_client_max_message_size_ntls; + post_process_message = ossl_statem_client_post_process_message_ntls; + } + +# ifndef OPENSSL_NO_KEYLESS + if (s->keyless_ntls && s->keyless_again) + goto keyless_recover; +# endif +# ifndef OPENSSL_NO_LURK + if (s->lurk_ntls && s->lurk_again) + goto keyless_recover; +# endif + + if (st->read_state_first_init) { + s->first_packet = 1; + st->read_state_first_init = 0; + } + + while (1) { + switch (st->read_state) { + case READ_STATE_HEADER: + /* Get the state the peer wants to move to */ + + ret = tls_get_message_header_ntls(s, &mt); + + if (ret == 0) { + /* Could be non-blocking IO */ + return SUB_STATE_ERROR; + } + + if (cb != NULL) { + /* Notify callback of an impending state change */ + if (s->server) + cb(s, SSL_CB_ACCEPT_LOOP, 1); + else + cb(s, SSL_CB_CONNECT_LOOP, 1); + } + /* + * Validate that we are allowed to move to the new state and move + * to that state if so + */ + if (!transition(s, mt)) + return SUB_STATE_ERROR; + + if (s->s3->tmp.message_size > max_message_size(s)) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_READ_STATE_MACHINE_NTLS, + SSL_R_EXCESSIVE_MESSAGE_SIZE); + return SUB_STATE_ERROR; + } + + if (s->s3->tmp.message_size > 0 + && !grow_init_buf(s, s->s3->tmp.message_size + + SSL3_HM_HEADER_LENGTH)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE_NTLS, + ERR_R_BUF_LIB); + return SUB_STATE_ERROR; + } + + st->read_state = READ_STATE_BODY; + /* Fall through */ + + case READ_STATE_BODY: + ret = tls_get_message_body_ntls(s, &len); + if (ret == 0) { + /* Could be non-blocking IO */ + return SUB_STATE_ERROR; + } + + + s->first_packet = 0; + if (!PACKET_buf_init(&pkt, s->init_msg, len)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE_NTLS, + ERR_R_INTERNAL_ERROR); + return SUB_STATE_ERROR; + } + +# if !(defined(OPENSSL_NO_KEYLESS) && defined(OPENSSL_NO_LURK)) +keyless_recover: +# endif + ret = process_message(s, &pkt); + + /* Discard the packet data */ + s->init_num = 0; + + switch (ret) { + case MSG_PROCESS_ERROR: +# ifndef OPENSSL_NO_KEYLESS + if (s->keyless_ntls && s->keyless_again) + return SSL_ERROR_WANT_KEYLESS_RESULT; +# endif +# ifndef OPENSSL_NO_LURK + if (s->lurk_ntls && s->lurk_again) + return SSL_ERROR_WANT_KEYLESS_RESULT; +# endif + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE_NTLS, + ERR_R_INTERNAL_ERROR); + return SUB_STATE_ERROR; + + case MSG_PROCESS_FINISHED_READING: + return SUB_STATE_FINISHED; + + case MSG_PROCESS_CONTINUE_PROCESSING: + st->read_state = READ_STATE_POST_PROCESS; + st->read_state_work = WORK_MORE_A; + break; + + default: + st->read_state = READ_STATE_HEADER; + break; + } + break; + + case READ_STATE_POST_PROCESS: + st->read_state_work = post_process_message(s, st->read_state_work); + switch (st->read_state_work) { + case WORK_ERROR: + check_fatal(s, SSL_F_READ_STATE_MACHINE_NTLS); + /* Fall through */ + case WORK_MORE_A: + case WORK_MORE_B: + case WORK_MORE_C: + return SUB_STATE_ERROR; + + case WORK_FINISHED_CONTINUE: + st->read_state = READ_STATE_HEADER; + break; + + case WORK_FINISHED_STOP: + return SUB_STATE_FINISHED; + + default: + /* Shouldn't happen */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE_NTLS, + ERR_R_INTERNAL_ERROR); + return SUB_STATE_ERROR; + } + break; + + default: + /* Shouldn't happen */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE_NTLS, + ERR_R_INTERNAL_ERROR); + return SUB_STATE_ERROR; + } + } +} + +/* + * Send a previously constructed message to the peer. + */ +static int statem_do_write(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + + if (st->hand_state == TLS_ST_CW_CHANGE + || st->hand_state == TLS_ST_SW_CHANGE) { + return ssl3_do_write_ntls(s, SSL3_RT_CHANGE_CIPHER_SPEC); + } else { + return ssl_do_write(s); + } +} + +/* + * Initialise the MSG_FLOW_WRITING sub-state machine + */ +static void init_write_state_machine_ntls(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + + st->write_state = WRITE_STATE_TRANSITION; +} + +/* + * This function implements the sub-state machine when the message flow is in + * MSG_FLOW_WRITING. The valid sub-states and transitions are: + * + * +-> WRITE_STATE_TRANSITION ------> [SUB_STATE_FINISHED] + * | | + * | v + * | WRITE_STATE_PRE_WORK -----> [SUB_STATE_END_HANDSHAKE] + * | | + * | v + * | WRITE_STATE_SEND + * | | + * | v + * | WRITE_STATE_POST_WORK + * | | + * +-------------+ + * + * WRITE_STATE_TRANSITION transitions the state of the handshake state machine + + * WRITE_STATE_PRE_WORK performs any work necessary to prepare the later + * sending of the message. This could result in an NBIO event occurring in + * which case control returns to the calling application. When this function + * is recalled we will resume in the same state where we left off. + * + * WRITE_STATE_SEND sends the message and performs any work to be done after + * sending. + * + * WRITE_STATE_POST_WORK performs any work necessary after the sending of the + * message has been completed. As for WRITE_STATE_PRE_WORK this could also + * result in an NBIO event. + */ +static SUB_STATE_RETURN write_state_machine_ntls(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + int ret; + WRITE_TRAN(*transition) (SSL *s); + WORK_STATE(*pre_work) (SSL *s, WORK_STATE wst); + WORK_STATE(*post_work) (SSL *s, WORK_STATE wst); + int (*get_construct_message_f) (SSL *s, WPACKET *pkt, + int (**confunc) (SSL *s, WPACKET *pkt), + int *mt); + void (*cb) (const SSL *ssl, int type, int val) = NULL; + int (*confunc) (SSL *s, WPACKET *pkt); + int mt; + WPACKET pkt; + + cb = get_callback(s); + + if (s->server) { + transition = ossl_statem_server_write_transition_ntls; + pre_work = ossl_statem_server_pre_work_ntls; + post_work = ossl_statem_server_post_work_ntls; + get_construct_message_f = ossl_statem_server_construct_message_ntls; + } else { + transition = ossl_statem_client_write_transition_ntls; + pre_work = ossl_statem_client_pre_work_ntls; + post_work = ossl_statem_client_post_work_ntls; + get_construct_message_f = ossl_statem_client_construct_message_ntls; + } + +# ifndef OPENSSL_NO_KEYLESS + if (s->keyless_ntls && s->keyless_again) + goto keyless_recover; +# endif +# ifndef OPENSSL_NO_LURK + if (s->lurk_ntls && s->lurk_again) + goto keyless_recover; +# endif + + while (1) { + switch (st->write_state) { + case WRITE_STATE_TRANSITION: + if (cb != NULL) { + /* Notify callback of an impending state change */ + if (s->server) + cb(s, SSL_CB_ACCEPT_LOOP, 1); + else + cb(s, SSL_CB_CONNECT_LOOP, 1); + } + switch (transition(s)) { + case WRITE_TRAN_CONTINUE: + st->write_state = WRITE_STATE_PRE_WORK; + st->write_state_work = WORK_MORE_A; + break; + + case WRITE_TRAN_FINISHED: + return SUB_STATE_FINISHED; + break; + + case WRITE_TRAN_ERROR: + check_fatal(s, SSL_F_WRITE_STATE_MACHINE_NTLS); + return SUB_STATE_ERROR; + } + break; + + case WRITE_STATE_PRE_WORK: + switch (st->write_state_work = pre_work(s, st->write_state_work)) { + case WORK_ERROR: + check_fatal(s, SSL_F_WRITE_STATE_MACHINE_NTLS); + /* Fall through */ + case WORK_MORE_A: + case WORK_MORE_B: + case WORK_MORE_C: + return SUB_STATE_ERROR; + + case WORK_FINISHED_CONTINUE: + st->write_state = WRITE_STATE_SEND; + break; + + case WORK_FINISHED_STOP: + return SUB_STATE_END_HANDSHAKE; + + default: + /* should not happen */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE_NTLS, + ERR_R_INTERNAL_ERROR); + return SUB_STATE_ERROR; + } +# if !(defined(OPENSSL_NO_KEYLESS) && defined(OPENSSL_NO_LURK)) +keyless_recover: +# endif + if (!get_construct_message_f(s, &pkt, &confunc, &mt)) { + /* SSLfatal_ntls() already called */ + return SUB_STATE_ERROR; + } + if (mt == SSL3_MT_DUMMY) { + /* Skip construction and sending. This isn't a "real" state */ + st->write_state = WRITE_STATE_POST_WORK; + st->write_state_work = WORK_MORE_A; + break; + } + +# ifndef OPENSSL_NO_KEYLESS + if (s->keyless_again && s->keyless_result == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE_NTLS, + ERR_R_INTERNAL_ERROR); + return SUB_STATE_ERROR; + } +# endif +# ifndef OPENSSL_NO_LURK + if (s->lurk_again && s->lurk_result == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE_NTLS, + ERR_R_INTERNAL_ERROR); + return SUB_STATE_ERROR; + } +# endif + + if (!WPACKET_init(&pkt, s->init_buf) + || !ssl_set_handshake_header(s, &pkt, mt)) { + WPACKET_cleanup(&pkt); + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE_NTLS, + ERR_R_INTERNAL_ERROR); + return SUB_STATE_ERROR; + } + if (confunc != NULL && !confunc(s, &pkt)) { + WPACKET_cleanup(&pkt); +# ifndef OPENSSL_NO_KEYLESS + if (s->keyless_ntls && s->keyless_again) + return SSL_ERROR_WANT_KEYLESS_RESULT; +# endif +# ifndef OPENSSL_NO_LURK + if (s->lurk_ntls && s->lurk_again) + return SSL_ERROR_WANT_KEYLESS_RESULT; +# endif + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE_NTLS, + ERR_R_INTERNAL_ERROR); + return SUB_STATE_ERROR; + } + if (!ssl_close_construct_packet(s, &pkt, mt) + || !WPACKET_finish(&pkt)) { + WPACKET_cleanup(&pkt); + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE_NTLS, + ERR_R_INTERNAL_ERROR); + return SUB_STATE_ERROR; + } + + /* Fall through */ + + case WRITE_STATE_SEND: + ret = statem_do_write(s); + if (ret <= 0) { + return SUB_STATE_ERROR; + } + st->write_state = WRITE_STATE_POST_WORK; + st->write_state_work = WORK_MORE_A; + /* Fall through */ + + case WRITE_STATE_POST_WORK: + switch (st->write_state_work = post_work(s, st->write_state_work)) { + case WORK_ERROR: + check_fatal(s, SSL_F_WRITE_STATE_MACHINE_NTLS); + /* Fall through */ + case WORK_MORE_A: + case WORK_MORE_B: + case WORK_MORE_C: + return SUB_STATE_ERROR; + + case WORK_FINISHED_CONTINUE: + st->write_state = WRITE_STATE_TRANSITION; + break; + + case WORK_FINISHED_STOP: + return SUB_STATE_END_HANDSHAKE; + + default: + /* should not happen */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE_NTLS, + ERR_R_INTERNAL_ERROR); + return SUB_STATE_ERROR; + } + break; + + default: + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE_NTLS, + ERR_R_INTERNAL_ERROR); + return SUB_STATE_ERROR; + } + } +} + +/* + * Flush the write BIO + */ +int statem_flush_ntls(SSL *s) +{ + s->rwstate = SSL_WRITING; + if (BIO_flush(s->wbio) <= 0) { + return 0; + } + s->rwstate = SSL_NOTHING; + + return 1; +} + +/* + * Called by the record layer to determine whether application data is + * allowed to be received in the current handshake state or not. + * + * Return values are: + * 1: Yes (application data allowed) + * 0: No (application data not allowed) + */ +int ossl_statem_app_data_allowed_ntls(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + + if (st->state == MSG_FLOW_UNINITED) + return 0; + + if (!s->s3->in_read_app_data || (s->s3->total_renegotiations == 0)) + return 0; + + if (s->server) { + /* + * If we're a server and we haven't got as far as writing our + * ServerHello yet then we allow app data + */ + if (st->hand_state == TLS_ST_BEFORE + || st->hand_state == TLS_ST_SR_CLNT_HELLO) + return 1; + } else { + /* + * If we're a client and we haven't read the ServerHello yet then we + * allow app data + */ + if (st->hand_state == TLS_ST_CW_CLNT_HELLO) + return 1; + } + + return 0; +} + +/* + * This function returns 1 if TLS exporter is ready to export keying + * material, or 0 if otherwise. + */ +int ossl_statem_export_allowed_ntls(SSL *s) +{ + return s->s3->previous_server_finished_len != 0 + && s->statem.hand_state != TLS_ST_SW_FINISHED; +} + +/* + * Return 1 if early TLS exporter is ready to export keying material, + * or 0 if otherwise. + */ +int ossl_statem_export_early_allowed_ntls(SSL *s) +{ + /* + * The early exporter secret is only present on the server if we + * have accepted early_data. It is present on the client as long + * as we have sent early_data. + */ + return s->ext.early_data == SSL_EARLY_DATA_ACCEPTED + || (!s->server && s->ext.early_data != SSL_EARLY_DATA_NOT_SENT); +} + +#endif diff --git a/ssl/statem_ntls/statem.h b/ssl/statem_ntls/statem.h new file mode 100644 index 000000000..5baa3b1b6 --- /dev/null +++ b/ssl/statem_ntls/statem.h @@ -0,0 +1,157 @@ +/* + * Copyright 2019 The BabaSSL Project Authors. All Rights Reserved. + */ + +/***************************************************************************** + * * + * These enums should be considered PRIVATE to the state machine. No * + * non-state machine code should need to use these * + * * + *****************************************************************************/ +/* + * Valid return codes used for functions performing work prior to or after + * sending or receiving a message + */ + +typedef enum { + /* Something went wrong */ + WORK_ERROR_NTLS, + /* We're done working and there shouldn't be anything else to do after */ + WORK_FINISHED_STOP_NTLS, + /* We're done working move onto the next thing */ + WORK_FINISHED_CONTINUE_NTLS, + /* We're working on phase A */ + WORK_MORE_A_NTLS, + /* We're working on phase B */ + WORK_MORE_B_NTLS, + /* We're working on phase C */ + WORK_MORE_C_NTLS +} WORK_STATE_NTLS; + +/* Write transition return codes */ +typedef enum { + /* Something went wrong */ + WRITE_TRAN_ERROR_NTLS, + /* A transition was successfully completed and we should continue */ + WRITE_TRAN_CONTINUE_NTLS, + /* There is no more write work to be done */ + WRITE_TRAN_FINISHED_NTLS +} WRITE_TRAN_NTLS; + +/* Message flow states */ +typedef enum { + /* No handshake in progress */ + MSG_FLOW_UNINITED_NTLS, + /* A permanent error with this connection */ + MSG_FLOW_ERROR_NTLS, + /* We are reading messages */ + MSG_FLOW_READING_NTLS, + /* We are writing messages */ + MSG_FLOW_WRITING_NTLS, + /* Handshake has finished */ + MSG_FLOW_FINISHED_NTLS +} MSG_FLOW_STATE_NTLS; + +/* Read states */ +typedef enum { + READ_STATE_HEADER_NTLS, + READ_STATE_BODY_NTLS, + READ_STATE_POST_PROCESS_NTLS +} READ_STATE_NTLS; + +/* Write states */ +typedef enum { + WRITE_STATE_TRANSITION_NTLS, + WRITE_STATE_PRE_WORK_NTLS, + WRITE_STATE_SEND_NTLS, + WRITE_STATE_POST_WORK_NTLS +} WRITE_STATE_NTLS; + +typedef enum { + /* The enc_write_ctx can be used normally */ + ENC_WRITE_STATE_VALID_NTLS, + /* The enc_write_ctx cannot be used */ + ENC_WRITE_STATE_INVALID_NTLS, + /* Write alerts in plaintext, but otherwise use the enc_write_ctx */ + ENC_WRITE_STATE_WRITE_PLAIN_ALERTS_NTLS +} ENC_WRITE_STATES_NTLS; + +typedef enum { + /* The enc_read_ctx can be used normally */ + ENC_READ_STATE_VALID_NTLS, + /* We may receive encrypted or plaintext alerts */ + ENC_READ_STATE_ALLOW_PLAIN_ALERTS_NTLS +} ENC_READ_STATES_NTLS; + +/***************************************************************************** + * * + * This structure should be considered "opaque" to anything outside of the * + * state machine. No non-state machine code should be accessing the members * + * of this structure. * + * * + *****************************************************************************/ + +struct ossl_statem_st_ntls { + MSG_FLOW_STATE_NTLS state; + WRITE_STATE_NTLS write_state; + WORK_STATE_NTLS write_state_work; + READ_STATE_NTLS read_state; + WORK_STATE_NTLS read_state_work; + OSSL_HANDSHAKE_STATE hand_state; + /* The handshake state requested by an API call (e.g. HelloRequest) */ + OSSL_HANDSHAKE_STATE request_state; + int in_init; + int read_state_first_init; + /* true when we are actually in SSL_accept() or SSL_connect() */ + int in_handshake; + /* + * True when are processing a "real" handshake that needs cleaning up (not + * just a HelloRequest or similar). + */ + int cleanuphand; + /* Should we skip the CertificateVerify message? */ + unsigned int no_cert_verify; + int use_timer; + ENC_WRITE_STATES_NTLS enc_write_state; + ENC_READ_STATES_NTLS enc_read_state; +}; + +typedef struct ossl_statem_st_ntls OSSL_STATEM_NTLS; + +/***************************************************************************** + * * + * The following macros/functions represent the libssl internal API to the * + * state machine. Any libssl code may call these functions/macros * + * * + *****************************************************************************/ + +__owur int ossl_statem_accept_ntls(SSL *s); +__owur int ossl_statem_connect_ntls(SSL *s); +void ossl_statem_clear_ntls(SSL *s); +void ossl_statem_set_renegotiate_ntls(SSL *s); +void ossl_statem_fatal_ntls(SSL *s, int al, int func, int reason, const char *file, + int line); +# define SSL_AD_NO_ALERT -1 +# ifndef OPENSSL_NO_ERR +# define SSLfatal_ntls(s, al, f, r) ossl_statem_fatal_ntls((s), (al), (f), (r), \ + OPENSSL_FILE, OPENSSL_LINE) +# else +# define SSLfatal_ntls(s, al, f, r) ossl_statem_fatal_ntls((s), (al), (f), (r), NULL, 0) +# endif + +int ossl_statem_in_error_ntls(const SSL *s); +void ossl_statem_set_in_init_ntls(SSL *s, int init); +int ossl_statem_get_in_handshake_ntls(SSL *s); +void ossl_statem_set_in_handshake_ntls(SSL *s, int inhand); +__owur int ossl_statem_skip_early_data_ntls(SSL *s); +void ossl_statem_check_finish_init_ntls(SSL *s, int send); +void ossl_statem_set_hello_verify_done_ntls(SSL *s); +__owur int ossl_statem_app_data_allowed_ntls(SSL *s); +__owur int ossl_statem_export_allowed_ntls(SSL *s); +__owur int ossl_statem_export_early_allowed_ntls(SSL *s); + +/* Flush the write BIO */ +int statem_flush_ntls(SSL *s); +int state_machine_ntls(SSL *s, int server); + +int SSL_connection_is_ntls(SSL *s, int is_server); diff --git a/ssl/statem_ntls/statem_clnt.c b/ssl/statem_ntls/statem_clnt.c new file mode 100644 index 000000000..3ce488158 --- /dev/null +++ b/ssl/statem_ntls/statem_clnt.c @@ -0,0 +1,2927 @@ +/* + * Copyright 2019 The BabaSSL Project Authors. All Rights Reserved. + */ + +#include +#include +#include +#include "ssl_local_ntls.h" +#include "statem_local_ntls.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if (!defined OPENSSL_NO_NTLS) && (!defined OPENSSL_NO_SM2) \ + && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) +static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL *s, PACKET *pkt); +static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt); + +static ossl_inline int cert_req_allowed(SSL *s); +static int key_exchange_expected(SSL *s); +static int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, + WPACKET *pkt); + +/* + * Is a CertificateRequest message allowed at the moment or not? + * + * Return values are: + * 1: Yes + * 0: No + */ +static ossl_inline int cert_req_allowed(SSL *s) +{ + /* TLS does not like anon-DH with client cert */ + if ((s->version > SSL3_VERSION + && (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)) + || (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aSRP | SSL_aPSK))) + return 0; + + return 1; +} + +/* + * Should we expect the ServerKeyExchange message or not? + * + * Return values are: + * 1: Yes + * 0: No + */ +static int key_exchange_expected(SSL *s) +{ + return 1; +} + + +/* + * ossl_statem_client_read_transition_ntls() encapsulates the logic for the allowed + * handshake state transitions when the client is reading messages from the + * server. The message type that the server has sent is provided in |mt|. The + * current state is in |s->statem.hand_state|. + * + * Return values are 1 for success (transition allowed) and 0 on error + * (transition not allowed) + */ +int ossl_statem_client_read_transition_ntls(SSL *s, int mt) +{ + OSSL_STATEM *st = &s->statem; + int ske_expected; + + /* + * Note that after writing the first ClientHello we don't know what version + * we are going to negotiate yet, so we don't take this branch until later. + */ + + switch (st->hand_state) { + default: + break; + + case TLS_ST_CW_CLNT_HELLO: + if (mt == SSL3_MT_SERVER_HELLO) { + st->hand_state = TLS_ST_CR_SRVR_HELLO; + return 1; + } + + break; + + case TLS_ST_EARLY_DATA: + /* + * We've not actually selected TLSv1.3 yet, but we have sent early + * data. The only thing allowed now is a ServerHello or a + * HelloRetryRequest. + */ + if (mt == SSL3_MT_SERVER_HELLO) { + st->hand_state = TLS_ST_CR_SRVR_HELLO; + return 1; + } + break; + + case TLS_ST_CR_SRVR_HELLO: + if (s->hit) { + if (s->ext.ticket_expected) { + if (mt == SSL3_MT_NEWSESSION_TICKET) { + st->hand_state = TLS_ST_CR_SESSION_TICKET; + return 1; + } + } else if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) { + st->hand_state = TLS_ST_CR_CHANGE; + return 1; + } + } else { + if (s->version >= TLS1_VERSION + && s->ext.session_secret_cb != NULL + && s->session->ext.tick != NULL + && mt == SSL3_MT_CHANGE_CIPHER_SPEC) { + /* + * Normally, we can tell if the server is resuming the session + * from the session ID. EAP-FAST (RFC 4851), however, relies on + * the next server message after the ServerHello to determine if + * the server is resuming. + */ + s->hit = 1; + st->hand_state = TLS_ST_CR_CHANGE; + return 1; + } else if (!(s->s3->tmp.new_cipher->algorithm_auth + & (SSL_aNULL | SSL_aSRP | SSL_aPSK))) { + if (mt == SSL3_MT_CERTIFICATE) { + st->hand_state = TLS_ST_CR_CERT; + return 1; + } + } else { + ske_expected = key_exchange_expected(s); + /* SKE is optional for some PSK ciphersuites */ + if (ske_expected + || ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK) + && mt == SSL3_MT_SERVER_KEY_EXCHANGE)) { + if (mt == SSL3_MT_SERVER_KEY_EXCHANGE) { + st->hand_state = TLS_ST_CR_KEY_EXCH; + return 1; + } + } else if (mt == SSL3_MT_CERTIFICATE_REQUEST + && cert_req_allowed(s)) { + st->hand_state = TLS_ST_CR_CERT_REQ; + return 1; + } else if (mt == SSL3_MT_SERVER_DONE) { + st->hand_state = TLS_ST_CR_SRVR_DONE; + return 1; + } + } + } + break; + + case TLS_ST_CR_CERT: + /* + * The CertificateStatus message is optional even if + * |ext.status_expected| is set + */ + if (s->ext.status_expected && mt == SSL3_MT_CERTIFICATE_STATUS) { + st->hand_state = TLS_ST_CR_CERT_STATUS; + return 1; + } + /* Fall through */ + + case TLS_ST_CR_CERT_STATUS: + ske_expected = key_exchange_expected(s); + /* SKE is optional for some PSK ciphersuites */ + if (ske_expected || ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK) + && mt == SSL3_MT_SERVER_KEY_EXCHANGE)) { + if (mt == SSL3_MT_SERVER_KEY_EXCHANGE) { + st->hand_state = TLS_ST_CR_KEY_EXCH; + return 1; + } + goto err; + } + /* Fall through */ + + case TLS_ST_CR_KEY_EXCH: + if (mt == SSL3_MT_CERTIFICATE_REQUEST) { + if (cert_req_allowed(s)) { + st->hand_state = TLS_ST_CR_CERT_REQ; + return 1; + } + goto err; + } + /* Fall through */ + + case TLS_ST_CR_CERT_REQ: + if (mt == SSL3_MT_SERVER_DONE) { + st->hand_state = TLS_ST_CR_SRVR_DONE; + return 1; + } + break; + + case TLS_ST_CW_FINISHED: + if (s->ext.ticket_expected) { + if (mt == SSL3_MT_NEWSESSION_TICKET) { + st->hand_state = TLS_ST_CR_SESSION_TICKET; + return 1; + } + } else if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) { + st->hand_state = TLS_ST_CR_CHANGE; + return 1; + } + break; + + case TLS_ST_CR_SESSION_TICKET: + if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) { + st->hand_state = TLS_ST_CR_CHANGE; + return 1; + } + break; + + case TLS_ST_CR_CHANGE: + if (mt == SSL3_MT_FINISHED) { + st->hand_state = TLS_ST_CR_FINISHED; + return 1; + } + break; + + case TLS_ST_OK: + if (mt == SSL3_MT_HELLO_REQUEST) { + st->hand_state = TLS_ST_CR_HELLO_REQ; + return 1; + } + break; + } + + err: + /* No valid transition found */ + if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) { + BIO *rbio; + + /* + * CCS messages don't have a message sequence number so this is probably + * because of an out-of-order CCS. We'll just drop it. + */ + s->init_num = 0; + s->rwstate = SSL_READING; + rbio = SSL_get_rbio(s); + BIO_clear_retry_flags(rbio); + BIO_set_retry_read(rbio); + return 0; + } + SSLfatal_ntls(s, SSL3_AD_UNEXPECTED_MESSAGE, + SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION_NTLS, + SSL_R_UNEXPECTED_MESSAGE); + return 0; +} + +/* + * ossl_statem_client_write_transition_ntls() works out what handshake state to + * move to next when the client is writing messages to be sent to the server. + */ +WRITE_TRAN ossl_statem_client_write_transition_ntls(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + + /* + * Note that immediately before/after a ClientHello we don't know what + * version we are going to negotiate yet, so we don't take this branch until + * later + */ + + switch (st->hand_state) { + default: + /* Shouldn't happen */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_CLIENT_WRITE_TRANSITION_NTLS, + ERR_R_INTERNAL_ERROR); + return WRITE_TRAN_ERROR; + + case TLS_ST_OK: + if (!s->renegotiate) { + /* + * We haven't requested a renegotiation ourselves so we must have + * received a message from the server. Better read it. + */ + return WRITE_TRAN_FINISHED; + } + /* Renegotiation */ + /* fall thru */ + case TLS_ST_BEFORE: + st->hand_state = TLS_ST_CW_CLNT_HELLO; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_CW_CLNT_HELLO: + if (s->early_data_state == SSL_EARLY_DATA_CONNECTING) { + /* + * We are assuming this is a TLSv1.3 connection, although we haven't + * actually selected a version yet. + */ + if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0) + st->hand_state = TLS_ST_CW_CHANGE; + else + st->hand_state = TLS_ST_EARLY_DATA; + return WRITE_TRAN_CONTINUE; + } + /* + * No transition at the end of writing because we don't know what + * we will be sent + */ + return WRITE_TRAN_FINISHED; + + case TLS_ST_CR_SRVR_HELLO: + /* + * We only get here in TLSv1.3. We just received an HRR, so issue a + * CCS unless middlebox compat mode is off, or we already issued one + * because we did early data. + */ + if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0 + && s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING) + st->hand_state = TLS_ST_CW_CHANGE; + else + st->hand_state = TLS_ST_CW_CLNT_HELLO; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_EARLY_DATA: + return WRITE_TRAN_FINISHED; + + case TLS_ST_CR_SRVR_DONE: + if (s->s3->tmp.cert_req) + st->hand_state = TLS_ST_CW_CERT; + else + st->hand_state = TLS_ST_CW_KEY_EXCH; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_CW_CERT: + st->hand_state = TLS_ST_CW_KEY_EXCH; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_CW_KEY_EXCH: + /* + * For TLS, cert_req is set to 2, so a cert chain of nothing is + * sent, but no verify packet is sent + */ + /* + * XXX: For now, we do not support client authentication in ECDH + * cipher suites with ECDH (rather than ECDSA) certificates. We + * need to skip the certificate verify message when client's + * ECDH public key is sent inside the client certificate. + */ + if (s->s3->tmp.cert_req == 1) { + st->hand_state = TLS_ST_CW_CERT_VRFY; + } else { + st->hand_state = TLS_ST_CW_CHANGE; + } + if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) { + st->hand_state = TLS_ST_CW_CHANGE; + } + return WRITE_TRAN_CONTINUE; + + case TLS_ST_CW_CERT_VRFY: + st->hand_state = TLS_ST_CW_CHANGE; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_CW_CHANGE: + if (s->hello_retry_request == SSL_HRR_PENDING) { + st->hand_state = TLS_ST_CW_CLNT_HELLO; + } else if (s->early_data_state == SSL_EARLY_DATA_CONNECTING) { + st->hand_state = TLS_ST_EARLY_DATA; + } else { +# if defined(OPENSSL_NO_NEXTPROTONEG) + st->hand_state = TLS_ST_CW_FINISHED; +# else + if (s->s3->npn_seen) + st->hand_state = TLS_ST_CW_NEXT_PROTO; + else + st->hand_state = TLS_ST_CW_FINISHED; +# endif + } + return WRITE_TRAN_CONTINUE; + +# if !defined(OPENSSL_NO_NEXTPROTONEG) + case TLS_ST_CW_NEXT_PROTO: + st->hand_state = TLS_ST_CW_FINISHED; + return WRITE_TRAN_CONTINUE; +# endif + + case TLS_ST_CW_FINISHED: + if (s->hit) { + st->hand_state = TLS_ST_OK; + return WRITE_TRAN_CONTINUE; + } else { + return WRITE_TRAN_FINISHED; + } + + case TLS_ST_CR_FINISHED: + if (s->hit) { + st->hand_state = TLS_ST_CW_CHANGE; + return WRITE_TRAN_CONTINUE; + } else { + st->hand_state = TLS_ST_OK; + return WRITE_TRAN_CONTINUE; + } + + case TLS_ST_CR_HELLO_REQ: + /* + * If we can renegotiate now then do so, otherwise wait for a more + * convenient time. + */ + if (ssl3_renegotiate_check(s, 1)) { + if (!tls_setup_handshake_ntls(s)) { + /* SSLfatal_ntls() already called */ + return WRITE_TRAN_ERROR; + } + st->hand_state = TLS_ST_CW_CLNT_HELLO; + return WRITE_TRAN_CONTINUE; + } + st->hand_state = TLS_ST_OK; + return WRITE_TRAN_CONTINUE; + } +} + +/* + * Perform any pre work that needs to be done prior to sending a message from + * the client to the server. + */ +WORK_STATE ossl_statem_client_pre_work_ntls(SSL *s, WORK_STATE wst) +{ + OSSL_STATEM *st = &s->statem; + + switch (st->hand_state) { + default: + /* No pre work to be done */ + break; + + case TLS_ST_CW_CLNT_HELLO: + s->shutdown = 0; + break; + + case TLS_ST_CW_CHANGE: + break; + + case TLS_ST_PENDING_EARLY_DATA_END: + /* + * If we've been called by SSL_do_handshake()/SSL_write(), or we did not + * attempt to write early data before calling SSL_read() then we press + * on with the handshake. Otherwise we pause here. + */ + if (s->early_data_state == SSL_EARLY_DATA_FINISHED_WRITING + || s->early_data_state == SSL_EARLY_DATA_NONE) + return WORK_FINISHED_CONTINUE; + /* Fall through */ + + case TLS_ST_EARLY_DATA: + return tls_finish_handshake_ntls(s, wst, 0, 1); + + case TLS_ST_OK: + /* Calls SSLfatal_ntls() as required */ + return tls_finish_handshake_ntls(s, wst, 1, 1); + } + + return WORK_FINISHED_CONTINUE; +} + +/* + * Perform any work that needs to be done after sending a message from the + * client to the server. + */ +WORK_STATE ossl_statem_client_post_work_ntls(SSL *s, WORK_STATE wst) +{ + OSSL_STATEM *st = &s->statem; + + s->init_num = 0; + + switch (st->hand_state) { + default: + /* No post work to be done */ + break; + + case TLS_ST_CW_CLNT_HELLO: + if (s->early_data_state == SSL_EARLY_DATA_CONNECTING + && s->max_early_data > 0) { + /* + * We haven't selected TLSv1.3 yet so we don't call the change + * cipher state function associated with the SSL_METHOD. Instead + * we call tls13_change_cipher_state() directly. + */ + if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) == 0) { + if (!tls13_change_cipher_state(s, + SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) { + /* SSLfatal_ntls() already called */ + return WORK_ERROR; + } + } + /* else we're in compat mode so we delay flushing until after CCS */ + } else if (!statem_flush_ntls(s)) { + return WORK_MORE_A; + } + + break; + + case TLS_ST_CW_END_OF_EARLY_DATA: + /* + * We set the enc_write_ctx back to NULL because we may end up writing + * in cleartext again if we get a HelloRetryRequest from the server. + */ + EVP_CIPHER_CTX_free(s->enc_write_ctx); + s->enc_write_ctx = NULL; + break; + + case TLS_ST_CW_KEY_EXCH: + if (tls_client_key_exchange_post_work_ntls(s) == 0) { + /* SSLfatal_ntls() already called */ + return WORK_ERROR; + } + break; + + case TLS_ST_CW_CHANGE: + if (s->hello_retry_request == SSL_HRR_PENDING) + break; + if (s->early_data_state == SSL_EARLY_DATA_CONNECTING + && s->max_early_data > 0) { + /* + * We haven't selected TLSv1.3 yet so we don't call the change + * cipher state function associated with the SSL_METHOD. Instead + * we call tls13_change_cipher_state() directly. + */ + if (!tls13_change_cipher_state(s, + SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) + return WORK_ERROR; + break; + } + s->session->cipher = s->s3->tmp.new_cipher; + s->session->compress_meth = 0; + + if (!s->method->ssl3_enc->setup_key_block(s)) { + /* SSLfatal_ntls() already called */ + return WORK_ERROR; + } + + if (!s->method->ssl3_enc->change_cipher_state(s, + SSL3_CHANGE_CIPHER_CLIENT_WRITE)) { + /* SSLfatal_ntls() already called */ + return WORK_ERROR; + } + + break; + + case TLS_ST_CW_FINISHED: + if (statem_flush_ntls(s) != 1) + return WORK_MORE_B; + break; + + case TLS_ST_CW_KEY_UPDATE: + if (statem_flush_ntls(s) != 1) + return WORK_MORE_A; + if (!tls13_update_key(s, 1)) { + /* SSLfatal_ntls() already called */ + return WORK_ERROR; + } + break; + } + + return WORK_FINISHED_CONTINUE; +} + +/* + * Get the message construction function and message type for sending from the + * client + * + * Valid return values are: + * 1: Success + * 0: Error + */ +int ossl_statem_client_construct_message_ntls(SSL *s, WPACKET *pkt, + confunc_f *confunc, int *mt) +{ + OSSL_STATEM *st = &s->statem; + + switch (st->hand_state) { + default: + /* Shouldn't happen */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE_NTLS, + SSL_R_BAD_HANDSHAKE_STATE); + return 0; + + case TLS_ST_CW_CHANGE: + *confunc = tls_construct_change_cipher_spec_ntls; + *mt = SSL3_MT_CHANGE_CIPHER_SPEC; + break; + + case TLS_ST_CW_CLNT_HELLO: + *confunc = tls_construct_client_hello_ntls; + *mt = SSL3_MT_CLIENT_HELLO; + break; + + case TLS_ST_CW_END_OF_EARLY_DATA: + *confunc = tls_construct_end_of_early_data_ntls; + *mt = SSL3_MT_END_OF_EARLY_DATA; + break; + + case TLS_ST_PENDING_EARLY_DATA_END: + *confunc = NULL; + *mt = SSL3_MT_DUMMY; + break; + + case TLS_ST_CW_CERT: + *confunc = ntls_construct_client_certificate_ntls; + *mt = SSL3_MT_CERTIFICATE; + break; + + case TLS_ST_CW_KEY_EXCH: + *confunc = ntls_construct_client_key_exchange_ntls; + *mt = SSL3_MT_CLIENT_KEY_EXCHANGE; + break; + + case TLS_ST_CW_CERT_VRFY: + *confunc = ntls_construct_cert_verify_ntls; + *mt = SSL3_MT_CERTIFICATE_VERIFY; + break; + +# if !defined(OPENSSL_NO_NEXTPROTONEG) + case TLS_ST_CW_NEXT_PROTO: + *confunc = tls_construct_next_proto_ntls; + *mt = SSL3_MT_NEXT_PROTO; + break; +# endif + case TLS_ST_CW_FINISHED: + *confunc = tls_construct_finished_ntls; + *mt = SSL3_MT_FINISHED; + break; + + case TLS_ST_CW_KEY_UPDATE: + *confunc = tls_construct_key_update_ntls; + *mt = SSL3_MT_KEY_UPDATE; + break; + } + + return 1; +} + +/* + * Returns the maximum allowed length for the current message that we are + * reading. Excludes the message header. + */ +size_t ossl_statem_client_max_message_size_ntls(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + + switch (st->hand_state) { + default: + /* Shouldn't happen */ + return 0; + + case TLS_ST_CR_SRVR_HELLO: + return SERVER_HELLO_MAX_LENGTH; + + case TLS_ST_CR_CERT: + return s->max_cert_list; + + case TLS_ST_CR_CERT_VRFY: + return SSL3_RT_MAX_PLAIN_LENGTH; + + case TLS_ST_CR_CERT_STATUS: + return SSL3_RT_MAX_PLAIN_LENGTH; + + case TLS_ST_CR_KEY_EXCH: + return SERVER_KEY_EXCH_MAX_LENGTH; + + case TLS_ST_CR_CERT_REQ: + /* + * Set to s->max_cert_list for compatibility with previous releases. In + * practice these messages can get quite long if servers are configured + * to provide a long list of acceptable CAs + */ + return s->max_cert_list; + + case TLS_ST_CR_SRVR_DONE: + return SERVER_HELLO_DONE_MAX_LENGTH; + + case TLS_ST_CR_CHANGE: + return CCS_MAX_LENGTH; + + case TLS_ST_CR_SESSION_TICKET: + return SSL3_RT_MAX_PLAIN_LENGTH; + + case TLS_ST_CR_FINISHED: + return FINISHED_MAX_LENGTH; + + case TLS_ST_CR_ENCRYPTED_EXTENSIONS: + return ENCRYPTED_EXTENSIONS_MAX_LENGTH; + + case TLS_ST_CR_KEY_UPDATE: + return KEY_UPDATE_MAX_LENGTH; + } +} + +/* + * Process a message that the client has been received from the server. + */ +MSG_PROCESS_RETURN ossl_statem_client_process_message_ntls(SSL *s, PACKET *pkt) +{ + OSSL_STATEM *st = &s->statem; + + switch (st->hand_state) { + default: + /* Shouldn't happen */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_CLIENT_PROCESS_MESSAGE_NTLS, + ERR_R_INTERNAL_ERROR); + return MSG_PROCESS_ERROR; + + case TLS_ST_CR_SRVR_HELLO: + return tls_process_server_hello_ntls(s, pkt); + + case TLS_ST_CR_CERT: + return tls_process_server_certificate_ntls(s, pkt); + + case TLS_ST_CR_CERT_VRFY: + return tls_process_cert_verify_ntls(s, pkt); + + case TLS_ST_CR_CERT_STATUS: + return tls_process_cert_status_ntls(s, pkt); + + case TLS_ST_CR_KEY_EXCH: + return ntls_process_server_key_exchange_ntls(s, pkt); + + + case TLS_ST_CR_CERT_REQ: + return tls_process_certificate_request_ntls(s, pkt); + + case TLS_ST_CR_SRVR_DONE: + return tls_process_server_done_ntls(s, pkt); + + case TLS_ST_CR_CHANGE: + return tls_process_change_cipher_spec_ntls(s, pkt); + + case TLS_ST_CR_SESSION_TICKET: + return tls_process_new_session_ticket_ntls(s, pkt); + + case TLS_ST_CR_FINISHED: + return tls_process_finished_ntls(s, pkt); + + case TLS_ST_CR_HELLO_REQ: + return tls_process_hello_req_ntls(s, pkt); + + case TLS_ST_CR_ENCRYPTED_EXTENSIONS: + return tls_process_encrypted_extensions(s, pkt); + + case TLS_ST_CR_KEY_UPDATE: + return tls_process_key_update_ntls(s, pkt); + } +} + +/* + * Perform any further processing required following the receipt of a message + * from the server + */ +WORK_STATE ossl_statem_client_post_process_message_ntls(SSL *s, WORK_STATE wst) +{ + OSSL_STATEM *st = &s->statem; + + switch (st->hand_state) { + default: + /* Shouldn't happen */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_CLIENT_POST_PROCESS_MESSAGE_NTLS, + ERR_R_INTERNAL_ERROR); + return WORK_ERROR; + + case TLS_ST_CR_CERT_VRFY: + case TLS_ST_CR_CERT_REQ: + return tls_prepare_client_certificate_ntls(s, wst); + } +} + +int tls_construct_client_hello_ntls(SSL *s, WPACKET *pkt) +{ + unsigned char *p; + size_t sess_id_len; + int i, protverr; + SSL_SESSION *sess = s->session; + unsigned char *session_id; + + /* Work out what SSL/TLS version to use */ + protverr = ssl_set_client_hello_version_ntls(s); + if (protverr != 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO_NTLS, + protverr); + return 0; + } + + if (sess == NULL + || !ssl_version_supported_ntls(s, sess->ssl_version, NULL) + || !SSL_SESSION_is_resumable(sess)) { + if (s->hello_retry_request == SSL_HRR_NONE + && !ssl_get_new_session(s, 0)) { + /* SSLfatal_ntls() already called */ + return 0; + } + } + /* else use the pre-loaded session */ + + p = s->s3->client_random; + i = (s->hello_retry_request == SSL_HRR_NONE); + + if (i && ssl_fill_hello_random(s, 0, p, sizeof(s->s3->client_random), + DOWNGRADE_NONE) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /*- + * version indicates the negotiated version: for example from + * an SSLv2/v3 compatible client hello). The client_version + * field is the maximum version we permit and it is also + * used in RSA encrypted premaster secrets. Some servers can + * choke if we initially report a higher version then + * renegotiate to a lower one in the premaster secret. This + * didn't happen with TLS 1.0 as most servers supported it + * but it can with TLS 1.1 or later if the server only supports + * 1.0. + * + * Possible scenario with previous logic: + * 1. Client hello indicates TLS 1.2 + * 2. Server hello says TLS 1.0 + * 3. RSA encrypted premaster secret uses 1.2. + * 4. Handshake proceeds using TLS 1.0. + * 5. Server sends hello request to renegotiate. + * 6. Client hello indicates TLS v1.0 as we now + * know that is maximum server supports. + * 7. Server chokes on RSA encrypted premaster secret + * containing version 1.0. + * + * For interoperability it should be OK to always use the + * maximum version we support in client hello and then rely + * on the checking of version to ensure the servers isn't + * being inconsistent: for example initially negotiating with + * TLS 1.0 and renegotiating with TLS 1.2. We do this by using + * client_version in client hello and not resetting it to + * the negotiated version. + * + * For TLS 1.3 we always set the ClientHello version to 1.2 and rely on the + * supported_versions extension for the real supported versions. + */ + if (!WPACKET_put_bytes_u16(pkt, s->client_version) + || !WPACKET_memcpy(pkt, s->s3->client_random, SSL3_RANDOM_SIZE)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* Session ID */ + session_id = s->session->session_id; + if (s->new_session || s->session->ssl_version == TLS1_3_VERSION) { + if (s->version == TLS1_3_VERSION + && (s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0) { + sess_id_len = sizeof(s->tmp_session_id); + s->tmp_session_id_len = sess_id_len; + session_id = s->tmp_session_id; + if (s->hello_retry_request == SSL_HRR_NONE + && RAND_bytes(s->tmp_session_id, sess_id_len) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CLIENT_HELLO_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + } else { + sess_id_len = 0; + } + } else { + assert(s->session->session_id_length <= sizeof(s->session->session_id)); + sess_id_len = s->session->session_id_length; + if (s->version == TLS1_3_VERSION) { + s->tmp_session_id_len = sess_id_len; + memcpy(s->tmp_session_id, s->session->session_id, sess_id_len); + } + } + if (!WPACKET_start_sub_packet_u8(pkt) + || (sess_id_len != 0 && !WPACKET_memcpy(pkt, session_id, + sess_id_len)) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* Ciphers supported */ + if (!WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), pkt)) { + /* SSLfatal_ntls() already called */ + return 0; + } + if (!WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* COMPRESSION */ + if (!WPACKET_start_sub_packet_u8(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* Add the NULL method */ + if (!WPACKET_put_bytes_u8(pkt, 0) || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +static int set_client_ciphersuite(SSL *s, const unsigned char *cipherchars) +{ + STACK_OF(SSL_CIPHER) *sk; + const SSL_CIPHER *c; + int i; + + c = ssl_get_cipher_by_char(s, cipherchars, 0); + if (c == NULL) { + /* unknown cipher */ + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE, + SSL_R_UNKNOWN_CIPHER_RETURNED); + return 0; + } + /* + * If it is a disabled cipher we either didn't send it in client hello, + * or it's not allowed for the selected protocol. So we return an error. + */ + if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_CHECK, 1)) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE, + SSL_R_WRONG_CIPHER_RETURNED); + return 0; + } + + sk = ssl_get_ciphers_by_id(s); + i = sk_SSL_CIPHER_find(sk, c); + if (i < 0) { + /* we did not say we would use this cipher */ + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE, + SSL_R_WRONG_CIPHER_RETURNED); + return 0; + } + + /* + * Depending on the session caching (internal/external), the cipher + * and/or cipher_id values may not be set. Make sure that cipher_id is + * set and use it for comparison. + */ + if (s->session->cipher != NULL) + s->session->cipher_id = s->session->cipher->id; + if (s->hit && (s->session->cipher_id != c->id)) { + /* + * Prior to TLSv1.3 resuming a session always meant using the same + * ciphersuite. + */ + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE, + SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED); + return 0; + } + s->s3->tmp.new_cipher = c; + + return 1; +} + +MSG_PROCESS_RETURN tls_process_server_hello_ntls(SSL *s, PACKET *pkt) +{ + PACKET session_id, extpkt; + size_t session_id_len; + const unsigned char *cipherchars; + int hrr = 0; + unsigned int compression; + unsigned int sversion; + unsigned int context; + RAW_EXTENSION *extensions = NULL; + + if (!PACKET_get_net_2(pkt, &sversion)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO_NTLS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + /* load the server random */ + if (s->version == TLS1_3_VERSION + && sversion == TLS1_2_VERSION + && PACKET_remaining(pkt) >= SSL3_RANDOM_SIZE + && memcmp(hrrrandom_ntls, PACKET_data(pkt), SSL3_RANDOM_SIZE) == 0) { + s->hello_retry_request = SSL_HRR_PENDING; + hrr = 1; + if (!PACKET_forward(pkt, SSL3_RANDOM_SIZE)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO_NTLS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + } else { + if (!PACKET_copy_bytes(pkt, s->s3->server_random, SSL3_RANDOM_SIZE)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO_NTLS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + } + + /* Get the session-id. */ + if (!PACKET_get_length_prefixed_1(pkt, &session_id)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO_NTLS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + session_id_len = PACKET_remaining(&session_id); + if (session_id_len > sizeof(s->session->session_id) + || session_id_len > SSL3_SESSION_ID_SIZE) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO_NTLS, + SSL_R_SSL3_SESSION_ID_TOO_LONG); + goto err; + } + + if (!PACKET_get_bytes(pkt, &cipherchars, TLS_CIPHER_LEN)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO_NTLS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + if (!PACKET_get_1(pkt, &compression)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO_NTLS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + /* TLS extensions */ + if (PACKET_remaining(pkt) == 0 && !hrr) { + PACKET_null_init(&extpkt); + } else if (!PACKET_as_length_prefixed_2(pkt, &extpkt) + || PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO_NTLS, + SSL_R_BAD_LENGTH); + goto err; + } + + if (!hrr) { + if (!tls_collect_extensions_ntls(s, &extpkt, + SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_SERVER_HELLO, + &extensions, NULL, 1)) { + /* SSLfatal_ntls() already called */ + goto err; + } + + if (!ssl_choose_client_version_ntls(s, sversion, extensions)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } + + if (hrr) { + if (compression != 0) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PROCESS_SERVER_HELLO_NTLS, + SSL_R_INVALID_COMPRESSION_ALGORITHM); + goto err; + } + + if (session_id_len != s->tmp_session_id_len + || memcmp(PACKET_data(&session_id), s->tmp_session_id, + session_id_len) != 0) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PROCESS_SERVER_HELLO_NTLS, SSL_R_INVALID_SESSION_ID); + goto err; + } + } + + if (hrr) { + if (!set_client_ciphersuite(s, cipherchars)) { + /* SSLfatal_ntls() already called */ + goto err; + } + + return tls_process_as_hello_retry_request(s, &extpkt); + } + + /* + * Now we have chosen the version we need to check again that the extensions + * are appropriate for this version. + */ + context = SSL_EXT_TLS1_2_SERVER_HELLO; + if (!tls_validate_all_contexts_ntls(s, context, extensions)) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO_NTLS, + SSL_R_BAD_EXTENSION); + goto err; + } + + s->hit = 0; + + /* + * Check if we can resume the session based on external pre-shared + * secret. EAP-FAST (RFC 4851) supports two types of session resumption. + * Resumption based on server-side state works with session IDs. + * Resumption based on pre-shared Protected Access Credentials (PACs) + * works by overriding the SessionTicket extension at the application + * layer, and does not send a session ID. (We do not know whether + * EAP-FAST servers would honour the session ID.) Therefore, the session + * ID alone is not a reliable indicator of session resumption, so we + * first check if we can resume, and later peek at the next handshake + * message to see if the server wants to resume. + */ + if (s->version >= TLS1_VERSION + && s->ext.session_secret_cb != NULL && s->session->ext.tick) { + const SSL_CIPHER *pref_cipher = NULL; + /* + * s->session->master_key_length is a size_t, but this is an int for + * backwards compat reasons + */ + int master_key_length; + master_key_length = sizeof(s->session->master_key); + if (s->ext.session_secret_cb(s, s->session->master_key, + &master_key_length, + NULL, &pref_cipher, + s->ext.session_secret_cb_arg) + && master_key_length > 0) { + s->session->master_key_length = master_key_length; + s->session->cipher = pref_cipher ? + pref_cipher : ssl_get_cipher_by_char(s, cipherchars, 0); + } else { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_SERVER_HELLO_NTLS, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (session_id_len != 0 + && session_id_len == s->session->session_id_length + && memcmp(PACKET_data(&session_id), s->session->session_id, + session_id_len) == 0) + s->hit = 1; + + if (s->hit) { + if (s->sid_ctx_length != s->session->sid_ctx_length + || memcmp(s->session->sid_ctx, s->sid_ctx, s->sid_ctx_length)) { + /* actually a client application bug */ + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PROCESS_SERVER_HELLO_NTLS, + SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT); + goto err; + } + } else { + /* + * If we were trying for session-id reuse but the server + * didn't resume, make a new SSL_SESSION. + * In the case of EAP-FAST and PAC, we do not send a session ID, + * so the PAC-based session secret is always preserved. It'll be + * overwritten if the server refuses resumption. + */ + if (s->session->session_id_length > 0) { + tsan_counter(&s->session_ctx->stats.sess_miss); + if (!ssl_get_new_session(s, 0)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } + + s->session->ssl_version = s->version; + /* + * In TLSv1.2 and below we save the session id we were sent so we can + * resume it later. In TLSv1.3 the session id we were sent is just an + * echo of what we originally sent in the ClientHello and should not be + * used for resumption. + */ + s->session->session_id_length = session_id_len; + /* session_id_len could be 0 */ + if (session_id_len > 0) + memcpy(s->session->session_id, PACKET_data(&session_id), + session_id_len); + } + + /* Session version and negotiated protocol version should match */ + if (s->version != s->session->ssl_version) { + SSLfatal_ntls(s, SSL_AD_PROTOCOL_VERSION, SSL_F_TLS_PROCESS_SERVER_HELLO_NTLS, + SSL_R_SSL_SESSION_VERSION_MISMATCH); + goto err; + } + /* + * Now that we know the version, update the check to see if it's an allowed + * version. + */ + s->s3->tmp.min_ver = s->version; + s->s3->tmp.max_ver = s->version; + + if (!set_client_ciphersuite(s, cipherchars)) { + /* SSLfatal_ntls() already called */ + goto err; + } + + if (compression != 0) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO_NTLS, + SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM); + goto err; + } + /* + * If compression is disabled we'd better not try to resume a session + * using compression. + */ + if (s->session->compress_meth != 0) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_SERVER_HELLO_NTLS, + SSL_R_INCONSISTENT_COMPRESSION); + goto err; + } + + + if (!tls_parse_all_extensions_ntls(s, context, extensions, NULL, 0, 1)) { + /* SSLfatal_ntls() already called */ + goto err; + } + + /* + * In TLSv1.3 we have some post-processing to change cipher state, otherwise + * we're done with this message + */ + OPENSSL_free(extensions); + return MSG_PROCESS_CONTINUE_READING; + err: + OPENSSL_free(extensions); + return MSG_PROCESS_ERROR; +} + +static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL *s, + PACKET *extpkt) +{ + RAW_EXTENSION *extensions = NULL; + + /* + * If we were sending early_data then the enc_write_ctx is now invalid and + * should not be used. + */ + EVP_CIPHER_CTX_free(s->enc_write_ctx); + s->enc_write_ctx = NULL; + + if (!tls_collect_extensions_ntls(s, extpkt, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST, + &extensions, NULL, 1) + || !tls_parse_all_extensions_ntls(s, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST, + extensions, NULL, 0, 1)) { + /* SSLfatal_ntls() already called */ + goto err; + } + + OPENSSL_free(extensions); + extensions = NULL; + + if (s->ext.tls13_cookie_len == 0 +# if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH) + && s->s3->tmp.pkey != NULL +# endif + ) { + /* + * We didn't receive a cookie or a new key_share so the next + * ClientHello will not change + */ + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PROCESS_AS_HELLO_RETRY_REQUEST, + SSL_R_NO_CHANGE_FOLLOWING_HRR); + goto err; + } + + /* + * Re-initialise the Transcript Hash. We're going to prepopulate it with + * a synthetic message_hash in place of ClientHello1. + */ + if (!create_synthetic_message_hash_ntls(s, NULL, 0, NULL, 0)) { + /* SSLfatal_ntls() already called */ + goto err; + } + + /* + * Add this message to the Transcript Hash. Normally this is done + * automatically prior to the message processing stage. However due to the + * need to create the synthetic message hash, we defer that step until now + * for HRR messages. + */ + if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, + s->init_num + SSL3_HM_HEADER_LENGTH)) { + /* SSLfatal_ntls() already called */ + goto err; + } + + return MSG_PROCESS_FINISHED_READING; + err: + OPENSSL_free(extensions); + return MSG_PROCESS_ERROR; +} + +MSG_PROCESS_RETURN tls_process_server_certificate_ntls(SSL *s, PACKET *pkt) +{ + int i; + MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR; + unsigned long cert_list_len, cert_len; + X509 *x = NULL; + const unsigned char *certstart, *certbytes; + STACK_OF(X509) *sk = NULL; + EVP_PKEY *pkey = NULL; + size_t chainidx, certidx; + unsigned int context = 0; + const SSL_CERT_LOOKUP *clu; + + if ((sk = sk_X509_new_null()) == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE_NTLS, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if (context != 0 + || !PACKET_get_net_3(pkt, &cert_list_len) + || PACKET_remaining(pkt) != cert_list_len + || PACKET_remaining(pkt) == 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE_NTLS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + for (chainidx = 0; PACKET_remaining(pkt); chainidx++) { + if (!PACKET_get_net_3(pkt, &cert_len) + || !PACKET_get_bytes(pkt, &certbytes, cert_len)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE_NTLS, + SSL_R_CERT_LENGTH_MISMATCH); + goto err; + } + + certstart = certbytes; + x = d2i_X509(NULL, (const unsigned char **)&certbytes, cert_len); + if (x == NULL) { + SSLfatal_ntls(s, SSL_AD_BAD_CERTIFICATE, + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE_NTLS, ERR_R_ASN1_LIB); + goto err; + } + if (certbytes != (certstart + cert_len)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE_NTLS, + SSL_R_CERT_LENGTH_MISMATCH); + goto err; + } + + if (!sk_X509_push(sk, x)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE_NTLS, + ERR_R_MALLOC_FAILURE); + goto err; + } + x = NULL; + } + +# ifndef OPENSSL_NO_SM2 + + { + int n = sk_X509_num(sk) - 1; + + while (n >= 0) { + X509 *cert = sk_X509_value(sk, n); + ASN1_OCTET_STRING *sm2_id; + sm2_id = ASN1_OCTET_STRING_new(); + + if (sm2_id == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE_NTLS, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!ASN1_OCTET_STRING_set(sm2_id, + (const unsigned char *)CERTVRIFY_SM2_ID, + CERTVRIFY_SM2_ID_LEN)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE_NTLS, + ERR_R_INTERNAL_ERROR); + ASN1_OCTET_STRING_free(sm2_id); + goto err; + } + + X509_set0_sm2_id(cert, sm2_id); + n--; + } + + } + +# endif + + + i = ssl_verify_cert_chain(s, sk); + /* + * The documented interface is that SSL_VERIFY_PEER should be set in order + * for client side verification of the server certificate to take place. + * However, historically the code has only checked that *any* flag is set + * to cause server verification to take place. Use of the other flags makes + * no sense in client mode. An attempt to clean up the semantics was + * reverted because at least one application *only* set + * SSL_VERIFY_FAIL_IF_NO_PEER_CERT. Prior to the clean up this still caused + * server verification to take place, after the clean up it silently did + * nothing. SSL_CTX_set_verify()/SSL_set_verify() cannot validate the flags + * sent to them because they are void functions. Therefore, we now use the + * (less clean) historic behaviour of performing validation if any flag is + * set. The *documented* interface remains the same. + */ + if (s->verify_mode != SSL_VERIFY_NONE && i <= 0) { + SSLfatal_ntls(s, ssl_x509err2alert_ntls(s->verify_result), + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE_NTLS, + SSL_R_CERTIFICATE_VERIFY_FAILED); + goto err; + } + ERR_clear_error(); /* but we keep s->verify_result */ + if (i > 1) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE_NTLS, i); + goto err; + } + + s->session->peer_chain = sk; + /* + * Inconsistency alert: cert_chain does include the peer's certificate, + * which we don't include in statem_srvr.c + */ + x = sk_X509_value(sk, 0); + sk = NULL; + + pkey = X509_get0_pubkey(x); + + if (pkey == NULL || EVP_PKEY_missing_parameters(pkey)) { + x = NULL; + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE_NTLS, + SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS); + goto err; + } + + if ((clu = ssl_cert_lookup_by_pkey(pkey, &certidx)) == NULL) { + x = NULL; + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE_NTLS, + SSL_R_UNKNOWN_CERTIFICATE_TYPE); + goto err; + } + /* + * Check certificate type is consistent with ciphersuite. For TLS 1.3 + * skip check since TLS 1.3 ciphersuites can be used with any certificate + * type. + */ + if ((clu->amask & s->s3->tmp.new_cipher->algorithm_auth) == 0) { + x = NULL; + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE_NTLS, + SSL_R_WRONG_CERTIFICATE_TYPE); + goto err; + } + s->session->peer_type = certidx; + + X509_free(s->session->peer); + X509_up_ref(x); + s->session->peer = x; + s->session->verify_result = s->verify_result; + x = NULL; + + ret = MSG_PROCESS_CONTINUE_READING; + + err: + X509_free(x); + sk_X509_pop_free(sk, X509_free); + return ret; +} + +static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt) +{ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE, + ERR_R_INTERNAL_ERROR); + return 0; + +} + +static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey) +{ +# ifndef OPENSSL_NO_DH + PACKET prime, generator, pub_key; + EVP_PKEY *peer_tmp = NULL; + + DH *dh = NULL; + BIGNUM *p = NULL, *g = NULL, *bnpub_key = NULL; + + int check_bits = 0; + + if (!PACKET_get_length_prefixed_2(pkt, &prime) + || !PACKET_get_length_prefixed_2(pkt, &generator) + || !PACKET_get_length_prefixed_2(pkt, &pub_key)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_DHE, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + peer_tmp = EVP_PKEY_new(); + dh = DH_new(); + + if (peer_tmp == NULL || dh == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE, + ERR_R_MALLOC_FAILURE); + goto err; + } + + /* TODO(size_t): Convert these calls */ + p = BN_bin2bn(PACKET_data(&prime), (int)PACKET_remaining(&prime), NULL); + g = BN_bin2bn(PACKET_data(&generator), (int)PACKET_remaining(&generator), + NULL); + bnpub_key = BN_bin2bn(PACKET_data(&pub_key), + (int)PACKET_remaining(&pub_key), NULL); + if (p == NULL || g == NULL || bnpub_key == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE, + ERR_R_BN_LIB); + goto err; + } + + /* test non-zero pubkey */ + if (BN_is_zero(bnpub_key)) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_DHE, + SSL_R_BAD_DH_VALUE); + goto err; + } + + if (!DH_set0_pqg(dh, p, NULL, g)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE, + ERR_R_BN_LIB); + goto err; + } + p = g = NULL; + + if (DH_check_params(dh, &check_bits) == 0 || check_bits != 0) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_DHE, + SSL_R_BAD_DH_VALUE); + goto err; + } + + if (!DH_set0_key(dh, bnpub_key, NULL)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE, + ERR_R_BN_LIB); + goto err; + } + bnpub_key = NULL; + + if (!ssl_security(s, SSL_SECOP_TMP_DH, DH_security_bits(dh), 0, dh)) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_SKE_DHE, + SSL_R_DH_KEY_TOO_SMALL); + goto err; + } + + if (EVP_PKEY_assign_DH(peer_tmp, dh) == 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE, + ERR_R_EVP_LIB); + goto err; + } + + s->s3->peer_tmp = peer_tmp; + + /* + * FIXME: This makes assumptions about which ciphersuites come with + * public keys. We should have a less ad-hoc way of doing this + */ + if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aRSA | SSL_aDSS)) + *pkey = X509_get0_pubkey(s->session->peer); + /* else anonymous DH, so no certificate or pkey. */ + + return 1; + + err: + BN_free(p); + BN_free(g); + BN_free(bnpub_key); + DH_free(dh); + EVP_PKEY_free(peer_tmp); + + return 0; +# else + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE, + ERR_R_INTERNAL_ERROR); + return 0; +# endif +} + +static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey) +{ +# ifndef OPENSSL_NO_EC + PACKET encoded_pt; + unsigned int curve_type, curve_id; + + /* + * Extract elliptic curve parameters and the server's ephemeral ECDH + * public key. We only support named (not generic) curves and + * ECParameters in this case is just three bytes. + */ + if (!PACKET_get_1(pkt, &curve_type) || !PACKET_get_net_2(pkt, &curve_id)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE, + SSL_R_LENGTH_TOO_SHORT); + return 0; + } + /* + * Check curve is named curve type and one of our preferences, if not + * server has sent an invalid curve. + */ + if (curve_type != NAMED_CURVE_TYPE + || !tls1_check_group_id(s, curve_id, 1)) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_ECDHE, + SSL_R_WRONG_CURVE); + return 0; + } + + if ((s->s3->peer_tmp = ssl_generate_param_group(curve_id)) == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE, + SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); + return 0; + } + + if (!PACKET_get_length_prefixed_1(pkt, &encoded_pt)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp, + PACKET_data(&encoded_pt), + PACKET_remaining(&encoded_pt))) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_ECDHE, + SSL_R_BAD_ECPOINT); + return 0; + } + + /* + * The ECC/TLS specification does not mention the use of DSA to sign + * ECParameters in the server key exchange message. We do support RSA + * and ECDSA. + */ + if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aECDSA) + *pkey = X509_get0_pubkey(s->session->peer); + else if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aSM2) + *pkey = X509_get0_pubkey(s->session->peer); + else if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aRSA) + *pkey = X509_get0_pubkey(s->session->peer); + /* else anonymous ECDH, so no certificate or pkey. */ + + return 1; +# else + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE, + ERR_R_INTERNAL_ERROR); + return 0; +# endif +} + +MSG_PROCESS_RETURN tls_process_key_exchange_ntls(SSL *s, PACKET *pkt) +{ + long alg_k; + EVP_PKEY *pkey = NULL; + EVP_MD_CTX *md_ctx = NULL; + EVP_PKEY_CTX *pctx = NULL; + PACKET save_param_start, signature; + + alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + + save_param_start = *pkt; + +# if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH) + EVP_PKEY_free(s->s3->peer_tmp); + s->s3->peer_tmp = NULL; +# endif + + if (alg_k & SSL_PSK) { + if (!tls_process_ske_psk_preamble(s, pkt)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } + + /* Nothing else to do for plain PSK or RSAPSK */ + if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) { + if (!tls_process_ske_dhe(s, pkt, &pkey)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) { + if (!tls_process_ske_ecdhe(s, pkt, &pkey)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else if (alg_k) { + SSLfatal_ntls(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_KEY_EXCHANGE_NTLS, + SSL_R_UNEXPECTED_MESSAGE); + goto err; + } + + /* if it was signed, check the signature */ + if (pkey != NULL) { + PACKET params; + int maxsig; + const EVP_MD *md = NULL; + unsigned char *tbs; + size_t tbslen; + int rv; + + /* + * |pkt| now points to the beginning of the signature, so the difference + * equals the length of the parameters. + */ + if (!PACKET_get_sub_packet(&save_param_start, ¶ms, + PACKET_remaining(&save_param_start) - + PACKET_remaining(pkt))) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (SSL_USE_SIGALGS(s)) { + unsigned int sigalg; + + if (!PACKET_get_net_2(pkt, &sigalg)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE_NTLS, + SSL_R_LENGTH_TOO_SHORT); + goto err; + } + if (tls12_check_peer_sigalg(s, sigalg, pkey) <=0) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else if (!tls1_set_peer_legacy_sigalg(s, pkey)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!tls1_lookup_md(s->s3->tmp.peer_sigalg, &md)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } +# ifdef SSL_DEBUG + if (SSL_USE_SIGALGS(s)) + fprintf(stderr, "USING TLSv1.2 HASH %s\n", + md == NULL ? "n/a" : EVP_MD_name(md)); +# endif + + if (!PACKET_get_length_prefixed_2(pkt, &signature) + || PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE_NTLS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + maxsig = EVP_PKEY_size(pkey); + if (maxsig < 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * Check signature length + */ + if (PACKET_remaining(&signature) > (size_t)maxsig) { + /* wrong packet length */ + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE_NTLS, + SSL_R_WRONG_SIGNATURE_LENGTH); + goto err; + } + + md_ctx = EVP_MD_CTX_new(); + if (md_ctx == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE_NTLS, + ERR_R_MALLOC_FAILURE); + goto err; + } + + /* FIXME: address RSA key... */ + EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2); + + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (pctx == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE_NTLS, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if (EVP_PKEY_CTX_set1_id(pctx, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LEN) + != 1) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE_NTLS, + ERR_R_MALLOC_FAILURE); + goto err; + } + + EVP_MD_CTX_set_pkey_ctx(md_ctx, pctx); + + + if (EVP_DigestVerifyInit(md_ctx, &pctx, md, NULL, pkey) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE_NTLS, + ERR_R_EVP_LIB); + goto err; + } + if (SSL_USE_PSS(s)) { + if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0 + || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, + RSA_PSS_SALTLEN_DIGEST) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_KEY_EXCHANGE_NTLS, ERR_R_EVP_LIB); + goto err; + } + } + tbslen = construct_key_exchange_tbs_ntls(s, &tbs, PACKET_data(¶ms), + PACKET_remaining(¶ms)); + if (tbslen == 0) { + /* SSLfatal_ntls() already called */ + goto err; + } + + rv = EVP_DigestVerify(md_ctx, PACKET_data(&signature), + PACKET_remaining(&signature), tbs, tbslen); + OPENSSL_free(tbs); + if (rv <= 0) { + SSLfatal_ntls(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE_NTLS, + SSL_R_BAD_SIGNATURE); + goto err; + } + EVP_MD_CTX_free(md_ctx); + md_ctx = NULL; + EVP_PKEY_CTX_free(pctx); + pctx = NULL; + } else { + /* aNULL, aSRP or PSK do not need public keys */ + if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP)) + && !(alg_k & SSL_PSK)) { + /* Might be wrong key type, check it */ + if (ssl3_check_cert_and_algorithm_ntls(s)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE_NTLS, + SSL_R_BAD_DATA); + } + /* else this shouldn't happen, SSLfatal_ntls() already called */ + goto err; + } + /* still data left over */ + if (PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE_NTLS, + SSL_R_EXTRA_DATA_IN_MESSAGE); + goto err; + } + } + + return MSG_PROCESS_CONTINUE_READING; + err: + EVP_MD_CTX_free(md_ctx); + EVP_PKEY_CTX_free(pctx); + pctx = NULL; + + return MSG_PROCESS_ERROR; +} + +MSG_PROCESS_RETURN tls_process_certificate_request_ntls(SSL *s, PACKET *pkt) +{ + size_t i; + + /* Clear certificate validity flags */ + for (i = 0; i < SSL_PKEY_NUM; i++) + s->s3->tmp.valid_flags[i] = 0; + + { + PACKET ctypes; + + /* get the certificate types */ + if (!PACKET_get_length_prefixed_1(pkt, &ctypes)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST_NTLS, + SSL_R_LENGTH_MISMATCH); + return MSG_PROCESS_ERROR; + } + + if (!PACKET_memdup(&ctypes, &s->s3->tmp.ctype, &s->s3->tmp.ctype_len)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST_NTLS, + ERR_R_INTERNAL_ERROR); + return MSG_PROCESS_ERROR; + } + + if (SSL_USE_SIGALGS(s)) { + PACKET sigalgs; + + if (!PACKET_get_length_prefixed_2(pkt, &sigalgs)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST_NTLS, + SSL_R_LENGTH_MISMATCH); + return MSG_PROCESS_ERROR; + } + + /* + * Despite this being for certificates, preserve compatibility + * with pre-TLS 1.3 and use the regular sigalgs field. + */ + if (!tls1_save_sigalgs(s, &sigalgs, 0)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST_NTLS, + SSL_R_SIGNATURE_ALGORITHMS_ERROR); + return MSG_PROCESS_ERROR; + } + if (!tls1_process_sigalgs(s)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST_NTLS, + ERR_R_MALLOC_FAILURE); + return MSG_PROCESS_ERROR; + } + } + + /* get the CA RDNs */ + if (!parse_ca_names_ntls(s, pkt)) { + /* SSLfatal_ntls() already called */ + return MSG_PROCESS_ERROR; + } + } + + if (PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST_NTLS, + SSL_R_LENGTH_MISMATCH); + return MSG_PROCESS_ERROR; + } + + /* we should setup a certificate to return.... */ + s->s3->tmp.cert_req = 1; + + return MSG_PROCESS_CONTINUE_PROCESSING; +} + +MSG_PROCESS_RETURN tls_process_new_session_ticket_ntls(SSL *s, PACKET *pkt) +{ + unsigned int ticklen; + unsigned long ticket_lifetime_hint, age_add = 0; + unsigned int sess_len; + RAW_EXTENSION *exts = NULL; + PACKET nonce; + + PACKET_null_init(&nonce); + + if (!PACKET_get_net_4(pkt, &ticket_lifetime_hint) + || !PACKET_get_net_2(pkt, &ticklen) + || (PACKET_remaining(pkt) != ticklen)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET_NTLS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + /* + * Server is allowed to change its mind (in <=TLSv1.2) and send an empty + * ticket. We already checked this TLSv1.3 case above, so it should never + * be 0 here in that instance + */ + if (ticklen == 0) + return MSG_PROCESS_CONTINUE_READING; + + /* + * Sessions must be immutable once they go into the session cache. Otherwise + * we can get multi-thread problems. Therefore we don't "update" sessions, + * we replace them with a duplicate. In TLSv1.3 we need to do this every + * time a NewSessionTicket arrives because those messages arrive + * post-handshake and the session may have already gone into the session + * cache. + */ + if (s->session->session_id_length > 0) { + SSL_SESSION *new_sess; + + /* + * We reused an existing session, so we need to replace it with a new + * one + */ + if ((new_sess = ssl_session_dup(s->session, 0)) == 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_NEW_SESSION_TICKET_NTLS, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if ((s->session_ctx->session_cache_mode & SSL_SESS_CACHE_CLIENT) != 0) { + /* + * In TLSv1.2 and below the arrival of a new tickets signals that + * any old ticket we were using is now out of date, so we remove the + * old session from the cache. We carry on if this fails + */ + SSL_CTX_remove_session(s->session_ctx, s->session); + } + + SSL_SESSION_free(s->session); + s->session = new_sess; + } + + /* + * Technically the cast to long here is not guaranteed by the C standard - + * but we use it elsewhere, so this should be ok. + */ + s->session->time = (long)time(NULL); + + OPENSSL_free(s->session->ext.tick); + s->session->ext.tick = NULL; + s->session->ext.ticklen = 0; + + s->session->ext.tick = OPENSSL_malloc(ticklen); + if (s->session->ext.tick == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET_NTLS, + ERR_R_MALLOC_FAILURE); + goto err; + } + if (!PACKET_copy_bytes(pkt, s->session->ext.tick, ticklen)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET_NTLS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + s->session->ext.tick_lifetime_hint = ticket_lifetime_hint; + s->session->ext.tick_age_add = age_add; + s->session->ext.ticklen = ticklen; + + /* + * There are two ways to detect a resumed ticket session. One is to set + * an appropriate session ID and then the server must return a match in + * ServerHello. This allows the normal client session ID matching to work + * and we know much earlier that the ticket has been accepted. The + * other way is to set zero length session ID when the ticket is + * presented and rely on the handshake to determine session resumption. + * We choose the former approach because this fits in with assumptions + * elsewhere in OpenSSL. The session ID is set to the SHA256 (or SHA1 is + * SHA256 is disabled) hash of the ticket. + */ + /* + * TODO(size_t): we use sess_len here because EVP_Digest expects an int + * but s->session->session_id_length is a size_t + */ + if (!EVP_Digest(s->session->ext.tick, ticklen, + s->session->session_id, &sess_len, + EVP_sha256(), NULL)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET_NTLS, + ERR_R_EVP_LIB); + goto err; + } + s->session->session_id_length = sess_len; + s->session->not_resumable = 0; + + return MSG_PROCESS_CONTINUE_READING; + err: + OPENSSL_free(exts); + return MSG_PROCESS_ERROR; +} + +/* + * In TLSv1.3 this is called from the extensions code, otherwise it is used to + * parse a separate message. Returns 1 on success or 0 on failure + */ +int tls_process_cert_status_body_ntls(SSL *s, PACKET *pkt) +{ + size_t resplen; + unsigned int type; + + if (!PACKET_get_1(pkt, &type) + || type != TLSEXT_STATUSTYPE_ocsp) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY_NTLS, + SSL_R_UNSUPPORTED_STATUS_TYPE); + return 0; + } + if (!PACKET_get_net_3_len(pkt, &resplen) + || PACKET_remaining(pkt) != resplen) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY_NTLS, + SSL_R_LENGTH_MISMATCH); + return 0; + } + s->ext.ocsp.resp = OPENSSL_malloc(resplen); + if (s->ext.ocsp.resp == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY_NTLS, + ERR_R_MALLOC_FAILURE); + return 0; + } + if (!PACKET_copy_bytes(pkt, s->ext.ocsp.resp, resplen)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY_NTLS, + SSL_R_LENGTH_MISMATCH); + return 0; + } + s->ext.ocsp.resp_len = resplen; + + return 1; +} + + +MSG_PROCESS_RETURN tls_process_cert_status_ntls(SSL *s, PACKET *pkt) +{ + if (!tls_process_cert_status_body_ntls(s, pkt)) { + /* SSLfatal_ntls() already called */ + return MSG_PROCESS_ERROR; + } + + return MSG_PROCESS_CONTINUE_READING; +} + +/* + * Perform miscellaneous checks and processing after we have received the + * server's initial flight. In TLS1.3 this is after the Server Finished message. + * In <=TLS1.2 this is after the ServerDone message. Returns 1 on success or 0 + * on failure. + */ +int tls_process_initial_server_flight_ntls(SSL *s) +{ + /* + * at this point we check that we have the required stuff from + * the server + */ + if (!ssl3_check_cert_and_algorithm_ntls(s)) { + /* SSLfatal_ntls() already called */ + return 0; + } + + /* + * Call the ocsp status callback if needed. The |ext.ocsp.resp| and + * |ext.ocsp.resp_len| values will be set if we actually received a status + * message, or NULL and -1 otherwise + */ + if (s->ext.status_type != TLSEXT_STATUSTYPE_nothing + && s->ctx->ext.status_cb != NULL) { + int ret = s->ctx->ext.status_cb(s, s->ctx->ext.status_arg); + + if (ret == 0) { + SSLfatal_ntls(s, SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE, + SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT_NTLS, + SSL_R_INVALID_STATUS_RESPONSE); + return 0; + } + if (ret < 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT_NTLS, + ERR_R_MALLOC_FAILURE); + return 0; + } + } +# ifndef OPENSSL_NO_CT + if (s->ct_validation_callback != NULL) { + /* Note we validate the SCTs whether or not we abort on error */ + if (!ssl_validate_ct(s) && (s->verify_mode & SSL_VERIFY_PEER)) { + /* SSLfatal_ntls() already called */ + return 0; + } + } +# endif + + return 1; +} + +MSG_PROCESS_RETURN tls_process_server_done_ntls(SSL *s, PACKET *pkt) +{ + if (PACKET_remaining(pkt) > 0) { + /* should contain no data */ + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_DONE_NTLS, + SSL_R_LENGTH_MISMATCH); + return MSG_PROCESS_ERROR; + } + + if (!tls_process_initial_server_flight_ntls(s)) { + /* SSLfatal_ntls() already called */ + return MSG_PROCESS_ERROR; + } + + return MSG_PROCESS_FINISHED_READING; +} + +static int tls_construct_cke_psk_preamble(SSL *s, WPACKET *pkt) +{ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, + ERR_R_INTERNAL_ERROR); + return 0; +} + +static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt) +{ +# ifndef OPENSSL_NO_RSA + unsigned char *encdata = NULL; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *pctx = NULL; + size_t enclen; + unsigned char *pms = NULL; + size_t pmslen = 0; + + if (s->session->peer == NULL) { + /* + * We should always have a server certificate with SSL_kRSA. + */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA, + ERR_R_INTERNAL_ERROR); + return 0; + } + + pkey = X509_get0_pubkey(s->session->peer); + if (EVP_PKEY_get0_RSA(pkey) == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA, + ERR_R_INTERNAL_ERROR); + return 0; + } + + pmslen = SSL_MAX_MASTER_KEY_LENGTH; + pms = OPENSSL_malloc(pmslen); + if (pms == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA, + ERR_R_MALLOC_FAILURE); + return 0; + } + + pms[0] = s->client_version >> 8; + pms[1] = s->client_version & 0xff; + /* TODO(size_t): Convert this function */ + if (RAND_bytes(pms + 2, (int)(pmslen - 2)) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA, + ERR_R_MALLOC_FAILURE); + goto err; + } + + /* Fix buf for TLS and beyond */ + + if (!WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA, + ERR_R_INTERNAL_ERROR); + goto err; + } + + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (pctx == NULL || EVP_PKEY_encrypt_init(pctx) <= 0 + || EVP_PKEY_encrypt(pctx, NULL, &enclen, pms, pmslen) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA, + ERR_R_EVP_LIB); + goto err; + } + if (!WPACKET_allocate_bytes(pkt, enclen, &encdata) + || EVP_PKEY_encrypt(pctx, encdata, &enclen, pms, pmslen) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA, + SSL_R_BAD_RSA_ENCRYPT); + goto err; + } + EVP_PKEY_CTX_free(pctx); + pctx = NULL; + + /* Fix buf for TLS and beyond */ + if (!WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* Log the premaster secret, if logging is enabled. */ + if (!ssl_log_rsa_client_key_exchange(s, encdata, enclen, pms, pmslen)) { + /* SSLfatal_ntls() already called */ + goto err; + } + + s->s3->tmp.pms = pms; + s->s3->tmp.pmslen = pmslen; + + return 1; + err: + OPENSSL_clear_free(pms, pmslen); + EVP_PKEY_CTX_free(pctx); + + return 0; +# else + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA, + ERR_R_INTERNAL_ERROR); + return 0; +# endif +} + +static int tls_construct_cke_dhe(SSL *s, WPACKET *pkt) +{ +# ifndef OPENSSL_NO_DH + DH *dh_clnt = NULL; + const BIGNUM *pub_key; + EVP_PKEY *ckey = NULL, *skey = NULL; + unsigned char *keybytes = NULL; + + skey = s->s3->peer_tmp; + if (skey == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + ckey = ssl_generate_pkey(skey); + if (ckey == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + dh_clnt = EVP_PKEY_get0_DH(ckey); + + if (dh_clnt == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (ssl_derive(s, ckey, skey, 0) == 0) { + /* SSLfatal_ntls() already called */ + goto err; + } + + /* send off the data */ + DH_get0_key(dh_clnt, &pub_key, NULL); + if (!WPACKET_sub_allocate_bytes_u16(pkt, BN_num_bytes(pub_key), + &keybytes)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + BN_bn2bin(pub_key, keybytes); + EVP_PKEY_free(ckey); + + return 1; + err: + EVP_PKEY_free(ckey); + return 0; +# else + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE, + ERR_R_INTERNAL_ERROR); + return 0; +# endif +} + +static int tls_construct_cke_ecdhe(SSL *s, WPACKET *pkt) +{ +# ifndef OPENSSL_NO_EC + unsigned char *encodedPoint = NULL; + size_t encoded_pt_len = 0; + EVP_PKEY *ckey = NULL, *skey = NULL; + int ret = 0; + + skey = s->s3->peer_tmp; + if (skey == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE, + ERR_R_INTERNAL_ERROR); + return 0; + } + + ckey = ssl_generate_pkey(skey); + if (ckey == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if (ssl_derive(s, ckey, skey, 0) == 0) { + /* SSLfatal_ntls() already called */ + goto err; + } + + /* Generate encoding of client key */ + encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(ckey, &encodedPoint); + + if (encoded_pt_len == 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE, + ERR_R_EC_LIB); + goto err; + } + + if (!WPACKET_sub_memcpy_u8(pkt, encodedPoint, encoded_pt_len)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + ret = 1; + err: + OPENSSL_free(encodedPoint); + EVP_PKEY_free(ckey); + return ret; +# else + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE, + ERR_R_INTERNAL_ERROR); + return 0; +# endif +} + +static int tls_construct_cke_gost(SSL *s, WPACKET *pkt) +{ +# ifndef OPENSSL_NO_GOST + /* GOST key exchange message creation */ + EVP_PKEY_CTX *pkey_ctx = NULL; + X509 *peer_cert; + size_t msglen; + unsigned int md_len; + unsigned char shared_ukm[32], tmp[256]; + EVP_MD_CTX *ukm_hash = NULL; + int dgst_nid = NID_id_GostR3411_94; + unsigned char *pms = NULL; + size_t pmslen = 0; + + if ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aGOST12) != 0) + dgst_nid = NID_id_GostR3411_2012_256; + + /* + * Get server certificate PKEY and create ctx from it + */ + peer_cert = s->session->peer; + if (!peer_cert) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_CONSTRUCT_CKE_GOST, + SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER); + return 0; + } + + pkey_ctx = EVP_PKEY_CTX_new(X509_get0_pubkey(peer_cert), NULL); + if (pkey_ctx == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST, + ERR_R_MALLOC_FAILURE); + return 0; + } + /* + * If we have send a certificate, and certificate key + * parameters match those of server certificate, use + * certificate key for key exchange + */ + + /* Otherwise, generate ephemeral key pair */ + pmslen = 32; + pms = OPENSSL_malloc(pmslen); + if (pms == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0 + /* Generate session key + * TODO(size_t): Convert this function + */ + || RAND_bytes(pms, (int)pmslen) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST, + ERR_R_INTERNAL_ERROR); + goto err; + }; + /* + * Compute shared IV and store it in algorithm-specific context + * data + */ + ukm_hash = EVP_MD_CTX_new(); + if (ukm_hash == NULL + || EVP_DigestInit(ukm_hash, EVP_get_digestbynid(dgst_nid)) <= 0 + || EVP_DigestUpdate(ukm_hash, s->s3->client_random, + SSL3_RANDOM_SIZE) <= 0 + || EVP_DigestUpdate(ukm_hash, s->s3->server_random, + SSL3_RANDOM_SIZE) <= 0 + || EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST, + ERR_R_INTERNAL_ERROR); + goto err; + } + EVP_MD_CTX_free(ukm_hash); + ukm_hash = NULL; + if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT, + EVP_PKEY_CTRL_SET_IV, 8, shared_ukm) < 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST, + SSL_R_LIBRARY_BUG); + goto err; + } + /* Make GOST keytransport blob message */ + /* + * Encapsulate it into sequence + */ + msglen = 255; + if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST, + SSL_R_LIBRARY_BUG); + goto err; + } + + if (!WPACKET_put_bytes_u8(pkt, V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) + || (msglen >= 0x80 && !WPACKET_put_bytes_u8(pkt, 0x81)) + || !WPACKET_sub_memcpy_u8(pkt, tmp, msglen)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST, + ERR_R_INTERNAL_ERROR); + goto err; + } + + EVP_PKEY_CTX_free(pkey_ctx); + s->s3->tmp.pms = pms; + s->s3->tmp.pmslen = pmslen; + + return 1; + err: + EVP_PKEY_CTX_free(pkey_ctx); + OPENSSL_clear_free(pms, pmslen); + EVP_MD_CTX_free(ukm_hash); + return 0; +# else + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST, + ERR_R_INTERNAL_ERROR); + return 0; +# endif +} + +int tls_construct_client_key_exchange_ntls(SSL *s, WPACKET *pkt) +{ + unsigned long alg_k; + + alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + + /* + * All of the construct functions below call SSLfatal_ntls() if necessary so + * no need to do so here. + */ + if ((alg_k & SSL_PSK) + && !tls_construct_cke_psk_preamble(s, pkt)) + goto err; + + if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) { + if (!tls_construct_cke_rsa(s, pkt)) + goto err; + } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) { + if (!tls_construct_cke_dhe(s, pkt)) + goto err; + } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK | SSL_kSM2DHE)) { + if (!tls_construct_cke_ecdhe(s, pkt)) + goto err; + } else if (alg_k & SSL_kGOST) { + if (!tls_construct_cke_gost(s, pkt)) + goto err; + } else if (!(alg_k & SSL_kPSK)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE_NTLS, ERR_R_INTERNAL_ERROR); + goto err; + } + + return 1; + err: + OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen); + s->s3->tmp.pms = NULL; + return 0; +} + +int tls_client_key_exchange_post_work_ntls(SSL *s) +{ + unsigned char *pms = NULL; + size_t pmslen = 0; + + pms = s->s3->tmp.pms; + pmslen = s->s3->tmp.pmslen; + + if (pms == NULL && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK_NTLS, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!ssl_generate_master_secret(s, pms, pmslen, 1)) { + /* SSLfatal_ntls() already called */ + /* ssl_generate_master_secret frees the pms even on error */ + pms = NULL; + pmslen = 0; + goto err; + } + pms = NULL; + pmslen = 0; + + return 1; + err: + OPENSSL_clear_free(pms, pmslen); + s->s3->tmp.pms = NULL; + return 0; +} + +/* + * Check a certificate can be used for client authentication. Currently check + * cert exists, if we have a suitable digest for TLS 1.2 if static DH client + * certificates can be used and optionally checks suitability for Suite B. + */ +static int ssl3_check_client_certificate(SSL *s) +{ + /* If no suitable signature algorithm can't use certificate */ + if (!tls_choose_sigalg(s, 0) || s->s3->tmp.sigalg == NULL) + return 0; + /* + * If strict mode check suitability of chain before using it. This also + * adjusts suite B digest if necessary. + */ + if (s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT && + !tls1_check_chain(s, NULL, NULL, NULL, -2)) + return 0; + return 1; +} + +WORK_STATE tls_prepare_client_certificate_ntls(SSL *s, WORK_STATE wst) +{ + X509 *x509 = NULL; + EVP_PKEY *pkey = NULL; + int i; + + if (wst == WORK_MORE_A) { + /* Let cert callback update client certificates if required */ + if (s->cert->cert_cb) { + i = s->cert->cert_cb(s, s->cert->cert_cb_arg); + if (i < 0) { + s->rwstate = SSL_X509_LOOKUP; + return WORK_MORE_A; + } + if (i == 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE_NTLS, + SSL_R_CALLBACK_FAILED); + return WORK_ERROR; + } + s->rwstate = SSL_NOTHING; + } + if (ssl3_check_client_certificate(s)) { + if (s->post_handshake_auth == SSL_PHA_REQUESTED) { + return WORK_FINISHED_STOP; + } + return WORK_FINISHED_CONTINUE; + } + + /* Fall through to WORK_MORE_B */ + wst = WORK_MORE_B; + } + + /* We need to get a client cert */ + if (wst == WORK_MORE_B) { + /* + * If we get an error, we need to ssl->rwstate=SSL_X509_LOOKUP; + * return(-1); We then get retied later + */ + i = ssl_do_client_cert_cb_ntls(s, &x509, &pkey); + if (i < 0) { + s->rwstate = SSL_X509_LOOKUP; + return WORK_MORE_B; + } + s->rwstate = SSL_NOTHING; + if ((i == 1) && (pkey != NULL) && (x509 != NULL)) { + if (!SSL_use_certificate(s, x509) || !SSL_use_PrivateKey(s, pkey)) + i = 0; + } else if (i == 1) { + i = 0; + SSLerr(SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE_NTLS, + SSL_R_BAD_DATA_RETURNED_BY_CALLBACK); + } + + X509_free(x509); + EVP_PKEY_free(pkey); + if (i && !ssl3_check_client_certificate(s)) + i = 0; + + if (s->post_handshake_auth == SSL_PHA_REQUESTED) + return WORK_FINISHED_STOP; + return WORK_FINISHED_CONTINUE; + } + + /* Shouldn't ever get here */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE_NTLS, + ERR_R_INTERNAL_ERROR); + return WORK_ERROR; +} + +int tls_construct_client_certificate_ntls(SSL *s, WPACKET *pkt) +{ + if (!ssl3_output_cert_chain_ntls(s, pkt, + (s->s3->tmp.cert_req == 2) ? NULL + : s->cert->key)) { + /* SSLfatal_ntls() already called */ + return 0; + } + + return 1; +} + +int ssl3_check_cert_and_algorithm_ntls(SSL *s) +{ + const SSL_CERT_LOOKUP *clu; + size_t idx; + long alg_k, alg_a; + + alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + alg_a = s->s3->tmp.new_cipher->algorithm_auth; + + /* we don't have a certificate */ + if (!(alg_a & SSL_aCERT)) + return 1; + + /* This is the passed certificate */ + clu = ssl_cert_lookup_by_pkey(X509_get0_pubkey(s->session->peer), &idx); + + /* Check certificate is recognised and suitable for cipher */ + if (clu == NULL || (alg_a & clu->amask) == 0) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM_NTLS, + SSL_R_MISSING_SIGNING_CERT); + return 0; + } + +# ifndef OPENSSL_NO_EC + if (clu->amask & SSL_aECDSA) { + if (ssl_check_srvr_ecc_cert_and_alg(s->session->peer, s)) + return 1; + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM_NTLS, SSL_R_BAD_ECC_CERT); + return 0; + } +# endif +# ifndef OPENSSL_NO_RSA + if (alg_k & (SSL_kRSA | SSL_kRSAPSK) && idx != SSL_PKEY_RSA) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM_NTLS, + SSL_R_MISSING_RSA_ENCRYPTING_CERT); + return 0; + } +# endif +# ifndef OPENSSL_NO_DH + if ((alg_k & SSL_kDHE) && (s->s3->peer_tmp == NULL)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } +# endif + + return 1; +} + +# ifndef OPENSSL_NO_NEXTPROTONEG +int tls_construct_next_proto_ntls(SSL *s, WPACKET *pkt) +{ + size_t len, padding_len; + unsigned char *padding = NULL; + + len = s->ext.npn_len; + padding_len = 32 - ((len + 2) % 32); + + if (!WPACKET_sub_memcpy_u8(pkt, s->ext.npn, len) + || !WPACKET_sub_allocate_bytes_u8(pkt, padding_len, &padding)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_NEXT_PROTO_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + memset(padding, 0, padding_len); + + return 1; +} +# endif + +MSG_PROCESS_RETURN tls_process_hello_req_ntls(SSL *s, PACKET *pkt) +{ + if (PACKET_remaining(pkt) > 0) { + /* should contain no data */ + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_HELLO_REQ_NTLS, + SSL_R_LENGTH_MISMATCH); + return MSG_PROCESS_ERROR; + } + + if ((s->options & SSL_OP_NO_RENEGOTIATION)) { + ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION); + return MSG_PROCESS_FINISHED_READING; + } + + /* + * This is a historical discrepancy (not in the RFC) maintained for + * compatibility reasons. If a TLS client receives a HelloRequest it will + * attempt an abbreviated handshake. + */ + SSL_renegotiate_abbreviated(s); + + return MSG_PROCESS_FINISHED_READING; +} + +static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt) +{ + PACKET extensions; + RAW_EXTENSION *rawexts = NULL; + + if (!PACKET_as_length_prefixed_2(pkt, &extensions) + || PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + if (!tls_collect_extensions_ntls(s, &extensions, + SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, &rawexts, + NULL, 1) + || !tls_parse_all_extensions_ntls(s, SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, + rawexts, NULL, 0, 1)) { + /* SSLfatal_ntls() already called */ + goto err; + } + + OPENSSL_free(rawexts); + return MSG_PROCESS_CONTINUE_READING; + + err: + OPENSSL_free(rawexts); + return MSG_PROCESS_ERROR; +} + +int ssl_do_client_cert_cb_ntls(SSL *s, X509 **px509, EVP_PKEY **ppkey) +{ + int i = 0; +# ifndef OPENSSL_NO_ENGINE + if (s->ctx->client_cert_engine) { + i = ENGINE_load_ssl_client_cert(s->ctx->client_cert_engine, s, + SSL_get_client_CA_list(s), + px509, ppkey, NULL, NULL, NULL); + if (i != 0) + return i; + } +# endif + if (s->ctx->client_cert_cb) + i = s->ctx->client_cert_cb(s, px509, ppkey); + return i; +} + +int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, WPACKET *pkt) +{ + int i; + size_t totlen = 0, len, maxlen, maxverok = 0; + int empty_reneg_info_scsv = !s->renegotiate; + + /* Set disabled masks for this session */ + if (!ssl_set_client_disabled(s)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES, + SSL_R_NO_PROTOCOLS_AVAILABLE); + return 0; + } + + if (sk == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES, + ERR_R_INTERNAL_ERROR); + return 0; + } + +# ifdef OPENSSL_MAX_TLS1_2_CIPHER_LENGTH +# if OPENSSL_MAX_TLS1_2_CIPHER_LENGTH < 6 +# error Max cipher length too short +# endif + /* + * Some servers hang if client hello > 256 bytes as hack workaround + * chop number of supported ciphers to keep it well below this if we + * use TLS v1.2 + */ + if (TLS1_get_version(s) >= TLS1_2_VERSION) + maxlen = OPENSSL_MAX_TLS1_2_CIPHER_LENGTH & ~1; + else +# endif + /* Maximum length that can be stored in 2 bytes. Length must be even */ + maxlen = 0xfffe; + + if (empty_reneg_info_scsv) + maxlen -= 2; + if (s->mode & SSL_MODE_SEND_FALLBACK_SCSV) + maxlen -= 2; + + for (i = 0; i < sk_SSL_CIPHER_num(sk) && totlen < maxlen; i++) { + const SSL_CIPHER *c; + + c = sk_SSL_CIPHER_value(sk, i); + /* Skip disabled ciphers */ + if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0)) + continue; + + if (!s->method->put_cipher_by_char(c, pkt, &len)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* Sanity check that the maximum version we offer has ciphers enabled */ + if (!maxverok) { + if (c->max_tls >= s->s3->tmp.max_ver + && c->min_tls <= s->s3->tmp.max_ver) + maxverok = 1; + + } + + totlen += len; + } + + if (totlen == 0 || !maxverok) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES, + SSL_R_NO_CIPHERS_AVAILABLE); + + if (!maxverok) + ERR_add_error_data(1, "No ciphers enabled for max supported " + "SSL/TLS version"); + + return 0; + } + + if (totlen != 0) { + if (empty_reneg_info_scsv) { + static SSL_CIPHER scsv = { + 0, NULL, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + if (!s->method->put_cipher_by_char(&scsv, pkt, &len)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_SSL_CIPHER_LIST_TO_BYTES, ERR_R_INTERNAL_ERROR); + return 0; + } + } + if (s->mode & SSL_MODE_SEND_FALLBACK_SCSV) { + static SSL_CIPHER scsv = { + 0, NULL, NULL, SSL3_CK_FALLBACK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + if (!s->method->put_cipher_by_char(&scsv, pkt, &len)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_SSL_CIPHER_LIST_TO_BYTES, ERR_R_INTERNAL_ERROR); + return 0; + } + } + } + + return 1; +} + +int tls_construct_end_of_early_data_ntls(SSL *s, WPACKET *pkt) +{ + if (s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY + && s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA_NTLS, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING; + return 1; +} + +#endif diff --git a/ssl/statem_ntls/statem_lib.c b/ssl/statem_ntls/statem_lib.c new file mode 100644 index 000000000..013dc1395 --- /dev/null +++ b/ssl/statem_ntls/statem_lib.c @@ -0,0 +1,2060 @@ +/* + * Copyright 2019 The BabaSSL Project Authors. All Rights Reserved. + */ + +#include +#include +#include +#include "ssl_local_ntls.h" +#include "statem_local_ntls.h" +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include + +#if (!defined OPENSSL_NO_NTLS) && (!defined OPENSSL_NO_SM2) \ + && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) +/* + * Map error codes to TLS/SSL alart types. + */ +typedef struct x509err2alert_st { + int x509err; + int alert; +} X509ERR2ALERT; + +/* Fixed value used in the ServerHello random field to identify an HRR */ +const unsigned char hrrrandom_ntls[] = { + 0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11, 0xbe, 0x1d, 0x8c, 0x02, + 0x1e, 0x65, 0xb8, 0x91, 0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e, + 0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c +}; + +/* + * send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or + * SSL3_RT_CHANGE_CIPHER_SPEC) + */ +int ssl3_do_write_ntls(SSL *s, int type) +{ + int ret; + size_t written = 0; + + ret = ssl3_write_bytes(s, type, &s->init_buf->data[s->init_off], + s->init_num, &written); + if (ret < 0) + return -1; + if (type == SSL3_RT_HANDSHAKE) + /* + * should not be done for 'Hello Request's, but in that case we'll + * ignore the result anyway + * TLS1.3 KeyUpdate and NewSessionTicket do not need to be added + */ + if ((s->statem.hand_state != TLS_ST_SW_SESSION_TICKET + && s->statem.hand_state != TLS_ST_CW_KEY_UPDATE + && s->statem.hand_state != TLS_ST_SW_KEY_UPDATE)) + if (!ssl3_finish_mac(s, + (unsigned char *)&s->init_buf->data[s->init_off], + written)) + return -1; + if (written == s->init_num) { + if (s->msg_callback) + s->msg_callback(1, s->version, type, s->init_buf->data, + (size_t)(s->init_off + s->init_num), s, + s->msg_callback_arg); + return 1; + } + s->init_off += written; + s->init_num -= written; + return 0; +} + +int tls_close_construct_packet_ntls(SSL *s, WPACKET *pkt, int htype) +{ + size_t msglen; + + if ((htype != SSL3_MT_CHANGE_CIPHER_SPEC && !WPACKET_close(pkt)) + || !WPACKET_get_length(pkt, &msglen) + || msglen > INT_MAX) + return 0; + s->init_num = (int)msglen; + s->init_off = 0; + + return 1; +} + +int tls_setup_handshake_ntls(SSL *s) +{ + if (!ssl3_init_finished_mac(s)) { + /* SSLfatal_ntls() already called */ + return 0; + } + + /* Reset any extension flags */ + memset(s->ext.extflags, 0, sizeof(s->ext.extflags)); + + if (s->server) { + STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(s); + int i, ver_min, ver_max, ok = 0; + + /* + * Sanity check that the maximum version we accept has ciphers + * enabled. For clients we do this check during construction of the + * ClientHello. + */ + if (ssl_get_min_max_version_ntls(s, &ver_min, &ver_max, NULL) != 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_SETUP_HANDSHAKE_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { + const SSL_CIPHER *c = sk_SSL_CIPHER_value(ciphers, i); + + if (ver_max >= c->min_tls && ver_max <= c->max_tls) { + ok = 1; + } + if (ok) + break; + } + if (!ok) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_SETUP_HANDSHAKE_NTLS, + SSL_R_NO_CIPHERS_AVAILABLE); + ERR_add_error_data(1, "No ciphers enabled for max supported " + "SSL/TLS version"); + return 0; + } + if (SSL_IS_FIRST_HANDSHAKE(s)) { + /* N.B. s->session_ctx == s->ctx here */ + tsan_counter(&s->session_ctx->stats.sess_accept); + } else { + /* N.B. s->ctx may not equal s->session_ctx */ + tsan_counter(&s->ctx->stats.sess_accept_renegotiate); + + s->s3->tmp.cert_request = 0; + } + } else { + if (SSL_IS_FIRST_HANDSHAKE(s)) + tsan_counter(&s->session_ctx->stats.sess_connect); + else + tsan_counter(&s->session_ctx->stats.sess_connect_renegotiate); + + /* mark client_random uninitialized */ + memset(s->s3->client_random, 0, sizeof(s->s3->client_random)); + s->hit = 0; + + s->s3->tmp.cert_req = 0; + + } + + return 1; +} + +/* + * Size of the to-be-signed TLS13 data, without the hash size itself: + * 64 bytes of value 32, 33 context bytes, 1 byte separator + */ +# define TLS13_TBS_START_SIZE 64 +# define TLS13_TBS_PREAMBLE_SIZE (TLS13_TBS_START_SIZE + 33 + 1) + +static int get_cert_verify_tbs_data(SSL *s, unsigned char *tls13tbs, + void **hdata, size_t *hdatalen) +{ + { + size_t retlen; + long retlen_l; + + retlen = retlen_l = BIO_get_mem_data(s->s3->handshake_buffer, hdata); + if (retlen_l <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_GET_CERT_VERIFY_TBS_DATA, + ERR_R_INTERNAL_ERROR); + return 0; + } + *hdatalen = retlen; + } + + return 1; +} + +MSG_PROCESS_RETURN tls_process_cert_verify_ntls(SSL *s, PACKET *pkt) +{ + EVP_PKEY *pkey = NULL; + const unsigned char *data; +# ifndef OPENSSL_NO_GOST + unsigned char *gost_data = NULL; +# endif + MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR; + int j; + unsigned int len; + X509 *peer; + const EVP_MD *md = NULL; + size_t hdatalen = 0; + void *hdata; + unsigned char tls13tbs[TLS13_TBS_PREAMBLE_SIZE + EVP_MAX_MD_SIZE]; + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + EVP_PKEY_CTX *pctx = NULL; + + if (mctx == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY_NTLS, + ERR_R_MALLOC_FAILURE); + goto err; + } + + peer = s->session->peer; + pkey = X509_get0_pubkey(peer); + if (pkey == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (ssl_cert_lookup_by_pkey(pkey, NULL) == NULL) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_CERT_VERIFY_NTLS, + SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE); + goto err; + } + + if (SSL_USE_SIGALGS(s)) { + unsigned int sigalg; + + if (!PACKET_get_net_2(pkt, &sigalg)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY_NTLS, + SSL_R_BAD_PACKET); + goto err; + } + if (tls12_check_peer_sigalg(s, sigalg, pkey) <= 0) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else if (!tls1_set_peer_legacy_sigalg(s, pkey)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!tls1_lookup_md(s->s3->tmp.peer_sigalg, &md)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + +# ifdef SSL_DEBUG + if (SSL_USE_SIGALGS(s)) + fprintf(stderr, "USING TLSv1.2 HASH %s\n", + md == NULL ? "n/a" : EVP_MD_name(md)); +# endif + + /* Check for broken implementations of GOST ciphersuites */ + /* + * If key is GOST and len is exactly 64 or 128, it is signature without + * length field (CryptoPro implementations at least till TLS 1.2) + */ +# ifndef OPENSSL_NO_GOST + if (!SSL_USE_SIGALGS(s) + && ((PACKET_remaining(pkt) == 64 + && (EVP_PKEY_id(pkey) == NID_id_GostR3410_2001 + || EVP_PKEY_id(pkey) == NID_id_GostR3410_2012_256)) + || (PACKET_remaining(pkt) == 128 + && EVP_PKEY_id(pkey) == NID_id_GostR3410_2012_512))) { + len = PACKET_remaining(pkt); + } else +# endif + if (!PACKET_get_net_2(pkt, &len)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY_NTLS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + j = EVP_PKEY_size(pkey); + if (((int)len > j) || ((int)PACKET_remaining(pkt) > j) + || (PACKET_remaining(pkt) == 0)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY_NTLS, + SSL_R_WRONG_SIGNATURE_SIZE); + goto err; + } + if (!PACKET_get_bytes(pkt, &data, len)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY_NTLS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + if (!get_cert_verify_tbs_data(s, tls13tbs, &hdata, &hdatalen)) { + /* SSLfatal_ntls() already called */ + goto err; + } + +# ifdef SSL_DEBUG + fprintf(stderr, "Using client verify alg %s\n", + md == NULL ? "n/a" : EVP_MD_name(md)); +# endif + +# ifndef OPENSSL_NO_SM2 + if (EVP_PKEY_is_sm2(pkey)) { + if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (pkey != NULL) { + pctx = EVP_PKEY_CTX_new(pkey, NULL); + + if (EVP_PKEY_CTX_set1_id(pctx, HANDSHAKE_SM2_ID, HANDSHAKE_SM2_ID_LEN) != 1) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY_NTLS, + ERR_R_EVP_LIB); + } + EVP_MD_CTX_set_pkey_ctx(mctx, pctx); + } + + if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_EC)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + } +# endif + + if (EVP_DigestVerifyInit(mctx, &pctx, md, NULL, pkey) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY_NTLS, + ERR_R_EVP_LIB); + goto err; + } +# ifndef OPENSSL_NO_GOST + { + int pktype = EVP_PKEY_id(pkey); + if (pktype == NID_id_GostR3410_2001 + || pktype == NID_id_GostR3410_2012_256 + || pktype == NID_id_GostR3410_2012_512) { + if ((gost_data = OPENSSL_malloc(len)) == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_CERT_VERIFY_NTLS, ERR_R_MALLOC_FAILURE); + goto err; + } + BUF_reverse(gost_data, data, len); + data = gost_data; + } + } +# endif + + if (SSL_USE_PSS(s)) { + if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0 + || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, + RSA_PSS_SALTLEN_DIGEST) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY_NTLS, + ERR_R_EVP_LIB); + goto err; + } + } + if (s->version == SSL3_VERSION) { + if (EVP_DigestVerifyUpdate(mctx, hdata, hdatalen) <= 0 + || !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET, + (int)s->session->master_key_length, + s->session->master_key)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY_NTLS, + ERR_R_EVP_LIB); + goto err; + } + if (EVP_DigestVerifyFinal(mctx, data, len) <= 0) { + SSLfatal_ntls(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY_NTLS, + SSL_R_BAD_SIGNATURE); + goto err; + } + } else { + j = EVP_DigestVerify(mctx, data, len, hdata, hdatalen); + if (j <= 0) { + SSLfatal_ntls(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY_NTLS, + SSL_R_BAD_SIGNATURE); + goto err; + } + } + + ret = MSG_PROCESS_CONTINUE_READING; + err: + BIO_free(s->s3->handshake_buffer); + s->s3->handshake_buffer = NULL; + EVP_MD_CTX_free(mctx); +# ifndef OPENSSL_NO_GOST + OPENSSL_free(gost_data); +# endif +# ifndef OPENSSL_NO_SM2 + if (pkey != NULL && EVP_PKEY_is_sm2(pkey)) { + /*other sig call EVP_PKEY_CTX_free there may cause segfault */ + EVP_PKEY_CTX_free(pctx); + } +# endif + return ret; +} + +int tls_construct_finished_ntls(SSL *s, WPACKET *pkt) +{ + size_t finish_md_len; + const char *sender; + size_t slen; + + /* This is a real handshake so make sure we clean it up at the end */ + if (!s->server && s->post_handshake_auth != SSL_PHA_REQUESTED) + s->statem.cleanuphand = 1; + + if (s->server) { + sender = s->method->ssl3_enc->server_finished_label; + slen = s->method->ssl3_enc->server_finished_label_len; + } else { + sender = s->method->ssl3_enc->client_finished_label; + slen = s->method->ssl3_enc->client_finished_label_len; + } + + finish_md_len = s->method->ssl3_enc->final_finish_mac(s, + sender, slen, + s->s3->tmp.finish_md); + if (finish_md_len == 0) { + /* SSLfatal_ntls() already called */ + return 0; + } + + s->s3->tmp.finish_md_len = finish_md_len; + + if (!WPACKET_memcpy(pkt, s->s3->tmp.finish_md, finish_md_len)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_FINISHED_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* + * Log the master secret, if logging is enabled. We don't log it for + * TLSv1.3: there's a different key schedule for that. + */ + if (!ssl_log_secret(s, MASTER_SECRET_LABEL, + s->session->master_key, + s->session->master_key_length)) { + /* SSLfatal_ntls() already called */ + return 0; + } + + /* + * Copy the finished so we can use it for renegotiation checks + */ + if (!ossl_assert(finish_md_len <= EVP_MAX_MD_SIZE)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_FINISHED_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + if (!s->server) { + memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md, + finish_md_len); + s->s3->previous_client_finished_len = finish_md_len; + } else { + memcpy(s->s3->previous_server_finished, s->s3->tmp.finish_md, + finish_md_len); + s->s3->previous_server_finished_len = finish_md_len; + } + + return 1; +} + +int tls_construct_key_update_ntls(SSL *s, WPACKET *pkt) +{ + if (!WPACKET_put_bytes_u8(pkt, s->key_update)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_KEY_UPDATE_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + s->key_update = SSL_KEY_UPDATE_NONE; + return 1; +} + +MSG_PROCESS_RETURN tls_process_key_update_ntls(SSL *s, PACKET *pkt) +{ + unsigned int updatetype; + + /* + * A KeyUpdate message signals a key change so the end of the message must + * be on a record boundary. + */ + if (RECORD_LAYER_processed_read_pending(&s->rlayer)) { + SSLfatal_ntls(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_KEY_UPDATE_NTLS, + SSL_R_NOT_ON_RECORD_BOUNDARY); + return MSG_PROCESS_ERROR; + } + + if (!PACKET_get_1(pkt, &updatetype) + || PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_UPDATE_NTLS, + SSL_R_BAD_KEY_UPDATE); + return MSG_PROCESS_ERROR; + } + + /* + * There are only two defined key update types. Fail if we get a value we + * didn't recognise. + */ + if (updatetype != SSL_KEY_UPDATE_NOT_REQUESTED + && updatetype != SSL_KEY_UPDATE_REQUESTED) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_KEY_UPDATE_NTLS, + SSL_R_BAD_KEY_UPDATE); + return MSG_PROCESS_ERROR; + } + + /* + * If we get a request for us to update our sending keys too then, we need + * to additionally send a KeyUpdate message. However that message should + * not also request an update (otherwise we get into an infinite loop). + */ + if (updatetype == SSL_KEY_UPDATE_REQUESTED) + s->key_update = SSL_KEY_UPDATE_NOT_REQUESTED; + + if (!tls13_update_key(s, 0)) { + /* SSLfatal_ntls() already called */ + return MSG_PROCESS_ERROR; + } + + return MSG_PROCESS_FINISHED_READING; +} + +/* + * ssl3_take_mac_ntls calculates the Finished MAC for the handshakes messages seen + * to far. + */ +int ssl3_take_mac_ntls(SSL *s) +{ + const char *sender; + size_t slen; + + if (!s->server) { + sender = s->method->ssl3_enc->server_finished_label; + slen = s->method->ssl3_enc->server_finished_label_len; + } else { + sender = s->method->ssl3_enc->client_finished_label; + slen = s->method->ssl3_enc->client_finished_label_len; + } + + s->s3->tmp.peer_finish_md_len = + s->method->ssl3_enc->final_finish_mac(s, sender, slen, + s->s3->tmp.peer_finish_md); + + if (s->s3->tmp.peer_finish_md_len == 0) { + /* SSLfatal_ntls() already called */ + return 0; + } + + return 1; +} + +MSG_PROCESS_RETURN tls_process_change_cipher_spec_ntls(SSL *s, PACKET *pkt) +{ + size_t remain; + + remain = PACKET_remaining(pkt); + /* + * 'Change Cipher Spec' is just a single byte, which should already have + * been consumed by ssl_get_message() so there should be no bytes left, + */ + if (remain != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC_NTLS, + SSL_R_BAD_CHANGE_CIPHER_SPEC); + return MSG_PROCESS_ERROR; + } + + + /* Check we have a cipher to change to */ + if (s->s3->tmp.new_cipher == NULL) { + SSLfatal_ntls(s, SSL_AD_UNEXPECTED_MESSAGE, + SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC_NTLS, SSL_R_CCS_RECEIVED_EARLY); + return MSG_PROCESS_ERROR; + } + + s->s3->change_cipher_spec = 1; + if (!ssl3_do_change_cipher_spec(s)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC_NTLS, + ERR_R_INTERNAL_ERROR); + return MSG_PROCESS_ERROR; + } + + return MSG_PROCESS_CONTINUE_READING; +} + +MSG_PROCESS_RETURN tls_process_finished_ntls(SSL *s, PACKET *pkt) +{ + size_t md_len; + + + /* This is a real handshake so make sure we clean it up at the end */ + if (s->server) { + /* + * To get this far we must have read encrypted data from the client. We + * no longer tolerate unencrypted alerts. This value is ignored if less + * than TLSv1.3 + */ + s->statem.enc_read_state = ENC_READ_STATE_VALID; + if (s->post_handshake_auth != SSL_PHA_REQUESTED) + s->statem.cleanuphand = 1; + } + + /* If this occurs, we have missed a message */ + if (!s->s3->change_cipher_spec) { + SSLfatal_ntls(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_FINISHED_NTLS, + SSL_R_GOT_A_FIN_BEFORE_A_CCS); + return MSG_PROCESS_ERROR; + } + s->s3->change_cipher_spec = 0; + + md_len = s->s3->tmp.peer_finish_md_len; + + if (md_len != PACKET_remaining(pkt)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_FINISHED_NTLS, + SSL_R_BAD_DIGEST_LENGTH); + return MSG_PROCESS_ERROR; + } + + if (CRYPTO_memcmp(PACKET_data(pkt), s->s3->tmp.peer_finish_md, + md_len) != 0) { + SSLfatal_ntls(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_FINISHED_NTLS, + SSL_R_DIGEST_CHECK_FAILED); + return MSG_PROCESS_ERROR; + } + + /* + * Copy the finished so we can use it for renegotiation checks + */ + if (!ossl_assert(md_len <= EVP_MAX_MD_SIZE)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_FINISHED_NTLS, + ERR_R_INTERNAL_ERROR); + return MSG_PROCESS_ERROR; + } + if (s->server) { + memcpy(s->s3->previous_client_finished, s->s3->tmp.peer_finish_md, + md_len); + s->s3->previous_client_finished_len = md_len; + } else { + memcpy(s->s3->previous_server_finished, s->s3->tmp.peer_finish_md, + md_len); + s->s3->previous_server_finished_len = md_len; + } + + return MSG_PROCESS_FINISHED_READING; +} + +int tls_construct_change_cipher_spec_ntls(SSL *s, WPACKET *pkt) +{ + if (!WPACKET_put_bytes_u8(pkt, SSL3_MT_CCS)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC_NTLS, ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +/* Add a certificate to the WPACKET */ +int ssl_add_cert_to_wpacket_ntls(SSL *s, WPACKET *pkt, X509 *x, int chain) +{ + int len; + unsigned char *outbytes; + + len = i2d_X509(x, NULL); + if (len < 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_TO_WPACKET_NTLS, + ERR_R_BUF_LIB); + return 0; + } + if (!WPACKET_sub_allocate_bytes_u24(pkt, len, &outbytes) + || i2d_X509(x, &outbytes) != len) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_TO_WPACKET_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +/* Add certificate chain to provided WPACKET */ +static int ssl_add_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk) +{ + int i, chain_count; + X509 *x; + STACK_OF(X509) *extra_certs; + STACK_OF(X509) *chain = NULL; + X509_STORE *chain_store; + + if (cpk == NULL || cpk->x509 == NULL) + return 1; + + x = cpk->x509; + + /* + * If we have a certificate specific chain use it, else use parent ctx. + */ + if (cpk->chain != NULL) + extra_certs = cpk->chain; + else + extra_certs = s->ctx->extra_certs; + + if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || extra_certs) + chain_store = NULL; + else if (s->cert->chain_store) + chain_store = s->cert->chain_store; + else + chain_store = s->ctx->cert_store; + + if (chain_store != NULL) { + X509_STORE_CTX *xs_ctx = X509_STORE_CTX_new(); + + if (xs_ctx == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, + ERR_R_MALLOC_FAILURE); + return 0; + } + if (!X509_STORE_CTX_init(xs_ctx, chain_store, x, NULL)) { + X509_STORE_CTX_free(xs_ctx); + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, + ERR_R_X509_LIB); + return 0; + } + /* + * It is valid for the chain not to be complete (because normally we + * don't include the root cert in the chain). Therefore we deliberately + * ignore the error return from this call. We're not actually verifying + * the cert - we're just building as much of the chain as we can + */ + (void)X509_verify_cert(xs_ctx); + /* Don't leave errors in the queue */ + ERR_clear_error(); + chain = X509_STORE_CTX_get0_chain(xs_ctx); + i = ssl_security_cert_chain(s, chain, NULL, 0); + if (i != 1) { +# if 0 + /* Dummy error calls so mkerr generates them */ + SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_EE_KEY_TOO_SMALL); + SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_CA_KEY_TOO_SMALL); + SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_CA_MD_TOO_WEAK); +# endif + X509_STORE_CTX_free(xs_ctx); + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, i); + return 0; + } + chain_count = sk_X509_num(chain); + for (i = 0; i < chain_count; i++) { + x = sk_X509_value(chain, i); + + if (!ssl_add_cert_to_wpacket_ntls(s, pkt, x, i)) { + /* SSLfatal_ntls() already called */ + X509_STORE_CTX_free(xs_ctx); + return 0; + } + + /* XXX: NTLS hook point... */ + if (i == 0) { + /* check for NTLS */ + if (!(X509_get_key_usage(x) & X509v3_KU_DIGITAL_SIGNATURE)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_SSL_ADD_CERT_CHAIN, ERR_R_X509_LIB); + X509_STORE_CTX_free(xs_ctx); + return 0; + } + x = s->cert->pkeys[SSL_PKEY_SM2_ENC].x509; + if (!ssl_add_cert_to_wpacket_ntls(s, pkt, x, i)) { + /* SSLfatal_ntls() already called */ + X509_STORE_CTX_free(xs_ctx); + return 0; + } + } + + } + X509_STORE_CTX_free(xs_ctx); + } else { + i = ssl_security_cert_chain(s, extra_certs, x, 0); + if (i != 1) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, i); + return 0; + } + if (!ssl_add_cert_to_wpacket_ntls(s, pkt, x, 0)) { + /* SSLfatal_ntls() already called */ + return 0; + } + for (i = 0; i < sk_X509_num(extra_certs); i++) { + x = sk_X509_value(extra_certs, i); + if (!ssl_add_cert_to_wpacket_ntls(s, pkt, x, i + 1)) { + /* SSLfatal_ntls() already called */ + return 0; + } + } + } + return 1; +} + +unsigned long ssl3_output_cert_chain_ntls(SSL *s, WPACKET *pkt, CERT_PKEY *cpk) +{ + if (!WPACKET_start_sub_packet_u24(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_OUTPUT_CERT_CHAIN_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!ssl_add_cert_chain(s, pkt, cpk)) + return 0; + + if (!WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_OUTPUT_CERT_CHAIN_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +/* + * Tidy up after the end of a handshake. In the case of SCTP this may result + * in NBIO events. If |clearbufs| is set then init_buf and the wbio buffer is + * freed up as well. + */ +WORK_STATE tls_finish_handshake_ntls(SSL *s, WORK_STATE wst, int clearbufs, int stop) +{ + void (*cb) (const SSL *ssl, int type, int val) = NULL; + int cleanuphand = s->statem.cleanuphand; + + if (clearbufs) { +# ifndef OPENSSL_NO_SCTP + if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { + BUF_MEM_free(s->init_buf); + s->init_buf = NULL; + } +# endif + if (!ssl_free_wbio_buffer(s)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_FINISH_HANDSHAKE_NTLS, + ERR_R_INTERNAL_ERROR); + return WORK_ERROR; + } + s->init_num = 0; + } + + /* + * Only set if there was a Finished message and this isn't after a TLSv1.3 + * post handshake exchange + */ + if (cleanuphand) { + /* skipped if we just sent a HelloRequest */ + s->renegotiate = 0; + s->new_session = 0; + s->statem.cleanuphand = 0; + s->ext.ticket_expected = 0; + + ssl3_cleanup_key_block(s); + + if (s->server) { + ssl_update_cache(s, SSL_SESS_CACHE_SERVER); + + /* N.B. s->ctx may not equal s->session_ctx */ + tsan_counter(&s->ctx->stats.sess_accept_good); + s->handshake_func = ossl_statem_accept_ntls; + } else { + ssl_update_cache(s, SSL_SESS_CACHE_CLIENT); + if (s->hit) + tsan_counter(&s->session_ctx->stats.sess_hit); + + s->handshake_func = ossl_statem_connect_ntls; + tsan_counter(&s->session_ctx->stats.sess_connect_good); + } + } + + if (s->info_callback != NULL) + cb = s->info_callback; + else if (s->ctx->info_callback != NULL) + cb = s->ctx->info_callback; + + /* The callback may expect us to not be in init at handshake done */ + ossl_statem_set_in_init_ntls(s, 0); + + if (cb != NULL) { + if (cleanuphand + || SSL_IS_FIRST_HANDSHAKE(s)) + cb(s, SSL_CB_HANDSHAKE_DONE, 1); + } + + if (!stop) { + /* If we've got more work to do we go back into init */ + ossl_statem_set_in_init_ntls(s, 1); + return WORK_FINISHED_CONTINUE; + } + + return WORK_FINISHED_STOP; +} + +int tls_get_message_header_ntls(SSL *s, int *mt) +{ + /* s->init_num < SSL3_HM_HEADER_LENGTH */ + int skip_message, i, recvd_type; + unsigned char *p; + size_t l, readbytes; + + p = (unsigned char *)s->init_buf->data; + + do { + while (s->init_num < SSL3_HM_HEADER_LENGTH) { + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type, + &p[s->init_num], + SSL3_HM_HEADER_LENGTH - s->init_num, + 0, &readbytes); + if (i <= 0) { + s->rwstate = SSL_READING; + return 0; + } + if (recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC) { + /* + * A ChangeCipherSpec must be a single byte and may not occur + * in the middle of a handshake message. + */ + if (s->init_num != 0 || readbytes != 1 || p[0] != SSL3_MT_CCS) { + SSLfatal_ntls(s, SSL_AD_UNEXPECTED_MESSAGE, + SSL_F_TLS_GET_MESSAGE_HEADER_NTLS, + SSL_R_BAD_CHANGE_CIPHER_SPEC); + return 0; + } + if (s->statem.hand_state == TLS_ST_BEFORE + && (s->s3->flags & TLS1_FLAGS_STATELESS) != 0) { + /* + * We are stateless and we received a CCS. Probably this is + * from a client between the first and second ClientHellos. + * We should ignore this, but return an error because we do + * not return success until we see the second ClientHello + * with a valid cookie. + */ + return 0; + } + s->s3->tmp.message_type = *mt = SSL3_MT_CHANGE_CIPHER_SPEC; + s->init_num = readbytes - 1; + s->init_msg = s->init_buf->data; + s->s3->tmp.message_size = readbytes; + return 1; + } else if (recvd_type != SSL3_RT_HANDSHAKE) { + SSLfatal_ntls(s, SSL_AD_UNEXPECTED_MESSAGE, + SSL_F_TLS_GET_MESSAGE_HEADER_NTLS, + SSL_R_CCS_RECEIVED_EARLY); + return 0; + } + s->init_num += readbytes; + } + + skip_message = 0; + if (!s->server) + if (s->statem.hand_state != TLS_ST_OK + && p[0] == SSL3_MT_HELLO_REQUEST) + /* + * The server may always send 'Hello Request' messages -- + * we are doing a handshake anyway now, so ignore them if + * their format is correct. Does not count for 'Finished' + * MAC. + */ + if (p[1] == 0 && p[2] == 0 && p[3] == 0) { + s->init_num = 0; + skip_message = 1; + + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, + p, SSL3_HM_HEADER_LENGTH, s, + s->msg_callback_arg); + } + } while (skip_message); + /* s->init_num == SSL3_HM_HEADER_LENGTH */ + + *mt = *p; + s->s3->tmp.message_type = *(p++); + + if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) { + /* + * Only happens with SSLv3+ in an SSLv2 backward compatible + * ClientHello + * + * Total message size is the remaining record bytes to read + * plus the SSL3_HM_HEADER_LENGTH bytes that we already read + */ + l = RECORD_LAYER_get_rrec_length(&s->rlayer) + + SSL3_HM_HEADER_LENGTH; + s->s3->tmp.message_size = l; + + s->init_msg = s->init_buf->data; + s->init_num = SSL3_HM_HEADER_LENGTH; + } else { + n2l3(p, l); + /* BUF_MEM_grow takes an 'int' parameter */ + if (l > (INT_MAX - SSL3_HM_HEADER_LENGTH)) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_GET_MESSAGE_HEADER_NTLS, + SSL_R_EXCESSIVE_MESSAGE_SIZE); + return 0; + } + s->s3->tmp.message_size = l; + + s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH; + s->init_num = 0; + } + + return 1; +} + +int tls_get_message_body_ntls(SSL *s, size_t *len) +{ + size_t n, readbytes; + unsigned char *p; + int i; + + if (s->s3->tmp.message_type == SSL3_MT_CHANGE_CIPHER_SPEC) { + /* We've already read everything in */ + *len = (unsigned long)s->init_num; + return 1; + } + + p = s->init_msg; + n = s->s3->tmp.message_size - s->init_num; + while (n > 0) { + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL, + &p[s->init_num], n, 0, &readbytes); + if (i <= 0) { + s->rwstate = SSL_READING; + *len = 0; + return 0; + } + s->init_num += readbytes; + n -= readbytes; + } + + /* + * If receiving Finished, record MAC of prior handshake messages for + * Finished verification. + */ + if (*(s->init_buf->data) == SSL3_MT_FINISHED && !ssl3_take_mac_ntls(s)) { + /* SSLfatal_ntls() already called */ + *len = 0; + return 0; + } + + /* Feed this message into MAC computation. */ + if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) { + if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, + s->init_num)) { + /* SSLfatal_ntls() already called */ + *len = 0; + return 0; + } + if (s->msg_callback) + s->msg_callback(0, SSL2_VERSION, 0, s->init_buf->data, + (size_t)s->init_num, s, s->msg_callback_arg); + } else { + /* + * We defer feeding in the HRR until later. We'll do it as part of + * processing the message + * The TLsv1.3 handshake transcript stops at the ClientFinished + * message. + */ +# define SERVER_HELLO_RANDOM_OFFSET (SSL3_HM_HEADER_LENGTH + 2) + /* KeyUpdate and NewSessionTicket do not need to be added */ + if ((s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET + && s->s3->tmp.message_type != SSL3_MT_KEY_UPDATE)) { + if (s->s3->tmp.message_type != SSL3_MT_SERVER_HELLO + || s->init_num < SERVER_HELLO_RANDOM_OFFSET + SSL3_RANDOM_SIZE + || memcmp(hrrrandom_ntls, + s->init_buf->data + SERVER_HELLO_RANDOM_OFFSET, + SSL3_RANDOM_SIZE) != 0) { + if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, + s->init_num + SSL3_HM_HEADER_LENGTH)) { + /* SSLfatal_ntls() already called */ + *len = 0; + return 0; + } + } + } + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, + (size_t)s->init_num + SSL3_HM_HEADER_LENGTH, s, + s->msg_callback_arg); + } + + *len = s->init_num; + return 1; +} + +static const X509ERR2ALERT x509table[] = { + {X509_V_ERR_APPLICATION_VERIFICATION, SSL_AD_HANDSHAKE_FAILURE}, + {X509_V_ERR_CA_KEY_TOO_SMALL, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_CA_MD_TOO_WEAK, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_CERT_CHAIN_TOO_LONG, SSL_AD_UNKNOWN_CA}, + {X509_V_ERR_CERT_HAS_EXPIRED, SSL_AD_CERTIFICATE_EXPIRED}, + {X509_V_ERR_CERT_NOT_YET_VALID, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_CERT_REJECTED, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_CERT_REVOKED, SSL_AD_CERTIFICATE_REVOKED}, + {X509_V_ERR_CERT_SIGNATURE_FAILURE, SSL_AD_DECRYPT_ERROR}, + {X509_V_ERR_CERT_UNTRUSTED, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_CRL_HAS_EXPIRED, SSL_AD_CERTIFICATE_EXPIRED}, + {X509_V_ERR_CRL_NOT_YET_VALID, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_CRL_SIGNATURE_FAILURE, SSL_AD_DECRYPT_ERROR}, + {X509_V_ERR_DANE_NO_MATCH, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT, SSL_AD_UNKNOWN_CA}, + {X509_V_ERR_EE_KEY_TOO_SMALL, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_EMAIL_MISMATCH, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_HOSTNAME_MISMATCH, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_INVALID_CA, SSL_AD_UNKNOWN_CA}, + {X509_V_ERR_INVALID_CALL, SSL_AD_INTERNAL_ERROR}, + {X509_V_ERR_INVALID_PURPOSE, SSL_AD_UNSUPPORTED_CERTIFICATE}, + {X509_V_ERR_IP_ADDRESS_MISMATCH, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_OUT_OF_MEM, SSL_AD_INTERNAL_ERROR}, + {X509_V_ERR_PATH_LENGTH_EXCEEDED, SSL_AD_UNKNOWN_CA}, + {X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN, SSL_AD_UNKNOWN_CA}, + {X509_V_ERR_STORE_LOOKUP, SSL_AD_INTERNAL_ERROR}, + {X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_UNABLE_TO_GET_CRL, SSL_AD_UNKNOWN_CA}, + {X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER, SSL_AD_UNKNOWN_CA}, + {X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT, SSL_AD_UNKNOWN_CA}, + {X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, SSL_AD_UNKNOWN_CA}, + {X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, SSL_AD_UNKNOWN_CA}, + {X509_V_ERR_UNSPECIFIED, SSL_AD_INTERNAL_ERROR}, + + /* Last entry; return this if we don't find the value above. */ + {X509_V_OK, SSL_AD_CERTIFICATE_UNKNOWN} +}; + +int ssl_x509err2alert_ntls(int x509err) +{ + const X509ERR2ALERT *tp; + + for (tp = x509table; tp->x509err != X509_V_OK; ++tp) + if (tp->x509err == x509err) + break; + return tp->alert; +} + +int ssl_allow_compression_ntls(SSL *s) +{ + if (s->options & SSL_OP_NO_COMPRESSION) + return 0; + return ssl_security(s, SSL_SECOP_COMPRESSION, 0, 0, NULL); +} + +static int version_cmp(const SSL *s, int a, int b) +{ + if (a == b) + return 0; + else + return a < b ? -1 : 1; +} + +typedef struct { + int version; + const SSL_METHOD *(*cmeth) (void); + const SSL_METHOD *(*smeth) (void); +} version_info; + +# if TLS_MAX_VERSION != TLS1_3_VERSION +# error Code needs update for TLS_method() support beyond TLS1_3_VERSION. +# endif + +/* Must be in order high to low */ +static const version_info tls_version_table[] = { +# ifndef OPENSSL_NO_TLS1_3 + {TLS1_3_VERSION, tlsv1_3_client_method, tlsv1_3_server_method}, +# else + {TLS1_3_VERSION, NULL, NULL}, +# endif +# ifndef OPENSSL_NO_TLS1_2 + {TLS1_2_VERSION, tlsv1_2_client_method, tlsv1_2_server_method}, +# else + {TLS1_2_VERSION, NULL, NULL}, +# endif +# ifndef OPENSSL_NO_TLS1_1 + {TLS1_1_VERSION, tlsv1_1_client_method, tlsv1_1_server_method}, +# else + {TLS1_1_VERSION, NULL, NULL}, +# endif +# ifndef OPENSSL_NO_TLS1 + {TLS1_VERSION, tlsv1_client_method, tlsv1_server_method}, +# else + {TLS1_VERSION, NULL, NULL}, +# endif + /* + * NTLS is not a standard version, so we don't set + * {NTLS_VERSION, NULL, NULL}, + */ + {NTLS_VERSION, ntls_client_method, ntls_server_method}, +# ifndef OPENSSL_NO_SSL3 + {SSL3_VERSION, sslv3_client_method, sslv3_server_method}, +# else + {SSL3_VERSION, NULL, NULL}, +# endif + {0, NULL, NULL}, +}; + + + + + +/* + * ssl_method_error - Check whether an SSL_METHOD is enabled. + * + * @s: The SSL handle for the candidate method + * @method: the intended method. + * + * Returns 0 on success, or an SSL error reason on failure. + */ +static int ssl_method_error(const SSL *s, const SSL_METHOD *method) +{ + int version = method->version; + + if ((s->min_proto_version != 0 && + version_cmp(s, version, s->min_proto_version) < 0) || + ssl_security(s, SSL_SECOP_VERSION, 0, version, NULL) == 0) + return SSL_R_VERSION_TOO_LOW; + + if (s->max_proto_version != 0 && + version_cmp(s, version, s->max_proto_version) > 0) + return SSL_R_VERSION_TOO_HIGH; + + if ((s->options & method->mask) != 0) + return SSL_R_UNSUPPORTED_PROTOCOL; + if ((method->flags & SSL_METHOD_NO_SUITEB) != 0 && tls1_suiteb(s)) + return SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE; + + return 0; +} + +/* + * ssl_version_supported_ntls - Check that the specified `version` is supported by + * `SSL *` instance + * + * @s: The SSL handle for the candidate method + * @version: Protocol version to test against + * + * Returns 1 when supported, otherwise 0 + */ +int ssl_version_supported_ntls(const SSL *s, int version, const SSL_METHOD **meth) +{ + const version_info *vent; + const version_info *table; + + switch (s->method->version) { + default: + /* Version should match method version for non-ANY method */ + return version_cmp(s, version, s->version) == 0; + case TLS_ANY_VERSION: + table = tls_version_table; + break; + } + + for (vent = table; + vent->version != 0 && version_cmp(s, version, vent->version) <= 0; + ++vent) { + if (vent->cmeth != NULL + && version_cmp(s, version, vent->version) == 0 + && ssl_method_error(s, vent->cmeth()) == 0 + && (!s->server + || version != TLS1_3_VERSION)) { + if (meth != NULL) + *meth = vent->cmeth(); + return 1; + } + } + return 0; +} + +/* + * ssl_check_version_downgrade_ntls - In response to RFC7507 SCSV version + * fallback indication from a client check whether we're using the highest + * supported protocol version. + * + * @s server SSL handle. + * + * Returns 1 when using the highest enabled version, 0 otherwise. + */ +int ssl_check_version_downgrade_ntls(SSL *s) +{ + const version_info *vent; + const version_info *table; + + /* + * Check that the current protocol is the highest enabled version + * (according to s->ctx->method, as version negotiation may have changed + * s->method). + */ + if (s->version == s->ctx->method->version) + return 1; + + /* + * Apparently we're using a version-flexible SSL_METHOD (not at its + * highest protocol version). + */ + if (s->ctx->method->version == TLS_method()->version) + table = tls_version_table; + else { + /* Unexpected state; fail closed. */ + return 0; + } + + for (vent = table; vent->version != 0; ++vent) { + if (vent->smeth != NULL && ssl_method_error(s, vent->smeth()) == 0) + return s->version == vent->version; + } + return 0; +} + +/* + * ssl_set_version_bound_ntls - set an upper or lower bound on the supported (D)TLS + * protocols, provided the initial (D)TLS method is version-flexible. This + * function sanity-checks the proposed value and makes sure the method is + * version-flexible, then sets the limit if all is well. + * + * @method_version: The version of the current SSL_METHOD. + * @version: the intended limit. + * @bound: pointer to limit to be updated. + * + * Returns 1 on success, 0 on failure. + */ +int ssl_set_version_bound_ntls(int method_version, int version, int *bound) +{ + if (version == 0) { + *bound = version; + return 1; + } + + /*- + * Restrict TLS methods to TLS protocol versions. + * + * Note that for both lower-bounds we use explicit versions, not + * (D)TLS_MIN_VERSION. This is because we don't want to break user + * configurations. If the MIN (supported) version ever rises, the user's + * "floor" remains valid even if no longer available. We don't expect the + * MAX ceiling to ever get lower, so making that variable makes sense. + */ + switch (method_version) { + default: + /* + * XXX For fixed version methods, should we always fail and not set any + * bounds, always succeed and not set any bounds, or set the bounds and + * arrange to fail later if they are not met? At present fixed-version + * methods are not subject to controls that disable individual protocol + * versions. + */ + if (version == NTLS_VERSION) + return 1; + return 0; + + case TLS_ANY_VERSION: + if ((version < SSL3_VERSION || version > TLS_MAX_VERSION) + && (version != NTLS_VERSION && version != MIN_VERSION_WITH_NTLS)) + return 0; + break; + } + + *bound = version; + return 1; +} + +static void check_for_downgrade(SSL *s, int vers, DOWNGRADE *dgrd) +{ + if (vers == TLS1_2_VERSION + && ssl_version_supported_ntls(s, TLS1_3_VERSION, NULL)) { + *dgrd = DOWNGRADE_TO_1_2; + } else if (vers < TLS1_2_VERSION + /* + * We need to ensure that a server that disables TLSv1.2 + * (creating a hole between TLSv1.3 and TLSv1.1) can still + * complete handshakes with clients that support TLSv1.2 and + * below. Therefore we do not enable the sentinel if TLSv1.3 is + * enabled and TLSv1.2 is not. + */ + && ssl_version_supported_ntls(s, TLS1_2_VERSION, NULL)) { + *dgrd = DOWNGRADE_TO_1_1; + } else { + *dgrd = DOWNGRADE_NONE; + } +} + +/* + * ssl_choose_server_version_ntls - Choose server (D)TLS version. Called when the + * client HELLO is received to select the final server protocol version and + * the version specific method. + * + * @s: server SSL handle. + * + * Returns 0 on success or an SSL error reason number on failure. + */ +int ssl_choose_server_version_ntls(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd) +{ + /*- + * With version-flexible methods we have an initial state with: + * + * s->method->version == (D)TLS_ANY_VERSION, + * s->version == (D)TLS_MAX_VERSION. + * + * So we detect version-flexible methods via the method version, not the + * handle version. + */ + int server_version = s->method->version; + int client_version = hello->legacy_version; + const version_info *vent; + const version_info *table; + int disabled = 0; + RAW_EXTENSION *suppversions; + + s->client_version = client_version; + + switch (server_version) { + default: + if (version_cmp(s, client_version, s->version) < 0) + return SSL_R_WRONG_SSL_VERSION; + *dgrd = DOWNGRADE_NONE; + /* + * If this SSL handle is not from a version flexible method we don't + * (and never did) check min/max FIPS or Suite B constraints. Hope + * that's OK. It is up to the caller to not choose fixed protocol + * versions they don't want. If not, then easy to fix, just return + * ssl_method_error(s, s->method) + */ + return 0; + /* + * Fall through if we are TLSv1.3 already (this means we must be after + * a HelloRetryRequest + */ + /* fall thru */ + case TLS_ANY_VERSION: + table = tls_version_table; + break; + } + + suppversions = &hello->pre_proc_exts[TLSEXT_IDX_supported_versions]; + + /* If we did an HRR then supported versions is mandatory */ + if (!suppversions->present && s->hello_retry_request != SSL_HRR_NONE) + return SSL_R_UNSUPPORTED_PROTOCOL; + + if (suppversions->present) { + unsigned int candidate_vers = 0; + unsigned int best_vers = 0; + const SSL_METHOD *best_method = NULL; + PACKET versionslist; + + suppversions->parsed = 1; + + if (!PACKET_as_length_prefixed_1(&suppversions->data, &versionslist)) { + /* Trailing or invalid data? */ + return SSL_R_LENGTH_MISMATCH; + } + + /* + * The TLSv1.3 spec says the client MUST set this to TLS1_2_VERSION. + * The spec only requires servers to check that it isn't SSLv3: + * "Any endpoint receiving a Hello message with + * ClientHello.legacy_version or ServerHello.legacy_version set to + * 0x0300 MUST abort the handshake with a "protocol_version" alert." + * We are slightly stricter and require that it isn't SSLv3 or lower. + * We tolerate TLSv1 and TLSv1.1. + */ + if (client_version <= SSL3_VERSION) + return SSL_R_BAD_LEGACY_VERSION; + + while (PACKET_get_net_2(&versionslist, &candidate_vers)) { + if (version_cmp(s, candidate_vers, best_vers) <= 0) + continue; + if (ssl_version_supported_ntls(s, candidate_vers, &best_method)) + best_vers = candidate_vers; + } + if (PACKET_remaining(&versionslist) != 0) { + /* Trailing data? */ + return SSL_R_LENGTH_MISMATCH; + } + + if (best_vers > 0) { + if (s->hello_retry_request != SSL_HRR_NONE) { + /* + * This is after a HelloRetryRequest so we better check that we + * negotiated TLSv1.3 + */ + if (best_vers != TLS1_3_VERSION) + return SSL_R_UNSUPPORTED_PROTOCOL; + return 0; + } + check_for_downgrade(s, best_vers, dgrd); + s->version = best_vers; + s->method = best_method; + return 0; + } + return SSL_R_UNSUPPORTED_PROTOCOL; + } + + /* + * If the supported versions extension isn't present, then the highest + * version we can negotiate is TLSv1.2 + */ + if (version_cmp(s, client_version, TLS1_3_VERSION) >= 0) + client_version = TLS1_2_VERSION; + + /* + * No supported versions extension, so we just use the version supplied in + * the ClientHello. + */ + for (vent = table; vent->version != 0; ++vent) { + const SSL_METHOD *method; + + if (vent->smeth == NULL || + version_cmp(s, client_version, vent->version) < 0) + continue; + method = vent->smeth(); + if (ssl_method_error(s, method) == 0) { + check_for_downgrade(s, vent->version, dgrd); + s->version = vent->version; + s->method = method; + return 0; + } + disabled = 1; + } + return disabled ? SSL_R_UNSUPPORTED_PROTOCOL : SSL_R_VERSION_TOO_LOW; +} + +/* + * ssl_choose_client_version_ntls - Choose client (D)TLS version. Called when the + * server HELLO is received to select the final client protocol version and + * the version specific method. + * + * @s: client SSL handle. + * @version: The proposed version from the server's HELLO. + * @extensions: The extensions received + * + * Returns 1 on success or 0 on error. + */ +int ssl_choose_client_version_ntls(SSL *s, int version, RAW_EXTENSION *extensions) +{ + const version_info *vent; + const version_info *table; + int ret, ver_min, ver_max, real_max, origv; + + origv = s->version; + s->version = version; + + /* This will overwrite s->version if the extension is present */ + if (!tls_parse_extension_ntls(s, TLSEXT_IDX_supported_versions, + SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_SERVER_HELLO, extensions, + NULL, 0)) { + s->version = origv; + return 0; + } + + if (s->hello_retry_request != SSL_HRR_NONE + && s->version != TLS1_3_VERSION) { + s->version = origv; + SSLfatal_ntls(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION_NTLS, + SSL_R_WRONG_SSL_VERSION); + return 0; + } + + switch (s->method->version) { + default: + if (s->version != s->method->version) { + s->version = origv; + SSLfatal_ntls(s, SSL_AD_PROTOCOL_VERSION, + SSL_F_SSL_CHOOSE_CLIENT_VERSION_NTLS, + SSL_R_WRONG_SSL_VERSION); + return 0; + } + /* + * If this SSL handle is not from a version flexible method we don't + * (and never did) check min/max, FIPS or Suite B constraints. Hope + * that's OK. It is up to the caller to not choose fixed protocol + * versions they don't want. If not, then easy to fix, just return + * ssl_method_error(s, s->method) + */ + return 1; + case TLS_ANY_VERSION: + table = tls_version_table; + break; + } + + ret = ssl_get_min_max_version_ntls(s, &ver_min, &ver_max, &real_max); + if (ret != 0) { + s->version = origv; + SSLfatal_ntls(s, SSL_AD_PROTOCOL_VERSION, + SSL_F_SSL_CHOOSE_CLIENT_VERSION_NTLS, ret); + return 0; + } + if (s->version < ver_min) { + s->version = origv; + SSLfatal_ntls(s, SSL_AD_PROTOCOL_VERSION, + SSL_F_SSL_CHOOSE_CLIENT_VERSION_NTLS, SSL_R_UNSUPPORTED_PROTOCOL); + return 0; + } else if (s->version > ver_max) { + s->version = origv; + SSLfatal_ntls(s, SSL_AD_PROTOCOL_VERSION, + SSL_F_SSL_CHOOSE_CLIENT_VERSION_NTLS, SSL_R_UNSUPPORTED_PROTOCOL); + return 0; + } + + if ((s->mode & SSL_MODE_SEND_FALLBACK_SCSV) == 0) + real_max = ver_max; + + /* Check for downgrades */ + if (s->version == TLS1_2_VERSION && real_max > s->version) { + if (memcmp(tls12downgrade, + s->s3->server_random + SSL3_RANDOM_SIZE + - sizeof(tls12downgrade), + sizeof(tls12downgrade)) == 0) { + s->version = origv; + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_SSL_CHOOSE_CLIENT_VERSION_NTLS, + SSL_R_INAPPROPRIATE_FALLBACK); + return 0; + } + } else if (s->version < TLS1_2_VERSION + && real_max > s->version) { + if (memcmp(tls11downgrade, + s->s3->server_random + SSL3_RANDOM_SIZE + - sizeof(tls11downgrade), + sizeof(tls11downgrade)) == 0) { + s->version = origv; + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_SSL_CHOOSE_CLIENT_VERSION_NTLS, + SSL_R_INAPPROPRIATE_FALLBACK); + return 0; + } + } + + for (vent = table; vent->version != 0; ++vent) { + if (vent->cmeth == NULL || s->version != vent->version) + continue; + + s->method = vent->cmeth(); + return 1; + } + + s->version = origv; + SSLfatal_ntls(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION_NTLS, + SSL_R_UNSUPPORTED_PROTOCOL); + return 0; +} + +/* + * ssl_get_min_max_version_ntls - get minimum and maximum protocol version + * @s: The SSL connection + * @min_version: The minimum supported version + * @max_version: The maximum supported version + * @real_max: The highest version below the lowest compile time version hole + * where that hole lies above at least one run-time enabled + * protocol. + * + * Work out what version we should be using for the initial ClientHello if the + * version is initially (D)TLS_ANY_VERSION. We apply any explicit SSL_OP_NO_xxx + * options, the MinProtocol and MaxProtocol configuration commands, any Suite B + * constraints and any floor imposed by the security level here, + * so we don't advertise the wrong protocol version to only reject the outcome later. + * + * Computing the right floor matters. If, e.g., TLS 1.0 and 1.2 are enabled, + * TLS 1.1 is disabled, but the security level, Suite-B and/or MinProtocol + * only allow TLS 1.2, we want to advertise TLS1.2, *not* TLS1. + * + * Returns 0 on success or an SSL error reason number on failure. On failure + * min_version and max_version will also be set to 0. + */ +int ssl_get_min_max_version_ntls(const SSL *s, int *min_version, int *max_version, + int *real_max) +{ + int version, tmp_real_max; + int hole; + const SSL_METHOD *single = NULL; + const SSL_METHOD *method; + const version_info *table; + const version_info *vent; + + switch (s->method->version) { + default: + /* + * If this SSL handle is not from a version flexible method we don't + * (and never did) check min/max FIPS or Suite B constraints. Hope + * that's OK. It is up to the caller to not choose fixed protocol + * versions they don't want. If not, then easy to fix, just return + * ssl_method_error(s, s->method) + */ + *min_version = *max_version = s->version; + /* + * Providing a real_max only makes sense where we're using a version + * flexible method. + */ + if (!ossl_assert(real_max == NULL)) + return ERR_R_INTERNAL_ERROR; + return 0; + case TLS_ANY_VERSION: + table = tls_version_table; + break; + } + + /* + * SSL_OP_NO_X disables all protocols above X *if* there are some protocols + * below X enabled. This is required in order to maintain the "version + * capability" vector contiguous. Any versions with a NULL client method + * (protocol version client is disabled at compile-time) is also a "hole". + * + * Our initial state is hole == 1, version == 0. That is, versions above + * the first version in the method table are disabled (a "hole" above + * the valid protocol entries) and we don't have a selected version yet. + * + * Whenever "hole == 1", and we hit an enabled method, its version becomes + * the selected version, and the method becomes a candidate "single" + * method. We're no longer in a hole, so "hole" becomes 0. + * + * If "hole == 0" and we hit an enabled method, then "single" is cleared, + * as we support a contiguous range of at least two methods. If we hit + * a disabled method, then hole becomes true again, but nothing else + * changes yet, because all the remaining methods may be disabled too. + * If we again hit an enabled method after the new hole, it becomes + * selected, as we start from scratch. + */ + *min_version = version = 0; + hole = 1; + if (real_max != NULL) + *real_max = 0; + tmp_real_max = 0; + for (vent = table; vent->version != 0; ++vent) { + /* + * A table entry with a NULL client method is still a hole in the + * "version capability" vector. + */ + if (vent->cmeth == NULL) { + hole = 1; + tmp_real_max = 0; + continue; + } + method = vent->cmeth(); + + if (hole == 1 && tmp_real_max == 0) + tmp_real_max = vent->version; + + if (ssl_method_error(s, method) != 0) { + hole = 1; + } else if (!hole) { + single = NULL; + *min_version = method->version; + } else { + if (real_max != NULL && tmp_real_max != 0) + *real_max = tmp_real_max; + version = (single = method)->version; + *min_version = version; + hole = 0; + } + } + + *max_version = version; + + /* Fail if everything is disabled */ + if (version == 0) + return SSL_R_NO_PROTOCOLS_AVAILABLE; + + return 0; +} + +/* + * ssl_set_client_hello_version_ntls - Work out what version we should be using for + * the initial ClientHello.legacy_version field. + * + * @s: client SSL handle. + * + * Returns 0 on success or an SSL error reason number on failure. + */ +int ssl_set_client_hello_version_ntls(SSL *s) +{ + int ver_min, ver_max, ret; + + /* + * In a renegotiation we always send the same client_version that we sent + * last time, regardless of which version we eventually negotiated. + */ + if (!SSL_IS_FIRST_HANDSHAKE(s)) + return 0; + + ret = ssl_get_min_max_version_ntls(s, &ver_min, &ver_max, NULL); + + if (ret != 0) + return ret; + + s->version = ver_max; + + /* TLS1.3 always uses TLS1.2 in the legacy_version field */ + if (ver_max > TLS1_2_VERSION) + ver_max = TLS1_2_VERSION; + + s->client_version = ver_max; + return 0; +} + +/* + * Checks a list of |groups| to determine if the |group_id| is in it. If it is + * and |checkallow| is 1 then additionally check if the group is allowed to be + * used. Returns 1 if the group is in the list (and allowed if |checkallow| is + * 1) or 0 otherwise. + */ +# ifndef OPENSSL_NO_EC +int check_in_list_ntls(SSL *s, uint16_t group_id, const uint16_t *groups, + size_t num_groups, int checkallow) +{ + size_t i; + + if (groups == NULL || num_groups == 0) + return 0; + + for (i = 0; i < num_groups; i++) { + uint16_t group = groups[i]; + + if (group_id == group + && (!checkallow + || tls_curve_allowed(s, group, SSL_SECOP_CURVE_CHECK))) { + return 1; + } + } + + return 0; +} +# endif + +/* Replace ClientHello1 in the transcript hash with a synthetic message */ +int create_synthetic_message_hash_ntls(SSL *s, const unsigned char *hashval, + size_t hashlen, const unsigned char *hrr, + size_t hrrlen) +{ + unsigned char hashvaltmp[EVP_MAX_MD_SIZE]; + unsigned char msghdr[SSL3_HM_HEADER_LENGTH]; + + memset(msghdr, 0, sizeof(msghdr)); + + if (hashval == NULL) { + hashval = hashvaltmp; + hashlen = 0; + /* Get the hash of the initial ClientHello */ + if (!ssl3_digest_cached_records(s, 0) + || !ssl_handshake_hash(s, hashvaltmp, sizeof(hashvaltmp), + &hashlen)) { + /* SSLfatal_ntls() already called */ + return 0; + } + } + + /* Reinitialise the transcript hash */ + if (!ssl3_init_finished_mac(s)) { + /* SSLfatal_ntls() already called */ + return 0; + } + + /* Inject the synthetic message_hash message */ + msghdr[0] = SSL3_MT_MESSAGE_HASH; + msghdr[SSL3_HM_HEADER_LENGTH - 1] = (unsigned char)hashlen; + if (!ssl3_finish_mac(s, msghdr, SSL3_HM_HEADER_LENGTH) + || !ssl3_finish_mac(s, hashval, hashlen)) { + /* SSLfatal_ntls() already called */ + return 0; + } + + /* + * Now re-inject the HRR and current message if appropriate (we just deleted + * it when we reinitialised the transcript hash above). Only necessary after + * receiving a ClientHello2 with a cookie. + */ + if (hrr != NULL + && (!ssl3_finish_mac(s, hrr, hrrlen) + || !ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, + s->s3->tmp.message_size + + SSL3_HM_HEADER_LENGTH))) { + /* SSLfatal_ntls() already called */ + return 0; + } + + return 1; +} + +static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b) +{ + return X509_NAME_cmp(*a, *b); +} + +int parse_ca_names_ntls(SSL *s, PACKET *pkt) +{ + STACK_OF(X509_NAME) *ca_sk = sk_X509_NAME_new(ca_dn_cmp); + X509_NAME *xn = NULL; + PACKET cadns; + + if (ca_sk == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_PARSE_CA_NAMES_NTLS, + ERR_R_MALLOC_FAILURE); + goto err; + } + /* get the CA RDNs */ + if (!PACKET_get_length_prefixed_2(pkt, &cadns)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR,SSL_F_PARSE_CA_NAMES_NTLS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + while (PACKET_remaining(&cadns)) { + const unsigned char *namestart, *namebytes; + unsigned int name_len; + + if (!PACKET_get_net_2(&cadns, &name_len) + || !PACKET_get_bytes(&cadns, &namebytes, name_len)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES_NTLS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + namestart = namebytes; + if ((xn = d2i_X509_NAME(NULL, &namebytes, name_len)) == NULL) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES_NTLS, + ERR_R_ASN1_LIB); + goto err; + } + if (namebytes != (namestart + name_len)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES_NTLS, + SSL_R_CA_DN_LENGTH_MISMATCH); + goto err; + } + + if (!sk_X509_NAME_push(ca_sk, xn)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_PARSE_CA_NAMES_NTLS, + ERR_R_MALLOC_FAILURE); + goto err; + } + xn = NULL; + } + + sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free); + s->s3->tmp.peer_ca_names = ca_sk; + + return 1; + + err: + sk_X509_NAME_pop_free(ca_sk, X509_NAME_free); + X509_NAME_free(xn); + return 0; +} + +const STACK_OF(X509_NAME) *get_ca_names_ntls(SSL *s) +{ + const STACK_OF(X509_NAME) *ca_sk = NULL;; + + if (s->server) { + ca_sk = SSL_get_client_CA_list(s); + if (ca_sk != NULL && sk_X509_NAME_num(ca_sk) == 0) + ca_sk = NULL; + } + + if (ca_sk == NULL) + ca_sk = SSL_get0_CA_list(s); + + return ca_sk; +} + +int construct_ca_names_ntls(SSL *s, const STACK_OF(X509_NAME) *ca_sk, WPACKET *pkt) +{ + /* Start sub-packet for client CA list */ + if (!WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (ca_sk != NULL) { + int i; + + for (i = 0; i < sk_X509_NAME_num(ca_sk); i++) { + unsigned char *namebytes; + X509_NAME *name = sk_X509_NAME_value(ca_sk, i); + int namelen; + + if (name == NULL + || (namelen = i2d_X509_NAME(name, NULL)) < 0 + || !WPACKET_sub_allocate_bytes_u16(pkt, namelen, + &namebytes) + || i2d_X509_NAME(name, &namebytes) != namelen) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + } + + if (!WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +/* Create a buffer containing data to be signed for server key exchange */ +size_t construct_key_exchange_tbs_ntls(SSL *s, unsigned char **ptbs, + const void *param, size_t paramlen) +{ + size_t tbslen = 2 * SSL3_RANDOM_SIZE + paramlen; + unsigned char *tbs = OPENSSL_malloc(tbslen); + + if (tbs == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS_NTLS, + ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(tbs, s->s3->client_random, SSL3_RANDOM_SIZE); + memcpy(tbs + SSL3_RANDOM_SIZE, s->s3->server_random, SSL3_RANDOM_SIZE); + + memcpy(tbs + SSL3_RANDOM_SIZE * 2, param, paramlen); + + *ptbs = tbs; + return tbslen; +} + +/* + * Saves the current handshake digest for Post-Handshake Auth, + * Done after ClientFinished is processed, done exactly once + */ +int tls13_save_handshake_digest_for_pha_ntls(SSL *s) +{ + if (s->pha_dgst == NULL) { + if (!ssl3_digest_cached_records(s, 1)) + /* SSLfatal_ntls() already called */ + return 0; + + s->pha_dgst = EVP_MD_CTX_new(); + if (s->pha_dgst == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + if (!EVP_MD_CTX_copy_ex(s->pha_dgst, + s->s3->handshake_dgst)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + return 1; +} + +/* + * Restores the Post-Handshake Auth handshake digest + * Done just before sending/processing the Cert Request + */ +int tls13_restore_handshake_digest_for_pha_ntls(SSL *s) +{ + if (s->pha_dgst == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + if (!EVP_MD_CTX_copy_ex(s->s3->handshake_dgst, + s->pha_dgst)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + return 1; +} +#endif diff --git a/ssl/statem_ntls/statem_local_ntls.h b/ssl/statem_ntls/statem_local_ntls.h new file mode 100644 index 000000000..7b2e7b43c --- /dev/null +++ b/ssl/statem_ntls/statem_local_ntls.h @@ -0,0 +1,479 @@ +/* + * Copyright 2019 The BabaSSL Project Authors. All Rights Reserved. + */ + +/***************************************************************************** + * * + * The following definitions are PRIVATE to the state machine. They should * + * NOT be used outside of the state machine. * + * * + *****************************************************************************/ + +/* Max message length definitions */ + +/* The spec allows for a longer length than this, but we limit it */ +#define HELLO_VERIFY_REQUEST_MAX_LENGTH 258 +#define END_OF_EARLY_DATA_MAX_LENGTH 0 +#define SERVER_HELLO_MAX_LENGTH 20000 +#define HELLO_RETRY_REQUEST_MAX_LENGTH 20000 +#define ENCRYPTED_EXTENSIONS_MAX_LENGTH 20000 +#define SERVER_KEY_EXCH_MAX_LENGTH 102400 +#define SERVER_HELLO_DONE_MAX_LENGTH 0 +#define KEY_UPDATE_MAX_LENGTH 1 +#define CCS_MAX_LENGTH 1 +/* Max should actually be 36 but we are generous */ +#define FINISHED_MAX_LENGTH 64 + +/* Dummy message type */ +#define SSL3_MT_DUMMY -1 + +#ifndef OPENSSL_NO_SM2 +/* + *standard handshake sm2-id and cert verify id is defined + * in IETF draft-yang-tls-tls13-sm-suites-01 + */ +# define HANDSHAKE_SM2_ID "TLSv1.3+GM+Cipher+Suite" +# define HANDSHAKE_SM2_ID_LEN sizeof(HANDSHAKE_SM2_ID) - 1 +# define CERTVRIFY_SM2_ID "1234567812345678" +# define CERTVRIFY_SM2_ID_LEN sizeof(CERTVRIFY_SM2_ID) - 1 + +#endif + +extern const unsigned char hrrrandom_ntls[]; + +/* Message processing return codes */ +typedef enum { + /* Something bad happened */ + MSG_PROCESS_ERROR, + /* We've finished reading - swap to writing */ + MSG_PROCESS_FINISHED_READING, + /* + * We've completed the main processing of this message but there is some + * post processing to be done. + */ + MSG_PROCESS_CONTINUE_PROCESSING, + /* We've finished this message - read the next message */ + MSG_PROCESS_CONTINUE_READING +} MSG_PROCESS_RETURN; + +typedef int (*confunc_f) (SSL *s, WPACKET *pkt); + +int ssl3_take_mac_ntls(SSL *s); +int check_in_list_ntls(SSL *s, uint16_t group_id, const uint16_t *groups, + size_t num_groups, int checkallow); +int create_synthetic_message_hash_ntls(SSL *s, const unsigned char *hashval, + size_t hashlen, const unsigned char *hrr, + size_t hrrlen); +int parse_ca_names_ntls(SSL *s, PACKET *pkt); +const STACK_OF(X509_NAME) *get_ca_names_ntls(SSL *s); +int construct_ca_names_ntls(SSL *s, const STACK_OF(X509_NAME) *ca_sk, WPACKET *pkt); +size_t construct_key_exchange_tbs_ntls(SSL *s, unsigned char **ptbs, + const void *param, size_t paramlen); +int ssl_add_cert_to_wpacket_ntls(SSL *s, WPACKET *pkt, X509 *x, int chain); + +/* + * TLS/DTLS client state machine functions + */ +int ossl_statem_client_read_transition_ntls(SSL *s, int mt); +WRITE_TRAN ossl_statem_client_write_transition_ntls(SSL *s); +WORK_STATE ossl_statem_client_pre_work_ntls(SSL *s, WORK_STATE wst); +WORK_STATE ossl_statem_client_post_work_ntls(SSL *s, WORK_STATE wst); +int ossl_statem_client_construct_message_ntls(SSL *s, WPACKET *pkt, + confunc_f *confunc, int *mt); +size_t ossl_statem_client_max_message_size_ntls(SSL *s); +MSG_PROCESS_RETURN ossl_statem_client_process_message_ntls(SSL *s, PACKET *pkt); +WORK_STATE ossl_statem_client_post_process_message_ntls(SSL *s, WORK_STATE wst); + +/* + * TLS/DTLS server state machine functions + */ +int ossl_statem_server_read_transition_ntls(SSL *s, int mt); +WRITE_TRAN ossl_statem_server_write_transition_ntls(SSL *s); +WORK_STATE ossl_statem_server_pre_work_ntls(SSL *s, WORK_STATE wst); +WORK_STATE ossl_statem_server_post_work_ntls(SSL *s, WORK_STATE wst); +int ossl_statem_server_construct_message_ntls(SSL *s, WPACKET *pkt, + confunc_f *confunc,int *mt); +size_t ossl_statem_server_max_message_size_ntls(SSL *s); +MSG_PROCESS_RETURN ossl_statem_server_process_message_ntls(SSL *s, PACKET *pkt); +WORK_STATE ossl_statem_server_post_process_message_ntls(SSL *s, WORK_STATE wst); + +/* Functions for getting new message data */ +__owur int tls_get_message_header_ntls(SSL *s, int *mt); +__owur int tls_get_message_body_ntls(SSL *s, size_t *len); +__owur int dtls_get_message_ntls(SSL *s, int *mt, size_t *len); + +/* Message construction and processing functions */ +__owur int tls_process_initial_server_flight_ntls(SSL *s); +__owur MSG_PROCESS_RETURN tls_process_change_cipher_spec_ntls(SSL *s, PACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_finished_ntls(SSL *s, PACKET *pkt); +__owur int tls_construct_change_cipher_spec_ntls(SSL *s, WPACKET *pkt); + + +__owur int tls_construct_finished_ntls(SSL *s, WPACKET *pkt); +__owur int tls_construct_key_update_ntls(SSL *s, WPACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_key_update_ntls(SSL *s, PACKET *pkt); +__owur WORK_STATE tls_finish_handshake_ntls(SSL *s, WORK_STATE wst, int clearbufs, + int stop); +__owur WORK_STATE dtls_wait_for_dry_ntls(SSL *s); + +/* some client-only functions */ +__owur int tls_construct_client_hello_ntls(SSL *s, WPACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_server_hello_ntls(SSL *s, PACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_certificate_request_ntls(SSL *s, PACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_new_session_ticket_ntls(SSL *s, PACKET *pkt); +__owur int tls_process_cert_status_body_ntls(SSL *s, PACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_cert_status_ntls(SSL *s, PACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_server_done_ntls(SSL *s, PACKET *pkt); +__owur WORK_STATE tls_prepare_client_certificate_ntls(SSL *s, WORK_STATE wst); +__owur int tls_construct_client_certificate_ntls(SSL *s, WPACKET *pkt); +__owur int ssl_do_client_cert_cb_ntls(SSL *s, X509 **px509, EVP_PKEY **ppkey); +__owur int tls_construct_client_key_exchange_ntls(SSL *s, WPACKET *pkt); +__owur int tls_client_key_exchange_post_work_ntls(SSL *s); +__owur int tls_construct_cert_status_body_ntls(SSL *s, WPACKET *pkt); +__owur int tls_construct_cert_status_ntls(SSL *s, WPACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_key_exchange_ntls(SSL *s, PACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_server_certificate_ntls(SSL *s, PACKET *pkt); +__owur int ssl3_check_cert_and_algorithm_ntls(SSL *s); +#ifndef OPENSSL_NO_NEXTPROTONEG +__owur int tls_construct_next_proto_ntls(SSL *s, WPACKET *pkt); +#endif +__owur MSG_PROCESS_RETURN tls_process_hello_req_ntls(SSL *s, PACKET *pkt); +__owur MSG_PROCESS_RETURN dtls_process_hello_verify_ntls(SSL *s, PACKET *pkt); +__owur int tls_construct_end_of_early_data_ntls(SSL *s, WPACKET *pkt); + +/* some server-only functions */ +__owur MSG_PROCESS_RETURN tls_process_client_hello_ntls(SSL *s, PACKET *pkt); +__owur WORK_STATE tls_post_process_client_hello_ntls(SSL *s, WORK_STATE wst); +__owur int tls_construct_server_hello_ntls(SSL *s, WPACKET *pkt); +__owur int dtls_construct_hello_verify_request_ntls(SSL *s, WPACKET *pkt); +__owur int tls_construct_server_certificate_ntls(SSL *s, WPACKET *pkt); +__owur int tls_construct_server_key_exchange_ntls(SSL *s, WPACKET *pkt); +__owur int tls_construct_certificate_request_ntls(SSL *s, WPACKET *pkt); +__owur int tls_construct_server_done_ntls(SSL *s, WPACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_client_certificate_ntls(SSL *s, PACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_client_key_exchange_ntls(SSL *s, PACKET *pkt); +__owur WORK_STATE tls_post_process_client_key_exchange_ntls(SSL *s, WORK_STATE wst); +__owur MSG_PROCESS_RETURN tls_process_cert_verify_ntls(SSL *s, PACKET *pkt); +#ifndef OPENSSL_NO_NEXTPROTONEG +__owur MSG_PROCESS_RETURN tls_process_next_proto_ntls(SSL *s, PACKET *pkt); +#endif +__owur int tls_construct_new_session_ticket_ntls(SSL *s, WPACKET *pkt); +MSG_PROCESS_RETURN tls_process_end_of_early_data_ntls(SSL *s, PACKET *pkt); + + +/* Extension processing */ + +typedef enum ext_return_en { + EXT_RETURN_FAIL, + EXT_RETURN_SENT, + EXT_RETURN_NOT_SENT +} EXT_RETURN; + +__owur int tls_validate_all_contexts_ntls(SSL *s, unsigned int thisctx, + RAW_EXTENSION *exts); +__owur int extension_is_relevant_ntls(SSL *s, unsigned int extctx, + unsigned int thisctx); +__owur int tls_collect_extensions_ntls(SSL *s, PACKET *packet, unsigned int context, + RAW_EXTENSION **res, size_t *len, int init); +__owur int tls_parse_extension_ntls(SSL *s, TLSEXT_INDEX idx, int context, + RAW_EXTENSION *exts, X509 *x, size_t chainidx); +__owur int tls_parse_all_extensions_ntls(SSL *s, int context, RAW_EXTENSION *exts, + X509 *x, size_t chainidx, int fin); +__owur int should_add_extension_ntls(SSL *s, unsigned int extctx, + unsigned int thisctx, int max_version); +__owur int tls_construct_extensions_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); + +__owur int tls_psk_do_binder_ntls(SSL *s, const EVP_MD *md, + const unsigned char *msgstart, + size_t binderoffset, const unsigned char *binderin, + unsigned char *binderout, + SSL_SESSION *sess, int sign, int external); + +/* Server Extension processing */ +int tls_parse_ctos_renegotiate_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_parse_ctos_server_name_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_parse_ctos_maxfragmentlen_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_parse_ctos_early_data_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#ifndef OPENSSL_NO_EC +int tls_parse_ctos_ec_pt_formats_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_parse_ctos_supported_groups_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidxl); +#endif +int tls_parse_ctos_session_ticket_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_parse_ctos_sig_algs_cert_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_parse_ctos_sig_algs_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +#ifndef OPENSSL_NO_OCSP +int tls_parse_ctos_status_request_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#endif +#ifndef OPENSSL_NO_NEXTPROTONEG +int tls_parse_ctos_npn_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +#endif +int tls_parse_ctos_alpn_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +#ifndef OPENSSL_NO_SRTP +int tls_parse_ctos_use_srtp_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +#endif +int tls_parse_ctos_etm_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +int tls_parse_ctos_key_share_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +int tls_parse_ctos_cookie_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +int tls_parse_ctos_ems_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +int tls_parse_ctos_psk_kex_modes_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_parse_ctos_psk_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +int tls_parse_ctos_post_handshake_auth_ntls(SSL *, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); + +EXT_RETURN tls_construct_stoc_renegotiate_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_stoc_server_name_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_stoc_early_data_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_stoc_maxfragmentlen_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +#ifndef OPENSSL_NO_EC +EXT_RETURN tls_construct_stoc_ec_pt_formats_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +#endif +EXT_RETURN tls_construct_stoc_supported_groups_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_stoc_session_ticket_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +#ifndef OPENSSL_NO_OCSP +EXT_RETURN tls_construct_stoc_status_request_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +#endif +#ifndef OPENSSL_NO_NEXTPROTONEG +EXT_RETURN tls_construct_stoc_next_proto_neg_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +#endif +EXT_RETURN tls_construct_stoc_alpn_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#ifndef OPENSSL_NO_SRTP +EXT_RETURN tls_construct_stoc_use_srtp_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#endif +EXT_RETURN tls_construct_stoc_etm_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +EXT_RETURN tls_construct_stoc_ems_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +EXT_RETURN tls_construct_stoc_supported_versions_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_stoc_key_share_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_stoc_cookie_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +/* + * Not in public headers as this is not an official extension. Only used when + * SSL_OP_CRYPTOPRO_TLSEXT_BUG is set. + */ +#define TLSEXT_TYPE_cryptopro_bug 0xfde8 +EXT_RETURN tls_construct_stoc_cryptopro_bug_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_stoc_psk_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); + +/* Client Extension processing */ +EXT_RETURN tls_construct_ctos_renegotiate_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +EXT_RETURN tls_construct_ctos_server_name_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +EXT_RETURN tls_construct_ctos_maxfragmentlen_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); + +#ifndef OPENSSL_NO_EC +EXT_RETURN tls_construct_ctos_ec_pt_formats_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_ctos_supported_groups_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +#endif +EXT_RETURN tls_construct_ctos_early_data_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_ctos_session_ticket_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_ctos_sig_algs_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +#ifndef OPENSSL_NO_OCSP +EXT_RETURN tls_construct_ctos_status_request_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +#endif +#ifndef OPENSSL_NO_NEXTPROTONEG +EXT_RETURN tls_construct_ctos_npn_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#endif +EXT_RETURN tls_construct_ctos_alpn_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#ifndef OPENSSL_NO_SRTP +EXT_RETURN tls_construct_ctos_use_srtp_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#endif +EXT_RETURN tls_construct_ctos_etm_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#ifndef OPENSSL_NO_CT +EXT_RETURN tls_construct_ctos_sct_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#endif +EXT_RETURN tls_construct_ctos_ems_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +EXT_RETURN tls_construct_ctos_supported_versions_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_ctos_key_share_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_ctos_psk_kex_modes_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_ctos_cookie_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +EXT_RETURN tls_construct_ctos_padding_ntls(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_ctos_psk_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +EXT_RETURN tls_construct_ctos_post_handshake_auth_ntls(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); + +int tls_parse_stoc_renegotiate_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_parse_stoc_server_name_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_parse_stoc_early_data_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_parse_stoc_maxfragmentlen_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#ifndef OPENSSL_NO_EC +int tls_parse_stoc_ec_pt_formats_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#endif +int tls_parse_stoc_session_ticket_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#ifndef OPENSSL_NO_OCSP +int tls_parse_stoc_status_request_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#endif +#ifndef OPENSSL_NO_CT +int tls_parse_stoc_sct_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +#endif +#ifndef OPENSSL_NO_NEXTPROTONEG +int tls_parse_stoc_npn_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +#endif +int tls_parse_stoc_alpn_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +#ifndef OPENSSL_NO_SRTP +int tls_parse_stoc_use_srtp_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +#endif +int tls_parse_stoc_etm_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +int tls_parse_stoc_ems_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +int tls_parse_stoc_supported_versions_ntls(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_parse_stoc_key_share_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +int tls_parse_stoc_cookie_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +int tls_parse_stoc_psk_ntls(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); + +int tls_handle_alpn_ntls(SSL *s); + +int tls13_save_handshake_digest_for_pha_ntls(SSL *s); +int tls13_restore_handshake_digest_for_pha_ntls(SSL *s); + + + +/* NTLS stuffs */ + +/* server side functions */ +__owur int ntls_construct_server_certificate_ntls(SSL *s, WPACKET *pkt); +__owur int ntls_construct_server_key_exchange_ntls(SSL *s, WPACKET *pkt); +__owur MSG_PROCESS_RETURN ntls_process_client_key_exchange_ntls(SSL *s, PACKET *pkt); +__owur MSG_PROCESS_RETURN ntls_process_cert_verify_ntls(SSL *s, PACKET *pkt); + +/* client side functions */ +__owur int ntls_construct_client_certificate_ntls(SSL *s, WPACKET *pkt); +__owur int ntls_construct_client_key_exchange_ntls(SSL *s, WPACKET *pkt); +__owur int ntls_construct_cert_verify_ntls(SSL *s, WPACKET *pkt); +__owur MSG_PROCESS_RETURN ntls_process_server_key_exchange_ntls(SSL *s, PACKET *pkt); + +/* common functions */ +int ntls_sm2_derive_ntls(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey); +int ntls_output_cert_chain_ntls(SSL *s, WPACKET *pkt, int a_idx, int k_idx); + +/* from statem.h move here */ + +/* function define in ssl.h */ + +__owur int SSL_CTX_has_client_custom_ext_ntls(const SSL_CTX *ctx, + unsigned int ext_type); + +__owur int SSL_CTX_add_client_custom_ext_ntls(SSL_CTX *ctx, + unsigned int ext_type, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, + void *parse_arg); + +__owur int SSL_CTX_add_server_custom_ext_ntls(SSL_CTX *ctx, + unsigned int ext_type, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, + void *parse_arg); + +__owur int SSL_CTX_add_custom_ext_ntls(SSL_CTX *ctx, unsigned int ext_type, + unsigned int context, + SSL_custom_ext_add_cb_ex add_cb, + SSL_custom_ext_free_cb_ex free_cb, + void *add_arg, + SSL_custom_ext_parse_cb_ex parse_cb, + void *parse_arg); + +__owur int SSL_extension_supported_ntls(unsigned int ext_type); +__owur OSSL_HANDSHAKE_STATE SSL_get_state_ntls(const SSL *ssl); +int SSL_in_init_ntls(const SSL *s); +int SSL_in_before_ntls(const SSL *s); +int SSL_is_init_finished_ntls(const SSL *s); + + diff --git a/ssl/statem_ntls/statem_ntls.c b/ssl/statem_ntls/statem_ntls.c new file mode 100644 index 000000000..233060f86 --- /dev/null +++ b/ssl/statem_ntls/statem_ntls.c @@ -0,0 +1,541 @@ +/* + * Copyright 2019 The BabaSSL Project Authors. All Rights Reserved. + */ + +#include +#include +#include "ssl_local_ntls.h" +#include "statem_local_ntls.h" +#include "internal/constant_time.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if (!defined OPENSSL_NO_NTLS) && (!defined OPENSSL_NO_SM2) \ + && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) + +#include +#include + +# if !(defined(OPENSSL_NO_KEYLESS) && defined(OPENSSL_NO_LURK)) +static int ntls_i2d_pkey(int (*i2d) (EVP_PKEY *, unsigned char **), + EVP_PKEY *pkey_in, unsigned char **str_out, int *len_out) +{ + int dsize; + unsigned char *idx; + + if ((dsize = i2d(pkey_in, NULL)) < 0) { + SSLerr(SSL_F_NTLS_I2D_PKEY, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* dsize + 8 bytes are needed */ + /* actually it needs the cipher block size extra... */ + *str_out = OPENSSL_malloc((unsigned int)dsize + 20); + idx = *str_out; + if (*str_out == NULL) { + SSLerr(SSL_F_NTLS_I2D_PKEY, ERR_R_INTERNAL_ERROR); + return 0; + } + + *len_out = i2d(pkey_in, &idx); + if (*len_out <= 0) { + OPENSSL_free(str_out); + SSLerr(SSL_F_NTLS_I2D_PKEY, ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} +# endif + +int ntls_sm2_derive_ntls(SSL *s, EVP_PKEY *tmp_priv, EVP_PKEY *peer_tmp_pub) +{ + int ret = 0, idx = 1; + /* peer ecdh temporary public key */ + EC_KEY *peer_tmp_pub_ec; + /* self ecdh temporary private key */ + EC_KEY *tmp_priv_ec; + /* peer encryption certificate, public PKEY and public EC key */ + X509 *peer_x509; + EVP_PKEY *peer_cert_pub; + EC_KEY *peer_cert_pub_ec; + /* self encryption certificate private key (PKEY and EC) */ + EVP_PKEY *cert_priv = NULL; + EC_KEY *cert_priv_ec = NULL; + /* self SM2 ID */ + char *id = "1234567812345678"; + /* peer SM2 ID */ + char *peer_id = "1234567812345678"; + /* pre-master secret */ + unsigned char *pms = NULL; + size_t pmslen = SSL_MAX_MASTER_KEY_LENGTH; + +#ifndef OPENSSL_NO_KEYLESS + if (s->keyless_ntls && s->keyless_again) + goto keyless_recover; +#endif +#ifndef OPENSSL_NO_LURK + if (s->lurk_ntls && s->lurk_again) + goto lurk_recover; +#endif + + if (!(peer_tmp_pub_ec = EVP_PKEY_get0_EC_KEY(peer_tmp_pub))) { + SSLerr(SSL_F_NTLS_SM2_DERIVE_NTLS, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!(tmp_priv_ec = EVP_PKEY_get0_EC_KEY(tmp_priv))) { + SSLerr(SSL_F_NTLS_SM2_DERIVE_NTLS, ERR_R_INTERNAL_ERROR); + return 0; + } + if (1 +#ifndef OPENSSL_NO_KEYLESS + && !s->keyless_ntls +#endif +#ifndef OPENSSL_NO_LURK + && !s->lurk_ntls +#endif + ) + { + /* SM2 requires to use the private key in encryption certificate */ + if (!(cert_priv = s->cert->pkeys[SSL_PKEY_SM2_ENC].privatekey)) { + SSLerr(SSL_F_NTLS_SM2_DERIVE_NTLS, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!(cert_priv_ec = EVP_PKEY_get0_EC_KEY(cert_priv))) { + SSLerr(SSL_F_NTLS_SM2_DERIVE_NTLS, ERR_R_INTERNAL_ERROR); + return 0; + } + } + /* + * XXX: + * + * For NTLS server side, s->session->peer stores the client signing + * certificate and s->session->peer_chain is an one-item stack which + * stores the client encryption certificate. + * + * We need to get the client encryption certificate at this stage, + * so we use index 0 in peer_chain. + * + * For client side of NTLS, the peer is an reference of the first element + * of the two-item stack stored in s->session->peer_chain, which is the + * signing certificate of server. So we need to get the second certificate + * in this scenario for encryption usage. + */ + if (s->session->peer_chain == NULL) { + SSLerr(SSL_F_NTLS_SM2_DERIVE_NTLS, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (s->server) + idx = 0; + + if (!(peer_x509 = sk_X509_value(s->session->peer_chain, idx))) { + SSLerr(SSL_F_NTLS_SM2_DERIVE_NTLS, ERR_R_INTERNAL_ERROR); + return 0; + } + + peer_cert_pub = X509_get0_pubkey(peer_x509); + if (!(peer_cert_pub_ec = EVP_PKEY_get0_EC_KEY(peer_cert_pub))) { + SSLerr(SSL_F_NTLS_SM2_DERIVE_NTLS, ERR_R_INTERNAL_ERROR); + return 0; + } + +#if !(defined(OPENSSL_NO_KEYLESS) && defined(OPENSSL_NO_LURK)) + if (0 +# ifndef OPENSSL_NO_KEYLESS + || s->keyless_ntls +# endif +# ifndef OPENSSL_NO_LURK + || s->lurk_ntls +# endif + ) + { + unsigned char *tmp_priv_char, *peer_tmp_pub_char, *peer_cert_pub_char; + unsigned char *tmp_buf, *buf_index; + int tmp_priv_len, peer_tmp_pub_len, peer_cert_pub_len; + uint32_t prefix_len; + uint32_t len_net; + int keyless_ret = 0; + + + if (ntls_i2d_pkey(i2d_PrivateKey, + tmp_priv, &tmp_priv_char, &tmp_priv_len) <=0 ) { + SSLerr(SSL_F_NTLS_SM2_DERIVE_NTLS, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (ntls_i2d_pkey(i2d_PUBKEY,peer_tmp_pub, + &peer_tmp_pub_char, &peer_tmp_pub_len) <=0 ) { + SSLerr(SSL_F_NTLS_SM2_DERIVE_NTLS, ERR_R_INTERNAL_ERROR); + OPENSSL_free(tmp_priv_char); + return 0; + } + + if (ntls_i2d_pkey(i2d_PUBKEY,peer_cert_pub, + &peer_cert_pub_char, &peer_cert_pub_len) <=0 ) { + SSLerr(SSL_F_NTLS_SM2_DERIVE_NTLS, ERR_R_INTERNAL_ERROR); + OPENSSL_free(tmp_priv_char); + OPENSSL_free(peer_tmp_pub_char); + return 0; + } + + /* + * package format + * -------------------------------------------------- + * tmp_priv_char (4byte) | data (tmp_priv_len bytes)| ... + * -------------------------------------------------- + * ---------------------------------------------------------- + * peer_tmp_pub_char (4byte) | data (peer_tmp_pub_len bytes)| ... + * ---------------------------------------------------------- + * ------------------------------------------------------------ + * peer_cert_pub_char (4byte) | data (peer_cert_pub_len bytes)| + * ------------------------------------------------------------ + */ + prefix_len = 4; + + tmp_buf = (unsigned char *)OPENSSL_malloc(prefix_len + tmp_priv_len + + prefix_len + peer_tmp_pub_len + + prefix_len + peer_cert_pub_len); + if (tmp_buf == NULL) { + SSLerr(SSL_F_NTLS_SM2_DERIVE_NTLS, ERR_R_INTERNAL_ERROR); + OPENSSL_free(tmp_priv_char); + OPENSSL_free(peer_tmp_pub_char); + OPENSSL_free(peer_cert_pub_char); + return 0; + } + buf_index = tmp_buf; + len_net = htonl(tmp_priv_len); + memcpy(buf_index, &len_net, prefix_len); + buf_index += prefix_len; + memcpy(buf_index, tmp_priv_char, tmp_priv_len); + buf_index += tmp_priv_len; + len_net = htonl(peer_tmp_pub_len); + memcpy(buf_index, &len_net, prefix_len); + buf_index += prefix_len; + memcpy(buf_index, peer_tmp_pub_char, peer_tmp_pub_len); + buf_index += peer_tmp_pub_len; + len_net = htonl(peer_cert_pub_len); + memcpy(buf_index, &len_net, prefix_len); + buf_index += prefix_len; + memcpy(buf_index, peer_cert_pub_char, peer_cert_pub_len); + OPENSSL_free(tmp_priv_char); + OPENSSL_free(peer_tmp_pub_char); + OPENSSL_free(peer_cert_pub_char); + +# ifndef OPENSSL_NO_KEYLESS + if (s->keyless_ntls) { + s->keyless_callback_param.data = tmp_buf; + s->keyless_callback_param.len = tmp_priv_len + peer_tmp_pub_len + + peer_cert_pub_len + 3 * prefix_len; + s->keyless_callback_param.type = SSL_KEYLESS_TYPE_SM2DHE_GEN_MASTER_KEY; + s->keyless_callback_param.cert_tag = SSL_ENC_CERT; + + keyless_ret = s->keyless_callback(s, &s->keyless_callback_param); + + OPENSSL_free(tmp_buf); + if (keyless_ret == 1) { + /* again or done */ + s->keyless_again = 1; + return 0; + } else if (keyless_ret == 0) { +keyless_recover: + pmslen = s->keyless_result_len; + if ((pms = OPENSSL_malloc(pmslen)) == NULL) { + SSLerr(SSL_F_NTLS_SM2_DERIVE_NTLS, ERR_R_INTERNAL_ERROR); + return 0; + } + memcpy(pms, s->keyless_result, s->keyless_result_len); + + if (s->keyless_again) + s->keyless_again = 0; + } else { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_SM2_DERIVE_NTLS, + SSL_R_KEYLESS_ERROR); + goto end; + } + } else +# endif +# ifndef OPENSSL_NO_LURK + if (s->lurk) { + s->lurk_callback_param.data = tmp_buf; + s->lurk_callback_param.len = tmp_priv_len + peer_tmp_pub_len + + peer_cert_pub_len + 3 * prefix_len; + s->lurk_callback_param.type = SSL_LURK_QUERY_SM2DHE_GEN_MASTER_KEY; + s->lurk_callback_param.cert_tag = SSL_ENC_CERT; + + keyless_ret = s->lurk_callback(s, &s->lurk_callback_param); + OPENSSL_free(tmp_buf); + if (keyless_ret == 1) { + /* again or done */ + s->lurk_again = 1; + return 0; + } else if (keyless_ret == 0) { +lurk_recover: + pmslen = s->lurk_result_len; + if ((pms = OPENSSL_malloc(pmslen)) == NULL) { + SSLerr(SSL_F_NTLS_SM2_DERIVE_NTLS, ERR_R_INTERNAL_ERROR); + return 0; + } + memcpy(pms, s->lurk_result, s->lurk_result_len); + + if (s->lurk_again) + s->lurk_again = 0; + } else { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_SM2_DERIVE_NTLS, + SSL_R_KEYLESS_ERROR); + goto end; + } + } +# else + { + } +# endif + } else +#endif + { + if ((pms = OPENSSL_malloc(pmslen)) == NULL) { + SSLerr(SSL_F_NTLS_SM2_DERIVE_NTLS, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!SM2_compute_key(pms, pmslen, s->server, + peer_id, strlen(peer_id), + id, strlen(id), + /* peer and self ecdh temp key */ + peer_tmp_pub_ec, tmp_priv_ec, + /* peer and self certificate key */ + peer_cert_pub_ec, cert_priv_ec, + EVP_sm3())) { + SSLerr(SSL_F_NTLS_SM2_DERIVE_NTLS, ERR_R_INTERNAL_ERROR); + goto end; + } + } + + if (s->server) { + ret = ssl_generate_master_secret(s, pms, pmslen, 1); + } else { + s->s3->tmp.pms = pms; + s->s3->tmp.pmslen = pmslen; + ret = 1; + } + + end: + return ret; +} + +int ntls_output_cert_chain_ntls(SSL *s, WPACKET *pkt, int a_idx, int k_idx) +{ + int i; + STACK_OF(X509) *extra_certs; + STACK_OF(X509) *chain = NULL; + X509_STORE *chain_store; + CERT_PKEY *a_cpk; + CERT_PKEY *k_cpk; + X509_STORE_CTX *xs_ctx = NULL; + + if (!WPACKET_start_sub_packet_u24(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_OUTPUT_CERT_CHAIN_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + a_cpk = &s->cert->pkeys[a_idx]; + k_cpk = &s->cert->pkeys[k_idx]; + + if (a_cpk->chain) + extra_certs = a_cpk->chain; + else if (k_cpk->chain) + extra_certs = k_cpk->chain; + else + extra_certs = s->ctx->extra_certs; + + if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || extra_certs) + chain_store = NULL; + else if (s->cert->chain_store) + chain_store = s->cert->chain_store; + else + chain_store = s->ctx->cert_store; + + if (chain_store) { + xs_ctx = X509_STORE_CTX_new(); + if (xs_ctx == NULL) + goto err; + + if (!X509_STORE_CTX_init(xs_ctx, chain_store, a_cpk->x509, NULL)) + goto err; + + /* + * deliberately skip the cert chain verification by don't check the + * return value + */ + (void)X509_verify_cert(xs_ctx); + ERR_clear_error(); + + chain = X509_STORE_CTX_get0_chain(xs_ctx); + if (chain == NULL) + goto err; + + i = ssl_security_cert_chain(s, chain, NULL, 0); + if (i != 1) { + goto err; + } + + /* add signing certificate */ + if (!ssl_add_cert_to_wpacket_ntls(s, pkt, s->cert->pkeys[a_idx].x509, 0)) { + goto err; + } + + /* add key encryption certificate */ + if (!ssl_add_cert_to_wpacket_ntls(s, pkt, s->cert->pkeys[k_idx].x509, 0)) { + goto err; + } + + /* add the following chain */ + for (i = 1; i < sk_X509_num(chain); i++) { + X509 *x = sk_X509_value(chain, i); + if (!ssl_add_cert_to_wpacket_ntls(s, pkt, x, i)) + goto err; + } + } else { + if (extra_certs == NULL && a_cpk->x509 == NULL) + goto err; + + i = ssl_security_cert_chain(s, extra_certs, a_cpk->x509, 0); + if (i != 1) + goto err; + + /* output sign cert and enc cert */ + if (!ssl_add_cert_to_wpacket_ntls(s, pkt, s->cert->pkeys[a_idx].x509, 0)) + goto err; + + if (!ssl_add_cert_to_wpacket_ntls(s, pkt, s->cert->pkeys[k_idx].x509, 0)) + goto err; + + /* output the following chain */ + for (i = 0; i < sk_X509_num(extra_certs); i++) { + X509 *x = sk_X509_value(extra_certs, i); + if (!ssl_add_cert_to_wpacket_ntls(s, pkt, x, i)) + goto err; + } + } + + if (!WPACKET_close(pkt)) + goto err; + X509_STORE_CTX_free(xs_ctx); + return 1; + + err: + X509_STORE_CTX_free(xs_ctx); + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_OUTPUT_CERT_CHAIN_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; +} + + +# define PEEK_HEADER_LENGTH 3 +int SSL_connection_is_ntls(SSL *s, int is_server) +{ + /* + * For client, or sometimes ssl_version is fixed, + * we can easily determine if version is NTLS + */ + if (s->version == NTLS1_1_VERSION) + return 1; +# ifndef OPENSSL_NO_KEYLESS + /* + * keyless processing has choosed verison before + */ + if ((s->keyless || s->keyless_ntls) && s->keyless_again) { + if (s->version == NTLS1_1_VERSION) + return 1; + else + return 0; + } +# endif +# ifndef OPENSSL_NO_LURK + /* + * keyless processing has choosed verison before + */ + if (s->lurk && s->lurk_ntls && s->lurk_again) { + if (s->version == NTLS1_1_VERSION) + return 1; + else + return 0; + } +# endif + + if (is_server) { + /* After receiving client hello and before choosing server version, + * get version from s->clienthello->legacy_version + */ + if (s->clienthello) { + if (s->clienthello->legacy_version == NTLS1_1_VERSION) + return 1; + else + return 0; + } + + /* + * For server, first flight has not set version, we + * have to get the server version from clientHello + */ + if (SSL_IS_FIRST_HANDSHAKE(s) && SSL_in_before(s)) { + int ret, fd; + PACKET pkt; + unsigned int version, type; + unsigned char buf[PEEK_HEADER_LENGTH]; + + ret = BIO_get_fd(s->rbio, &fd); + + if (ret <= 0) { + /* NTLS only support socket communication */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CONNECTION_IS_NTLS, + ERR_R_INTERNAL_ERROR); + return -1; + } + + ret = recv(fd, buf, PEEK_HEADER_LENGTH, MSG_PEEK); + if (ret < PEEK_HEADER_LENGTH) { + s->rwstate = SSL_READING; + return -1; + } + + if (!PACKET_buf_init(&pkt, buf, 3)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CONNECTION_IS_NTLS, + ERR_R_INTERNAL_ERROR); + return -1; + } + + if (!PACKET_get_1(&pkt, &type)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_SSL_CONNECTION_IS_NTLS, + ERR_R_INTERNAL_ERROR); + return -1; + } + + if (!PACKET_get_net_2(&pkt, &version)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_SSL_CONNECTION_IS_NTLS, + ERR_R_INTERNAL_ERROR); + return -1; + } + + if (version == NTLS1_1_VERSION) + return 1; + else + return 0; + } + } + + return 0; +} + +#endif diff --git a/ssl/statem_ntls/statem_ntls_clnt.c b/ssl/statem_ntls/statem_ntls_clnt.c new file mode 100644 index 000000000..e95a5c543 --- /dev/null +++ b/ssl/statem_ntls/statem_ntls_clnt.c @@ -0,0 +1,882 @@ +/* + * Copyright 2019 The BabaSSL Project Authors. All Rights Reserved. + */ + +#include +#include +#include "ssl_local_ntls.h" +#include "statem_local_ntls.h" +#include "internal/constant_time.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if (!defined OPENSSL_NO_NTLS) && (!defined OPENSSL_NO_SM2) \ + && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) +static int ntls_process_ske_sm2dhe(SSL *s, PACKET *pkt) +{ + int ret = 0; + const unsigned char *ecparams; + PACKET encoded_pt; + EVP_PKEY_CTX *pctx = NULL; + int paramslen; + PACKET signature; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *mpctx = NULL; + int maxsig; + char *id = "1234567812345678"; + EVP_MD_CTX *md_ctx = NULL; + + /* parse ECParameter */ + if (!PACKET_get_bytes(pkt, &ecparams, 3)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2DHE, SSL_R_LENGTH_TOO_SHORT); + return 0; + } + + /* parse ECPoint */ + if (!PACKET_get_length_prefixed_1(pkt, &encoded_pt)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2DHE, SSL_R_LENGTH_MISMATCH); + return 0; + } + + if (!(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL))) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2DHE, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (EVP_PKEY_paramgen_init(pctx) <= 0 + || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_sm2) <= 0 + || EVP_PKEY_paramgen(pctx, &s->s3->peer_tmp) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2DHE, ERR_R_EVP_LIB); + goto end; + } + + if (s->s3->peer_tmp == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2DHE, ERR_R_INTERNAL_ERROR); + goto end; + } + + if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp, + PACKET_data(&encoded_pt), + PACKET_remaining(&encoded_pt))) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2DHE, SSL_R_BAD_ECPOINT); + goto end; + } + + /* get ECDHEParams length */ + paramslen = PACKET_data(pkt) - ecparams; + + /* parse signature packet, check no data remaining */ + if (!PACKET_get_length_prefixed_2(pkt, &signature) + || PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2DHE, SSL_R_LENGTH_MISMATCH); + goto end; + } + + if ((pkey = X509_get0_pubkey(s->session->peer)) == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2DHE, ERR_R_INTERNAL_ERROR); + goto end; + } + + if ((maxsig = EVP_PKEY_size(pkey)) < 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2DHE, ERR_R_INTERNAL_ERROR); + goto end; + } + + if (PACKET_remaining(&signature) > (size_t)maxsig) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2DHE, SSL_R_WRONG_SIGNATURE_LENGTH); + goto end; + } + + if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2DHE, ERR_R_EVP_LIB); + goto end; + } + + /* verify the signature */ + if ((md_ctx = EVP_MD_CTX_new()) == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2DHE, ERR_R_MALLOC_FAILURE); + goto end; + } + + mpctx = EVP_PKEY_CTX_new(pkey, NULL); + if (mpctx == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2DHE, ERR_R_EVP_LIB); + goto end; + } + + if (EVP_PKEY_CTX_set1_id(mpctx, id, strlen(id)) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2DHE, ERR_R_EVP_LIB); + goto end; + } + + EVP_MD_CTX_set_pkey_ctx(md_ctx, mpctx);; + + if (EVP_DigestVerifyInit(md_ctx, NULL, EVP_sm3(), NULL, pkey) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2DHE, ERR_R_EVP_LIB); + goto end; + } + + if (EVP_DigestVerifyUpdate(md_ctx, &(s->s3->client_random[0]), + SSL3_RANDOM_SIZE) <= 0 + || EVP_DigestVerifyUpdate(md_ctx, &(s->s3->server_random[0]), + SSL3_RANDOM_SIZE) <= 0 + || EVP_DigestVerifyUpdate(md_ctx, ecparams, paramslen) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2DHE, ERR_R_EVP_LIB); + goto end; + } + + if (EVP_DigestVerifyFinal(md_ctx, PACKET_data(&signature), + PACKET_remaining(&signature)) <= 0) { + SSLfatal_ntls(s, SSL_AD_DECRYPT_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2DHE, SSL_R_BAD_SIGNATURE); + goto end; + } + + ret = 1; + + end: + EVP_PKEY_CTX_free(pctx); + EVP_MD_CTX_free(md_ctx); + EVP_PKEY_CTX_free(mpctx); + return ret; +} + +static int ntls_process_ske_sm2(SSL *s, PACKET *pkt) +{ + int ret = 0; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *pctx = NULL; + X509 *x509; + unsigned char *buf = NULL, *p = NULL; + int n; + PACKET signature; + int maxsig; + EVP_MD_CTX *md_ctx = NULL; + char *id = "1234567812345678"; + + /* get peer's signing pkey */ + if (!(pkey = X509_get0_pubkey(s->session->peer))) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* get peer's encryption cert */ + if ((x509 = sk_X509_value(s->session->peer_chain, 1)) == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2, ERR_R_INTERNAL_ERROR); + return 0; + } + + if ((n = i2d_X509(x509, NULL)) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* XXX: Should the heading 3 bytes be necessary? */ + buf = OPENSSL_malloc(n + 3); + if (buf == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2, ERR_R_INTERNAL_ERROR); + return 0; + } + + p = &(buf[3]); + if ((n = i2d_X509(x509, &p)) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2, ERR_R_INTERNAL_ERROR); + goto end; + } + + l2n3(n, buf); + buf -= 3; + + /* get signature packet, check no data remaining */ + if (!PACKET_get_length_prefixed_2(pkt, &signature) + || PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2, SSL_R_LENGTH_MISMATCH); + goto end; + } + + maxsig = EVP_PKEY_size(pkey); + if (maxsig < 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2, ERR_R_INTERNAL_ERROR); + goto end; + } + + if (PACKET_remaining(&signature) > (size_t)maxsig) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2, SSL_R_WRONG_SIGNATURE_LENGTH); + goto end; + } + + /* verify the signature */ + if ((md_ctx = EVP_MD_CTX_new()) == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2, ERR_R_EVP_LIB); + goto end; + } + + /* set pkey to SM2 */ + if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2, ERR_R_EVP_LIB); + goto end; + } + + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (pctx == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2, ERR_R_EVP_LIB); + goto end; + } + + if (EVP_PKEY_CTX_set1_id(pctx, id, strlen(id)) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2, ERR_R_EVP_LIB); + goto end; + } + + EVP_MD_CTX_set_pkey_ctx(md_ctx, pctx);; + + if (EVP_DigestVerifyInit(md_ctx, NULL, EVP_sm3(), NULL, pkey) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2, ERR_R_EVP_LIB); + goto end; + } + + if (EVP_DigestVerifyUpdate(md_ctx, &(s->s3->client_random[0]), + SSL3_RANDOM_SIZE) <= 0 + || EVP_DigestVerifyUpdate(md_ctx, &(s->s3->server_random[0]), + SSL3_RANDOM_SIZE) <= 0 + || EVP_DigestVerifyUpdate(md_ctx, buf, n + 3) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2, ERR_R_EVP_LIB); + goto end; + } + + if (EVP_DigestVerifyFinal(md_ctx, PACKET_data(&signature), + PACKET_remaining(&signature)) <= 0) { + SSLfatal_ntls(s, SSL_AD_DECRYPT_ERROR, + SSL_F_NTLS_PROCESS_SKE_SM2, SSL_R_BAD_SIGNATURE); + ERR_print_errors_fp(stderr); + goto end; + } + + ret = 1; + +end: + OPENSSL_free(buf); + EVP_MD_CTX_free(md_ctx); + EVP_PKEY_CTX_free(pctx); + + return ret; +} + +static int ntls_process_ske_rsa(SSL *s, PACKET *pkt) +{ + int ret = 0; + EVP_PKEY *pkey; + X509 *x509; + PACKET signature; + int maxsig; + unsigned char *buf = NULL, *p = NULL; + int n; + const EVP_MD *md; + EVP_MD_CTX *md_ctx = NULL; + + /* get peer's signing pkey */ + if ((pkey = X509_get0_pubkey(s->session->peer)) == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_RSA, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* get peer's encryption cert */ + if ((x509 = sk_X509_value(s->session->peer_chain, 1)) == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_RSA, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* get signature packet, check no data remaining */ + if (!PACKET_get_length_prefixed_2(pkt, &signature) + || PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_NTLS_PROCESS_SKE_RSA, SSL_R_LENGTH_MISMATCH); + return 0; + } + + maxsig = EVP_PKEY_size(pkey); + if (maxsig < 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_RSA, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (PACKET_remaining(&signature) > (size_t)maxsig) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_NTLS_PROCESS_SKE_RSA, SSL_R_WRONG_SIGNATURE_LENGTH); + return 0; + } + + if ((n = i2d_X509(x509, NULL)) <= 0) + return 0; + + /* XXX: Should the heading 3 bytes be necessary? */ + buf = OPENSSL_malloc(n + 3); + if (buf == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_RSA, ERR_R_INTERNAL_ERROR); + return 0; + } + + p = &(buf[3]); + + if ((n = i2d_X509(x509, &p)) <= 0) + goto end; + + l2n3(n, buf); + buf -= 3; + + /* verify the signature */ + if (!(md_ctx = EVP_MD_CTX_new())) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_RSA, ERR_R_EVP_LIB); + goto end; + } + + if (!ssl_cipher_get_evp(s->session, NULL, &md, NULL, NULL, NULL, 0)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_RSA, ERR_R_INTERNAL_ERROR); + goto end; + } + + if (EVP_VerifyInit_ex(md_ctx, md, NULL) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_RSA, ERR_R_INTERNAL_ERROR); + goto end; + } + + if (EVP_VerifyUpdate(md_ctx, &(s->s3->client_random[0]), + SSL3_RANDOM_SIZE) <= 0 + || EVP_VerifyUpdate(md_ctx, &(s->s3->server_random[0]), + SSL3_RANDOM_SIZE) <= 0 + || EVP_VerifyUpdate(md_ctx, buf, n) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_SKE_RSA, ERR_R_INTERNAL_ERROR); + goto end; + } + + if (EVP_VerifyFinal(md_ctx, PACKET_data(&signature), + PACKET_remaining(&signature), pkey) <= 0) { + SSLfatal_ntls(s, SSL_AD_DECRYPT_ERROR, + SSL_F_NTLS_PROCESS_SKE_RSA, SSL_R_BAD_SIGNATURE); + goto end; + } + + ret = 1; + + end: + OPENSSL_free(buf); + EVP_MD_CTX_free(md_ctx); + return ret; +} + +MSG_PROCESS_RETURN ntls_process_server_key_exchange_ntls(SSL *s, PACKET *pkt) +{ + unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + + if (alg_k & SSL_kSM2DHE) { + if (!ntls_process_ske_sm2dhe(s, pkt)) { + /* SSLfatal_ntls already called */ + goto err; + } + } else if (alg_k & SSL_kSM2) { + if (!ntls_process_ske_sm2(s, pkt)) { + /* SSLfatal_ntls already called */ + goto err; + } + } else if (alg_k & SSL_kRSA) { + if (!ntls_process_ske_rsa(s, pkt)) { + /* SSLfatal_ntls already called */ + goto err; + } + } else { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_NTLS_PROCESS_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + return MSG_PROCESS_CONTINUE_READING; + + err: + return MSG_PROCESS_ERROR; +} + +int ntls_construct_client_certificate_ntls(SSL *s, WPACKET *pkt) +{ + unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth; + + if (alg_a & SSL_aSM2) { + if (!ntls_output_cert_chain_ntls(s, pkt, SSL_PKEY_SM2_SIGN, SSL_PKEY_SM2_ENC)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else if (alg_a & SSL_aRSA) { + /* FIXME: RSA should also has two certificate types */ + if (!ntls_output_cert_chain_ntls(s, pkt, SSL_PKEY_RSA, SSL_PKEY_RSA)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CLIENT_CERTIFICATE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + return 1; + err: + return 0; +} + +static int ntls_construct_cke_sm2dhe(SSL *s, WPACKET *pkt) +{ + int ret = 0; + EVP_PKEY *skey; + EVP_PKEY *ckey = NULL; + unsigned char *encodedPoint = NULL; + int encodedlen; + int curve_id; + + if ((skey = s->s3->peer_tmp) == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_SM2DHE, ERR_R_INTERNAL_ERROR); + return 0; + } + + curve_id = tls1_shared_group(s, -2); + + /* XXX: do we need this in NTLS? */ + if (!WPACKET_put_bytes_u8(pkt, NAMED_CURVE_TYPE) + || !WPACKET_put_bytes_u8(pkt, 0) + || !WPACKET_put_bytes_u8(pkt, curve_id)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_SM2DHE, ERR_R_INTERNAL_ERROR); + return 0; + } + + if ((ckey = ssl_generate_pkey(skey)) == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_SM2DHE, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!ntls_sm2_derive_ntls(s, ckey, skey)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_SM2DHE, ERR_R_INTERNAL_ERROR); + goto end; + } + + if (!(encodedlen = EVP_PKEY_get1_tls_encodedpoint(ckey, &encodedPoint))) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_SM2DHE, ERR_R_INTERNAL_ERROR); + goto end; + } + + if (!WPACKET_sub_memcpy_u8(pkt, encodedPoint, encodedlen)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_SM2DHE, ERR_R_INTERNAL_ERROR); + goto end; + } + + ret = 1; + end: + EVP_PKEY_free(ckey); + OPENSSL_free(encodedPoint); + return ret; +} + +static int ntls_construct_cke_sm2(SSL *s, WPACKET *pkt) +{ + int ret = 0; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *pctx = NULL; + size_t enclen; + unsigned char *pms = NULL; + size_t pmslen; + unsigned char *encdata = NULL; + X509 *x509; + + /* get sm2 encryption key from enc cert */ + if (s->session->peer_chain == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_SM2, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* + * XXX: + * + * for client side, s->session->peer == s->session->peer_chain[0] is + * the server signing certificate. + * + * s->session->peer_chain[1] is the server encryption certificate + */ + if ((x509 = sk_X509_value(s->session->peer_chain, 1)) == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_SM2, ERR_R_INTERNAL_ERROR); + return 0; + } + + pkey = X509_get0_pubkey(x509); + if (EVP_PKEY_get0_EC_KEY(pkey) == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_SM2, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* generate pre_master_secret */ + pmslen = SSL_MAX_MASTER_KEY_LENGTH; + if ((pms = OPENSSL_malloc(pmslen)) == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_SM2, ERR_R_MALLOC_FAILURE); + return 0; + } + + pms[0] = s->client_version >> 8; + pms[1] = s->client_version & 0xff; + + if (RAND_bytes(pms + 2, pmslen - 2) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_SM2, ERR_R_INTERNAL_ERROR); + goto end; + } + + /* set pkey to SM2 */ + if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_SM2, ERR_R_EVP_LIB); + goto end; + } + + /* encrypt pre_master_secret */ + if ((pctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) { + SSLerr(SSL_F_NTLS_CONSTRUCT_CKE_SM2, ERR_R_MALLOC_FAILURE); + goto end; + } + + if (EVP_PKEY_encrypt_init(pctx) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_SM2, ERR_R_MALLOC_FAILURE); + goto end; + } + + if (EVP_PKEY_encrypt(pctx, NULL, &enclen, pms, pmslen) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_SM2, ERR_R_EVP_LIB); + goto end; + } + + /* + * XXX: + * This is very unclear. The standard TLS protocol requries no u16 len + * bytes before the encrypted PMS value. The NTLS specification is also + * very blurry on this. But major implementations require the 2 bytes + * length field (which is redundant), otherwise handshake will fail... + */ + if (!WPACKET_sub_allocate_bytes_u16(pkt, enclen, &encdata) + || EVP_PKEY_encrypt(pctx, encdata, &enclen, pms, pmslen) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_SM2, SSL_R_BAD_SM2_ENCRYPT); + goto end; + } + + /* save pre_master_secret */ + if (s->s3->tmp.pms != NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_SM2, ERR_R_INTERNAL_ERROR); + goto end; + } + + s->s3->tmp.pms = pms; + s->s3->tmp.pmslen = pmslen; + pms = NULL; + + ret = 1; + + end: + OPENSSL_clear_free(pms, pmslen); + EVP_PKEY_CTX_free(pctx); + return ret; +} + +static int ntls_construct_cke_rsa(SSL *s, WPACKET *pkt) +{ + int ret = 0; + unsigned char *encdata; + X509 *x509; + EVP_PKEY *pkey; + EVP_PKEY_CTX *pctx = NULL; + size_t enclen; + unsigned char *pms = NULL; + size_t pmslen = 0; + + /* get peer's encryption cert */ + if (s->session->peer_chain == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!(x509 = sk_X509_value(s->session->peer_chain, 0))) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR); + return 0; + } + + pkey = X509_get0_pubkey(x509); + if (!EVP_PKEY_get0_RSA(pkey)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* generate pre_master_secret */ + pmslen = SSL_MAX_MASTER_KEY_LENGTH; + if ((pms = OPENSSL_malloc(pmslen)) == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_RSA, ERR_R_MALLOC_FAILURE); + return 0; + } + + pms[0] = s->client_version >> 8; + pms[1] = s->client_version & 0xff; + if (RAND_bytes(pms + 2, pmslen - 2) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR); + goto end; + } + + /* encrypt pre_master_secret and output packet */ + if ((pctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_RSA, ERR_R_MALLOC_FAILURE); + goto end; + } + + if (EVP_PKEY_encrypt_init(pctx) <= 0 + || EVP_PKEY_encrypt(pctx, NULL, &enclen, pms, pmslen) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_RSA, ERR_R_EVP_LIB); + goto end; + } + + /* XXX: does NTLS RSA requires a 2 bytes length-prefix? */ + if (!WPACKET_allocate_bytes(pkt, enclen, &encdata) + || EVP_PKEY_encrypt(pctx, encdata, &enclen, pms, pmslen) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_RSA, SSL_R_BAD_RSA_ENCRYPT); + goto end; + } + + if (!WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR); + goto end; + } + + /* save local pre_master_secret */ + s->s3->tmp.pms = pms; + s->s3->tmp.pmslen = pmslen; + pms = NULL; + pmslen = 0; + + ret = 1; + +end: + OPENSSL_clear_free(pms, pmslen); + EVP_PKEY_CTX_free(pctx); + return ret; +} + +int ntls_construct_client_key_exchange_ntls(SSL *s, WPACKET *pkt) +{ + unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + + if (alg_k & SSL_kRSA) { + if (!ntls_construct_cke_rsa(s, pkt)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else if (alg_k & SSL_kSM2) { + if (!ntls_construct_cke_sm2(s, pkt)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else if (alg_k & (SSL_kSM2DHE)) { + if (!ntls_construct_cke_sm2dhe(s, pkt)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_NTLS_CONSTRUCT_CLIENT_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + return 1; + err: + return 0; +} + +int ntls_construct_cert_verify_ntls(SSL *s, WPACKET *pkt) +{ + EVP_PKEY *pkey = NULL; + const EVP_MD *md = EVP_sm3(); + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + EVP_MD_CTX *mctx2 = EVP_MD_CTX_new(); + EVP_PKEY_CTX *pctx = NULL; + size_t hdatalen = 0, siglen = 0; + void *hdata; + unsigned char *sig = NULL; + unsigned char out[EVP_MAX_MD_SIZE]; + size_t outlen = 0; + + /* Need to use SM3 calculate the message twice */ + if (s->cert->pkeys[SSL_PKEY_SM2_SIGN].privatekey == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_CONSTRUCT_CERT_VERIFY_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + pkey = s->cert->pkeys[SSL_PKEY_SM2_SIGN].privatekey; + if (pkey == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_CONSTRUCT_CERT_VERIFY_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (mctx == NULL || mctx2 == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_CONSTRUCT_CERT_VERIFY_NTLS, + ERR_R_MALLOC_FAILURE); + goto err; + } + + /* The only valid EC pkey in NTLS is SM2 */ + if (EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_CONSTRUCT_CERT_VERIFY_NTLS, + ERR_R_EVP_LIB); + goto err; + } + + hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata); + if (hdatalen <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_CONSTRUCT_CERT_VERIFY_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * XXX: This is silly. + * SM3 is called two times on the handshake_data + * Otherwise we could not handshake with other implementations, sigh... + */ + if (!EVP_DigestInit_ex(mctx2, md, NULL) + || !EVP_DigestUpdate(mctx2, hdata, hdatalen) + || !EVP_DigestFinal(mctx2, out, (unsigned int *)&outlen)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_CONSTRUCT_CERT_VERIFY_NTLS, + ERR_R_EVP_LIB); + goto err; + } + + siglen = EVP_PKEY_size(pkey); + sig = OPENSSL_malloc(siglen); + if (sig == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_CONSTRUCT_CERT_VERIFY_NTLS, + ERR_R_MALLOC_FAILURE); + goto err; + } + + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (pctx == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_CONSTRUCT_CERT_VERIFY_NTLS, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if (EVP_PKEY_CTX_set1_id(pctx, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LEN) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_CONSTRUCT_CERT_VERIFY_NTLS, + ERR_R_EVP_LIB); + goto err; + } + + EVP_MD_CTX_set_pkey_ctx(mctx, pctx); + + if (EVP_DigestSignInit(mctx, NULL, md, NULL, pkey) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_CONSTRUCT_CERT_VERIFY_NTLS, + ERR_R_EVP_LIB); + goto err; + } + + if (EVP_DigestSign(mctx, sig, &siglen, out, outlen) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_CONSTRUCT_CERT_VERIFY_NTLS, + ERR_R_EVP_LIB); + goto err; + } + + if (!WPACKET_sub_memcpy_u16(pkt, sig, siglen)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_CONSTRUCT_CERT_VERIFY_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* Digest cached records and discard handshake buffer */ + if (!ssl3_digest_cached_records(s, 0)) { + /* SSLfatal_ntls() already called */ + goto err; + } + + OPENSSL_free(sig); + EVP_MD_CTX_free(mctx); + EVP_MD_CTX_free(mctx2); + EVP_PKEY_CTX_free(pctx); + return 1; + err: + OPENSSL_free(sig); + EVP_MD_CTX_free(mctx); + EVP_MD_CTX_free(mctx2); + EVP_PKEY_CTX_free(pctx); + return 0; +} + +#endif diff --git a/ssl/statem_ntls/statem_ntls_srvr.c b/ssl/statem_ntls/statem_ntls_srvr.c new file mode 100644 index 000000000..5951a6365 --- /dev/null +++ b/ssl/statem_ntls/statem_ntls_srvr.c @@ -0,0 +1,1327 @@ +/* + * Copyright 2019 The BabaSSL Project Authors. All Rights Reserved. + */ + +#include +#include +#include "ssl_local_ntls.h" +#include "statem_local_ntls.h" +#include "internal/constant_time.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if (!defined OPENSSL_NO_NTLS) && (!defined OPENSSL_NO_SM2) \ + && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) +int ntls_construct_server_certificate_ntls(SSL *s, WPACKET *pkt) +{ + unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth; + + if (alg_a & SSL_aSM2) { + if (!ntls_output_cert_chain_ntls(s, pkt, SSL_PKEY_SM2_SIGN, SSL_PKEY_SM2_ENC)) + goto err; + } else if (alg_a & SSL_aRSA) { + if (!ntls_output_cert_chain_ntls(s, pkt, SSL_PKEY_RSA, SSL_PKEY_RSA)) + goto err; + } else { + goto err; + } + + return 1; + + err: + /* SSLfatal_ntls() already called */ + return 0; +} + +static int ntls_construct_ske_sm2dhe(SSL *s, WPACKET *pkt) +{ + int ret = 0; + X509 *x509; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *pctx = NULL; + unsigned char *encodedPoint = NULL; + int encodedlen; + EVP_MD_CTX *md_ctx = NULL; + char *id = "1234567812345678"; + size_t siglen; + size_t paramlen, paramoffset; + unsigned char *sigbytes1, *sigbytes2; + int curve_id; + + if (!WPACKET_get_total_written(pkt, ¶moffset)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* get signing cert and pkey */ + if (!(x509 = s->cert->pkeys[SSL_PKEY_SM2_SIGN].x509)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_INTERNAL_ERROR); + return 0; + } +#ifndef OPENSSL_NO_KEYLESS + if (s->keyless_ntls && s->keyless_again) + goto keyless_recover; +#endif +#ifndef OPENSSL_NO_LURK + if (s->lurk_ntls && s->lurk_again) + goto lurk_recover; +#endif + +#if !(defined(OPENSSL_NO_KEYLESS) && defined(OPENSSL_NO_LURK)) + if (0 +# ifndef OPENSSL_NO_KEYLESS + || s->keyless_ntls +# endif +# ifndef OPENSSL_NO_LURK + || s->lurk_ntls +# endif + ) + pkey = X509_get0_pubkey(s->cert->pkeys[SSL_PKEY_SM2_SIGN].x509); + else +#endif + pkey = s->cert->pkeys[SSL_PKEY_SM2_SIGN].privatekey; + if (pkey == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* check tmp pkey not set */ + if (s->s3->tmp.pkey != NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_INTERNAL_ERROR); + return 0; + } + + curve_id = tls1_shared_group(s, -2); + + if (!WPACKET_put_bytes_u8(pkt, NAMED_CURVE_TYPE) + || !WPACKET_put_bytes_u8(pkt, 0) + || !WPACKET_put_bytes_u8(pkt, curve_id)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* generate tmp pkey and output ECPoint */ + /* FIXME: curveid is fixed to 31 + if (!(curve_id = tls1_ec_nid2curve_id(NID_sm2p256v1))) + return 0; + */ + s->s3->tmp.pkey = ssl_generate_pkey_group(s, curve_id); + /* Generate a new key for this curve */ + if (s->s3->tmp.pkey == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* Encode the public key. */ + encodedlen = EVP_PKEY_get1_tls_encodedpoint(s->s3->tmp.pkey, + &encodedPoint); + if (encodedlen == 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_EVP_LIB); + goto err; + } + + if (!WPACKET_sub_memcpy_u8(pkt, encodedPoint, encodedlen)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!WPACKET_get_length(pkt, ¶mlen)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!(md_ctx = EVP_MD_CTX_new())) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_EVP_LIB); + goto err; + } + + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (pctx == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (EVP_PKEY_CTX_set1_id(pctx, id, strlen(id)) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_EVP_LIB); + goto err; + } + + EVP_MD_CTX_set_pkey_ctx(md_ctx, pctx);; + + /* sign digest of {client_random, server_random, sm2dhe_params} */ + if (EVP_DigestSignInit(md_ctx, NULL, EVP_sm3(), NULL, pkey) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_EVP_LIB); + goto err; + } + + if (EVP_DigestSignUpdate(md_ctx, &(s->s3->client_random[0]), + SSL3_RANDOM_SIZE) <= 0 + || EVP_DigestSignUpdate(md_ctx, &(s->s3->server_random[0]), + SSL3_RANDOM_SIZE) <= 0 + || EVP_DigestSignUpdate(md_ctx, s->init_buf->data + paramoffset, + paramlen) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_EVP_LIB); + goto err; + } + + if ((siglen = EVP_PKEY_size(pkey)) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_EVP_LIB); + goto err; + } + + if (!WPACKET_sub_reserve_bytes_u16(pkt, siglen, &sigbytes1)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_INTERNAL_ERROR); + goto err; + } + +#if !(defined(OPENSSL_NO_KEYLESS) && defined(OPENSSL_NO_LURK)) + if (0 +# ifndef OPENSSL_NO_KEYLESS + || s->keyless_ntls +# endif +# ifndef OPENSSL_NO_LURK + || s->lurk_ntls +# endif + ) + { + unsigned char md_buf[EVP_MAX_MD_SIZE]; + unsigned int mdlen = 0; + int keyless_ret = 0; + + if (EVP_DigestFinal(md_ctx, &(md_buf[0]), &mdlen) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, + ERR_R_INTERNAL_ERROR); + goto err; + } + +# ifndef OPENSSL_NO_KEYLESS + if (s->keyless_ntls) { + s->keyless_callback_param.data = md_buf; + s->keyless_callback_param.len = mdlen; + s->keyless_callback_param.type = SSL_KEYLESS_TYPE_SM2_SIGN_NTLS; + s->keyless_callback_param.cert_tag = SSL_SIGN_CERT; + s->keyless_recover_pos = sigbytes1; + s->keyless_recover_n = pkt->written; + + keyless_ret = s->keyless_callback(s, &s->keyless_callback_param); + + if (keyless_ret == 1) { + /* again or done */ + s->keyless_again = 1; + return 0; + } else if (keyless_ret == 0) { +keyless_recover: + siglen = s->keyless_result_len; + sigbytes1 = s->keyless_recover_pos; + pkt->curr = pkt->written = s->keyless_recover_n; + + memcpy(sigbytes1, s->keyless_result, siglen); + + if (s->keyless_again) + s->keyless_again = 0; + } else { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, + SSL_R_KEYLESS_ERROR); + goto err; + } + } else +# endif +# ifndef OPENSSL_NO_LURK + if (s->lurk && s->lurk_ntls) { + s->lurk_callback_param.data = md_buf; + s->lurk_callback_param.len = mdlen; + s->lurk_callback_param.type = SSL_LURK_QUERY_SM2_SIGN_NTLS; + s->lurk_callback_param.cert_tag = SSL_SIGN_CERT; + s->lurk_recover_pos = sigbytes1; + s->lurk_recover_n = pkt->written; + + keyless_ret = s->lurk_callback(s, &s->lurk_callback_param); + + if (keyless_ret == 1) { + /* again or done */ + s->lurk_again = 1; + return 0; + } else if (keyless_ret == 0) { +lurk_recover: + siglen = s->lurk_result_len; + sigbytes1 = s->lurk_recover_pos; + pkt->curr = pkt->written = s->lurk_recover_n; + + memcpy(sigbytes1, s->lurk_result, siglen); + + if (s->lurk_again) + s->lurk_again = 0; + } else { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, + SSL_R_KEYLESS_ERROR); + goto err; + } + } +# else + { + } +# endif + } else +#endif + { + if (EVP_DigestSignFinal(md_ctx, sigbytes1, (size_t *)&siglen) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_EVP_LIB); + goto err; + } + } + + if (!WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2) + || sigbytes1 != sigbytes2) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_INTERNAL_ERROR); + goto err; + } + + ret = 1; + + err: + if (!ret && s->s3->tmp.pkey) { + EVP_PKEY_free(s->s3->tmp.pkey); + s->s3->tmp.pkey = NULL; + } + OPENSSL_free(encodedPoint); + EVP_MD_CTX_free(md_ctx); + EVP_PKEY_CTX_free(pctx); + return ret; +} + +static int ntls_construct_ske_sm2(SSL *s, WPACKET *pkt) +{ + int ret = 0, n; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *pctx = NULL; + X509 *x509; + unsigned char *buf = NULL, *p = NULL; + EVP_MD_CTX *md_ctx = NULL; + char *id = "1234567812345678"; + size_t siglen; + unsigned char *sigbytes1, *sigbytes2; + +#ifndef OPENSSL_NO_KEYLESS + if (s->keyless_ntls && s->keyless_again) + goto keyless_recover; +#endif +#ifndef OPENSSL_NO_LURK + if (s->lurk_ntls && s->lurk_again) + goto lurk_recover; +#endif + +#if !(defined(OPENSSL_NO_KEYLESS) && defined(OPENSSL_NO_LURK)) + if (0 +# ifndef OPENSSL_NO_KEYLESS + || s->keyless_ntls +# endif +# ifndef OPENSSL_NO_LURK + || s->lurk_ntls +# endif + ) + pkey = X509_get0_pubkey(s->cert->pkeys[SSL_PKEY_SM2_SIGN].x509); + else +#endif + pkey = s->cert->pkeys[SSL_PKEY_SM2_SIGN].privatekey; + /* prepare sign key */ + if (pkey == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* prepare encrypt cert buffer */ + if (!(x509 = s->cert->pkeys[SSL_PKEY_SM2_ENC].x509)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2, ERR_R_INTERNAL_ERROR); + return 0; + } + + if ((n = i2d_X509(x509, NULL)) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* + * XXX: This is very stupid since the standard doesn't mention the + * 3 bytes for length + */ + buf = OPENSSL_malloc(n + 3); + if (buf == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2, ERR_R_MALLOC_FAILURE); + return 0; + } + + p = buf; + l2n3(n, p); + + if ((n = i2d_X509(x509, &p)) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2, ERR_R_INTERNAL_ERROR); + goto end; + } + + n += 3; + + md_ctx = EVP_MD_CTX_new(); + if (md_ctx == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2, ERR_R_MALLOC_FAILURE); + goto end; + } + + if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2, ERR_R_EVP_LIB); + goto end; + } + + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (pctx == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2, ERR_R_MALLOC_FAILURE); + goto end; + } + + if (EVP_PKEY_CTX_set1_id(pctx, id, strlen(id)) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2, ERR_R_EVP_LIB); + goto end; + } + + EVP_MD_CTX_set_pkey_ctx(md_ctx, pctx); + + /* generate signature */ + if ((siglen = EVP_PKEY_size(pkey)) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2, ERR_R_EVP_LIB); + goto end; + } + + if (!WPACKET_sub_reserve_bytes_u16(pkt, siglen, &sigbytes1)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2, ERR_R_INTERNAL_ERROR); + goto end; + } + + /* sign digest of {client_random, server_random, enc_cert} */ + if (EVP_DigestSignInit(md_ctx, NULL, EVP_sm3(), NULL, pkey) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2, ERR_R_EVP_LIB); + goto end; + } + + if (EVP_DigestSignUpdate(md_ctx, &(s->s3->client_random[0]), + SSL3_RANDOM_SIZE) <= 0 + || EVP_DigestSignUpdate(md_ctx, &(s->s3->server_random[0]), + SSL3_RANDOM_SIZE) <= 0 + || EVP_DigestSignUpdate(md_ctx, buf, n) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2, ERR_R_EVP_LIB); + goto end; + } + +#if !(defined(OPENSSL_NO_KEYLESS) && defined(OPENSSL_NO_LURK)) + if (0 +# ifndef OPENSSL_NO_KEYLESS + || s->keyless_ntls +# endif +# ifndef OPENSSL_NO_LURK + || s->lurk_ntls +# endif + ) + { + unsigned char md_buf[EVP_MAX_MD_SIZE]; + unsigned int mdlen = 0; + int keyless_ret = 0; + + if (EVP_DigestFinal(md_ctx, &(md_buf[0]), &mdlen) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2, + ERR_R_INTERNAL_ERROR); + goto end; + } + +# ifndef OPENSSL_NO_KEYLESS + if (s->keyless_ntls) { + s->keyless_callback_param.data = md_buf; + s->keyless_callback_param.len = mdlen; + s->keyless_callback_param.type = SSL_KEYLESS_TYPE_SM2_SIGN_NTLS; + s->keyless_callback_param.cert_tag = SSL_SIGN_CERT; + s->keyless_recover_pos = sigbytes1; + s->keyless_recover_n = pkt->written; + + keyless_ret = s->keyless_callback(s, &s->keyless_callback_param); + + if (keyless_ret == 1) { + /* again or done */ + s->keyless_again = 1; + return 0; + } else if (keyless_ret == 0) { +keyless_recover: + siglen = s->keyless_result_len; + sigbytes1 = s->keyless_recover_pos; + pkt->curr = pkt->written = s->keyless_recover_n; + + memcpy(sigbytes1, s->keyless_result, siglen); + + if (s->keyless_again) + s->keyless_again = 0; + } else { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_CONSTRUCT_SKE_SM2, + SSL_R_KEYLESS_ERROR); + goto end; + } + } else +# endif +# ifndef OPENSSL_NO_LURK + if (s->lurk && s->lurk_ntls) { + s->lurk_callback_param.data = md_buf; + s->lurk_callback_param.len = mdlen; + s->lurk_callback_param.type = SSL_LURK_QUERY_SM2_SIGN_NTLS; + s->lurk_callback_param.cert_tag = SSL_SIGN_CERT; + s->lurk_recover_pos = sigbytes1; + s->lurk_recover_n = pkt->written; + + keyless_ret = s->lurk_callback(s, &s->lurk_callback_param); + + if (keyless_ret == 1) { + /* again or done */ + s->lurk_again = 1; + return 0; + } else if (keyless_ret == 0) { +lurk_recover: + siglen = s->lurk_result_len; + sigbytes1 = s->lurk_recover_pos; + pkt->curr = pkt->written = s->lurk_recover_n; + + memcpy(sigbytes1, s->lurk_result, siglen); + + if (s->lurk_again) + s->lurk_again = 0; + } else { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_CONSTRUCT_SKE_SM2, + SSL_R_KEYLESS_ERROR); + goto end; + } + } +# else + { + } +# endif + + } else +#endif + { + if (EVP_DigestSignFinal(md_ctx, sigbytes1, &siglen) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2, ERR_R_EVP_LIB); + goto end; + } + } + + if (!WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2) + || sigbytes1 != sigbytes2) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_SM2, ERR_R_INTERNAL_ERROR); + goto end; + } + + ret = 1; + + end: + OPENSSL_free(buf); + EVP_MD_CTX_free(md_ctx); + EVP_PKEY_CTX_free(pctx); + return ret; +} + +static int ntls_construct_ske_rsa(SSL *s, WPACKET *pkt) +{ + int ret = 0; + EVP_PKEY *pkey; + X509 *x509; + const EVP_MD *md; + EVP_MD_CTX *md_ctx = NULL; + unsigned char *buf = NULL, *p = NULL; + int n; + unsigned int siglen; + unsigned char *sigbytes1, *sigbytes2; + + /* get digest algor */ + if (!ssl_cipher_get_evp(s->session, NULL, &md, NULL, NULL, NULL, 0)) + return 0; + + /* FIXME: RSA 2 certificate */ + /* get sign pkey */ + if (!(pkey = s->cert->pkeys[SSL_PKEY_RSA].privatekey)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_RSA, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* create encryption cert packet */ + if (!(x509 = s->cert->pkeys[SSL_PKEY_SM2_ENC].x509)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_RSA, ERR_R_INTERNAL_ERROR); + return 0; + } + + if ((n = i2d_X509(x509, NULL)) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_RSA, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* XXX: Should the heading 3 bytes be necessary? */ + buf = OPENSSL_malloc(n + 3); + if (buf == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_RSA, ERR_R_MALLOC_FAILURE); + return 0; + } + + p = &(buf[3]); + + if ((n = i2d_X509(x509, &p)) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_RSA, ERR_R_INTERNAL_ERROR); + goto end; + } + + l2n3(n, buf); + buf -= 3; + + /* generate signature */ + if (!(md_ctx = EVP_MD_CTX_new())) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_RSA, ERR_R_MALLOC_FAILURE); + goto end; + } + + if (EVP_SignInit_ex(md_ctx, md, NULL) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_RSA, ERR_R_EVP_LIB); + goto end; + } + + if (EVP_SignUpdate(md_ctx, &(s->s3->client_random[0]), + SSL3_RANDOM_SIZE) <= 0 + || EVP_SignUpdate(md_ctx, &(s->s3->server_random[0]), + SSL3_RANDOM_SIZE) <= 0 + || EVP_SignUpdate(md_ctx, buf, n) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_RSA, ERR_R_EVP_LIB); + goto end; + } + + siglen = EVP_PKEY_size(pkey); + + if (!WPACKET_sub_reserve_bytes_u16(pkt, siglen, &sigbytes1)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_RSA, ERR_R_INTERNAL_ERROR); + goto end; + } + + if (EVP_SignFinal(md_ctx, sigbytes1, &siglen, pkey) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_RSA, ERR_R_EVP_LIB); + goto end; + } + + if (!WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2) + || sigbytes1 != sigbytes2) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_CONSTRUCT_SKE_RSA, ERR_R_INTERNAL_ERROR); + goto end; + } + + end: + EVP_MD_CTX_free(md_ctx); + OPENSSL_free(buf); + return ret; +} + +int ntls_construct_server_key_exchange_ntls(SSL *s, WPACKET *pkt) +{ + unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + + if (alg_k & SSL_kSM2) { + if (!ntls_construct_ske_sm2(s, pkt)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else if (alg_k & SSL_kSM2DHE) { + if (!ntls_construct_ske_sm2dhe(s, pkt)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else if (alg_k & SSL_kRSA) { + if (!ntls_construct_ske_rsa(s, pkt)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_NTLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + return 1; + + err: + return 0; +} + +static int ntls_process_cke_sm2dhe(SSL *s, PACKET *pkt) +{ + int ret = 0; + const unsigned char *ecparams; + PACKET encoded_pt; + EVP_PKEY *skey = s->s3->tmp.pkey; + EVP_PKEY *ckey = NULL; + +#ifndef OPENSSL_NO_KEYLESS + if (s->keyless_ntls && s->keyless_again) + goto keyless_recover; +#endif +#ifndef OPENSSL_NO_LURK + if (s->lurk_ntls && s->lurk_again) + goto keyless_recover; +#endif + + if ((skey = s->s3->tmp.pkey) == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_CKE_SM2DHE, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!PACKET_get_bytes(pkt, &ecparams, 3)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_NTLS_PROCESS_CKE_SM2DHE, SSL_R_LENGTH_TOO_SHORT); + return 0; + } + + /* parse ECPoint */ + if (!PACKET_get_length_prefixed_1(pkt, &encoded_pt) + || PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_NTLS_PROCESS_CKE_SM2DHE, SSL_R_LENGTH_MISMATCH); + return 0; + } + + if (!(ckey = EVP_PKEY_new())) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_CKE_SM2DHE, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (EVP_PKEY_copy_parameters(ckey, skey) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_CKE_SM2DHE, ERR_R_EVP_LIB); + goto end; + } + + if (!EVP_PKEY_set1_tls_encodedpoint(ckey, PACKET_data(&encoded_pt), + PACKET_remaining(&encoded_pt))) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_NTLS_PROCESS_CKE_SM2DHE, ERR_R_EVP_LIB); + goto end; + } +#if !(defined(OPENSSL_NO_KEYLESS) && defined(OPENSSL_NO_LURK)) +keyless_recover: +#endif + if (!ntls_sm2_derive_ntls(s, skey, ckey)) { +#ifndef OPENSSL_NO_KEYLESS + if (s->keyless_ntls && s->keyless_again) + goto end; +#endif +#ifndef OPENSSL_NO_LURK + if (s->lurk_ntls && s->lurk_again) + goto end; +#endif + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_NTLS_PROCESS_CKE_SM2DHE, ERR_R_INTERNAL_ERROR); + goto end; + } + + ret = 1; + + end: + EVP_PKEY_free(s->s3->tmp.pkey); + s->s3->tmp.pkey = NULL; + EVP_PKEY_free(ckey); + + return ret; +} + +static int ntls_process_cke_sm2(SSL *s, PACKET *pkt) +{ + int ret = 0; + EVP_PKEY *pkey = NULL; + PACKET enced_pms; + EVP_PKEY_CTX *pctx = NULL; + size_t pmslen; + unsigned char pms[SSL_MAX_MASTER_KEY_LENGTH]; + +#ifndef OPENSSL_NO_KEYLESS + if (s->keyless_ntls && s->keyless_again) + goto keyless_recover; +#endif +#ifndef OPENSSL_NO_LURK + if (s->lurk_ntls && s->lurk_again) + goto lurk_recover; +#endif + +#if !(defined(OPENSSL_NO_KEYLESS) && defined(OPENSSL_NO_LURK)) + if (0 +# ifndef OPENSSL_NO_KEYLESS + || s->keyless_ntls +# endif +# ifndef OPENSSL_NO_LURK + || s->lurk_ntls +# endif + ) + pkey = X509_get0_pubkey(s->cert->pkeys[SSL_PKEY_SM2_ENC].x509); + else +#endif + pkey = s->cert->pkeys[SSL_PKEY_SM2_ENC].privatekey; + + /* prepare decryption key */ + if (pkey == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_CKE_SM2, SSL_R_MISSING_SM2_ENC_CERTIFICATE); + return 0; + } + + /* set pkey to SM2 */ + if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_CKE_SM2, ERR_R_EVP_LIB); + goto end; + } + + /* + * XXX: + * This is very unclear. The standard TLS protocol requries no u16 len + * bytes before the encrypted PMS value. The NTLS specification is also + * very blurry on this. But major implementations require the 2 bytes + * length field (which is redundant), otherwise handshake will fail... + */ + /* parse encrypted pre_master_secret */ + if (!PACKET_get_length_prefixed_2(pkt, &enced_pms) + || PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_NTLS_PROCESS_CKE_SM2, SSL_R_LENGTH_MISMATCH); + return 0; + } + +#if !(defined(OPENSSL_NO_KEYLESS) && defined(OPENSSL_NO_LURK)) + if (0 +# ifndef OPENSSL_NO_KEYLESS + || s->keyless_ntls +# endif +# ifndef OPENSSL_NO_LURK + || s->lurk_ntls +# endif + ) + { + int keyless_ret = 0; +# ifndef OPENSSL_NO_KEYLESS + if (s->keyless_ntls) { + s->keyless_callback_param.data = PACKET_data(&enced_pms); + s->keyless_callback_param.len = PACKET_remaining(&enced_pms); + s->keyless_callback_param.type = SSL_KEYLESS_TYPE_ECC_ENC_DECRYPT; + s->keyless_callback_param.cert_tag = SSL_ENC_CERT; + + keyless_ret = s->keyless_callback(s, &s->keyless_callback_param); + + if (keyless_ret == 1) { + /* again or done */ + s->keyless_again = 1; + return 0; + } else if (keyless_ret == 0) { +keyless_recover: + pmslen = s->keyless_result_len; + memcpy(pms, s->keyless_result, s->keyless_result_len); + + if (s->keyless_again) + s->keyless_again = 0; + } else { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_PROCESS_CKE_SM2, + SSL_R_KEYLESS_ERROR); + goto end; + } + } else +# endif +# ifndef OPENSSL_NO_LURK + if (s->lurk && s->lurk_ntls) { + s->lurk_callback_param.data = PACKET_data(&enced_pms); + s->lurk_callback_param.len = PACKET_remaining(&enced_pms); + s->lurk_callback_param.type = SSL_LURK_QUERY_ECC_ENC_DECRYPT; + s->lurk_callback_param.cert_tag = SSL_ENC_CERT; + + keyless_ret = s->lurk_callback(s, &s->lurk_callback_param); + + if (keyless_ret == 1) { + /* again or done */ + s->lurk_again = 1; + return 0; + } else if (keyless_ret == 0) { +lurk_recover: + pmslen = s->lurk_result_len; + memcpy(pms, s->lurk_result, s->lurk_result_len); + + if (s->lurk_again) + s->lurk_again = 0; + } else { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_PROCESS_CKE_SM2, + SSL_R_KEYLESS_ERROR); + goto end; + } + } +# else + { + } +# endif + } else +#endif + { + /* decrypt encrypted pre_master_secret */ + if ((pctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_CKE_SM2, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!EVP_PKEY_decrypt_init(pctx)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_CKE_SM2, ERR_R_EVP_LIB); + goto end; + } + + pmslen = sizeof(pms); + + if (!EVP_PKEY_decrypt(pctx, pms, &pmslen, + PACKET_data(&enced_pms), + PACKET_remaining(&enced_pms))) { + SSLfatal_ntls(s, SSL_AD_DECRYPT_ERROR, + SSL_F_NTLS_PROCESS_CKE_SM2, SSL_R_DECRYPTION_FAILED); + goto end; + } + } + + if (pmslen != SSL_MAX_MASTER_KEY_LENGTH) { + SSLfatal_ntls(s, SSL_AD_DECRYPT_ERROR, + SSL_F_NTLS_PROCESS_CKE_SM2, SSL_R_DECRYPTION_FAILED); + goto end; + } + + /* XXX: don't care about versions in PMS */ + + /* generate master_secret */ + if (!ssl_generate_master_secret(s, pms, pmslen, 0)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_CKE_SM2, ERR_R_EVP_LIB); + goto end; + } + + ret = 1; + end: + EVP_PKEY_CTX_free(pctx); + OPENSSL_cleanse(pms, sizeof(pms)); + + return ret; +} + +static int ntls_process_cke_rsa(SSL *s, PACKET *pkt) +{ + unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH]; + int decrypt_len; + unsigned char decrypt_good, version_good; + size_t j, padding_len; + PACKET enc_premaster; + RSA *rsa = NULL; + unsigned char *rsa_decrypt = NULL; + int ret = 0; + + rsa = EVP_PKEY_get0_RSA(s->cert->pkeys[SSL_PKEY_RSA].privatekey); + if (rsa == NULL) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_NTLS_PROCESS_CKE_RSA, SSL_R_MISSING_RSA_CERTIFICATE); + return 0; + } + + if (!PACKET_get_length_prefixed_2(pkt, &enc_premaster) + || PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_NTLS_PROCESS_CKE_RSA, SSL_R_LENGTH_MISMATCH); + return 0; + } + + /* + * We want to be sure that the plaintext buffer size makes it safe to + * iterate over the entire size of a premaster secret + * (SSL_MAX_MASTER_KEY_LENGTH). Reject overly short RSA keys because + * their ciphertext cannot accommodate a premaster secret anyway. + */ + if (RSA_size(rsa) < SSL_MAX_MASTER_KEY_LENGTH) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_CKE_RSA, RSA_R_KEY_SIZE_TOO_SMALL); + return 0; + } + + rsa_decrypt = OPENSSL_malloc(RSA_size(rsa)); + if (rsa_decrypt == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_CKE_RSA, ERR_R_MALLOC_FAILURE); + return 0; + } + + /* + * We must not leak whether a decryption failure occurs because of + * Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see RFC 2246, + * section 7.4.7.1). The code follows that advice of the TLS RFC and + * generates a random premaster secret for the case that the decrypt + * fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1 + */ + + if (RAND_bytes(rand_premaster_secret, sizeof(rand_premaster_secret)) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_CKE_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * Decrypt with no padding. PKCS#1 padding will be removed as part of + * the timing-sensitive code below. + */ + decrypt_len = RSA_private_decrypt(PACKET_remaining(&enc_premaster), + PACKET_data(&enc_premaster), + rsa_decrypt, rsa, RSA_NO_PADDING); + if (decrypt_len < 0) { + SSLfatal_ntls(s, SSL_AD_DECRYPT_ERROR, + SSL_F_NTLS_PROCESS_CKE_RSA, SSL_R_DECRYPTION_FAILED); + goto err; + } + + /* Check the padding. See RFC 3447, section 7.2.2. */ + + /* + * The smallest padded premaster is 11 bytes of overhead. Small keys + * are publicly invalid, so this may return immediately. This ensures + * PS is at least 8 bytes. + */ + if (decrypt_len < 11 + SSL_MAX_MASTER_KEY_LENGTH) { + SSLfatal_ntls(s, SSL_AD_DECRYPT_ERROR, + SSL_F_NTLS_PROCESS_CKE_RSA, SSL_R_DECRYPTION_FAILED); + goto err; + } + + padding_len = decrypt_len - SSL_MAX_MASTER_KEY_LENGTH; + + decrypt_good = constant_time_eq_int_8(rsa_decrypt[0], 0) & + constant_time_eq_int_8(rsa_decrypt[1], 2); + + for (j = 2; j < padding_len - 1; j++) + decrypt_good &= ~constant_time_is_zero_8(rsa_decrypt[j]); + + decrypt_good &= constant_time_is_zero_8(rsa_decrypt[padding_len - 1]); + + /* + * If the version in the decrypted pre-master secret is correct then + * version_good will be 0xff, otherwise it'll be zero. The + * Klima-Pokorny-Rosa extension of Bleichenbacher's attack + * (http://eprint.iacr.org/2003/052/) exploits the version number + * check as a "bad version oracle". Thus version checks are done in + * constant time and are treated like any other decryption error. + */ + version_good = constant_time_eq_8(rsa_decrypt[padding_len], + (unsigned)(s->client_version >> 8)); + version_good &= constant_time_eq_8(rsa_decrypt[padding_len + 1], + (unsigned)(s->client_version & 0xff)); + + /* + * The premaster secret must contain the same version number as the + * ClientHello to detect version rollback attacks (strangely, the + * protocol does not offer such protection for DH ciphersuites). + * However, buggy clients exist that send the negotiated protocol + * version instead if the server does not support the requested + * protocol version. If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such + * clients. + */ + if (s->options & SSL_OP_TLS_ROLLBACK_BUG) { + unsigned char workaround_good; + workaround_good = constant_time_eq_8(rsa_decrypt[padding_len], + (unsigned)(s->version >> 8)); + workaround_good &= + constant_time_eq_8(rsa_decrypt[padding_len + 1], + (unsigned)(s->version & 0xff)); + version_good |= workaround_good; + } + + /* + * Both decryption and version must be good for decrypt_good to + * remain non-zero (0xff). + */ + decrypt_good &= version_good; + + /* + * Now copy rand_premaster_secret over from p using + * decrypt_good_mask. If decryption failed, then p does not + * contain valid plaintext, however, a check above guarantees + * it is still sufficiently large to read from. + */ + for (j = 0; j < sizeof(rand_premaster_secret); j++) { + rsa_decrypt[padding_len + j] = constant_time_select_8( + decrypt_good, rsa_decrypt[padding_len + j], + rand_premaster_secret[j] + ); + } + + if (!ssl_generate_master_secret(s, rsa_decrypt + padding_len, + sizeof(rand_premaster_secret), 0)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_NTLS_PROCESS_CKE_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + + ret = 1; + err: + OPENSSL_free(rsa_decrypt); + return ret; +} + +MSG_PROCESS_RETURN ntls_process_client_key_exchange_ntls(SSL *s, PACKET *pkt) +{ + unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + + if (alg_k & SSL_kRSA) { + if (!ntls_process_cke_rsa(s, pkt)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else if (alg_k & SSL_kSM2) { + if (!ntls_process_cke_sm2(s, pkt)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else if (alg_k & SSL_kSM2DHE) { + if (!ntls_process_cke_sm2dhe(s, pkt)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_NTLS_PROCESS_CLIENT_KEY_EXCHANGE_NTLS, + SSL_R_UNKNOWN_CIPHER_TYPE); + goto err; + } + + return MSG_PROCESS_CONTINUE_PROCESSING; + + err: + return MSG_PROCESS_ERROR; +} + +static int ntls_process_cv_sm2dhe(SSL *s, PACKET *pkt) +{ + EVP_PKEY *pkey = NULL; + const unsigned char *data; + unsigned int len; + X509 *peer; + const EVP_MD *md = NULL; + size_t hdatalen = 0; + void *hdata; + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + EVP_MD_CTX *mctx2 = EVP_MD_CTX_new(); + EVP_PKEY_CTX *pctx = NULL; + int j, ret = 0; + unsigned char out[EVP_MAX_MD_SIZE]; + size_t outlen = 0; + + if (mctx == NULL || mctx2 == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_PROCESS_CV_SM2DHE, + ERR_R_MALLOC_FAILURE); + goto err; + } + + /* + * XXX: Don't forget that session->peer stores the client signing + * certificate... + */ + peer = s->session->peer; + pkey = X509_get0_pubkey(peer); + if (pkey == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_PROCESS_CV_SM2DHE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (ssl_cert_lookup_by_pkey(pkey, NULL) == NULL) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_NTLS_PROCESS_CV_SM2DHE, + SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE); + goto err; + } + + /* + * SM2DHE uses no SIGALG bytes, and we don't need to decide peer sigalg + * because in NTLS SM2, hash algorithm is fixed to SM3 + */ + md = EVP_sm3(); + + /* The only valid EC pkey in NTLS is SM2 */ + if (EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_PROCESS_CV_SM2DHE, + ERR_R_EVP_LIB); + goto err; + } + +#ifdef SSL_DEBUG + if (SSL_USE_SIGALGS(s)) + fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md)); +#endif + + if (!PACKET_get_net_2(pkt, &len)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_NTLS_PROCESS_CV_SM2DHE, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + j = EVP_PKEY_size(pkey); + if (((int)len > j) || ((int)PACKET_remaining(pkt) > j) + || (PACKET_remaining(pkt) == 0)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_NTLS_PROCESS_CV_SM2DHE, + SSL_R_WRONG_SIGNATURE_SIZE); + goto err; + } + + if (!PACKET_get_bytes(pkt, &data, len)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_NTLS_PROCESS_CV_SM2DHE, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata); + if (hdatalen <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_PROCESS_CV_SM2DHE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * XXX: This is silly. + * SM3 is called two times on the handshake_data + * Otherwise we could not handshake with other implementations, sigh... + */ + if (!EVP_DigestInit_ex(mctx2, md, NULL) + || !EVP_DigestUpdate(mctx2, hdata, hdatalen) + || !EVP_DigestFinal(mctx2, out, (unsigned int *)&outlen)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_PROCESS_CV_SM2DHE, + ERR_R_EVP_LIB); + goto err; + } + +#ifdef SSL_DEBUG + fprintf(stderr, "Using client verify alg %s\n", EVP_MD_name(md)); + fprintf(stderr, "EVP_PKEY type: %s\n", OBJ_nid2ln(EVP_PKEY_id(pkey))); +#endif + + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (pctx == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_PROCESS_CV_SM2DHE, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if (EVP_PKEY_CTX_set1_id(pctx, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LEN) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_PROCESS_CV_SM2DHE, + ERR_R_EVP_LIB); + goto err; + } + + EVP_MD_CTX_set_pkey_ctx(mctx, pctx); + + if (EVP_DigestVerifyInit(mctx, NULL, md, NULL, pkey) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_NTLS_PROCESS_CV_SM2DHE, + ERR_R_EVP_LIB); + goto err; + } + + ret = EVP_DigestVerify(mctx, data, len, out, outlen); + if (ret <= 0) { + SSLfatal_ntls(s, SSL_AD_DECRYPT_ERROR, SSL_F_NTLS_PROCESS_CV_SM2DHE, + SSL_R_BAD_SIGNATURE); + goto err; + } + + ret = 1; + err: + EVP_MD_CTX_free(mctx2); + EVP_MD_CTX_free(mctx); + EVP_PKEY_CTX_free(pctx); + return ret; +} + +MSG_PROCESS_RETURN ntls_process_cert_verify_ntls(SSL *s, PACKET *pkt) +{ + MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR; + unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + + if (alg_k & SSL_kSM2DHE) { + if (!ntls_process_cv_sm2dhe(s, pkt)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_NTLS_PROCESS_CERT_VERIFY_NTLS, + SSL_R_UNKNOWN_CIPHER_TYPE); + goto err; + } + + ret = MSG_PROCESS_CONTINUE_READING; + + err: + BIO_free(s->s3->handshake_buffer); + s->s3->handshake_buffer = NULL; + return ret; +} + +#endif diff --git a/ssl/statem_ntls/statem_srvr.c b/ssl/statem_ntls/statem_srvr.c new file mode 100644 index 000000000..8e690d72a --- /dev/null +++ b/ssl/statem_ntls/statem_srvr.c @@ -0,0 +1,3442 @@ +/* + * Copyright 2019 The BabaSSL Project Authors. All Rights Reserved. + */ + +#include +#include "ssl_local_ntls.h" +#include "statem_local_ntls.h" +#include "internal/constant_time.h" +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if (!defined OPENSSL_NO_NTLS) && (!defined OPENSSL_NO_SM2) \ + && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) + +# define TICKET_NONCE_SIZE 8 + +static int tls_construct_encrypted_extensions(SSL *s, WPACKET *pkt); + +/* + * ossl_statem_server_read_transition_ntls() encapsulates the logic for the allowed + * handshake state transitions when the server is reading messages from the + * client. The message type that the client has sent is provided in |mt|. The + * current state is in |s->statem.hand_state|. + * + * Return values are 1 for success (transition allowed) and 0 on error + * (transition not allowed) + */ +int ossl_statem_server_read_transition_ntls(SSL *s, int mt) +{ + OSSL_STATEM *st = &s->statem; + + switch (st->hand_state) { + default: + break; + + case TLS_ST_BEFORE: + case TLS_ST_OK: + if (mt == SSL3_MT_CLIENT_HELLO) { + st->hand_state = TLS_ST_SR_CLNT_HELLO; + return 1; + } + break; + + case TLS_ST_SW_SRVR_DONE: + /* + * If we get a CKE message after a ServerDone then either + * 1) We didn't request a Certificate + * OR + * 2) If we did request one then + * a) We allow no Certificate to be returned + * AND + * b) We are running SSL3 (in TLS1.0+ the client must return a 0 + * list if we requested a certificate) + */ + if (mt == SSL3_MT_CLIENT_KEY_EXCHANGE) { + if (s->s3->tmp.cert_request) { + if (s->version == SSL3_VERSION) { + if ((s->verify_mode & SSL_VERIFY_PEER) + && (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) { + /* + * This isn't an unexpected message as such - we're just + * not going to accept it because we require a client + * cert. + */ + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION_NTLS, + SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); + return 0; + } + st->hand_state = TLS_ST_SR_KEY_EXCH; + return 1; + } + } else { + st->hand_state = TLS_ST_SR_KEY_EXCH; + return 1; + } + } else if (s->s3->tmp.cert_request) { + if (mt == SSL3_MT_CERTIFICATE) { + st->hand_state = TLS_ST_SR_CERT; + return 1; + } + } + break; + + case TLS_ST_SR_CERT: + if (mt == SSL3_MT_CLIENT_KEY_EXCHANGE) { + st->hand_state = TLS_ST_SR_KEY_EXCH; + return 1; + } + break; + + case TLS_ST_SR_KEY_EXCH: + /* + * We should only process a CertificateVerify message if we have + * received a Certificate from the client. If so then |s->session->peer| + * will be non NULL. In some instances a CertificateVerify message is + * not required even if the peer has sent a Certificate (e.g. such as in + * the case of static DH). In that case |st->no_cert_verify| should be + * set. + */ + if (s->session->peer == NULL || st->no_cert_verify) { + if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) { + /* + * For the ECDH ciphersuites when the client sends its ECDH + * pub key in a certificate, the CertificateVerify message is + * not sent. Also for GOST ciphersuites when the client uses + * its key from the certificate for key exchange. + */ + st->hand_state = TLS_ST_SR_CHANGE; + return 1; + } + } else { + if (mt == SSL3_MT_CERTIFICATE_VERIFY) { + st->hand_state = TLS_ST_SR_CERT_VRFY; + return 1; + } + } + break; + + case TLS_ST_SR_CERT_VRFY: + if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) { + st->hand_state = TLS_ST_SR_CHANGE; + return 1; + } + break; + + case TLS_ST_SR_CHANGE: +# ifndef OPENSSL_NO_NEXTPROTONEG + if (s->s3->npn_seen) { + if (mt == SSL3_MT_NEXT_PROTO) { + st->hand_state = TLS_ST_SR_NEXT_PROTO; + return 1; + } + } else { +# endif + if (mt == SSL3_MT_FINISHED) { + st->hand_state = TLS_ST_SR_FINISHED; + return 1; + } +# ifndef OPENSSL_NO_NEXTPROTONEG + } +# endif + break; + +# ifndef OPENSSL_NO_NEXTPROTONEG + case TLS_ST_SR_NEXT_PROTO: + if (mt == SSL3_MT_FINISHED) { + st->hand_state = TLS_ST_SR_FINISHED; + return 1; + } + break; +# endif + + case TLS_ST_SW_FINISHED: + if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) { + st->hand_state = TLS_ST_SR_CHANGE; + return 1; + } + break; + } + + /* No valid transition found */ + SSLfatal_ntls(s, SSL3_AD_UNEXPECTED_MESSAGE, + SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION_NTLS, + SSL_R_UNEXPECTED_MESSAGE); + return 0; +} + +/* + * Should we send a ServerKeyExchange message? + * + * Valid return values are: + * 1: Yes + * 0: No + */ +static int send_server_key_exchange(SSL *s) +{ + return 1; +} + +/* + * Should we send a CertificateRequest message? + * + * Valid return values are: + * 1: Yes + * 0: No + */ +int send_certificate_request_ntls(SSL *s) +{ + if ( + /* don't request cert unless asked for it: */ + s->verify_mode & SSL_VERIFY_PEER + /* + * if SSL_VERIFY_CLIENT_ONCE is set, don't request cert + * a second time: + */ + && (s->certreqs_sent < 1 || + !(s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) + /* + * never request cert in anonymous ciphersuites (see + * section "Certificate request" in SSL 3 drafts and in + * RFC 2246): + */ + && (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) + /* + * ... except when the application insists on + * verification (against the specs, but statem_clnt.c accepts + * this for SSL 3) + */ + || (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) + /* don't request certificate for SRP auth */ + && !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aSRP) + /* + * With normal PSK Certificates and Certificate Requests + * are omitted + */ + && !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK)) { + return 1; + } + + return 0; +} + +/* + * ossl_statem_server_write_transition_ntls() works out what handshake state to move + * to next when the server is writing messages to be sent to the client. + */ +WRITE_TRAN ossl_statem_server_write_transition_ntls(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + + /* + * Note that before the ClientHello we don't know what version we are going + * to negotiate yet, so we don't take this branch until later + */ + + switch (st->hand_state) { + default: + /* Shouldn't happen */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION_NTLS, + ERR_R_INTERNAL_ERROR); + return WRITE_TRAN_ERROR; + + case TLS_ST_OK: + if (st->request_state == TLS_ST_SW_HELLO_REQ) { + /* We must be trying to renegotiate */ + st->hand_state = TLS_ST_SW_HELLO_REQ; + st->request_state = TLS_ST_BEFORE; + return WRITE_TRAN_CONTINUE; + } + /* Must be an incoming ClientHello */ + if (!tls_setup_handshake_ntls(s)) { + /* SSLfatal_ntls() already called */ + return WRITE_TRAN_ERROR; + } + /* Fall through */ + + case TLS_ST_BEFORE: + /* Just go straight to trying to read from the client */ + return WRITE_TRAN_FINISHED; + + case TLS_ST_SW_HELLO_REQ: + st->hand_state = TLS_ST_OK; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SR_CLNT_HELLO: + if (s->renegotiate == 0 && !SSL_IS_FIRST_HANDSHAKE(s)) { + /* We must have rejected the renegotiation */ + st->hand_state = TLS_ST_OK; + return WRITE_TRAN_CONTINUE; + } else { + st->hand_state = TLS_ST_SW_SRVR_HELLO; + } + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SW_SRVR_HELLO: + if (s->hit) { + if (s->ext.ticket_expected) + st->hand_state = TLS_ST_SW_SESSION_TICKET; + else + st->hand_state = TLS_ST_SW_CHANGE; + } else { + /* Check if it is anon DH or anon ECDH, */ + /* normal PSK or SRP */ + if (!(s->s3->tmp.new_cipher->algorithm_auth & + (SSL_aNULL | SSL_aSRP | SSL_aPSK))) { + st->hand_state = TLS_ST_SW_CERT; + } else if (send_server_key_exchange(s)) { + st->hand_state = TLS_ST_SW_KEY_EXCH; + } else if (send_certificate_request_ntls(s)) { + st->hand_state = TLS_ST_SW_CERT_REQ; + } else { + st->hand_state = TLS_ST_SW_SRVR_DONE; + } + } + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SW_CERT: + if (s->ext.status_expected) { + st->hand_state = TLS_ST_SW_CERT_STATUS; + return WRITE_TRAN_CONTINUE; + } + /* Fall through */ + + case TLS_ST_SW_CERT_STATUS: + if (send_server_key_exchange(s)) { + st->hand_state = TLS_ST_SW_KEY_EXCH; + return WRITE_TRAN_CONTINUE; + } + /* Fall through */ + + case TLS_ST_SW_KEY_EXCH: + if (send_certificate_request_ntls(s)) { + st->hand_state = TLS_ST_SW_CERT_REQ; + return WRITE_TRAN_CONTINUE; + } + /* Fall through */ + + case TLS_ST_SW_CERT_REQ: + st->hand_state = TLS_ST_SW_SRVR_DONE; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SW_SRVR_DONE: + return WRITE_TRAN_FINISHED; + + case TLS_ST_SR_FINISHED: + if (s->hit) { + st->hand_state = TLS_ST_OK; + return WRITE_TRAN_CONTINUE; + } else if (s->ext.ticket_expected) { + st->hand_state = TLS_ST_SW_SESSION_TICKET; + } else { + st->hand_state = TLS_ST_SW_CHANGE; + } + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SW_SESSION_TICKET: + st->hand_state = TLS_ST_SW_CHANGE; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SW_CHANGE: + st->hand_state = TLS_ST_SW_FINISHED; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SW_FINISHED: + if (s->hit) { + return WRITE_TRAN_FINISHED; + } + st->hand_state = TLS_ST_OK; + return WRITE_TRAN_CONTINUE; + } +} + +/* + * Perform any pre work that needs to be done prior to sending a message from + * the server to the client. + */ +WORK_STATE ossl_statem_server_pre_work_ntls(SSL *s, WORK_STATE wst) +{ + OSSL_STATEM *st = &s->statem; + + switch (st->hand_state) { + default: + /* No pre work to be done */ + break; + + case TLS_ST_SW_HELLO_REQ: + s->shutdown = 0; + break; + + case TLS_ST_SW_SRVR_HELLO: + break; + + case TLS_ST_SW_SRVR_DONE: + return WORK_FINISHED_CONTINUE; + + case TLS_ST_SW_SESSION_TICKET: + break; + + case TLS_ST_SW_CHANGE: + s->session->cipher = s->s3->tmp.new_cipher; + if (!s->method->ssl3_enc->setup_key_block(s)) { + /* SSLfatal_ntls() already called */ + return WORK_ERROR; + } + return WORK_FINISHED_CONTINUE; + + case TLS_ST_EARLY_DATA: + if (s->early_data_state != SSL_EARLY_DATA_ACCEPTING + && (s->s3->flags & TLS1_FLAGS_STATELESS) == 0) + return WORK_FINISHED_CONTINUE; + /* Fall through */ + + case TLS_ST_OK: + /* Calls SSLfatal_ntls() as required */ + return tls_finish_handshake_ntls(s, wst, 1, 1); + } + + return WORK_FINISHED_CONTINUE; +} + +static ossl_inline int conn_is_closed(void) +{ + switch (get_last_sys_error()) { +# if defined(EPIPE) + case EPIPE: + return 1; +# endif +# if defined(ECONNRESET) + case ECONNRESET: + return 1; +# endif +# if defined(WSAECONNRESET) + case WSAECONNRESET: + return 1; +# endif + default: + return 0; + } +} + +/* + * Perform any work that needs to be done after sending a message from the + * server to the client. + */ +WORK_STATE ossl_statem_server_post_work_ntls(SSL *s, WORK_STATE wst) +{ + OSSL_STATEM *st = &s->statem; + + s->init_num = 0; + + switch (st->hand_state) { + default: + /* No post work to be done */ + break; + + case TLS_ST_SW_HELLO_REQ: + if (statem_flush_ntls(s) != 1) + return WORK_MORE_A; + if (!ssl3_init_finished_mac(s)) { + /* SSLfatal_ntls() already called */ + return WORK_ERROR; + } + break; + + case TLS_ST_SW_SRVR_HELLO: + break; + /* Fall through */ + + case TLS_ST_SW_CHANGE: + if (s->hello_retry_request == SSL_HRR_PENDING) { + if (!statem_flush_ntls(s)) + return WORK_MORE_A; + break; + } + + if (!s->method->ssl3_enc->change_cipher_state(s, + SSL3_CHANGE_CIPHER_SERVER_WRITE)) + { + /* SSLfatal_ntls() already called */ + return WORK_ERROR; + } + + break; + + case TLS_ST_SW_SRVR_DONE: + if (statem_flush_ntls(s) != 1) + return WORK_MORE_A; + break; + + case TLS_ST_SW_FINISHED: + if (statem_flush_ntls(s) != 1) + return WORK_MORE_A; + break; + + case TLS_ST_SW_CERT_REQ: + if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) { + if (statem_flush_ntls(s) != 1) + return WORK_MORE_A; + } + break; + + case TLS_ST_SW_KEY_UPDATE: + if (statem_flush_ntls(s) != 1) + return WORK_MORE_A; + if (!tls13_update_key(s, 1)) { + /* SSLfatal_ntls() already called */ + return WORK_ERROR; + } + break; + + case TLS_ST_SW_SESSION_TICKET: + clear_sys_error(); + break; + } + + return WORK_FINISHED_CONTINUE; +} + +/* + * Get the message construction function and message type for sending from the + * server + * + * Valid return values are: + * 1: Success + * 0: Error + */ +int ossl_statem_server_construct_message_ntls(SSL *s, WPACKET *pkt, + confunc_f *confunc, int *mt) +{ + OSSL_STATEM *st = &s->statem; + + switch (st->hand_state) { + default: + /* Shouldn't happen */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE_NTLS, + SSL_R_BAD_HANDSHAKE_STATE); + return 0; + + case TLS_ST_SW_CHANGE: + *confunc = tls_construct_change_cipher_spec_ntls; + *mt = SSL3_MT_CHANGE_CIPHER_SPEC; + break; + + case TLS_ST_SW_HELLO_REQ: + /* No construction function needed */ + *confunc = NULL; + *mt = SSL3_MT_HELLO_REQUEST; + break; + + case TLS_ST_SW_SRVR_HELLO: + *confunc = tls_construct_server_hello_ntls; + *mt = SSL3_MT_SERVER_HELLO; + break; + + case TLS_ST_SW_CERT: + *confunc = ntls_construct_server_certificate_ntls; + *mt = SSL3_MT_CERTIFICATE; + break; + + + case TLS_ST_SW_KEY_EXCH: + *confunc = ntls_construct_server_key_exchange_ntls; + *mt = SSL3_MT_SERVER_KEY_EXCHANGE; + break; + + case TLS_ST_SW_CERT_REQ: + *confunc = tls_construct_certificate_request_ntls; + *mt = SSL3_MT_CERTIFICATE_REQUEST; + break; + + case TLS_ST_SW_SRVR_DONE: + *confunc = tls_construct_server_done_ntls; + *mt = SSL3_MT_SERVER_DONE; + break; + + case TLS_ST_SW_SESSION_TICKET: + *confunc = tls_construct_new_session_ticket_ntls; + *mt = SSL3_MT_NEWSESSION_TICKET; + break; + + case TLS_ST_SW_CERT_STATUS: + *confunc = tls_construct_cert_status_ntls; + *mt = SSL3_MT_CERTIFICATE_STATUS; + break; + + case TLS_ST_SW_FINISHED: + *confunc = tls_construct_finished_ntls; + *mt = SSL3_MT_FINISHED; + break; + + case TLS_ST_EARLY_DATA: + *confunc = NULL; + *mt = SSL3_MT_DUMMY; + break; + + case TLS_ST_SW_ENCRYPTED_EXTENSIONS: + *confunc = tls_construct_encrypted_extensions; + *mt = SSL3_MT_ENCRYPTED_EXTENSIONS; + break; + + case TLS_ST_SW_KEY_UPDATE: + *confunc = tls_construct_key_update_ntls; + *mt = SSL3_MT_KEY_UPDATE; + break; + } + + return 1; +} + +/* + * Maximum size (excluding the Handshake header) of a ClientHello message, + * calculated as follows: + * + * 2 + # client_version + * 32 + # only valid length for random + * 1 + # length of session_id + * 32 + # maximum size for session_id + * 2 + # length of cipher suites + * 2^16-2 + # maximum length of cipher suites array + * 1 + # length of compression_methods + * 2^8-1 + # maximum length of compression methods + * 2 + # length of extensions + * 2^16-1 # maximum length of extensions + */ +# define CLIENT_HELLO_MAX_LENGTH 131396 + +# define CLIENT_KEY_EXCH_MAX_LENGTH 2048 +# define NEXT_PROTO_MAX_LENGTH 514 + +/* + * Returns the maximum allowed length for the current message that we are + * reading. Excludes the message header. + */ +size_t ossl_statem_server_max_message_size_ntls(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + + switch (st->hand_state) { + default: + /* Shouldn't happen */ + return 0; + + case TLS_ST_SR_CLNT_HELLO: + return CLIENT_HELLO_MAX_LENGTH; + + case TLS_ST_SR_END_OF_EARLY_DATA: + return END_OF_EARLY_DATA_MAX_LENGTH; + + case TLS_ST_SR_CERT: + return s->max_cert_list; + + case TLS_ST_SR_KEY_EXCH: + return CLIENT_KEY_EXCH_MAX_LENGTH; + + case TLS_ST_SR_CERT_VRFY: + return SSL3_RT_MAX_PLAIN_LENGTH; + +# ifndef OPENSSL_NO_NEXTPROTONEG + case TLS_ST_SR_NEXT_PROTO: + return NEXT_PROTO_MAX_LENGTH; +# endif + + case TLS_ST_SR_CHANGE: + return CCS_MAX_LENGTH; + + case TLS_ST_SR_FINISHED: + return FINISHED_MAX_LENGTH; + + case TLS_ST_SR_KEY_UPDATE: + return KEY_UPDATE_MAX_LENGTH; + } +} + +/* + * Process a message that the server has received from the client. + */ +MSG_PROCESS_RETURN ossl_statem_server_process_message_ntls(SSL *s, PACKET *pkt) +{ + OSSL_STATEM *st = &s->statem; + + switch (st->hand_state) { + default: + /* Shouldn't happen */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE_NTLS, + ERR_R_INTERNAL_ERROR); + return MSG_PROCESS_ERROR; + + case TLS_ST_SR_CLNT_HELLO: + return tls_process_client_hello_ntls(s, pkt); + + case TLS_ST_SR_END_OF_EARLY_DATA: + return tls_process_end_of_early_data_ntls(s, pkt); + + case TLS_ST_SR_CERT: + return tls_process_client_certificate_ntls(s, pkt); + + case TLS_ST_SR_KEY_EXCH: + return ntls_process_client_key_exchange_ntls(s, pkt); + + case TLS_ST_SR_CERT_VRFY: + return ntls_process_cert_verify_ntls(s, pkt); + +# ifndef OPENSSL_NO_NEXTPROTONEG + case TLS_ST_SR_NEXT_PROTO: + return tls_process_next_proto_ntls(s, pkt); +# endif + + case TLS_ST_SR_CHANGE: + return tls_process_change_cipher_spec_ntls(s, pkt); + + case TLS_ST_SR_FINISHED: + return tls_process_finished_ntls(s, pkt); + + case TLS_ST_SR_KEY_UPDATE: + return tls_process_key_update_ntls(s, pkt); + + } +} + +/* + * Perform any further processing required following the receipt of a message + * from the client + */ +WORK_STATE ossl_statem_server_post_process_message_ntls(SSL *s, WORK_STATE wst) +{ + OSSL_STATEM *st = &s->statem; + + switch (st->hand_state) { + default: + /* Shouldn't happen */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE_NTLS, + ERR_R_INTERNAL_ERROR); + return WORK_ERROR; + + case TLS_ST_SR_CLNT_HELLO: + return tls_post_process_client_hello_ntls(s, wst); + + case TLS_ST_SR_KEY_EXCH: + return tls_post_process_client_key_exchange_ntls(s, wst); + } +} + +# ifndef OPENSSL_NO_EC +/*- + * ssl_check_for_safari attempts to fingerprint Safari using OS X + * SecureTransport using the TLS extension block in |hello|. + * Safari, since 10.6, sends exactly these extensions, in this order: + * SNI, + * elliptic_curves + * ec_point_formats + * signature_algorithms (for TLSv1.2 only) + * + * We wish to fingerprint Safari because they broke ECDHE-ECDSA support in 10.8, + * but they advertise support. So enabling ECDHE-ECDSA ciphers breaks them. + * Sadly we cannot differentiate 10.6, 10.7 and 10.8.4 (which work), from + * 10.8..10.8.3 (which don't work). + */ +static void ssl_check_for_safari(SSL *s, const CLIENTHELLO_MSG *hello) +{ + static const unsigned char kSafariExtensionsBlock[] = { + 0x00, 0x0a, /* elliptic_curves extension */ + 0x00, 0x08, /* 8 bytes */ + 0x00, 0x06, /* 6 bytes of curve ids */ + 0x00, 0x17, /* P-256 */ + 0x00, 0x18, /* P-384 */ + 0x00, 0x19, /* P-521 */ + + 0x00, 0x0b, /* ec_point_formats */ + 0x00, 0x02, /* 2 bytes */ + 0x01, /* 1 point format */ + 0x00, /* uncompressed */ + /* The following is only present in TLS 1.2 */ + 0x00, 0x0d, /* signature_algorithms */ + 0x00, 0x0c, /* 12 bytes */ + 0x00, 0x0a, /* 10 bytes */ + 0x05, 0x01, /* SHA-384/RSA */ + 0x04, 0x01, /* SHA-256/RSA */ + 0x02, 0x01, /* SHA-1/RSA */ + 0x04, 0x03, /* SHA-256/ECDSA */ + 0x02, 0x03, /* SHA-1/ECDSA */ + }; + /* Length of the common prefix (first two extensions). */ + static const size_t kSafariCommonExtensionsLength = 18; + unsigned int type; + PACKET sni, tmppkt; + size_t ext_len; + + tmppkt = hello->extensions; + + if (!PACKET_forward(&tmppkt, 2) + || !PACKET_get_net_2(&tmppkt, &type) + || !PACKET_get_length_prefixed_2(&tmppkt, &sni)) { + return; + } + + if (type != TLSEXT_TYPE_server_name) + return; + + ext_len = TLS1_get_client_version(s) >= TLS1_2_VERSION ? + sizeof(kSafariExtensionsBlock) : kSafariCommonExtensionsLength; + + s->s3->is_probably_safari = PACKET_equal(&tmppkt, kSafariExtensionsBlock, + ext_len); +} +# endif /* !OPENSSL_NO_EC */ + +MSG_PROCESS_RETURN tls_process_client_hello_ntls(SSL *s, PACKET *pkt) +{ + PACKET session_id, compression, extensions, cookie; + static const unsigned char null_compression = 0; + CLIENTHELLO_MSG *clienthello = NULL; + + /* Check if this is actually an unexpected renegotiation ClientHello */ + if (s->renegotiate == 0 && !SSL_IS_FIRST_HANDSHAKE(s)) { + if ((s->options & SSL_OP_NO_RENEGOTIATION) != 0 + || (!s->s3->send_connection_binding + && (s->options + & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) == 0)) { + ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION); + return MSG_PROCESS_FINISHED_READING; + } + s->renegotiate = 1; + s->new_session = 1; + } + + clienthello = OPENSSL_zalloc(sizeof(*clienthello)); + if (clienthello == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * First, parse the raw ClientHello data into the CLIENTHELLO_MSG structure. + */ + clienthello->isv2 = RECORD_LAYER_is_sslv2_record(&s->rlayer); + PACKET_null_init(&cookie); + + if (clienthello->isv2) { + unsigned int mt; + + if (!SSL_IS_FIRST_HANDSHAKE(s) + || s->hello_retry_request != SSL_HRR_NONE) { + SSLfatal_ntls(s, SSL_AD_UNEXPECTED_MESSAGE, + SSL_F_TLS_PROCESS_CLIENT_HELLO_NTLS, SSL_R_UNEXPECTED_MESSAGE); + goto err; + } + + /*- + * An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2 + * header is sent directly on the wire, not wrapped as a TLS + * record. Our record layer just processes the message length and passes + * the rest right through. Its format is: + * Byte Content + * 0-1 msg_length - decoded by the record layer + * 2 msg_type - s->init_msg points here + * 3-4 version + * 5-6 cipher_spec_length + * 7-8 session_id_length + * 9-10 challenge_length + * ... ... + */ + + if (!PACKET_get_1(pkt, &mt) + || mt != SSL2_MT_CLIENT_HELLO) { + /* + * Should never happen. We should have tested this in the record + * layer in order to have determined that this is a SSLv2 record + * in the first place + */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (!PACKET_get_net_2(pkt, &clienthello->legacy_version)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO_NTLS, + SSL_R_LENGTH_TOO_SHORT); + goto err; + } + + /* Parse the message and load client random. */ + if (clienthello->isv2) { + /* + * Handle an SSLv2 backwards compatible ClientHello + * Note, this is only for SSLv3+ using the backward compatible format. + * Real SSLv2 is not supported, and is rejected below. + */ + unsigned int ciphersuite_len, session_id_len, challenge_len; + PACKET challenge; + + if (!PACKET_get_net_2(pkt, &ciphersuite_len) + || !PACKET_get_net_2(pkt, &session_id_len) + || !PACKET_get_net_2(pkt, &challenge_len)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO_NTLS, + SSL_R_RECORD_LENGTH_MISMATCH); + goto err; + } + + if (session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) { + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PROCESS_CLIENT_HELLO_NTLS, SSL_R_LENGTH_MISMATCH); + goto err; + } + + if (!PACKET_get_sub_packet(pkt, &clienthello->ciphersuites, + ciphersuite_len) + || !PACKET_copy_bytes(pkt, clienthello->session_id, session_id_len) + || !PACKET_get_sub_packet(pkt, &challenge, challenge_len) + /* No extensions. */ + || PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO_NTLS, + SSL_R_RECORD_LENGTH_MISMATCH); + goto err; + } + clienthello->session_id_len = session_id_len; + + /* Load the client random and compression list. We use SSL3_RANDOM_SIZE + * here rather than sizeof(clienthello->random) because that is the limit + * for SSLv3 and it is fixed. It won't change even if + * sizeof(clienthello->random) does. + */ + challenge_len = challenge_len > SSL3_RANDOM_SIZE + ? SSL3_RANDOM_SIZE : challenge_len; + memset(clienthello->random, 0, SSL3_RANDOM_SIZE); + if (!PACKET_copy_bytes(&challenge, + clienthello->random + SSL3_RANDOM_SIZE - + challenge_len, challenge_len) + /* Advertise only null compression. */ + || !PACKET_buf_init(&compression, &null_compression, 1)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + PACKET_null_init(&clienthello->extensions); + } else { + /* Regular ClientHello. */ + if (!PACKET_copy_bytes(pkt, clienthello->random, SSL3_RANDOM_SIZE) + || !PACKET_get_length_prefixed_1(pkt, &session_id) + || !PACKET_copy_all(&session_id, clienthello->session_id, + SSL_MAX_SSL_SESSION_ID_LENGTH, + &clienthello->session_id_len)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO_NTLS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + if (!PACKET_get_length_prefixed_2(pkt, &clienthello->ciphersuites)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO_NTLS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + if (!PACKET_get_length_prefixed_1(pkt, &compression)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO_NTLS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + /* Could be empty. */ + if (PACKET_remaining(pkt) == 0) { + PACKET_null_init(&clienthello->extensions); + } else { + if (!PACKET_get_length_prefixed_2(pkt, &clienthello->extensions) + || PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO_NTLS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + } + } + + if (!PACKET_copy_all(&compression, clienthello->compressions, + MAX_COMPRESSIONS_SIZE, + &clienthello->compressions_len)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* Preserve the raw extensions PACKET for later use */ + extensions = clienthello->extensions; + if (!tls_collect_extensions_ntls(s, &extensions, SSL_EXT_CLIENT_HELLO, + &clienthello->pre_proc_exts, + &clienthello->pre_proc_exts_len, 1)) { + /* SSLfatal_ntls already been called */ + goto err; + } + s->clienthello = clienthello; + + return MSG_PROCESS_CONTINUE_PROCESSING; + + err: + if (clienthello != NULL) + OPENSSL_free(clienthello->pre_proc_exts); + OPENSSL_free(clienthello); + + return MSG_PROCESS_ERROR; +} + +static int tls_early_post_process_client_hello(SSL *s) +{ + unsigned int j; + int i, al = SSL_AD_INTERNAL_ERROR; + int protverr; + size_t loop; + unsigned long id; + + const SSL_CIPHER *c; + STACK_OF(SSL_CIPHER) *ciphers = NULL; + STACK_OF(SSL_CIPHER) *scsvs = NULL; + CLIENTHELLO_MSG *clienthello = s->clienthello; + DOWNGRADE dgrd = DOWNGRADE_NONE; + + /* Finished parsing the ClientHello, now we can start processing it */ + /* Give the ClientHello callback a crack at things */ + if (s->ctx->client_hello_cb != NULL) { + /* A failure in the ClientHello callback terminates the connection. */ + switch (s->ctx->client_hello_cb(s, &al, s->ctx->client_hello_cb_arg)) { + case SSL_CLIENT_HELLO_SUCCESS: + break; + case SSL_CLIENT_HELLO_RETRY: + s->rwstate = SSL_CLIENT_HELLO_CB; + return -1; + case SSL_CLIENT_HELLO_ERROR: + default: + SSLfatal_ntls(s, al, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_CALLBACK_FAILED); + goto err; + } + } + + /* Set up the client_random */ + memcpy(s->s3->client_random, clienthello->random, SSL3_RANDOM_SIZE); + + /* Choose the version */ + + if (clienthello->isv2) { + if (clienthello->legacy_version == NTLS_VERSION) { + /* do nothing */ + } else if (clienthello->legacy_version == SSL2_VERSION + || (clienthello->legacy_version & 0xff00) + != (SSL3_VERSION_MAJOR << 8)) { + /* + * This is real SSLv2 or something completely unknown. We don't + * support it. + */ + SSLfatal_ntls(s, SSL_AD_PROTOCOL_VERSION, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_UNKNOWN_PROTOCOL); + goto err; + } + /* SSLv3/TLS */ + s->client_version = clienthello->legacy_version; + } + /* + * Do SSL/TLS version negotiation if applicable. Version negotiation comes later. + */ + protverr = ssl_choose_server_version_ntls(s, clienthello, &dgrd); + + if (protverr) { + if (SSL_IS_FIRST_HANDSHAKE(s)) { + /* like ssl3_get_record, send alert using remote version number */ + s->version = s->client_version = clienthello->legacy_version; + } + SSLfatal_ntls(s, SSL_AD_PROTOCOL_VERSION, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, protverr); + goto err; + } + + s->hit = 0; + + if (!ssl_cache_cipherlist(s, &clienthello->ciphersuites, + clienthello->isv2) || + !bytes_to_cipher_list(s, &clienthello->ciphersuites, &ciphers, &scsvs, + clienthello->isv2, 1)) { + /* SSLfatal_ntls() already called */ + goto err; + } + + s->s3->send_connection_binding = 0; + /* Check what signalling cipher-suite values were received. */ + if (scsvs != NULL) { + for(i = 0; i < sk_SSL_CIPHER_num(scsvs); i++) { + c = sk_SSL_CIPHER_value(scsvs, i); + if (SSL_CIPHER_get_id(c) == SSL3_CK_SCSV) { + if (s->renegotiate) { + /* SCSV is fatal if renegotiating */ + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING); + goto err; + } + s->s3->send_connection_binding = 1; + } else if (SSL_CIPHER_get_id(c) == SSL3_CK_FALLBACK_SCSV && + !ssl_check_version_downgrade_ntls(s)) { + /* + * This SCSV indicates that the client previously tried + * a higher version. We should fail if the current version + * is an unexpected downgrade, as that indicates that the first + * connection may have been tampered with in order to trigger + * an insecure downgrade. + */ + SSLfatal_ntls(s, SSL_AD_INAPPROPRIATE_FALLBACK, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_INAPPROPRIATE_FALLBACK); + goto err; + } + } + } + + /* We need to do this before getting the session */ + if (!tls_parse_extension_ntls(s, TLSEXT_IDX_extended_master_secret, + SSL_EXT_CLIENT_HELLO, + clienthello->pre_proc_exts, NULL, 0)) { + /* SSLfatal_ntls() already called */ + goto err; + } + + /* + * We don't allow resumption in a backwards compatible ClientHello. + * TODO(openssl-team): in TLS1.1+, session_id MUST be empty. + * + * Versions before 0.9.7 always allow clients to resume sessions in + * renegotiation. 0.9.7 and later allow this by default, but optionally + * ignore resumption requests with flag + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (it's a new flag rather + * than a change to default behavior so that applications relying on + * this for security won't even compile against older library versions). + * 1.0.1 and later also have a function SSL_renegotiate_abbreviated() to + * request renegotiation but not a new session (s->new_session remains + * unset): for servers, this essentially just means that the + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION setting will be + * ignored. + */ + if (clienthello->isv2 || + (s->new_session && + (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) { + if (!ssl_get_new_session(s, 1)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else { + i = ssl_get_prev_session(s, clienthello); + if (i == 1) { + /* previous session */ + s->hit = 1; + } else if (i == -1) { + /* SSLfatal_ntls() already called */ + goto err; + } else { + /* i == 0 */ + if (!ssl_get_new_session(s, 1)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } + } + + + + /* + * If it is a hit, check that the cipher is in the list. In TLSv1.3 we check + * ciphersuite compatibility with the session as part of resumption. + */ + if (s->hit) { + j = 0; + id = s->session->cipher->id; + +# ifdef CIPHER_DEBUG + fprintf(stderr, "client sent %d ciphers\n", sk_SSL_CIPHER_num(ciphers)); +# endif + for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { + c = sk_SSL_CIPHER_value(ciphers, i); +# ifdef CIPHER_DEBUG + fprintf(stderr, "client [%2d of %2d]:%s\n", + i, sk_SSL_CIPHER_num(ciphers), SSL_CIPHER_get_name(c)); +# endif + if (c->id == id) { + j = 1; + break; + } + } + if (j == 0) { + /* + * we need to have the cipher in the cipher list if we are asked + * to reuse it + */ + SSLfatal_ntls(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_REQUIRED_CIPHER_MISSING); + goto err; + } + } + + for (loop = 0; loop < clienthello->compressions_len; loop++) { + if (clienthello->compressions[loop] == 0) + break; + } + + if (loop >= clienthello->compressions_len) { + /* no compress */ + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_NO_COMPRESSION_SPECIFIED); + goto err; + } + +# ifndef OPENSSL_NO_EC + if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG) + ssl_check_for_safari(s, clienthello); +# endif /* !OPENSSL_NO_EC */ + + /* TLS extensions */ + if (!tls_parse_all_extensions_ntls(s, SSL_EXT_CLIENT_HELLO, + clienthello->pre_proc_exts, NULL, 0, 1)) { + /* SSLfatal_ntls() already called */ + goto err; + } + + /* + * Check if we want to use external pre-shared secret for this handshake + * for not reused session only. We need to generate server_random before + * calling tls_session_secret_cb in order to allow SessionTicket + * processing to use it in key derivation. + */ + { + unsigned char *pos; + pos = s->s3->server_random; + if (ssl_fill_hello_random(s, 1, pos, SSL3_RANDOM_SIZE, dgrd) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + ERR_R_INTERNAL_ERROR); + goto err; + } + } + +# if !(defined(OPENSSL_NO_KEYLESS) && defined(OPENSSL_NO_LURK)) + if (s->sig_hash && s->cert->cert_cb2) { + int rv = s->cert->cert_cb2(s, s->cert->cert_cb2_arg); + if (rv < 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_CERT_CB2_ERROR); + goto err; + } + } +# endif + + if (!s->hit + && s->version >= TLS1_VERSION + && s->ext.session_secret_cb) { + const SSL_CIPHER *pref_cipher = NULL; + /* + * s->session->master_key_length is a size_t, but this is an int for + * backwards compat reasons + */ + int master_key_length; + + master_key_length = sizeof(s->session->master_key); + if (s->ext.session_secret_cb(s, s->session->master_key, + &master_key_length, ciphers, + &pref_cipher, + s->ext.session_secret_cb_arg) + && master_key_length > 0) { + s->session->master_key_length = master_key_length; + s->hit = 1; + s->peer_ciphers = ciphers; + s->session->verify_result = X509_V_OK; + + ciphers = NULL; + + /* check if some cipher was preferred by call back */ + if (pref_cipher == NULL) + pref_cipher = ssl3_choose_cipher(s, s->peer_ciphers, + SSL_get_ciphers(s)); + if (pref_cipher == NULL) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_NO_SHARED_CIPHER); + goto err; + } + + s->session->cipher = pref_cipher; + sk_SSL_CIPHER_free(s->cipher_list); + s->cipher_list = sk_SSL_CIPHER_dup(s->peer_ciphers); + sk_SSL_CIPHER_free(s->cipher_list_by_id); + s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->peer_ciphers); + } + } + + /* + * Worst case, we will use the NULL compression, but if we have other + * options, we will now look for them. We have complen-1 compression + * algorithms from the client, starting at q. + */ + s->s3->tmp.new_compression = NULL; + + /* + * If compression is disabled we'd better not try to resume a session + * using compression. + */ + if (s->session->compress_meth != 0) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_INCONSISTENT_COMPRESSION); + goto err; + } + + + /* + * Given s->peer_ciphers and SSL_get_ciphers, we must pick a cipher + */ + + if (!s->hit) { + sk_SSL_CIPHER_free(s->peer_ciphers); + s->peer_ciphers = ciphers; + if (ciphers == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + ERR_R_INTERNAL_ERROR); + goto err; + } + ciphers = NULL; + } + + if (!s->hit) { + s->session->compress_meth = 0; + + if (!tls1_set_server_sigalgs(s)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } + + sk_SSL_CIPHER_free(ciphers); + sk_SSL_CIPHER_free(scsvs); + OPENSSL_free(clienthello->pre_proc_exts); + OPENSSL_free(s->clienthello); + s->clienthello = NULL; + return 1; + err: + sk_SSL_CIPHER_free(ciphers); + sk_SSL_CIPHER_free(scsvs); + OPENSSL_free(clienthello->pre_proc_exts); + OPENSSL_free(s->clienthello); + s->clienthello = NULL; + + return 0; +} + +/* + * Call the status request callback if needed. Upon success, returns 1. + * Upon failure, returns 0. + */ +static int tls_handle_status_request(SSL *s) +{ + s->ext.status_expected = 0; + + /* + * If status request then ask callback what to do. Note: this must be + * called after servername callbacks in case the certificate has changed, + * and must be called after the cipher has been chosen because this may + * influence which certificate is sent + */ + if (s->ext.status_type != TLSEXT_STATUSTYPE_nothing && s->ctx != NULL + && s->ctx->ext.status_cb != NULL) { + int ret; + + /* If no certificate can't return certificate status */ + if (s->s3->tmp.cert != NULL) { + /* + * Set current certificate to one we will use so SSL_get_certificate + * et al can pick it up. + */ + s->cert->key = s->s3->tmp.cert; + ret = s->ctx->ext.status_cb(s, s->ctx->ext.status_arg); + switch (ret) { + /* We don't want to send a status request response */ + case SSL_TLSEXT_ERR_NOACK: + s->ext.status_expected = 0; + break; + /* status request response should be sent */ + case SSL_TLSEXT_ERR_OK: + if (s->ext.ocsp.resp) + s->ext.status_expected = 1; + break; + /* something bad happened */ + case SSL_TLSEXT_ERR_ALERT_FATAL: + default: + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_HANDLE_STATUS_REQUEST, + SSL_R_CLIENTHELLO_TLSEXT); + return 0; + } + } + } + + return 1; +} + +/* + * Call the alpn_select callback if needed. Upon success, returns 1. + * Upon failure, returns 0. + */ +int tls_handle_alpn_ntls(SSL *s) +{ + const unsigned char *selected = NULL; + unsigned char selected_len = 0; + + if (s->ctx->ext.alpn_select_cb != NULL && s->s3->alpn_proposed != NULL) { + int r = s->ctx->ext.alpn_select_cb(s, &selected, &selected_len, + s->s3->alpn_proposed, + (unsigned int)s->s3->alpn_proposed_len, + s->ctx->ext.alpn_select_cb_arg); + + if (r == SSL_TLSEXT_ERR_OK) { + OPENSSL_free(s->s3->alpn_selected); + s->s3->alpn_selected = OPENSSL_memdup(selected, selected_len); + if (s->s3->alpn_selected == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_HANDLE_ALPN_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + s->s3->alpn_selected_len = selected_len; +# ifndef OPENSSL_NO_NEXTPROTONEG + /* ALPN takes precedence over NPN. */ + s->s3->npn_seen = 0; +# endif + + /* Check ALPN is consistent with session */ + if (s->session->ext.alpn_selected == NULL + || selected_len != s->session->ext.alpn_selected_len + || memcmp(selected, s->session->ext.alpn_selected, + selected_len) != 0) { + /* Not consistent so can't be used for early_data */ + s->ext.early_data_ok = 0; + + if (!s->hit) { + /* + * This is a new session and so alpn_selected should have + * been initialised to NULL. We should update it with the + * selected ALPN. + */ + if (!ossl_assert(s->session->ext.alpn_selected == NULL)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_HANDLE_ALPN_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + s->session->ext.alpn_selected = OPENSSL_memdup(selected, + selected_len); + if (s->session->ext.alpn_selected == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_HANDLE_ALPN_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + s->session->ext.alpn_selected_len = selected_len; + } + } + + return 1; + } else if (r != SSL_TLSEXT_ERR_NOACK) { + SSLfatal_ntls(s, SSL_AD_NO_APPLICATION_PROTOCOL, SSL_F_TLS_HANDLE_ALPN_NTLS, + SSL_R_NO_APPLICATION_PROTOCOL); + return 0; + } + /* + * If r == SSL_TLSEXT_ERR_NOACK then behave as if no callback was + * present. + */ + } + + /* Check ALPN is consistent with session */ + if (s->session->ext.alpn_selected != NULL) { + /* Not consistent so can't be used for early_data */ + s->ext.early_data_ok = 0; + } + + return 1; +} + +WORK_STATE tls_post_process_client_hello_ntls(SSL *s, WORK_STATE wst) +{ + const SSL_CIPHER *cipher; + + if (wst == WORK_MORE_A) { + int rv = tls_early_post_process_client_hello(s); + if (rv == 0) { + /* SSLfatal_ntls() was already called */ + goto err; + } + if (rv < 0) + return WORK_MORE_A; + wst = WORK_MORE_B; + } + if (wst == WORK_MORE_B) { + if (!s->hit) { + /* Let cert callback update server certificates if required */ + if (!s->hit && s->cert->cert_cb != NULL) { + int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg); + if (rv == 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_POST_PROCESS_CLIENT_HELLO_NTLS, + SSL_R_CERT_CB_ERROR); + goto err; + } + if (rv < 0) { + s->rwstate = SSL_X509_LOOKUP; + return WORK_MORE_B; + } + s->rwstate = SSL_NOTHING; + } + + cipher = + ssl3_choose_cipher(s, s->peer_ciphers, SSL_get_ciphers(s)); + + if (cipher == NULL) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_POST_PROCESS_CLIENT_HELLO_NTLS, + SSL_R_NO_SHARED_CIPHER); + goto err; + } + s->s3->tmp.new_cipher = cipher; + + if (!s->hit) { + if (!tls_choose_sigalg(s, 1)) { + /* SSLfatal_ntls already called */ + goto err; + } + /* check whether we should disable session resumption */ + if (s->not_resumable_session_cb != NULL) + s->session->not_resumable = + s->not_resumable_session_cb(s, + ((s->s3->tmp.new_cipher->algorithm_mkey + & (SSL_kDHE | SSL_kECDHE)) != 0)); + if (s->session->not_resumable) + /* do not send a session ticket */ + s->ext.ticket_expected = 0; + } + } else { + /* Session-id reuse */ + s->s3->tmp.new_cipher = s->session->cipher; + } + + if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSM2DHE) + s->verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT + | SSL_VERIFY_CLIENT_ONCE; + + /*- + * we now have the following setup. + * client_random + * cipher_list - our preferred list of ciphers + * ciphers - the clients preferred list of ciphers + * compression - basically ignored right now + * ssl version is set - sslv3 + * s->session - The ssl session has been setup. + * s->hit - session reuse flag + * s->s3->tmp.new_cipher- the new cipher to use. + */ + + /* + * Call status_request callback if needed. Has to be done after the + * certificate callbacks etc above. + */ + if (!tls_handle_status_request(s)) { + /* SSLfatal_ntls() already called */ + goto err; + } + /* + * Call alpn_select callback if needed. Has to be done after SNI and + * cipher negotiation (HTTP/2 restricts permitted ciphers). In TLSv1.3 + * we already did this because cipher negotiation happens earlier, and + * we must handle ALPN before we decide whether to accept early_data. + */ + if (!tls_handle_alpn_ntls(s)) { + /* SSLfatal_ntls() already called */ + goto err; + } + + wst = WORK_MORE_C; + } + + return WORK_FINISHED_STOP; + err: + return WORK_ERROR; +} + +int tls_construct_server_hello_ntls(SSL *s, WPACKET *pkt) +{ + int compm; + size_t sl, len; + int version; + unsigned char *session_id; + int usetls13 = s->hello_retry_request == SSL_HRR_PENDING; + + version = usetls13 ? TLS1_2_VERSION : s->version; + if (!WPACKET_put_bytes_u16(pkt, version) + /* + * Random stuff. Filling of the server_random takes place in + * tls_process_client_hello_ntls() + */ + || !WPACKET_memcpy(pkt, + s->hello_retry_request == SSL_HRR_PENDING + ? hrrrandom_ntls : s->s3->server_random, + SSL3_RANDOM_SIZE)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /*- + * There are several cases for the session ID to send + * back in the server hello: + * - For session reuse from the session cache, + * we send back the old session ID. + * - If stateless session reuse (using a session ticket) + * is successful, we send back the client's "session ID" + * (which doesn't actually identify the session). + * - If it is a new session, we send back the new + * session ID. + * - However, if we want the new session to be single-use, + * we send back a 0-length session ID. + * - In TLSv1.3 we echo back the session id sent to us by the client + * regardless + * s->hit is non-zero in either case of session reuse, + * so the following won't overwrite an ID that we're supposed + * to send back. + */ + if (s->session->not_resumable || + (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER) + && !s->hit)) + s->session->session_id_length = 0; + + if (usetls13) { + sl = s->tmp_session_id_len; + session_id = s->tmp_session_id; + } else { + sl = s->session->session_id_length; + session_id = s->session->session_id; + } + + if (sl > sizeof(s->session->session_id)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* set up the compression method */ + compm = 0; + + if (!WPACKET_sub_memcpy_u8(pkt, session_id, sl) + || !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt, &len) + || !WPACKET_put_bytes_u8(pkt, compm)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (s->hello_retry_request == SSL_HRR_PENDING) { + /* Ditch the session. We'll create a new one next time around */ + SSL_SESSION_free(s->session); + s->session = NULL; + s->hit = 0; + + /* + * Re-initialise the Transcript Hash. We're going to prepopulate it with + * a synthetic message_hash in place of ClientHello1. + */ + if (!create_synthetic_message_hash_ntls(s, NULL, 0, NULL, 0)) { + /* SSLfatal_ntls() already called */ + return 0; + } + } else if (!(s->verify_mode & SSL_VERIFY_PEER) + && !ssl3_digest_cached_records(s, 0)) { + /* SSLfatal_ntls() already called */; + return 0; + } + + return 1; +} + +int tls_construct_server_done_ntls(SSL *s, WPACKET *pkt) +{ + if (!s->s3->tmp.cert_request) { + if (!ssl3_digest_cached_records(s, 0)) { + /* SSLfatal_ntls() already called */ + return 0; + } + } + return 1; +} + +int tls_construct_server_key_exchange_ntls(SSL *s, WPACKET *pkt) +{ +# ifndef OPENSSL_NO_DH + EVP_PKEY *pkdh = NULL; +# endif +# ifndef OPENSSL_NO_EC + unsigned char *encodedPoint = NULL; + size_t encodedlen = 0; + int curve_id = 0; +# endif + const SIGALG_LOOKUP *lu = s->s3->tmp.sigalg; + int i; + unsigned long type; + const BIGNUM *r[4]; +# if !(defined(OPENSSL_NO_KEYLESS) && defined(OPENSSL_NO_LURK)) + EVP_MD_CTX *md_ctx = NULL; +# else + EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); +# endif + EVP_PKEY_CTX *pctx = NULL; + size_t paramlen, paramoffset; +# if !(defined(OPENSSL_NO_KEYLESS) && defined(OPENSSL_NO_LURK)) + int use_keyless = 0; + + if (0 +# ifndef OPENSSL_NO_KEYLESS + || s->keyless_ntls +# endif +# ifndef OPENSSL_NO_LURK + || s->lurk_ntls +# endif + ) + { + /*We currently support rsa and ecdsa signature processes*/ + if (lu->sig == EVP_PKEY_RSA + || lu->sig == EVP_PKEY_RSA_PSS +# ifndef OPENSSL_NO_SM2 + || lu->sig == EVP_PKEY_SM2 +# endif + || lu->sig == EVP_PKEY_EC) + use_keyless = 1; + +# ifndef OPENSSL_NO_KEYLESS + if (s->keyless_again) + goto keyless_recover; +# endif +# ifndef OPENSSL_NO_LURK + if (s->lurk_again) + goto lurk_recover; +# endif + } +# endif +# if !(defined(OPENSSL_NO_KEYLESS) && defined(OPENSSL_NO_LURK)) + md_ctx = EVP_MD_CTX_new(); +# endif + + if (!WPACKET_get_total_written(pkt, ¶moffset)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (md_ctx == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, ERR_R_MALLOC_FAILURE); + goto err; + } + + type = s->s3->tmp.new_cipher->algorithm_mkey; + + r[0] = r[1] = r[2] = r[3] = NULL; +# ifndef OPENSSL_NO_DH + if (type & (SSL_kDHE | SSL_kDHEPSK)) { + CERT *cert = s->cert; + + EVP_PKEY *pkdhp = NULL; + DH *dh; + + if (s->cert->dh_tmp_auto) { + DH *dhp = ssl_get_auto_dh(s); + pkdh = EVP_PKEY_new(); + if (pkdh == NULL || dhp == NULL) { + DH_free(dhp); + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + EVP_PKEY_assign_DH(pkdh, dhp); + pkdhp = pkdh; + } else { + pkdhp = cert->dh_tmp; + } + if ((pkdhp == NULL) && (s->cert->dh_tmp_cb != NULL)) { + DH *dhp = s->cert->dh_tmp_cb(s, 0, 1024); + pkdh = ssl_dh_to_pkey(dhp); + if (pkdh == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + pkdhp = pkdh; + } + if (pkdhp == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + SSL_R_MISSING_TMP_DH_KEY); + goto err; + } + if (!ssl_security(s, SSL_SECOP_TMP_DH, + EVP_PKEY_security_bits(pkdhp), 0, pkdhp)) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + SSL_R_DH_KEY_TOO_SMALL); + goto err; + } + if (s->s3->tmp.pkey != NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + s->s3->tmp.pkey = ssl_generate_pkey(pkdhp); + if (s->s3->tmp.pkey == NULL) { + /* SSLfatal_ntls() already called */ + goto err; + } + + dh = EVP_PKEY_get0_DH(s->s3->tmp.pkey); + if (dh == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + EVP_PKEY_free(pkdh); + pkdh = NULL; + + DH_get0_pqg(dh, &r[0], NULL, &r[1]); + DH_get0_key(dh, &r[2], NULL); + } else +# endif +# ifndef OPENSSL_NO_EC + if (type & (SSL_kECDHE | SSL_kECDHEPSK)) { + + if (s->s3->tmp.pkey != NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* Get NID of appropriate shared curve */ + curve_id = tls1_shared_group(s, -2); + if (curve_id == 0) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); + goto err; + } + s->s3->tmp.pkey = ssl_generate_pkey_group(s, curve_id); + /* Generate a new key for this curve */ + if (s->s3->tmp.pkey == NULL) { + /* SSLfatal_ntls() already called */ + goto err; + } + + /* Encode the public key. */ + encodedlen = EVP_PKEY_get1_tls_encodedpoint(s->s3->tmp.pkey, + &encodedPoint); + if (encodedlen == 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, ERR_R_EC_LIB); + goto err; + } + + /* + * We'll generate the serverKeyExchange message explicitly so we + * can set these to NULLs + */ + r[0] = NULL; + r[1] = NULL; + r[2] = NULL; + r[3] = NULL; + } else +# endif /* !OPENSSL_NO_EC */ + { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); + goto err; + } + + if (((s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP)) != 0) + || ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)) != 0) { + lu = NULL; + } else if (lu == NULL) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, ERR_R_INTERNAL_ERROR); + goto err; + } + + for (i = 0; i < 4 && r[i] != NULL; i++) { + unsigned char *binval; + int res; + + res = WPACKET_start_sub_packet_u16(pkt); + + if (!res) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + +# ifndef OPENSSL_NO_DH + /*- + * for interoperability with some versions of the Microsoft TLS + * stack, we need to zero pad the DHE pub key to the same length + * as the prime + */ + if ((i == 2) && (type & (SSL_kDHE | SSL_kDHEPSK))) { + size_t len = BN_num_bytes(r[0]) - BN_num_bytes(r[2]); + + if (len > 0) { + if (!WPACKET_allocate_bytes(pkt, len, &binval)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + memset(binval, 0, len); + } + } +# endif + if (!WPACKET_allocate_bytes(pkt, BN_num_bytes(r[i]), &binval) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + BN_bn2bin(r[i], binval); + } + +# ifndef OPENSSL_NO_EC + if (type & (SSL_kECDHE | SSL_kECDHEPSK)) { + /* + * We only support named (not generic) curves. In this situation, the + * ServerKeyExchange message has: [1 byte CurveType], [2 byte CurveName] + * [1 byte length of encoded point], followed by the actual encoded + * point itself + */ + if (!WPACKET_put_bytes_u8(pkt, NAMED_CURVE_TYPE) + || !WPACKET_put_bytes_u8(pkt, 0) + || !WPACKET_put_bytes_u8(pkt, curve_id) + || !WPACKET_sub_memcpy_u8(pkt, encodedPoint, encodedlen)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + OPENSSL_free(encodedPoint); + encodedPoint = NULL; + } +# endif + + /* not anonymous */ + if (lu != NULL) { + EVP_PKEY *pkey; + const EVP_MD *md; + unsigned char *sigbytes1, *sigbytes2, *tbs; + size_t siglen, tbslen; + int rv; + +# if !(defined(OPENSSL_NO_KEYLESS) && defined(OPENSSL_NO_LURK)) + if (use_keyless) + pkey = X509_get0_pubkey(s->s3->tmp.cert->x509); + else +# endif + pkey = s->s3->tmp.cert->privatekey; + + if (pkey == NULL || !tls1_lookup_md(lu, &md)) { + /* Should never happen */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + /* Get length of the parameters we have written above */ + if (!WPACKET_get_length(pkt, ¶mlen)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + /* send signature algorithm */ + if (SSL_USE_SIGALGS(s) && !WPACKET_put_bytes_u16(pkt, lu->sigalg)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + /* + * Create the signature. We don't know the actual length of the sig + * until after we've created it, so we reserve enough bytes for it + * up front, and then properly allocate them in the WPACKET + * afterwards. + */ + siglen = EVP_PKEY_size(pkey); +# if !(defined(OPENSSL_NO_KEYLESS) && defined(OPENSSL_NO_LURK)) + if (use_keyless) { + if (!WPACKET_sub_reserve_bytes_u16(pkt, siglen, &sigbytes1) + || (EVP_DigestInit(md_ctx, md) <= 0)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + } else +# endif + { + if (!WPACKET_sub_reserve_bytes_u16(pkt, siglen, &sigbytes1) + || EVP_DigestSignInit(md_ctx, &pctx, md, NULL, pkey) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + if (lu->sig == EVP_PKEY_RSA_PSS) { + if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0 + || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, RSA_PSS_SALTLEN_DIGEST) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_EVP_LIB); + goto err; + } + } + } + tbslen = construct_key_exchange_tbs_ntls(s, &tbs, + s->init_buf->data + paramoffset, + paramlen); + if (tbslen == 0) { + /* SSLfatal_ntls() already called */ + goto err; + } +# ifndef OPENSSL_NO_KEYLESS + if (s->keyless_ntls && use_keyless) { + unsigned char md_buf[EVP_MAX_MD_SIZE]; + unsigned int mdlen = 0; + int ret = 0; + unsigned char *tbuf = NULL; + + if ((EVP_DigestUpdate(md_ctx, (const void *)tbs, tbslen) <= 0) + || (EVP_DigestFinal(md_ctx,&(md_buf[0]), &mdlen) <= 0)) { + OPENSSL_free(tbs); + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + OPENSSL_free(tbs); + + if (lu->sig == EVP_PKEY_RSA_PSS) { + tbuf = OPENSSL_malloc(EVP_PKEY_size(pkey)); + if (tbuf == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!RSA_padding_add_PKCS1_PSS_mgf1(EVP_PKEY_get0_RSA(pkey), + tbuf, &(md_buf[0]), + md, md, + RSA_PSS_SALTLEN_DIGEST)) { + OPENSSL_free(tbuf); + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + s->keyless_callback_param.data = tbuf; + s->keyless_callback_param.len = RSA_size(EVP_PKEY_get0_RSA(pkey)); + s->keyless_callback_param.type = SSL_KEYLESS_TYPE_RSA_PSS_SIGN; + } else { + s->keyless_callback_param.data = md_buf; + s->keyless_callback_param.len = mdlen; + if (lu->sig == EVP_PKEY_RSA) + s->keyless_callback_param.type = EVP_MD_type(md); +# ifndef OPENSSL_NO_SM2 + else if (lu->sig == EVP_PKEY_SM2) + s->keyless_callback_param.type = SSL_KEYLESS_TYPE_SM2_SIGN; +# endif + else + s->keyless_callback_param.type = SSL_KEYLESS_TYPE_ECDSA_SIGN; + } + s->keyless_callback_param.cert_tag = SSL_NORMAL_CERT; + s->keyless_recover_pos = sigbytes1; + s->keyless_recover_n = pkt->written; + ret = s->keyless_callback(s, &s->keyless_callback_param); + if (lu->sig == EVP_PKEY_RSA_PSS) { + OPENSSL_free(tbuf); + tbuf = NULL; + } + if (ret == 1) { + /* again or done */ + s->keyless_again = 1; + return 0; + } else if (ret == 2) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + SSL_R_KEYLESS_ERROR); + goto err; + } else if (ret == 0) { +keyless_recover: + siglen = s->keyless_result_len; + sigbytes1 = s->keyless_recover_pos; + pkt->curr = pkt->written = s->keyless_recover_n; + + memcpy(sigbytes1, s->keyless_result, siglen); + + if (s->keyless_again) + s->keyless_again = 0; + } else { + /* invalid return value */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + SSL_R_KEYLESS_INVALID_RETURN_ERROR); + goto err; + } + + if (!WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2) + || sigbytes1 != sigbytes2) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + + } else +# endif + /* signature params and callback */ +# ifndef OPENSSL_NO_LURK + if (s->lurk_ntls && s->lurk && use_keyless) { + int ret = 0; + + s->lurk_callback_param.type = SSL_LURK_QUERY_ECDHE; + s->lurk_callback_param.data = (unsigned char *)s->init_buf->data + paramoffset; + s->lurk_callback_param.len = paramlen; + +# ifndef OPENSSL_NO_SM2 + if (lu->sig == EVP_PKEY_SM2) { + unsigned char md_buf[EVP_MAX_MD_SIZE]; + unsigned int mdlen = 0; + + if ((EVP_DigestUpdate(md_ctx, (const void *)tbs, tbslen) <= 0) + || (EVP_DigestFinal(md_ctx, &(md_buf[0]), &mdlen) <= 0)) { + OPENSSL_free(tbs); + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + OPENSSL_free(tbs); + + s->lurk_callback_param.data = md_buf; + s->lurk_callback_param.len = mdlen; + + s->lurk_callback_param.cert_tag = SSL_NORMAL_CERT; + s->lurk_callback_param.type = SSL_LURK_QUERY_SM2_SIGN; + } +# endif + + EVP_MD_CTX_free(md_ctx); + md_ctx = NULL; + + s->lurk_recover_pos = sigbytes1; + s->lurk_recover_n = pkt->written; + + ret = s->lurk_callback(s, &s->lurk_callback_param); + switch(ret) { + case SSL_LURK_OK: + lurk_recover: + if (s->lurk_result == NULL || s->lurk_result_len == 0) + goto err; + + siglen = s->lurk_result_len; + sigbytes1 = s->lurk_recover_pos; + pkt->curr = pkt->written = s->lurk_recover_n; + + memcpy(sigbytes1, s->lurk_result, siglen); + + s->lurk_again = 0; + break; + case SSL_LURK_AGAIN: + case SSL_LURK_DONE: + /* again or done */ + s->lurk_again = 1; + return 0; + case SSL_LURK_ERROR: + /* error */ + default: + /* invalid return value */ + goto err; + } + + if (!WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2) + || sigbytes1 != sigbytes2) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + } else +# endif + { + rv = EVP_DigestSign(md_ctx, sigbytes1, &siglen, tbs, tbslen); + OPENSSL_free(tbs); + if (rv <= 0 || !WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2) + || sigbytes1 != sigbytes2) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + goto err; + } + } + } + + EVP_MD_CTX_free(md_ctx); + return 1; + err: +# ifndef OPENSSL_NO_DH + EVP_PKEY_free(pkdh); +# endif +# ifndef OPENSSL_NO_EC + OPENSSL_free(encodedPoint); +# endif + EVP_MD_CTX_free(md_ctx); + return 0; +} + +int tls_construct_certificate_request_ntls(SSL *s, WPACKET *pkt) +{ + /* get the list of acceptable cert types */ + if (!WPACKET_start_sub_packet_u8(pkt) + || !ssl3_get_req_cert_type(s, pkt) || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST_NTLS, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (SSL_USE_SIGALGS(s)) { + const uint16_t *psigs; + size_t nl = tls12_get_psigalgs(s, 1, &psigs); + + if (!WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_set_flags(pkt, WPACKET_FLAGS_NON_ZERO_LENGTH) + || !tls12_copy_sigalgs(s, pkt, psigs, nl) + || !WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + + if (!construct_ca_names_ntls(s, get_ca_names_ntls(s), pkt)) { + /* SSLfatal_ntls() already called */ + return 0; + } + + s->certreqs_sent++; + s->s3->tmp.cert_request = 1; + return 1; +} + +static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt) +{ + /* Should never happen */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, + ERR_R_INTERNAL_ERROR); + return 0; + +} + +static int tls_process_cke_rsa(SSL *s, PACKET *pkt) +{ +# ifndef OPENSSL_NO_RSA + unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH]; + int decrypt_len; + unsigned char decrypt_good, version_good; + size_t j, padding_len; + PACKET enc_premaster; + RSA *rsa = NULL; + unsigned char *rsa_decrypt = NULL; + int ret = 0; + +# ifndef OPENSSL_NO_KEYLESS + if (s->keyless_ntls && s->keyless_again) + goto keyless_recover; +# endif +# ifndef OPENSSL_NO_LURK + if(s->lurk_ntls && s->lurk_again) + goto lurk_recover; +# endif + +# ifndef OPENSSL_NO_LURK + if (s->lurk_ntls && s->lurk) { + /* SSLv3 omit the length bytes. */ + if (s->version == SSL3_VERSION) { + enc_premaster = *pkt; + } else { + if (!PACKET_get_length_prefixed_2(pkt, &enc_premaster) + || PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, + SSL_R_LENGTH_MISMATCH); + return 0; + } + } + + s->lurk_callback_param.data = (unsigned char *)PACKET_data(&enc_premaster); + s->lurk_callback_param.len = (int)PACKET_remaining(&enc_premaster); + + if (s->session->flags & SSL_SESS_FLAG_EXTMS) + s->lurk_callback_param.type = SSL_LURK_QUERY_RSA_EXTEND_MASTER; + else + s->lurk_callback_param.type = SSL_LURK_QUERY_RSA_MASTER; + + ret = s->lurk_callback(s, &s->lurk_callback_param); + switch(ret) { + case SSL_LURK_OK: + lurk_recover: + if (s->lurk_result == NULL || s->lurk_result_len == 0) { + SSLfatal_ntls(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, + ERR_R_RSA_LIB); + goto err; + } + + if (s->lurk_result_len > SSL_MAX_MASTER_KEY_LENGTH) + goto err; + + s->session->master_key_length = s->lurk_result_len; + memcpy(s->session->master_key, s->lurk_result, s->lurk_result_len); + + s->lurk_again = 0; + return 1; + case SSL_LURK_AGAIN: + case SSL_LURK_DONE: + /* again or done */ + s->lurk_again = 1; + return 1; + case SSL_LURK_ERROR: + /* error */ + default: + /* invalid return value */ + goto err; + } + } +# endif +# ifndef OPENSSL_NO_KEYLESS + if (s->keyless_ntls) { + /*The following use the RSA secret key of the large number N, keyless scenario + *we use the public key*/ + EVP_PKEY *t_pkey; + t_pkey = X509_get0_pubkey(s->cert->pkeys[SSL_PKEY_RSA].x509); + if (t_pkey == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, + SSL_R_MISSING_RSA_CERTIFICATE); + return 0; + } + rsa = EVP_PKEY_get0_RSA(t_pkey); + } else +# endif + rsa = EVP_PKEY_get0_RSA(s->cert->pkeys[SSL_PKEY_RSA].privatekey); + if (rsa == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, + SSL_R_MISSING_RSA_CERTIFICATE); + return 0; + } + + /* SSLv3 omit the length bytes. */ + if (s->version == SSL3_VERSION) { + enc_premaster = *pkt; + } else { + if (!PACKET_get_length_prefixed_2(pkt, &enc_premaster) + || PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, + SSL_R_LENGTH_MISMATCH); + return 0; + } + } + + /* + * We want to be sure that the plaintext buffer size makes it safe to + * iterate over the entire size of a premaster secret + * (SSL_MAX_MASTER_KEY_LENGTH). Reject overly short RSA keys because + * their ciphertext cannot accommodate a premaster secret anyway. + */ + if (RSA_size(rsa) < SSL_MAX_MASTER_KEY_LENGTH) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, + RSA_R_KEY_SIZE_TOO_SMALL); + return 0; + } + + rsa_decrypt = OPENSSL_malloc(RSA_size(rsa)); + if (rsa_decrypt == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, + ERR_R_MALLOC_FAILURE); + return 0; + } + + /* + * We must not leak whether a decryption failure occurs because of + * Bleichenbacher's attack on PKCS # 1 v1.5 RSA padding (see RFC 2246, + * section 7.4.7.1). The code follows that advice of the TLS RFC and + * generates a random premaster secret for the case that the decrypt + * fails. See https://tools.ietf.org/html/rfc5246# section-7.4.7.1 + */ + + if (RAND_priv_bytes(rand_premaster_secret, + sizeof(rand_premaster_secret)) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, + ERR_R_INTERNAL_ERROR); + goto err; + } +# ifndef OPENSSL_NO_KEYLESS + if (s->keyless_ntls) { + int keyless_ret = 0; + s->keyless_recover_pos = rsa_decrypt; + s->keyless_callback_param.data = PACKET_data(&enc_premaster); + s->keyless_callback_param.len = (unsigned long)PACKET_remaining(&enc_premaster); + s->keyless_callback_param.type = SSL_KEYLESS_TYPE_RSA_DECRYPT; + s->keyless_callback_param.cert_tag = SSL_NORMAL_CERT; + + keyless_ret = s->keyless_callback(s, &s->keyless_callback_param); + if (keyless_ret == 1) { + /* again or done */ + s->keyless_again = 1; + return 0; + } else if (keyless_ret == 2) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, + SSL_R_KEYLESS_ERROR); + goto err; + } else if (keyless_ret == 0) { +keyless_recover: + decrypt_len = s->keyless_result_len; + rsa_decrypt = s->keyless_recover_pos; + if (s->keyless_again) + s->keyless_again = 0; + + memcpy(rsa_decrypt, s->keyless_result, decrypt_len); + } else { + /* invalid return value */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, + SSL_R_KEYLESS_INVALID_RETURN_ERROR); + goto err; + } + padding_len = 0; + decrypt_good = 0xff; + } else +# endif + { + /* + * Decrypt with no padding. PKCS# 1 padding will be removed as part of + * the timing-sensitive code below. + */ + /* TODO(size_t): Convert this function */ + decrypt_len = (int)RSA_private_decrypt((int)PACKET_remaining(&enc_premaster), + PACKET_data(&enc_premaster), + rsa_decrypt, rsa, RSA_NO_PADDING); + + if (decrypt_len < 0) { + SSLfatal_ntls(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* Check the padding. See RFC 3447, section 7.2.2. */ + + /* + * The smallest padded premaster is 11 bytes of overhead. Small keys + * are publicly invalid, so this may return immediately. This ensures + * PS is at least 8 bytes. + */ + if (decrypt_len < 11 + SSL_MAX_MASTER_KEY_LENGTH) { + SSLfatal_ntls(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, + SSL_R_DECRYPTION_FAILED); + goto err; + } + + padding_len = decrypt_len - SSL_MAX_MASTER_KEY_LENGTH; + decrypt_good = constant_time_eq_int_8(rsa_decrypt[0], 0) & + constant_time_eq_int_8(rsa_decrypt[1], 2); + for (j = 2; j < padding_len - 1; j++) { + decrypt_good &= ~constant_time_is_zero_8(rsa_decrypt[j]); + } + decrypt_good &= constant_time_is_zero_8(rsa_decrypt[padding_len - 1]); + } + + /* + * If the version in the decrypted pre-master secret is correct then + * version_good will be 0xff, otherwise it'll be zero. The + * Klima-Pokorny-Rosa extension of Bleichenbacher's attack + * (http://eprint.iacr.org/2003/052/) exploits the version number + * check as a "bad version oracle". Thus version checks are done in + * constant time and are treated like any other decryption error. + */ + version_good = + constant_time_eq_8(rsa_decrypt[padding_len], + (unsigned)(s->client_version >> 8)); + version_good &= + constant_time_eq_8(rsa_decrypt[padding_len + 1], + (unsigned)(s->client_version & 0xff)); + + /* + * The premaster secret must contain the same version number as the + * ClientHello to detect version rollback attacks (strangely, the + * protocol does not offer such protection for DH ciphersuites). + * However, buggy clients exist that send the negotiated protocol + * version instead if the server does not support the requested + * protocol version. If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such + * clients. + */ + if (s->options & SSL_OP_TLS_ROLLBACK_BUG) { + unsigned char workaround_good; + workaround_good = constant_time_eq_8(rsa_decrypt[padding_len], + (unsigned)(s->version >> 8)); + workaround_good &= + constant_time_eq_8(rsa_decrypt[padding_len + 1], + (unsigned)(s->version & 0xff)); + version_good |= workaround_good; + } + + /* + * Both decryption and version must be good for decrypt_good to + * remain non-zero (0xff). + */ + decrypt_good &= version_good; + + /* + * Now copy rand_premaster_secret over from p using + * decrypt_good_mask. If decryption failed, then p does not + * contain valid plaintext, however, a check above guarantees + * it is still sufficiently large to read from. + */ + for (j = 0; j < sizeof(rand_premaster_secret); j++) { + rsa_decrypt[padding_len + j] = + constant_time_select_8(decrypt_good, + rsa_decrypt[padding_len + j], + rand_premaster_secret[j]); + } + + if (!ssl_generate_master_secret(s, rsa_decrypt + padding_len, + sizeof(rand_premaster_secret), 0)) { + /* SSLfatal_ntls() already called */ + goto err; + } + + ret = 1; + err: + OPENSSL_free(rsa_decrypt); + return ret; +# else + /* Should never happen */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, + ERR_R_INTERNAL_ERROR); + return 0; +# endif +} + +static int tls_process_cke_dhe(SSL *s, PACKET *pkt) +{ +# ifndef OPENSSL_NO_DH + EVP_PKEY *skey = NULL; + DH *cdh; + unsigned int i; + BIGNUM *pub_key; + const unsigned char *data; + EVP_PKEY *ckey = NULL; + int ret = 0; + + if (!PACKET_get_net_2(pkt, &i) || PACKET_remaining(pkt) != i) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_DHE, + SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG); + goto err; + } + skey = s->s3->tmp.pkey; + if (skey == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE, + SSL_R_MISSING_TMP_DH_KEY); + goto err; + } + + if (PACKET_remaining(pkt) == 0L) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_DHE, + SSL_R_MISSING_TMP_DH_KEY); + goto err; + } + if (!PACKET_get_bytes(pkt, &data, i)) { + /* We already checked we have enough data */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE, + ERR_R_INTERNAL_ERROR); + goto err; + } + ckey = EVP_PKEY_new(); + if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) == 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE, + SSL_R_BN_LIB); + goto err; + } + + cdh = EVP_PKEY_get0_DH(ckey); + pub_key = BN_bin2bn(data, i, NULL); + if (pub_key == NULL || cdh == NULL || !DH_set0_key(cdh, pub_key, NULL)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE, + ERR_R_INTERNAL_ERROR); + BN_free(pub_key); + goto err; + } + + if (ssl_derive(s, skey, ckey, 1) == 0) { + /* SSLfatal_ntls() already called */ + goto err; + } + + ret = 1; + EVP_PKEY_free(s->s3->tmp.pkey); + s->s3->tmp.pkey = NULL; + err: + EVP_PKEY_free(ckey); + return ret; +# else + /* Should never happen */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE, + ERR_R_INTERNAL_ERROR); + return 0; +# endif +} + +static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt) +{ +# ifndef OPENSSL_NO_EC + EVP_PKEY *skey = s->s3->tmp.pkey; + EVP_PKEY *ckey = NULL; + int ret = 0; + + if (PACKET_remaining(pkt) == 0L) { + /* We don't support ECDH client auth */ + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_CKE_ECDHE, + SSL_R_MISSING_TMP_ECDH_KEY); + goto err; + } else { + unsigned int i; + const unsigned char *data; + + /* + * Get client's public key from encoded point in the + * ClientKeyExchange message. + */ + + /* Get encoded point length */ + if (!PACKET_get_1(pkt, &i) || !PACKET_get_bytes(pkt, &data, i) + || PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE, + SSL_R_LENGTH_MISMATCH); + goto err; + } + if (skey == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE, + SSL_R_MISSING_TMP_ECDH_KEY); + goto err; + } + + ckey = EVP_PKEY_new(); + if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE, + ERR_R_EVP_LIB); + goto err; + } + if (EVP_PKEY_set1_tls_encodedpoint(ckey, data, i) == 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE, + ERR_R_EC_LIB); + goto err; + } + } + + if (ssl_derive(s, skey, ckey, 1) == 0) { + /* SSLfatal_ntls() already called */ + goto err; + } + + ret = 1; + EVP_PKEY_free(s->s3->tmp.pkey); + s->s3->tmp.pkey = NULL; + err: + EVP_PKEY_free(ckey); + + return ret; +# else + /* Should never happen */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE, + ERR_R_INTERNAL_ERROR); + return 0; +# endif +} + +static int tls_process_cke_gost(SSL *s, PACKET *pkt) +{ +# ifndef OPENSSL_NO_GOST + EVP_PKEY_CTX *pkey_ctx; + EVP_PKEY *client_pub_pkey = NULL, *pk = NULL; + unsigned char premaster_secret[32]; + const unsigned char *start; + size_t outlen = 32, inlen; + unsigned long alg_a; + unsigned int asn1id, asn1len; + int ret = 0; + PACKET encdata; + + /* Get our certificate private key */ + alg_a = s->s3->tmp.new_cipher->algorithm_auth; + if (alg_a & SSL_aGOST12) { + /* + * New GOST ciphersuites have SSL_aGOST01 bit too + */ + pk = s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey; + if (pk == NULL) { + pk = s->cert->pkeys[SSL_PKEY_GOST12_256].privatekey; + } + if (pk == NULL) { + pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey; + } + } else if (alg_a & SSL_aGOST01) { + pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey; + } + + pkey_ctx = EVP_PKEY_CTX_new(pk, NULL); + if (pkey_ctx == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + ERR_R_MALLOC_FAILURE); + return 0; + } + if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + ERR_R_INTERNAL_ERROR); + return 0; + } + /* + * If client certificate is present and is of the same type, maybe + * use it for key exchange. Don't mind errors from + * EVP_PKEY_derive_set_peer, because it is completely valid to use a + * client certificate for authorization only. + */ + client_pub_pkey = X509_get0_pubkey(s->session->peer); + if (client_pub_pkey) { + if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0) + ERR_clear_error(); + } + /* Decrypt session key */ + if (!PACKET_get_1(pkt, &asn1id) + || asn1id != (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) + || !PACKET_peek_1(pkt, &asn1len)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + SSL_R_DECRYPTION_FAILED); + goto err; + } + if (asn1len == 0x81) { + /* + * Long form length. Should only be one byte of length. Anything else + * isn't supported. + * We did a successful peek before so this shouldn't fail + */ + if (!PACKET_forward(pkt, 1)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + SSL_R_DECRYPTION_FAILED); + goto err; + } + } else if (asn1len >= 0x80) { + /* + * Indefinite length, or more than one long form length bytes. We don't + * support it + */ + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + SSL_R_DECRYPTION_FAILED); + goto err; + } /* else short form length */ + + if (!PACKET_as_length_prefixed_1(pkt, &encdata)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + SSL_R_DECRYPTION_FAILED); + goto err; + } + inlen = PACKET_remaining(&encdata); + start = PACKET_data(&encdata); + + if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start, + inlen) <= 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + SSL_R_DECRYPTION_FAILED); + goto err; + } + /* Generate master secret */ + if (!ssl_generate_master_secret(s, premaster_secret, + sizeof(premaster_secret), 0)) { + /* SSLfatal_ntls() already called */ + goto err; + } + /* Check if pubkey from client certificate was used */ + if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, + NULL) > 0) + s->statem.no_cert_verify = 1; + + ret = 1; + err: + EVP_PKEY_CTX_free(pkey_ctx); + return ret; +# else + /* Should never happen */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + ERR_R_INTERNAL_ERROR); + return 0; +# endif +} + +MSG_PROCESS_RETURN tls_process_client_key_exchange_ntls(SSL *s, PACKET *pkt) +{ + unsigned long alg_k; + + alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + + /* For PSK parse and retrieve identity, obtain PSK key */ + if ((alg_k & SSL_PSK) && !tls_process_cke_psk_preamble(s, pkt)) { + /* SSLfatal_ntls() already called */ + goto err; + } + + if (alg_k & SSL_kPSK) { + /* Identity extracted earlier: should be nothing left */ + if (PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE_NTLS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + /* PSK handled by ssl_generate_master_secret */ + if (!ssl_generate_master_secret(s, NULL, 0, 0)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) { + if (!tls_process_cke_rsa(s, pkt)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) { + if (!tls_process_cke_dhe(s, pkt)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) { + if (!tls_process_cke_ecdhe(s, pkt)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else if (alg_k & SSL_kGOST) { + if (!tls_process_cke_gost(s, pkt)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE_NTLS, + SSL_R_UNKNOWN_CIPHER_TYPE); + goto err; + } + +# ifndef OPENSSL_NO_KEYLESS + if (s->keyless_ntls && s->keyless_again) + return MSG_PROCESS_ERROR; +# endif + +# ifndef OPENSSL_NO_LURK + if (s->lurk_ntls && s->lurk_again) + return MSG_PROCESS_ERROR; +# endif + + return MSG_PROCESS_CONTINUE_PROCESSING; + err: + return MSG_PROCESS_ERROR; +} + +WORK_STATE tls_post_process_client_key_exchange_ntls(SSL *s, WORK_STATE wst) +{ + if (s->statem.no_cert_verify || !s->session->peer) { + /* + * No certificate verify or no peer certificate so we no longer need + * the handshake_buffer + */ + if (!ssl3_digest_cached_records(s, 0)) { + /* SSLfatal_ntls() already called */ + return WORK_ERROR; + } + return WORK_FINISHED_CONTINUE; + } else { + if (!s->s3->handshake_buffer) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE_NTLS, + ERR_R_INTERNAL_ERROR); + return WORK_ERROR; + } + /* + * For sigalgs freeze the handshake buffer. If we support + * extms we've done this already so this is a no-op + */ + if (!ssl3_digest_cached_records(s, 1)) { + /* SSLfatal_ntls() already called */ + return WORK_ERROR; + } + } + + return WORK_FINISHED_CONTINUE; +} + +MSG_PROCESS_RETURN tls_process_client_certificate_ntls(SSL *s, PACKET *pkt) +{ + int i; + MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR; + X509 *x = NULL; + unsigned long l; + const unsigned char *certstart, *certbytes; + STACK_OF(X509) *sk = NULL; + PACKET spkt; + size_t chainidx; + SSL_SESSION *new_sess = NULL; + + /* + * To get this far we must have read encrypted data from the client. We no + * longer tolerate unencrypted alerts. This value is ignored if less than + * TLSv1.3 + */ + s->statem.enc_read_state = ENC_READ_STATE_VALID; + + if ((sk = sk_X509_new_null()) == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE_NTLS, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!PACKET_get_length_prefixed_3(pkt, &spkt) + || PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE_NTLS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + for (chainidx = 0; PACKET_remaining(&spkt) > 0; chainidx++) { + if (!PACKET_get_net_3(&spkt, &l) + || !PACKET_get_bytes(&spkt, &certbytes, l)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE_NTLS, + SSL_R_CERT_LENGTH_MISMATCH); + goto err; + } + + certstart = certbytes; + x = d2i_X509(NULL, (const unsigned char **)&certbytes, l); + if (x == NULL) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE_NTLS, ERR_R_ASN1_LIB); + goto err; + } + if (certbytes != (certstart + l)) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE_NTLS, + SSL_R_CERT_LENGTH_MISMATCH); + goto err; + } + + if (!sk_X509_push(sk, x)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE_NTLS, + ERR_R_MALLOC_FAILURE); + goto err; + } + x = NULL; + } + + if (sk_X509_num(sk) <= 0) { + /* TLS does not mind 0 certs returned */ + if (s->version == SSL3_VERSION) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE_NTLS, + SSL_R_NO_CERTIFICATES_RETURNED); + goto err; + } + /* Fail for TLS only if we required a certificate */ + else if ((s->verify_mode & SSL_VERIFY_PEER) && + (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) { + SSLfatal_ntls(s, SSL_AD_CERTIFICATE_REQUIRED, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE_NTLS, + SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); + goto err; + } + /* No client certificate so digest cached records */ + if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s, 0)) { + /* SSLfatal_ntls() already called */ + goto err; + } + } else { + EVP_PKEY *pkey; + i = ssl_verify_cert_chain(s, sk); + + /* + * for ECDHE-SM2, we don't have a standard to verify cert + * so we choose to ignore verify result for temp + */ + if (i <= 0) { + const char *cipher_name = (s->s3->tmp.new_cipher)->name; + if (strcmp(cipher_name, NTLS_TXT_SM2DHE_WITH_SM4_SM3) == 0 || + strcmp(cipher_name, NTLS_TXT_ECDHE_SM2_SM4_CBC_SM3) == 0 || + strcmp(cipher_name, NTLS_TXT_ECDHE_SM2_SM4_GCM_SM3) == 0) { + i = 1; + } + } + + if (i <= 0) { + SSLfatal_ntls(s, ssl_x509err2alert_ntls(s->verify_result), + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE_NTLS, + SSL_R_CERTIFICATE_VERIFY_FAILED); + goto err; + } + if (i > 1) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE_NTLS, i); + goto err; + } + pkey = X509_get0_pubkey(sk_X509_value(sk, 0)); + if (pkey == NULL) { + SSLfatal_ntls(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE_NTLS, + SSL_R_UNKNOWN_CERTIFICATE_TYPE); + goto err; + } + } + + /* + * Sessions must be immutable once they go into the session cache. Otherwise + * we can get multi-thread problems. Therefore we don't "update" sessions, + * we replace them with a duplicate. Here, we need to do this every time + * a new certificate is received via post-handshake authentication, as the + * session may have already gone into the session cache. + */ + + if (s->post_handshake_auth == SSL_PHA_REQUESTED) { + if ((new_sess = ssl_session_dup(s->session, 0)) == 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE_NTLS, + ERR_R_MALLOC_FAILURE); + goto err; + } + + SSL_SESSION_free(s->session); + s->session = new_sess; + } + + X509_free(s->session->peer); + s->session->peer = sk_X509_shift(sk); + s->session->verify_result = s->verify_result; + + sk_X509_pop_free(s->session->peer_chain, X509_free); + /* + * XXX: + * + * For NTLS, s->session->peer stores the client signing certificate + * and s->session->peer_chain is an one item stack which stores + * the client encryption certificate. + */ + s->session->peer_chain = sk; + + /* + * Inconsistency alert: cert_chain does *not* include the peer's own + * certificate, while we do include it in statem_clnt.c + */ + sk = NULL; + ret = MSG_PROCESS_CONTINUE_READING; + + err: + X509_free(x); + sk_X509_pop_free(sk, X509_free); + return ret; +} + +int tls_construct_server_certificate_ntls(SSL *s, WPACKET *pkt) +{ + CERT_PKEY *cpk = s->s3->tmp.cert; + + if (cpk == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE_NTLS, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!ssl3_output_cert_chain_ntls(s, pkt, cpk)) { + /* SSLfatal_ntls() already called */ + return 0; + } + + return 1; +} + +static int create_ticket_prequel(SSL *s, WPACKET *pkt, uint32_t age_add, + unsigned char *tick_nonce) +{ + /* + * Ticket lifetime hint: For TLSv1.2 this is advisory only and we leave this + * unspecified for resumed session (for simplicity). + * In TLSv1.3 we reset the "time" field above, and always specify the + * timeout. + */ + if (!WPACKET_put_bytes_u32(pkt, + (s->hit) + ? 0 : s->session->timeout)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_CREATE_TICKET_PREQUEL, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* Start the sub-packet for the actual ticket data */ + if (!WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_CREATE_TICKET_PREQUEL, + ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add, + unsigned char *tick_nonce) +{ + unsigned char *senc = NULL; + EVP_CIPHER_CTX *ctx = NULL; + HMAC_CTX *hctx = NULL; + unsigned char *p, *encdata1, *encdata2, *macdata1, *macdata2; + const unsigned char *const_p; + int len, slen_full, slen, lenfinal; + SSL_SESSION *sess; + unsigned int hlen; + SSL_CTX *tctx = s->session_ctx; + unsigned char iv[EVP_MAX_IV_LENGTH]; + unsigned char key_name[TLSEXT_KEYNAME_LENGTH]; + int iv_len, ok = 0; + size_t macoffset, macendoffset; + + /* get session encoding length */ + slen_full = i2d_SSL_SESSION(s->session, NULL); + /* + * Some length values are 16 bits, so forget it if session is too + * long + */ + if (slen_full == 0 || slen_full > 0xFF00) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET, + ERR_R_INTERNAL_ERROR); + goto err; + } + senc = OPENSSL_malloc(slen_full); + if (senc == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_CONSTRUCT_STATELESS_TICKET, ERR_R_MALLOC_FAILURE); + goto err; + } + + ctx = EVP_CIPHER_CTX_new(); + hctx = HMAC_CTX_new(); + if (ctx == NULL || hctx == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET, + ERR_R_MALLOC_FAILURE); + goto err; + } + + p = senc; + if (!i2d_SSL_SESSION(s->session, &p)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * create a fresh copy (not shared with other threads) to clean up + */ + const_p = senc; + sess = d2i_SSL_SESSION(NULL, &const_p, slen_full); + if (sess == NULL) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET, + ERR_R_INTERNAL_ERROR); + goto err; + } + + slen = i2d_SSL_SESSION(sess, NULL); + if (slen == 0 || slen > slen_full) { + /* shouldn't ever happen */ + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET, + ERR_R_INTERNAL_ERROR); + SSL_SESSION_free(sess); + goto err; + } + p = senc; + if (!i2d_SSL_SESSION(sess, &p)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET, + ERR_R_INTERNAL_ERROR); + SSL_SESSION_free(sess); + goto err; + } + SSL_SESSION_free(sess); + + /* + * Initialize HMAC and cipher contexts. If callback present it does + * all the work otherwise use generated values from parent ctx. + */ + if (tctx->ext.ticket_key_cb) { + /* if 0 is returned, write an empty ticket */ + int ret = tctx->ext.ticket_key_cb(s, key_name, iv, ctx, + hctx, 1); + + if (ret == 0) { + + /* Put timeout and length */ + if (!WPACKET_put_bytes_u32(pkt, 0) + || !WPACKET_put_bytes_u16(pkt, 0)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_CONSTRUCT_STATELESS_TICKET, + ERR_R_INTERNAL_ERROR); + goto err; + } + OPENSSL_free(senc); + EVP_CIPHER_CTX_free(ctx); + HMAC_CTX_free(hctx); + return 1; + } + if (ret < 0) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET, + SSL_R_CALLBACK_FAILED); + goto err; + } + iv_len = EVP_CIPHER_CTX_iv_length(ctx); + } else { + const EVP_CIPHER *cipher = EVP_aes_256_cbc(); + + iv_len = EVP_CIPHER_iv_length(cipher); + if (RAND_bytes(iv, iv_len) <= 0 + || !EVP_EncryptInit_ex(ctx, cipher, NULL, + tctx->ext.secure->tick_aes_key, iv) + || !HMAC_Init_ex(hctx, tctx->ext.secure->tick_hmac_key, + sizeof(tctx->ext.secure->tick_hmac_key), + EVP_sha256(), NULL)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET, + ERR_R_INTERNAL_ERROR); + goto err; + } + memcpy(key_name, tctx->ext.tick_key_name, + sizeof(tctx->ext.tick_key_name)); + } + + if (!create_ticket_prequel(s, pkt, age_add, tick_nonce)) { + /* SSLfatal_ntls() already called */ + goto err; + } + + if (!WPACKET_get_total_written(pkt, &macoffset) + /* Output key name */ + || !WPACKET_memcpy(pkt, key_name, sizeof(key_name)) + /* output IV */ + || !WPACKET_memcpy(pkt, iv, iv_len) + || !WPACKET_reserve_bytes(pkt, slen + EVP_MAX_BLOCK_LENGTH, + &encdata1) + /* Encrypt session data */ + || !EVP_EncryptUpdate(ctx, encdata1, &len, senc, slen) + || !WPACKET_allocate_bytes(pkt, len, &encdata2) + || encdata1 != encdata2 + || !EVP_EncryptFinal(ctx, encdata1 + len, &lenfinal) + || !WPACKET_allocate_bytes(pkt, lenfinal, &encdata2) + || encdata1 + len != encdata2 + || len + lenfinal > slen + EVP_MAX_BLOCK_LENGTH + || !WPACKET_get_total_written(pkt, &macendoffset) + || !HMAC_Update(hctx, + (unsigned char *)s->init_buf->data + macoffset, + macendoffset - macoffset) + || !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &macdata1) + || !HMAC_Final(hctx, macdata1, &hlen) + || hlen > EVP_MAX_MD_SIZE + || !WPACKET_allocate_bytes(pkt, hlen, &macdata2) + || macdata1 != macdata2) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, + SSL_F_CONSTRUCT_STATELESS_TICKET, ERR_R_INTERNAL_ERROR); + goto err; + } + + /* Close the sub-packet created by create_ticket_prequel() */ + if (!WPACKET_close(pkt)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET, + ERR_R_INTERNAL_ERROR); + goto err; + } + + ok = 1; + err: + OPENSSL_free(senc); + EVP_CIPHER_CTX_free(ctx); + HMAC_CTX_free(hctx); + return ok; +} + +int tls_construct_new_session_ticket_ntls(SSL *s, WPACKET *pkt) +{ + SSL_CTX *tctx = s->session_ctx; + unsigned char tick_nonce[TICKET_NONCE_SIZE]; + union { + unsigned char age_add_c[sizeof(uint32_t)]; + uint32_t age_add; + } age_add_u; + + age_add_u.age_add = 0; + + if (tctx->generate_ticket_cb != NULL && + tctx->generate_ticket_cb(s, tctx->ticket_cb_data) == 0) + goto err; + + if (!construct_stateless_ticket(s, pkt, age_add_u.age_add, + tick_nonce)) { + /* SSLfatal_ntls() already called */ + goto err; + } + + return 1; + err: + return 0; +} + +/* + * In TLSv1.3 this is called from the extensions code, otherwise it is used to + * create a separate message. Returns 1 on success or 0 on failure. + */ +int tls_construct_cert_status_body_ntls(SSL *s, WPACKET *pkt) +{ + if (!WPACKET_put_bytes_u8(pkt, s->ext.status_type) + || !WPACKET_sub_memcpy_u24(pkt, s->ext.ocsp.resp, + s->ext.ocsp.resp_len)) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_STATUS_BODY_NTLS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +int tls_construct_cert_status_ntls(SSL *s, WPACKET *pkt) +{ + if (!tls_construct_cert_status_body_ntls(s, pkt)) { + /* SSLfatal_ntls() already called */ + return 0; + } + + return 1; +} + +# ifndef OPENSSL_NO_NEXTPROTONEG +/* + * tls_process_next_proto_ntls reads a Next Protocol Negotiation handshake message. + * It sets the next_proto member in s if found + */ +MSG_PROCESS_RETURN tls_process_next_proto_ntls(SSL *s, PACKET *pkt) +{ + PACKET next_proto, padding; + size_t next_proto_len; + + /*- + * The payload looks like: + * uint8 proto_len; + * uint8 proto[proto_len]; + * uint8 padding_len; + * uint8 padding[padding_len]; + */ + if (!PACKET_get_length_prefixed_1(pkt, &next_proto) + || !PACKET_get_length_prefixed_1(pkt, &padding) + || PACKET_remaining(pkt) > 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEXT_PROTO_NTLS, + SSL_R_LENGTH_MISMATCH); + return MSG_PROCESS_ERROR; + } + + if (!PACKET_memdup(&next_proto, &s->ext.npn, &next_proto_len)) { + s->ext.npn_len = 0; + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEXT_PROTO_NTLS, + ERR_R_INTERNAL_ERROR); + return MSG_PROCESS_ERROR; + } + + s->ext.npn_len = (unsigned char)next_proto_len; + + return MSG_PROCESS_CONTINUE_READING; +} +# endif + +static int tls_construct_encrypted_extensions(SSL *s, WPACKET *pkt) +{ + if (!tls_construct_extensions_ntls(s, pkt, SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, + NULL, 0)) { + /* SSLfatal_ntls() already called */ + return 0; + } + + return 1; +} + +MSG_PROCESS_RETURN tls_process_end_of_early_data_ntls(SSL *s, PACKET *pkt) +{ + if (PACKET_remaining(pkt) != 0) { + SSLfatal_ntls(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_END_OF_EARLY_DATA_NTLS, + SSL_R_LENGTH_MISMATCH); + return MSG_PROCESS_ERROR; + } + + if (s->early_data_state != SSL_EARLY_DATA_READING + && s->early_data_state != SSL_EARLY_DATA_READ_RETRY) { + SSLfatal_ntls(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_END_OF_EARLY_DATA_NTLS, + ERR_R_INTERNAL_ERROR); + return MSG_PROCESS_ERROR; + } + + /* + * EndOfEarlyData signals a key change so the end of the message must be on + * a record boundary. + */ + if (RECORD_LAYER_processed_read_pending(&s->rlayer)) { + SSLfatal_ntls(s, SSL_AD_UNEXPECTED_MESSAGE, + SSL_F_TLS_PROCESS_END_OF_EARLY_DATA_NTLS, + SSL_R_NOT_ON_RECORD_BOUNDARY); + return MSG_PROCESS_ERROR; + } + + s->early_data_state = SSL_EARLY_DATA_FINISHED_READING; + if (!s->method->ssl3_enc->change_cipher_state(s, + SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_READ)) { + /* SSLfatal_ntls() already called */ + return MSG_PROCESS_ERROR; + } + + return MSG_PROCESS_CONTINUE_READING; +} +#endif diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index d5dac82a7..bc99f8079 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -23,6 +23,9 @@ static const SIGALG_LOOKUP *find_sig_alg(SSL *s, X509 *x, EVP_PKEY *pkey); static int tls12_sigalg_allowed(const SSL *s, int op, const SIGALG_LOOKUP *lu); +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +static const SIGALG_LOOKUP *find_dc_sig_alg(SSL *s); +#endif SSL3_ENC_METHOD const TLSv1_enc_data = { tls1_enc, @@ -852,7 +855,7 @@ static const uint16_t tls_default_sigalg[] = { }; /* Lookup TLS signature algorithm */ -static const SIGALG_LOOKUP *tls1_lookup_sigalg(uint16_t sigalg) +const SIGALG_LOOKUP *tls1_lookup_sigalg(uint16_t sigalg) { size_t i; const SIGALG_LOOKUP *s; @@ -883,6 +886,22 @@ int tls1_lookup_md(const SIGALG_LOOKUP *lu, const EVP_MD **pmd) return 1; } +/* get NID of signature algorithm and NID of hash algorithm */ +int tls1_get_sig_and_hash(uint16_t sigalg, int *psig, int *phash) +{ + const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(sigalg); + if (!lu) + return 0; + + if (psig) + *psig = lu->sig; + + if (phash) + *phash = lu->hash; + + return 1; +} + void tls1_lookup_get_sig_and_md(uint16_t sigalg, int *psig, const EVP_MD **pmd) { const EVP_MD *md = NULL; @@ -2843,6 +2862,9 @@ static const SIGALG_LOOKUP *find_sig_alg(SSL *s, X509 *x, EVP_PKEY *pkey) */ int tls_choose_sigalg(SSL *s, int fatalerrs) { +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + const SIGALG_LOOKUP *dc_lu = NULL; +#endif const SIGALG_LOOKUP *lu = NULL; int sig_idx = -1; @@ -2850,14 +2872,21 @@ int tls_choose_sigalg(SSL *s, int fatalerrs) s->s3->tmp.sigalg = NULL; if (SSL_IS_TLS13(s)) { - lu = find_sig_alg(s, NULL, NULL); - if (lu == NULL) { - if (!fatalerrs) - return 1; - SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_CHOOSE_SIGALG, - SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM); - return 0; +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + dc_lu = find_dc_sig_alg(s); + if (dc_lu == NULL) { +#endif + lu = find_sig_alg(s, NULL, NULL); + if (lu == NULL) { + if (!fatalerrs) + return 1; + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_CHOOSE_SIGALG, + SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM); + return 0; + } +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL } +#endif } else { /* If ciphersuite doesn't require a cert nothing to do */ if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aCERT)) @@ -2983,11 +3012,25 @@ int tls_choose_sigalg(SSL *s, int fatalerrs) } } } - if (sig_idx == -1) - sig_idx = lu->sig_idx; - s->s3->tmp.cert = &s->cert->pkeys[sig_idx]; - s->cert->key = s->s3->tmp.cert; - s->s3->tmp.sigalg = lu; +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + if (dc_lu) { + sig_idx = dc_lu->sig_idx; + s->s3->tmp.cert = s->cert->dc_pkeys[sig_idx].parent; + s->cert->key = s->s3->tmp.cert; + s->s3->tmp.sigalg = dc_lu; + + s->delegated_credential_tag |= DC_HAS_BEEN_USED_FOR_SIGN; + } else { +#endif + if (sig_idx == -1) + sig_idx = lu->sig_idx; + s->s3->tmp.cert = &s->cert->pkeys[sig_idx]; + s->cert->key = s->s3->tmp.cert; + s->s3->tmp.sigalg = lu; +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + } +#endif + return 1; } @@ -3021,3 +3064,222 @@ uint8_t SSL_SESSION_get_max_fragment_length(const SSL_SESSION *session) { return session->ext.max_fragment_len_mode; } + +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +static int check_dc_usable(SSL *s, const SIGALG_LOOKUP *sig, + DELEGATED_CREDENTIAL *dc, EVP_PKEY *pkey) +{ + int default_mdnid; + size_t i; + unsigned int dc_expect_sig_alg; + + /* If the EVP_PKEY reports a mandatory digest, allow nothing else. */ + ERR_set_mark(); + if (EVP_PKEY_get_default_digest_nid(pkey, &default_mdnid) == 2 && + sig->hash != default_mdnid) + return 0; + + /* If it didn't report a mandatory NID, for whatever reasons, + * just clear the error and allow all hashes to be used. */ + ERR_pop_to_mark(); + + dc_expect_sig_alg = DC_get_expected_cert_verify_algorithm(dc); + + for (i = 0; i < s->s3->tmp.peer_dc_sigalgslen; i++) { + if (dc_expect_sig_alg == s->s3->tmp.peer_dc_sigalgs[i]) { + return 1; + } + } + + return 0; +} + +static int has_usable_dc(SSL *s, const SIGALG_LOOKUP *sig, int idx) +{ + if (idx == -1) + idx = sig->sig_idx; + + if (!ssl_has_dc(s, idx)) + return 0; + + return check_dc_usable(s, sig, s->cert->dc_pkeys[idx].dc, + s->cert->dc_pkeys[idx].privatekey); +} + +static const SIGALG_LOOKUP *find_dc_sig_alg(SSL *s) +{ + const SIGALG_LOOKUP *lu = NULL; + size_t i; +#ifndef OPENSSL_NO_EC + int curve = -1; +#endif + EVP_PKEY *tmppkey; + + if (!s->enable_sign_by_dc || !SSL_IS_TLS13(s)) + return NULL; + + /* Look for a shared sigalgs matching possible certificates */ + for (i = 0; i < s->shared_dc_sigalgslen; i++) { + lu = s->shared_dc_sigalgs[i]; + + /* Skip SHA1, SHA224, DSA and RSA if not PSS */ + if (lu->hash == NID_sha1 + || lu->hash == NID_sha224 + || lu->sig == EVP_PKEY_DSA + || lu->sig == EVP_PKEY_RSA) + continue; + + if (!tls1_lookup_md(lu, NULL)) + continue; + + if (!has_usable_dc(s, lu, -1)) + continue; + + tmppkey = s->cert->dc_pkeys[lu->sig_idx].privatekey; + + if (lu->sig == EVP_PKEY_EC + # ifndef OPENSSL_NO_SM2 + || lu->sig == EVP_PKEY_SM2 +# endif + ) { +#ifndef OPENSSL_NO_EC + if (curve == -1) { + EC_KEY *ec = EVP_PKEY_get0_EC_KEY(tmppkey); + curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); + } + if (lu->curve != NID_undef && curve != lu->curve) + continue; +#else + continue; +#endif + } else if (lu->sig == EVP_PKEY_RSA_PSS) { + /* validate that key is large enough for the signature algorithm */ + if (!rsa_pss_check_min_key_size(EVP_PKEY_get0(tmppkey), lu)) + continue; + } + break; + } + + if (i == s->shared_dc_sigalgslen) + return NULL; + + return lu; +} + +int tls1_set_shared_dc_sigalgs(SSL *s) +{ + const uint16_t *pref, *allow, *conf; + size_t preflen, allowlen, conflen; + size_t nmatch; + const SIGALG_LOOKUP **salgs = NULL; + unsigned int is_suiteb = tls1_suiteb(s); + + OPENSSL_free(s->shared_dc_sigalgs); + s->shared_dc_sigalgs = NULL; + s->shared_dc_sigalgslen = 0; + + conflen = tls12_get_psigalgs(s, 0, &conf); + + if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || is_suiteb) { + pref = conf; + preflen = conflen; + allow = s->s3->tmp.peer_dc_sigalgs; + allowlen = s->s3->tmp.peer_dc_sigalgslen; + } else { + allow = conf; + allowlen = conflen; + pref = s->s3->tmp.peer_dc_sigalgs; + preflen = s->s3->tmp.peer_dc_sigalgslen; + } + + nmatch = tls12_shared_sigalgs(s, NULL, pref, preflen, allow, allowlen); + if (nmatch) { + if ((salgs = OPENSSL_malloc(nmatch * sizeof(*salgs))) == NULL) { + SSLerr(SSL_F_TLS1_SET_SHARED_DC_SIGALGS, ERR_R_MALLOC_FAILURE); + return 0; + } + nmatch = tls12_shared_sigalgs(s, salgs, pref, preflen, allow, allowlen); + } else { + salgs = NULL; + } + + s->shared_dc_sigalgs = salgs; + s->shared_dc_sigalgslen = nmatch; + return 1; +} +#endif + +int tls1_lookup_sigalg_by_pkey_and_hash(EVP_PKEY *pkey, int hash, int is_tls13, + uint16_t *psigalg) +{ + int md_nid = hash; + int def_nid, def_ret; + size_t i; + size_t sig_idx; +#ifndef OPENSSL_NO_EC + int curve_nid = NID_undef; + const EC_GROUP *group = NULL; +#endif + const SIGALG_LOOKUP *s; + + if (ssl_cert_lookup_by_pkey(pkey, &sig_idx) == NULL) { + return 0; + } + + def_ret = EVP_PKEY_get_default_digest_nid(pkey, &def_nid); + if (def_ret == 2) { + md_nid = def_nid; + } else if (def_ret == 1) { + if (md_nid == NID_undef) { + md_nid = def_nid; + } + } + +#ifndef OPENSSL_NO_EC + if (sig_idx == SSL_PKEY_ECC +#if (!defined OPENSSL_NO_SM2) && (!defined OPENSSL_NO_SM3) + || sig_idx == SSL_PKEY_SM2 +#endif + ) { + group = EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey)); + + if (group) { + curve_nid = EC_GROUP_get_curve_name(group); + } + } +#endif + + for (i = 0, s = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl); + i++, s++) { + + if (is_tls13) { + /* Skip SHA1, SHA224, DSA and RSA if not PSS */ + if (s->hash == NID_sha1 + || s->hash == NID_sha224 + || s->sig == EVP_PKEY_DSA + || s->sig == EVP_PKEY_RSA) + continue; + } + + if (s->sig_idx != (int)sig_idx) + continue; + + if (s->hash != NID_undef && s->hash != md_nid) + continue; + +#ifndef OPENSSL_NO_EC + if (s->curve != curve_nid) + continue; +#endif + if (psigalg) + *psigalg = s->sigalg; + + break; + } + + if (i == OSSL_NELEM(sigalg_lookup_tbl)) + return 0; + + return 1; +} + diff --git a/test/build.info b/test/build.info index a8ffebf80..4bd8b3d24 100644 --- a/test/build.info +++ b/test/build.info @@ -51,7 +51,8 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=MAIN recordlentest drbgtest drbg_cavs_test sslbuffertest \ time_offset_test pemtest ssl_cert_table_internal_test ciphername_test \ servername_test ocspapitest rsa_mp_test fatalerrtest tls13ccstest \ - sysdefaulttest errtest ssl_ctx_test gosttest + sysdefaulttest errtest ssl_ctx_test gosttest \ + ssl_ntls_api_test SOURCE[versions]=versions.c diff --git a/test/certs/test_rsa_crt.pem b/test/certs/test_rsa_crt.pem index abafc98f6..b36f64a8c 100644 --- a/test/certs/test_rsa_crt.pem +++ b/test/certs/test_rsa_crt.pem @@ -1,19 +1,20 @@ -----BEGIN CERTIFICATE----- -MIIDATCCAekCFHtrL6LgAAo9od9xDpCoG1EqJQgqMA0GCSqGSIb3DQEBCwUAMD0x -CzAJBgNVBAYTAkNOMQswCQYDVQQIDAJDRDEhMB8GA1UECgwYSW50ZXJuZXQgV2lk -Z2l0cyBQdHkgTHRkMB4XDTE5MTExMjAyMjQ0NVoXDTIwMTExMTAyMjQ0NVowPTEL -MAkGA1UEBhMCQ04xCzAJBgNVBAgMAkNEMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRn -aXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsQ+jc -s33WqhynMDJl6tMbwhvobEN3zl65TcWII+chetPwN9xnfNfGDfpu8F/8w47ONRRw -LDCNmM/8tSDJiqtaLaxZF6wHdiWBQR55jUHSwVoy6eVAmOHgArKCloj3xK7HkQz6 -68SalZ1LSePJeIlZycimgFrnSzsP6jbdtA9cMHuMWGBCVb23C8A5+L2C/zO1bo22 -djrtxsm/TiBM39WplXc6OLfaPPI5THDA/EnSyvv7Wur9WSmT/ZZPl0aEPtYwoYLL -SDYgtmjx+7tjqLe+jHZdWUzknaEPFlQU3wlVdTMjbCu7pi0tBp8fk+G4EQX1Vr4W -bkKHAs/UeF95s15HAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAB/MLRHcW2En94Qx -npTZjJ7c05SOgaYXE/E2OEuQeqbekfqdkpxV6YV9CURhYGdbhPh6CO6Z8wy1d1jN -76dNlcKXxxZ9qM2IRllsfJkw/Ao/5eSYX/gxBJx51Yxxj/itwqtrROk5nlyh5hNa -2y+2ANyqJmBDtKU93qHCAeyIDEo5rPqfvazflwfGDu+9zmUUeyMoNQxXMINgbtJb -NQUN74uZXxBoFQiYmfQEEZpr6NNOFkFHXwsE6fsu97SIyz8PLB7o9C3JK3Yhbnnz -forZHIy4STtfWoXAo43uZa0ufRnuVJvXQgjUkBgSqdS8xVEyAbuOJB/w5TBeo6Be -Rd1/wJ0= ------END CERTIFICATE----- +MIIDTzCCAjegAwIBAgIJAIFk+9Cn3ucfMA0GCSqGSIb3DQEBCwUAMD0xCzAJBgNV +BAYTAkNOMQswCQYDVQQIDAJDRDEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ +dHkgTHRkMCAXDTIxMDExNTA4MzYwMVoYDzIxMjAxMjIyMDgzNjAxWjA9MQswCQYD +VQQGEwJDTjELMAkGA1UECAwCQ0QxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMg +UHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANyl2BE3cNuF +f7fil0M62PLjhLmg8ev6l/lq04TeqNYJsMhq7GAkOD5oZHrS4+fe6Iv1hwKi4Zmf +ldIfpfYy0ZBRyufWaXW5hBSs/4DYXbFewZUHEkzx9Ry0S1WxpMsIJDU7VZKC5EYj +eLInOCKRYm7JRn9TQqmhOL7bsa5JS6srvuHnf7TlwBWYoiDWuGLZ7cvPB/huLckb +aJL6lNM7JsJegKeLq+RPgoLAjX2YVC8m3Q2QXLBB/EPpFFOU+LZAiFXhcESn9OnA +LLfjKSnsBWWxXmEZenJaSUDGWH8bpXsP0gFt1Ax02ObCMX5zl4Hnxc+blJh4IVoS +20vcOWJklP0CAwEAAaNQME4wHQYDVR0OBBYEFBixU5cBVWH/yyeixZXCUcHF+T/Y +MB8GA1UdIwQYMBaAFBixU5cBVWH/yyeixZXCUcHF+T/YMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQELBQADggEBAM0eIMFnL+t46580CU6OfflXMpiG8iePpeOoSuI3 +T339vxyPCUVRaS1q4iIv0Jw5rk2B3QbTtuuZD3owdVCdg+vTAinH1w4gqrNOs04J +1MAyfLc7L7zAhBDtpwkR4cAS/j2/fQevYWG1YR63k/xkI5rVMRzTzKECtCuW0+P9 +7imqcNh8I5k3ceHp8sNNAckubpVxqJ+rETp9MH79+D8I2gMiLuT/nROGqYkR9qPq +pqz+WKgUXw8dvg1SvQqwAjIScUCrZ/XbXzGYvZIw7+J/jVTmxGpQSJZH3TqJ6d7w +dkvtirQtWoj0S1xtzXqa6Vt1Tf4BvsA1IEb532Sb7BvTLEs= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/test/certs/test_rsa_key.pem b/test/certs/test_rsa_key.pem index 284d2811e..f18632829 100644 --- a/test/certs/test_rsa_key.pem +++ b/test/certs/test_rsa_key.pem @@ -1,28 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -MIIEpQIBAAKCAQEArEPo3LN91qocpzAyZerTG8Ib6GxDd85euU3FiCPnIXrT8Dfc -Z3zXxg36bvBf/MOOzjUUcCwwjZjP/LUgyYqrWi2sWResB3YlgUEeeY1B0sFaMunl -QJjh4AKygpaI98Sux5EM+uvEmpWdS0njyXiJWcnIpoBa50s7D+o23bQPXDB7jFhg -QlW9twvAOfi9gv8ztW6NtnY67cbJv04gTN/VqZV3Oji32jzyOUxwwPxJ0sr7+1rq -/Vkpk/2WT5dGhD7WMKGCy0g2ILZo8fu7Y6i3vox2XVlM5J2hDxZUFN8JVXUzI2wr -u6YtLQafH5PhuBEF9Va+Fm5ChwLP1HhfebNeRwIDAQABAoIBACVsF0EiqPqiN9lG -ChzD15qXH3LtWfbD2SYONBQwIHzQbwwnRnUg1MsMrFO/WkrRvMslEsyPfPi1srEm -M/o0aqcLdv5fuxpf2yPqHpGvUxZStKKM1yWiUKdWTqs5woV4r7Ng2l4EK9CdIe+C -HL7etY/Q2wr4pUbLvAfoDIU7IX8YGcMWVwSU02d+0XNIhv4I86x/2hCDk+qoIfLW -S62FE4ID8UAL+GLn6d/IHiPBT+vw5s2m9FfrL8HJ2MvmRVnGELGyGqS+8f+jOMhi -2M82I8z3WmQr/VUFCYTUF31kaLVMNq6yZrU6uGdV+yBxisZPutOuOXbjjBmqwLj9 -HcdZwxkCgYEA36BzwA9Unnw5Y08D2i15r0f8EaFN3AAFfm9mfrLLJgB/WJSxAg2J -kXfnDojlARlY0YW4d8MKz+A9+B/uvCrvxDqm4lodryiBIxaAHHfZF/qqBUslupf3 -zcpRabD9cnPNcwaUyRQDS6XRuVf2xbJs7qyaaosvnGdMcfE7LJIqsnMCgYEAxTQD -qN4eDd89J6xdMVOwPwLz0G0qKUStBLM2ExE6u/CpdC8VTiO5kUZHMcecFPg4z1/K -qAqJxDlSIxvOR1mEZPLtAj7A/92OSnMbpqbs7vP2vHUS6ImiPL/bumhFPXKapHWB -dp7oWXHNTIRxA+4BJEuTZfRqz6zCrUw8H8gqK90CgYEAmGSqnMaVvs8e+JsfH+5/ -j0B5+bW37mWhWNEnws2q/QG3xrDFk4WQKy7PqasGjGIukdITrKGg25qQAGgac+a6 -sDncAkKxGe17W2L4+O1/ZwTuGl9knaz0NSxboK/5d6aM6ocgm4rk2AdvTWQxifYW -n+vF6zdgwa/ve3KOBciyChsCgYEAvpVTSBtJ/mwWJUZuVmKj/XG0AmXODk4hzF4K -T4kiM0oV6oQqWfcquxypZ5Ga5aUy+i+AosB0fmBLYkTYKZp42jrwFXBig6Uyg/8U -5Q2EBDdg6KdYm8WQNpfRGij1abpde71YXjSbJv5Vw7Jnqr2U+ufTTwBVTdmP133K -yYhgQT0CgYEAwnvnoIIpesOnBOh03WSCGd7n7jGa5m0kWjq04odYt10LlCiIcGVn -Nf0bizYHL6xHMFJZbNRWDAolEv8+3Vx6pJI/+FA0Xbdo2dbRWE+XPFG1bBQ5vwqT -o38OxpwGRkwQUMSx9rX1AUt6iuSZeEeimFCxhEp7JjUQ5wzTftiUu4Y= ------END RSA PRIVATE KEY----- - +MIIEpAIBAAKCAQEA3KXYETdw24V/t+KXQzrY8uOEuaDx6/qX+WrThN6o1gmwyGrs +YCQ4PmhketLj597oi/WHAqLhmZ+V0h+l9jLRkFHK59ZpdbmEFKz/gNhdsV7BlQcS +TPH1HLRLVbGkywgkNTtVkoLkRiN4sic4IpFibslGf1NCqaE4vtuxrklLqyu+4ed/ +tOXAFZiiINa4Ytnty88H+G4tyRtokvqU0zsmwl6Ap4ur5E+CgsCNfZhULybdDZBc +sEH8Q+kUU5T4tkCIVeFwRKf06cAst+MpKewFZbFeYRl6clpJQMZYfxulew/SAW3U +DHTY5sIxfnOXgefFz5uUmHghWhLbS9w5YmSU/QIDAQABAoIBAEXiTRXe3mLY3IPM +Q6ZqfA4p237Dp/vaqcm4ePfrYcQw24oOu4ET17CEddak9sQYyMSTZkiCeDuk3Nnp +ZjIdFFzGWyKkuVAtCtVVmbMgVER6Q4vE6pnuRHjr7bRdiFk54eXuPgMia9R/JZof +a9se+vMl0qs/Hq0FQCjLAnK2Cj5TDObdWZ4z19/+8yWXgf8DxQRawKyUnOyT6Qr6 +sSxgCwAzZcnZcGHpmjIpiNGaXKn9wThb2L9Fq7tx6hOdPKUMUaYYW5nhzoBrWotP +ttVbCMZhOBCIF+bYZL2Ddg1awyUnTKqf8rwCNL6yBFHz8AJueaK9yAnNuuMdp47C +v+D8P20CgYEA+nlhL61KlmjiWGDz9zBbsnCH7F9aro1jwKYXxh7j/dTuTi37ZjBr +7dqrwvakv4BKWOMyDxS9esUqd7TvRiM2UPF7H8y4orq1j2QJogt1Y8H+5YujPvOp +suyxw1blLLVA+ugoaDAllKAZqg0H0j/2SRtT+K9rqp8elNihBnznvI8CgYEA4YQD +IYCKJ4Sxaiq1MEnEyiYQGfdC3NCuAPXBvYLbZ23YtXAdEKpnqvU3X6VjN6+7XK+B +GynM6ffWECaHzHh2W4X4dDtWPJw3dV9EXlHoIdNT+Dn2iqNBCeQ9lWGgRaPsV+t4 +cHYeGOnqaavNmQ0HJ9yOBZxjcPXTf2MoRZWg87MCgYAOKu13X+r3JQmgjCNgmQim +yDy3/xDHDNJWpE5182tcAT5Vh75Pom+IbbUHeyIIfv41luxO9BJfrmVfjgl2wykg +XPhk7RSIh90bNkJhOxqxwNhlLYfXWLsBlufbL8AYzkvVpWobspV9may59LC7kMii +i/ws9ec2KHf3XWWGU2xcOwKBgQDHZe1Kwxfk50vjfo2ke6V3w/36p4lEK3OfP60l +fr22jwbNLqtUYAe3vohOlrLKuyQkSL4UIXqg6VUqBJeQMHceZ6+OPiT7BHl421pd +N3jT58JYOhAG92B7eYcGPUL0MIO6HWbpsVbdWn69Hn50tHM+SKJ+zY+TgpiWCzvB +gxLERwKBgQDntcpY0gbVGX8nOm7+EKLAeYV6nHzKG9V7wS8cK6I58O0hT0Zt0bgE +F15QRTgcWbqRuNGw9/PWaaGpM3MW1bQnap2Cd1+9dlapZjL6jP2f4o824m/QNHBw +LbQ5tfjY+TqfOSHwOlztoFnbI/xVl+6BcUTLrXPMsoBVT9LciW6R2Q== +-----END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/test/ciphername_test.c b/test/ciphername_test.c index ffe7589c1..1cc6de7e5 100644 --- a/test/ciphername_test.c +++ b/test/ciphername_test.c @@ -438,7 +438,7 @@ static int test_cipher_name(void) continue; #if (!defined OPENSSL_NO_NTLS) && (!defined OPENSSL_NO_SM2) \ && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) - if ((id == 0xE011) || (id == 0xE013) || (id == 0xE019) || (id == 0xE01a)) + if ((id == 0xE011) || (id == 0xE051) || (id == 0xE013) || (id == 0xE053)) /* skip GM/T cipher suites who have no standard TLS names */ continue; #endif diff --git a/test/handshake_helper.c b/test/handshake_helper.c index 3323e5526..345adbad5 100644 --- a/test/handshake_helper.c +++ b/test/handshake_helper.c @@ -1420,6 +1420,31 @@ static int create_sctp_socks(int *ssock, int *csock) * in cleaner argument passing but would complicate the test configuration * parsing.) */ +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +static ssl_test_dc_usage_t get_ssl_dc_usage(SSL *s) +{ + int dc_tag = SSL_get_delegated_credential_tag(s); + + switch (dc_tag) + { + case DC_HAS_BEEN_USED_FOR_VERIFY_PEER: + case DC_REQ_HAS_BEEN_SEND_TO_PEER|DC_HAS_BEEN_USED_FOR_VERIFY_PEER: + return SSL_VERIFY_PEER_BY_DC_ONLY; + + case DC_HAS_BEEN_USED_FOR_SIGN: + case DC_REQ_HAS_BEEN_SEND_TO_PEER|DC_HAS_BEEN_USED_FOR_SIGN: + return SSL_SIGN_BY_DC_ONLY; + + case DC_HAS_BEEN_USED_FOR_SIGN|DC_HAS_BEEN_USED_FOR_VERIFY_PEER: + case DC_REQ_HAS_BEEN_SEND_TO_PEER|DC_HAS_BEEN_USED_FOR_SIGN|DC_HAS_BEEN_USED_FOR_VERIFY_PEER: + return SSL_VERIFY_PEER_AND_SIGN_BY_DC; + + default: + return SSL_NOT_USE_DC; + } +} +#endif + static HANDSHAKE_RESULT *do_handshake_internal( SSL_CTX *server_ctx, SSL_CTX *server2_ctx, SSL_CTX *client_ctx, const SSL_TEST_CTX *test_ctx, const SSL_TEST_EXTRA_CONF *extra, @@ -1733,6 +1758,10 @@ static HANDSHAKE_RESULT *do_handshake_internal( ret->server_cert_type = peer_pkey_type(client.ssl); ret->client_cert_type = peer_pkey_type(server.ssl); +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + ret->client_dc_usage = get_ssl_dc_usage(client.ssl); + ret->server_dc_usage = get_ssl_dc_usage(server.ssl); +#endif ctx_data_free_data(&server_ctx_data); ctx_data_free_data(&server2_ctx_data); ctx_data_free_data(&client_ctx_data); diff --git a/test/handshake_helper.h b/test/handshake_helper.h index 96406dd93..46d9328bd 100644 --- a/test/handshake_helper.h +++ b/test/handshake_helper.h @@ -67,6 +67,10 @@ typedef struct handshake_result { char *cipher; /* session ticket application data */ char *result_session_ticket_app_data; +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + int client_dc_usage; + int server_dc_usage; +#endif } HANDSHAKE_RESULT; HANDSHAKE_RESULT *HANDSHAKE_RESULT_new(void); diff --git a/test/recipes/80-test_dc_sign.t b/test/recipes/80-test_dc_sign.t new file mode 100644 index 000000000..e06119409 --- /dev/null +++ b/test/recipes/80-test_dc_sign.t @@ -0,0 +1,72 @@ +use strict; +use warnings; + +use POSIX; +use File::Spec::Functions qw/splitdir curdir catfile/; +use File::Compare; +use OpenSSL::Test qw/:DEFAULT data_file data_dir cmdstr srctop_file/; +use OpenSSL::Test::Utils; + +setup("test_dc_sign"); + +$ENV{DATADIR} = data_dir(); + +plan skip_all => "dc_sign is not supported by this OpenSSL build" + if disabled("delegated-credential"); + +plan tests => 10; + +ok(run(cmd(["sh", data_file("sign_dc.sh")]))); + +# sign client dc +ok(run(app(["openssl", "delecred", "-new", "-client", "-sec", "604800", + "-dc_key", data_file("dc-ecc-client-longterm.key"), + "-out", data_file("dc-ecc-client-longterm.dc"), + "-parent_cert", data_file("dc-ecc-leaf.crt"), + "-parent_key", data_file("dc-ecc-leaf.key"), + "-expect_verify_md", "sha256", "-sha256"]))); + +ok(run(app(["openssl", "delecred", + "-in", data_file("dc-ecc-client-longterm.dc"), + "-text", "-noout"]))); + +# sign server dc +ok(run(app(["openssl", "delecred", "-new", "-server", "-sec", "604800", + "-dc_key", data_file("dc-ecc-server-longterm.key"), + "-out", data_file("dc-server.dc.tmp"), + "-parent_cert", data_file("dc-ecc-leaf.crt"), + "-parent_key", data_file("dc-ecc-leaf.key"), + "-expect_verify_md", "sha256", "-sha256"]))); + +ok(run(app(["openssl", "delecred", + "-in", data_file("dc-server.dc.tmp"), + "-text", "-noout"]))); + +# valid time too large +ok(!run(app(["openssl", "delecred", "-new", "-server", "-sec", "604801", + "-dc_key", data_file("dc-ecc-server-longterm.key"), + "-out", data_file("dc-server.dc.tmp"), + "-parent_cert", data_file("dc-ecc-leaf.crt"), + "-parent_key", data_file("dc-ecc-leaf.key"), + "-expect_verify_md", "sha256", "-sha256"]))); +# default md +ok(run(app(["openssl", "delecred", "-new", "-client", "-sec", "604800", + "-dc_key", data_file("dc-ecc-client-longterm.key"), + "-out", data_file("dc-ecc-client-longterm.dc"), + "-parent_cert", data_file("dc-ecc-leaf.crt"), + "-parent_key", data_file("dc-ecc-leaf.key"), + "-expect_verify_md", "sha256"]))); + +ok(run(app(["openssl", "delecred", + "-in", data_file("dc-ecc-client-longterm.dc"), + "-text", "-noout"]))); + +# default expect verify md +ok(run(app(["openssl", "delecred", "-new", "-server", "-sec", "604800", + "-dc_key", data_file("dc-ecc-server-longterm.key"), + "-out", data_file("dc-ecc-server-longterm.key"), + "-parent_cert", data_file("dc-ecc-leaf.crt"), + "-parent_key", data_file("dc-ecc-leaf.key")]))); + +ok(run(app(["openssl", "delecred", "-in", data_file("dc-ecc-server-longterm.key"), + "-text", "-noout"]))); \ No newline at end of file diff --git a/test/recipes/80-test_dc_sign_data/openssl.cnf b/test/recipes/80-test_dc_sign_data/openssl.cnf new file mode 100644 index 000000000..577e36b6c --- /dev/null +++ b/test/recipes/80-test_dc_sign_data/openssl.cnf @@ -0,0 +1,144 @@ +[ ca ] +# `man ca` +default_ca = CA_default + +[ CA_default ] +# Directory and file locations. +dir = ./ +certs = $dir/certs +crl_dir = $dir/crl +new_certs_dir = $dir/newcerts +database = $dir/db/index +unique_subject = no +serial = $dir/db/serial +RANDFILE = $dir/private/random + +# The root key and root certificate. +private_key = $dir/dc-ecc-root.key +certificate = $dir/dc-ecc-root.crt + +# For certificate revocation lists. +crlnumber = $dir/crl/crlnumber +crl = $dir/crl/ca.crl.pem +crl_extensions = crl_ext +default_crl_days = 30 + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sm3 + +name_opt = ca_default +cert_opt = ca_default +default_days = 365 +preserve = no +policy = policy_strict + +[ policy_strict ] +# The root CA should only sign intermediate certificates that match. +# See the POLICY FORMAT section of `man ca`. +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ policy_loose ] +# Allow the intermediate CA to sign a more diverse range of certificates. +# See the POLICY FORMAT section of the `ca` man page. +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ req ] +# Options for the `req` tool (`man req`). +default_bits = 2048 +distinguished_name = req_distinguished_name +string_mask = utf8only + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sha256 + +# Extension to add when the -x509 option is used. +x509_extensions = v3_ca + +req_extensions = v3_req + +[ req_distinguished_name ] +# See . +countryName = optional +stateOrProvinceName = optional +localityName = optional +0.organizationName = optional +organizationalUnitName = optional +commonName = optional +emailAddress = optional + +# Optionally, specify some defaults. +countryName_default = CN +stateOrProvinceName_default = China +localityName_default = +0.organizationName_default = Alipay +#organizationalUnitName_default = +#emailAddress_default = + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +subjectAltName = @alt_names + +[ alt_names ] +DNS.1 = alipay.com +DNS.2 = *.alipay.com + +[ v3_ca ] +# Extensions for a typical CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ v3_intermediate_ca ] +# Extensions for a typical intermediate CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true, pathlen:0 +keyUsage = critical, digitalSignature, cRLSign, keyCertSign +[ usr_cert ] +# Extensions for client certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = client, email +nsComment = "OpenSSL Generated Client Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment +extendedKeyUsage = clientAuth, emailProtection + +[ server_cert ] +# Extensions for server certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = server +nsComment = "OpenSSL Generated Server Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always +keyUsage = critical, digitalSignature, keyEncipherment +extendedKeyUsage = serverAuth +subjectAltName = @alt_names +delegationUsage = .. +[ crl_ext ] +# Extension for CRLs (`man x509v3_config`). +authorityKeyIdentifier=keyid:always + +[ ocsp ] +# Extension for OCSP signing certificates (`man ocsp`). +basicConstraints = CA:FALSE +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, digitalSignature +extendedKeyUsage = critical, OCSPSigning diff --git a/test/recipes/80-test_dc_sign_data/openssl_middleca.cnf b/test/recipes/80-test_dc_sign_data/openssl_middleca.cnf new file mode 100644 index 000000000..56d3151fe --- /dev/null +++ b/test/recipes/80-test_dc_sign_data/openssl_middleca.cnf @@ -0,0 +1,146 @@ +[ ca ] +# `man ca` +default_ca = CA_default + +[ CA_default ] +# Directory and file locations. +dir = ./ +certs = $dir/certs +crl_dir = $dir/crl +new_certs_dir = $dir/newcerts +database = $dir/db/index +unique_subject = no +serial = $dir/db/serial +RANDFILE = $dir/private/random + +# The root key and root certificate. +private_key = $dir/dc-ecc-middle-ca.key +certificate = $dir/dc-ecc-middle-ca.crt + +# For certificate revocation lists. +crlnumber = $dir/crlnumber +crl = $dir/crl/ca.crl.pem +crl_extensions = crl_ext +default_crl_days = 30 + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sm3 + +name_opt = ca_default +cert_opt = ca_default +default_days = 365 +preserve = no +policy = policy_strict + +[ policy_strict ] +# The root CA should only sign intermediate certificates that match. +# See the POLICY FORMAT section of `man ca`. +countryName = optional +stateOrProvinceName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ policy_loose ] +# Allow the intermediate CA to sign a more diverse range of certificates. +# See the POLICY FORMAT section of the `ca` man page. +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ req ] +# Options for the `req` tool (`man req`). +default_bits = 2048 +distinguished_name = req_distinguished_name +string_mask = utf8only + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sha256 + +# Extension to add when the -x509 option is used. +x509_extensions = v3_ca + +req_extensions = v3_req + +[ req_distinguished_name ] +# See . +countryName = optional +stateOrProvinceName = optional +localityName = optional +0.organizationName = optional +organizationalUnitName = optional +commonName = optional +emailAddress = optional + +# Optionally, specify some defaults. +countryName_default = CN +stateOrProvinceName_default = China +localityName_default = +0.organizationName_default = Alipay +#organizationalUnitName_default = +#emailAddress_default = + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +subjectAltName = @alt_names + +[ alt_names ] +DNS.1 = alipay.com +DNS.2 = *.alipay.com + +[ v3_ca ] +# Extensions for a typical CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ v3_intermediate_ca ] +# Extensions for a typical intermediate CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true, pathlen:0 +keyUsage = critical, digitalSignature, cRLSign, keyCertSign +[ usr_cert ] +# Extensions for client certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = client, email +nsComment = "OpenSSL Generated Client Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment +extendedKeyUsage = clientAuth, emailProtection +delegationUsage = serverDelegation, clientDelegation + +[ server_cert ] +# Extensions for server certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = server +nsComment = "OpenSSL Generated Server Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always +keyUsage = critical, digitalSignature, keyEncipherment +extendedKeyUsage = serverAuth +subjectAltName = @alt_names +delegationUsage = serverDelegation, clientDelegation + +[ crl_ext ] +# Extension for CRLs (`man x509v3_config`). +authorityKeyIdentifier=keyid:always + +[ ocsp ] +# Extension for OCSP signing certificates (`man ocsp`). +basicConstraints = CA:FALSE +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, digitalSignature +extendedKeyUsage = critical, OCSPSigning diff --git a/test/recipes/80-test_dc_sign_data/sign_dc.sh b/test/recipes/80-test_dc_sign_data/sign_dc.sh new file mode 100644 index 000000000..afd5e9f6a --- /dev/null +++ b/test/recipes/80-test_dc_sign_data/sign_dc.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +set -e + +O_EXE=`pwd`/$BLDTOP/apps +O_LIB=`pwd`/$BLDTOP + +export PATH=$O_EXE:$PATH +export LD_LIBRARY_PATH=$O_LIB:$LD_LIBRARY_PATH + +echo $DATADIR +which openssl + +cd $DATADIR + +rm -rf {newcerts,db,private,crl} +mkdir {newcerts,db,private,crl} +touch db/{index,serial} +echo 00 > db/serial + +# ca +openssl genpkey -algorithm ec -pkeyopt ec_paramgen_curve:P-256 -out dc-ecc-root.key + +openssl req -config openssl.cnf -new -key dc-ecc-root.key -out dc-ecc-root.csr -sha256 -subj "/C=AA/ST=BB/O=CC/OU=DD/CN=root ca" -batch + +openssl ca -selfsign -config openssl.cnf -in dc-ecc-root.csr -extensions v3_ca -days 3650 -out dc-ecc-root.crt -md sha256 -batch + +# middle ca +openssl genpkey -algorithm ec -pkeyopt ec_paramgen_curve:P-256 -out dc-ecc-middle-ca.key + +openssl req -config openssl.cnf -new -key dc-ecc-middle-ca.key -out dc-ecc-middle-ca.csr -sha256 -subj "/C=AA/ST=BB/O=CC/OU=DD/CN=middle ca" -batch + +openssl ca -config openssl.cnf -extensions v3_intermediate_ca -days 3650 -in dc-ecc-middle-ca.csr -out dc-ecc-middle-ca.crt -md sha256 -batch + +cat dc-ecc-root.crt dc-ecc-middle-ca.crt > dc-ecc-chain-ca.crt + +# server +openssl genpkey -algorithm ec -pkeyopt ec_paramgen_curve:P-256 -out dc-ecc-leaf.key + +openssl req -config openssl_middleca.cnf -new -key dc-ecc-leaf.key -out dc-ecc-leaf.csr -sha256 -subj "/C=AA/ST=BB/O=CC/OU=DD/CN=server" -batch + +openssl ca -config openssl_middleca.cnf -extensions server_cert -days 3650 -in dc-ecc-leaf.csr -out dc-ecc-leaf.crt -md sha256 -batch + +# client +openssl genpkey -algorithm ec -pkeyopt ec_paramgen_curve:P-256 -out dc-ecc-leaf-clientUse.key + +openssl req -config openssl_middleca.cnf -new -key dc-ecc-leaf-clientUse.key -out dc-ecc-leaf-clientUse.csr -sha256 -subj "/C=AA/ST=BB/O=CC/OU=DD/CN=client" -batch + +openssl ca -config openssl_middleca.cnf -extensions usr_cert -days 3650 -in dc-ecc-leaf-clientUse.csr -out dc-ecc-leaf-clientUse.crt -md sha256 -batch + +# server dc +openssl genpkey -algorithm ec -pkeyopt ec_paramgen_curve:P-256 -out dc-ecc-server-longterm.key + +openssl delecred -new -server -sec 604800 -dc_key dc-ecc-server-longterm.key -out dc-ecc-server-longterm.dc -parent_cert dc-ecc-leaf.crt -parent_key dc-ecc-leaf.key -expect_verify_md sha256 -sha256 + +# client dc +openssl genpkey -algorithm ec -pkeyopt ec_paramgen_curve:P-256 -out dc-ecc-client-longterm.key + +openssl delecred -new -client -sec 604800 -dc_key dc-ecc-client-longterm.key -out dc-ecc-client-longterm.dc -parent_cert dc-ecc-leaf-clientUse.crt -parent_key dc-ecc-leaf-clientUse.key -expect_verify_md sha256 -sha256 + +# server expire dc +openssl genpkey -algorithm ec -pkeyopt ec_paramgen_curve:P-256 -out dc-ecc-server-expire.key + +openssl delecred -new -server -sec 1 -dc_key dc-ecc-server-expire.key -out dc-ecc-server-expire.dc -parent_cert dc-ecc-leaf.crt -parent_key dc-ecc-leaf.key -expect_verify_md sha256 -sha256 + +# client expire dc +openssl genpkey -algorithm ec -pkeyopt ec_paramgen_curve:P-256 -out dc-ecc-client-expire.key + +openssl delecred -new -client -sec 1 -dc_key dc-ecc-client-expire.key -out dc-ecc-client-expire.dc -parent_cert dc-ecc-leaf-clientUse.crt -parent_key dc-ecc-leaf-clientUse.key -expect_verify_md sha256 -sha256 + +cp -r *.crt ../../certs +cp -r *.key ../../certs +cp -r *.dc ../../certs diff --git a/test/recipes/80-test_ssl_new.t b/test/recipes/80-test_ssl_new.t index 72ba9795e..73195330e 100644 --- a/test/recipes/80-test_ssl_new.t +++ b/test/recipes/80-test_ssl_new.t @@ -28,7 +28,7 @@ map { s/\^// } @conf_files if $^O eq "VMS"; # We hard-code the number of tests to double-check that the globbing above # finds all files as expected. -plan tests => 37; # = scalar @conf_srcs +plan tests => 32; # = scalar @conf_srcs # Some test results depend on the configuration of enabled protocols. We only # verify generated sources in the default configuration. @@ -105,12 +105,7 @@ my %skip = ( "29-dtls-sctp-label-bug.conf" => disabled("sctp") || disabled("sock"), "30-tls13-sm.conf" => disabled("sm2") || disabled("sm3") || disabled("sm4"), "31-ntls.conf" => disabled("ntls") || disabled("sm2") || disabled("sm3") || disabled("sm4"), - "32-keyless-normal.conf" => disabled("keyless"), - "33-keyless-tls13-sm.conf" => disabled("keyless") || disabled("sm2") || disabled("sm3") || disabled("sm4"), - "34-keyless-ntls.conf" => disabled("ntls") || disabled("keyless") || disabled("sm2") || disabled("sm3") || disabled("sm4"), - "35-lurk-normal.conf" => disabled("lurk"), - "36-lurk-tls13-sm.conf" => disabled("lurk") || disabled("sm2") || disabled("sm3") || disabled("sm4"), - "37-lurk-ntls.conf" => disabled("ntls") || disabled("lurk") || disabled("sm2") || disabled("sm3") || disabled("sm4"), + "38-delegated-credential.conf" => disabled("delegated-credential"), ); foreach my $conf (@conf_files) { diff --git a/test/recipes/88-test_ssl_ntls_api.t b/test/recipes/88-test_ssl_ntls_api.t new file mode 100644 index 000000000..310a383a0 --- /dev/null +++ b/test/recipes/88-test_ssl_ntls_api.t @@ -0,0 +1,18 @@ +#! /usr/bin/env perl + +use strict; +use OpenSSL::Test; +use OpenSSL::Test::Simple; +use OpenSSL::Test::Utils; +use OpenSSL::Test qw/:DEFAULT srctop_file srctop_dir/; +use File::Temp qw(tempfile); + +setup("test_ssl_ntls_api"); + +plan tests => 1; + +ok(run(test(["ssl_ntls_api_test", + srctop_file("test", "certs", "SS.cert.pem"), + srctop_file("test", "certs", "SS.key.pem"), + srctop_file("test", "certs", "SE.cert.pem"), + srctop_file("test", "certs", "SE.key.pem")]))); diff --git a/test/ssl-tests/31-ntls.conf b/test/ssl-tests/31-ntls.conf index 837119c15..f0e705961 100644 --- a/test/ssl-tests/31-ntls.conf +++ b/test/ssl-tests/31-ntls.conf @@ -1,20 +1,22 @@ # Generated with generate_ssl_tests.pl -num_tests = 3 +num_tests = 5 -test-0 = 0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only -test-1 = 1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode -test-2 = 2-test ntls client doing handshake without setting certs and pkey +test-0 = 0-test cipher ECC-SM2-SM4-CBC-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only +test-1 = 1-test cipher ECC-SM2-SM4-GCM-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only +test-2 = 2-test cipher ECDHE-SM2-SM4-CBC-SM3 in NTLS_UNIQUE mode +test-3 = 3-test cipher ECDHE-SM2-SM4-GCM-SM3 in NTLS_UNIQUE mode +test-4 = 4-test ntls client doing handshake without setting certs and pkey # =========================================================== -[0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only] -ssl_conf = 0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-ssl +[0-test cipher ECC-SM2-SM4-CBC-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only] +ssl_conf = 0-test cipher ECC-SM2-SM4-CBC-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-ssl -[0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-ssl] -server = 0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-server -client = 0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-client +[0-test cipher ECC-SM2-SM4-CBC-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-ssl] +server = 0-test cipher ECC-SM2-SM4-CBC-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-server +client = 0-test cipher ECC-SM2-SM4-CBC-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-client -[0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-server] +[0-test cipher ECC-SM2-SM4-CBC-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT Enable_ntls = on @@ -24,14 +26,14 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem SignCertificate = ${ENV::TEST_CERTS_DIR}/SS.cert.pem SignPrivateKey = ${ENV::TEST_CERTS_DIR}/SS.key.pem -[0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-client] -CipherString = ECC-SM2-WITH-SM4-SM3 +[0-test cipher ECC-SM2-SM4-CBC-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-client] +CipherString = ECC-SM2-SM4-CBC-SM3 Enable_ntls = on VerifyCAFile = ${ENV::TEST_CERTS_DIR}/CA.cert.pem VerifyMode = Peer [test-0] -ExpectedCipher = ECC-SM2-WITH-SM4-SM3 +ExpectedCipher = ECC-SM2-SM4-CBC-SM3 ExpectedProtocol = NTLS ExpectedResult = Success Method = NTLS @@ -39,14 +41,14 @@ Method = NTLS # =========================================================== -[1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode] -ssl_conf = 1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode-ssl +[1-test cipher ECC-SM2-SM4-GCM-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only] +ssl_conf = 1-test cipher ECC-SM2-SM4-GCM-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-ssl -[1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode-ssl] -server = 1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode-server -client = 1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode-client +[1-test cipher ECC-SM2-SM4-GCM-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-ssl] +server = 1-test cipher ECC-SM2-SM4-GCM-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-server +client = 1-test cipher ECC-SM2-SM4-GCM-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-client -[1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode-server] +[1-test cipher ECC-SM2-SM4-GCM-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT Enable_ntls = on @@ -55,10 +57,42 @@ EncPrivateKey = ${ENV::TEST_CERTS_DIR}/SE.key.pem PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem SignCertificate = ${ENV::TEST_CERTS_DIR}/SS.cert.pem SignPrivateKey = ${ENV::TEST_CERTS_DIR}/SS.key.pem + +[1-test cipher ECC-SM2-SM4-GCM-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-client] +CipherString = ECC-SM2-SM4-GCM-SM3 +Enable_ntls = on VerifyCAFile = ${ENV::TEST_CERTS_DIR}/CA.cert.pem +VerifyMode = Peer + +[test-1] +ExpectedCipher = ECC-SM2-SM4-GCM-SM3 +ExpectedProtocol = NTLS +ExpectedResult = Success +Method = NTLS + + +# =========================================================== -[1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode-client] -CipherString = ECDHE-SM2-WITH-SM4-SM3 +[2-test cipher ECDHE-SM2-SM4-CBC-SM3 in NTLS_UNIQUE mode] +ssl_conf = 2-test cipher ECDHE-SM2-SM4-CBC-SM3 in NTLS_UNIQUE mode-ssl + +[2-test cipher ECDHE-SM2-SM4-CBC-SM3 in NTLS_UNIQUE mode-ssl] +server = 2-test cipher ECDHE-SM2-SM4-CBC-SM3 in NTLS_UNIQUE mode-server +client = 2-test cipher ECDHE-SM2-SM4-CBC-SM3 in NTLS_UNIQUE mode-client + +[2-test cipher ECDHE-SM2-SM4-CBC-SM3 in NTLS_UNIQUE mode-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +Enable_ntls = on +EncCertificate = ${ENV::TEST_CERTS_DIR}/SE.cert.pem +EncPrivateKey = ${ENV::TEST_CERTS_DIR}/SE.key.pem +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem +SignCertificate = ${ENV::TEST_CERTS_DIR}/SS.cert.pem +SignPrivateKey = ${ENV::TEST_CERTS_DIR}/SS.key.pem +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/CA.cert.pem + +[2-test cipher ECDHE-SM2-SM4-CBC-SM3 in NTLS_UNIQUE mode-client] +CipherString = ECDHE-SM2-SM4-CBC-SM3 Enable_ntls = on EncCertificate = ${ENV::TEST_CERTS_DIR}/CE.cert.pem EncPrivateKey = ${ENV::TEST_CERTS_DIR}/CE.key.pem @@ -67,8 +101,8 @@ SignPrivateKey = ${ENV::TEST_CERTS_DIR}/CS.key.pem VerifyCAFile = ${ENV::TEST_CERTS_DIR}/CA.cert.pem VerifyMode = Peer -[test-1] -ExpectedCipher = ECDHE-SM2-WITH-SM4-SM3 +[test-2] +ExpectedCipher = ECDHE-SM2-SM4-CBC-SM3 ExpectedProtocol = NTLS ExpectedResult = Success Method = NTLS @@ -76,26 +110,63 @@ Method = NTLS # =========================================================== -[2-test ntls client doing handshake without setting certs and pkey] -ssl_conf = 2-test ntls client doing handshake without setting certs and pkey-ssl +[3-test cipher ECDHE-SM2-SM4-GCM-SM3 in NTLS_UNIQUE mode] +ssl_conf = 3-test cipher ECDHE-SM2-SM4-GCM-SM3 in NTLS_UNIQUE mode-ssl -[2-test ntls client doing handshake without setting certs and pkey-ssl] -server = 2-test ntls client doing handshake without setting certs and pkey-server -client = 2-test ntls client doing handshake without setting certs and pkey-client +[3-test cipher ECDHE-SM2-SM4-GCM-SM3 in NTLS_UNIQUE mode-ssl] +server = 3-test cipher ECDHE-SM2-SM4-GCM-SM3 in NTLS_UNIQUE mode-server +client = 3-test cipher ECDHE-SM2-SM4-GCM-SM3 in NTLS_UNIQUE mode-client -[2-test ntls client doing handshake without setting certs and pkey-server] +[3-test cipher ECDHE-SM2-SM4-GCM-SM3 in NTLS_UNIQUE mode-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT Enable_ntls = on +EncCertificate = ${ENV::TEST_CERTS_DIR}/SE.cert.pem +EncPrivateKey = ${ENV::TEST_CERTS_DIR}/SE.key.pem PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem +SignCertificate = ${ENV::TEST_CERTS_DIR}/SS.cert.pem +SignPrivateKey = ${ENV::TEST_CERTS_DIR}/SS.key.pem +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/CA.cert.pem + +[3-test cipher ECDHE-SM2-SM4-GCM-SM3 in NTLS_UNIQUE mode-client] +CipherString = ECDHE-SM2-SM4-GCM-SM3 +Enable_ntls = on +EncCertificate = ${ENV::TEST_CERTS_DIR}/CE.cert.pem +EncPrivateKey = ${ENV::TEST_CERTS_DIR}/CE.key.pem +SignCertificate = ${ENV::TEST_CERTS_DIR}/CS.cert.pem +SignPrivateKey = ${ENV::TEST_CERTS_DIR}/CS.key.pem +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/CA.cert.pem +VerifyMode = Peer + +[test-3] +ExpectedCipher = ECDHE-SM2-SM4-GCM-SM3 +ExpectedProtocol = NTLS +ExpectedResult = Success +Method = NTLS + + +# =========================================================== + +[4-test ntls client doing handshake without setting certs and pkey] +ssl_conf = 4-test ntls client doing handshake without setting certs and pkey-ssl + +[4-test ntls client doing handshake without setting certs and pkey-ssl] +server = 4-test ntls client doing handshake without setting certs and pkey-server +client = 4-test ntls client doing handshake without setting certs and pkey-client -[2-test ntls client doing handshake without setting certs and pkey-client] -CipherString = ECC-SM2-WITH-SM4-SM3 +[4-test ntls client doing handshake without setting certs and pkey-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +Enable_ntls = on +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[4-test ntls client doing handshake without setting certs and pkey-client] +CipherString = ECC-SM2-SM4-CBC-SM3 Enable_ntls = on VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem VerifyMode = Peer -[test-2] +[test-4] ExpectedResult = ServerFail Method = NTLS diff --git a/test/ssl-tests/31-ntls.conf.in b/test/ssl-tests/31-ntls.conf.in index 4db12ea62..53edbbe92 100644 --- a/test/ssl-tests/31-ntls.conf.in +++ b/test/ssl-tests/31-ntls.conf.in @@ -7,7 +7,7 @@ use OpenSSL::Test::Utils; our @tests = ( { - name => "test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only", + name => "test cipher ECC-SM2-SM4-CBC-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only", server => { "EncCertificate" => test_pem("SE.cert.pem"), "EncPrivateKey" => test_pem("SE.key.pem"), @@ -16,20 +16,69 @@ our @tests = ( "Enable_ntls" => "on", }, client => { - "CipherString" => "ECC-SM2-WITH-SM4-SM3", + "CipherString" => "ECC-SM2-SM4-CBC-SM3", "VerifyCAFile" => test_pem("CA.cert.pem"), "Enable_ntls" => "on", }, test => { "Method" => "NTLS", "ExpectedResult" => "Success", - "ExpectedCipher" => "ECC-SM2-WITH-SM4-SM3", + "ExpectedCipher" => "ECC-SM2-SM4-CBC-SM3", "ExpectedProtocol" => "NTLS", }, }, { - name => "test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode", + name => "test cipher ECC-SM2-SM4-GCM-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only", + server => { + "EncCertificate" => test_pem("SE.cert.pem"), + "EncPrivateKey" => test_pem("SE.key.pem"), + "SignCertificate" => test_pem("SS.cert.pem"), + "SignPrivateKey" => test_pem("SS.key.pem"), + "Enable_ntls" => "on", + }, + client => { + "CipherString" => "ECC-SM2-SM4-GCM-SM3", + "VerifyCAFile" => test_pem("CA.cert.pem"), + "Enable_ntls" => "on", + }, + test => { + "Method" => "NTLS", + "ExpectedResult" => "Success", + "ExpectedCipher" => "ECC-SM2-SM4-GCM-SM3", + "ExpectedProtocol" => "NTLS", + }, + }, + + { + name => "test cipher ECDHE-SM2-SM4-CBC-SM3 in NTLS_UNIQUE mode", + server => { + "EncCertificate" => test_pem("SE.cert.pem"), + "EncPrivateKey" => test_pem("SE.key.pem"), + "SignCertificate" => test_pem("SS.cert.pem"), + "SignPrivateKey" => test_pem("SS.key.pem"), + "VerifyCAFile" => test_pem("CA.cert.pem"), + "Enable_ntls" => "on", + }, + client => { + "SignCertificate" => test_pem("CS.cert.pem"), + "SignPrivateKey" => test_pem("CS.key.pem"), + "EncCertificate" => test_pem("CE.cert.pem"), + "EncPrivateKey" => test_pem("CE.key.pem"), + "CipherString" => "ECDHE-SM2-SM4-CBC-SM3", + "VerifyCAFile" => test_pem("CA.cert.pem"), + "Enable_ntls" => "on", + }, + test => { + "Method" => "NTLS", + "ExpectedResult" => "Success", + "ExpectedCipher" => "ECDHE-SM2-SM4-CBC-SM3", + "ExpectedProtocol" => "NTLS", + }, + }, + + { + name => "test cipher ECDHE-SM2-SM4-GCM-SM3 in NTLS_UNIQUE mode", server => { "EncCertificate" => test_pem("SE.cert.pem"), "EncPrivateKey" => test_pem("SE.key.pem"), @@ -43,14 +92,14 @@ our @tests = ( "SignPrivateKey" => test_pem("CS.key.pem"), "EncCertificate" => test_pem("CE.cert.pem"), "EncPrivateKey" => test_pem("CE.key.pem"), - "CipherString" => "ECDHE-SM2-WITH-SM4-SM3", + "CipherString" => "ECDHE-SM2-SM4-GCM-SM3", "VerifyCAFile" => test_pem("CA.cert.pem"), "Enable_ntls" => "on", }, test => { "Method" => "NTLS", "ExpectedResult" => "Success", - "ExpectedCipher" => "ECDHE-SM2-WITH-SM4-SM3", + "ExpectedCipher" => "ECDHE-SM2-SM4-GCM-SM3", "ExpectedProtocol" => "NTLS", }, }, @@ -61,7 +110,7 @@ our @tests = ( "Enable_ntls" => "on", }, client => { - "CipherString" => "ECC-SM2-WITH-SM4-SM3", + "CipherString" => "ECC-SM2-SM4-CBC-SM3", "Enable_ntls" => "on", }, test => { diff --git a/test/ssl-tests/32-keyless-normal.conf b/test/ssl-tests/32-keyless-normal.conf deleted file mode 100644 index fe75f290a..000000000 --- a/test/ssl-tests/32-keyless-normal.conf +++ /dev/null @@ -1,84 +0,0 @@ -# Generated with generate_ssl_tests.pl - -num_tests = 3 - -test-0 = 0-test rsa sign keyless -test-1 = 1-test rsa decrypt and sign keyless -test-2 = 2-test ecc sign keyless -# =========================================================== - -[0-test rsa sign keyless] -ssl_conf = 0-test rsa sign keyless-ssl - -[0-test rsa sign keyless-ssl] -server = 0-test rsa sign keyless-server -client = 0-test rsa sign keyless-client - -[0-test rsa sign keyless-server] -Certificate = ${ENV::TEST_CERTS_DIR}/server-pss-cert.pem -CipherString = DEFAULT -Keyless = on -PrivateKey = ${ENV::TEST_CERTS_DIR}/server-pss-key.pem - -[0-test rsa sign keyless-client] -CipherString = DEFAULT -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem -VerifyMode = Peer - -[test-0] -ExpectedResult = Success - - -# =========================================================== - -[1-test rsa decrypt and sign keyless] -ssl_conf = 1-test rsa decrypt and sign keyless-ssl - -[1-test rsa decrypt and sign keyless-ssl] -server = 1-test rsa decrypt and sign keyless-server -client = 1-test rsa decrypt and sign keyless-client - -[1-test rsa decrypt and sign keyless-server] -Certificate = ${ENV::TEST_CERTS_DIR}/test_rsa_crt.pem -CipherString = DEFAULT -Keyless = on -MaxProtocol = TLSv1.2 -MinProtocol = TLSv1.2 -PrivateKey = ${ENV::TEST_CERTS_DIR}/test_rsa_key.pem - -[1-test rsa decrypt and sign keyless-client] -CipherString = AES128-GCM-SHA256 -MaxProtocol = TLSv1.2 -MinProtocol = TLSv1.2 -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/test_rsa_crt.pem -VerifyMode = Peer - -[test-1] -ExpectedCipher = AES128-GCM-SHA256 -ExpectedResult = Success - - -# =========================================================== - -[2-test ecc sign keyless] -ssl_conf = 2-test ecc sign keyless-ssl - -[2-test ecc sign keyless-ssl] -server = 2-test ecc sign keyless-server -client = 2-test ecc sign keyless-client - -[2-test ecc sign keyless-server] -Certificate = ${ENV::TEST_CERTS_DIR}/server-cecdsa-cert.pem -CipherString = DEFAULT -Keyless = on -PrivateKey = ${ENV::TEST_CERTS_DIR}/server-cecdsa-key.pem - -[2-test ecc sign keyless-client] -CipherString = DEFAULT -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem -VerifyMode = Peer - -[test-2] -ExpectedResult = Success - - diff --git a/test/ssl-tests/32-keyless-normal.conf.in b/test/ssl-tests/32-keyless-normal.conf.in deleted file mode 100644 index 6787dbe37..000000000 --- a/test/ssl-tests/32-keyless-normal.conf.in +++ /dev/null @@ -1,59 +0,0 @@ -use strict; -use warnings; - -package ssltests; -use OpenSSL::Test::Utils; - -our @tests = ( - { - name => "test rsa sign keyless", - server => { - "Certificate" => test_pem("server-pss-cert.pem"), - "PrivateKey" => test_pem("server-pss-key.pem"), - "Keyless" => "on", - }, - client => { - }, - test => { - "ExpectedResult" => "Success", - }, - }, - - { - name => "test rsa decrypt and sign keyless", - server => { - "MinProtocol" => "TLSv1.2", - "MaxProtocol" => "TLSv1.2", - "Certificate" => test_pem("test_rsa_crt.pem"), - "PrivateKey" => test_pem("test_rsa_key.pem"), - "Keyless" => "on", - }, - client => { - "MinProtocol" => "TLSv1.2", - "MaxProtocol" => "TLSv1.2", - "VerifyCAFile" => test_pem("test_rsa_crt.pem"), - "CipherString" => "AES128-GCM-SHA256", - }, - test => { - "ExpectedResult" => "Success", - "ExpectedCipher" => "AES128-GCM-SHA256", - }, - }, - - { - name => "test ecc sign keyless", - server => { - "Certificate" => test_pem("server-cecdsa-cert.pem"), - "PrivateKey" => test_pem("server-cecdsa-key.pem"), - "Keyless" => "on", - }, - client => { - }, - test => { - "ExpectedResult" => "Success", - }, - }, -); - - -push @tests unless disabled("keyless"); diff --git a/test/ssl-tests/33-keyless-tls13-sm.conf b/test/ssl-tests/33-keyless-tls13-sm.conf deleted file mode 100644 index 004aa859d..000000000 --- a/test/ssl-tests/33-keyless-tls13-sm.conf +++ /dev/null @@ -1,36 +0,0 @@ -# Generated with generate_ssl_tests.pl - -num_tests = 1 - -test-0 = 0-test ciphersuites TLS_SM4_GCM_SM3 -# =========================================================== - -[0-test ciphersuites TLS_SM4_GCM_SM3] -ssl_conf = 0-test ciphersuites TLS_SM4_GCM_SM3-ssl - -[0-test ciphersuites TLS_SM4_GCM_SM3-ssl] -server = 0-test ciphersuites TLS_SM4_GCM_SM3-server -client = 0-test ciphersuites TLS_SM4_GCM_SM3-client - -[0-test ciphersuites TLS_SM4_GCM_SM3-server] -Certificate = ${ENV::TEST_CERTS_DIR}/sm2-first-crt.pem -CipherString = DEFAULT -Ciphersuites = TLS_SM4_GCM_SM3 -Keyless = on -MaxProtocol = TLSv1.3 -MinProtocol = TLSv1.3 -PrivateKey = ${ENV::TEST_CERTS_DIR}/sm2-first-key.pem - -[0-test ciphersuites TLS_SM4_GCM_SM3-client] -CipherString = DEFAULT -Ciphersuites = TLS_SM4_GCM_SM3 -MaxProtocol = TLSv1.3 -MinProtocol = TLSv1.3 -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/sm2-root-crt.pem -VerifyMode = Peer - -[test-0] -ExpectedCipher = TLS_SM4_GCM_SM3 -ExpectedResult = Success - - diff --git a/test/ssl-tests/33-keyless-tls13-sm.conf.in b/test/ssl-tests/33-keyless-tls13-sm.conf.in deleted file mode 100644 index 96afc5d31..000000000 --- a/test/ssl-tests/33-keyless-tls13-sm.conf.in +++ /dev/null @@ -1,31 +0,0 @@ -use strict; -use warnings; - -package ssltests; -use OpenSSL::Test::Utils; - -our @tests = ( - { - name => "test ciphersuites TLS_SM4_GCM_SM3", - server => { - "MinProtocol" => "TLSv1.3", - "MaxProtocol" => "TLSv1.3", - "Ciphersuites" => "TLS_SM4_GCM_SM3", - "Certificate" => test_pem("sm2-first-crt.pem"), - "PrivateKey" => test_pem("sm2-first-key.pem"), - "Keyless" => "on", - }, - client => { - "MinProtocol" => "TLSv1.3", - "MaxProtocol" => "TLSv1.3", - "Ciphersuites" => "TLS_SM4_GCM_SM3", - "VerifyCAFile" => test_pem("sm2-root-crt.pem"), - }, - test => { - "ExpectedResult" => "Success", - "ExpectedCipher" => "TLS_SM4_GCM_SM3", - }, - }, -); - -push @tests unless disabled("keyless") || disabled("sm2") || disabled("sm3") || disabled("sm4"); diff --git a/test/ssl-tests/34-keyless-ntls.conf b/test/ssl-tests/34-keyless-ntls.conf deleted file mode 100644 index 3dde402c9..000000000 --- a/test/ssl-tests/34-keyless-ntls.conf +++ /dev/null @@ -1,105 +0,0 @@ -# Generated with generate_ssl_tests.pl - -num_tests = 3 - -test-0 = 0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only -test-1 = 1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode -test-2 = 2-test ntls request fail when server ntls keyless not set PrivateKey -# =========================================================== - -[0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only] -ssl_conf = 0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-ssl - -[0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-ssl] -server = 0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-server -client = 0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-client - -[0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-server] -Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem -CipherString = DEFAULT -Enable_ntls = on -EncCertificate = ${ENV::TEST_CERTS_DIR}/SE.cert.pem -EncPrivateKey = ${ENV::TEST_CERTS_DIR}/SE.key.pem -KeylessNtls = on -PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -SignCertificate = ${ENV::TEST_CERTS_DIR}/SS.cert.pem -SignPrivateKey = ${ENV::TEST_CERTS_DIR}/SS.key.pem - -[0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-client] -CipherString = ECC-SM2-WITH-SM4-SM3 -Enable_ntls = on -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/CA.cert.pem -VerifyMode = Peer - -[test-0] -ExpectedCipher = ECC-SM2-WITH-SM4-SM3 -ExpectedProtocol = NTLS -ExpectedResult = Success -Method = NTLS - - -# =========================================================== - -[1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode] -ssl_conf = 1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode-ssl - -[1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode-ssl] -server = 1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode-server -client = 1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode-client - -[1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode-server] -Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem -CipherString = DEFAULT -Enable_ntls = on -EncCertificate = ${ENV::TEST_CERTS_DIR}/SE.cert.pem -EncPrivateKey = ${ENV::TEST_CERTS_DIR}/SE.key.pem -KeylessNtls = on -PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -SignCertificate = ${ENV::TEST_CERTS_DIR}/SS.cert.pem -SignPrivateKey = ${ENV::TEST_CERTS_DIR}/SS.key.pem -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/CA.cert.pem - -[1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode-client] -CipherString = ECDHE-SM2-WITH-SM4-SM3 -Enable_ntls = on -EncCertificate = ${ENV::TEST_CERTS_DIR}/CE.cert.pem -EncPrivateKey = ${ENV::TEST_CERTS_DIR}/CE.key.pem -SignCertificate = ${ENV::TEST_CERTS_DIR}/CS.cert.pem -SignPrivateKey = ${ENV::TEST_CERTS_DIR}/CS.key.pem -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/CA.cert.pem -VerifyMode = Peer - -[test-1] -ExpectedCipher = ECDHE-SM2-WITH-SM4-SM3 -ExpectedProtocol = NTLS -ExpectedResult = Success -Method = NTLS - - -# =========================================================== - -[2-test ntls request fail when server ntls keyless not set PrivateKey] -ssl_conf = 2-test ntls request fail when server ntls keyless not set PrivateKey-ssl - -[2-test ntls request fail when server ntls keyless not set PrivateKey-ssl] -server = 2-test ntls request fail when server ntls keyless not set PrivateKey-server -client = 2-test ntls request fail when server ntls keyless not set PrivateKey-client - -[2-test ntls request fail when server ntls keyless not set PrivateKey-server] -Certificate = ${ENV::TEST_CERTS_DIR}/server-cecdsa-cert.pem -CipherString = DEFAULT -Enable_ntls = on -Keyless = on -PrivateKey = ${ENV::TEST_CERTS_DIR}/server-cecdsa-key.pem - -[2-test ntls request fail when server ntls keyless not set PrivateKey-client] -CipherString = ECC-SM2-WITH-SM4-SM3 -Enable_ntls = on -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/CA.cert.pem -VerifyMode = Peer - -[test-2] -ExpectedResult = ServerFail -Method = NTLS - - diff --git a/test/ssl-tests/34-keyless-ntls.conf.in b/test/ssl-tests/34-keyless-ntls.conf.in deleted file mode 100644 index 08220d0c2..000000000 --- a/test/ssl-tests/34-keyless-ntls.conf.in +++ /dev/null @@ -1,79 +0,0 @@ -use strict; -use warnings; - -package ssltests; -use OpenSSL::Test::Utils; - -our @tests = ( - { - name => "test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only", - server => { - "EncCertificate" => test_pem("SE.cert.pem"), - "EncPrivateKey" => test_pem("SE.key.pem"), - "SignCertificate" => test_pem("SS.cert.pem"), - "SignPrivateKey" => test_pem("SS.key.pem"), - "Enable_ntls" => "on", - "KeylessNtls" => "on", - }, - client => { - "CipherString" => "ECC-SM2-WITH-SM4-SM3", - "VerifyCAFile" => test_pem("CA.cert.pem"), - "Enable_ntls" => "on", - }, - test => { - "Method" => "NTLS", - "ExpectedResult" => "Success", - "ExpectedCipher" => "ECC-SM2-WITH-SM4-SM3", - "ExpectedProtocol" => "NTLS", - }, - }, - - { - name => "test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode", - server => { - "EncCertificate" => test_pem("SE.cert.pem"), - "EncPrivateKey" => test_pem("SE.key.pem"), - "SignCertificate" => test_pem("SS.cert.pem"), - "SignPrivateKey" => test_pem("SS.key.pem"), - "VerifyCAFile" => test_pem("CA.cert.pem"), - "Enable_ntls" => "on", - "KeylessNtls" => "on", - }, - client => { - "SignCertificate" => test_pem("CS.cert.pem"), - "SignPrivateKey" => test_pem("CS.key.pem"), - "EncCertificate" => test_pem("CE.cert.pem"), - "EncPrivateKey" => test_pem("CE.key.pem"), - "CipherString" => "ECDHE-SM2-WITH-SM4-SM3", - "VerifyCAFile" => test_pem("CA.cert.pem"), - "Enable_ntls" => "on", - }, - test => { - "Method" => "NTLS", - "ExpectedResult" => "Success", - "ExpectedCipher" => "ECDHE-SM2-WITH-SM4-SM3", - "ExpectedProtocol" => "NTLS", - }, - }, - - { - name => "test ntls request fail when server ntls keyless not set PrivateKey", - server => { - "Certificate" => test_pem("server-cecdsa-cert.pem"), - "PrivateKey" => test_pem("server-cecdsa-key.pem"), - "Keyless" => "on", - "Enable_ntls" => "on", - }, - client => { - "CipherString" => "ECC-SM2-WITH-SM4-SM3", - "VerifyCAFile" => test_pem("CA.cert.pem"), - "Enable_ntls" => "on", - }, - test => { - "Method" => "NTLS", - "ExpectedResult" => "ServerFail", - }, - }, -); - -push @tests unless disabled("ntls") || disabled("keyless") || disabled("sm2") || disabled("sm3") || disabled("sm4"); diff --git a/test/ssl-tests/35-lurk-normal.conf b/test/ssl-tests/35-lurk-normal.conf deleted file mode 100644 index c8bee69ac..000000000 --- a/test/ssl-tests/35-lurk-normal.conf +++ /dev/null @@ -1,143 +0,0 @@ -# Generated with generate_ssl_tests.pl - -num_tests = 5 - -test-0 = 0-test rsa sign lurk -test-1 = 1-test rsa decrypt and sign lurk with TLSv1.2 and AES128-GCM-SHA256 -test-2 = 2-test rsa decrypt and sign lurk with TLSv1.0 and AES128-SHA -test-3 = 3-test ecc sign lurk -test-4 = 4-test ecc sign lurk with TLSv1.2 -# =========================================================== - -[0-test rsa sign lurk] -ssl_conf = 0-test rsa sign lurk-ssl - -[0-test rsa sign lurk-ssl] -server = 0-test rsa sign lurk-server -client = 0-test rsa sign lurk-client - -[0-test rsa sign lurk-server] -Certificate = ${ENV::TEST_CERTS_DIR}/server-pss-cert.pem -CipherString = DEFAULT -Lurk = on -PrivateKey = ${ENV::TEST_CERTS_DIR}/server-pss-key.pem - -[0-test rsa sign lurk-client] -CipherString = DEFAULT -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem -VerifyMode = Peer - -[test-0] -ExpectedResult = Success - - -# =========================================================== - -[1-test rsa decrypt and sign lurk with TLSv1.2 and AES128-GCM-SHA256] -ssl_conf = 1-test rsa decrypt and sign lurk with TLSv1.2 and AES128-GCM-SHA256-ssl - -[1-test rsa decrypt and sign lurk with TLSv1.2 and AES128-GCM-SHA256-ssl] -server = 1-test rsa decrypt and sign lurk with TLSv1.2 and AES128-GCM-SHA256-server -client = 1-test rsa decrypt and sign lurk with TLSv1.2 and AES128-GCM-SHA256-client - -[1-test rsa decrypt and sign lurk with TLSv1.2 and AES128-GCM-SHA256-server] -Certificate = ${ENV::TEST_CERTS_DIR}/test_rsa_crt.pem -CipherString = DEFAULT -Lurk = on -MaxProtocol = TLSv1.2 -MinProtocol = TLSv1.2 -PrivateKey = ${ENV::TEST_CERTS_DIR}/test_rsa_key.pem - -[1-test rsa decrypt and sign lurk with TLSv1.2 and AES128-GCM-SHA256-client] -CipherString = AES128-GCM-SHA256 -MaxProtocol = TLSv1.2 -MinProtocol = TLSv1.2 -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/test_rsa_crt.pem -VerifyMode = Peer - -[test-1] -ExpectedCipher = AES128-GCM-SHA256 -ExpectedResult = Success - - -# =========================================================== - -[2-test rsa decrypt and sign lurk with TLSv1.0 and AES128-SHA] -ssl_conf = 2-test rsa decrypt and sign lurk with TLSv1.0 and AES128-SHA-ssl - -[2-test rsa decrypt and sign lurk with TLSv1.0 and AES128-SHA-ssl] -server = 2-test rsa decrypt and sign lurk with TLSv1.0 and AES128-SHA-server -client = 2-test rsa decrypt and sign lurk with TLSv1.0 and AES128-SHA-client - -[2-test rsa decrypt and sign lurk with TLSv1.0 and AES128-SHA-server] -Certificate = ${ENV::TEST_CERTS_DIR}/test_rsa_crt.pem -CipherString = DEFAULT -Lurk = on -MaxProtocol = TLSv1 -MinProtocol = TLSv1 -PrivateKey = ${ENV::TEST_CERTS_DIR}/test_rsa_key.pem - -[2-test rsa decrypt and sign lurk with TLSv1.0 and AES128-SHA-client] -CipherString = AES128-SHA -ExtendedMasterSecret = off -MaxProtocol = TLSv1 -MinProtocol = TLSv1 -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/test_rsa_crt.pem -VerifyMode = Peer - -[test-2] -ExpectedResult = Success - - -# =========================================================== - -[3-test ecc sign lurk] -ssl_conf = 3-test ecc sign lurk-ssl - -[3-test ecc sign lurk-ssl] -server = 3-test ecc sign lurk-server -client = 3-test ecc sign lurk-client - -[3-test ecc sign lurk-server] -Certificate = ${ENV::TEST_CERTS_DIR}/server-cecdsa-cert.pem -CipherString = DEFAULT -Lurk = on -PrivateKey = ${ENV::TEST_CERTS_DIR}/server-cecdsa-key.pem - -[3-test ecc sign lurk-client] -CipherString = DEFAULT -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem -VerifyMode = Peer - -[test-3] -ExpectedResult = Success - - -# =========================================================== - -[4-test ecc sign lurk with TLSv1.2] -ssl_conf = 4-test ecc sign lurk with TLSv1.2-ssl - -[4-test ecc sign lurk with TLSv1.2-ssl] -server = 4-test ecc sign lurk with TLSv1.2-server -client = 4-test ecc sign lurk with TLSv1.2-client - -[4-test ecc sign lurk with TLSv1.2-server] -Certificate = ${ENV::TEST_CERTS_DIR}/server-cecdsa-cert.pem -CipherString = DEFAULT -Lurk = on -MaxProtocol = TLSv1.2 -MinProtocol = TLSv1.2 -PrivateKey = ${ENV::TEST_CERTS_DIR}/server-cecdsa-key.pem - -[4-test ecc sign lurk with TLSv1.2-client] -CipherString = DEFAULT -MaxProtocol = TLSv1.2 -MinProtocol = TLSv1.2 -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem -VerifyMode = Peer - -[test-4] -ExpectedResult = Success - - diff --git a/test/ssl-tests/35-lurk-normal.conf.in b/test/ssl-tests/35-lurk-normal.conf.in deleted file mode 100644 index 51b85e668..000000000 --- a/test/ssl-tests/35-lurk-normal.conf.in +++ /dev/null @@ -1,98 +0,0 @@ -use strict; -use warnings; - -package ssltests; -use OpenSSL::Test::Utils; - -our @tests = ( - { - name => "test rsa sign lurk", - server => { - "Certificate" => test_pem("server-pss-cert.pem"), - "PrivateKey" => test_pem("server-pss-key.pem"), - "Lurk" => "on", - }, - client => { - }, - test => { - "ExpectedResult" => "Success", - }, - }, - - { - name => "test rsa decrypt and sign lurk with TLSv1.2 and AES128-GCM-SHA256", - server => { - "MinProtocol" => "TLSv1.2", - "MaxProtocol" => "TLSv1.2", - "Certificate" => test_pem("test_rsa_crt.pem"), - "PrivateKey" => test_pem("test_rsa_key.pem"), - "Lurk" => "on", - }, - client => { - "MinProtocol" => "TLSv1.2", - "MaxProtocol" => "TLSv1.2", - "VerifyCAFile" => test_pem("test_rsa_crt.pem"), - "CipherString" => "AES128-GCM-SHA256", - }, - test => { - "ExpectedResult" => "Success", - "ExpectedCipher" => "AES128-GCM-SHA256", - }, - }, - - { - name => "test rsa decrypt and sign lurk with TLSv1.0 and AES128-SHA", - server => { - "MinProtocol" => "TLSv1", - "MaxProtocol" => "TLSv1", - "Certificate" => test_pem("test_rsa_crt.pem"), - "PrivateKey" => test_pem("test_rsa_key.pem"), - "Lurk" => "on", - }, - client => { - "MinProtocol" => "TLSv1", - "MaxProtocol" => "TLSv1", - "VerifyCAFile" => test_pem("test_rsa_crt.pem"), - "CipherString" => "AES128-SHA", - "ExtendedMasterSecret" => "off", - }, - test => { - "ExpectedResult" => "Success", - }, - }, - - { - name => "test ecc sign lurk", - server => { - "Certificate" => test_pem("server-cecdsa-cert.pem"), - "PrivateKey" => test_pem("server-cecdsa-key.pem"), - "Lurk" => "on", - }, - client => { - }, - test => { - "ExpectedResult" => "Success", - }, - }, - - { - name => "test ecc sign lurk with TLSv1.2", - server => { - "MinProtocol" => "TLSv1.2", - "MaxProtocol" => "TLSv1.2", - "Certificate" => test_pem("server-cecdsa-cert.pem"), - "PrivateKey" => test_pem("server-cecdsa-key.pem"), - "Lurk" => "on", - }, - client => { - "MinProtocol" => "TLSv1.2", - "MaxProtocol" => "TLSv1.2", - }, - test => { - "ExpectedResult" => "Success", - }, - }, -); - - -push @tests unless disabled("lurk"); diff --git a/test/ssl-tests/36-lurk-tls13-sm.conf b/test/ssl-tests/36-lurk-tls13-sm.conf deleted file mode 100644 index ddb141939..000000000 --- a/test/ssl-tests/36-lurk-tls13-sm.conf +++ /dev/null @@ -1,36 +0,0 @@ -# Generated with generate_ssl_tests.pl - -num_tests = 1 - -test-0 = 0-test ciphersuites TLS_SM4_GCM_SM3 -# =========================================================== - -[0-test ciphersuites TLS_SM4_GCM_SM3] -ssl_conf = 0-test ciphersuites TLS_SM4_GCM_SM3-ssl - -[0-test ciphersuites TLS_SM4_GCM_SM3-ssl] -server = 0-test ciphersuites TLS_SM4_GCM_SM3-server -client = 0-test ciphersuites TLS_SM4_GCM_SM3-client - -[0-test ciphersuites TLS_SM4_GCM_SM3-server] -Certificate = ${ENV::TEST_CERTS_DIR}/sm2-first-crt.pem -CipherString = DEFAULT -Ciphersuites = TLS_SM4_GCM_SM3 -Lurk = on -MaxProtocol = TLSv1.3 -MinProtocol = TLSv1.3 -PrivateKey = ${ENV::TEST_CERTS_DIR}/sm2-first-key.pem - -[0-test ciphersuites TLS_SM4_GCM_SM3-client] -CipherString = DEFAULT -Ciphersuites = TLS_SM4_GCM_SM3 -MaxProtocol = TLSv1.3 -MinProtocol = TLSv1.3 -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/sm2-root-crt.pem -VerifyMode = Peer - -[test-0] -ExpectedCipher = TLS_SM4_GCM_SM3 -ExpectedResult = Success - - diff --git a/test/ssl-tests/36-lurk-tls13-sm.conf.in b/test/ssl-tests/36-lurk-tls13-sm.conf.in deleted file mode 100644 index 600273f62..000000000 --- a/test/ssl-tests/36-lurk-tls13-sm.conf.in +++ /dev/null @@ -1,31 +0,0 @@ -use strict; -use warnings; - -package ssltests; -use OpenSSL::Test::Utils; - -our @tests = ( - { - name => "test ciphersuites TLS_SM4_GCM_SM3", - server => { - "MinProtocol" => "TLSv1.3", - "MaxProtocol" => "TLSv1.3", - "Ciphersuites" => "TLS_SM4_GCM_SM3", - "Certificate" => test_pem("sm2-first-crt.pem"), - "PrivateKey" => test_pem("sm2-first-key.pem"), - "Lurk" => "on", - }, - client => { - "MinProtocol" => "TLSv1.3", - "MaxProtocol" => "TLSv1.3", - "Ciphersuites" => "TLS_SM4_GCM_SM3", - "VerifyCAFile" => test_pem("sm2-root-crt.pem"), - }, - test => { - "ExpectedResult" => "Success", - "ExpectedCipher" => "TLS_SM4_GCM_SM3", - }, - }, -); - -push @tests unless disabled("lurk") || disabled("sm2") || disabled("sm3") || disabled("sm4"); diff --git a/test/ssl-tests/37-lurk-ntls.conf b/test/ssl-tests/37-lurk-ntls.conf deleted file mode 100644 index 3f85f337b..000000000 --- a/test/ssl-tests/37-lurk-ntls.conf +++ /dev/null @@ -1,107 +0,0 @@ -# Generated with generate_ssl_tests.pl - -num_tests = 3 - -test-0 = 0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only -test-1 = 1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode -test-2 = 2-test ntls request fail when server ntls lurk not set PrivateKey -# =========================================================== - -[0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only] -ssl_conf = 0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-ssl - -[0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-ssl] -server = 0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-server -client = 0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-client - -[0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-server] -Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem -CipherString = DEFAULT -Enable_ntls = on -EncCertificate = ${ENV::TEST_CERTS_DIR}/SE.cert.pem -EncPrivateKey = ${ENV::TEST_CERTS_DIR}/SE.key.pem -Lurk = on -LurkNtls = on -PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -SignCertificate = ${ENV::TEST_CERTS_DIR}/SS.cert.pem -SignPrivateKey = ${ENV::TEST_CERTS_DIR}/SS.key.pem - -[0-test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only-client] -CipherString = ECC-SM2-WITH-SM4-SM3 -Enable_ntls = on -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/CA.cert.pem -VerifyMode = Peer - -[test-0] -ExpectedCipher = ECC-SM2-WITH-SM4-SM3 -ExpectedProtocol = NTLS -ExpectedResult = Success -Method = NTLS - - -# =========================================================== - -[1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode] -ssl_conf = 1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode-ssl - -[1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode-ssl] -server = 1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode-server -client = 1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode-client - -[1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode-server] -Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem -CipherString = DEFAULT -Enable_ntls = on -EncCertificate = ${ENV::TEST_CERTS_DIR}/SE.cert.pem -EncPrivateKey = ${ENV::TEST_CERTS_DIR}/SE.key.pem -Lurk = on -LurkNtls = on -PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -SignCertificate = ${ENV::TEST_CERTS_DIR}/SS.cert.pem -SignPrivateKey = ${ENV::TEST_CERTS_DIR}/SS.key.pem -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/CA.cert.pem - -[1-test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode-client] -CipherString = ECDHE-SM2-WITH-SM4-SM3 -Enable_ntls = on -EncCertificate = ${ENV::TEST_CERTS_DIR}/CE.cert.pem -EncPrivateKey = ${ENV::TEST_CERTS_DIR}/CE.key.pem -SignCertificate = ${ENV::TEST_CERTS_DIR}/CS.cert.pem -SignPrivateKey = ${ENV::TEST_CERTS_DIR}/CS.key.pem -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/CA.cert.pem -VerifyMode = Peer - -[test-1] -ExpectedCipher = ECDHE-SM2-WITH-SM4-SM3 -ExpectedProtocol = NTLS -ExpectedResult = Success -Method = NTLS - - -# =========================================================== - -[2-test ntls request fail when server ntls lurk not set PrivateKey] -ssl_conf = 2-test ntls request fail when server ntls lurk not set PrivateKey-ssl - -[2-test ntls request fail when server ntls lurk not set PrivateKey-ssl] -server = 2-test ntls request fail when server ntls lurk not set PrivateKey-server -client = 2-test ntls request fail when server ntls lurk not set PrivateKey-client - -[2-test ntls request fail when server ntls lurk not set PrivateKey-server] -Certificate = ${ENV::TEST_CERTS_DIR}/server-cecdsa-cert.pem -CipherString = DEFAULT -Enable_ntls = on -Lurk = on -PrivateKey = ${ENV::TEST_CERTS_DIR}/server-cecdsa-key.pem - -[2-test ntls request fail when server ntls lurk not set PrivateKey-client] -CipherString = ECC-SM2-WITH-SM4-SM3 -Enable_ntls = on -VerifyCAFile = ${ENV::TEST_CERTS_DIR}/CA.cert.pem -VerifyMode = Peer - -[test-2] -ExpectedResult = ServerFail -Method = NTLS - - diff --git a/test/ssl-tests/37-lurk-ntls.conf.in b/test/ssl-tests/37-lurk-ntls.conf.in deleted file mode 100644 index 1ad7d64da..000000000 --- a/test/ssl-tests/37-lurk-ntls.conf.in +++ /dev/null @@ -1,81 +0,0 @@ -use strict; -use warnings; - -package ssltests; -use OpenSSL::Test::Utils; - -our @tests = ( - { - name => "test cipher ECC-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode, NTLS_UNIQUE test server and client all use NTLS only", - server => { - "EncCertificate" => test_pem("SE.cert.pem"), - "EncPrivateKey" => test_pem("SE.key.pem"), - "SignCertificate" => test_pem("SS.cert.pem"), - "SignPrivateKey" => test_pem("SS.key.pem"), - "Enable_ntls" => "on", - "Lurk" => "on", - "LurkNtls" => "on", - }, - client => { - "CipherString" => "ECC-SM2-WITH-SM4-SM3", - "VerifyCAFile" => test_pem("CA.cert.pem"), - "Enable_ntls" => "on", - }, - test => { - "Method" => "NTLS", - "ExpectedResult" => "Success", - "ExpectedCipher" => "ECC-SM2-WITH-SM4-SM3", - "ExpectedProtocol" => "NTLS", - }, - }, - - { - name => "test cipher ECDHE-SM2-WITH-SM4-SM3 in NTLS_UNIQUE mode", - server => { - "EncCertificate" => test_pem("SE.cert.pem"), - "EncPrivateKey" => test_pem("SE.key.pem"), - "SignCertificate" => test_pem("SS.cert.pem"), - "SignPrivateKey" => test_pem("SS.key.pem"), - "VerifyCAFile" => test_pem("CA.cert.pem"), - "Enable_ntls" => "on", - "Lurk" => "on", - "LurkNtls" => "on", - }, - client => { - "SignCertificate" => test_pem("CS.cert.pem"), - "SignPrivateKey" => test_pem("CS.key.pem"), - "EncCertificate" => test_pem("CE.cert.pem"), - "EncPrivateKey" => test_pem("CE.key.pem"), - "CipherString" => "ECDHE-SM2-WITH-SM4-SM3", - "VerifyCAFile" => test_pem("CA.cert.pem"), - "Enable_ntls" => "on", - }, - test => { - "Method" => "NTLS", - "ExpectedResult" => "Success", - "ExpectedCipher" => "ECDHE-SM2-WITH-SM4-SM3", - "ExpectedProtocol" => "NTLS", - }, - }, - - { - name => "test ntls request fail when server ntls lurk not set PrivateKey", - server => { - "Certificate" => test_pem("server-cecdsa-cert.pem"), - "PrivateKey" => test_pem("server-cecdsa-key.pem"), - "Lurk" => "on", - "Enable_ntls" => "on", - }, - client => { - "CipherString" => "ECC-SM2-WITH-SM4-SM3", - "VerifyCAFile" => test_pem("CA.cert.pem"), - "Enable_ntls" => "on", - }, - test => { - "Method" => "NTLS", - "ExpectedResult" => "ServerFail", - }, - }, -); - -push @tests unless disabled("ntls") || disabled("lurk") || disabled("sm2") || disabled("sm3") || disabled("sm4"); diff --git a/test/ssl-tests/38-delegated-credential.conf b/test/ssl-tests/38-delegated-credential.conf new file mode 100644 index 000000000..0a4d65f86 --- /dev/null +++ b/test/ssl-tests/38-delegated-credential.conf @@ -0,0 +1,122 @@ +# Generated with generate_ssl_tests.pl + +num_tests = 3 + +test-0 = 0-test client can verify server by delegated credential +test-1 = 1-test client/server can do mtls by delegated credential +test-2 = 2-test depoly cert and dc at the same time, but do not open dc +# =========================================================== + +[0-test client can verify server by delegated credential] +ssl_conf = 0-test client can verify server by delegated credential-ssl + +[0-test client can verify server by delegated credential-ssl] +server = 0-test client can verify server by delegated credential-server +client = 0-test client can verify server by delegated credential-client + +[0-test client can verify server by delegated credential-server] +Certificate = ${ENV::TEST_CERTS_DIR}/dc-ecc-leaf.crt +CipherString = DEFAULT +DC = ${ENV::TEST_CERTS_DIR}/dc-ecc-server-longterm.dc +DCKey = ${ENV::TEST_CERTS_DIR}/dc-ecc-server-longterm.key +Enable_sign_by_dc = on +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/dc-ecc-leaf.key + +[0-test client can verify server by delegated credential-client] +CipherString = DEFAULT +Enable_verify_peer_by_dc = on +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/dc-ecc-chain-ca.crt +VerifyMode = Peer + +[test-0] +ExpectedResult = Success +ExpextClientDCusage = VerifyPeerByDCOnly +ExpextServerDCusage = SignByDCOnly + + +# =========================================================== + +[1-test client/server can do mtls by delegated credential] +ssl_conf = 1-test client/server can do mtls by delegated credential-ssl + +[1-test client/server can do mtls by delegated credential-ssl] +server = 1-test client/server can do mtls by delegated credential-server +client = 1-test client/server can do mtls by delegated credential-client + +[1-test client/server can do mtls by delegated credential-server] +Certificate = ${ENV::TEST_CERTS_DIR}/dc-ecc-leaf.crt +CipherString = DEFAULT +DC = ${ENV::TEST_CERTS_DIR}/dc-ecc-server-longterm.dc +DCKey = ${ENV::TEST_CERTS_DIR}/dc-ecc-server-longterm.key +Enable_sign_by_dc = on +Enable_verify_peer_by_dc = on +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/dc-ecc-leaf.key +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/dc-ecc-chain-ca.crt +VerifyMode = Request + +[1-test client/server can do mtls by delegated credential-client] +Certificate = ${ENV::TEST_CERTS_DIR}/dc-ecc-leaf-clientUse.crt +CipherString = DEFAULT +DC = ${ENV::TEST_CERTS_DIR}/dc-ecc-client-longterm.dc +DCKey = ${ENV::TEST_CERTS_DIR}/dc-ecc-client-longterm.key +Enable_sign_by_dc = on +Enable_verify_peer_by_dc = on +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/dc-ecc-leaf-clientUse.key +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/dc-ecc-chain-ca.crt +VerifyMode = Peer + +[test-1] +ExpectedResult = Success +ExpextClientDCusage = VerifyPeerAndSignByDC +ExpextServerDCusage = VerifyPeerAndSignByDC + + +# =========================================================== + +[2-test depoly cert and dc at the same time, but do not open dc ] +ssl_conf = 2-test depoly cert and dc at the same time, but do not open dc -ssl + +[2-test depoly cert and dc at the same time, but do not open dc -ssl] +server = 2-test depoly cert and dc at the same time, but do not open dc -server +client = 2-test depoly cert and dc at the same time, but do not open dc -client + +[2-test depoly cert and dc at the same time, but do not open dc -server] +Certificate = ${ENV::TEST_CERTS_DIR}/dc-ecc-leaf.crt +CipherString = DEFAULT +DC = ${ENV::TEST_CERTS_DIR}/dc-ecc-server-longterm.dc +DCKey = ${ENV::TEST_CERTS_DIR}/dc-ecc-server-longterm.key +Enable_sign_by_dc = off +Enable_verify_peer_by_dc = off +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/dc-ecc-leaf.key +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/dc-ecc-chain-ca.crt +VerifyMode = Request + +[2-test depoly cert and dc at the same time, but do not open dc -client] +Certificate = ${ENV::TEST_CERTS_DIR}/dc-ecc-leaf-clientUse.crt +CipherString = DEFAULT +DC = ${ENV::TEST_CERTS_DIR}/dc-ecc-client-longterm.dc +DCKey = ${ENV::TEST_CERTS_DIR}/dc-ecc-client-longterm.key +Enable_sign_by_dc = off +Enable_verify_peer_by_dc = off +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/dc-ecc-leaf-clientUse.key +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/dc-ecc-chain-ca.crt +VerifyMode = Peer + +[test-2] +ExpectedResult = Success +ExpextClientDCusage = NotUseDC +ExpextServerDCusage = NotUseDC + + diff --git a/test/ssl-tests/38-delegated-credential.conf.in b/test/ssl-tests/38-delegated-credential.conf.in new file mode 100644 index 000000000..fe6b5c004 --- /dev/null +++ b/test/ssl-tests/38-delegated-credential.conf.in @@ -0,0 +1,89 @@ +package ssltests; + +our @tests = ( + { + name => "test client can verify server by delegated credential", + server => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "Enable_sign_by_dc" => "on", + "Certificate" => test_pem("dc-ecc-leaf.crt"), + "PrivateKey" => test_pem("dc-ecc-leaf.key"), + "DC" => test_pem("dc-ecc-server-longterm.dc"), + "DCKey" => test_pem("dc-ecc-server-longterm.key"), + }, + client => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "VerifyCAFile" => test_pem("dc-ecc-chain-ca.crt"), + "Enable_verify_peer_by_dc" => "on", + }, + test => { + "ExpectedResult" => "Success", + "ExpextClientDCusage" => "VerifyPeerByDCOnly", + "ExpextServerDCusage" => "SignByDCOnly", + }, + }, + { + name => "test client/server can do mtls by delegated credential", + server => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "Enable_sign_by_dc" => "on", + "Enable_verify_peer_by_dc" => "on", + "Certificate" => test_pem("dc-ecc-leaf.crt"), + "PrivateKey" => test_pem("dc-ecc-leaf.key"), + "DC" => test_pem("dc-ecc-server-longterm.dc"), + "DCKey" => test_pem("dc-ecc-server-longterm.key"), + "VerifyCAFile" => test_pem("dc-ecc-chain-ca.crt"), + "VerifyMode" => "Request", + }, + client => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "VerifyCAFile" => test_pem("dc-ecc-chain-ca.crt"), + "Enable_sign_by_dc" => "on", + "Enable_verify_peer_by_dc" => "on", + "Certificate" => test_pem("dc-ecc-leaf-clientUse.crt"), + "PrivateKey" => test_pem("dc-ecc-leaf-clientUse.key"), + "DC" => test_pem("dc-ecc-client-longterm.dc"), + "DCKey" => test_pem("dc-ecc-client-longterm.key"), + }, + test => { + "ExpectedResult" => "Success", + "ExpextClientDCusage" => "VerifyPeerAndSignByDC", + "ExpextServerDCusage" => "VerifyPeerAndSignByDC", + }, + }, + { + name => "test depoly cert and dc at the same time, but do not open dc ", + server => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "Enable_sign_by_dc" => "off", + "Enable_verify_peer_by_dc" => "off", + "Certificate" => test_pem("dc-ecc-leaf.crt"), + "PrivateKey" => test_pem("dc-ecc-leaf.key"), + "DC" => test_pem("dc-ecc-server-longterm.dc"), + "DCKey" => test_pem("dc-ecc-server-longterm.key"), + "VerifyCAFile" => test_pem("dc-ecc-chain-ca.crt"), + "VerifyMode" => "Request", + }, + client => { + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + "VerifyCAFile" => test_pem("dc-ecc-chain-ca.crt"), + "Enable_sign_by_dc" => "off", + "Enable_verify_peer_by_dc" => "off", + "Certificate" => test_pem("dc-ecc-leaf-clientUse.crt"), + "PrivateKey" => test_pem("dc-ecc-leaf-clientUse.key"), + "DC" => test_pem("dc-ecc-client-longterm.dc"), + "DCKey" => test_pem("dc-ecc-client-longterm.key"), + }, + test => { + "ExpectedResult" => "Success", + "ExpextClientDCusage" => "NotUseDC", + "ExpextServerDCusage" => "NotUseDC", + }, + }, +); diff --git a/test/ssl_ntls_api_test.c b/test/ssl_ntls_api_test.c index de0889dbc..242ca15f4 100644 --- a/test/ssl_ntls_api_test.c +++ b/test/ssl_ntls_api_test.c @@ -10,6 +10,97 @@ static const char *sign_key_file; static const char *enc_cert_file; static const char *enc_key_file; +static int test_ntls_ctx_set_cipher_list(void) +{ + int ret = 1; +#ifndef OPENSSL_NO_NTLS + SSL_CTX *ctx = NULL; + + ret = 0; + ctx = SSL_CTX_new(NTLS_client_method()); + if (!TEST_true(ctx != NULL)) + goto err; + + SSL_CTX_enable_ntls(ctx); + if (!TEST_true(ctx->enable_ntls == 1)) + goto err; + + if (!TEST_true(SSL_CTX_set_cipher_list(ctx, NTLS_TXT_SM2DHE_WITH_SM4_SM3))) { + goto err; + } + + if (!TEST_true(SSL_CTX_set_cipher_list(ctx, NTLS_TXT_SM2_WITH_SM4_SM3))) { + goto err; + } + + if (!TEST_true(SSL_CTX_set_cipher_list(ctx, NTLS_TXT_ECDHE_SM2_SM4_CBC_SM3))) { + goto err; + } + + if (!TEST_true(SSL_CTX_set_cipher_list(ctx, NTLS_TXT_ECDHE_SM2_SM4_GCM_SM3))) { + goto err; + } + + if (!TEST_true(SSL_CTX_set_cipher_list(ctx, NTLS_TXT_ECC_SM2_SM4_CBC_SM3))) { + goto err; + } + + if (!TEST_true(SSL_CTX_set_cipher_list(ctx, NTLS_TXT_ECC_SM2_SM4_GCM_SM3))) { + goto err; + } + + ret = 1; +err: + SSL_CTX_free(ctx); +#endif + return ret; +} + +static int test_ntls_ssl_set_cipher_list(void) +{ + int ret = 1; +#ifndef OPENSSL_NO_NTLS + SSL_CTX *ctx = NULL; + SSL *ssl = NULL; + + ret = 0; + ctx = SSL_CTX_new(NTLS_client_method()); + if (!TEST_true(ctx != NULL)) + goto err; + + SSL_CTX_enable_ntls(ctx); + if (!TEST_true(ctx->enable_ntls == 1)) + goto err; + + + ssl = SSL_new(ctx); + if (!TEST_true(ssl != NULL)) + goto err; + + if (!TEST_true(SSL_set_cipher_list(ssl, NTLS_TXT_ECDHE_SM2_SM4_CBC_SM3))) { + goto err; + } + + if (!TEST_true(SSL_set_cipher_list(ssl, NTLS_TXT_ECDHE_SM2_SM4_GCM_SM3))) { + goto err; + } + + if (!TEST_true(SSL_set_cipher_list(ssl, NTLS_TXT_ECC_SM2_SM4_CBC_SM3))) { + goto err; + } + + if (!TEST_true(SSL_set_cipher_list(ssl, NTLS_TXT_ECC_SM2_SM4_GCM_SM3))) { + goto err; + } + + ret = 1; +err: + SSL_CTX_free(ctx); + SSL_free(ssl); +#endif + return ret; +} + static int test_ntls_ctx_set_cert_pkey_file_api(void) { int ret = 1; @@ -353,5 +444,7 @@ int setup_tests(void) ADD_TEST(test_ntls_ssl_set_cert_pkey_file_api); ADD_TEST(test_ntls_ssl_set_cert_pkey_api); ADD_TEST(test_ntls_method_api); + ADD_TEST(test_ntls_ctx_set_cipher_list); + ADD_TEST(test_ntls_ssl_set_cipher_list); return 1; } diff --git a/test/ssl_test.c b/test/ssl_test.c index 895a7d096..2af0717e5 100644 --- a/test/ssl_test.c +++ b/test/ssl_test.c @@ -39,6 +39,30 @@ static int check_result(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) return 1; } +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +static int check_client_dc_usage(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) +{ + if (!TEST_int_eq(result->client_dc_usage, test_ctx->client_expected_dc_usage)) { + TEST_info("ExpectedDcUsaged mismatch: expected %s, got %s.", + ssl_test_dc_usage(test_ctx->client_expected_dc_usage), + ssl_test_dc_usage(result->client_dc_usage)); + return 0; + } + return 1; +} + +static int check_server_dc_usage(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) +{ + if (!TEST_int_eq(result->server_dc_usage, test_ctx->server_expected_dc_usage)) { + TEST_info("ExpectedDcUsaged mismatch: expected %s, got %s.", + ssl_test_dc_usage(test_ctx->server_expected_dc_usage), + ssl_test_dc_usage(result->server_dc_usage)); + return 0; + } + return 1; +} +#endif + static int check_alerts(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) { if (!TEST_int_eq(result->client_alert_sent, @@ -345,9 +369,25 @@ static int check_cipher(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) return 1; if (!TEST_ptr(result->cipher)) return 0; + +#if (!defined OPENSSL_NO_NTLS) && (!defined OPENSSL_NO_SM2) \ + && (!defined OPENSSL_NO_SM3) && (!defined OPENSSL_NO_SM4) + if ((TEST_str_eq(test_ctx->expected_cipher, NTLS_TXT_SM2DHE_WITH_SM4_SM3) + && TEST_str_eq(result->cipher, NTLS_TXT_ECDHE_SM2_SM4_CBC_SM3)) + || (TEST_str_eq(test_ctx->expected_cipher, NTLS_TXT_ECDHE_SM2_SM4_CBC_SM3) + && TEST_str_eq(result->cipher, NTLS_TXT_SM2DHE_WITH_SM4_SM3))) + return 1; + + if ((TEST_str_eq(test_ctx->expected_cipher, NTLS_TXT_SM2_WITH_SM4_SM3) + && TEST_str_eq(result->cipher, NTLS_TXT_ECC_SM2_SM4_CBC_SM3)) + || (TEST_str_eq(test_ctx->expected_cipher, NTLS_TXT_ECC_SM2_SM4_CBC_SM3) + && TEST_str_eq(result->cipher, NTLS_TXT_SM2_WITH_SM4_SM3))) + return 1; +#endif if (!TEST_str_eq(test_ctx->expected_cipher, result->cipher)) return 0; + return 1; } @@ -384,6 +424,10 @@ static int check_test(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) ret &= check_client_sign_hash(result, test_ctx); ret &= check_client_sign_type(result, test_ctx); ret &= check_client_ca_names(result, test_ctx); +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + ret &= check_client_dc_usage(result, test_ctx); + ret &= check_server_dc_usage(result, test_ctx); +#endif } return ret; } diff --git a/test/ssl_test_ctx.c b/test/ssl_test_ctx.c index e4e3fa58c..bf12b4a96 100644 --- a/test/ssl_test_ctx.c +++ b/test/ssl_test_ctx.c @@ -118,6 +118,44 @@ const char *ssl_test_result_name(ssl_test_result_t result) return enum_name(ssl_test_results, OSSL_NELEM(ssl_test_results), result); } +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +/* ExpextDCusage */ + +static const test_enum ssl_dc_usage[] = { + {"NotUseDC", SSL_NOT_USE_DC}, + {"VerifyPeerByDCOnly", SSL_VERIFY_PEER_BY_DC_ONLY}, + {"SignByDCOnly", SSL_SIGN_BY_DC_ONLY}, + {"VerifyPeerAndSignByDC", SSL_VERIFY_PEER_AND_SIGN_BY_DC}, +}; + +__owur static int parse_client_expected_dc_usage(SSL_TEST_CTX *test_ctx, const char *value) +{ + int ret_value; + if (!parse_enum(ssl_dc_usage, OSSL_NELEM(ssl_dc_usage), + &ret_value, value)) { + return 0; + } + test_ctx->client_expected_dc_usage = ret_value; + return 1; +} + +__owur static int parse_server_expected_dc_usage(SSL_TEST_CTX *test_ctx, const char *value) +{ + int ret_value; + if (!parse_enum(ssl_dc_usage, OSSL_NELEM(ssl_dc_usage), + &ret_value, value)) { + return 0; + } + test_ctx->server_expected_dc_usage = ret_value; + return 1; +} + +const char *ssl_test_dc_usage(ssl_test_dc_usage_t result) +{ + return enum_name(ssl_dc_usage, OSSL_NELEM(ssl_dc_usage), result); +} +#endif + /* ExpectedClientAlert / ExpectedServerAlert */ static const test_enum ssl_alerts[] = { @@ -681,6 +719,10 @@ static const ssl_test_ctx_option ssl_test_ctx_options[] = { { "EnableServerSCTPLabelBug", &parse_test_enable_server_sctp_label_bug }, { "ExpectedCipher", &parse_test_expected_cipher }, { "ExpectedSessionTicketAppData", &parse_test_expected_session_ticket_app_data }, +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + { "ExpextClientDCusage", &parse_client_expected_dc_usage}, + { "ExpextServerDCusage", &parse_server_expected_dc_usage}, +#endif }; /* Nested client options. */ diff --git a/test/ssl_test_ctx.h b/test/ssl_test_ctx.h index fbb311221..65e77ac79 100644 --- a/test/ssl_test_ctx.h +++ b/test/ssl_test_ctx.h @@ -22,6 +22,15 @@ typedef enum { SSL_TEST_FIRST_HANDSHAKE_FAILED } ssl_test_result_t; +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +typedef enum { + SSL_NOT_USE_DC, + SSL_VERIFY_PEER_BY_DC_ONLY, + SSL_SIGN_BY_DC_ONLY, + SSL_VERIFY_PEER_AND_SIGN_BY_DC +} ssl_test_dc_usage_t; +#endif + typedef enum { SSL_TEST_VERIFY_NONE = 0, /* Default */ SSL_TEST_VERIFY_ACCEPT_ALL, @@ -226,9 +235,16 @@ typedef struct { char *expected_cipher; /* Expected Session Ticket Application Data */ char *expected_session_ticket_app_data; +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL + ssl_test_dc_usage_t client_expected_dc_usage; + ssl_test_dc_usage_t server_expected_dc_usage; +#endif } SSL_TEST_CTX; const char *ssl_test_result_name(ssl_test_result_t result); +#ifndef OPENSSL_NO_DELEGATED_CREDENTIAL +const char *ssl_test_dc_usage(ssl_test_dc_usage_t result); +#endif const char *ssl_alert_name(int alert); const char *ssl_protocol_name(int protocol); const char *ssl_verify_callback_name(ssl_verify_callback_t verify_callback); diff --git a/test/sslapitest.c b/test/sslapitest.c index bffc6545e..77fff4fa7 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -6323,136 +6323,6 @@ static int test_ca_names(int tst) return testresult; } -#ifndef OPENSSL_NO_QUIC - -static int test_quic_set_encryption_secrets(SSL *ssl, OSSL_ENCRYPTION_LEVEL level, - const uint8_t *read_secret, - const uint8_t *write_secret, size_t secret_len) -{ - test_printf_stderr("quic_set_encryption_secrets() %s, lvl=%d, len=%zd\n", - ssl->server ? "server" : "client", level, secret_len); - return 1; -} -static int test_quic_add_handshake_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL level, - const uint8_t *data, size_t len) -{ - SSL *peer = (SSL*)SSL_get_app_data(ssl); - - test_printf_stderr("quic_add_handshake_data() %s, lvl=%d, *data=0x%02X, len=%zd\n", - ssl->server ? "server" : "client", level, (int)*data, len); - if (!TEST_ptr(peer)) - return 0; - - if (!TEST_true(SSL_provide_quic_data(peer, level, data, len))) { - ERR_print_errors_fp(stderr); - return 0; - } - - return 1; -} -static int test_quic_flush_flight(SSL *ssl) -{ - test_printf_stderr("quic_flush_flight() %s\n", ssl->server ? "server" : "client"); - return 1; -} -static int test_quic_send_alert(SSL *ssl, enum ssl_encryption_level_t level, uint8_t alert) -{ - test_printf_stderr("quic_send_alert() %s, lvl=%d, alert=%d\n", - ssl->server ? "server" : "client", level, alert); - return 1; -} - -static SSL_QUIC_METHOD quic_method = { - test_quic_set_encryption_secrets, - test_quic_add_handshake_data, - test_quic_flush_flight, - test_quic_send_alert, -}; - -static int test_quic_api(void) -{ - SSL_CTX *cctx = NULL, *sctx = NULL; - SSL *clientssl = NULL, *serverssl = NULL; - int testresult = 0; - static const char *server_str = "SERVER"; - static const char *client_str = "CLIENT"; - const uint8_t *peer_str; - size_t peer_str_len; - - /* Clean up logging space */ - memset(client_log_buffer, 0, sizeof(client_log_buffer)); - memset(server_log_buffer, 0, sizeof(server_log_buffer)); - client_log_buffer_index = 0; - server_log_buffer_index = 0; - error_writing_log = 0; - - - if (!TEST_ptr(sctx = SSL_CTX_new(TLS_server_method())) - || !TEST_true(SSL_CTX_set_quic_method(sctx, &quic_method)) - || !TEST_ptr(sctx->quic_method) - || !TEST_ptr(serverssl = SSL_new(sctx)) - || !TEST_true(SSL_IS_QUIC(serverssl)) - || !TEST_true(SSL_set_quic_method(serverssl, NULL)) - || !TEST_false(SSL_IS_QUIC(serverssl)) - || !TEST_true(SSL_set_quic_method(serverssl, &quic_method)) - || !TEST_true(SSL_IS_QUIC(serverssl))) - goto end; - - SSL_CTX_free(sctx); - sctx = NULL; - SSL_free(serverssl); - serverssl = NULL; - - if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), - TLS_client_method(), - TLS1_3_VERSION, 0, - &sctx, &cctx, cert, privkey)) - || !TEST_true(SSL_CTX_set_quic_method(sctx, &quic_method)) - || !TEST_true(SSL_CTX_set_quic_method(cctx, &quic_method)) - || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, - &clientssl, NULL, NULL)) - || !TEST_true(SSL_set_quic_transport_params(serverssl, - (unsigned char*)server_str, - strlen(server_str))) - || !TEST_true(SSL_set_quic_transport_params(clientssl, - (unsigned char*)client_str, - strlen(client_str))) - || !TEST_true(SSL_set_app_data(serverssl, clientssl)) - || !TEST_true(SSL_set_app_data(clientssl, serverssl)) - || !TEST_true(create_ssl_connection(serverssl, clientssl, - SSL_ERROR_NONE)) - || !TEST_true(SSL_version(serverssl) == TLS1_3_VERSION) - || !TEST_true(SSL_version(clientssl) == TLS1_3_VERSION) - || !(TEST_int_eq(SSL_quic_read_level(clientssl), ssl_encryption_application)) - || !(TEST_int_eq(SSL_quic_read_level(serverssl), ssl_encryption_application)) - || !(TEST_int_eq(SSL_quic_write_level(clientssl), ssl_encryption_application)) - || !(TEST_int_eq(SSL_quic_write_level(serverssl), ssl_encryption_application))) - goto end; - - SSL_get_peer_quic_transport_params(serverssl, &peer_str, &peer_str_len); - if (!TEST_mem_eq(peer_str, peer_str_len, client_str, strlen(client_str))) - goto end; - SSL_get_peer_quic_transport_params(clientssl, &peer_str, &peer_str_len); - if (!TEST_mem_eq(peer_str, peer_str_len, server_str, strlen(server_str))) - goto end; - - /* Deal with two NewSessionTickets */ - if (!TEST_true(SSL_process_quic_post_handshake(clientssl)) - || !TEST_true(SSL_process_quic_post_handshake(clientssl))) - goto end; - - testresult = 1; - -end: - SSL_free(serverssl); - SSL_free(clientssl); - SSL_CTX_free(sctx); - SSL_CTX_free(cctx); - - return testresult; -} -#endif - /* * Test 0: Client sets servername and server acknowledges it (TLSv1.2) * Test 1: Client sets servername and server does not acknowledge it (TLSv1.2) @@ -6607,6 +6477,419 @@ static int test_servername(int tst) return testresult; } +#ifndef OPENSSL_NO_QUIC +static uint8_t default_quic_early_data_ctx[2] = {1, 2}; + +static int test_quic_set_read_secret(SSL *ssl, + OSSL_ENCRYPTION_LEVEL level, + const SSL_CIPHER *cipher, + const uint8_t *secret, + size_t secret_len) +{ + test_printf_stderr("test_quic_set_read_secret() %s, lvl=%d, len=%zd\n", + ssl->server ? "server" : "client", level, secret_len); + return 1; +} + +static int test_quic_set_write_secret(SSL *ssl, + OSSL_ENCRYPTION_LEVEL level, + const SSL_CIPHER *cipher, + const uint8_t *secret, + size_t secret_len) +{ + test_printf_stderr("test_quic_set_write_secret() %s, lvl=%d, len=%zd\n", + ssl->server ? "server" : "client", level, secret_len); + return 1; +} + +static int test_quic_add_handshake_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL level, + const uint8_t *data, size_t len) +{ + SSL *peer = (SSL*)SSL_get_app_data(ssl); + + TEST_info("quic_add_handshake_data() %s, lvl=%d, *data=0x%02X, len=%zd\n", + ssl->server ? "server" : "client", level, (int)*data, len); + if (!TEST_ptr(peer)) + return 0; + + /* We're called with what is locally written; this gives it to the peer */ + if (!TEST_true(SSL_provide_quic_data(peer, level, data, len))) { + ERR_print_errors_fp(stderr); + return 0; + } + + return 1; +} +static int test_quic_flush_flight(SSL *ssl) +{ + test_printf_stderr("quic_flush_flight() %s\n", ssl->server ? "server" : "client"); + return 1; +} +static int test_quic_send_alert(SSL *ssl, enum ssl_encryption_level_t level, uint8_t alert) +{ + test_printf_stderr("quic_send_alert() %s, lvl=%d, alert=%d\n", + ssl->server ? "server" : "client", level, alert); + return 1; +} + +static SSL_QUIC_METHOD quic_method = { + test_quic_set_read_secret, + test_quic_set_write_secret, + test_quic_add_handshake_data, + test_quic_flush_flight, + test_quic_send_alert, +}; + +static int test_quic_api_set_versions(SSL *ssl, int ver) +{ + SSL_set_quic_transport_version(ssl, ver); + return 1; +} + +static int test_quic_api_version(int clnt, int srvr) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + int testresult = 0; + static const char *server_str = "SERVER"; + static const char *client_str = "CLIENT"; + const uint8_t *peer_str; + size_t peer_str_len; + + TEST_info("original clnt=0x%X, srvr=0x%X\n", clnt, srvr); + + if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), + TLS_client_method(), + TLS1_3_VERSION, 0, + &sctx, &cctx, cert, privkey)) + || !TEST_true(SSL_CTX_set_quic_method(sctx, &quic_method)) + || !TEST_true(SSL_CTX_set_quic_method(cctx, &quic_method)) + || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, + &clientssl, NULL, NULL)) + || !TEST_true(SSL_set_quic_transport_params(serverssl, + (unsigned char*)server_str, + strlen(server_str)+1)) + || !TEST_true(SSL_set_quic_transport_params(clientssl, + (unsigned char*)client_str, + strlen(client_str)+1)) + || !TEST_true(SSL_set_app_data(serverssl, clientssl)) + || !TEST_true(SSL_set_app_data(clientssl, serverssl)) + || !TEST_true(test_quic_api_set_versions(clientssl, clnt)) + || !TEST_true(test_quic_api_set_versions(serverssl, srvr)) + || !TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE)) + || !TEST_true(SSL_version(serverssl) == TLS1_3_VERSION) + || !TEST_true(SSL_version(clientssl) == TLS1_3_VERSION) + || !(TEST_int_eq(SSL_quic_read_level(clientssl), ssl_encryption_application)) + || !(TEST_int_eq(SSL_quic_read_level(serverssl), ssl_encryption_application)) + || !(TEST_int_eq(SSL_quic_write_level(clientssl), ssl_encryption_application)) + || !(TEST_int_eq(SSL_quic_write_level(serverssl), ssl_encryption_application))) + goto end; + + SSL_get_peer_quic_transport_params(serverssl, &peer_str, &peer_str_len); + if (!TEST_mem_eq(peer_str, peer_str_len, client_str, strlen(client_str)+1)) + goto end; + SSL_get_peer_quic_transport_params(clientssl, &peer_str, &peer_str_len); + if (!TEST_mem_eq(peer_str, peer_str_len, server_str, strlen(server_str)+1)) + goto end; + + /* Deal with two NewSessionTickets */ + if (!TEST_true(SSL_process_quic_post_handshake(clientssl))) + goto end; + + /* Dummy handshake call should succeed */ + if (!TEST_true(SSL_do_handshake(clientssl))) + goto end; + /* Test that we (correctly) fail to send KeyUpdate */ + if (!TEST_true(SSL_key_update(clientssl, SSL_KEY_UPDATE_NOT_REQUESTED)) + || !TEST_int_le(SSL_do_handshake(clientssl), 0)) + goto end; + if (!TEST_true(SSL_key_update(serverssl, SSL_KEY_UPDATE_NOT_REQUESTED)) + || !TEST_int_le(SSL_do_handshake(serverssl), 0)) + goto end; + + TEST_info("original clnt=0x%X, srvr=0x%X\n", clnt, srvr); + if (srvr == 0 && clnt == 0) + srvr = clnt = TLSEXT_TYPE_quic_transport_parameters; + else if (srvr == 0) + srvr = clnt; + else if (clnt == 0) + clnt = srvr; + TEST_info("expected clnt=0x%X, srvr=0x%X\n", clnt, srvr); + if (!TEST_int_eq(SSL_get_peer_quic_transport_version(serverssl), clnt)) + goto end; + if (!TEST_int_eq(SSL_get_peer_quic_transport_version(clientssl), srvr)) + goto end; + + testresult = 1; + +end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + + return testresult; +} + +static int test_quic_api(int tst) +{ + SSL_CTX *sctx = NULL; + SSL *serverssl = NULL; + int testresult = 0; + static int clnt_params[] = { 0, + TLSEXT_TYPE_quic_transport_parameters_draft, + TLSEXT_TYPE_quic_transport_parameters, + 0, + TLSEXT_TYPE_quic_transport_parameters_draft, + TLSEXT_TYPE_quic_transport_parameters, + 0, + TLSEXT_TYPE_quic_transport_parameters_draft, + TLSEXT_TYPE_quic_transport_parameters }; + static int srvr_params[] = { 0, + 0, + 0, + TLSEXT_TYPE_quic_transport_parameters_draft, + TLSEXT_TYPE_quic_transport_parameters_draft, + TLSEXT_TYPE_quic_transport_parameters_draft, + TLSEXT_TYPE_quic_transport_parameters, + TLSEXT_TYPE_quic_transport_parameters, + TLSEXT_TYPE_quic_transport_parameters }; + static int results[] = { 1, 1, 1, 1, 1, 0, 1, 0, 1 }; + + /* Failure cases: + * test 6/[5] clnt = parameters, srvr = draft + * test 8/[7] clnt = draft, srvr = parameters + */ + + /* Clean up logging space */ + memset(client_log_buffer, 0, sizeof(client_log_buffer)); + memset(server_log_buffer, 0, sizeof(server_log_buffer)); + client_log_buffer_index = 0; + server_log_buffer_index = 0; + error_writing_log = 0; + + if (!TEST_ptr(sctx = SSL_CTX_new(TLS_server_method())) + || !TEST_true(SSL_CTX_set_quic_method(sctx, &quic_method)) + || !TEST_ptr(sctx->quic_method) + || !TEST_ptr(serverssl = SSL_new(sctx)) + || !TEST_true(SSL_IS_QUIC(serverssl)) + || !TEST_true(SSL_set_quic_method(serverssl, NULL)) + || !TEST_false(SSL_IS_QUIC(serverssl)) + || !TEST_true(SSL_set_quic_method(serverssl, &quic_method)) + || !TEST_true(SSL_IS_QUIC(serverssl))) + goto end; + + if (!TEST_int_eq(test_quic_api_version(clnt_params[tst], srvr_params[tst]), results[tst])) + goto end; + + testresult = 1; + +end: + SSL_CTX_free(sctx); + sctx = NULL; + SSL_free(serverssl); + serverssl = NULL; + return testresult; +} + +/* + * Helper method to setup objects for QUIC early data test. Caller + * frees objects on error. + */ +static int quic_setupearly_data_test(SSL_CTX **cctx, SSL_CTX **sctx, + SSL **clientssl, SSL **serverssl, + SSL_SESSION **sess, int idx) +{ + static const char *server_str = "SERVER"; + static const char *client_str = "CLIENT"; + + if (*sctx == NULL + && (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), + TLS_client_method(), + TLS1_3_VERSION, 0, + sctx, cctx, cert, privkey)) + || !TEST_true(SSL_CTX_set_quic_method(*sctx, &quic_method)) + || !TEST_true(SSL_CTX_set_quic_method(*cctx, &quic_method)) + || !TEST_true(SSL_CTX_set_max_early_data(*sctx, 0xffffffffu)))) + return 0; + + if (idx == 1) { + /* When idx == 1 we repeat the tests with read_ahead set */ + SSL_CTX_set_read_ahead(*cctx, 1); + SSL_CTX_set_read_ahead(*sctx, 1); + } else if (idx == 2) { + /* When idx == 2 we are doing early_data with a PSK. Set up callbacks */ + SSL_CTX_set_psk_use_session_callback(*cctx, use_session_cb); + SSL_CTX_set_psk_find_session_callback(*sctx, find_session_cb); + use_session_cb_cnt = 0; + find_session_cb_cnt = 0; + srvid = pskid; + } + + if (!TEST_true(create_ssl_objects(*sctx, *cctx, serverssl, clientssl, + NULL, NULL)) + || !TEST_true(SSL_set_quic_transport_params(*serverssl, + (unsigned char*)server_str, + strlen(server_str)+1)) + || !TEST_true(SSL_set_quic_transport_params(*clientssl, + (unsigned char*)client_str, + strlen(client_str)+1)) + || !TEST_true(SSL_set_quic_early_data_context(*serverssl, + default_quic_early_data_ctx, + sizeof(default_quic_early_data_ctx))) + || !TEST_true(SSL_set_app_data(*serverssl, *clientssl)) + || !TEST_true(SSL_set_app_data(*clientssl, *serverssl))) + return 0; + + /* + * For one of the run throughs (doesn't matter which one), we'll try sending + * some SNI data in the initial ClientHello. This will be ignored (because + * there is no SNI cb set up by the server), so it should not impact + * early_data. + */ + if (idx == 1 + && !TEST_true(SSL_set_tlsext_host_name(*clientssl, "localhost"))) + return 0; + + if (idx == 2) { + clientpsk = create_a_psk(*clientssl); + if (!TEST_ptr(clientpsk) + || !TEST_true(SSL_SESSION_set_max_early_data(clientpsk, + 0xffffffffu)) + || !TEST_true(SSL_SESSION_up_ref(clientpsk))) { + SSL_SESSION_free(clientpsk); + clientpsk = NULL; + return 0; + } + + if ((*serverssl)->quic_early_data_context) { + clientpsk->quic_early_data_context = + OPENSSL_memdup((*serverssl)->quic_early_data_context, + (*serverssl)->quic_early_data_context_len); + if (!TEST_ptr(clientpsk->quic_early_data_context)) { + SSL_SESSION_free(clientpsk); + clientpsk = NULL; + return 0; + } + + clientpsk->quic_early_data_context_len = + (*serverssl)->quic_early_data_context_len; + } + + serverpsk = clientpsk; + + if (sess != NULL) { + if (!TEST_true(SSL_SESSION_up_ref(clientpsk))) { + SSL_SESSION_free(clientpsk); + SSL_SESSION_free(serverpsk); + clientpsk = serverpsk = NULL; + return 0; + } + *sess = clientpsk; + } + + SSL_set_quic_early_data_enabled(*serverssl, 1); + SSL_set_quic_early_data_enabled(*clientssl, 1); + + return 1; + } + + if (sess == NULL) + return 1; + + if (!TEST_true(create_ssl_connection(*serverssl, *clientssl, + SSL_ERROR_NONE))) + return 0; + + /* Deal with two NewSessionTickets */ + if (!TEST_true(SSL_process_quic_post_handshake(*clientssl))) + return 0; + + *sess = SSL_get1_session(*clientssl); + SSL_shutdown(*clientssl); + SSL_shutdown(*serverssl); + SSL_free(*serverssl); + SSL_free(*clientssl); + *serverssl = *clientssl = NULL; + + if (!TEST_true(create_ssl_objects(*sctx, *cctx, serverssl, + clientssl, NULL, NULL)) + || !TEST_true(SSL_set_session(*clientssl, *sess)) + || !TEST_true(SSL_set_quic_transport_params(*serverssl, + (unsigned char*)server_str, + strlen(server_str)+1)) + || !TEST_true(SSL_set_quic_transport_params(*clientssl, + (unsigned char*)client_str, + strlen(client_str)+1)) + || !TEST_true(SSL_set_app_data(*serverssl, *clientssl)) + || !TEST_true(SSL_set_app_data(*clientssl, *serverssl))) + return 0; + + SSL_set_quic_early_data_enabled(*serverssl, 1); + SSL_set_quic_early_data_enabled(*clientssl, 1); + + return 1; +} + +/* + * TEST 0: quic early data + * TEST 1: quic early data with read_ahead set + * TEST 2: quic early data, client use session cb, server find session cb + * TEST 3: quic early data context not compatible, reject early data + */ +static int test_quic_early_data(int tst) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + int testresult = 0; + SSL_SESSION *sess = NULL; + uint8_t quic_early_data_ctx[2] = {8, 8}; + + if (!TEST_true(quic_setupearly_data_test(&cctx, &sctx, &clientssl, + &serverssl, &sess, tst))) + goto end; + + if (tst < 3) { + if (!TEST_true(SSL_set_quic_early_data_context(serverssl, + default_quic_early_data_ctx, + sizeof(default_quic_early_data_ctx)))) + goto end; + } else { + if (!TEST_true(SSL_set_quic_early_data_context(serverssl, + quic_early_data_ctx, + sizeof(quic_early_data_ctx)))) + goto end; + } + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) + goto end; + + if (tst < 3) { + if (!TEST_int_eq(SSL_get_early_data_status(serverssl), + SSL_EARLY_DATA_ACCEPTED)) + goto end; + } else { + if (!TEST_int_eq(SSL_get_early_data_status(serverssl), + SSL_EARLY_DATA_REJECTED)) + goto end; + } + + testresult = 1; + +end: + SSL_SESSION_free(sess); + SSL_SESSION_free(clientpsk); + SSL_SESSION_free(serverpsk); + clientpsk = serverpsk = NULL; + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + return testresult; +} +#endif + int setup_tests(void) { if (!TEST_ptr(certsdir = test_get_argument(0)) @@ -6725,10 +7008,12 @@ int setup_tests(void) ADD_ALL_TESTS(test_cert_cb, 6); ADD_ALL_TESTS(test_client_cert_cb, 2); ADD_ALL_TESTS(test_ca_names, 3); + ADD_ALL_TESTS(test_servername, 10); #ifndef OPENSSL_NO_QUIC - ADD_TEST(test_quic_api); + ADD_ALL_TESTS(test_quic_api, 9); + ADD_ALL_TESTS(test_quic_early_data, 4); #endif - ADD_ALL_TESTS(test_servername, 10); + return 1; } diff --git a/test/tls13secretstest.c b/test/tls13secretstest.c index 970c2f4aa..ec8da3203 100644 --- a/test/tls13secretstest.c +++ b/test/tls13secretstest.c @@ -217,7 +217,7 @@ int ossl_statem_export_early_allowed(SSL *s) } #ifndef OPENSSL_NO_QUIC -int quic_set_encryption_secrets(SSL *ssl, OSSL_ENCRYPTION_LEVEL level) +int quic_set_encryption_secrets(SSL *s, OSSL_ENCRYPTION_LEVEL level) { return 1; } diff --git a/util/libcrypto.num b/util/libcrypto.num index 0f24cba65..664e3d25b 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -4602,3 +4602,38 @@ RSA_get0_pss_params 4555 1_1_1e EXIST::FUNCTION:RSA X509_ALGOR_copy 4556 1_1_1h EXIST::FUNCTION: X509_REQ_set0_signature 4557 1_1_1h EXIST::FUNCTION: X509_REQ_set1_signature_algo 4558 1_1_1h EXIST::FUNCTION: +DC_set0_dc_publickey 4559 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_set_expected_cert_verify_algorithm 4560 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_set_dc_signature_len 4561 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_get_dc_signature_len 4562 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_get_dc_publickey_len 4563 1_1_1h NOEXIST::FUNCTION: +DC_get_valid_time 4564 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_get_expected_cert_verify_algorithm 4565 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_set_valid_time 4566 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_get_dc_signature 4567 1_1_1h NOEXIST::FUNCTION: +DC_set_dc_publickey_len 4568 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_set0_dc_signature 4569 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_check_valid 4570 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_set_signature_sign_algorithm 4571 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +delegated_credential_check_valid 4572 1_1_1h NOEXIST::FUNCTION: +DC_get_dc_publickey 4573 1_1_1h NOEXIST::FUNCTION: +DC_get_signature_sign_algorithm 4574 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_free 4575 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_new 4577 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_check_time_valid 4578 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_check_parent_cert_valid 4579 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +X509_get0_der_encode_len 4580 1_1_1h NOEXIST::FUNCTION: +X509_get0_der_encode 4581 1_1_1h NOEXIST::FUNCTION: +DC_set1_raw_byte 4582 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_new_from_raw_byte 4583 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_get0_dc_signature 4584 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_set0_publickey 4585 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_get0_dc_publickey_raw 4586 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_get0_publickey 4587 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_get_raw_byte_len 4588 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_get_dc_publickey_raw_len 4589 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_get0_raw_byte 4590 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_check_private_key 4591 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_up_ref 4592 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_load_from_file 4593 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_set0_raw_byte 4594 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL diff --git a/util/libssl.num b/util/libssl.num index 88110684a..343f17aab 100644 --- a/util/libssl.num +++ b/util/libssl.num @@ -570,15 +570,40 @@ SSL_CTX_set_options2 622 1_1_1g EXIST::FUNCTION:OPTIONS2 SSL_CTX_clear_options2 623 1_1_1g EXIST::FUNCTION:OPTIONS2 SSL_get_options2 625 1_1_1g EXIST::FUNCTION:OPTIONS2 SSL_clear_options2 626 1_1_1g EXIST::FUNCTION:OPTIONS2 -SSL_quic_read_level 10094 1_1_1d EXIST::FUNCTION:QUIC -SSL_set_quic_transport_params 10095 1_1_1d EXIST::FUNCTION:QUIC -SSL_CIPHER_get_prf_nid 10096 1_1_1d EXIST::FUNCTION: -SSL_is_quic 10097 1_1_1d EXIST::FUNCTION:QUIC -SSL_get_peer_quic_transport_params 10098 1_1_1d EXIST::FUNCTION:QUIC -SSL_quic_write_level 10099 1_1_1d EXIST::FUNCTION:QUIC -SSL_CTX_set_quic_method 10100 1_1_1d EXIST::FUNCTION:QUIC -SSL_set_quic_method 10101 1_1_1d EXIST::FUNCTION:QUIC -SSL_quic_max_handshake_flight_len 10102 1_1_1d EXIST::FUNCTION:QUIC -SSL_process_quic_post_handshake 10103 1_1_1d EXIST::FUNCTION:QUIC -SSL_provide_quic_data 10104 1_1_1d EXIST::FUNCTION:QUIC -SSL_set_quic_early_data_enabled 11000 1_1_1d EXIST::FUNCTION:QUIC +SSL_verify_delegated_credential_signature 632 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +SSL_disable_verify_peer_by_dc 639 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +SSL_CTX_enable_sign_by_dc 640 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +SSL_enable_sign_by_dc 641 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +SSL_CTX_disable_verify_peer_by_dc 642 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +SSL_enable_verify_peer_by_dc 643 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +SSL_disable_sign_by_dc 644 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +SSL_CTX_disable_sign_by_dc 645 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +SSL_CTX_enable_verify_peer_by_dc 646 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +SSL_get_delegated_credential_tag 652 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +SSL_quic_read_level 20000 1_1_1h EXIST::FUNCTION:QUIC +SSL_set_quic_transport_params 20001 1_1_1h EXIST::FUNCTION:QUIC +SSL_CIPHER_get_prf_nid 20002 1_1_1h EXIST::FUNCTION:QUIC +SSL_is_quic 20003 1_1_1h EXIST::FUNCTION:QUIC +SSL_get_peer_quic_transport_params 20004 1_1_1h EXIST::FUNCTION:QUIC +SSL_quic_write_level 20005 1_1_1h EXIST::FUNCTION:QUIC +SSL_CTX_set_quic_method 20006 1_1_1h EXIST::FUNCTION:QUIC +SSL_set_quic_method 20007 1_1_1h EXIST::FUNCTION:QUIC +SSL_quic_max_handshake_flight_len 20008 1_1_1h EXIST::FUNCTION:QUIC +SSL_process_quic_post_handshake 20009 1_1_1h EXIST::FUNCTION:QUIC +SSL_provide_quic_data 20010 1_1_1h EXIST::FUNCTION:QUIC +SSL_set_quic_use_legacy_codepoint 20011 1_1_1h EXIST::FUNCTION:QUIC +SSL_set_quic_transport_version 20012 1_1_1h EXIST::FUNCTION:QUIC +SSL_get_peer_quic_transport_version 20013 1_1_1h EXIST::FUNCTION:QUIC +SSL_get_quic_transport_version 20014 1_1_1h EXIST::FUNCTION:QUIC +SSL_set_quic_early_data_enabled 20015 1_1_1h EXIST::FUNCTION:QUIC +SSL_set_quic_early_data_context 20016 1_1_1h EXIST::FUNCTION:QUIC +SSL_use_dc 20017 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +SSL_CTX_use_dc 20018 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +SSL_use_dc_PrivateKey 20019 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +SSL_CTX_use_dc_PrivateKey 20020 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +SSL_use_dc_file 20021 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +SSL_CTX_use_dc_file 20022 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +SSL_use_dc_PrivateKey_file 20023 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +SSL_CTX_use_dc_PrivateKey_file 20024 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_sign 20025 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL +DC_print 20026 1_1_1h EXIST::FUNCTION:DELEGATED_CREDENTIAL diff --git a/util/mktar.sh b/util/mktar.sh new file mode 100755 index 000000000..17115cf59 --- /dev/null +++ b/util/mktar.sh @@ -0,0 +1,36 @@ +#! /bin/sh +# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +HERE=`dirname $0` + +version=`grep 'OPENSSL_VERSION_TEXT *"OpenSSL' $HERE/../include/openssl/opensslv.h | sed -e 's|.*"OpenSSL ||' -e 's| .*||'` +basename=openssl + +NAME="$basename-$version" + +while [ $# -gt 0 ]; do + case "$1" in + --name=* ) NAME=`echo "$1" | sed -e 's|[^=]*=||'` ;; + --name ) shift; NAME="$1" ;; + --tarfile=* ) TARFILE=`echo "$1" | sed -e 's|[^=]*=||'` ;; + --tarfile ) shift; TARFILE="$1" ;; + * ) echo >&2 "Could not parse '$1'"; exit 1 ;; + esac + shift +done + +if [ -z "$TARFILE" ]; then TARFILE="$NAME.tar"; fi + +# This counts on .gitattributes to specify what files should be ignored +git archive --worktree-attributes --format=tar --prefix="$NAME/" -v HEAD \ + | gzip -9 > "$TARFILE.gz" + +# Good old way to ensure we display an absolute path +td=`dirname $TARFILE` +tf=`basename $TARFILE` +ls -l "`cd $td; pwd`/$tf.gz"