aboutsummaryrefslogtreecommitdiff
path: root/openssl-1.1.0h/ssl
diff options
context:
space:
mode:
Diffstat (limited to 'openssl-1.1.0h/ssl')
-rw-r--r--openssl-1.1.0h/ssl/bio_ssl.c516
-rw-r--r--openssl-1.1.0h/ssl/build.info14
-rw-r--r--openssl-1.1.0h/ssl/d1_lib.c1087
-rw-r--r--openssl-1.1.0h/ssl/d1_msg.c84
-rw-r--r--openssl-1.1.0h/ssl/d1_srtp.c329
-rw-r--r--openssl-1.1.0h/ssl/methods.c266
-rw-r--r--openssl-1.1.0h/ssl/packet_locl.h555
-rw-r--r--openssl-1.1.0h/ssl/pqueue.c154
-rw-r--r--openssl-1.1.0h/ssl/record/README74
-rw-r--r--openssl-1.1.0h/ssl/record/dtls1_bitmap.c78
-rw-r--r--openssl-1.1.0h/ssl/record/rec_layer_d1.c1229
-rw-r--r--openssl-1.1.0h/ssl/record/rec_layer_s3.c1549
-rw-r--r--openssl-1.1.0h/ssl/record/record.h243
-rw-r--r--openssl-1.1.0h/ssl/record/record_locl.h116
-rw-r--r--openssl-1.1.0h/ssl/record/ssl3_buffer.c163
-rw-r--r--openssl-1.1.0h/ssl/record/ssl3_record.c1641
-rw-r--r--openssl-1.1.0h/ssl/s3_cbc.c529
-rw-r--r--openssl-1.1.0h/ssl/s3_enc.c550
-rw-r--r--openssl-1.1.0h/ssl/s3_lib.c4140
-rw-r--r--openssl-1.1.0h/ssl/s3_msg.c102
-rw-r--r--openssl-1.1.0h/ssl/ssl_asn1.c367
-rw-r--r--openssl-1.1.0h/ssl/ssl_cert.c1087
-rw-r--r--openssl-1.1.0h/ssl/ssl_ciph.c1962
-rw-r--r--openssl-1.1.0h/ssl/ssl_conf.c893
-rw-r--r--openssl-1.1.0h/ssl/ssl_err.c689
-rw-r--r--openssl-1.1.0h/ssl/ssl_init.c210
-rw-r--r--openssl-1.1.0h/ssl/ssl_lib.c4476
-rw-r--r--openssl-1.1.0h/ssl/ssl_locl.h2133
-rw-r--r--openssl-1.1.0h/ssl/ssl_mcnf.c199
-rw-r--r--openssl-1.1.0h/ssl/ssl_rsa.c964
-rw-r--r--openssl-1.1.0h/ssl/ssl_sess.c1179
-rw-r--r--openssl-1.1.0h/ssl/ssl_stat.c362
-rw-r--r--openssl-1.1.0h/ssl/ssl_txt.c217
-rw-r--r--openssl-1.1.0h/ssl/ssl_utst.c28
-rw-r--r--openssl-1.1.0h/ssl/statem/README63
-rw-r--r--openssl-1.1.0h/ssl/statem/statem.c860
-rw-r--r--openssl-1.1.0h/ssl/statem/statem.h116
-rw-r--r--openssl-1.1.0h/ssl/statem/statem_clnt.c2946
-rw-r--r--openssl-1.1.0h/ssl/statem/statem_dtls.c1220
-rw-r--r--openssl-1.1.0h/ssl/statem/statem_lib.c1083
-rw-r--r--openssl-1.1.0h/ssl/statem/statem_locl.h125
-rw-r--r--openssl-1.1.0h/ssl/statem/statem_srvr.c3341
-rw-r--r--openssl-1.1.0h/ssl/t1_enc.c668
-rw-r--r--openssl-1.1.0h/ssl/t1_ext.c283
-rw-r--r--openssl-1.1.0h/ssl/t1_lib.c4228
-rw-r--r--openssl-1.1.0h/ssl/t1_reneg.c165
-rw-r--r--openssl-1.1.0h/ssl/t1_trce.c1322
-rw-r--r--openssl-1.1.0h/ssl/tls_srp.c430
48 files changed, 45035 insertions, 0 deletions
diff --git a/openssl-1.1.0h/ssl/bio_ssl.c b/openssl-1.1.0h/ssl/bio_ssl.c
new file mode 100644
index 0000000..97540e6
--- /dev/null
+++ b/openssl-1.1.0h/ssl/bio_ssl.c
@@ -0,0 +1,516 @@
+/*
+ * Copyright 1995-2017 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
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <openssl/crypto.h>
+#include "internal/bio.h"
+#include <openssl/err.h>
+#include "ssl_locl.h"
+
+static int ssl_write(BIO *h, const char *buf, int num);
+static int ssl_read(BIO *h, char *buf, int size);
+static int ssl_puts(BIO *h, const char *str);
+static long ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2);
+static int ssl_new(BIO *h);
+static int ssl_free(BIO *data);
+static long ssl_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
+typedef struct bio_ssl_st {
+ SSL *ssl; /* The ssl handle :-) */
+ /* re-negotiate every time the total number of bytes is this size */
+ int num_renegotiates;
+ unsigned long renegotiate_count;
+ unsigned long byte_count;
+ unsigned long renegotiate_timeout;
+ unsigned long last_time;
+} BIO_SSL;
+
+static const BIO_METHOD methods_sslp = {
+ BIO_TYPE_SSL,
+ "ssl",
+ ssl_write,
+ ssl_read,
+ ssl_puts,
+ NULL, /* ssl_gets, */
+ ssl_ctrl,
+ ssl_new,
+ ssl_free,
+ ssl_callback_ctrl,
+};
+
+const BIO_METHOD *BIO_f_ssl(void)
+{
+ return (&methods_sslp);
+}
+
+static int ssl_new(BIO *bi)
+{
+ BIO_SSL *bs = OPENSSL_zalloc(sizeof(*bs));
+
+ if (bs == NULL) {
+ BIOerr(BIO_F_SSL_NEW, ERR_R_MALLOC_FAILURE);
+ return (0);
+ }
+ BIO_set_init(bi, 0);
+ BIO_set_data(bi, bs);
+ /* Clear all flags */
+ BIO_clear_flags(bi, ~0);
+
+ return 1;
+}
+
+static int ssl_free(BIO *a)
+{
+ BIO_SSL *bs;
+
+ if (a == NULL)
+ return (0);
+ bs = BIO_get_data(a);
+ if (bs->ssl != NULL)
+ SSL_shutdown(bs->ssl);
+ if (BIO_get_shutdown(a)) {
+ if (BIO_get_init(a))
+ SSL_free(bs->ssl);
+ /* Clear all flags */
+ BIO_clear_flags(a, ~0);
+ BIO_set_init(a, 0);
+ }
+ OPENSSL_free(bs);
+ return 1;
+}
+
+static int ssl_read(BIO *b, char *out, int outl)
+{
+ int ret = 1;
+ BIO_SSL *sb;
+ SSL *ssl;
+ int retry_reason = 0;
+ int r = 0;
+
+ if (out == NULL)
+ return (0);
+ sb = BIO_get_data(b);
+ ssl = sb->ssl;
+
+ BIO_clear_retry_flags(b);
+
+ ret = SSL_read(ssl, out, outl);
+
+ switch (SSL_get_error(ssl, ret)) {
+ case SSL_ERROR_NONE:
+ if (ret <= 0)
+ break;
+ if (sb->renegotiate_count > 0) {
+ sb->byte_count += ret;
+ if (sb->byte_count > sb->renegotiate_count) {
+ sb->byte_count = 0;
+ sb->num_renegotiates++;
+ SSL_renegotiate(ssl);
+ r = 1;
+ }
+ }
+ if ((sb->renegotiate_timeout > 0) && (!r)) {
+ unsigned long tm;
+
+ tm = (unsigned long)time(NULL);
+ if (tm > sb->last_time + sb->renegotiate_timeout) {
+ sb->last_time = tm;
+ sb->num_renegotiates++;
+ SSL_renegotiate(ssl);
+ }
+ }
+
+ break;
+ case SSL_ERROR_WANT_READ:
+ BIO_set_retry_read(b);
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ BIO_set_retry_write(b);
+ break;
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ BIO_set_retry_special(b);
+ retry_reason = BIO_RR_SSL_X509_LOOKUP;
+ break;
+ case SSL_ERROR_WANT_ACCEPT:
+ BIO_set_retry_special(b);
+ retry_reason = BIO_RR_ACCEPT;
+ break;
+ case SSL_ERROR_WANT_CONNECT:
+ BIO_set_retry_special(b);
+ retry_reason = BIO_RR_CONNECT;
+ break;
+ case SSL_ERROR_SYSCALL:
+ case SSL_ERROR_SSL:
+ case SSL_ERROR_ZERO_RETURN:
+ default:
+ break;
+ }
+
+ BIO_set_retry_reason(b, retry_reason);
+ return (ret);
+}
+
+static int ssl_write(BIO *b, const char *out, int outl)
+{
+ int ret, r = 0;
+ int retry_reason = 0;
+ SSL *ssl;
+ BIO_SSL *bs;
+
+ if (out == NULL)
+ return (0);
+ bs = BIO_get_data(b);
+ ssl = bs->ssl;
+
+ BIO_clear_retry_flags(b);
+
+ /*
+ * ret=SSL_do_handshake(ssl); if (ret > 0)
+ */
+ ret = SSL_write(ssl, out, outl);
+
+ switch (SSL_get_error(ssl, ret)) {
+ case SSL_ERROR_NONE:
+ if (ret <= 0)
+ break;
+ if (bs->renegotiate_count > 0) {
+ bs->byte_count += ret;
+ if (bs->byte_count > bs->renegotiate_count) {
+ bs->byte_count = 0;
+ bs->num_renegotiates++;
+ SSL_renegotiate(ssl);
+ r = 1;
+ }
+ }
+ if ((bs->renegotiate_timeout > 0) && (!r)) {
+ unsigned long tm;
+
+ tm = (unsigned long)time(NULL);
+ if (tm > bs->last_time + bs->renegotiate_timeout) {
+ bs->last_time = tm;
+ bs->num_renegotiates++;
+ SSL_renegotiate(ssl);
+ }
+ }
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ BIO_set_retry_write(b);
+ break;
+ case SSL_ERROR_WANT_READ:
+ BIO_set_retry_read(b);
+ break;
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ BIO_set_retry_special(b);
+ retry_reason = BIO_RR_SSL_X509_LOOKUP;
+ break;
+ case SSL_ERROR_WANT_CONNECT:
+ BIO_set_retry_special(b);
+ retry_reason = BIO_RR_CONNECT;
+ case SSL_ERROR_SYSCALL:
+ case SSL_ERROR_SSL:
+ default:
+ break;
+ }
+
+ BIO_set_retry_reason(b, retry_reason);
+ return ret;
+}
+
+static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr)
+{
+ SSL **sslp, *ssl;
+ BIO_SSL *bs, *dbs;
+ BIO *dbio, *bio;
+ long ret = 1;
+ BIO *next;
+
+ bs = BIO_get_data(b);
+ next = BIO_next(b);
+ ssl = bs->ssl;
+ if ((ssl == NULL) && (cmd != BIO_C_SET_SSL))
+ return (0);
+ switch (cmd) {
+ case BIO_CTRL_RESET:
+ SSL_shutdown(ssl);
+
+ if (ssl->handshake_func == ssl->method->ssl_connect)
+ SSL_set_connect_state(ssl);
+ else if (ssl->handshake_func == ssl->method->ssl_accept)
+ SSL_set_accept_state(ssl);
+
+ if (!SSL_clear(ssl)) {
+ ret = 0;
+ break;
+ }
+
+ if (next != NULL)
+ ret = BIO_ctrl(next, cmd, num, ptr);
+ else if (ssl->rbio != NULL)
+ ret = BIO_ctrl(ssl->rbio, cmd, num, ptr);
+ else
+ ret = 1;
+ break;
+ case BIO_CTRL_INFO:
+ ret = 0;
+ break;
+ case BIO_C_SSL_MODE:
+ if (num) /* client mode */
+ SSL_set_connect_state(ssl);
+ else
+ SSL_set_accept_state(ssl);
+ break;
+ case BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT:
+ ret = bs->renegotiate_timeout;
+ if (num < 60)
+ num = 5;
+ bs->renegotiate_timeout = (unsigned long)num;
+ bs->last_time = (unsigned long)time(NULL);
+ break;
+ case BIO_C_SET_SSL_RENEGOTIATE_BYTES:
+ ret = bs->renegotiate_count;
+ if ((long)num >= 512)
+ bs->renegotiate_count = (unsigned long)num;
+ break;
+ case BIO_C_GET_SSL_NUM_RENEGOTIATES:
+ ret = bs->num_renegotiates;
+ break;
+ case BIO_C_SET_SSL:
+ if (ssl != NULL) {
+ ssl_free(b);
+ if (!ssl_new(b))
+ return 0;
+ }
+ BIO_set_shutdown(b, num);
+ ssl = (SSL *)ptr;
+ bs->ssl = ssl;
+ bio = SSL_get_rbio(ssl);
+ if (bio != NULL) {
+ if (next != NULL)
+ BIO_push(bio, next);
+ BIO_set_next(b, bio);
+ BIO_up_ref(bio);
+ }
+ BIO_set_init(b, 1);
+ break;
+ case BIO_C_GET_SSL:
+ if (ptr != NULL) {
+ sslp = (SSL **)ptr;
+ *sslp = ssl;
+ } else
+ ret = 0;
+ break;
+ case BIO_CTRL_GET_CLOSE:
+ ret = BIO_get_shutdown(b);
+ break;
+ case BIO_CTRL_SET_CLOSE:
+ BIO_set_shutdown(b, (int)num);
+ break;
+ case BIO_CTRL_WPENDING:
+ ret = BIO_ctrl(ssl->wbio, cmd, num, ptr);
+ break;
+ case BIO_CTRL_PENDING:
+ ret = SSL_pending(ssl);
+ if (ret == 0)
+ ret = BIO_pending(ssl->rbio);
+ break;
+ case BIO_CTRL_FLUSH:
+ BIO_clear_retry_flags(b);
+ ret = BIO_ctrl(ssl->wbio, cmd, num, ptr);
+ BIO_copy_next_retry(b);
+ break;
+ case BIO_CTRL_PUSH:
+ if ((next != NULL) && (next != ssl->rbio)) {
+ /*
+ * We are going to pass ownership of next to the SSL object...but
+ * we don't own a reference to pass yet - so up ref
+ */
+ BIO_up_ref(next);
+ SSL_set_bio(ssl, next, next);
+ }
+ break;
+ case BIO_CTRL_POP:
+ /* Only detach if we are the BIO explicitly being popped */
+ if (b == ptr) {
+ /* This will clear the reference we obtained during push */
+ SSL_set_bio(ssl, NULL, NULL);
+ }
+ break;
+ case BIO_C_DO_STATE_MACHINE:
+ BIO_clear_retry_flags(b);
+
+ BIO_set_retry_reason(b, 0);
+ ret = (int)SSL_do_handshake(ssl);
+
+ switch (SSL_get_error(ssl, (int)ret)) {
+ case SSL_ERROR_WANT_READ:
+ BIO_set_flags(b, BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY);
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ BIO_set_flags(b, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY);
+ break;
+ case SSL_ERROR_WANT_CONNECT:
+ BIO_set_flags(b, BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY);
+ BIO_set_retry_reason(b, BIO_get_retry_reason(next));
+ break;
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ BIO_set_retry_special(b);
+ BIO_set_retry_reason(b, BIO_RR_SSL_X509_LOOKUP);
+ break;
+ default:
+ break;
+ }
+ break;
+ case BIO_CTRL_DUP:
+ dbio = (BIO *)ptr;
+ dbs = BIO_get_data(dbio);
+ SSL_free(dbs->ssl);
+ dbs->ssl = SSL_dup(ssl);
+ dbs->num_renegotiates = bs->num_renegotiates;
+ dbs->renegotiate_count = bs->renegotiate_count;
+ dbs->byte_count = bs->byte_count;
+ dbs->renegotiate_timeout = bs->renegotiate_timeout;
+ dbs->last_time = bs->last_time;
+ ret = (dbs->ssl != NULL);
+ break;
+ case BIO_C_GET_FD:
+ ret = BIO_ctrl(ssl->rbio, cmd, num, ptr);
+ break;
+ case BIO_CTRL_SET_CALLBACK:
+ {
+#if 0 /* FIXME: Should this be used? -- Richard
+ * Levitte */
+ SSLerr(SSL_F_SSL_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ret = -1;
+#else
+ ret = 0;
+#endif
+ }
+ break;
+ default:
+ ret = BIO_ctrl(ssl->rbio, cmd, num, ptr);
+ break;
+ }
+ return (ret);
+}
+
+static long ssl_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
+{
+ SSL *ssl;
+ BIO_SSL *bs;
+ long ret = 1;
+
+ bs = BIO_get_data(b);
+ ssl = bs->ssl;
+ switch (cmd) {
+ case BIO_CTRL_SET_CALLBACK:
+ ret = BIO_callback_ctrl(ssl->rbio, cmd, fp);
+ break;
+ default:
+ ret = 0;
+ break;
+ }
+ return (ret);
+}
+
+static int ssl_puts(BIO *bp, const char *str)
+{
+ int n, ret;
+
+ n = strlen(str);
+ ret = BIO_write(bp, str, n);
+ return (ret);
+}
+
+BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx)
+{
+#ifndef OPENSSL_NO_SOCK
+ BIO *ret = NULL, *buf = NULL, *ssl = NULL;
+
+ if ((buf = BIO_new(BIO_f_buffer())) == NULL)
+ return (NULL);
+ if ((ssl = BIO_new_ssl_connect(ctx)) == NULL)
+ goto err;
+ if ((ret = BIO_push(buf, ssl)) == NULL)
+ goto err;
+ return (ret);
+ err:
+ BIO_free(buf);
+ BIO_free(ssl);
+#endif
+ return (NULL);
+}
+
+BIO *BIO_new_ssl_connect(SSL_CTX *ctx)
+{
+#ifndef OPENSSL_NO_SOCK
+ BIO *ret = NULL, *con = NULL, *ssl = NULL;
+
+ if ((con = BIO_new(BIO_s_connect())) == NULL)
+ return (NULL);
+ if ((ssl = BIO_new_ssl(ctx, 1)) == NULL)
+ goto err;
+ if ((ret = BIO_push(ssl, con)) == NULL)
+ goto err;
+ return (ret);
+ err:
+ BIO_free(con);
+#endif
+ return (NULL);
+}
+
+BIO *BIO_new_ssl(SSL_CTX *ctx, int client)
+{
+ BIO *ret;
+ SSL *ssl;
+
+ if ((ret = BIO_new(BIO_f_ssl())) == NULL)
+ return (NULL);
+ if ((ssl = SSL_new(ctx)) == NULL) {
+ BIO_free(ret);
+ return (NULL);
+ }
+ if (client)
+ SSL_set_connect_state(ssl);
+ else
+ SSL_set_accept_state(ssl);
+
+ BIO_set_ssl(ret, ssl, BIO_CLOSE);
+ return (ret);
+}
+
+int BIO_ssl_copy_session_id(BIO *t, BIO *f)
+{
+ BIO_SSL *tdata, *fdata;
+ t = BIO_find_type(t, BIO_TYPE_SSL);
+ f = BIO_find_type(f, BIO_TYPE_SSL);
+ if ((t == NULL) || (f == NULL))
+ return 0;
+ tdata = BIO_get_data(t);
+ fdata = BIO_get_data(f);
+ if ((tdata->ssl == NULL) || (fdata->ssl == NULL))
+ return (0);
+ if (!SSL_copy_session_id(tdata->ssl, (fdata->ssl)))
+ return 0;
+ return (1);
+}
+
+void BIO_ssl_shutdown(BIO *b)
+{
+ BIO_SSL *bdata;
+
+ for (; b != NULL; b = BIO_next(b)) {
+ if (BIO_method_type(b) != BIO_TYPE_SSL)
+ continue;
+ bdata = BIO_get_data(b);
+ if (bdata != NULL && bdata->ssl != NULL)
+ SSL_shutdown(bdata->ssl);
+ }
+}
diff --git a/openssl-1.1.0h/ssl/build.info b/openssl-1.1.0h/ssl/build.info
new file mode 100644
index 0000000..6977246
--- /dev/null
+++ b/openssl-1.1.0h/ssl/build.info
@@ -0,0 +1,14 @@
+LIBS=../libssl
+SOURCE[../libssl]=\
+ pqueue.c \
+ statem/statem_srvr.c statem/statem_clnt.c s3_lib.c s3_enc.c record/rec_layer_s3.c \
+ statem/statem_lib.c s3_cbc.c s3_msg.c \
+ methods.c t1_lib.c t1_enc.c t1_ext.c \
+ d1_lib.c record/rec_layer_d1.c d1_msg.c \
+ statem/statem_dtls.c d1_srtp.c \
+ ssl_lib.c ssl_cert.c ssl_sess.c \
+ ssl_ciph.c ssl_stat.c ssl_rsa.c \
+ ssl_asn1.c ssl_txt.c ssl_init.c ssl_conf.c ssl_mcnf.c \
+ bio_ssl.c ssl_err.c t1_reneg.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
diff --git a/openssl-1.1.0h/ssl/d1_lib.c b/openssl-1.1.0h/ssl/d1_lib.c
new file mode 100644
index 0000000..55a81c3
--- /dev/null
+++ b/openssl-1.1.0h/ssl/d1_lib.c
@@ -0,0 +1,1087 @@
+/*
+ * Copyright 2005-2016 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
+ */
+
+#include <stdio.h>
+#define USE_SOCKETS
+#include <openssl/objects.h>
+#include <openssl/rand.h>
+#include "ssl_locl.h"
+
+#if defined(OPENSSL_SYS_VMS)
+# include <sys/timeb.h>
+#elif defined(OPENSSL_SYS_VXWORKS)
+# include <sys/times.h>
+#elif !defined(OPENSSL_SYS_WIN32)
+# include <sys/time.h>
+#endif
+
+static void get_current_time(struct timeval *t);
+static int dtls1_set_handshake_header(SSL *s, int type, unsigned long len);
+static int dtls1_handshake_write(SSL *s);
+static unsigned int dtls1_link_min_mtu(void);
+
+/* XDTLS: figure out the right values */
+static const unsigned int g_probable_mtu[] = { 1500, 512, 256 };
+
+const SSL3_ENC_METHOD DTLSv1_enc_data = {
+ tls1_enc,
+ tls1_mac,
+ tls1_setup_key_block,
+ tls1_generate_master_secret,
+ tls1_change_cipher_state,
+ tls1_final_finish_mac,
+ TLS1_FINISH_MAC_LENGTH,
+ TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
+ TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
+ tls1_alert_code,
+ tls1_export_keying_material,
+ SSL_ENC_FLAG_DTLS | SSL_ENC_FLAG_EXPLICIT_IV,
+ DTLS1_HM_HEADER_LENGTH,
+ dtls1_set_handshake_header,
+ dtls1_handshake_write
+};
+
+const SSL3_ENC_METHOD DTLSv1_2_enc_data = {
+ tls1_enc,
+ tls1_mac,
+ tls1_setup_key_block,
+ tls1_generate_master_secret,
+ tls1_change_cipher_state,
+ tls1_final_finish_mac,
+ TLS1_FINISH_MAC_LENGTH,
+ TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
+ TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
+ tls1_alert_code,
+ tls1_export_keying_material,
+ SSL_ENC_FLAG_DTLS | SSL_ENC_FLAG_EXPLICIT_IV | SSL_ENC_FLAG_SIGALGS
+ | SSL_ENC_FLAG_SHA256_PRF | SSL_ENC_FLAG_TLS1_2_CIPHERS,
+ DTLS1_HM_HEADER_LENGTH,
+ dtls1_set_handshake_header,
+ dtls1_handshake_write
+};
+
+long dtls1_default_timeout(void)
+{
+ /*
+ * 2 hours, the 24 hours mentioned in the DTLSv1 spec is way too long for
+ * http, the cache would over fill
+ */
+ return (60 * 60 * 2);
+}
+
+int dtls1_new(SSL *s)
+{
+ DTLS1_STATE *d1;
+
+ if (!DTLS_RECORD_LAYER_new(&s->rlayer)) {
+ return 0;
+ }
+
+ if (!ssl3_new(s))
+ return (0);
+ if ((d1 = OPENSSL_zalloc(sizeof(*d1))) == NULL) {
+ ssl3_free(s);
+ return (0);
+ }
+
+ d1->buffered_messages = pqueue_new();
+ d1->sent_messages = pqueue_new();
+
+ if (s->server) {
+ d1->cookie_len = sizeof(s->d1->cookie);
+ }
+
+ d1->link_mtu = 0;
+ d1->mtu = 0;
+
+ if (d1->buffered_messages == NULL || d1->sent_messages == NULL) {
+ pqueue_free(d1->buffered_messages);
+ pqueue_free(d1->sent_messages);
+ OPENSSL_free(d1);
+ ssl3_free(s);
+ return (0);
+ }
+
+ s->d1 = d1;
+ s->method->ssl_clear(s);
+ return (1);
+}
+
+static void dtls1_clear_queues(SSL *s)
+{
+ dtls1_clear_received_buffer(s);
+ dtls1_clear_sent_buffer(s);
+}
+
+void dtls1_clear_received_buffer(SSL *s)
+{
+ pitem *item = NULL;
+ hm_fragment *frag = NULL;
+
+ while ((item = pqueue_pop(s->d1->buffered_messages)) != NULL) {
+ frag = (hm_fragment *)item->data;
+ dtls1_hm_fragment_free(frag);
+ pitem_free(item);
+ }
+}
+
+void dtls1_clear_sent_buffer(SSL *s)
+{
+ pitem *item = NULL;
+ hm_fragment *frag = NULL;
+
+ while ((item = pqueue_pop(s->d1->sent_messages)) != NULL) {
+ frag = (hm_fragment *)item->data;
+ dtls1_hm_fragment_free(frag);
+ pitem_free(item);
+ }
+}
+
+
+void dtls1_free(SSL *s)
+{
+ DTLS_RECORD_LAYER_free(&s->rlayer);
+
+ ssl3_free(s);
+
+ dtls1_clear_queues(s);
+
+ pqueue_free(s->d1->buffered_messages);
+ pqueue_free(s->d1->sent_messages);
+
+ OPENSSL_free(s->d1);
+ s->d1 = NULL;
+}
+
+void dtls1_clear(SSL *s)
+{
+ pqueue *buffered_messages;
+ pqueue *sent_messages;
+ unsigned int mtu;
+ unsigned int link_mtu;
+
+ DTLS_RECORD_LAYER_clear(&s->rlayer);
+
+ if (s->d1) {
+ buffered_messages = s->d1->buffered_messages;
+ sent_messages = s->d1->sent_messages;
+ mtu = s->d1->mtu;
+ link_mtu = s->d1->link_mtu;
+
+ dtls1_clear_queues(s);
+
+ memset(s->d1, 0, sizeof(*s->d1));
+
+ if (s->server) {
+ s->d1->cookie_len = sizeof(s->d1->cookie);
+ }
+
+ if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU) {
+ s->d1->mtu = mtu;
+ s->d1->link_mtu = link_mtu;
+ }
+
+ s->d1->buffered_messages = buffered_messages;
+ s->d1->sent_messages = sent_messages;
+ }
+
+ ssl3_clear(s);
+
+ if (s->method->version == DTLS_ANY_VERSION)
+ s->version = DTLS_MAX_VERSION;
+#ifndef OPENSSL_NO_DTLS1_METHOD
+ else if (s->options & SSL_OP_CISCO_ANYCONNECT)
+ s->client_version = s->version = DTLS1_BAD_VER;
+#endif
+ else
+ s->version = s->method->version;
+}
+
+long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
+{
+ int ret = 0;
+
+ switch (cmd) {
+ case DTLS_CTRL_GET_TIMEOUT:
+ if (dtls1_get_timeout(s, (struct timeval *)parg) != NULL) {
+ ret = 1;
+ }
+ break;
+ case DTLS_CTRL_HANDLE_TIMEOUT:
+ ret = dtls1_handle_timeout(s);
+ break;
+ case DTLS_CTRL_SET_LINK_MTU:
+ if (larg < (long)dtls1_link_min_mtu())
+ return 0;
+ s->d1->link_mtu = larg;
+ return 1;
+ case DTLS_CTRL_GET_LINK_MIN_MTU:
+ return (long)dtls1_link_min_mtu();
+ case SSL_CTRL_SET_MTU:
+ /*
+ * We may not have a BIO set yet so can't call dtls1_min_mtu()
+ * We'll have to make do with dtls1_link_min_mtu() and max overhead
+ */
+ if (larg < (long)dtls1_link_min_mtu() - DTLS1_MAX_MTU_OVERHEAD)
+ return 0;
+ s->d1->mtu = larg;
+ return larg;
+ default:
+ ret = ssl3_ctrl(s, cmd, larg, parg);
+ break;
+ }
+ return (ret);
+}
+
+void dtls1_start_timer(SSL *s)
+{
+#ifndef OPENSSL_NO_SCTP
+ /* Disable timer for SCTP */
+ if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
+ memset(&s->d1->next_timeout, 0, sizeof(s->d1->next_timeout));
+ return;
+ }
+#endif
+
+ /* If timer is not set, initialize duration with 1 second */
+ if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
+ s->d1->timeout_duration = 1;
+ }
+
+ /* Set timeout to current time */
+ get_current_time(&(s->d1->next_timeout));
+
+ /* Add duration to current time */
+ s->d1->next_timeout.tv_sec += s->d1->timeout_duration;
+ BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
+ &(s->d1->next_timeout));
+}
+
+struct timeval *dtls1_get_timeout(SSL *s, struct timeval *timeleft)
+{
+ struct timeval timenow;
+
+ /* If no timeout is set, just return NULL */
+ if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
+ return NULL;
+ }
+
+ /* Get current time */
+ get_current_time(&timenow);
+
+ /* If timer already expired, set remaining time to 0 */
+ if (s->d1->next_timeout.tv_sec < timenow.tv_sec ||
+ (s->d1->next_timeout.tv_sec == timenow.tv_sec &&
+ s->d1->next_timeout.tv_usec <= timenow.tv_usec)) {
+ memset(timeleft, 0, sizeof(*timeleft));
+ return timeleft;
+ }
+
+ /* Calculate time left until timer expires */
+ memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval));
+ timeleft->tv_sec -= timenow.tv_sec;
+ timeleft->tv_usec -= timenow.tv_usec;
+ if (timeleft->tv_usec < 0) {
+ timeleft->tv_sec--;
+ timeleft->tv_usec += 1000000;
+ }
+
+ /*
+ * If remaining time is less than 15 ms, set it to 0 to prevent issues
+ * because of small divergences with socket timeouts.
+ */
+ if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000) {
+ memset(timeleft, 0, sizeof(*timeleft));
+ }
+
+ return timeleft;
+}
+
+int dtls1_is_timer_expired(SSL *s)
+{
+ struct timeval timeleft;
+
+ /* Get time left until timeout, return false if no timer running */
+ if (dtls1_get_timeout(s, &timeleft) == NULL) {
+ return 0;
+ }
+
+ /* Return false if timer is not expired yet */
+ if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0) {
+ return 0;
+ }
+
+ /* Timer expired, so return true */
+ return 1;
+}
+
+void dtls1_double_timeout(SSL *s)
+{
+ s->d1->timeout_duration *= 2;
+ if (s->d1->timeout_duration > 60)
+ s->d1->timeout_duration = 60;
+ dtls1_start_timer(s);
+}
+
+void dtls1_stop_timer(SSL *s)
+{
+ /* Reset everything */
+ memset(&s->d1->timeout, 0, sizeof(s->d1->timeout));
+ memset(&s->d1->next_timeout, 0, sizeof(s->d1->next_timeout));
+ s->d1->timeout_duration = 1;
+ BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
+ &(s->d1->next_timeout));
+ /* Clear retransmission buffer */
+ dtls1_clear_sent_buffer(s);
+}
+
+int dtls1_check_timeout_num(SSL *s)
+{
+ unsigned int mtu;
+
+ s->d1->timeout.num_alerts++;
+
+ /* Reduce MTU after 2 unsuccessful retransmissions */
+ if (s->d1->timeout.num_alerts > 2
+ && !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
+ mtu =
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL);
+ if (mtu < s->d1->mtu)
+ s->d1->mtu = mtu;
+ }
+
+ if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) {
+ /* fail the connection, enough alerts have been sent */
+ SSLerr(SSL_F_DTLS1_CHECK_TIMEOUT_NUM, SSL_R_READ_TIMEOUT_EXPIRED);
+ return -1;
+ }
+
+ return 0;
+}
+
+int dtls1_handle_timeout(SSL *s)
+{
+ /* if no timer is expired, don't do anything */
+ if (!dtls1_is_timer_expired(s)) {
+ return 0;
+ }
+
+ dtls1_double_timeout(s);
+
+ if (dtls1_check_timeout_num(s) < 0)
+ return -1;
+
+ s->d1->timeout.read_timeouts++;
+ if (s->d1->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) {
+ s->d1->timeout.read_timeouts = 1;
+ }
+#ifndef OPENSSL_NO_HEARTBEATS
+ if (s->tlsext_hb_pending) {
+ s->tlsext_hb_pending = 0;
+ return dtls1_heartbeat(s);
+ }
+#endif
+
+ dtls1_start_timer(s);
+ return dtls1_retransmit_buffered_messages(s);
+}
+
+static void get_current_time(struct timeval *t)
+{
+#if defined(_WIN32)
+ SYSTEMTIME st;
+ union {
+ unsigned __int64 ul;
+ FILETIME ft;
+ } now;
+
+ GetSystemTime(&st);
+ SystemTimeToFileTime(&st, &now.ft);
+ /* re-bias to 1/1/1970 */
+# ifdef __MINGW32__
+ now.ul -= 116444736000000000ULL;
+# else
+ /* *INDENT-OFF* */
+ now.ul -= 116444736000000000UI64;
+ /* *INDENT-ON* */
+# endif
+ t->tv_sec = (long)(now.ul / 10000000);
+ t->tv_usec = ((int)(now.ul % 10000000)) / 10;
+#elif defined(OPENSSL_SYS_VMS)
+ struct timeb tb;
+ ftime(&tb);
+ t->tv_sec = (long)tb.time;
+ t->tv_usec = (long)tb.millitm * 1000;
+#else
+ gettimeofday(t, NULL);
+#endif
+}
+
+#define LISTEN_SUCCESS 2
+#define LISTEN_SEND_VERIFY_REQUEST 1
+
+#ifndef OPENSSL_NO_SOCK
+int DTLSv1_listen(SSL *s, BIO_ADDR *client)
+{
+ int next, n, ret = 0, clearpkt = 0;
+ unsigned char cookie[DTLS1_COOKIE_LENGTH];
+ unsigned char seq[SEQ_NUM_SIZE];
+ const unsigned char *data;
+ unsigned char *p, *buf;
+ unsigned long reclen, fragoff, fraglen, msglen;
+ unsigned int rectype, versmajor, msgseq, msgtype, clientvers, cookielen;
+ BIO *rbio, *wbio;
+ BUF_MEM *bufm;
+ BIO_ADDR *tmpclient = NULL;
+ PACKET pkt, msgpkt, msgpayload, session, cookiepkt;
+
+ if (s->handshake_func == NULL) {
+ /* Not properly initialized yet */
+ SSL_set_accept_state(s);
+ }
+
+ /* Ensure there is no state left over from a previous invocation */
+ if (!SSL_clear(s))
+ return -1;
+
+ ERR_clear_error();
+
+ rbio = SSL_get_rbio(s);
+ wbio = SSL_get_wbio(s);
+
+ if (!rbio || !wbio) {
+ SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_BIO_NOT_SET);
+ return -1;
+ }
+
+ /*
+ * We only peek at incoming ClientHello's until we're sure we are going to
+ * to respond with a HelloVerifyRequest. If its a ClientHello with a valid
+ * cookie then we leave it in the BIO for accept to handle.
+ */
+ BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 1, NULL);
+
+ /*
+ * Note: This check deliberately excludes DTLS1_BAD_VER because that version
+ * requires the MAC to be calculated *including* the first ClientHello
+ * (without the cookie). Since DTLSv1_listen is stateless that cannot be
+ * supported. DTLS1_BAD_VER must use cookies in a stateful manner (e.g. via
+ * SSL_accept)
+ */
+ if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) {
+ SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNSUPPORTED_SSL_VERSION);
+ return -1;
+ }
+
+ if (s->init_buf == NULL) {
+ if ((bufm = BUF_MEM_new()) == NULL) {
+ SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+
+ if (!BUF_MEM_grow(bufm, SSL3_RT_MAX_PLAIN_LENGTH)) {
+ BUF_MEM_free(bufm);
+ SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ s->init_buf = bufm;
+ }
+ buf = (unsigned char *)s->init_buf->data;
+
+ do {
+ /* Get a packet */
+
+ clear_sys_error();
+ /*
+ * Technically a ClientHello could be SSL3_RT_MAX_PLAIN_LENGTH
+ * + DTLS1_RT_HEADER_LENGTH bytes long. Normally init_buf does not store
+ * the record header as well, but we do here. We've set up init_buf to
+ * be the standard size for simplicity. In practice we shouldn't ever
+ * receive a ClientHello as long as this. If we do it will get dropped
+ * in the record length check below.
+ */
+ n = BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH);
+
+ if (n <= 0) {
+ if (BIO_should_retry(rbio)) {
+ /* Non-blocking IO */
+ goto end;
+ }
+ return -1;
+ }
+
+ /* If we hit any problems we need to clear this packet from the BIO */
+ clearpkt = 1;
+
+ if (!PACKET_buf_init(&pkt, buf, n)) {
+ SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ /*
+ * Parse the received record. If there are any problems with it we just
+ * dump it - with no alert. RFC6347 says this "Unlike TLS, DTLS is
+ * resilient in the face of invalid records (e.g., invalid formatting,
+ * length, MAC, etc.). In general, invalid records SHOULD be silently
+ * discarded, thus preserving the association; however, an error MAY be
+ * logged for diagnostic purposes."
+ */
+
+ /* this packet contained a partial record, dump it */
+ if (n < DTLS1_RT_HEADER_LENGTH) {
+ SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_RECORD_TOO_SMALL);
+ goto end;
+ }
+
+ if (s->msg_callback)
+ s->msg_callback(0, 0, SSL3_RT_HEADER, buf,
+ DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg);
+
+ /* Get the record header */
+ if (!PACKET_get_1(&pkt, &rectype)
+ || !PACKET_get_1(&pkt, &versmajor)) {
+ SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
+ goto end;
+ }
+
+ if (rectype != SSL3_RT_HANDSHAKE) {
+ SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
+ goto end;
+ }
+
+ /*
+ * Check record version number. We only check that the major version is
+ * the same.
+ */
+ if (versmajor != DTLS1_VERSION_MAJOR) {
+ SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_BAD_PROTOCOL_VERSION_NUMBER);
+ goto end;
+ }
+
+ if (!PACKET_forward(&pkt, 1)
+ /* Save the sequence number: 64 bits, with top 2 bytes = epoch */
+ || !PACKET_copy_bytes(&pkt, seq, SEQ_NUM_SIZE)
+ || !PACKET_get_length_prefixed_2(&pkt, &msgpkt)) {
+ SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
+ goto end;
+ }
+ /*
+ * We allow data remaining at the end of the packet because there could
+ * be a second record (but we ignore it)
+ */
+
+ /* This is an initial ClientHello so the epoch has to be 0 */
+ if (seq[0] != 0 || seq[1] != 0) {
+ SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
+ goto end;
+ }
+
+ /* Get a pointer to the raw message for the later callback */
+ data = PACKET_data(&msgpkt);
+
+ /* Finished processing the record header, now process the message */
+ if (!PACKET_get_1(&msgpkt, &msgtype)
+ || !PACKET_get_net_3(&msgpkt, &msglen)
+ || !PACKET_get_net_2(&msgpkt, &msgseq)
+ || !PACKET_get_net_3(&msgpkt, &fragoff)
+ || !PACKET_get_net_3(&msgpkt, &fraglen)
+ || !PACKET_get_sub_packet(&msgpkt, &msgpayload, fraglen)
+ || PACKET_remaining(&msgpkt) != 0) {
+ SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
+ goto end;
+ }
+
+ if (msgtype != SSL3_MT_CLIENT_HELLO) {
+ SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
+ goto end;
+ }
+
+ /* Message sequence number can only be 0 or 1 */
+ if (msgseq > 2) {
+ SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_INVALID_SEQUENCE_NUMBER);
+ goto end;
+ }
+
+ /*
+ * We don't support fragment reassembly for ClientHellos whilst
+ * listening because that would require server side state (which is
+ * against the whole point of the ClientHello/HelloVerifyRequest
+ * mechanism). Instead we only look at the first ClientHello fragment
+ * and require that the cookie must be contained within it.
+ */
+ if (fragoff != 0 || fraglen > msglen) {
+ /* Non initial ClientHello fragment (or bad fragment) */
+ SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_FRAGMENTED_CLIENT_HELLO);
+ goto end;
+ }
+
+ if (s->msg_callback)
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, data,
+ fraglen + DTLS1_HM_HEADER_LENGTH, s,
+ s->msg_callback_arg);
+
+ if (!PACKET_get_net_2(&msgpayload, &clientvers)) {
+ SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
+ goto end;
+ }
+
+ /*
+ * Verify client version is supported
+ */
+ if (DTLS_VERSION_LT(clientvers, (unsigned int)s->method->version) &&
+ s->method->version != DTLS_ANY_VERSION) {
+ SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_WRONG_VERSION_NUMBER);
+ goto end;
+ }
+
+ if (!PACKET_forward(&msgpayload, SSL3_RANDOM_SIZE)
+ || !PACKET_get_length_prefixed_1(&msgpayload, &session)
+ || !PACKET_get_length_prefixed_1(&msgpayload, &cookiepkt)) {
+ /*
+ * Could be malformed or the cookie does not fit within the initial
+ * ClientHello fragment. Either way we can't handle it.
+ */
+ SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
+ goto end;
+ }
+
+ /*
+ * Check if we have a cookie or not. If not we need to send a
+ * HelloVerifyRequest.
+ */
+ if (PACKET_remaining(&cookiepkt) == 0) {
+ next = LISTEN_SEND_VERIFY_REQUEST;
+ } else {
+ /*
+ * We have a cookie, so lets check it.
+ */
+ if (s->ctx->app_verify_cookie_cb == NULL) {
+ SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_NO_VERIFY_COOKIE_CALLBACK);
+ /* This is fatal */
+ return -1;
+ }
+ if (s->ctx->app_verify_cookie_cb(s, PACKET_data(&cookiepkt),
+ PACKET_remaining(&cookiepkt)) ==
+ 0) {
+ /*
+ * We treat invalid cookies in the same was as no cookie as
+ * per RFC6347
+ */
+ next = LISTEN_SEND_VERIFY_REQUEST;
+ } else {
+ /* Cookie verification succeeded */
+ next = LISTEN_SUCCESS;
+ }
+ }
+
+ if (next == LISTEN_SEND_VERIFY_REQUEST) {
+ /*
+ * There was no cookie in the ClientHello so we need to send a
+ * HelloVerifyRequest. If this fails we do not worry about trying
+ * to resend, we just drop it.
+ */
+
+ /*
+ * Dump the read packet, we don't need it any more. Ignore return
+ * value
+ */
+ BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 0, NULL);
+ BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH);
+ BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 1, NULL);
+
+ /* Generate the cookie */
+ if (s->ctx->app_gen_cookie_cb == NULL ||
+ s->ctx->app_gen_cookie_cb(s, cookie, &cookielen) == 0 ||
+ cookielen > 255) {
+ SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
+ /* This is fatal */
+ return -1;
+ }
+
+ p = &buf[DTLS1_RT_HEADER_LENGTH];
+ msglen = dtls_raw_hello_verify_request(p + DTLS1_HM_HEADER_LENGTH,
+ cookie, cookielen);
+
+ *p++ = DTLS1_MT_HELLO_VERIFY_REQUEST;
+
+ /* Message length */
+ l2n3(msglen, p);
+
+ /* Message sequence number is always 0 for a HelloVerifyRequest */
+ s2n(0, p);
+
+ /*
+ * We never fragment a HelloVerifyRequest, so fragment offset is 0
+ * and fragment length is message length
+ */
+ l2n3(0, p);
+ l2n3(msglen, p);
+
+ /* Set reclen equal to length of whole handshake message */
+ reclen = msglen + DTLS1_HM_HEADER_LENGTH;
+
+ /* Add the record header */
+ p = buf;
+
+ *(p++) = SSL3_RT_HANDSHAKE;
+ /*
+ * Special case: for hello verify request, client version 1.0 and we
+ * haven't decided which version to use yet send back using version
+ * 1.0 header: otherwise some clients will ignore it.
+ */
+ if (s->method->version == DTLS_ANY_VERSION) {
+ *(p++) = DTLS1_VERSION >> 8;
+ *(p++) = DTLS1_VERSION & 0xff;
+ } else {
+ *(p++) = s->version >> 8;
+ *(p++) = s->version & 0xff;
+ }
+
+ /*
+ * Record sequence number is always the same as in the received
+ * ClientHello
+ */
+ memcpy(p, seq, SEQ_NUM_SIZE);
+ p += SEQ_NUM_SIZE;
+
+ /* Length */
+ s2n(reclen, p);
+
+ /*
+ * Set reclen equal to length of whole record including record
+ * header
+ */
+ reclen += DTLS1_RT_HEADER_LENGTH;
+
+ if (s->msg_callback)
+ s->msg_callback(1, 0, SSL3_RT_HEADER, buf,
+ DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg);
+
+ if ((tmpclient = BIO_ADDR_new()) == NULL) {
+ SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+
+ /*
+ * This is unnecessary if rbio and wbio are one and the same - but
+ * maybe they're not. We ignore errors here - some BIOs do not
+ * support this.
+ */
+ if (BIO_dgram_get_peer(rbio, tmpclient) > 0) {
+ (void)BIO_dgram_set_peer(wbio, tmpclient);
+ }
+ BIO_ADDR_free(tmpclient);
+ tmpclient = NULL;
+
+ if (BIO_write(wbio, buf, reclen) < (int)reclen) {
+ if (BIO_should_retry(wbio)) {
+ /*
+ * Non-blocking IO...but we're stateless, so we're just
+ * going to drop this packet.
+ */
+ goto end;
+ }
+ return -1;
+ }
+
+ if (BIO_flush(wbio) <= 0) {
+ if (BIO_should_retry(wbio)) {
+ /*
+ * Non-blocking IO...but we're stateless, so we're just
+ * going to drop this packet.
+ */
+ goto end;
+ }
+ return -1;
+ }
+ }
+ } while (next != LISTEN_SUCCESS);
+
+ /*
+ * Set expected sequence numbers to continue the handshake.
+ */
+ s->d1->handshake_read_seq = 1;
+ s->d1->handshake_write_seq = 1;
+ s->d1->next_handshake_write_seq = 1;
+ DTLS_RECORD_LAYER_set_write_sequence(&s->rlayer, seq);
+
+ /*
+ * We are doing cookie exchange, so make sure we set that option in the
+ * SSL object
+ */
+ SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);
+
+ /*
+ * Tell the state machine that we've done the initial hello verify
+ * exchange
+ */
+ ossl_statem_set_hello_verify_done(s);
+
+ /*
+ * Some BIOs may not support this. If we fail we clear the client address
+ */
+ if (BIO_dgram_get_peer(rbio, client) <= 0)
+ BIO_ADDR_clear(client);
+
+ ret = 1;
+ clearpkt = 0;
+ end:
+ BIO_ADDR_free(tmpclient);
+ BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 0, NULL);
+ if (clearpkt) {
+ /* Dump this packet. Ignore return value */
+ BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH);
+ }
+ return ret;
+}
+#endif
+
+static int dtls1_set_handshake_header(SSL *s, int htype, unsigned long len)
+{
+ dtls1_set_message_header(s, htype, len, 0, len);
+ s->init_num = (int)len + DTLS1_HM_HEADER_LENGTH;
+ s->init_off = 0;
+ /* Buffer the message to handle re-xmits */
+
+ if (!dtls1_buffer_message(s, 0))
+ return 0;
+
+ return 1;
+}
+
+static int dtls1_handshake_write(SSL *s)
+{
+ return dtls1_do_write(s, SSL3_RT_HANDSHAKE);
+}
+
+#ifndef OPENSSL_NO_HEARTBEATS
+
+# define HEARTBEAT_SIZE(payload, padding) ( \
+ 1 /* heartbeat type */ + \
+ 2 /* heartbeat length */ + \
+ (payload) + (padding))
+
+# define HEARTBEAT_SIZE_STD(payload) HEARTBEAT_SIZE(payload, 16)
+
+int dtls1_process_heartbeat(SSL *s, unsigned char *p, unsigned int length)
+{
+ unsigned char *pl;
+ unsigned short hbtype;
+ unsigned int payload;
+ unsigned int padding = 16; /* Use minimum padding */
+
+ if (s->msg_callback)
+ s->msg_callback(0, s->version, DTLS1_RT_HEARTBEAT,
+ p, length, s, s->msg_callback_arg);
+
+ /* Read type and payload length */
+ if (HEARTBEAT_SIZE_STD(0) > length)
+ return 0; /* silently discard */
+ if (length > SSL3_RT_MAX_PLAIN_LENGTH)
+ return 0; /* silently discard per RFC 6520 sec. 4 */
+
+ hbtype = *p++;
+ n2s(p, payload);
+ if (HEARTBEAT_SIZE_STD(payload) > length)
+ return 0; /* silently discard per RFC 6520 sec. 4 */
+ pl = p;
+
+ if (hbtype == TLS1_HB_REQUEST) {
+ unsigned char *buffer, *bp;
+ unsigned int write_length = HEARTBEAT_SIZE(payload, padding);
+ int r;
+
+ if (write_length > SSL3_RT_MAX_PLAIN_LENGTH)
+ return 0;
+
+ /* Allocate memory for the response. */
+ buffer = OPENSSL_malloc(write_length);
+ if (buffer == NULL)
+ return -1;
+ bp = buffer;
+
+ /* Enter response type, length and copy payload */
+ *bp++ = TLS1_HB_RESPONSE;
+ s2n(payload, bp);
+ memcpy(bp, pl, payload);
+ bp += payload;
+ /* Random padding */
+ if (RAND_bytes(bp, padding) <= 0) {
+ OPENSSL_free(buffer);
+ return -1;
+ }
+
+ r = dtls1_write_bytes(s, DTLS1_RT_HEARTBEAT, buffer, write_length);
+
+ if (r >= 0 && s->msg_callback)
+ s->msg_callback(1, s->version, DTLS1_RT_HEARTBEAT,
+ buffer, write_length, s, s->msg_callback_arg);
+
+ OPENSSL_free(buffer);
+
+ if (r < 0)
+ return r;
+ } else if (hbtype == TLS1_HB_RESPONSE) {
+ unsigned int seq;
+
+ /*
+ * We only send sequence numbers (2 bytes unsigned int), and 16
+ * random bytes, so we just try to read the sequence number
+ */
+ n2s(pl, seq);
+
+ if (payload == 18 && seq == s->tlsext_hb_seq) {
+ dtls1_stop_timer(s);
+ s->tlsext_hb_seq++;
+ s->tlsext_hb_pending = 0;
+ }
+ }
+
+ return 0;
+}
+
+int dtls1_heartbeat(SSL *s)
+{
+ unsigned char *buf, *p;
+ int ret = -1;
+ unsigned int payload = 18; /* Sequence number + random bytes */
+ unsigned int padding = 16; /* Use minimum padding */
+ unsigned int size;
+
+ /* Only send if peer supports and accepts HB requests... */
+ if (!(s->tlsext_heartbeat & SSL_DTLSEXT_HB_ENABLED) ||
+ s->tlsext_heartbeat & SSL_DTLSEXT_HB_DONT_SEND_REQUESTS) {
+ SSLerr(SSL_F_DTLS1_HEARTBEAT, SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT);
+ return -1;
+ }
+
+ /* ...and there is none in flight yet... */
+ if (s->tlsext_hb_pending) {
+ SSLerr(SSL_F_DTLS1_HEARTBEAT, SSL_R_TLS_HEARTBEAT_PENDING);
+ return -1;
+ }
+
+ /* ...and no handshake in progress. */
+ if (SSL_in_init(s) || ossl_statem_get_in_handshake(s)) {
+ SSLerr(SSL_F_DTLS1_HEARTBEAT, SSL_R_UNEXPECTED_MESSAGE);
+ return -1;
+ }
+
+ /*-
+ * Create HeartBeat message, we just use a sequence number
+ * as payload to distinguish different messages and add
+ * some random stuff.
+ */
+ size = HEARTBEAT_SIZE(payload, padding);
+ buf = OPENSSL_malloc(size);
+ if (buf == NULL) {
+ SSLerr(SSL_F_DTLS1_HEARTBEAT, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ p = buf;
+ /* Message Type */
+ *p++ = TLS1_HB_REQUEST;
+ /* Payload length (18 bytes here) */
+ s2n(payload, p);
+ /* Sequence number */
+ s2n(s->tlsext_hb_seq, p);
+ /* 16 random bytes */
+ if (RAND_bytes(p, 16) <= 0) {
+ SSLerr(SSL_F_DTLS1_HEARTBEAT, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ p += 16;
+ /* Random padding */
+ if (RAND_bytes(p, padding) <= 0) {
+ SSLerr(SSL_F_DTLS1_HEARTBEAT, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ ret = dtls1_write_bytes(s, DTLS1_RT_HEARTBEAT, buf, size);
+ if (ret >= 0) {
+ if (s->msg_callback)
+ s->msg_callback(1, s->version, DTLS1_RT_HEARTBEAT,
+ buf, size, s, s->msg_callback_arg);
+
+ dtls1_start_timer(s);
+ s->tlsext_hb_pending = 1;
+ }
+
+ err:
+ OPENSSL_free(buf);
+
+ return ret;
+}
+#endif
+
+int dtls1_shutdown(SSL *s)
+{
+ int ret;
+#ifndef OPENSSL_NO_SCTP
+ BIO *wbio;
+
+ wbio = SSL_get_wbio(s);
+ if (wbio != NULL && BIO_dgram_is_sctp(wbio) &&
+ !(s->shutdown & SSL_SENT_SHUTDOWN)) {
+ ret = BIO_dgram_sctp_wait_for_dry(wbio);
+ if (ret < 0)
+ return -1;
+
+ if (ret == 0)
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 1,
+ NULL);
+ }
+#endif
+ ret = ssl3_shutdown(s);
+#ifndef OPENSSL_NO_SCTP
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 0, NULL);
+#endif
+ return ret;
+}
+
+int dtls1_query_mtu(SSL *s)
+{
+ if (s->d1->link_mtu) {
+ s->d1->mtu =
+ s->d1->link_mtu - BIO_dgram_get_mtu_overhead(SSL_get_wbio(s));
+ s->d1->link_mtu = 0;
+ }
+
+ /* AHA! Figure out the MTU, and stick to the right size */
+ if (s->d1->mtu < dtls1_min_mtu(s)) {
+ if (!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
+ s->d1->mtu =
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
+
+ /*
+ * I've seen the kernel return bogus numbers when it doesn't know
+ * (initial write), so just make sure we have a reasonable number
+ */
+ if (s->d1->mtu < dtls1_min_mtu(s)) {
+ /* Set to min mtu */
+ s->d1->mtu = dtls1_min_mtu(s);
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU,
+ s->d1->mtu, NULL);
+ }
+ } else
+ return 0;
+ }
+ return 1;
+}
+
+static unsigned int dtls1_link_min_mtu(void)
+{
+ return (g_probable_mtu[(sizeof(g_probable_mtu) /
+ sizeof(g_probable_mtu[0])) - 1]);
+}
+
+unsigned int dtls1_min_mtu(SSL *s)
+{
+ return dtls1_link_min_mtu() - BIO_dgram_get_mtu_overhead(SSL_get_wbio(s));
+}
diff --git a/openssl-1.1.0h/ssl/d1_msg.c b/openssl-1.1.0h/ssl/d1_msg.c
new file mode 100644
index 0000000..7471fd3
--- /dev/null
+++ b/openssl-1.1.0h/ssl/d1_msg.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2005-2016 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
+ */
+
+#define USE_SOCKETS
+#include "ssl_locl.h"
+
+int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf_, int len)
+{
+ int i;
+
+ if (SSL_in_init(s) && !ossl_statem_get_in_handshake(s)) {
+ i = s->handshake_func(s);
+ if (i < 0)
+ return (i);
+ if (i == 0) {
+ SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES,
+ SSL_R_SSL_HANDSHAKE_FAILURE);
+ return -1;
+ }
+ }
+
+ if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
+ SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES, SSL_R_DTLS_MESSAGE_TOO_BIG);
+ return -1;
+ }
+
+ i = dtls1_write_bytes(s, type, buf_, len);
+ return i;
+}
+
+int dtls1_dispatch_alert(SSL *s)
+{
+ int i, j;
+ void (*cb) (const SSL *ssl, int type, int val) = NULL;
+ unsigned char buf[DTLS1_AL_HEADER_LENGTH];
+ unsigned char *ptr = &buf[0];
+
+ s->s3->alert_dispatch = 0;
+
+ memset(buf, 0, sizeof(buf));
+ *ptr++ = s->s3->send_alert[0];
+ *ptr++ = s->s3->send_alert[1];
+
+#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
+ if (s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE) {
+ s2n(s->d1->handshake_read_seq, ptr);
+ l2n3(s->d1->r_msg_hdr.frag_off, ptr);
+ }
+#endif
+
+ i = do_dtls1_write(s, SSL3_RT_ALERT, &buf[0], sizeof(buf), 0);
+ if (i <= 0) {
+ s->s3->alert_dispatch = 1;
+ /* fprintf( stderr, "not done with alert\n" ); */
+ } else {
+ if (s->s3->send_alert[0] == SSL3_AL_FATAL
+#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
+ || s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
+#endif
+ )
+ (void)BIO_flush(s->wbio);
+
+ if (s->msg_callback)
+ s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert,
+ 2, s, s->msg_callback_arg);
+
+ if (s->info_callback != NULL)
+ cb = s->info_callback;
+ else if (s->ctx->info_callback != NULL)
+ cb = s->ctx->info_callback;
+
+ if (cb != NULL) {
+ j = (s->s3->send_alert[0] << 8) | s->s3->send_alert[1];
+ cb(s, SSL_CB_WRITE_ALERT, j);
+ }
+ }
+ return (i);
+}
diff --git a/openssl-1.1.0h/ssl/d1_srtp.c b/openssl-1.1.0h/ssl/d1_srtp.c
new file mode 100644
index 0000000..7e88f17
--- /dev/null
+++ b/openssl-1.1.0h/ssl/d1_srtp.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright 2011-2016 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
+ */
+
+/*
+ * DTLS code by Eric Rescorla <ekr@rtfm.com>
+ *
+ * Copyright (C) 2006, Network Resonance, Inc. Copyright (C) 2011, RTFM, Inc.
+ */
+
+#include <stdio.h>
+#include <openssl/objects.h>
+#include "ssl_locl.h"
+
+#ifndef OPENSSL_NO_SRTP
+
+static SRTP_PROTECTION_PROFILE srtp_known_profiles[] = {
+ {
+ "SRTP_AES128_CM_SHA1_80",
+ SRTP_AES128_CM_SHA1_80,
+ },
+ {
+ "SRTP_AES128_CM_SHA1_32",
+ SRTP_AES128_CM_SHA1_32,
+ },
+ {
+ "SRTP_AEAD_AES_128_GCM",
+ SRTP_AEAD_AES_128_GCM,
+ },
+ {
+ "SRTP_AEAD_AES_256_GCM",
+ SRTP_AEAD_AES_256_GCM,
+ },
+ {0}
+};
+
+static int find_profile_by_name(char *profile_name,
+ SRTP_PROTECTION_PROFILE **pptr, unsigned len)
+{
+ SRTP_PROTECTION_PROFILE *p;
+
+ p = srtp_known_profiles;
+ while (p->name) {
+ if ((len == strlen(p->name))
+ && strncmp(p->name, profile_name, len) == 0) {
+ *pptr = p;
+ return 0;
+ }
+
+ p++;
+ }
+
+ return 1;
+}
+
+static int ssl_ctx_make_profiles(const char *profiles_string,
+ STACK_OF(SRTP_PROTECTION_PROFILE) **out)
+{
+ STACK_OF(SRTP_PROTECTION_PROFILE) *profiles;
+
+ char *col;
+ char *ptr = (char *)profiles_string;
+ SRTP_PROTECTION_PROFILE *p;
+
+ if ((profiles = sk_SRTP_PROTECTION_PROFILE_new_null()) == NULL) {
+ SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES,
+ SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES);
+ return 1;
+ }
+
+ do {
+ col = strchr(ptr, ':');
+
+ if (!find_profile_by_name(ptr, &p, col ? col - ptr : (int)strlen(ptr))) {
+ if (sk_SRTP_PROTECTION_PROFILE_find(profiles, p) >= 0) {
+ SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ goto err;
+ }
+
+ if (!sk_SRTP_PROTECTION_PROFILE_push(profiles, p)) {
+ SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES,
+ SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES);
+ goto err;
+ }
+ } else {
+ SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES,
+ SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE);
+ goto err;
+ }
+
+ if (col)
+ ptr = col + 1;
+ } while (col);
+
+ sk_SRTP_PROTECTION_PROFILE_free(*out);
+
+ *out = profiles;
+
+ return 0;
+ err:
+ sk_SRTP_PROTECTION_PROFILE_free(profiles);
+ return 1;
+}
+
+int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, const char *profiles)
+{
+ return ssl_ctx_make_profiles(profiles, &ctx->srtp_profiles);
+}
+
+int SSL_set_tlsext_use_srtp(SSL *s, const char *profiles)
+{
+ return ssl_ctx_make_profiles(profiles, &s->srtp_profiles);
+}
+
+STACK_OF(SRTP_PROTECTION_PROFILE) *SSL_get_srtp_profiles(SSL *s)
+{
+ if (s != NULL) {
+ if (s->srtp_profiles != NULL) {
+ return s->srtp_profiles;
+ } else if ((s->ctx != NULL) && (s->ctx->srtp_profiles != NULL)) {
+ return s->ctx->srtp_profiles;
+ }
+ }
+
+ return NULL;
+}
+
+SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s)
+{
+ return s->srtp_profile;
+}
+
+/*
+ * Note: this function returns 0 length if there are no profiles specified
+ */
+int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len,
+ int maxlen)
+{
+ int ct = 0;
+ int i;
+ STACK_OF(SRTP_PROTECTION_PROFILE) *clnt = 0;
+ SRTP_PROTECTION_PROFILE *prof;
+
+ clnt = SSL_get_srtp_profiles(s);
+ ct = sk_SRTP_PROTECTION_PROFILE_num(clnt); /* -1 if clnt == 0 */
+
+ if (p) {
+ if (ct == 0) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT,
+ SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST);
+ return 1;
+ }
+
+ if ((2 + ct * 2 + 1) > maxlen) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT,
+ SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG);
+ return 1;
+ }
+
+ /* Add the length */
+ s2n(ct * 2, p);
+ for (i = 0; i < ct; i++) {
+ prof = sk_SRTP_PROTECTION_PROFILE_value(clnt, i);
+ s2n(prof->id, p);
+ }
+
+ /* Add an empty use_mki value */
+ *p++ = 0;
+ }
+
+ *len = 2 + ct * 2 + 1;
+
+ return 0;
+}
+
+int ssl_parse_clienthello_use_srtp_ext(SSL *s, PACKET *pkt, int *al)
+{
+ SRTP_PROTECTION_PROFILE *sprof;
+ STACK_OF(SRTP_PROTECTION_PROFILE) *srvr;
+ unsigned int ct, mki_len, id;
+ int i, srtp_pref;
+ PACKET subpkt;
+
+ /* 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)) {
+ SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ *al = SSL_AD_DECODE_ERROR;
+ return 1;
+ }
+
+ 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)) {
+ SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ *al = SSL_AD_DECODE_ERROR;
+ return 1;
+ }
+
+ /*
+ * 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++) {
+ 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)) {
+ SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ *al = SSL_AD_DECODE_ERROR;
+ return 1;
+ }
+
+ if (!PACKET_forward(pkt, mki_len)
+ || PACKET_remaining(pkt)) {
+ SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
+ SSL_R_BAD_SRTP_MKI_VALUE);
+ *al = SSL_AD_DECODE_ERROR;
+ return 1;
+ }
+
+ return 0;
+}
+
+int ssl_add_serverhello_use_srtp_ext(SSL *s, unsigned char *p, int *len,
+ int maxlen)
+{
+ if (p) {
+ if (maxlen < 5) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT,
+ SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG);
+ return 1;
+ }
+
+ if (s->srtp_profile == 0) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT,
+ SSL_R_USE_SRTP_NOT_NEGOTIATED);
+ return 1;
+ }
+ s2n(2, p);
+ s2n(s->srtp_profile->id, p);
+ *p++ = 0;
+ }
+ *len = 5;
+
+ return 0;
+}
+
+int ssl_parse_serverhello_use_srtp_ext(SSL *s, PACKET *pkt, int *al)
+{
+ 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) {
+ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ *al = SSL_AD_DECODE_ERROR;
+ return 1;
+ }
+
+ if (mki != 0) {
+ /* Must be no MKI, since we never offer one */
+ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT,
+ SSL_R_BAD_SRTP_MKI_VALUE);
+ *al = SSL_AD_ILLEGAL_PARAMETER;
+ return 1;
+ }
+
+ clnt = SSL_get_srtp_profiles(s);
+
+ /* Throw an error if the server gave us an unsolicited extension */
+ if (clnt == NULL) {
+ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT,
+ SSL_R_NO_SRTP_PROFILES);
+ *al = SSL_AD_DECODE_ERROR;
+ return 1;
+ }
+
+ /*
+ * 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;
+ *al = 0;
+ return 0;
+ }
+ }
+
+ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ *al = SSL_AD_DECODE_ERROR;
+ return 1;
+}
+
+#endif
diff --git a/openssl-1.1.0h/ssl/methods.c b/openssl-1.1.0h/ssl/methods.c
new file mode 100644
index 0000000..c846143
--- /dev/null
+++ b/openssl-1.1.0h/ssl/methods.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright 1995-2016 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
+ */
+
+#include <stdio.h>
+#include <openssl/objects.h>
+#include "ssl_locl.h"
+
+/*-
+ * TLS/SSLv3 methods
+ */
+
+IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, 0, 0,
+ TLS_method,
+ ossl_statem_accept,
+ ossl_statem_connect, TLSv1_2_enc_data)
+#ifndef OPENSSL_NO_TLS1_2_METHOD
+IMPLEMENT_tls_meth_func(TLS1_2_VERSION, 0, SSL_OP_NO_TLSv1_2,
+ tlsv1_2_method,
+ ossl_statem_accept,
+ ossl_statem_connect, TLSv1_2_enc_data)
+#endif
+#ifndef OPENSSL_NO_TLS1_1_METHOD
+IMPLEMENT_tls_meth_func(TLS1_1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1_1,
+ tlsv1_1_method,
+ ossl_statem_accept,
+ ossl_statem_connect, TLSv1_1_enc_data)
+#endif
+#ifndef OPENSSL_NO_TLS1_METHOD
+IMPLEMENT_tls_meth_func(TLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1,
+ tlsv1_method,
+ ossl_statem_accept, ossl_statem_connect, TLSv1_enc_data)
+#endif
+#ifndef OPENSSL_NO_SSL3_METHOD
+IMPLEMENT_ssl3_meth_func(sslv3_method, ossl_statem_accept, ossl_statem_connect)
+#endif
+/*-
+ * TLS/SSLv3 server methods
+ */
+IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, 0, 0,
+ TLS_server_method,
+ ossl_statem_accept,
+ ssl_undefined_function, TLSv1_2_enc_data)
+#ifndef OPENSSL_NO_TLS1_2_METHOD
+IMPLEMENT_tls_meth_func(TLS1_2_VERSION, 0, SSL_OP_NO_TLSv1_2,
+ tlsv1_2_server_method,
+ ossl_statem_accept,
+ ssl_undefined_function, TLSv1_2_enc_data)
+#endif
+#ifndef OPENSSL_NO_TLS1_1_METHOD
+IMPLEMENT_tls_meth_func(TLS1_1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1_1,
+ tlsv1_1_server_method,
+ ossl_statem_accept,
+ ssl_undefined_function, TLSv1_1_enc_data)
+#endif
+#ifndef OPENSSL_NO_TLS1_METHOD
+IMPLEMENT_tls_meth_func(TLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1,
+ tlsv1_server_method,
+ ossl_statem_accept,
+ ssl_undefined_function, TLSv1_enc_data)
+#endif
+#ifndef OPENSSL_NO_SSL3_METHOD
+IMPLEMENT_ssl3_meth_func(sslv3_server_method,
+ ossl_statem_accept, ssl_undefined_function)
+#endif
+/*-
+ * TLS/SSLv3 client methods
+ */
+IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, 0, 0,
+ TLS_client_method,
+ ssl_undefined_function,
+ ossl_statem_connect, TLSv1_2_enc_data)
+#ifndef OPENSSL_NO_TLS1_2_METHOD
+IMPLEMENT_tls_meth_func(TLS1_2_VERSION, 0, SSL_OP_NO_TLSv1_2,
+ tlsv1_2_client_method,
+ ssl_undefined_function,
+ ossl_statem_connect, TLSv1_2_enc_data)
+#endif
+#ifndef OPENSSL_NO_TLS1_1_METHOD
+IMPLEMENT_tls_meth_func(TLS1_1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1_1,
+ tlsv1_1_client_method,
+ ssl_undefined_function,
+ ossl_statem_connect, TLSv1_1_enc_data)
+#endif
+#ifndef OPENSSL_NO_TLS1_METHOD
+IMPLEMENT_tls_meth_func(TLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1,
+ tlsv1_client_method,
+ ssl_undefined_function,
+ ossl_statem_connect, TLSv1_enc_data)
+#endif
+#ifndef OPENSSL_NO_SSL3_METHOD
+IMPLEMENT_ssl3_meth_func(sslv3_client_method,
+ ssl_undefined_function, ossl_statem_connect)
+#endif
+/*-
+ * DTLS methods
+ */
+#ifndef OPENSSL_NO_DTLS1_METHOD
+IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_DTLSv1,
+ dtlsv1_method,
+ ossl_statem_accept,
+ ossl_statem_connect, DTLSv1_enc_data)
+#endif
+#ifndef OPENSSL_NO_DTLS1_2_METHOD
+IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, 0, SSL_OP_NO_DTLSv1_2,
+ dtlsv1_2_method,
+ ossl_statem_accept,
+ ossl_statem_connect, DTLSv1_2_enc_data)
+#endif
+IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, 0, 0,
+ DTLS_method,
+ ossl_statem_accept,
+ ossl_statem_connect, DTLSv1_2_enc_data)
+
+/*-
+ * DTLS server methods
+ */
+#ifndef OPENSSL_NO_DTLS1_METHOD
+IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_DTLSv1,
+ dtlsv1_server_method,
+ ossl_statem_accept,
+ ssl_undefined_function, DTLSv1_enc_data)
+#endif
+#ifndef OPENSSL_NO_DTLS1_2_METHOD
+IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, 0, SSL_OP_NO_DTLSv1_2,
+ dtlsv1_2_server_method,
+ ossl_statem_accept,
+ ssl_undefined_function, DTLSv1_2_enc_data)
+#endif
+IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, 0, 0,
+ DTLS_server_method,
+ ossl_statem_accept,
+ ssl_undefined_function, DTLSv1_2_enc_data)
+
+/*-
+ * DTLS client methods
+ */
+#ifndef OPENSSL_NO_DTLS1_METHOD
+IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_DTLSv1,
+ dtlsv1_client_method,
+ ssl_undefined_function,
+ ossl_statem_connect, DTLSv1_enc_data)
+IMPLEMENT_dtls1_meth_func(DTLS1_BAD_VER, SSL_METHOD_NO_SUITEB, SSL_OP_NO_DTLSv1,
+ dtls_bad_ver_client_method,
+ ssl_undefined_function,
+ ossl_statem_connect, DTLSv1_enc_data)
+#endif
+#ifndef OPENSSL_NO_DTLS1_2_METHOD
+IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, 0, SSL_OP_NO_DTLSv1_2,
+ dtlsv1_2_client_method,
+ ssl_undefined_function,
+ ossl_statem_connect, DTLSv1_2_enc_data)
+#endif
+IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, 0, 0,
+ DTLS_client_method,
+ ssl_undefined_function,
+ ossl_statem_connect, DTLSv1_2_enc_data)
+#if OPENSSL_API_COMPAT < 0x10100000L
+# ifndef OPENSSL_NO_TLS1_2_METHOD
+const SSL_METHOD *TLSv1_2_method(void)
+{
+ return tlsv1_2_method();
+}
+
+const SSL_METHOD *TLSv1_2_server_method(void)
+{
+ return tlsv1_2_server_method();
+}
+
+const SSL_METHOD *TLSv1_2_client_method(void)
+{
+ return tlsv1_2_client_method();
+}
+# endif
+
+# ifndef OPENSSL_NO_TLS1_1_METHOD
+const SSL_METHOD *TLSv1_1_method(void)
+{
+ return tlsv1_1_method();
+}
+
+const SSL_METHOD *TLSv1_1_server_method(void)
+{
+ return tlsv1_1_server_method();
+}
+
+const SSL_METHOD *TLSv1_1_client_method(void)
+{
+ return tlsv1_1_client_method();
+}
+# endif
+
+# ifndef OPENSSL_NO_TLS1_METHOD
+const SSL_METHOD *TLSv1_method(void)
+{
+ return tlsv1_method();
+}
+
+const SSL_METHOD *TLSv1_server_method(void)
+{
+ return tlsv1_server_method();
+}
+
+const SSL_METHOD *TLSv1_client_method(void)
+{
+ return tlsv1_client_method();
+}
+# endif
+
+# ifndef OPENSSL_NO_SSL3_METHOD
+const SSL_METHOD *SSLv3_method(void)
+{
+ return sslv3_method();
+}
+
+const SSL_METHOD *SSLv3_server_method(void)
+{
+ return sslv3_server_method();
+}
+
+const SSL_METHOD *SSLv3_client_method(void)
+{
+ return sslv3_client_method();
+}
+# endif
+
+# ifndef OPENSSL_NO_DTLS1_2_METHOD
+const SSL_METHOD *DTLSv1_2_method(void)
+{
+ return dtlsv1_2_method();
+}
+
+const SSL_METHOD *DTLSv1_2_server_method(void)
+{
+ return dtlsv1_2_server_method();
+}
+
+const SSL_METHOD *DTLSv1_2_client_method(void)
+{
+ return dtlsv1_2_client_method();
+}
+# endif
+
+# ifndef OPENSSL_NO_DTLS1_METHOD
+const SSL_METHOD *DTLSv1_method(void)
+{
+ return dtlsv1_method();
+}
+
+const SSL_METHOD *DTLSv1_server_method(void)
+{
+ return dtlsv1_server_method();
+}
+
+const SSL_METHOD *DTLSv1_client_method(void)
+{
+ return dtlsv1_client_method();
+}
+# endif
+
+#endif
diff --git a/openssl-1.1.0h/ssl/packet_locl.h b/openssl-1.1.0h/ssl/packet_locl.h
new file mode 100644
index 0000000..d34034d
--- /dev/null
+++ b/openssl-1.1.0h/ssl/packet_locl.h
@@ -0,0 +1,555 @@
+/*
+ * Copyright 2015-2016 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
+ */
+
+#ifndef HEADER_PACKET_LOCL_H
+# define HEADER_PACKET_LOCL_H
+
+# include <string.h>
+# include <openssl/bn.h>
+# include <openssl/buffer.h>
+# include <openssl/crypto.h>
+# include <openssl/e_os2.h>
+
+# include "internal/numbers.h"
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+typedef struct {
+ /* Pointer to where we are currently reading from */
+ const unsigned char *curr;
+ /* Number of bytes remaining */
+ size_t remaining;
+} PACKET;
+
+/* Internal unchecked shorthand; don't use outside this file. */
+static ossl_inline void packet_forward(PACKET *pkt, size_t len)
+{
+ pkt->curr += len;
+ pkt->remaining -= len;
+}
+
+/*
+ * Returns the number of bytes remaining to be read in the PACKET
+ */
+static ossl_inline size_t PACKET_remaining(const PACKET *pkt)
+{
+ return pkt->remaining;
+}
+
+/*
+ * Returns a pointer to the first byte after the packet data.
+ * Useful for integrating with non-PACKET parsing code.
+ * Specifically, we use PACKET_end() to verify that a d2i_... call
+ * has consumed the entire packet contents.
+ */
+static ossl_inline const unsigned char *PACKET_end(const PACKET *pkt)
+{
+ return pkt->curr + pkt->remaining;
+}
+
+/*
+ * Returns a pointer to the PACKET's current position.
+ * For use in non-PACKETized APIs.
+ */
+static ossl_inline const unsigned char *PACKET_data(const PACKET *pkt)
+{
+ return pkt->curr;
+}
+
+/*
+ * Initialise a PACKET with |len| bytes held in |buf|. This does not make a
+ * copy of the data so |buf| must be present for the whole time that the PACKET
+ * is being used.
+ */
+__owur static ossl_inline int PACKET_buf_init(PACKET *pkt,
+ const unsigned char *buf,
+ size_t len)
+{
+ /* Sanity check for negative values. */
+ if (len > (size_t)(SIZE_MAX / 2))
+ return 0;
+
+ pkt->curr = buf;
+ pkt->remaining = len;
+ return 1;
+}
+
+/* Initialize a PACKET to hold zero bytes. */
+static ossl_inline void PACKET_null_init(PACKET *pkt)
+{
+ pkt->curr = NULL;
+ pkt->remaining = 0;
+}
+
+/*
+ * Returns 1 if the packet has length |num| and its contents equal the |num|
+ * bytes read from |ptr|. Returns 0 otherwise (lengths or contents not equal).
+ * If lengths are equal, performs the comparison in constant time.
+ */
+__owur static ossl_inline int PACKET_equal(const PACKET *pkt, const void *ptr,
+ size_t num)
+{
+ if (PACKET_remaining(pkt) != num)
+ return 0;
+ return CRYPTO_memcmp(pkt->curr, ptr, num) == 0;
+}
+
+/*
+ * Peek ahead and initialize |subpkt| with the next |len| bytes read from |pkt|.
+ * Data is not copied: the |subpkt| packet will share its underlying buffer with
+ * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
+ */
+__owur static ossl_inline int PACKET_peek_sub_packet(const PACKET *pkt,
+ PACKET *subpkt, size_t len)
+{
+ if (PACKET_remaining(pkt) < len)
+ return 0;
+
+ return PACKET_buf_init(subpkt, pkt->curr, len);
+}
+
+/*
+ * Initialize |subpkt| with the next |len| bytes read from |pkt|. Data is not
+ * copied: the |subpkt| packet will share its underlying buffer with the
+ * original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
+ */
+__owur static ossl_inline int PACKET_get_sub_packet(PACKET *pkt,
+ PACKET *subpkt, size_t len)
+{
+ if (!PACKET_peek_sub_packet(pkt, subpkt, len))
+ return 0;
+
+ packet_forward(pkt, len);
+
+ return 1;
+}
+
+/*
+ * Peek ahead at 2 bytes in network order from |pkt| and store the value in
+ * |*data|
+ */
+__owur static ossl_inline int PACKET_peek_net_2(const PACKET *pkt,
+ unsigned int *data)
+{
+ if (PACKET_remaining(pkt) < 2)
+ return 0;
+
+ *data = ((unsigned int)(*pkt->curr)) << 8;
+ *data |= *(pkt->curr + 1);
+
+ return 1;
+}
+
+/* Equivalent of n2s */
+/* Get 2 bytes in network order from |pkt| and store the value in |*data| */
+__owur static ossl_inline int PACKET_get_net_2(PACKET *pkt, unsigned int *data)
+{
+ if (!PACKET_peek_net_2(pkt, data))
+ return 0;
+
+ packet_forward(pkt, 2);
+
+ return 1;
+}
+
+/*
+ * Peek ahead at 3 bytes in network order from |pkt| and store the value in
+ * |*data|
+ */
+__owur static ossl_inline int PACKET_peek_net_3(const PACKET *pkt,
+ unsigned long *data)
+{
+ if (PACKET_remaining(pkt) < 3)
+ return 0;
+
+ *data = ((unsigned long)(*pkt->curr)) << 16;
+ *data |= ((unsigned long)(*(pkt->curr + 1))) << 8;
+ *data |= *(pkt->curr + 2);
+
+ return 1;
+}
+
+/* Equivalent of n2l3 */
+/* Get 3 bytes in network order from |pkt| and store the value in |*data| */
+__owur static ossl_inline int PACKET_get_net_3(PACKET *pkt, unsigned long *data)
+{
+ if (!PACKET_peek_net_3(pkt, data))
+ return 0;
+
+ packet_forward(pkt, 3);
+
+ return 1;
+}
+
+/*
+ * Peek ahead at 4 bytes in network order from |pkt| and store the value in
+ * |*data|
+ */
+__owur static ossl_inline int PACKET_peek_net_4(const PACKET *pkt,
+ unsigned long *data)
+{
+ if (PACKET_remaining(pkt) < 4)
+ return 0;
+
+ *data = ((unsigned long)(*pkt->curr)) << 24;
+ *data |= ((unsigned long)(*(pkt->curr + 1))) << 16;
+ *data |= ((unsigned long)(*(pkt->curr + 2))) << 8;
+ *data |= *(pkt->curr + 3);
+
+ return 1;
+}
+
+/* Equivalent of n2l */
+/* Get 4 bytes in network order from |pkt| and store the value in |*data| */
+__owur static ossl_inline int PACKET_get_net_4(PACKET *pkt, unsigned long *data)
+{
+ if (!PACKET_peek_net_4(pkt, data))
+ return 0;
+
+ packet_forward(pkt, 4);
+
+ return 1;
+}
+
+/* Peek ahead at 1 byte from |pkt| and store the value in |*data| */
+__owur static ossl_inline int PACKET_peek_1(const PACKET *pkt,
+ unsigned int *data)
+{
+ if (!PACKET_remaining(pkt))
+ return 0;
+
+ *data = *pkt->curr;
+
+ return 1;
+}
+
+/* Get 1 byte from |pkt| and store the value in |*data| */
+__owur static ossl_inline int PACKET_get_1(PACKET *pkt, unsigned int *data)
+{
+ if (!PACKET_peek_1(pkt, data))
+ return 0;
+
+ packet_forward(pkt, 1);
+
+ return 1;
+}
+
+/*
+ * Peek ahead at 4 bytes in reverse network order from |pkt| and store the value
+ * in |*data|
+ */
+__owur static ossl_inline int PACKET_peek_4(const PACKET *pkt,
+ unsigned long *data)
+{
+ if (PACKET_remaining(pkt) < 4)
+ return 0;
+
+ *data = *pkt->curr;
+ *data |= ((unsigned long)(*(pkt->curr + 1))) << 8;
+ *data |= ((unsigned long)(*(pkt->curr + 2))) << 16;
+ *data |= ((unsigned long)(*(pkt->curr + 3))) << 24;
+
+ return 1;
+}
+
+/* Equivalent of c2l */
+/*
+ * Get 4 bytes in reverse network order from |pkt| and store the value in
+ * |*data|
+ */
+__owur static ossl_inline int PACKET_get_4(PACKET *pkt, unsigned long *data)
+{
+ if (!PACKET_peek_4(pkt, data))
+ return 0;
+
+ packet_forward(pkt, 4);
+
+ return 1;
+}
+
+/*
+ * Peek ahead at |len| bytes from the |pkt| and store a pointer to them in
+ * |*data|. This just points at the underlying buffer that |pkt| is using. The
+ * caller should not free this data directly (it will be freed when the
+ * underlying buffer gets freed
+ */
+__owur static ossl_inline int PACKET_peek_bytes(const PACKET *pkt,
+ const unsigned char **data,
+ size_t len)
+{
+ if (PACKET_remaining(pkt) < len)
+ return 0;
+
+ *data = pkt->curr;
+
+ return 1;
+}
+
+/*
+ * Read |len| bytes from the |pkt| and store a pointer to them in |*data|. This
+ * just points at the underlying buffer that |pkt| is using. The caller should
+ * not free this data directly (it will be freed when the underlying buffer gets
+ * freed
+ */
+__owur static ossl_inline int PACKET_get_bytes(PACKET *pkt,
+ const unsigned char **data,
+ size_t len)
+{
+ if (!PACKET_peek_bytes(pkt, data, len))
+ return 0;
+
+ packet_forward(pkt, len);
+
+ return 1;
+}
+
+/* Peek ahead at |len| bytes from |pkt| and copy them to |data| */
+__owur static ossl_inline int PACKET_peek_copy_bytes(const PACKET *pkt,
+ unsigned char *data,
+ size_t len)
+{
+ if (PACKET_remaining(pkt) < len)
+ return 0;
+
+ memcpy(data, pkt->curr, len);
+
+ return 1;
+}
+
+/*
+ * Read |len| bytes from |pkt| and copy them to |data|.
+ * The caller is responsible for ensuring that |data| can hold |len| bytes.
+ */
+__owur static ossl_inline int PACKET_copy_bytes(PACKET *pkt,
+ unsigned char *data, size_t len)
+{
+ if (!PACKET_peek_copy_bytes(pkt, data, len))
+ return 0;
+
+ packet_forward(pkt, len);
+
+ return 1;
+}
+
+/*
+ * Copy packet data to |dest|, and set |len| to the number of copied bytes.
+ * If the packet has more than |dest_len| bytes, nothing is copied.
+ * Returns 1 if the packet data fits in |dest_len| bytes, 0 otherwise.
+ * Does not forward PACKET position (because it is typically the last thing
+ * done with a given PACKET).
+ */
+__owur static ossl_inline int PACKET_copy_all(const PACKET *pkt,
+ unsigned char *dest,
+ size_t dest_len, size_t *len)
+{
+ if (PACKET_remaining(pkt) > dest_len) {
+ *len = 0;
+ return 0;
+ }
+ *len = pkt->remaining;
+ memcpy(dest, pkt->curr, pkt->remaining);
+ return 1;
+}
+
+/*
+ * Copy |pkt| bytes to a newly allocated buffer and store a pointer to the
+ * result in |*data|, and the length in |len|.
+ * If |*data| is not NULL, the old data is OPENSSL_free'd.
+ * If the packet is empty, or malloc fails, |*data| will be set to NULL.
+ * Returns 1 if the malloc succeeds and 0 otherwise.
+ * Does not forward PACKET position (because it is typically the last thing
+ * done with a given PACKET).
+ */
+__owur static ossl_inline int PACKET_memdup(const PACKET *pkt,
+ unsigned char **data, size_t *len)
+{
+ size_t length;
+
+ OPENSSL_free(*data);
+ *data = NULL;
+ *len = 0;
+
+ length = PACKET_remaining(pkt);
+
+ if (length == 0)
+ return 1;
+
+ *data = OPENSSL_memdup(pkt->curr, length);
+ if (*data == NULL)
+ return 0;
+
+ *len = length;
+ return 1;
+}
+
+/*
+ * Read a C string from |pkt| and copy to a newly allocated, NUL-terminated
+ * buffer. Store a pointer to the result in |*data|.
+ * If |*data| is not NULL, the old data is OPENSSL_free'd.
+ * If the data in |pkt| does not contain a NUL-byte, the entire data is
+ * copied and NUL-terminated.
+ * Returns 1 if the malloc succeeds and 0 otherwise.
+ * Does not forward PACKET position (because it is typically the last thing done
+ * with a given PACKET).
+ */
+__owur static ossl_inline int PACKET_strndup(const PACKET *pkt, char **data)
+{
+ OPENSSL_free(*data);
+
+ /* This will succeed on an empty packet, unless pkt->curr == NULL. */
+ *data = OPENSSL_strndup((const char *)pkt->curr, PACKET_remaining(pkt));
+ return (*data != NULL);
+}
+
+/* Returns 1 if |pkt| contains at least one 0-byte, 0 otherwise. */
+static ossl_inline int PACKET_contains_zero_byte(const PACKET *pkt)
+{
+ return memchr(pkt->curr, 0, pkt->remaining) != NULL;
+}
+
+/* Move the current reading position forward |len| bytes */
+__owur static ossl_inline int PACKET_forward(PACKET *pkt, size_t len)
+{
+ if (PACKET_remaining(pkt) < len)
+ return 0;
+
+ packet_forward(pkt, len);
+
+ return 1;
+}
+
+/*
+ * Reads a variable-length vector prefixed with a one-byte length, and stores
+ * the contents in |subpkt|. |pkt| can equal |subpkt|.
+ * Data is not copied: the |subpkt| packet will share its underlying buffer with
+ * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
+ * Upon failure, the original |pkt| and |subpkt| are not modified.
+ */
+__owur static ossl_inline int PACKET_get_length_prefixed_1(PACKET *pkt,
+ PACKET *subpkt)
+{
+ unsigned int length;
+ const unsigned char *data;
+ PACKET tmp = *pkt;
+ if (!PACKET_get_1(&tmp, &length) ||
+ !PACKET_get_bytes(&tmp, &data, (size_t)length)) {
+ return 0;
+ }
+
+ *pkt = tmp;
+ subpkt->curr = data;
+ subpkt->remaining = length;
+
+ return 1;
+}
+
+/*
+ * Like PACKET_get_length_prefixed_1, but additionally, fails when there are
+ * leftover bytes in |pkt|.
+ */
+__owur static ossl_inline int PACKET_as_length_prefixed_1(PACKET *pkt,
+ PACKET *subpkt)
+{
+ unsigned int length;
+ const unsigned char *data;
+ PACKET tmp = *pkt;
+ if (!PACKET_get_1(&tmp, &length) ||
+ !PACKET_get_bytes(&tmp, &data, (size_t)length) ||
+ PACKET_remaining(&tmp) != 0) {
+ return 0;
+ }
+
+ *pkt = tmp;
+ subpkt->curr = data;
+ subpkt->remaining = length;
+
+ return 1;
+}
+
+/*
+ * Reads a variable-length vector prefixed with a two-byte length, and stores
+ * the contents in |subpkt|. |pkt| can equal |subpkt|.
+ * Data is not copied: the |subpkt| packet will share its underlying buffer with
+ * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
+ * Upon failure, the original |pkt| and |subpkt| are not modified.
+ */
+__owur static ossl_inline int PACKET_get_length_prefixed_2(PACKET *pkt,
+ PACKET *subpkt)
+{
+ unsigned int length;
+ const unsigned char *data;
+ PACKET tmp = *pkt;
+
+ if (!PACKET_get_net_2(&tmp, &length) ||
+ !PACKET_get_bytes(&tmp, &data, (size_t)length)) {
+ return 0;
+ }
+
+ *pkt = tmp;
+ subpkt->curr = data;
+ subpkt->remaining = length;
+
+ return 1;
+}
+
+/*
+ * Like PACKET_get_length_prefixed_2, but additionally, fails when there are
+ * leftover bytes in |pkt|.
+ */
+__owur static ossl_inline int PACKET_as_length_prefixed_2(PACKET *pkt,
+ PACKET *subpkt)
+{
+ unsigned int length;
+ const unsigned char *data;
+ PACKET tmp = *pkt;
+
+ if (!PACKET_get_net_2(&tmp, &length) ||
+ !PACKET_get_bytes(&tmp, &data, (size_t)length) ||
+ PACKET_remaining(&tmp) != 0) {
+ return 0;
+ }
+
+ *pkt = tmp;
+ subpkt->curr = data;
+ subpkt->remaining = length;
+
+ return 1;
+}
+
+/*
+ * Reads a variable-length vector prefixed with a three-byte length, and stores
+ * the contents in |subpkt|. |pkt| can equal |subpkt|.
+ * Data is not copied: the |subpkt| packet will share its underlying buffer with
+ * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
+ * Upon failure, the original |pkt| and |subpkt| are not modified.
+ */
+__owur static ossl_inline int PACKET_get_length_prefixed_3(PACKET *pkt,
+ PACKET *subpkt)
+{
+ unsigned long length;
+ const unsigned char *data;
+ PACKET tmp = *pkt;
+ if (!PACKET_get_net_3(&tmp, &length) ||
+ !PACKET_get_bytes(&tmp, &data, (size_t)length)) {
+ return 0;
+ }
+
+ *pkt = tmp;
+ subpkt->curr = data;
+ subpkt->remaining = length;
+
+ return 1;
+}
+# ifdef __cplusplus
+}
+# endif
+
+#endif /* HEADER_PACKET_LOCL_H */
diff --git a/openssl-1.1.0h/ssl/pqueue.c b/openssl-1.1.0h/ssl/pqueue.c
new file mode 100644
index 0000000..b447e1d
--- /dev/null
+++ b/openssl-1.1.0h/ssl/pqueue.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2005-2016 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
+ */
+
+#include "ssl_locl.h"
+#include <openssl/bn.h>
+
+struct pqueue_st {
+ pitem *items;
+ int count;
+};
+
+pitem *pitem_new(unsigned char *prio64be, void *data)
+{
+ pitem *item = OPENSSL_malloc(sizeof(*item));
+ if (item == NULL)
+ return NULL;
+
+ memcpy(item->priority, prio64be, sizeof(item->priority));
+
+ item->data = data;
+ item->next = NULL;
+
+ return item;
+}
+
+void pitem_free(pitem *item)
+{
+ OPENSSL_free(item);
+}
+
+pqueue *pqueue_new()
+{
+ pqueue *pq = OPENSSL_zalloc(sizeof(*pq));
+
+ return pq;
+}
+
+void pqueue_free(pqueue *pq)
+{
+ OPENSSL_free(pq);
+}
+
+pitem *pqueue_insert(pqueue *pq, pitem *item)
+{
+ pitem *curr, *next;
+
+ if (pq->items == NULL) {
+ pq->items = item;
+ return item;
+ }
+
+ for (curr = NULL, next = pq->items;
+ next != NULL; curr = next, next = next->next) {
+ /*
+ * we can compare 64-bit value in big-endian encoding with memcmp:-)
+ */
+ int cmp = memcmp(next->priority, item->priority, 8);
+ if (cmp > 0) { /* next > item */
+ item->next = next;
+
+ if (curr == NULL)
+ pq->items = item;
+ else
+ curr->next = item;
+
+ return item;
+ }
+
+ else if (cmp == 0) /* duplicates not allowed */
+ return NULL;
+ }
+
+ item->next = NULL;
+ curr->next = item;
+
+ return item;
+}
+
+pitem *pqueue_peek(pqueue *pq)
+{
+ return pq->items;
+}
+
+pitem *pqueue_pop(pqueue *pq)
+{
+ pitem *item = pq->items;
+
+ if (pq->items != NULL)
+ pq->items = pq->items->next;
+
+ return item;
+}
+
+pitem *pqueue_find(pqueue *pq, unsigned char *prio64be)
+{
+ pitem *next;
+ pitem *found = NULL;
+
+ if (pq->items == NULL)
+ return NULL;
+
+ for (next = pq->items; next->next != NULL; next = next->next) {
+ if (memcmp(next->priority, prio64be, 8) == 0) {
+ found = next;
+ break;
+ }
+ }
+
+ /* check the one last node */
+ if (memcmp(next->priority, prio64be, 8) == 0)
+ found = next;
+
+ if (!found)
+ return NULL;
+
+ return found;
+}
+
+pitem *pqueue_iterator(pqueue *pq)
+{
+ return pqueue_peek(pq);
+}
+
+pitem *pqueue_next(pitem **item)
+{
+ pitem *ret;
+
+ if (item == NULL || *item == NULL)
+ return NULL;
+
+ /* *item != NULL */
+ ret = *item;
+ *item = (*item)->next;
+
+ return ret;
+}
+
+int pqueue_size(pqueue *pq)
+{
+ pitem *item = pq->items;
+ int count = 0;
+
+ while (item != NULL) {
+ count++;
+ item = item->next;
+ }
+ return count;
+}
diff --git a/openssl-1.1.0h/ssl/record/README b/openssl-1.1.0h/ssl/record/README
new file mode 100644
index 0000000..987e9fd
--- /dev/null
+++ b/openssl-1.1.0h/ssl/record/README
@@ -0,0 +1,74 @@
+Record Layer Design
+===================
+
+This file provides some guidance on the thinking behind the design of the
+record layer code to aid future maintenance.
+
+The record layer is divided into a number of components. At the time of writing
+there are four: SSL3_RECORD, SSL3_BUFFER, DLTS1_BITMAP and RECORD_LAYER. Each
+of these components is defined by:
+1) A struct definition of the same name as the component
+2) A set of source files that define the functions for that component
+3) A set of accessor macros
+
+All struct definitions are in record.h. The functions and macros are either
+defined in record.h or record_locl.h dependent on whether they are intended to
+be private to the record layer, or whether they form part of the API to the rest
+of libssl.
+
+The source files map to components as follows:
+
+dtls1_bitmap.c -> DTLS1_BITMAP component
+ssl3_buffer.c -> SSL3_BUFFER component
+ssl3_record.c -> SSL3_RECORD component
+rec_layer_s3.c, rec_layer_d1.c -> RECORD_LAYER component
+
+The RECORD_LAYER component is a facade pattern, i.e. it provides a simplified
+interface to the record layer for the rest of libssl. The other 3 components are
+entirely private to the record layer and therefore should never be accessed
+directly by libssl.
+
+Any component can directly access its own members - they are private to that
+component, e.g. ssl3_buffer.c can access members of the SSL3_BUFFER struct
+without using a macro. No component can directly access the members of another
+component, e.g. ssl3_buffer cannot reach inside the RECORD_LAYER component to
+directly access its members. Instead components use accessor macros, so if code
+in ssl3_buffer.c wants to access the members of the RECORD_LAYER it uses the
+RECORD_LAYER_* macros.
+
+Conceptually it looks like this:
+
+ libssl
+ |
+---------------------------|-----record.h--------------------------------------
+ |
+ _______V______________
+ | |
+ | RECORD_LAYER |
+ | |
+ | rec_layer_s3.c |
+ | ^ |
+ | _________|__________ |
+ || ||
+ || DTLS1_RECORD_LAYER ||
+ || ||
+ || rec_layer_d1.c ||
+ ||____________________||
+ |______________________|
+ record_locl.h ^ ^ ^
+ _________________| | |_________________
+ | | |
+ _____V_________ ______V________ _______V________
+ | | | | | |
+ | SSL3_BUFFER | | SSL3_RECORD | | DTLS1_BITMAP |
+ | |--->| | | |
+ | ssl3_buffer.c | | ssl3_record.c | | dtls1_bitmap.c |
+ |_______________| |_______________| |________________|
+
+
+The two RECORD_LAYER source files build on each other, i.e.
+the main one is rec_layer_s3.c which provides the core SSL/TLS layer. The second
+one is rec_layer_d1.c which builds off of the SSL/TLS code to provide DTLS
+specific capabilities. It uses some DTLS specific RECORD_LAYER component members
+which should only be accessed from rec_layer_d1.c. These are held in the
+DTLS1_RECORD_LAYER struct.
diff --git a/openssl-1.1.0h/ssl/record/dtls1_bitmap.c b/openssl-1.1.0h/ssl/record/dtls1_bitmap.c
new file mode 100644
index 0000000..5923c53
--- /dev/null
+++ b/openssl-1.1.0h/ssl/record/dtls1_bitmap.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2005-2016 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
+ */
+
+#include "../ssl_locl.h"
+#include "record_locl.h"
+
+/* mod 128 saturating subtract of two 64-bit values in big-endian order */
+static int satsub64be(const unsigned char *v1, const unsigned char *v2)
+{
+ int64_t ret;
+ uint64_t l1, l2;
+
+ n2l8(v1, l1);
+ n2l8(v2, l2);
+
+ ret = l1 - l2;
+
+ /* We do not permit wrap-around */
+ if (l1 > l2 && ret < 0)
+ return 128;
+ else if (l2 > l1 && ret > 0)
+ return -128;
+
+ if (ret > 128)
+ return 128;
+ else if (ret < -128)
+ return -128;
+ else
+ return (int)ret;
+}
+
+int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap)
+{
+ int cmp;
+ unsigned int shift;
+ const unsigned char *seq = s->rlayer.read_sequence;
+
+ cmp = satsub64be(seq, bitmap->max_seq_num);
+ if (cmp > 0) {
+ SSL3_RECORD_set_seq_num(RECORD_LAYER_get_rrec(&s->rlayer), seq);
+ return 1; /* this record in new */
+ }
+ shift = -cmp;
+ if (shift >= sizeof(bitmap->map) * 8)
+ return 0; /* stale, outside the window */
+ else if (bitmap->map & (1UL << shift))
+ return 0; /* record previously received */
+
+ SSL3_RECORD_set_seq_num(RECORD_LAYER_get_rrec(&s->rlayer), seq);
+ return 1;
+}
+
+void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap)
+{
+ int cmp;
+ unsigned int shift;
+ const unsigned char *seq = RECORD_LAYER_get_read_sequence(&s->rlayer);
+
+ cmp = satsub64be(seq, bitmap->max_seq_num);
+ if (cmp > 0) {
+ shift = cmp;
+ if (shift < sizeof(bitmap->map) * 8)
+ bitmap->map <<= shift, bitmap->map |= 1UL;
+ else
+ bitmap->map = 1UL;
+ memcpy(bitmap->max_seq_num, seq, SEQ_NUM_SIZE);
+ } else {
+ shift = -cmp;
+ if (shift < sizeof(bitmap->map) * 8)
+ bitmap->map |= 1UL << shift;
+ }
+}
diff --git a/openssl-1.1.0h/ssl/record/rec_layer_d1.c b/openssl-1.1.0h/ssl/record/rec_layer_d1.c
new file mode 100644
index 0000000..b3ff5f1
--- /dev/null
+++ b/openssl-1.1.0h/ssl/record/rec_layer_d1.c
@@ -0,0 +1,1229 @@
+/*
+ * Copyright 2005-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
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#define USE_SOCKETS
+#include "../ssl_locl.h"
+#include <openssl/evp.h>
+#include <openssl/buffer.h>
+#include "record_locl.h"
+
+int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl)
+{
+ DTLS_RECORD_LAYER *d;
+
+ if ((d = OPENSSL_malloc(sizeof(*d))) == NULL)
+ return (0);
+
+ rl->d = d;
+
+ d->unprocessed_rcds.q = pqueue_new();
+ d->processed_rcds.q = pqueue_new();
+ d->buffered_app_data.q = pqueue_new();
+
+ if (d->unprocessed_rcds.q == NULL || d->processed_rcds.q == NULL
+ || d->buffered_app_data.q == NULL) {
+ pqueue_free(d->unprocessed_rcds.q);
+ pqueue_free(d->processed_rcds.q);
+ pqueue_free(d->buffered_app_data.q);
+ OPENSSL_free(d);
+ rl->d = NULL;
+ return (0);
+ }
+
+ return 1;
+}
+
+void DTLS_RECORD_LAYER_free(RECORD_LAYER *rl)
+{
+ DTLS_RECORD_LAYER_clear(rl);
+ pqueue_free(rl->d->unprocessed_rcds.q);
+ pqueue_free(rl->d->processed_rcds.q);
+ pqueue_free(rl->d->buffered_app_data.q);
+ OPENSSL_free(rl->d);
+ rl->d = NULL;
+}
+
+void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl)
+{
+ DTLS_RECORD_LAYER *d;
+ pitem *item = NULL;
+ DTLS1_RECORD_DATA *rdata;
+ pqueue *unprocessed_rcds;
+ pqueue *processed_rcds;
+ pqueue *buffered_app_data;
+
+ d = rl->d;
+
+ while ((item = pqueue_pop(d->unprocessed_rcds.q)) != NULL) {
+ rdata = (DTLS1_RECORD_DATA *)item->data;
+ OPENSSL_free(rdata->rbuf.buf);
+ OPENSSL_free(item->data);
+ pitem_free(item);
+ }
+
+ while ((item = pqueue_pop(d->processed_rcds.q)) != NULL) {
+ rdata = (DTLS1_RECORD_DATA *)item->data;
+ OPENSSL_free(rdata->rbuf.buf);
+ OPENSSL_free(item->data);
+ pitem_free(item);
+ }
+
+ while ((item = pqueue_pop(d->buffered_app_data.q)) != NULL) {
+ rdata = (DTLS1_RECORD_DATA *)item->data;
+ OPENSSL_free(rdata->rbuf.buf);
+ OPENSSL_free(item->data);
+ pitem_free(item);
+ }
+
+ unprocessed_rcds = d->unprocessed_rcds.q;
+ processed_rcds = d->processed_rcds.q;
+ buffered_app_data = d->buffered_app_data.q;
+ memset(d, 0, sizeof(*d));
+ d->unprocessed_rcds.q = unprocessed_rcds;
+ d->processed_rcds.q = processed_rcds;
+ d->buffered_app_data.q = buffered_app_data;
+}
+
+void DTLS_RECORD_LAYER_set_saved_w_epoch(RECORD_LAYER *rl, unsigned short e)
+{
+ if (e == rl->d->w_epoch - 1) {
+ memcpy(rl->d->curr_write_sequence,
+ rl->write_sequence, sizeof(rl->write_sequence));
+ memcpy(rl->write_sequence,
+ rl->d->last_write_sequence, sizeof(rl->write_sequence));
+ } else if (e == rl->d->w_epoch + 1) {
+ memcpy(rl->d->last_write_sequence,
+ rl->write_sequence, sizeof(unsigned char[8]));
+ memcpy(rl->write_sequence,
+ rl->d->curr_write_sequence, sizeof(rl->write_sequence));
+ }
+ rl->d->w_epoch = e;
+}
+
+void DTLS_RECORD_LAYER_resync_write(RECORD_LAYER *rl)
+{
+ memcpy(rl->write_sequence, rl->read_sequence, sizeof(rl->write_sequence));
+}
+
+void DTLS_RECORD_LAYER_set_write_sequence(RECORD_LAYER *rl, unsigned char *seq)
+{
+ memcpy(rl->write_sequence, seq, SEQ_NUM_SIZE);
+}
+
+static int have_handshake_fragment(SSL *s, int type, unsigned char *buf,
+ int len);
+
+/* copy buffered record into SSL structure */
+static int dtls1_copy_record(SSL *s, pitem *item)
+{
+ DTLS1_RECORD_DATA *rdata;
+
+ rdata = (DTLS1_RECORD_DATA *)item->data;
+
+ SSL3_BUFFER_release(&s->rlayer.rbuf);
+
+ s->rlayer.packet = rdata->packet;
+ s->rlayer.packet_length = rdata->packet_length;
+ memcpy(&s->rlayer.rbuf, &(rdata->rbuf), sizeof(SSL3_BUFFER));
+ memcpy(&s->rlayer.rrec, &(rdata->rrec), sizeof(SSL3_RECORD));
+
+ /* Set proper sequence number for mac calculation */
+ memcpy(&(s->rlayer.read_sequence[2]), &(rdata->packet[5]), 6);
+
+ return (1);
+}
+
+int dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority)
+{
+ DTLS1_RECORD_DATA *rdata;
+ pitem *item;
+
+ /* Limit the size of the queue to prevent DOS attacks */
+ if (pqueue_size(queue->q) >= 100)
+ return 0;
+
+ rdata = OPENSSL_malloc(sizeof(*rdata));
+ item = pitem_new(priority, rdata);
+ if (rdata == NULL || item == NULL) {
+ OPENSSL_free(rdata);
+ pitem_free(item);
+ SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ rdata->packet = s->rlayer.packet;
+ rdata->packet_length = s->rlayer.packet_length;
+ memcpy(&(rdata->rbuf), &s->rlayer.rbuf, sizeof(SSL3_BUFFER));
+ memcpy(&(rdata->rrec), &s->rlayer.rrec, sizeof(SSL3_RECORD));
+
+ item->data = rdata;
+
+#ifndef OPENSSL_NO_SCTP
+ /* Store bio_dgram_sctp_rcvinfo struct */
+ if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
+ (SSL_get_state(s) == TLS_ST_SR_FINISHED
+ || SSL_get_state(s) == TLS_ST_CR_FINISHED)) {
+ BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_GET_RCVINFO,
+ sizeof(rdata->recordinfo), &rdata->recordinfo);
+ }
+#endif
+
+ s->rlayer.packet = NULL;
+ s->rlayer.packet_length = 0;
+ memset(&s->rlayer.rbuf, 0, sizeof(s->rlayer.rbuf));
+ memset(&s->rlayer.rrec, 0, sizeof(s->rlayer.rrec));
+
+ if (!ssl3_setup_buffers(s)) {
+ SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
+ OPENSSL_free(rdata->rbuf.buf);
+ OPENSSL_free(rdata);
+ pitem_free(item);
+ return (-1);
+ }
+
+ /* insert should not fail, since duplicates are dropped */
+ if (pqueue_insert(queue->q, item) == NULL) {
+ SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
+ OPENSSL_free(rdata->rbuf.buf);
+ OPENSSL_free(rdata);
+ pitem_free(item);
+ return (-1);
+ }
+
+ return (1);
+}
+
+int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue)
+{
+ pitem *item;
+
+ item = pqueue_pop(queue->q);
+ if (item) {
+ dtls1_copy_record(s, item);
+
+ OPENSSL_free(item->data);
+ pitem_free(item);
+
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
+ * retrieve a buffered record that belongs to the new epoch, i.e., not
+ * processed yet
+ */
+#define dtls1_get_unprocessed_record(s) \
+ dtls1_retrieve_buffered_record((s), \
+ &((s)->rlayer.d->unprocessed_rcds))
+
+int dtls1_process_buffered_records(SSL *s)
+{
+ pitem *item;
+ SSL3_BUFFER *rb;
+ SSL3_RECORD *rr;
+ DTLS1_BITMAP *bitmap;
+ unsigned int is_next_epoch;
+ int replayok = 1;
+
+ item = pqueue_peek(s->rlayer.d->unprocessed_rcds.q);
+ if (item) {
+ /* Check if epoch is current. */
+ if (s->rlayer.d->unprocessed_rcds.epoch != s->rlayer.d->r_epoch)
+ return 1; /* Nothing to do. */
+
+ rr = RECORD_LAYER_get_rrec(&s->rlayer);
+
+ rb = RECORD_LAYER_get_rbuf(&s->rlayer);
+
+ if (SSL3_BUFFER_get_left(rb) > 0) {
+ /*
+ * We've still got data from the current packet to read. There could
+ * be a record from the new epoch in it - so don't overwrite it
+ * with the unprocessed records yet (we'll do it when we've
+ * finished reading the current packet).
+ */
+ return 1;
+ }
+
+ /* Process all the records. */
+ while (pqueue_peek(s->rlayer.d->unprocessed_rcds.q)) {
+ dtls1_get_unprocessed_record(s);
+ bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
+ if (bitmap == NULL) {
+ /*
+ * Should not happen. This will only ever be NULL when the
+ * current record is from a different epoch. But that cannot
+ * be the case because we already checked the epoch above
+ */
+ SSLerr(SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+#ifndef OPENSSL_NO_SCTP
+ /* Only do replay check if no SCTP bio */
+ if (!BIO_dgram_is_sctp(SSL_get_rbio(s)))
+#endif
+ {
+ /*
+ * Check whether this is a repeat, or aged record. We did this
+ * check once already when we first received the record - but
+ * we might have updated the window since then due to
+ * records we subsequently processed.
+ */
+ replayok = dtls1_record_replay_check(s, bitmap);
+ }
+
+ if (!replayok || !dtls1_process_record(s, bitmap)) {
+ /* dump this record */
+ rr->length = 0;
+ RECORD_LAYER_reset_packet_length(&s->rlayer);
+ continue;
+ }
+
+ if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds),
+ SSL3_RECORD_get_seq_num(s->rlayer.rrec)) < 0)
+ return 0;
+ }
+ }
+
+ /*
+ * sync epoch numbers once all the unprocessed records have been
+ * processed
+ */
+ s->rlayer.d->processed_rcds.epoch = s->rlayer.d->r_epoch;
+ s->rlayer.d->unprocessed_rcds.epoch = s->rlayer.d->r_epoch + 1;
+
+ return 1;
+}
+
+/*-
+ * Return up to 'len' payload bytes received in 'type' records.
+ * 'type' is one of the following:
+ *
+ * - SSL3_RT_HANDSHAKE (when ssl3_get_message calls us)
+ * - SSL3_RT_APPLICATION_DATA (when ssl3_read calls us)
+ * - 0 (during a shutdown, no data has to be returned)
+ *
+ * If we don't have stored data to work from, read a SSL/TLS record first
+ * (possibly multiple records if we still don't have anything to return).
+ *
+ * This function must handle any surprises the peer may have for us, such as
+ * Alert records (e.g. close_notify) or renegotiation requests. ChangeCipherSpec
+ * messages are treated as if they were handshake messages *if* the |recd_type|
+ * argument is non NULL.
+ * Also if record payloads contain fragments too small to process, we store
+ * them until there is enough for the respective protocol (the record protocol
+ * may use arbitrary fragmentation and even interleaving):
+ * Change cipher spec protocol
+ * just 1 byte needed, no need for keeping anything stored
+ * Alert protocol
+ * 2 bytes needed (AlertLevel, AlertDescription)
+ * Handshake protocol
+ * 4 bytes needed (HandshakeType, uint24 length) -- we just have
+ * to detect unexpected Client Hello and Hello Request messages
+ * here, anything else is handled by higher layers
+ * Application data protocol
+ * none of our business
+ */
+int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
+ int len, int peek)
+{
+ int al, i, j, ret;
+ unsigned int n;
+ SSL3_RECORD *rr;
+ void (*cb) (const SSL *ssl, int type2, int val) = NULL;
+
+ if (!SSL3_BUFFER_is_initialised(&s->rlayer.rbuf)) {
+ /* Not initialized yet */
+ if (!ssl3_setup_buffers(s))
+ return (-1);
+ }
+
+ if ((type && (type != SSL3_RT_APPLICATION_DATA) &&
+ (type != SSL3_RT_HANDSHAKE)) ||
+ (peek && (type != SSL3_RT_APPLICATION_DATA))) {
+ SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ /*
+ * check whether there's a handshake message (client hello?) waiting
+ */
+ if ((ret = have_handshake_fragment(s, type, buf, len))) {
+ *recvd_type = SSL3_RT_HANDSHAKE;
+ return ret;
+ }
+
+ /*
+ * Now s->rlayer.d->handshake_fragment_len == 0 if
+ * type == SSL3_RT_HANDSHAKE.
+ */
+
+ if (!ossl_statem_get_in_handshake(s) && SSL_in_init(s))
+ {
+ /* type == SSL3_RT_APPLICATION_DATA */
+ i = s->handshake_func(s);
+ if (i < 0)
+ return (i);
+ if (i == 0) {
+ SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE);
+ return (-1);
+ }
+ }
+
+ start:
+ s->rwstate = SSL_NOTHING;
+
+ /*-
+ * s->s3->rrec.type - is the type of record
+ * s->s3->rrec.data, - data
+ * s->s3->rrec.off, - offset into 'data' for next read
+ * s->s3->rrec.length, - number of bytes.
+ */
+ rr = s->rlayer.rrec;
+
+ /*
+ * We are not handshaking and have no data yet, so process data buffered
+ * during the last handshake in advance, if any.
+ */
+ if (SSL_is_init_finished(s) && SSL3_RECORD_get_length(rr) == 0) {
+ pitem *item;
+ item = pqueue_pop(s->rlayer.d->buffered_app_data.q);
+ if (item) {
+#ifndef OPENSSL_NO_SCTP
+ /* Restore bio_dgram_sctp_rcvinfo struct */
+ if (BIO_dgram_is_sctp(SSL_get_rbio(s))) {
+ DTLS1_RECORD_DATA *rdata = (DTLS1_RECORD_DATA *)item->data;
+ BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_SET_RCVINFO,
+ sizeof(rdata->recordinfo), &rdata->recordinfo);
+ }
+#endif
+
+ dtls1_copy_record(s, item);
+
+ OPENSSL_free(item->data);
+ pitem_free(item);
+ }
+ }
+
+ /* Check for timeout */
+ if (dtls1_handle_timeout(s) > 0)
+ goto start;
+
+ /* get new packet if necessary */
+ if ((SSL3_RECORD_get_length(rr) == 0)
+ || (s->rlayer.rstate == SSL_ST_READ_BODY)) {
+ ret = dtls1_get_record(s);
+ if (ret <= 0) {
+ ret = dtls1_read_failed(s, ret);
+ /* anything other than a timeout is an error */
+ if (ret <= 0)
+ return (ret);
+ else
+ goto start;
+ }
+ }
+
+ /*
+ * Reset the count of consecutive warning alerts if we've got a non-empty
+ * record that isn't an alert.
+ */
+ if (SSL3_RECORD_get_type(rr) != SSL3_RT_ALERT
+ && SSL3_RECORD_get_length(rr) != 0)
+ s->rlayer.alert_count = 0;
+
+ /* we now have a packet which can be read and processed */
+
+ if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
+ * reset by ssl3_get_finished */
+ && (SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE)) {
+ /*
+ * We now have application data between CCS and Finished. Most likely
+ * the packets were reordered on their way, so buffer the application
+ * data for later processing rather than dropping the connection.
+ */
+ if (dtls1_buffer_record(s, &(s->rlayer.d->buffered_app_data),
+ SSL3_RECORD_get_seq_num(rr)) < 0) {
+ SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+ SSL3_RECORD_set_length(rr, 0);
+ goto start;
+ }
+
+ /*
+ * If the other end has shut down, throw anything we read away (even in
+ * 'peek' mode)
+ */
+ if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
+ SSL3_RECORD_set_length(rr, 0);
+ s->rwstate = SSL_NOTHING;
+ return (0);
+ }
+
+ if (type == SSL3_RECORD_get_type(rr)
+ || (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC
+ && type == SSL3_RT_HANDSHAKE && recvd_type != NULL)) {
+ /*
+ * SSL3_RT_APPLICATION_DATA or
+ * SSL3_RT_HANDSHAKE or
+ * SSL3_RT_CHANGE_CIPHER_SPEC
+ */
+ /*
+ * make sure that we are not getting application data when we are
+ * doing a handshake for the first time
+ */
+ if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) &&
+ (s->enc_read_ctx == NULL)) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_APP_DATA_IN_HANDSHAKE);
+ goto f_err;
+ }
+
+ if (recvd_type != NULL)
+ *recvd_type = SSL3_RECORD_get_type(rr);
+
+ if (len <= 0)
+ return (len);
+
+ if ((unsigned int)len > SSL3_RECORD_get_length(rr))
+ n = SSL3_RECORD_get_length(rr);
+ else
+ n = (unsigned int)len;
+
+ memcpy(buf, &(SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)]), n);
+ if (!peek) {
+ SSL3_RECORD_sub_length(rr, n);
+ SSL3_RECORD_add_off(rr, n);
+ if (SSL3_RECORD_get_length(rr) == 0) {
+ s->rlayer.rstate = SSL_ST_READ_HEADER;
+ SSL3_RECORD_set_off(rr, 0);
+ }
+ }
+#ifndef OPENSSL_NO_SCTP
+ /*
+ * We might had to delay a close_notify alert because of reordered
+ * app data. If there was an alert and there is no message to read
+ * anymore, finally set shutdown.
+ */
+ if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
+ s->d1->shutdown_received
+ && !BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) {
+ s->shutdown |= SSL_RECEIVED_SHUTDOWN;
+ return (0);
+ }
+#endif
+ return (n);
+ }
+
+ /*
+ * If we get here, then type != rr->type; if we have a handshake message,
+ * then it was unexpected (Hello Request or Client Hello).
+ */
+
+ /*
+ * In case of record types for which we have 'fragment' storage, fill
+ * that so that we can process the data at a fixed place.
+ */
+ {
+ unsigned int k, dest_maxlen = 0;
+ unsigned char *dest = NULL;
+ unsigned int *dest_len = NULL;
+
+ if (SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) {
+ dest_maxlen = sizeof(s->rlayer.d->handshake_fragment);
+ dest = s->rlayer.d->handshake_fragment;
+ dest_len = &s->rlayer.d->handshake_fragment_len;
+ } else if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) {
+ dest_maxlen = sizeof(s->rlayer.d->alert_fragment);
+ dest = s->rlayer.d->alert_fragment;
+ dest_len = &s->rlayer.d->alert_fragment_len;
+ }
+#ifndef OPENSSL_NO_HEARTBEATS
+ else if (SSL3_RECORD_get_type(rr) == DTLS1_RT_HEARTBEAT) {
+ /* We allow a 0 return */
+ if (dtls1_process_heartbeat(s, SSL3_RECORD_get_data(rr),
+ SSL3_RECORD_get_length(rr)) < 0) {
+ return -1;
+ }
+ /* Exit and notify application to read again */
+ SSL3_RECORD_set_length(rr, 0);
+ s->rwstate = SSL_READING;
+ BIO_clear_retry_flags(SSL_get_rbio(s));
+ BIO_set_retry_read(SSL_get_rbio(s));
+ return (-1);
+ }
+#endif
+ /* else it's a CCS message, or application data or wrong */
+ else if (SSL3_RECORD_get_type(rr) != SSL3_RT_CHANGE_CIPHER_SPEC) {
+ /*
+ * Application data while renegotiating is allowed. Try again
+ * reading.
+ */
+ if (SSL3_RECORD_get_type(rr) == SSL3_RT_APPLICATION_DATA) {
+ BIO *bio;
+ s->s3->in_read_app_data = 2;
+ bio = SSL_get_rbio(s);
+ s->rwstate = SSL_READING;
+ BIO_clear_retry_flags(bio);
+ BIO_set_retry_read(bio);
+ return (-1);
+ }
+
+ /* Not certain if this is the right error handling */
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD);
+ goto f_err;
+ }
+
+ if (dest_maxlen > 0) {
+ /*
+ * XDTLS: In a pathological case, the Client Hello may be
+ * fragmented--don't always expect dest_maxlen bytes
+ */
+ if (SSL3_RECORD_get_length(rr) < dest_maxlen) {
+#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
+ /*
+ * for normal alerts rr->length is 2, while
+ * dest_maxlen is 7 if we were to handle this
+ * non-existing alert...
+ */
+ FIX ME;
+#endif
+ s->rlayer.rstate = SSL_ST_READ_HEADER;
+ SSL3_RECORD_set_length(rr, 0);
+ goto start;
+ }
+
+ /* now move 'n' bytes: */
+ for (k = 0; k < dest_maxlen; k++) {
+ dest[k] = SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)];
+ SSL3_RECORD_add_off(rr, 1);
+ SSL3_RECORD_add_length(rr, -1);
+ }
+ *dest_len = dest_maxlen;
+ }
+ }
+
+ /*-
+ * s->rlayer.d->handshake_fragment_len == 12 iff rr->type == SSL3_RT_HANDSHAKE;
+ * s->rlayer.d->alert_fragment_len == 7 iff rr->type == SSL3_RT_ALERT.
+ * (Possibly rr is 'empty' now, i.e. rr->length may be 0.)
+ */
+
+ /* If we are a client, check for an incoming 'Hello Request': */
+ if ((!s->server) &&
+ (s->rlayer.d->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
+ (s->rlayer.d->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&
+ (s->session != NULL) && (s->session->cipher != NULL)) {
+ s->rlayer.d->handshake_fragment_len = 0;
+
+ if ((s->rlayer.d->handshake_fragment[1] != 0) ||
+ (s->rlayer.d->handshake_fragment[2] != 0) ||
+ (s->rlayer.d->handshake_fragment[3] != 0)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_BAD_HELLO_REQUEST);
+ goto f_err;
+ }
+
+ /*
+ * no need to check sequence number on HELLO REQUEST messages
+ */
+
+ if (s->msg_callback)
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
+ s->rlayer.d->handshake_fragment, 4, s,
+ s->msg_callback_arg);
+
+ if (SSL_is_init_finished(s) &&
+ (s->options & SSL_OP_NO_RENEGOTIATION) == 0 &&
+ !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&
+ !s->s3->renegotiate) {
+ s->d1->handshake_read_seq++;
+ s->new_session = 1;
+ ssl3_renegotiate(s);
+ if (ssl3_renegotiate_check(s)) {
+ i = s->handshake_func(s);
+ if (i < 0)
+ return (i);
+ if (i == 0) {
+ SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE);
+ return (-1);
+ }
+
+ if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
+ if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) {
+ /* no read-ahead left? */
+ BIO *bio;
+ /*
+ * In the case where we try to read application data,
+ * but we trigger an SSL handshake, we return -1 with
+ * the retry option set. Otherwise renegotiation may
+ * cause nasty problems in the blocking world
+ */
+ s->rwstate = SSL_READING;
+ bio = SSL_get_rbio(s);
+ BIO_clear_retry_flags(bio);
+ BIO_set_retry_read(bio);
+ return (-1);
+ }
+ }
+ }
+ } else {
+ SSL3_RECORD_set_length(rr, 0);
+ ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
+ }
+ /*
+ * we either finished a handshake or ignored the request, now try
+ * again to obtain the (application) data we were asked for
+ */
+ goto start;
+ }
+
+ /*
+ * If we are a server and get a client hello when renegotiation isn't
+ * allowed send back a no renegotiation alert and carry on.
+ */
+ if (s->server
+ && SSL_is_init_finished(s)
+ && s->rlayer.d->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH
+ && s->rlayer.d->handshake_fragment[0] == SSL3_MT_CLIENT_HELLO
+ && s->s3->previous_client_finished_len != 0
+ && ((!s->s3->send_connection_binding
+ && (s->options
+ & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) == 0)
+ || (s->options & SSL_OP_NO_RENEGOTIATION) != 0)) {
+ s->rlayer.d->handshake_fragment_len = 0;
+ SSL3_RECORD_set_length(rr, 0);
+ ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
+ goto start;
+ }
+
+ if (s->rlayer.d->alert_fragment_len >= DTLS1_AL_HEADER_LENGTH) {
+ int alert_level = s->rlayer.d->alert_fragment[0];
+ int alert_descr = s->rlayer.d->alert_fragment[1];
+
+ s->rlayer.d->alert_fragment_len = 0;
+
+ if (s->msg_callback)
+ s->msg_callback(0, s->version, SSL3_RT_ALERT,
+ s->rlayer.d->alert_fragment, 2, s,
+ s->msg_callback_arg);
+
+ if (s->info_callback != NULL)
+ cb = s->info_callback;
+ else if (s->ctx->info_callback != NULL)
+ cb = s->ctx->info_callback;
+
+ if (cb != NULL) {
+ j = (alert_level << 8) | alert_descr;
+ cb(s, SSL_CB_READ_ALERT, j);
+ }
+
+ if (alert_level == SSL3_AL_WARNING) {
+ s->s3->warn_alert = alert_descr;
+
+ s->rlayer.alert_count++;
+ if (s->rlayer.alert_count == MAX_WARN_ALERT_COUNT) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_TOO_MANY_WARN_ALERTS);
+ goto f_err;
+ }
+
+ if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
+#ifndef OPENSSL_NO_SCTP
+ /*
+ * With SCTP and streams the socket may deliver app data
+ * after a close_notify alert. We have to check this first so
+ * that nothing gets discarded.
+ */
+ if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
+ BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) {
+ s->d1->shutdown_received = 1;
+ s->rwstate = SSL_READING;
+ BIO_clear_retry_flags(SSL_get_rbio(s));
+ BIO_set_retry_read(SSL_get_rbio(s));
+ return -1;
+ }
+#endif
+ s->shutdown |= SSL_RECEIVED_SHUTDOWN;
+ return (0);
+ }
+#if 0
+ /* XXX: this is a possible improvement in the future */
+ /* now check if it's a missing record */
+ if (alert_descr == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE) {
+ unsigned short seq;
+ unsigned int frag_off;
+ unsigned char *p = &(s->rlayer.d->alert_fragment[2]);
+
+ n2s(p, seq);
+ n2l3(p, frag_off);
+
+ dtls1_retransmit_message(s,
+ dtls1_get_queue_priority
+ (frag->msg_header.seq, 0), frag_off,
+ &found);
+ if (!found && SSL_in_init(s)) {
+ /*
+ * fprintf( stderr,"in init = %d\n", SSL_in_init(s));
+ */
+ /*
+ * requested a message not yet sent, send an alert
+ * ourselves
+ */
+ ssl3_send_alert(s, SSL3_AL_WARNING,
+ DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
+ }
+ }
+#endif
+ } else if (alert_level == SSL3_AL_FATAL) {
+ char tmp[16];
+
+ s->rwstate = SSL_NOTHING;
+ s->s3->fatal_alert = alert_descr;
+ SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_AD_REASON_OFFSET + alert_descr);
+ BIO_snprintf(tmp, sizeof(tmp), "%d", alert_descr);
+ ERR_add_error_data(2, "SSL alert number ", tmp);
+ s->shutdown |= SSL_RECEIVED_SHUTDOWN;
+ SSL_CTX_remove_session(s->session_ctx, s->session);
+ return (0);
+ } else {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNKNOWN_ALERT_TYPE);
+ goto f_err;
+ }
+
+ goto start;
+ }
+
+ if (s->shutdown & SSL_SENT_SHUTDOWN) { /* but we have not received a
+ * shutdown */
+ s->rwstate = SSL_NOTHING;
+ SSL3_RECORD_set_length(rr, 0);
+ return (0);
+ }
+
+ if (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC) {
+ /*
+ * We can't process a CCS now, because previous handshake messages
+ * are still missing, so just drop it.
+ */
+ SSL3_RECORD_set_length(rr, 0);
+ goto start;
+ }
+
+ /*
+ * Unexpected handshake message (Client Hello, or protocol violation)
+ */
+ if ((s->rlayer.d->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
+ !ossl_statem_get_in_handshake(s)) {
+ struct hm_header_st msg_hdr;
+
+ /* this may just be a stale retransmit */
+ dtls1_get_message_header(rr->data, &msg_hdr);
+ if (SSL3_RECORD_get_epoch(rr) != s->rlayer.d->r_epoch) {
+ SSL3_RECORD_set_length(rr, 0);
+ goto start;
+ }
+
+ /*
+ * If we are server, we may have a repeated FINISHED of the client
+ * here, then retransmit our CCS and FINISHED.
+ */
+ if (msg_hdr.type == SSL3_MT_FINISHED) {
+ if (dtls1_check_timeout_num(s) < 0)
+ return -1;
+
+ dtls1_retransmit_buffered_messages(s);
+ SSL3_RECORD_set_length(rr, 0);
+ goto start;
+ }
+
+ if (SSL_is_init_finished(s) &&
+ !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) {
+ ossl_statem_set_in_init(s, 1);
+ s->renegotiate = 1;
+ s->new_session = 1;
+ }
+ i = s->handshake_func(s);
+ if (i < 0)
+ return (i);
+ if (i == 0) {
+ SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE);
+ return (-1);
+ }
+
+ if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
+ if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) {
+ /* no read-ahead left? */
+ BIO *bio;
+ /*
+ * In the case where we try to read application data, but we
+ * trigger an SSL handshake, we return -1 with the retry
+ * option set. Otherwise renegotiation may cause nasty
+ * problems in the blocking world
+ */
+ s->rwstate = SSL_READING;
+ bio = SSL_get_rbio(s);
+ BIO_clear_retry_flags(bio);
+ BIO_set_retry_read(bio);
+ return (-1);
+ }
+ }
+ goto start;
+ }
+
+ switch (SSL3_RECORD_get_type(rr)) {
+ default:
+ /* TLS just ignores unknown message types */
+ if (s->version == TLS1_VERSION) {
+ SSL3_RECORD_set_length(rr, 0);
+ goto start;
+ }
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD);
+ goto f_err;
+ case SSL3_RT_CHANGE_CIPHER_SPEC:
+ case SSL3_RT_ALERT:
+ case SSL3_RT_HANDSHAKE:
+ /*
+ * we already handled all of these, with the possible exception of
+ * SSL3_RT_HANDSHAKE when ossl_statem_get_in_handshake(s) is true, but
+ * that should not happen when type != rr->type
+ */
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ case SSL3_RT_APPLICATION_DATA:
+ /*
+ * At this point, we were expecting handshake data, but have
+ * application data. If the library was running inside ssl3_read()
+ * (i.e. in_read_app_data is set) and it makes sense to read
+ * application data at this point (session renegotiation not yet
+ * started), we will indulge it.
+ */
+ if (s->s3->in_read_app_data &&
+ (s->s3->total_renegotiations != 0) &&
+ ossl_statem_app_data_allowed(s)) {
+ s->s3->in_read_app_data = 2;
+ return (-1);
+ } else {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD);
+ goto f_err;
+ }
+ }
+ /* not reached */
+
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ return (-1);
+}
+
+ /*
+ * this only happens when a client hello is received and a handshake
+ * is started.
+ */
+static int have_handshake_fragment(SSL *s, int type, unsigned char *buf,
+ int len)
+{
+
+ if ((type == SSL3_RT_HANDSHAKE)
+ && (s->rlayer.d->handshake_fragment_len > 0))
+ /* (partially) satisfy request from storage */
+ {
+ unsigned char *src = s->rlayer.d->handshake_fragment;
+ unsigned char *dst = buf;
+ unsigned int k, n;
+
+ /* peek == 0 */
+ n = 0;
+ while ((len > 0) && (s->rlayer.d->handshake_fragment_len > 0)) {
+ *dst++ = *src++;
+ len--;
+ s->rlayer.d->handshake_fragment_len--;
+ n++;
+ }
+ /* move any remaining fragment bytes: */
+ for (k = 0; k < s->rlayer.d->handshake_fragment_len; k++)
+ s->rlayer.d->handshake_fragment[k] = *src++;
+ return n;
+ }
+
+ return 0;
+}
+
+/*
+ * Call this to write data in records of type 'type' It will return <= 0 if
+ * not all data has been sent or non-blocking IO.
+ */
+int dtls1_write_bytes(SSL *s, int type, const void *buf, int len)
+{
+ int i;
+
+ OPENSSL_assert(len <= SSL3_RT_MAX_PLAIN_LENGTH);
+ s->rwstate = SSL_NOTHING;
+ i = do_dtls1_write(s, type, buf, len, 0);
+ return i;
+}
+
+int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
+ unsigned int len, int create_empty_fragment)
+{
+ unsigned char *p, *pseq;
+ int i, mac_size, clear = 0;
+ int prefix_len = 0;
+ int eivlen;
+ SSL3_RECORD wr;
+ SSL3_BUFFER *wb;
+ SSL_SESSION *sess;
+
+ wb = &s->rlayer.wbuf[0];
+
+ /*
+ * first check if there is a SSL3_BUFFER still being written out. This
+ * will happen with non blocking IO
+ */
+ if (SSL3_BUFFER_get_left(wb) != 0) {
+ OPENSSL_assert(0); /* XDTLS: want to see if we ever get here */
+ return (ssl3_write_pending(s, type, buf, len));
+ }
+
+ /* If we have an alert to send, lets send it */
+ if (s->s3->alert_dispatch) {
+ i = s->method->ssl_dispatch_alert(s);
+ if (i <= 0)
+ return (i);
+ /* if it went, fall through and send more stuff */
+ }
+
+ if (len == 0 && !create_empty_fragment)
+ return 0;
+
+ if (len > s->max_send_fragment) {
+ SSLerr(SSL_F_DO_DTLS1_WRITE, SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE);
+ return 0;
+ }
+
+ sess = s->session;
+
+ if ((sess == NULL) ||
+ (s->enc_write_ctx == NULL) || (EVP_MD_CTX_md(s->write_hash) == NULL))
+ clear = 1;
+
+ if (clear)
+ mac_size = 0;
+ else {
+ mac_size = EVP_MD_CTX_size(s->write_hash);
+ if (mac_size < 0)
+ goto err;
+ }
+
+ p = SSL3_BUFFER_get_buf(wb) + prefix_len;
+
+ /* write the header */
+
+ *(p++) = type & 0xff;
+ SSL3_RECORD_set_type(&wr, type);
+ /*
+ * Special case: for hello verify request, client version 1.0 and we
+ * haven't decided which version to use yet send back using version 1.0
+ * header: otherwise some clients will ignore it.
+ */
+ if (s->method->version == DTLS_ANY_VERSION &&
+ s->max_proto_version != DTLS1_BAD_VER) {
+ *(p++) = DTLS1_VERSION >> 8;
+ *(p++) = DTLS1_VERSION & 0xff;
+ } else {
+ *(p++) = s->version >> 8;
+ *(p++) = s->version & 0xff;
+ }
+
+ /* field where we are to write out packet epoch, seq num and len */
+ pseq = p;
+ p += 10;
+
+ /* Explicit IV length, block ciphers appropriate version flag */
+ if (s->enc_write_ctx) {
+ int mode = EVP_CIPHER_CTX_mode(s->enc_write_ctx);
+ if (mode == EVP_CIPH_CBC_MODE) {
+ eivlen = EVP_CIPHER_CTX_iv_length(s->enc_write_ctx);
+ if (eivlen <= 1)
+ eivlen = 0;
+ }
+ /* Need explicit part of IV for GCM mode */
+ else if (mode == EVP_CIPH_GCM_MODE)
+ eivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ else if (mode == EVP_CIPH_CCM_MODE)
+ eivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ else
+ eivlen = 0;
+ } else
+ eivlen = 0;
+
+ /* lets setup the record stuff. */
+ SSL3_RECORD_set_data(&wr, p + eivlen); /* make room for IV in case of CBC */
+ SSL3_RECORD_set_length(&wr, (int)len);
+ SSL3_RECORD_set_input(&wr, (unsigned char *)buf);
+
+ /*
+ * we now 'read' from wr.input, wr.length bytes into wr.data
+ */
+
+ /* first we compress */
+ if (s->compress != NULL) {
+ if (!ssl3_do_compress(s, &wr)) {
+ SSLerr(SSL_F_DO_DTLS1_WRITE, SSL_R_COMPRESSION_FAILURE);
+ goto err;
+ }
+ } else {
+ memcpy(SSL3_RECORD_get_data(&wr), SSL3_RECORD_get_input(&wr),
+ SSL3_RECORD_get_length(&wr));
+ SSL3_RECORD_reset_input(&wr);
+ }
+
+ /*
+ * we should still have the output to wr.data and the input from
+ * wr.input. Length should be wr.length. wr.data still points in the
+ * wb->buf
+ */
+
+ if (mac_size != 0) {
+ if (s->method->ssl3_enc->mac(s, &wr,
+ &(p[SSL3_RECORD_get_length(&wr) + eivlen]),
+ 1) < 0)
+ goto err;
+ SSL3_RECORD_add_length(&wr, mac_size);
+ }
+
+ /* this is true regardless of mac size */
+ SSL3_RECORD_set_data(&wr, p);
+ SSL3_RECORD_reset_input(&wr);
+
+ if (eivlen)
+ SSL3_RECORD_add_length(&wr, eivlen);
+
+ if (s->method->ssl3_enc->enc(s, &wr, 1, 1) < 1)
+ goto err;
+
+ /* record length after mac and block padding */
+ /*
+ * if (type == SSL3_RT_APPLICATION_DATA || (type == SSL3_RT_ALERT && !
+ * SSL_in_init(s)))
+ */
+
+ /* there's only one epoch between handshake and app data */
+
+ s2n(s->rlayer.d->w_epoch, pseq);
+
+ /* XDTLS: ?? */
+ /*
+ * else s2n(s->d1->handshake_epoch, pseq);
+ */
+
+ memcpy(pseq, &(s->rlayer.write_sequence[2]), 6);
+ pseq += 6;
+ s2n(SSL3_RECORD_get_length(&wr), pseq);
+
+ if (s->msg_callback)
+ s->msg_callback(1, 0, SSL3_RT_HEADER, pseq - DTLS1_RT_HEADER_LENGTH,
+ DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg);
+
+ /*
+ * we should now have wr.data pointing to the encrypted data, which is
+ * wr->length long
+ */
+ SSL3_RECORD_set_type(&wr, type); /* not needed but helps for debugging */
+ SSL3_RECORD_add_length(&wr, DTLS1_RT_HEADER_LENGTH);
+
+ ssl3_record_sequence_update(&(s->rlayer.write_sequence[0]));
+
+ if (create_empty_fragment) {
+ /*
+ * we are in a recursive call; just return the length, don't write
+ * out anything here
+ */
+ return wr.length;
+ }
+
+ /* now let's set up wb */
+ SSL3_BUFFER_set_left(wb, prefix_len + SSL3_RECORD_get_length(&wr));
+ SSL3_BUFFER_set_offset(wb, 0);
+
+ /*
+ * memorize arguments so that ssl3_write_pending can detect bad write
+ * retries later
+ */
+ s->rlayer.wpend_tot = len;
+ s->rlayer.wpend_buf = buf;
+ s->rlayer.wpend_type = type;
+ s->rlayer.wpend_ret = len;
+
+ /* we now just need to write the buffer */
+ return ssl3_write_pending(s, type, buf, len);
+ err:
+ return -1;
+}
+
+DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
+ unsigned int *is_next_epoch)
+{
+
+ *is_next_epoch = 0;
+
+ /* In current epoch, accept HM, CCS, DATA, & ALERT */
+ if (rr->epoch == s->rlayer.d->r_epoch)
+ return &s->rlayer.d->bitmap;
+
+ /*
+ * Only HM and ALERT messages can be from the next epoch and only if we
+ * have already processed all of the unprocessed records from the last
+ * epoch
+ */
+ else if (rr->epoch == (unsigned long)(s->rlayer.d->r_epoch + 1) &&
+ s->rlayer.d->unprocessed_rcds.epoch != s->rlayer.d->r_epoch &&
+ (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) {
+ *is_next_epoch = 1;
+ return &s->rlayer.d->next_bitmap;
+ }
+
+ return NULL;
+}
+
+void dtls1_reset_seq_numbers(SSL *s, int rw)
+{
+ unsigned char *seq;
+ unsigned int seq_bytes = sizeof(s->rlayer.read_sequence);
+
+ if (rw & SSL3_CC_READ) {
+ seq = s->rlayer.read_sequence;
+ s->rlayer.d->r_epoch++;
+ memcpy(&s->rlayer.d->bitmap, &s->rlayer.d->next_bitmap,
+ sizeof(s->rlayer.d->bitmap));
+ memset(&s->rlayer.d->next_bitmap, 0, sizeof(s->rlayer.d->next_bitmap));
+
+ /*
+ * We must not use any buffered messages received from the previous
+ * epoch
+ */
+ dtls1_clear_received_buffer(s);
+ } else {
+ seq = s->rlayer.write_sequence;
+ memcpy(s->rlayer.d->last_write_sequence, seq,
+ sizeof(s->rlayer.write_sequence));
+ s->rlayer.d->w_epoch++;
+ }
+
+ memset(seq, 0, seq_bytes);
+}
diff --git a/openssl-1.1.0h/ssl/record/rec_layer_s3.c b/openssl-1.1.0h/ssl/record/rec_layer_s3.c
new file mode 100644
index 0000000..1ffc120
--- /dev/null
+++ b/openssl-1.1.0h/ssl/record/rec_layer_s3.c
@@ -0,0 +1,1549 @@
+/*
+ * Copyright 1995-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
+ */
+
+#include <stdio.h>
+#include <limits.h>
+#include <errno.h>
+#define USE_SOCKETS
+#include "../ssl_locl.h"
+#include <openssl/evp.h>
+#include <openssl/buffer.h>
+#include <openssl/rand.h>
+#include "record_locl.h"
+
+#if defined(OPENSSL_SMALL_FOOTPRINT) || \
+ !( defined(AES_ASM) && ( \
+ defined(__x86_64) || defined(__x86_64__) || \
+ defined(_M_AMD64) || defined(_M_X64) ) \
+ )
+# undef EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
+# define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0
+#endif
+
+void RECORD_LAYER_init(RECORD_LAYER *rl, SSL *s)
+{
+ rl->s = s;
+ RECORD_LAYER_set_first_record(&s->rlayer);
+ SSL3_RECORD_clear(rl->rrec, SSL_MAX_PIPELINES);
+}
+
+void RECORD_LAYER_clear(RECORD_LAYER *rl)
+{
+ rl->rstate = SSL_ST_READ_HEADER;
+
+ /*
+ * Do I need to clear read_ahead? As far as I can tell read_ahead did not
+ * previously get reset by SSL_clear...so I'll keep it that way..but is
+ * that right?
+ */
+
+ rl->packet = NULL;
+ rl->packet_length = 0;
+ rl->wnum = 0;
+ memset(rl->alert_fragment, 0, sizeof(rl->alert_fragment));
+ rl->alert_fragment_len = 0;
+ memset(rl->handshake_fragment, 0, sizeof(rl->handshake_fragment));
+ rl->handshake_fragment_len = 0;
+ rl->wpend_tot = 0;
+ rl->wpend_type = 0;
+ rl->wpend_ret = 0;
+ rl->wpend_buf = NULL;
+
+ SSL3_BUFFER_clear(&rl->rbuf);
+ ssl3_release_write_buffer(rl->s);
+ rl->numrpipes = 0;
+ SSL3_RECORD_clear(rl->rrec, SSL_MAX_PIPELINES);
+
+ RECORD_LAYER_reset_read_sequence(rl);
+ RECORD_LAYER_reset_write_sequence(rl);
+
+ if (rl->d)
+ DTLS_RECORD_LAYER_clear(rl);
+}
+
+void RECORD_LAYER_release(RECORD_LAYER *rl)
+{
+ if (SSL3_BUFFER_is_initialised(&rl->rbuf))
+ ssl3_release_read_buffer(rl->s);
+ if (rl->numwpipes > 0)
+ ssl3_release_write_buffer(rl->s);
+ SSL3_RECORD_release(rl->rrec, SSL_MAX_PIPELINES);
+}
+
+/* Checks if we have unprocessed read ahead data pending */
+int RECORD_LAYER_read_pending(const RECORD_LAYER *rl)
+{
+ return SSL3_BUFFER_get_left(&rl->rbuf) != 0;
+}
+
+/* Checks if we have decrypted unread record data pending */
+int RECORD_LAYER_processed_read_pending(const RECORD_LAYER *rl)
+{
+ size_t curr_rec = 0, num_recs = RECORD_LAYER_get_numrpipes(rl);
+ const SSL3_RECORD *rr = rl->rrec;
+
+ while (curr_rec < num_recs && SSL3_RECORD_is_read(&rr[curr_rec]))
+ curr_rec++;
+
+ return curr_rec < num_recs;
+}
+
+int RECORD_LAYER_write_pending(const RECORD_LAYER *rl)
+{
+ return (rl->numwpipes > 0)
+ && SSL3_BUFFER_get_left(&rl->wbuf[rl->numwpipes - 1]) != 0;
+}
+
+int RECORD_LAYER_set_data(RECORD_LAYER *rl, const unsigned char *buf, int len)
+{
+ rl->packet_length = len;
+ if (len != 0) {
+ rl->rstate = SSL_ST_READ_HEADER;
+ if (!SSL3_BUFFER_is_initialised(&rl->rbuf))
+ if (!ssl3_setup_read_buffer(rl->s))
+ return 0;
+ }
+
+ rl->packet = SSL3_BUFFER_get_buf(&rl->rbuf);
+ SSL3_BUFFER_set_data(&rl->rbuf, buf, len);
+
+ return 1;
+}
+
+void RECORD_LAYER_reset_read_sequence(RECORD_LAYER *rl)
+{
+ memset(rl->read_sequence, 0, sizeof(rl->read_sequence));
+}
+
+void RECORD_LAYER_reset_write_sequence(RECORD_LAYER *rl)
+{
+ memset(rl->write_sequence, 0, sizeof(rl->write_sequence));
+}
+
+int ssl3_pending(const SSL *s)
+{
+ unsigned int i;
+ int num = 0;
+
+ if (s->rlayer.rstate == SSL_ST_READ_BODY)
+ return 0;
+
+ for (i = 0; i < RECORD_LAYER_get_numrpipes(&s->rlayer); i++) {
+ if (SSL3_RECORD_get_type(&s->rlayer.rrec[i])
+ != SSL3_RT_APPLICATION_DATA)
+ return 0;
+ num += SSL3_RECORD_get_length(&s->rlayer.rrec[i]);
+ }
+
+ return num;
+}
+
+void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len)
+{
+ ctx->default_read_buf_len = len;
+}
+
+void SSL_set_default_read_buffer_len(SSL *s, size_t len)
+{
+ SSL3_BUFFER_set_default_len(RECORD_LAYER_get_rbuf(&s->rlayer), len);
+}
+
+const char *SSL_rstate_string_long(const SSL *s)
+{
+ switch (s->rlayer.rstate) {
+ case SSL_ST_READ_HEADER:
+ return "read header";
+ case SSL_ST_READ_BODY:
+ return "read body";
+ case SSL_ST_READ_DONE:
+ return "read done";
+ default:
+ return "unknown";
+ }
+}
+
+const char *SSL_rstate_string(const SSL *s)
+{
+ switch (s->rlayer.rstate) {
+ case SSL_ST_READ_HEADER:
+ return "RH";
+ case SSL_ST_READ_BODY:
+ return "RB";
+ case SSL_ST_READ_DONE:
+ return "RD";
+ default:
+ return "unknown";
+ }
+}
+
+/*
+ * Return values are as per SSL_read()
+ */
+int ssl3_read_n(SSL *s, int n, int max, int extend, int clearold)
+{
+ /*
+ * If extend == 0, obtain new n-byte packet; if extend == 1, increase
+ * packet by another n bytes. The packet will be in the sub-array of
+ * s->s3->rbuf.buf specified by s->packet and s->packet_length. (If
+ * s->rlayer.read_ahead is set, 'max' bytes may be stored in rbuf [plus
+ * s->packet_length bytes if extend == 1].)
+ * if clearold == 1, move the packet to the start of the buffer; if
+ * clearold == 0 then leave any old packets where they were
+ */
+ int i, len, left;
+ size_t align = 0;
+ unsigned char *pkt;
+ SSL3_BUFFER *rb;
+
+ if (n <= 0)
+ return n;
+
+ rb = &s->rlayer.rbuf;
+ if (rb->buf == NULL)
+ if (!ssl3_setup_read_buffer(s))
+ return -1;
+
+ left = rb->left;
+#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
+ align = (size_t)rb->buf + SSL3_RT_HEADER_LENGTH;
+ align = SSL3_ALIGN_PAYLOAD - 1 - ((align - 1) % SSL3_ALIGN_PAYLOAD);
+#endif
+
+ if (!extend) {
+ /* start with empty packet ... */
+ if (left == 0)
+ rb->offset = align;
+ else if (align != 0 && left >= SSL3_RT_HEADER_LENGTH) {
+ /*
+ * check if next packet length is large enough to justify payload
+ * alignment...
+ */
+ pkt = rb->buf + rb->offset;
+ if (pkt[0] == SSL3_RT_APPLICATION_DATA
+ && (pkt[3] << 8 | pkt[4]) >= 128) {
+ /*
+ * Note that even if packet is corrupted and its length field
+ * is insane, we can only be led to wrong decision about
+ * whether memmove will occur or not. Header values has no
+ * effect on memmove arguments and therefore no buffer
+ * overrun can be triggered.
+ */
+ memmove(rb->buf + align, pkt, left);
+ rb->offset = align;
+ }
+ }
+ s->rlayer.packet = rb->buf + rb->offset;
+ s->rlayer.packet_length = 0;
+ /* ... now we can act as if 'extend' was set */
+ }
+
+ len = s->rlayer.packet_length;
+ pkt = rb->buf + align;
+ /*
+ * Move any available bytes to front of buffer: 'len' bytes already
+ * pointed to by 'packet', 'left' extra ones at the end
+ */
+ if (s->rlayer.packet != pkt && clearold == 1) {
+ memmove(pkt, s->rlayer.packet, len + left);
+ s->rlayer.packet = pkt;
+ rb->offset = len + align;
+ }
+
+ /*
+ * For DTLS/UDP reads should not span multiple packets because the read
+ * operation returns the whole packet at once (as long as it fits into
+ * the buffer).
+ */
+ if (SSL_IS_DTLS(s)) {
+ if (left == 0 && extend)
+ return 0;
+ if (left > 0 && n > left)
+ n = left;
+ }
+
+ /* if there is enough in the buffer from a previous read, take some */
+ if (left >= n) {
+ s->rlayer.packet_length += n;
+ rb->left = left - n;
+ rb->offset += n;
+ return (n);
+ }
+
+ /* else we need to read more data */
+
+ if (n > (int)(rb->len - rb->offset)) { /* does not happen */
+ SSLerr(SSL_F_SSL3_READ_N, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ /* We always act like read_ahead is set for DTLS */
+ if (!s->rlayer.read_ahead && !SSL_IS_DTLS(s))
+ /* ignore max parameter */
+ max = n;
+ else {
+ if (max < n)
+ max = n;
+ if (max > (int)(rb->len - rb->offset))
+ max = rb->len - rb->offset;
+ }
+
+ while (left < n) {
+ /*
+ * Now we have len+left bytes at the front of s->s3->rbuf.buf and
+ * need to read in more until we have len+n (up to len+max if
+ * possible)
+ */
+
+ clear_sys_error();
+ if (s->rbio != NULL) {
+ s->rwstate = SSL_READING;
+ i = BIO_read(s->rbio, pkt + len + left, max - left);
+ } else {
+ SSLerr(SSL_F_SSL3_READ_N, SSL_R_READ_BIO_NOT_SET);
+ i = -1;
+ }
+
+ if (i <= 0) {
+ rb->left = left;
+ if (s->mode & SSL_MODE_RELEASE_BUFFERS && !SSL_IS_DTLS(s))
+ if (len + left == 0)
+ ssl3_release_read_buffer(s);
+ return i;
+ }
+ left += i;
+ /*
+ * reads should *never* span multiple packets for DTLS because the
+ * underlying transport protocol is message oriented as opposed to
+ * byte oriented as in the TLS case.
+ */
+ if (SSL_IS_DTLS(s)) {
+ if (n > left)
+ n = left; /* makes the while condition false */
+ }
+ }
+
+ /* done reading, now the book-keeping */
+ rb->offset += n;
+ rb->left = left - n;
+ s->rlayer.packet_length += n;
+ s->rwstate = SSL_NOTHING;
+ return (n);
+}
+
+/*
+ * Call this to write data in records of type 'type' It will return <= 0 if
+ * not all data has been sent or non-blocking IO.
+ */
+int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
+{
+ const unsigned char *buf = buf_;
+ int tot;
+ unsigned int n, split_send_fragment, maxpipes;
+#if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
+ unsigned int max_send_fragment, nw;
+ unsigned int u_len = (unsigned int)len;
+#endif
+ SSL3_BUFFER *wb = &s->rlayer.wbuf[0];
+ int i;
+
+ if (len < 0) {
+ SSLerr(SSL_F_SSL3_WRITE_BYTES, SSL_R_SSL_NEGATIVE_LENGTH);
+ return -1;
+ }
+
+ s->rwstate = SSL_NOTHING;
+ tot = s->rlayer.wnum;
+ /*
+ * ensure that if we end up with a smaller value of data to write out
+ * than the the original len from a write which didn't complete for
+ * non-blocking I/O and also somehow ended up avoiding the check for
+ * this in ssl3_write_pending/SSL_R_BAD_WRITE_RETRY as it must never be
+ * possible to end up with (len-tot) as a large number that will then
+ * promptly send beyond the end of the users buffer ... so we trap and
+ * report the error in a way the user will notice
+ */
+ if (((unsigned int)len < s->rlayer.wnum)
+ || ((wb->left != 0) && ((unsigned int)len < (s->rlayer.wnum + s->rlayer.wpend_tot)))) {
+ SSLerr(SSL_F_SSL3_WRITE_BYTES, SSL_R_BAD_LENGTH);
+ return -1;
+ }
+
+ s->rlayer.wnum = 0;
+
+ if (SSL_in_init(s) && !ossl_statem_get_in_handshake(s)) {
+ i = s->handshake_func(s);
+ if (i < 0)
+ return (i);
+ if (i == 0) {
+ SSLerr(SSL_F_SSL3_WRITE_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE);
+ return -1;
+ }
+ }
+
+ /*
+ * first check if there is a SSL3_BUFFER still being written out. This
+ * will happen with non blocking IO
+ */
+ if (wb->left != 0) {
+ i = ssl3_write_pending(s, type, &buf[tot], s->rlayer.wpend_tot);
+ if (i <= 0) {
+ /* XXX should we ssl3_release_write_buffer if i<0? */
+ s->rlayer.wnum = tot;
+ return i;
+ }
+ tot += i; /* this might be last fragment */
+ }
+#if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
+ /*
+ * Depending on platform multi-block can deliver several *times*
+ * better performance. Downside is that it has to allocate
+ * jumbo buffer to accommodate up to 8 records, but the
+ * compromise is considered worthy.
+ */
+ if (type == SSL3_RT_APPLICATION_DATA &&
+ u_len >= 4 * (max_send_fragment = s->max_send_fragment) &&
+ s->compress == NULL && s->msg_callback == NULL &&
+ !SSL_WRITE_ETM(s) && SSL_USE_EXPLICIT_IV(s) &&
+ EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx)) &
+ EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK) {
+ unsigned char aad[13];
+ EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param;
+ int packlen;
+
+ /* minimize address aliasing conflicts */
+ if ((max_send_fragment & 0xfff) == 0)
+ max_send_fragment -= 512;
+
+ if (tot == 0 || wb->buf == NULL) { /* allocate jumbo buffer */
+ ssl3_release_write_buffer(s);
+
+ packlen = EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
+ EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE,
+ max_send_fragment, NULL);
+
+ if (u_len >= 8 * max_send_fragment)
+ packlen *= 8;
+ else
+ packlen *= 4;
+
+ if (!ssl3_setup_write_buffer(s, 1, packlen)) {
+ SSLerr(SSL_F_SSL3_WRITE_BYTES, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ } else if (tot == len) { /* done? */
+ /* free jumbo buffer */
+ ssl3_release_write_buffer(s);
+ return tot;
+ }
+
+ n = (len - tot);
+ for (;;) {
+ if (n < 4 * max_send_fragment) {
+ /* free jumbo buffer */
+ ssl3_release_write_buffer(s);
+ break;
+ }
+
+ if (s->s3->alert_dispatch) {
+ i = s->method->ssl_dispatch_alert(s);
+ if (i <= 0) {
+ s->rlayer.wnum = tot;
+ return i;
+ }
+ }
+
+ if (n >= 8 * max_send_fragment)
+ nw = max_send_fragment * (mb_param.interleave = 8);
+ else
+ nw = max_send_fragment * (mb_param.interleave = 4);
+
+ memcpy(aad, s->rlayer.write_sequence, 8);
+ aad[8] = type;
+ aad[9] = (unsigned char)(s->version >> 8);
+ aad[10] = (unsigned char)(s->version);
+ aad[11] = 0;
+ aad[12] = 0;
+ mb_param.out = NULL;
+ mb_param.inp = aad;
+ mb_param.len = nw;
+
+ packlen = EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
+ EVP_CTRL_TLS1_1_MULTIBLOCK_AAD,
+ sizeof(mb_param), &mb_param);
+
+ if (packlen <= 0 || packlen > (int)wb->len) { /* never happens */
+ /* free jumbo buffer */
+ ssl3_release_write_buffer(s);
+ break;
+ }
+
+ mb_param.out = wb->buf;
+ mb_param.inp = &buf[tot];
+ mb_param.len = nw;
+
+ if (EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
+ EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT,
+ sizeof(mb_param), &mb_param) <= 0)
+ return -1;
+
+ s->rlayer.write_sequence[7] += mb_param.interleave;
+ if (s->rlayer.write_sequence[7] < mb_param.interleave) {
+ int j = 6;
+ while (j >= 0 && (++s->rlayer.write_sequence[j--]) == 0) ;
+ }
+
+ wb->offset = 0;
+ wb->left = packlen;
+
+ s->rlayer.wpend_tot = nw;
+ s->rlayer.wpend_buf = &buf[tot];
+ s->rlayer.wpend_type = type;
+ s->rlayer.wpend_ret = nw;
+
+ i = ssl3_write_pending(s, type, &buf[tot], nw);
+ if (i <= 0) {
+ if (i < 0 && (!s->wbio || !BIO_should_retry(s->wbio))) {
+ /* free jumbo buffer */
+ ssl3_release_write_buffer(s);
+ }
+ s->rlayer.wnum = tot;
+ return i;
+ }
+ if (i == (int)n) {
+ /* free jumbo buffer */
+ ssl3_release_write_buffer(s);
+ return tot + i;
+ }
+ n -= i;
+ tot += i;
+ }
+ } else
+#endif
+ if (tot == len) { /* done? */
+ if (s->mode & SSL_MODE_RELEASE_BUFFERS && !SSL_IS_DTLS(s))
+ ssl3_release_write_buffer(s);
+
+ return tot;
+ }
+
+ n = (len - tot);
+
+ split_send_fragment = s->split_send_fragment;
+ /*
+ * If max_pipelines is 0 then this means "undefined" and we default to
+ * 1 pipeline. Similarly if the cipher does not support pipelined
+ * processing then we also only use 1 pipeline, or if we're not using
+ * explicit IVs
+ */
+ maxpipes = s->max_pipelines;
+ if (maxpipes > SSL_MAX_PIPELINES) {
+ /*
+ * We should have prevented this when we set max_pipelines so we
+ * shouldn't get here
+ */
+ SSLerr(SSL_F_SSL3_WRITE_BYTES, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+ if (maxpipes == 0
+ || s->enc_write_ctx == NULL
+ || !(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx))
+ & EVP_CIPH_FLAG_PIPELINE)
+ || !SSL_USE_EXPLICIT_IV(s))
+ maxpipes = 1;
+ if (s->max_send_fragment == 0 || split_send_fragment > s->max_send_fragment
+ || split_send_fragment == 0) {
+ /*
+ * We should have prevented this when we set the split and max send
+ * fragments so we shouldn't get here
+ */
+ SSLerr(SSL_F_SSL3_WRITE_BYTES, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ for (;;) {
+ unsigned int pipelens[SSL_MAX_PIPELINES], tmppipelen, remain;
+ unsigned int numpipes, j;
+
+ if (n == 0)
+ numpipes = 1;
+ else
+ numpipes = ((n - 1) / split_send_fragment) + 1;
+ if (numpipes > maxpipes)
+ numpipes = maxpipes;
+
+ if (n / numpipes >= s->max_send_fragment) {
+ /*
+ * We have enough data to completely fill all available
+ * pipelines
+ */
+ for (j = 0; j < numpipes; j++) {
+ pipelens[j] = s->max_send_fragment;
+ }
+ } else {
+ /* We can partially fill all available pipelines */
+ tmppipelen = n / numpipes;
+ remain = n % numpipes;
+ for (j = 0; j < numpipes; j++) {
+ pipelens[j] = tmppipelen;
+ if (j < remain)
+ pipelens[j]++;
+ }
+ }
+
+ i = do_ssl3_write(s, type, &(buf[tot]), pipelens, numpipes, 0);
+ if (i <= 0) {
+ /* XXX should we ssl3_release_write_buffer if i<0? */
+ s->rlayer.wnum = tot;
+ return i;
+ }
+
+ if ((i == (int)n) ||
+ (type == SSL3_RT_APPLICATION_DATA &&
+ (s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))) {
+ /*
+ * next chunk of data should get another prepended empty fragment
+ * in ciphersuites with known-IV weakness:
+ */
+ s->s3->empty_fragment_done = 0;
+
+ if ((i == (int)n) && s->mode & SSL_MODE_RELEASE_BUFFERS &&
+ !SSL_IS_DTLS(s))
+ ssl3_release_write_buffer(s);
+
+ return tot + i;
+ }
+
+ n -= i;
+ tot += i;
+ }
+}
+
+int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
+ unsigned int *pipelens, unsigned int numpipes,
+ int create_empty_fragment)
+{
+ unsigned char *outbuf[SSL_MAX_PIPELINES], *plen[SSL_MAX_PIPELINES];
+ SSL3_RECORD wr[SSL_MAX_PIPELINES];
+ int i, mac_size, clear = 0;
+ int prefix_len = 0;
+ int eivlen;
+ size_t align = 0;
+ SSL3_BUFFER *wb;
+ SSL_SESSION *sess;
+ unsigned int totlen = 0;
+ unsigned int j;
+
+ for (j = 0; j < numpipes; j++)
+ totlen += pipelens[j];
+ /*
+ * first check if there is a SSL3_BUFFER still being written out. This
+ * will happen with non blocking IO
+ */
+ if (RECORD_LAYER_write_pending(&s->rlayer))
+ return (ssl3_write_pending(s, type, buf, totlen));
+
+ /* If we have an alert to send, lets send it */
+ if (s->s3->alert_dispatch) {
+ i = s->method->ssl_dispatch_alert(s);
+ if (i <= 0)
+ return (i);
+ /* if it went, fall through and send more stuff */
+ }
+
+ if (s->rlayer.numwpipes < numpipes)
+ if (!ssl3_setup_write_buffer(s, numpipes, 0))
+ return -1;
+
+ if (totlen == 0 && !create_empty_fragment)
+ return 0;
+
+ sess = s->session;
+
+ if ((sess == NULL) ||
+ (s->enc_write_ctx == NULL) || (EVP_MD_CTX_md(s->write_hash) == NULL)) {
+ clear = s->enc_write_ctx ? 0 : 1; /* must be AEAD cipher */
+ mac_size = 0;
+ } else {
+ mac_size = EVP_MD_CTX_size(s->write_hash);
+ if (mac_size < 0)
+ goto err;
+ }
+
+ /*
+ * 'create_empty_fragment' is true only when this function calls itself
+ */
+ if (!clear && !create_empty_fragment && !s->s3->empty_fragment_done) {
+ /*
+ * countermeasure against known-IV weakness in CBC ciphersuites (see
+ * http://www.openssl.org/~bodo/tls-cbc.txt)
+ */
+
+ if (s->s3->need_empty_fragments && type == SSL3_RT_APPLICATION_DATA) {
+ /*
+ * recursive function call with 'create_empty_fragment' set; this
+ * prepares and buffers the data for an empty fragment (these
+ * 'prefix_len' bytes are sent out later together with the actual
+ * payload)
+ */
+ unsigned int tmppipelen = 0;
+
+ prefix_len = do_ssl3_write(s, type, buf, &tmppipelen, 1, 1);
+ if (prefix_len <= 0)
+ goto err;
+
+ if (prefix_len >
+ (SSL3_RT_HEADER_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD)) {
+ /* insufficient space */
+ SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+
+ s->s3->empty_fragment_done = 1;
+ }
+
+ if (create_empty_fragment) {
+ wb = &s->rlayer.wbuf[0];
+#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
+ /*
+ * extra fragment would be couple of cipher blocks, which would be
+ * multiple of SSL3_ALIGN_PAYLOAD, so if we want to align the real
+ * payload, then we can just pretend we simply have two headers.
+ */
+ align = (size_t)SSL3_BUFFER_get_buf(wb) + 2 * SSL3_RT_HEADER_LENGTH;
+ align = SSL3_ALIGN_PAYLOAD - 1 - ((align - 1) % SSL3_ALIGN_PAYLOAD);
+#endif
+ outbuf[0] = SSL3_BUFFER_get_buf(wb) + align;
+ SSL3_BUFFER_set_offset(wb, align);
+ } else if (prefix_len) {
+ wb = &s->rlayer.wbuf[0];
+ outbuf[0] = SSL3_BUFFER_get_buf(wb) + SSL3_BUFFER_get_offset(wb)
+ + prefix_len;
+ } else {
+ for (j = 0; j < numpipes; j++) {
+ wb = &s->rlayer.wbuf[j];
+#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
+ align = (size_t)SSL3_BUFFER_get_buf(wb) + SSL3_RT_HEADER_LENGTH;
+ align = SSL3_ALIGN_PAYLOAD - 1 - ((align - 1) % SSL3_ALIGN_PAYLOAD);
+#endif
+ outbuf[j] = SSL3_BUFFER_get_buf(wb) + align;
+ SSL3_BUFFER_set_offset(wb, align);
+ }
+ }
+
+ /* Explicit IV length, block ciphers appropriate version flag */
+ if (s->enc_write_ctx && SSL_USE_EXPLICIT_IV(s)) {
+ int mode = EVP_CIPHER_CTX_mode(s->enc_write_ctx);
+ if (mode == EVP_CIPH_CBC_MODE) {
+ eivlen = EVP_CIPHER_CTX_iv_length(s->enc_write_ctx);
+ if (eivlen <= 1)
+ eivlen = 0;
+ }
+ /* Need explicit part of IV for GCM mode */
+ else if (mode == EVP_CIPH_GCM_MODE)
+ eivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ else if (mode == EVP_CIPH_CCM_MODE)
+ eivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ else
+ eivlen = 0;
+ } else
+ eivlen = 0;
+
+ totlen = 0;
+ /* Clear our SSL3_RECORD structures */
+ memset(wr, 0, sizeof(wr));
+ for (j = 0; j < numpipes; j++) {
+ /* write the header */
+ *(outbuf[j]++) = type & 0xff;
+ SSL3_RECORD_set_type(&wr[j], type);
+
+ *(outbuf[j]++) = (s->version >> 8);
+ /*
+ * Some servers hang if initial client hello is larger than 256 bytes
+ * and record version number > TLS 1.0
+ */
+ if (SSL_get_state(s) == TLS_ST_CW_CLNT_HELLO
+ && !s->renegotiate && TLS1_get_version(s) > TLS1_VERSION)
+ *(outbuf[j]++) = 0x1;
+ else
+ *(outbuf[j]++) = s->version & 0xff;
+
+ /* field where we are to write out packet length */
+ plen[j] = outbuf[j];
+ outbuf[j] += 2;
+
+ /* lets setup the record stuff. */
+ SSL3_RECORD_set_data(&wr[j], outbuf[j] + eivlen);
+ SSL3_RECORD_set_length(&wr[j], (int)pipelens[j]);
+ SSL3_RECORD_set_input(&wr[j], (unsigned char *)&buf[totlen]);
+ totlen += pipelens[j];
+
+ /*
+ * we now 'read' from wr->input, wr->length bytes into wr->data
+ */
+
+ /* first we compress */
+ if (s->compress != NULL) {
+ if (!ssl3_do_compress(s, &wr[j])) {
+ SSLerr(SSL_F_DO_SSL3_WRITE, SSL_R_COMPRESSION_FAILURE);
+ goto err;
+ }
+ } else {
+ memcpy(wr[j].data, wr[j].input, wr[j].length);
+ SSL3_RECORD_reset_input(&wr[j]);
+ }
+
+ /*
+ * we should still have the output to wr->data and the input from
+ * wr->input. Length should be wr->length. wr->data still points in the
+ * wb->buf
+ */
+
+ if (!SSL_WRITE_ETM(s) && mac_size != 0) {
+ if (s->method->ssl3_enc->mac(s, &wr[j],
+ &(outbuf[j][wr[j].length + eivlen]),
+ 1) < 0)
+ goto err;
+ SSL3_RECORD_add_length(&wr[j], mac_size);
+ }
+
+ SSL3_RECORD_set_data(&wr[j], outbuf[j]);
+ SSL3_RECORD_reset_input(&wr[j]);
+
+ if (eivlen) {
+ /*
+ * if (RAND_pseudo_bytes(p, eivlen) <= 0) goto err;
+ */
+ SSL3_RECORD_add_length(&wr[j], eivlen);
+ }
+ }
+
+ if (s->method->ssl3_enc->enc(s, wr, numpipes, 1) < 1)
+ goto err;
+
+ for (j = 0; j < numpipes; j++) {
+ if (SSL_WRITE_ETM(s) && mac_size != 0) {
+ if (s->method->ssl3_enc->mac(s, &wr[j],
+ outbuf[j] + wr[j].length, 1) < 0)
+ goto err;
+ SSL3_RECORD_add_length(&wr[j], mac_size);
+ }
+
+ /* record length after mac and block padding */
+ s2n(SSL3_RECORD_get_length(&wr[j]), plen[j]);
+
+ if (s->msg_callback)
+ s->msg_callback(1, 0, SSL3_RT_HEADER, plen[j] - 5, 5, s,
+ s->msg_callback_arg);
+
+ /*
+ * we should now have wr->data pointing to the encrypted data, which is
+ * wr->length long
+ */
+ SSL3_RECORD_set_type(&wr[j], type); /* not needed but helps for
+ * debugging */
+ SSL3_RECORD_add_length(&wr[j], SSL3_RT_HEADER_LENGTH);
+
+ if (create_empty_fragment) {
+ /*
+ * we are in a recursive call; just return the length, don't write
+ * out anything here
+ */
+ if (j > 0) {
+ /* We should never be pipelining an empty fragment!! */
+ SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ return SSL3_RECORD_get_length(wr);
+ }
+
+ /* now let's set up wb */
+ SSL3_BUFFER_set_left(&s->rlayer.wbuf[j],
+ prefix_len + SSL3_RECORD_get_length(&wr[j]));
+ }
+
+ /*
+ * memorize arguments so that ssl3_write_pending can detect bad write
+ * retries later
+ */
+ s->rlayer.wpend_tot = totlen;
+ s->rlayer.wpend_buf = buf;
+ s->rlayer.wpend_type = type;
+ s->rlayer.wpend_ret = totlen;
+
+ /* we now just need to write the buffer */
+ return ssl3_write_pending(s, type, buf, totlen);
+ err:
+ return -1;
+}
+
+/* if s->s3->wbuf.left != 0, we need to call this
+ *
+ * Return values are as per SSL_write()
+ */
+int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
+ unsigned int len)
+{
+ int i;
+ SSL3_BUFFER *wb = s->rlayer.wbuf;
+ unsigned int currbuf = 0;
+
+ if ((s->rlayer.wpend_tot > (int)len)
+ || (!(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)
+ && (s->rlayer.wpend_buf != buf))
+ || (s->rlayer.wpend_type != type)) {
+ SSLerr(SSL_F_SSL3_WRITE_PENDING, SSL_R_BAD_WRITE_RETRY);
+ return (-1);
+ }
+
+ for (;;) {
+ /* Loop until we find a buffer we haven't written out yet */
+ if (SSL3_BUFFER_get_left(&wb[currbuf]) == 0
+ && currbuf < s->rlayer.numwpipes - 1) {
+ currbuf++;
+ continue;
+ }
+ clear_sys_error();
+ if (s->wbio != NULL) {
+ s->rwstate = SSL_WRITING;
+ i = BIO_write(s->wbio, (char *)
+ &(SSL3_BUFFER_get_buf(&wb[currbuf])
+ [SSL3_BUFFER_get_offset(&wb[currbuf])]),
+ (unsigned int)SSL3_BUFFER_get_left(&wb[currbuf]));
+ } else {
+ SSLerr(SSL_F_SSL3_WRITE_PENDING, SSL_R_BIO_NOT_SET);
+ i = -1;
+ }
+ if (i == SSL3_BUFFER_get_left(&wb[currbuf])) {
+ SSL3_BUFFER_set_left(&wb[currbuf], 0);
+ SSL3_BUFFER_add_offset(&wb[currbuf], i);
+ if (currbuf + 1 < s->rlayer.numwpipes)
+ continue;
+ s->rwstate = SSL_NOTHING;
+ return (s->rlayer.wpend_ret);
+ } else if (i <= 0) {
+ if (SSL_IS_DTLS(s)) {
+ /*
+ * For DTLS, just drop it. That's kind of the whole point in
+ * using a datagram service
+ */
+ SSL3_BUFFER_set_left(&wb[currbuf], 0);
+ }
+ return i;
+ }
+ SSL3_BUFFER_add_offset(&wb[currbuf], i);
+ SSL3_BUFFER_add_left(&wb[currbuf], -i);
+ }
+}
+
+/*-
+ * Return up to 'len' payload bytes received in 'type' records.
+ * 'type' is one of the following:
+ *
+ * - SSL3_RT_HANDSHAKE (when ssl3_get_message calls us)
+ * - SSL3_RT_APPLICATION_DATA (when ssl3_read calls us)
+ * - 0 (during a shutdown, no data has to be returned)
+ *
+ * If we don't have stored data to work from, read a SSL/TLS record first
+ * (possibly multiple records if we still don't have anything to return).
+ *
+ * This function must handle any surprises the peer may have for us, such as
+ * Alert records (e.g. close_notify) or renegotiation requests. ChangeCipherSpec
+ * messages are treated as if they were handshake messages *if* the |recd_type|
+ * argument is non NULL.
+ * Also if record payloads contain fragments too small to process, we store
+ * them until there is enough for the respective protocol (the record protocol
+ * may use arbitrary fragmentation and even interleaving):
+ * Change cipher spec protocol
+ * just 1 byte needed, no need for keeping anything stored
+ * Alert protocol
+ * 2 bytes needed (AlertLevel, AlertDescription)
+ * Handshake protocol
+ * 4 bytes needed (HandshakeType, uint24 length) -- we just have
+ * to detect unexpected Client Hello and Hello Request messages
+ * here, anything else is handled by higher layers
+ * Application data protocol
+ * none of our business
+ */
+int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
+ int len, int peek)
+{
+ int al, i, j, ret;
+ unsigned int n, curr_rec, num_recs, read_bytes;
+ SSL3_RECORD *rr;
+ SSL3_BUFFER *rbuf;
+ void (*cb) (const SSL *ssl, int type2, int val) = NULL;
+
+ rbuf = &s->rlayer.rbuf;
+
+ if (!SSL3_BUFFER_is_initialised(rbuf)) {
+ /* Not initialized yet */
+ if (!ssl3_setup_read_buffer(s))
+ return (-1);
+ }
+
+ if ((type && (type != SSL3_RT_APPLICATION_DATA)
+ && (type != SSL3_RT_HANDSHAKE)) || (peek
+ && (type !=
+ SSL3_RT_APPLICATION_DATA))) {
+ SSLerr(SSL_F_SSL3_READ_BYTES, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ if ((type == SSL3_RT_HANDSHAKE) && (s->rlayer.handshake_fragment_len > 0))
+ /* (partially) satisfy request from storage */
+ {
+ unsigned char *src = s->rlayer.handshake_fragment;
+ unsigned char *dst = buf;
+ unsigned int k;
+
+ /* peek == 0 */
+ n = 0;
+ while ((len > 0) && (s->rlayer.handshake_fragment_len > 0)) {
+ *dst++ = *src++;
+ len--;
+ s->rlayer.handshake_fragment_len--;
+ n++;
+ }
+ /* move any remaining fragment bytes: */
+ for (k = 0; k < s->rlayer.handshake_fragment_len; k++)
+ s->rlayer.handshake_fragment[k] = *src++;
+
+ if (recvd_type != NULL)
+ *recvd_type = SSL3_RT_HANDSHAKE;
+
+ return n;
+ }
+
+ /*
+ * Now s->rlayer.handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE.
+ */
+
+ if (!ossl_statem_get_in_handshake(s) && SSL_in_init(s)) {
+ /* type == SSL3_RT_APPLICATION_DATA */
+ i = s->handshake_func(s);
+ if (i < 0)
+ return (i);
+ if (i == 0) {
+ SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE);
+ return (-1);
+ }
+ }
+ start:
+ s->rwstate = SSL_NOTHING;
+
+ /*-
+ * For each record 'i' up to |num_recs]
+ * rr[i].type - is the type of record
+ * rr[i].data, - data
+ * rr[i].off, - offset into 'data' for next read
+ * rr[i].length, - number of bytes.
+ */
+ rr = s->rlayer.rrec;
+ num_recs = RECORD_LAYER_get_numrpipes(&s->rlayer);
+
+ do {
+ /* get new records if necessary */
+ if (num_recs == 0) {
+ ret = ssl3_get_record(s);
+ if (ret <= 0)
+ return (ret);
+ num_recs = RECORD_LAYER_get_numrpipes(&s->rlayer);
+ if (num_recs == 0) {
+ /* Shouldn't happen */
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_READ_BYTES, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
+ }
+ /* Skip over any records we have already read */
+ for (curr_rec = 0;
+ curr_rec < num_recs && SSL3_RECORD_is_read(&rr[curr_rec]);
+ curr_rec++) ;
+ if (curr_rec == num_recs) {
+ RECORD_LAYER_set_numrpipes(&s->rlayer, 0);
+ num_recs = 0;
+ curr_rec = 0;
+ }
+ } while (num_recs == 0);
+ rr = &rr[curr_rec];
+
+ /*
+ * Reset the count of consecutive warning alerts if we've got a non-empty
+ * record that isn't an alert.
+ */
+ if (SSL3_RECORD_get_type(rr) != SSL3_RT_ALERT
+ && SSL3_RECORD_get_length(rr) != 0)
+ s->rlayer.alert_count = 0;
+
+ /* we now have a packet which can be read and processed */
+
+ if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
+ * reset by ssl3_get_finished */
+ && (SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE)) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_DATA_BETWEEN_CCS_AND_FINISHED);
+ goto f_err;
+ }
+
+ /*
+ * If the other end has shut down, throw anything we read away (even in
+ * 'peek' mode)
+ */
+ if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
+ SSL3_RECORD_set_length(rr, 0);
+ s->rwstate = SSL_NOTHING;
+ return (0);
+ }
+
+ if (type == SSL3_RECORD_get_type(rr)
+ || (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC
+ && type == SSL3_RT_HANDSHAKE && recvd_type != NULL)) {
+ /*
+ * SSL3_RT_APPLICATION_DATA or
+ * SSL3_RT_HANDSHAKE or
+ * SSL3_RT_CHANGE_CIPHER_SPEC
+ */
+ /*
+ * make sure that we are not getting application data when we are
+ * doing a handshake for the first time
+ */
+ if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) &&
+ (s->enc_read_ctx == NULL)) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_APP_DATA_IN_HANDSHAKE);
+ goto f_err;
+ }
+
+ if (type == SSL3_RT_HANDSHAKE
+ && SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC
+ && s->rlayer.handshake_fragment_len > 0) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_CCS_RECEIVED_EARLY);
+ goto f_err;
+ }
+
+ if (recvd_type != NULL)
+ *recvd_type = SSL3_RECORD_get_type(rr);
+
+ if (len <= 0) {
+ /*
+ * Mark a zero length record as read. This ensures multiple calls to
+ * SSL_read() with a zero length buffer will eventually cause
+ * SSL_pending() to report data as being available.
+ */
+ if (SSL3_RECORD_get_length(rr) == 0)
+ SSL3_RECORD_set_read(rr);
+ return len;
+ }
+
+ read_bytes = 0;
+ do {
+ if ((unsigned int)len - read_bytes > SSL3_RECORD_get_length(rr))
+ n = SSL3_RECORD_get_length(rr);
+ else
+ n = (unsigned int)len - read_bytes;
+
+ memcpy(buf, &(rr->data[rr->off]), n);
+ buf += n;
+ if (peek) {
+ /* Mark any zero length record as consumed CVE-2016-6305 */
+ if (SSL3_RECORD_get_length(rr) == 0)
+ SSL3_RECORD_set_read(rr);
+ } else {
+ SSL3_RECORD_sub_length(rr, n);
+ SSL3_RECORD_add_off(rr, n);
+ if (SSL3_RECORD_get_length(rr) == 0) {
+ s->rlayer.rstate = SSL_ST_READ_HEADER;
+ SSL3_RECORD_set_off(rr, 0);
+ SSL3_RECORD_set_read(rr);
+ }
+ }
+ if (SSL3_RECORD_get_length(rr) == 0
+ || (peek && n == SSL3_RECORD_get_length(rr))) {
+ curr_rec++;
+ rr++;
+ }
+ read_bytes += n;
+ } while (type == SSL3_RT_APPLICATION_DATA && curr_rec < num_recs
+ && read_bytes < (unsigned int)len);
+ if (read_bytes == 0) {
+ /* We must have read empty records. Get more data */
+ goto start;
+ }
+ if (!peek && curr_rec == num_recs
+ && (s->mode & SSL_MODE_RELEASE_BUFFERS)
+ && SSL3_BUFFER_get_left(rbuf) == 0)
+ ssl3_release_read_buffer(s);
+ return read_bytes;
+ }
+
+ /*
+ * If we get here, then type != rr->type; if we have a handshake message,
+ * then it was unexpected (Hello Request or Client Hello) or invalid (we
+ * were actually expecting a CCS).
+ */
+
+ /*
+ * Lets just double check that we've not got an SSLv2 record
+ */
+ if (rr->rec_version == SSL2_VERSION) {
+ /*
+ * Should never happen. ssl3_get_record() should only give us an SSLv2
+ * record back if this is the first packet and we are looking for an
+ * initial ClientHello. Therefore |type| should always be equal to
+ * |rr->type|. If not then something has gone horribly wrong
+ */
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_READ_BYTES, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
+
+ if (s->method->version == TLS_ANY_VERSION
+ && (s->server || rr->type != SSL3_RT_ALERT)) {
+ /*
+ * If we've got this far and still haven't decided on what version
+ * we're using then this must be a client side alert we're dealing with
+ * (we don't allow heartbeats yet). We shouldn't be receiving anything
+ * other than a ClientHello if we are a server.
+ */
+ s->version = rr->rec_version;
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_UNEXPECTED_MESSAGE);
+ goto f_err;
+ }
+
+ /*
+ * In case of record types for which we have 'fragment' storage, fill
+ * that so that we can process the data at a fixed place.
+ */
+ {
+ unsigned int dest_maxlen = 0;
+ unsigned char *dest = NULL;
+ unsigned int *dest_len = NULL;
+
+ if (SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) {
+ dest_maxlen = sizeof(s->rlayer.handshake_fragment);
+ dest = s->rlayer.handshake_fragment;
+ dest_len = &s->rlayer.handshake_fragment_len;
+ } else if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) {
+ dest_maxlen = sizeof(s->rlayer.alert_fragment);
+ dest = s->rlayer.alert_fragment;
+ dest_len = &s->rlayer.alert_fragment_len;
+ }
+
+ if (dest_maxlen > 0) {
+ n = dest_maxlen - *dest_len; /* available space in 'dest' */
+ if (SSL3_RECORD_get_length(rr) < n)
+ n = SSL3_RECORD_get_length(rr); /* available bytes */
+
+ /* now move 'n' bytes: */
+ while (n-- > 0) {
+ dest[(*dest_len)++] =
+ SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)];
+ SSL3_RECORD_add_off(rr, 1);
+ SSL3_RECORD_add_length(rr, -1);
+ }
+
+ if (*dest_len < dest_maxlen) {
+ SSL3_RECORD_set_read(rr);
+ goto start; /* fragment was too small */
+ }
+ }
+ }
+
+ /*-
+ * s->rlayer.handshake_fragment_len == 4 iff rr->type == SSL3_RT_HANDSHAKE;
+ * s->rlayer.alert_fragment_len == 2 iff rr->type == SSL3_RT_ALERT.
+ * (Possibly rr is 'empty' now, i.e. rr->length may be 0.)
+ */
+
+ /* If we are a client, check for an incoming 'Hello Request': */
+ if ((!s->server) &&
+ (s->rlayer.handshake_fragment_len >= 4) &&
+ (s->rlayer.handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&
+ (s->session != NULL) && (s->session->cipher != NULL)) {
+ s->rlayer.handshake_fragment_len = 0;
+
+ if ((s->rlayer.handshake_fragment[1] != 0) ||
+ (s->rlayer.handshake_fragment[2] != 0) ||
+ (s->rlayer.handshake_fragment[3] != 0)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_BAD_HELLO_REQUEST);
+ goto f_err;
+ }
+
+ if (s->msg_callback)
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
+ s->rlayer.handshake_fragment, 4, s,
+ s->msg_callback_arg);
+ if (SSL_is_init_finished(s) &&
+ (s->options & SSL_OP_NO_RENEGOTIATION) == 0 &&
+ !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&
+ !s->s3->renegotiate) {
+ ssl3_renegotiate(s);
+ if (ssl3_renegotiate_check(s)) {
+ i = s->handshake_func(s);
+ if (i < 0)
+ return (i);
+ if (i == 0) {
+ SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE);
+ return (-1);
+ }
+
+ if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
+ if (SSL3_BUFFER_get_left(rbuf) == 0) {
+ /* no read-ahead left? */
+ BIO *bio;
+ /*
+ * In the case where we try to read application data,
+ * but we trigger an SSL handshake, we return -1 with
+ * the retry option set. Otherwise renegotiation may
+ * cause nasty problems in the blocking world
+ */
+ s->rwstate = SSL_READING;
+ bio = SSL_get_rbio(s);
+ BIO_clear_retry_flags(bio);
+ BIO_set_retry_read(bio);
+ return (-1);
+ }
+ }
+ } else {
+ SSL3_RECORD_set_read(rr);
+ }
+ } else {
+ ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
+ SSL3_RECORD_set_read(rr);
+ }
+ /*
+ * we either finished a handshake or ignored the request, now try
+ * again to obtain the (application) data we were asked for
+ */
+ goto start;
+ }
+ /*
+ * If we are a server and get a client hello when renegotiation isn't
+ * allowed send back a no renegotiation alert and carry on.
+ */
+ if (s->server
+ && SSL_is_init_finished(s)
+ && s->version > SSL3_VERSION
+ && s->rlayer.handshake_fragment_len >= SSL3_HM_HEADER_LENGTH
+ && s->rlayer.handshake_fragment[0] == SSL3_MT_CLIENT_HELLO
+ && s->s3->previous_client_finished_len != 0
+ && ((!s->s3->send_connection_binding
+ && (s->options
+ & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) == 0)
+ || (s->options & SSL_OP_NO_RENEGOTIATION) != 0)) {
+ SSL3_RECORD_set_length(rr, 0);
+ SSL3_RECORD_set_read(rr);
+ ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
+ goto start;
+ }
+ if (s->rlayer.alert_fragment_len >= 2) {
+ int alert_level = s->rlayer.alert_fragment[0];
+ int alert_descr = s->rlayer.alert_fragment[1];
+
+ s->rlayer.alert_fragment_len = 0;
+
+ if (s->msg_callback)
+ s->msg_callback(0, s->version, SSL3_RT_ALERT,
+ s->rlayer.alert_fragment, 2, s,
+ s->msg_callback_arg);
+
+ if (s->info_callback != NULL)
+ cb = s->info_callback;
+ else if (s->ctx->info_callback != NULL)
+ cb = s->ctx->info_callback;
+
+ if (cb != NULL) {
+ j = (alert_level << 8) | alert_descr;
+ cb(s, SSL_CB_READ_ALERT, j);
+ }
+
+ if (alert_level == SSL3_AL_WARNING) {
+ s->s3->warn_alert = alert_descr;
+ SSL3_RECORD_set_read(rr);
+
+ s->rlayer.alert_count++;
+ if (s->rlayer.alert_count == MAX_WARN_ALERT_COUNT) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_TOO_MANY_WARN_ALERTS);
+ goto f_err;
+ }
+
+ if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
+ s->shutdown |= SSL_RECEIVED_SHUTDOWN;
+ return (0);
+ }
+ /*
+ * This is a warning but we receive it if we requested
+ * renegotiation and the peer denied it. Terminate with a fatal
+ * alert because if application tried to renegotiate it
+ * presumably had a good reason and expects it to succeed. In
+ * future we might have a renegotiation where we don't care if
+ * the peer refused it where we carry on.
+ */
+ else if (alert_descr == SSL_AD_NO_RENEGOTIATION) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_NO_RENEGOTIATION);
+ goto f_err;
+ }
+#ifdef SSL_AD_MISSING_SRP_USERNAME
+ else if (alert_descr == SSL_AD_MISSING_SRP_USERNAME)
+ return (0);
+#endif
+ } else if (alert_level == SSL3_AL_FATAL) {
+ char tmp[16];
+
+ s->rwstate = SSL_NOTHING;
+ s->s3->fatal_alert = alert_descr;
+ SSLerr(SSL_F_SSL3_READ_BYTES, SSL_AD_REASON_OFFSET + alert_descr);
+ BIO_snprintf(tmp, sizeof(tmp), "%d", alert_descr);
+ ERR_add_error_data(2, "SSL alert number ", tmp);
+ s->shutdown |= SSL_RECEIVED_SHUTDOWN;
+ SSL3_RECORD_set_read(rr);
+ SSL_CTX_remove_session(s->session_ctx, s->session);
+ return (0);
+ } else {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_UNKNOWN_ALERT_TYPE);
+ goto f_err;
+ }
+
+ goto start;
+ }
+
+ if (s->shutdown & SSL_SENT_SHUTDOWN) { /* but we have not received a
+ * shutdown */
+ s->rwstate = SSL_NOTHING;
+ SSL3_RECORD_set_length(rr, 0);
+ SSL3_RECORD_set_read(rr);
+ return (0);
+ }
+
+ if (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_CCS_RECEIVED_EARLY);
+ goto f_err;
+ }
+
+ /*
+ * Unexpected handshake message (Client Hello, or protocol violation)
+ */
+ if ((s->rlayer.handshake_fragment_len >= 4)
+ && !ossl_statem_get_in_handshake(s)) {
+ if (SSL_is_init_finished(s) &&
+ !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) {
+ ossl_statem_set_in_init(s, 1);
+ s->renegotiate = 1;
+ s->new_session = 1;
+ }
+ i = s->handshake_func(s);
+ if (i < 0)
+ return (i);
+ if (i == 0) {
+ SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE);
+ return (-1);
+ }
+
+ if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
+ if (SSL3_BUFFER_get_left(rbuf) == 0) {
+ /* no read-ahead left? */
+ BIO *bio;
+ /*
+ * In the case where we try to read application data, but we
+ * trigger an SSL handshake, we return -1 with the retry
+ * option set. Otherwise renegotiation may cause nasty
+ * problems in the blocking world
+ */
+ s->rwstate = SSL_READING;
+ bio = SSL_get_rbio(s);
+ BIO_clear_retry_flags(bio);
+ BIO_set_retry_read(bio);
+ return (-1);
+ }
+ }
+ goto start;
+ }
+
+ switch (SSL3_RECORD_get_type(rr)) {
+ default:
+ /*
+ * TLS 1.0 and 1.1 say you SHOULD ignore unrecognised record types, but
+ * TLS 1.2 says you MUST send an unexpected message alert. We use the
+ * TLS 1.2 behaviour for all protocol versions to prevent issues where
+ * no progress is being made and the peer continually sends unrecognised
+ * record types, using up resources processing them.
+ */
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_UNEXPECTED_RECORD);
+ goto f_err;
+ case SSL3_RT_CHANGE_CIPHER_SPEC:
+ case SSL3_RT_ALERT:
+ case SSL3_RT_HANDSHAKE:
+ /*
+ * we already handled all of these, with the possible exception of
+ * SSL3_RT_HANDSHAKE when ossl_statem_get_in_handshake(s) is true, but
+ * that should not happen when type != rr->type
+ */
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_SSL3_READ_BYTES, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ case SSL3_RT_APPLICATION_DATA:
+ /*
+ * At this point, we were expecting handshake data, but have
+ * application data. If the library was running inside ssl3_read()
+ * (i.e. in_read_app_data is set) and it makes sense to read
+ * application data at this point (session renegotiation not yet
+ * started), we will indulge it.
+ */
+ if (ossl_statem_app_data_allowed(s)) {
+ s->s3->in_read_app_data = 2;
+ return (-1);
+ } else {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_UNEXPECTED_RECORD);
+ goto f_err;
+ }
+ }
+ /* not reached */
+
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ return (-1);
+}
+
+void ssl3_record_sequence_update(unsigned char *seq)
+{
+ int i;
+
+ for (i = 7; i >= 0; i--) {
+ ++seq[i];
+ if (seq[i] != 0)
+ break;
+ }
+}
+
+/*
+ * Returns true if the current rrec was sent in SSLv2 backwards compatible
+ * format and false otherwise.
+ */
+int RECORD_LAYER_is_sslv2_record(RECORD_LAYER *rl)
+{
+ return SSL3_RECORD_is_sslv2_record(&rl->rrec[0]);
+}
+
+/*
+ * Returns the length in bytes of the current rrec
+ */
+unsigned int RECORD_LAYER_get_rrec_length(RECORD_LAYER *rl)
+{
+ return SSL3_RECORD_get_length(&rl->rrec[0]);
+}
diff --git a/openssl-1.1.0h/ssl/record/record.h b/openssl-1.1.0h/ssl/record/record.h
new file mode 100644
index 0000000..9bb2431
--- /dev/null
+++ b/openssl-1.1.0h/ssl/record/record.h
@@ -0,0 +1,243 @@
+/*
+ * Copyright 1995-2016 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
+ */
+
+/*****************************************************************************
+ * *
+ * These structures should be considered PRIVATE to the record layer. No *
+ * non-record layer code should be using these structures in any way. *
+ * *
+ *****************************************************************************/
+
+typedef struct ssl3_buffer_st {
+ /* at least SSL3_RT_MAX_PACKET_SIZE bytes, see ssl3_setup_buffers() */
+ unsigned char *buf;
+ /* default buffer size (or 0 if no default set) */
+ size_t default_len;
+ /* buffer size */
+ size_t len;
+ /* where to 'copy from' */
+ int offset;
+ /* how many bytes left */
+ int left;
+} SSL3_BUFFER;
+
+#define SEQ_NUM_SIZE 8
+
+typedef struct ssl3_record_st {
+ /* Record layer version */
+ /* r */
+ int rec_version;
+ /* type of record */
+ /* r */
+ int type;
+ /* How many bytes available */
+ /* rw */
+ unsigned int length;
+ /*
+ * How many bytes were available before padding was removed? This is used
+ * to implement the MAC check in constant time for CBC records.
+ */
+ /* rw */
+ unsigned int orig_len;
+ /* read/write offset into 'buf' */
+ /* r */
+ unsigned int off;
+ /* pointer to the record data */
+ /* rw */
+ unsigned char *data;
+ /* where the decode bytes are */
+ /* rw */
+ unsigned char *input;
+ /* only used with decompression - malloc()ed */
+ /* r */
+ unsigned char *comp;
+ /* Whether the data from this record has already been read or not */
+ /* r */
+ unsigned int read;
+ /* epoch number, needed by DTLS1 */
+ /* r */
+ unsigned long epoch;
+ /* sequence number, needed by DTLS1 */
+ /* r */
+ unsigned char seq_num[SEQ_NUM_SIZE];
+} SSL3_RECORD;
+
+typedef struct dtls1_bitmap_st {
+ /* Track 32 packets on 32-bit systems and 64 - on 64-bit systems */
+ unsigned long map;
+ /* Max record number seen so far, 64-bit value in big-endian encoding */
+ unsigned char max_seq_num[SEQ_NUM_SIZE];
+} DTLS1_BITMAP;
+
+typedef struct record_pqueue_st {
+ unsigned short epoch;
+ struct pqueue_st *q;
+} record_pqueue;
+
+typedef struct dtls1_record_data_st {
+ unsigned char *packet;
+ unsigned int packet_length;
+ SSL3_BUFFER rbuf;
+ SSL3_RECORD rrec;
+#ifndef OPENSSL_NO_SCTP
+ struct bio_dgram_sctp_rcvinfo recordinfo;
+#endif
+} DTLS1_RECORD_DATA;
+
+typedef struct dtls_record_layer_st {
+ /*
+ * The current data and handshake epoch. This is initially
+ * undefined, and starts at zero once the initial handshake is
+ * completed
+ */
+ unsigned short r_epoch;
+ unsigned short w_epoch;
+ /* records being received in the current epoch */
+ DTLS1_BITMAP bitmap;
+ /* renegotiation starts a new set of sequence numbers */
+ DTLS1_BITMAP next_bitmap;
+ /* Received handshake records (processed and unprocessed) */
+ record_pqueue unprocessed_rcds;
+ record_pqueue processed_rcds;
+ /*
+ * Buffered application records. Only for records between CCS and
+ * Finished to prevent either protocol violation or unnecessary message
+ * loss.
+ */
+ record_pqueue buffered_app_data;
+ /*
+ * storage for Alert/Handshake protocol data received but not yet
+ * processed by ssl3_read_bytes:
+ */
+ unsigned char alert_fragment[DTLS1_AL_HEADER_LENGTH];
+ unsigned int alert_fragment_len;
+ unsigned char handshake_fragment[DTLS1_HM_HEADER_LENGTH];
+ unsigned int handshake_fragment_len;
+ /* save last and current sequence numbers for retransmissions */
+ unsigned char last_write_sequence[8];
+ unsigned char curr_write_sequence[8];
+} DTLS_RECORD_LAYER;
+
+/*****************************************************************************
+ * *
+ * This structure should be considered "opaque" to anything outside of the *
+ * record layer. No non-record layer code should be accessing the members of *
+ * this structure. *
+ * *
+ *****************************************************************************/
+
+typedef struct record_layer_st {
+ /* The parent SSL structure */
+ SSL *s;
+ /*
+ * Read as many input bytes as possible (for
+ * non-blocking reads)
+ */
+ int read_ahead;
+ /* where we are when reading */
+ int rstate;
+ /* How many pipelines can be used to read data */
+ unsigned int numrpipes;
+ /* How many pipelines can be used to write data */
+ unsigned int numwpipes;
+ /* read IO goes into here */
+ SSL3_BUFFER rbuf;
+ /* write IO goes into here */
+ SSL3_BUFFER wbuf[SSL_MAX_PIPELINES];
+ /* each decoded record goes in here */
+ SSL3_RECORD rrec[SSL_MAX_PIPELINES];
+ /* used internally to point at a raw packet */
+ unsigned char *packet;
+ unsigned int packet_length;
+ /* number of bytes sent so far */
+ unsigned int wnum;
+ /*
+ * storage for Alert/Handshake protocol data received but not yet
+ * processed by ssl3_read_bytes:
+ */
+ unsigned char alert_fragment[2];
+ unsigned int alert_fragment_len;
+ unsigned char handshake_fragment[4];
+ unsigned int handshake_fragment_len;
+ /* The number of consecutive empty records we have received */
+ unsigned int empty_record_count;
+ /* partial write - check the numbers match */
+ /* number bytes written */
+ int wpend_tot;
+ int wpend_type;
+ /* number of bytes submitted */
+ int wpend_ret;
+ const unsigned char *wpend_buf;
+ unsigned char read_sequence[SEQ_NUM_SIZE];
+ unsigned char write_sequence[SEQ_NUM_SIZE];
+ /* Set to true if this is the first record in a connection */
+ unsigned int is_first_record;
+ /* Count of the number of consecutive warning alerts received */
+ unsigned int alert_count;
+ DTLS_RECORD_LAYER *d;
+} RECORD_LAYER;
+
+/*****************************************************************************
+ * *
+ * The following macros/functions represent the libssl internal API to the *
+ * record layer. Any libssl code may call these functions/macros *
+ * *
+ *****************************************************************************/
+
+#define MIN_SSL2_RECORD_LEN 9
+
+#define RECORD_LAYER_set_read_ahead(rl, ra) ((rl)->read_ahead = (ra))
+#define RECORD_LAYER_get_read_ahead(rl) ((rl)->read_ahead)
+#define RECORD_LAYER_get_packet(rl) ((rl)->packet)
+#define RECORD_LAYER_get_packet_length(rl) ((rl)->packet_length)
+#define RECORD_LAYER_add_packet_length(rl, inc) ((rl)->packet_length += (inc))
+#define DTLS_RECORD_LAYER_get_w_epoch(rl) ((rl)->d->w_epoch)
+#define DTLS_RECORD_LAYER_get_processed_rcds(rl) \
+ ((rl)->d->processed_rcds)
+#define DTLS_RECORD_LAYER_get_unprocessed_rcds(rl) \
+ ((rl)->d->unprocessed_rcds)
+
+void RECORD_LAYER_init(RECORD_LAYER *rl, SSL *s);
+void RECORD_LAYER_clear(RECORD_LAYER *rl);
+void RECORD_LAYER_release(RECORD_LAYER *rl);
+int RECORD_LAYER_read_pending(const RECORD_LAYER *rl);
+int RECORD_LAYER_processed_read_pending(const RECORD_LAYER *rl);
+int RECORD_LAYER_write_pending(const RECORD_LAYER *rl);
+int RECORD_LAYER_set_data(RECORD_LAYER *rl, const unsigned char *buf, int len);
+void RECORD_LAYER_reset_read_sequence(RECORD_LAYER *rl);
+void RECORD_LAYER_reset_write_sequence(RECORD_LAYER *rl);
+int RECORD_LAYER_is_sslv2_record(RECORD_LAYER *rl);
+unsigned int RECORD_LAYER_get_rrec_length(RECORD_LAYER *rl);
+__owur int ssl3_pending(const SSL *s);
+__owur int ssl3_write_bytes(SSL *s, int type, const void *buf, int len);
+__owur int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
+ unsigned int *pipelens, unsigned int numpipes,
+ int create_empty_fragment);
+__owur int ssl3_read_bytes(SSL *s, int type, int *recvd_type,
+ unsigned char *buf, int len, int peek);
+__owur int ssl3_setup_buffers(SSL *s);
+__owur int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, unsigned int n_recs, int send);
+__owur int n_ssl3_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int send);
+__owur int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
+ unsigned int len);
+__owur int tls1_enc(SSL *s, SSL3_RECORD *recs, unsigned int n_recs, int send);
+__owur int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int send);
+int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl);
+void DTLS_RECORD_LAYER_free(RECORD_LAYER *rl);
+void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl);
+void DTLS_RECORD_LAYER_set_saved_w_epoch(RECORD_LAYER *rl, unsigned short e);
+void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl);
+void DTLS_RECORD_LAYER_resync_write(RECORD_LAYER *rl);
+void DTLS_RECORD_LAYER_set_write_sequence(RECORD_LAYER *rl, unsigned char *seq);
+__owur int dtls1_read_bytes(SSL *s, int type, int *recvd_type,
+ unsigned char *buf, int len, int peek);
+__owur int dtls1_write_bytes(SSL *s, int type, const void *buf, int len);
+__owur int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
+ unsigned int len, int create_empty_fragement);
+void dtls1_reset_seq_numbers(SSL *s, int rw);
diff --git a/openssl-1.1.0h/ssl/record/record_locl.h b/openssl-1.1.0h/ssl/record/record_locl.h
new file mode 100644
index 0000000..b69afd8
--- /dev/null
+++ b/openssl-1.1.0h/ssl/record/record_locl.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright 1995-2016 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
+ */
+
+/*****************************************************************************
+ * *
+ * The following macros/functions are PRIVATE to the record layer. They *
+ * should NOT be used outside of the record layer. *
+ * *
+ *****************************************************************************/
+
+#define MAX_WARN_ALERT_COUNT 5
+
+/* Functions/macros provided by the RECORD_LAYER component */
+
+#define RECORD_LAYER_get_rbuf(rl) (&(rl)->rbuf)
+#define RECORD_LAYER_get_wbuf(rl) ((rl)->wbuf)
+#define RECORD_LAYER_get_rrec(rl) ((rl)->rrec)
+#define RECORD_LAYER_set_packet(rl, p) ((rl)->packet = (p))
+#define RECORD_LAYER_reset_packet_length(rl) ((rl)->packet_length = 0)
+#define RECORD_LAYER_get_rstate(rl) ((rl)->rstate)
+#define RECORD_LAYER_set_rstate(rl, st) ((rl)->rstate = (st))
+#define RECORD_LAYER_get_read_sequence(rl) ((rl)->read_sequence)
+#define RECORD_LAYER_get_write_sequence(rl) ((rl)->write_sequence)
+#define RECORD_LAYER_get_numrpipes(rl) ((rl)->numrpipes)
+#define RECORD_LAYER_set_numrpipes(rl, n) ((rl)->numrpipes = (n))
+#define RECORD_LAYER_inc_empty_record_count(rl) ((rl)->empty_record_count++)
+#define RECORD_LAYER_reset_empty_record_count(rl) \
+ ((rl)->empty_record_count = 0)
+#define RECORD_LAYER_get_empty_record_count(rl) ((rl)->empty_record_count)
+#define RECORD_LAYER_is_first_record(rl) ((rl)->is_first_record)
+#define RECORD_LAYER_set_first_record(rl) ((rl)->is_first_record = 1)
+#define RECORD_LAYER_clear_first_record(rl) ((rl)->is_first_record = 0)
+#define DTLS_RECORD_LAYER_get_r_epoch(rl) ((rl)->d->r_epoch)
+
+__owur int ssl3_read_n(SSL *s, int n, int max, int extend, int clearold);
+
+void RECORD_LAYER_set_write_sequence(RECORD_LAYER *rl, const unsigned char *ws);
+DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
+ unsigned int *is_next_epoch);
+int dtls1_process_buffered_records(SSL *s);
+int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue);
+int dtls1_buffer_record(SSL *s, record_pqueue *q, unsigned char *priority);
+void ssl3_record_sequence_update(unsigned char *seq);
+
+/* Functions provided by the DTLS1_BITMAP component */
+
+int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap);
+void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap);
+
+/* Macros/functions provided by the SSL3_BUFFER component */
+
+#define SSL3_BUFFER_get_buf(b) ((b)->buf)
+#define SSL3_BUFFER_set_buf(b, n) ((b)->buf = (n))
+#define SSL3_BUFFER_get_len(b) ((b)->len)
+#define SSL3_BUFFER_set_len(b, l) ((b)->len = (l))
+#define SSL3_BUFFER_get_left(b) ((b)->left)
+#define SSL3_BUFFER_set_left(b, l) ((b)->left = (l))
+#define SSL3_BUFFER_add_left(b, l) ((b)->left += (l))
+#define SSL3_BUFFER_get_offset(b) ((b)->offset)
+#define SSL3_BUFFER_set_offset(b, o) ((b)->offset = (o))
+#define SSL3_BUFFER_add_offset(b, o) ((b)->offset += (o))
+#define SSL3_BUFFER_is_initialised(b) ((b)->buf != NULL)
+#define SSL3_BUFFER_set_default_len(b, l) ((b)->default_len = (l))
+
+void SSL3_BUFFER_clear(SSL3_BUFFER *b);
+void SSL3_BUFFER_set_data(SSL3_BUFFER *b, const unsigned char *d, int n);
+void SSL3_BUFFER_release(SSL3_BUFFER *b);
+__owur int ssl3_setup_read_buffer(SSL *s);
+__owur int ssl3_setup_write_buffer(SSL *s, unsigned int numwpipes, size_t len);
+int ssl3_release_read_buffer(SSL *s);
+int ssl3_release_write_buffer(SSL *s);
+
+/* Macros/functions provided by the SSL3_RECORD component */
+
+#define SSL3_RECORD_get_type(r) ((r)->type)
+#define SSL3_RECORD_set_type(r, t) ((r)->type = (t))
+#define SSL3_RECORD_get_length(r) ((r)->length)
+#define SSL3_RECORD_set_length(r, l) ((r)->length = (l))
+#define SSL3_RECORD_add_length(r, l) ((r)->length += (l))
+#define SSL3_RECORD_sub_length(r, l) ((r)->length -= (l))
+#define SSL3_RECORD_get_data(r) ((r)->data)
+#define SSL3_RECORD_set_data(r, d) ((r)->data = (d))
+#define SSL3_RECORD_get_input(r) ((r)->input)
+#define SSL3_RECORD_set_input(r, i) ((r)->input = (i))
+#define SSL3_RECORD_reset_input(r) ((r)->input = (r)->data)
+#define SSL3_RECORD_get_seq_num(r) ((r)->seq_num)
+#define SSL3_RECORD_get_off(r) ((r)->off)
+#define SSL3_RECORD_set_off(r, o) ((r)->off = (o))
+#define SSL3_RECORD_add_off(r, o) ((r)->off += (o))
+#define SSL3_RECORD_get_epoch(r) ((r)->epoch)
+#define SSL3_RECORD_is_sslv2_record(r) \
+ ((r)->rec_version == SSL2_VERSION)
+#define SSL3_RECORD_is_read(r) ((r)->read)
+#define SSL3_RECORD_set_read(r) ((r)->read = 1)
+
+void SSL3_RECORD_clear(SSL3_RECORD *r, unsigned int num_recs);
+void SSL3_RECORD_release(SSL3_RECORD *r, unsigned int num_recs);
+void SSL3_RECORD_set_seq_num(SSL3_RECORD *r, const unsigned char *seq_num);
+int ssl3_get_record(SSL *s);
+__owur int ssl3_do_compress(SSL *ssl, SSL3_RECORD *wr);
+__owur int ssl3_do_uncompress(SSL *ssl, SSL3_RECORD *rr);
+void ssl3_cbc_copy_mac(unsigned char *out,
+ const SSL3_RECORD *rec, unsigned md_size);
+__owur int ssl3_cbc_remove_padding(SSL3_RECORD *rec,
+ unsigned block_size, unsigned mac_size);
+__owur int tls1_cbc_remove_padding(const SSL *s,
+ SSL3_RECORD *rec,
+ unsigned block_size, unsigned mac_size);
+int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap);
+__owur int dtls1_get_record(SSL *s);
diff --git a/openssl-1.1.0h/ssl/record/ssl3_buffer.c b/openssl-1.1.0h/ssl/record/ssl3_buffer.c
new file mode 100644
index 0000000..b6ed771
--- /dev/null
+++ b/openssl-1.1.0h/ssl/record/ssl3_buffer.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright 1995-2016 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
+ */
+
+#include "../ssl_locl.h"
+#include "record_locl.h"
+
+void SSL3_BUFFER_set_data(SSL3_BUFFER *b, const unsigned char *d, int n)
+{
+ if (d != NULL)
+ memcpy(b->buf, d, n);
+ b->left = n;
+ b->offset = 0;
+}
+
+/*
+ * Clear the contents of an SSL3_BUFFER but retain any memory allocated. Also
+ * retains the default_len setting
+ */
+void SSL3_BUFFER_clear(SSL3_BUFFER *b)
+{
+ b->offset = 0;
+ b->left = 0;
+}
+
+void SSL3_BUFFER_release(SSL3_BUFFER *b)
+{
+ OPENSSL_free(b->buf);
+ b->buf = NULL;
+}
+
+int ssl3_setup_read_buffer(SSL *s)
+{
+ unsigned char *p;
+ size_t len, align = 0, headerlen;
+ SSL3_BUFFER *b;
+
+ b = RECORD_LAYER_get_rbuf(&s->rlayer);
+
+ if (SSL_IS_DTLS(s))
+ headerlen = DTLS1_RT_HEADER_LENGTH;
+ else
+ headerlen = SSL3_RT_HEADER_LENGTH;
+
+#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
+ align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1);
+#endif
+
+ if (b->buf == NULL) {
+ len = SSL3_RT_MAX_PLAIN_LENGTH
+ + SSL3_RT_MAX_ENCRYPTED_OVERHEAD + headerlen + align;
+#ifndef OPENSSL_NO_COMP
+ if (ssl_allow_compression(s))
+ len += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
+#endif
+ if (b->default_len > len)
+ len = b->default_len;
+ if ((p = OPENSSL_malloc(len)) == NULL)
+ goto err;
+ b->buf = p;
+ b->len = len;
+ }
+
+ RECORD_LAYER_set_packet(&s->rlayer, &(b->buf[0]));
+ return 1;
+
+ err:
+ SSLerr(SSL_F_SSL3_SETUP_READ_BUFFER, ERR_R_MALLOC_FAILURE);
+ return 0;
+}
+
+int ssl3_setup_write_buffer(SSL *s, unsigned int numwpipes, size_t len)
+{
+ unsigned char *p;
+ size_t align = 0, headerlen;
+ SSL3_BUFFER *wb;
+ unsigned int currpipe;
+
+ s->rlayer.numwpipes = numwpipes;
+
+ if (len == 0) {
+ if (SSL_IS_DTLS(s))
+ headerlen = DTLS1_RT_HEADER_LENGTH + 1;
+ else
+ headerlen = SSL3_RT_HEADER_LENGTH;
+
+#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
+ align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1);
+#endif
+
+ len = s->max_send_fragment
+ + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + headerlen + align;
+#ifndef OPENSSL_NO_COMP
+ if (ssl_allow_compression(s))
+ len += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
+#endif
+ if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS))
+ len += headerlen + align + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD;
+ }
+
+ wb = RECORD_LAYER_get_wbuf(&s->rlayer);
+ for (currpipe = 0; currpipe < numwpipes; currpipe++) {
+ SSL3_BUFFER *thiswb = &wb[currpipe];
+
+ if (thiswb->buf == NULL) {
+ p = OPENSSL_malloc(len);
+ if (p == NULL) {
+ s->rlayer.numwpipes = currpipe;
+ goto err;
+ }
+ memset(thiswb, 0, sizeof(SSL3_BUFFER));
+ thiswb->buf = p;
+ thiswb->len = len;
+ }
+ }
+
+ return 1;
+
+ err:
+ SSLerr(SSL_F_SSL3_SETUP_WRITE_BUFFER, ERR_R_MALLOC_FAILURE);
+ return 0;
+}
+
+int ssl3_setup_buffers(SSL *s)
+{
+ if (!ssl3_setup_read_buffer(s))
+ return 0;
+ if (!ssl3_setup_write_buffer(s, 1, 0))
+ return 0;
+ return 1;
+}
+
+int ssl3_release_write_buffer(SSL *s)
+{
+ SSL3_BUFFER *wb;
+ unsigned int pipes;
+
+ pipes = s->rlayer.numwpipes;
+ while (pipes > 0) {
+ wb = &RECORD_LAYER_get_wbuf(&s->rlayer)[pipes - 1];
+
+ OPENSSL_free(wb->buf);
+ wb->buf = NULL;
+ pipes--;
+ }
+ s->rlayer.numwpipes = 0;
+ return 1;
+}
+
+int ssl3_release_read_buffer(SSL *s)
+{
+ SSL3_BUFFER *b;
+
+ b = RECORD_LAYER_get_rbuf(&s->rlayer);
+ OPENSSL_free(b->buf);
+ b->buf = NULL;
+ return 1;
+}
diff --git a/openssl-1.1.0h/ssl/record/ssl3_record.c b/openssl-1.1.0h/ssl/record/ssl3_record.c
new file mode 100644
index 0000000..c7a54fe
--- /dev/null
+++ b/openssl-1.1.0h/ssl/record/ssl3_record.c
@@ -0,0 +1,1641 @@
+/*
+ * Copyright 1995-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
+ */
+
+#include <assert.h>
+#include "../ssl_locl.h"
+#include "internal/constant_time_locl.h"
+#include <openssl/rand.h>
+#include "record_locl.h"
+
+static const unsigned char ssl3_pad_1[48] = {
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
+};
+
+static const unsigned char ssl3_pad_2[48] = {
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
+};
+
+/*
+ * Clear the contents of an SSL3_RECORD but retain any memory allocated
+ */
+void SSL3_RECORD_clear(SSL3_RECORD *r, unsigned int num_recs)
+{
+ unsigned char *comp;
+ unsigned int i;
+
+ for (i = 0; i < num_recs; i++) {
+ comp = r[i].comp;
+
+ memset(&r[i], 0, sizeof(*r));
+ r[i].comp = comp;
+ }
+}
+
+void SSL3_RECORD_release(SSL3_RECORD *r, unsigned int num_recs)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_recs; i++) {
+ OPENSSL_free(r[i].comp);
+ r[i].comp = NULL;
+ }
+}
+
+void SSL3_RECORD_set_seq_num(SSL3_RECORD *r, const unsigned char *seq_num)
+{
+ memcpy(r->seq_num, seq_num, SEQ_NUM_SIZE);
+}
+
+/*
+ * Peeks ahead into "read_ahead" data to see if we have a whole record waiting
+ * for us in the buffer.
+ */
+static int ssl3_record_app_data_waiting(SSL *s)
+{
+ SSL3_BUFFER *rbuf;
+ int left, len;
+ unsigned char *p;
+
+ rbuf = RECORD_LAYER_get_rbuf(&s->rlayer);
+
+ p = SSL3_BUFFER_get_buf(rbuf);
+ if (p == NULL)
+ return 0;
+
+ left = SSL3_BUFFER_get_left(rbuf);
+
+ if (left < SSL3_RT_HEADER_LENGTH)
+ return 0;
+
+ p += SSL3_BUFFER_get_offset(rbuf);
+
+ /*
+ * We only check the type and record length, we will sanity check version
+ * etc later
+ */
+ if (*p != SSL3_RT_APPLICATION_DATA)
+ return 0;
+
+ p += 3;
+ n2s(p, len);
+
+ if (left < SSL3_RT_HEADER_LENGTH + len)
+ return 0;
+
+ return 1;
+}
+
+/*
+ * MAX_EMPTY_RECORDS defines the number of consecutive, empty records that
+ * will be processed per call to ssl3_get_record. Without this limit an
+ * attacker could send empty records at a faster rate than we can process and
+ * cause ssl3_get_record to loop forever.
+ */
+#define MAX_EMPTY_RECORDS 32
+
+#define SSL2_RT_HEADER_LENGTH 2
+/*-
+ * Call this to get new input records.
+ * It will return <= 0 if more data is needed, normally due to an error
+ * or non-blocking IO.
+ * When it finishes, |numrpipes| records have been decoded. For each record 'i':
+ * rr[i].type - is the type of record
+ * rr[i].data, - data
+ * rr[i].length, - number of bytes
+ * Multiple records will only be returned if the record types are all
+ * SSL3_RT_APPLICATION_DATA. The number of records returned will always be <=
+ * |max_pipelines|
+ */
+/* used only by ssl3_read_bytes */
+int ssl3_get_record(SSL *s)
+{
+ int ssl_major, ssl_minor, al;
+ int enc_err, n, i, ret = -1;
+ SSL3_RECORD *rr;
+ SSL3_BUFFER *rbuf;
+ SSL_SESSION *sess;
+ unsigned char *p;
+ unsigned char md[EVP_MAX_MD_SIZE];
+ short version;
+ unsigned mac_size;
+ int imac_size;
+ unsigned int num_recs = 0;
+ unsigned int max_recs;
+ unsigned int j;
+
+ rr = RECORD_LAYER_get_rrec(&s->rlayer);
+ rbuf = RECORD_LAYER_get_rbuf(&s->rlayer);
+ max_recs = s->max_pipelines;
+ if (max_recs == 0)
+ max_recs = 1;
+ sess = s->session;
+
+ do {
+ /* check if we have the header */
+ if ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) ||
+ (RECORD_LAYER_get_packet_length(&s->rlayer)
+ < SSL3_RT_HEADER_LENGTH)) {
+ n = ssl3_read_n(s, SSL3_RT_HEADER_LENGTH,
+ SSL3_BUFFER_get_len(rbuf), 0,
+ num_recs == 0 ? 1 : 0);
+ if (n <= 0)
+ return (n); /* error or non-blocking */
+ RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY);
+
+ p = RECORD_LAYER_get_packet(&s->rlayer);
+
+ /*
+ * The first record received by the server may be a V2ClientHello.
+ */
+ if (s->server && RECORD_LAYER_is_first_record(&s->rlayer)
+ && (p[0] & 0x80) && (p[2] == SSL2_MT_CLIENT_HELLO)) {
+ /*
+ * SSLv2 style record
+ *
+ * |num_recs| here will actually always be 0 because
+ * |num_recs > 0| only ever occurs when we are processing
+ * multiple app data records - which we know isn't the case here
+ * because it is an SSLv2ClientHello. We keep it using
+ * |num_recs| for the sake of consistency
+ */
+ rr[num_recs].type = SSL3_RT_HANDSHAKE;
+ rr[num_recs].rec_version = SSL2_VERSION;
+
+ rr[num_recs].length = ((p[0] & 0x7f) << 8) | p[1];
+
+ if (rr[num_recs].length > SSL3_BUFFER_get_len(rbuf)
+ - SSL2_RT_HEADER_LENGTH) {
+ al = SSL_AD_RECORD_OVERFLOW;
+ SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_PACKET_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+
+ if (rr[num_recs].length < MIN_SSL2_RECORD_LEN) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+ } else {
+ /* SSLv3+ style record */
+ if (s->msg_callback)
+ s->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, s,
+ s->msg_callback_arg);
+
+ /* Pull apart the header into the SSL3_RECORD */
+ rr[num_recs].type = *(p++);
+ ssl_major = *(p++);
+ ssl_minor = *(p++);
+ version = (ssl_major << 8) | ssl_minor;
+ rr[num_recs].rec_version = version;
+ n2s(p, rr[num_recs].length);
+
+ /* Lets check version */
+ if (!s->first_packet && version != s->version) {
+ SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER);
+ if ((s->version & 0xFF00) == (version & 0xFF00)
+ && !s->enc_write_ctx && !s->write_hash) {
+ if (rr->type == SSL3_RT_ALERT) {
+ /*
+ * The record is using an incorrect version number,
+ * but what we've got appears to be an alert. We
+ * haven't read the body yet to check whether its a
+ * fatal or not - but chances are it is. We probably
+ * shouldn't send a fatal alert back. We'll just
+ * end.
+ */
+ goto err;
+ }
+ /*
+ * Send back error using their minor version number :-)
+ */
+ s->version = (unsigned short)version;
+ }
+ al = SSL_AD_PROTOCOL_VERSION;
+ goto f_err;
+ }
+
+ if ((version >> 8) != SSL3_VERSION_MAJOR) {
+ if (RECORD_LAYER_is_first_record(&s->rlayer)) {
+ /* Go back to start of packet, look at the five bytes
+ * that we have. */
+ p = RECORD_LAYER_get_packet(&s->rlayer);
+ if (strncmp((char *)p, "GET ", 4) == 0 ||
+ strncmp((char *)p, "POST ", 5) == 0 ||
+ strncmp((char *)p, "HEAD ", 5) == 0 ||
+ strncmp((char *)p, "PUT ", 4) == 0) {
+ SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_HTTP_REQUEST);
+ goto err;
+ } else if (strncmp((char *)p, "CONNE", 5) == 0) {
+ SSLerr(SSL_F_SSL3_GET_RECORD,
+ SSL_R_HTTPS_PROXY_REQUEST);
+ goto err;
+ }
+
+ /* Doesn't look like TLS - don't send an alert */
+ SSLerr(SSL_F_SSL3_GET_RECORD,
+ SSL_R_WRONG_VERSION_NUMBER);
+ goto err;
+ } else {
+ SSLerr(SSL_F_SSL3_GET_RECORD,
+ SSL_R_WRONG_VERSION_NUMBER);
+ al = SSL_AD_PROTOCOL_VERSION;
+ goto f_err;
+ }
+ }
+
+ if (rr[num_recs].length >
+ SSL3_BUFFER_get_len(rbuf) - SSL3_RT_HEADER_LENGTH) {
+ al = SSL_AD_RECORD_OVERFLOW;
+ SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_PACKET_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+ }
+
+ /* now s->rlayer.rstate == SSL_ST_READ_BODY */
+ }
+
+ /*
+ * s->rlayer.rstate == SSL_ST_READ_BODY, get and decode the data.
+ * Calculate how much more data we need to read for the rest of the
+ * record
+ */
+ if (rr[num_recs].rec_version == SSL2_VERSION) {
+ i = rr[num_recs].length + SSL2_RT_HEADER_LENGTH
+ - SSL3_RT_HEADER_LENGTH;
+ } else {
+ i = rr[num_recs].length;
+ }
+ if (i > 0) {
+ /* now s->packet_length == SSL3_RT_HEADER_LENGTH */
+
+ n = ssl3_read_n(s, i, i, 1, 0);
+ if (n <= 0)
+ return (n); /* error or non-blocking io */
+ }
+
+ /* set state for later operations */
+ RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_HEADER);
+
+ /*
+ * At this point, s->packet_length == SSL3_RT_HEADER_LENGTH + rr->length,
+ * or s->packet_length == SSL2_RT_HEADER_LENGTH + rr->length
+ * and we have that many bytes in s->packet
+ */
+ if (rr[num_recs].rec_version == SSL2_VERSION) {
+ rr[num_recs].input =
+ &(RECORD_LAYER_get_packet(&s->rlayer)[SSL2_RT_HEADER_LENGTH]);
+ } else {
+ rr[num_recs].input =
+ &(RECORD_LAYER_get_packet(&s->rlayer)[SSL3_RT_HEADER_LENGTH]);
+ }
+
+ /*
+ * ok, we can now read from 's->packet' data into 'rr' rr->input points
+ * at rr->length bytes, which need to be copied into rr->data by either
+ * the decryption or by the decompression When the data is 'copied' into
+ * the rr->data buffer, rr->input will be pointed at the new buffer
+ */
+
+ /*
+ * We now have - encrypted [ MAC [ compressed [ plain ] ] ] rr->length
+ * bytes of encrypted compressed stuff.
+ */
+
+ /* check is not needed I believe */
+ if (rr[num_recs].length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
+ al = SSL_AD_RECORD_OVERFLOW;
+ SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+
+ /* decrypt in place in 'rr->input' */
+ rr[num_recs].data = rr[num_recs].input;
+ rr[num_recs].orig_len = rr[num_recs].length;
+
+ /* Mark this record as not read by upper layers yet */
+ rr[num_recs].read = 0;
+
+ num_recs++;
+
+ /* we have pulled in a full packet so zero things */
+ RECORD_LAYER_reset_packet_length(&s->rlayer);
+ RECORD_LAYER_clear_first_record(&s->rlayer);
+ } while (num_recs < max_recs
+ && rr[num_recs - 1].type == SSL3_RT_APPLICATION_DATA
+ && SSL_USE_EXPLICIT_IV(s)
+ && s->enc_read_ctx != NULL
+ && (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_read_ctx))
+ & EVP_CIPH_FLAG_PIPELINE)
+ && ssl3_record_app_data_waiting(s));
+
+ /*
+ * If in encrypt-then-mac mode calculate mac from encrypted record. All
+ * the details below are public so no timing details can leak.
+ */
+ if (SSL_READ_ETM(s) && s->read_hash) {
+ unsigned char *mac;
+
+ imac_size = EVP_MD_CTX_size(s->read_hash);
+ assert(imac_size >= 0 && imac_size <= EVP_MAX_MD_SIZE);
+ if (imac_size < 0 || imac_size > EVP_MAX_MD_SIZE) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_RECORD, ERR_LIB_EVP);
+ goto f_err;
+ }
+ mac_size = (unsigned)imac_size;
+
+ for (j = 0; j < num_recs; j++) {
+ if (rr[j].length < mac_size) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+ rr[j].length -= mac_size;
+ mac = rr[j].data + rr[j].length;
+ i = s->method->ssl3_enc->mac(s, &rr[j], md, 0 /* not send */ );
+ if (i < 0 || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) {
+ al = SSL_AD_BAD_RECORD_MAC;
+ SSLerr(SSL_F_SSL3_GET_RECORD,
+ SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
+ goto f_err;
+ }
+ }
+ }
+
+ enc_err = s->method->ssl3_enc->enc(s, rr, num_recs, 0);
+ /*-
+ * enc_err is:
+ * 0: (in non-constant time) if the record is publically invalid.
+ * 1: if the padding is valid
+ * -1: if the padding is invalid
+ */
+ if (enc_err == 0) {
+ al = SSL_AD_DECRYPTION_FAILED;
+ SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
+ goto f_err;
+ }
+#ifdef SSL_DEBUG
+ printf("dec %d\n", rr->length);
+ {
+ unsigned int z;
+ for (z = 0; z < rr->length; z++)
+ printf("%02X%c", rr->data[z], ((z + 1) % 16) ? ' ' : '\n');
+ }
+ printf("\n");
+#endif
+
+ /* r->length is now the compressed data plus mac */
+ if ((sess != NULL) &&
+ (s->enc_read_ctx != NULL) &&
+ (!SSL_READ_ETM(s) && EVP_MD_CTX_md(s->read_hash) != NULL)) {
+ /* s->read_hash != NULL => mac_size != -1 */
+ unsigned char *mac = NULL;
+ unsigned char mac_tmp[EVP_MAX_MD_SIZE];
+
+ mac_size = EVP_MD_CTX_size(s->read_hash);
+ OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE);
+
+ for (j = 0; j < num_recs; j++) {
+ /*
+ * orig_len is the length of the record before any padding was
+ * removed. This is public information, as is the MAC in use,
+ * therefore we can safely process the record in a different amount
+ * of time if it's too short to possibly contain a MAC.
+ */
+ if (rr[j].orig_len < mac_size ||
+ /* CBC records must have a padding length byte too. */
+ (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
+ rr[j].orig_len < mac_size + 1)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+
+ if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) {
+ /*
+ * We update the length so that the TLS header bytes can be
+ * constructed correctly but we need to extract the MAC in
+ * constant time from within the record, without leaking the
+ * contents of the padding bytes.
+ */
+ mac = mac_tmp;
+ ssl3_cbc_copy_mac(mac_tmp, &rr[j], mac_size);
+ rr[j].length -= mac_size;
+ } else {
+ /*
+ * In this case there's no padding, so |rec->orig_len| equals
+ * |rec->length| and we checked that there's enough bytes for
+ * |mac_size| above.
+ */
+ rr[j].length -= mac_size;
+ mac = &rr[j].data[rr[j].length];
+ }
+
+ i = s->method->ssl3_enc->mac(s, &rr[j], md, 0 /* not send */ );
+ if (i < 0 || mac == NULL
+ || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0)
+ enc_err = -1;
+ if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size)
+ enc_err = -1;
+ }
+ }
+
+ if (enc_err < 0) {
+ /*
+ * A separate 'decryption_failed' alert was introduced with TLS 1.0,
+ * SSL 3.0 only has 'bad_record_mac'. But unless a decryption
+ * failure is directly visible from the ciphertext anyway, we should
+ * not reveal which kind of error occurred -- this might become
+ * visible to an attacker (e.g. via a logfile)
+ */
+ al = SSL_AD_BAD_RECORD_MAC;
+ SSLerr(SSL_F_SSL3_GET_RECORD,
+ SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
+ goto f_err;
+ }
+
+ for (j = 0; j < num_recs; j++) {
+ /* rr[j].length is now just compressed */
+ if (s->expand != NULL) {
+ if (rr[j].length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
+ al = SSL_AD_RECORD_OVERFLOW;
+ SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_COMPRESSED_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+ if (!ssl3_do_uncompress(s, &rr[j])) {
+ al = SSL_AD_DECOMPRESSION_FAILURE;
+ SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_BAD_DECOMPRESSION);
+ goto f_err;
+ }
+ }
+
+ if (rr[j].length > SSL3_RT_MAX_PLAIN_LENGTH) {
+ al = SSL_AD_RECORD_OVERFLOW;
+ SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_DATA_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+
+ rr[j].off = 0;
+ /*-
+ * So at this point the following is true
+ * rr[j].type is the type of record
+ * rr[j].length == number of bytes in record
+ * rr[j].off == offset to first valid byte
+ * rr[j].data == where to take bytes from, increment after use :-).
+ */
+
+ /* just read a 0 length packet */
+ if (rr[j].length == 0) {
+ RECORD_LAYER_inc_empty_record_count(&s->rlayer);
+ if (RECORD_LAYER_get_empty_record_count(&s->rlayer)
+ > MAX_EMPTY_RECORDS) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_RECORD_TOO_SMALL);
+ goto f_err;
+ }
+ } else {
+ RECORD_LAYER_reset_empty_record_count(&s->rlayer);
+ }
+ }
+
+ RECORD_LAYER_set_numrpipes(&s->rlayer, num_recs);
+ return 1;
+
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ err:
+ return ret;
+}
+
+int ssl3_do_uncompress(SSL *ssl, SSL3_RECORD *rr)
+{
+#ifndef OPENSSL_NO_COMP
+ int i;
+
+ if (rr->comp == NULL) {
+ rr->comp = (unsigned char *)
+ OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH);
+ }
+ if (rr->comp == NULL)
+ return 0;
+
+ i = COMP_expand_block(ssl->expand, rr->comp,
+ SSL3_RT_MAX_PLAIN_LENGTH, rr->data, (int)rr->length);
+ if (i < 0)
+ return 0;
+ else
+ rr->length = i;
+ rr->data = rr->comp;
+#endif
+ return 1;
+}
+
+int ssl3_do_compress(SSL *ssl, SSL3_RECORD *wr)
+{
+#ifndef OPENSSL_NO_COMP
+ int i;
+
+ i = COMP_compress_block(ssl->compress, wr->data,
+ SSL3_RT_MAX_COMPRESSED_LENGTH,
+ wr->input, (int)wr->length);
+ if (i < 0)
+ return (0);
+ else
+ wr->length = i;
+
+ wr->input = wr->data;
+#endif
+ return (1);
+}
+
+/*-
+ * ssl3_enc encrypts/decrypts |n_recs| records in |inrecs|
+ *
+ * Returns:
+ * 0: (in non-constant time) if the record is publically invalid (i.e. too
+ * short etc).
+ * 1: if the record's padding is valid / the encryption was successful.
+ * -1: if the record's padding is invalid or, if sending, an internal error
+ * occurred.
+ */
+int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, unsigned int n_recs, int sending)
+{
+ SSL3_RECORD *rec;
+ EVP_CIPHER_CTX *ds;
+ unsigned long l;
+ int bs, i, mac_size = 0;
+ const EVP_CIPHER *enc;
+
+ rec = inrecs;
+ /*
+ * We shouldn't ever be called with more than one record in the SSLv3 case
+ */
+ if (n_recs != 1)
+ return 0;
+ if (sending) {
+ ds = s->enc_write_ctx;
+ if (s->enc_write_ctx == NULL)
+ enc = NULL;
+ else
+ enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
+ } else {
+ ds = s->enc_read_ctx;
+ if (s->enc_read_ctx == NULL)
+ enc = NULL;
+ else
+ enc = EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
+ }
+
+ if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) {
+ memmove(rec->data, rec->input, rec->length);
+ rec->input = rec->data;
+ } else {
+ l = rec->length;
+ bs = EVP_CIPHER_CTX_block_size(ds);
+
+ /* COMPRESS */
+
+ if ((bs != 1) && sending) {
+ i = bs - ((int)l % bs);
+
+ /* we need to add 'i-1' padding bytes */
+ l += i;
+ /*
+ * the last of these zero bytes will be overwritten with the
+ * padding length.
+ */
+ memset(&rec->input[rec->length], 0, i);
+ rec->length += i;
+ rec->input[l - 1] = (i - 1);
+ }
+
+ if (!sending) {
+ if (l == 0 || l % bs != 0)
+ return 0;
+ /* otherwise, rec->length >= bs */
+ }
+
+ if (EVP_Cipher(ds, rec->data, rec->input, l) < 1)
+ return -1;
+
+ if (EVP_MD_CTX_md(s->read_hash) != NULL)
+ mac_size = EVP_MD_CTX_size(s->read_hash);
+ if ((bs != 1) && !sending)
+ return ssl3_cbc_remove_padding(rec, bs, mac_size);
+ }
+ return (1);
+}
+
+/*-
+ * tls1_enc encrypts/decrypts |n_recs| in |recs|.
+ *
+ * Returns:
+ * 0: (in non-constant time) if the record is publically invalid (i.e. too
+ * short etc).
+ * 1: if the record's padding is valid / the encryption was successful.
+ * -1: if the record's padding/AEAD-authenticator is invalid or, if sending,
+ * an internal error occurred.
+ */
+int tls1_enc(SSL *s, SSL3_RECORD *recs, unsigned int n_recs, int sending)
+{
+ EVP_CIPHER_CTX *ds;
+ size_t reclen[SSL_MAX_PIPELINES];
+ unsigned char buf[SSL_MAX_PIPELINES][EVP_AEAD_TLS1_AAD_LEN];
+ int bs, i, j, k, pad = 0, ret, mac_size = 0;
+ const EVP_CIPHER *enc;
+ unsigned int ctr;
+
+ if (n_recs == 0)
+ return 0;
+
+ if (sending) {
+ if (EVP_MD_CTX_md(s->write_hash)) {
+ int n = EVP_MD_CTX_size(s->write_hash);
+ OPENSSL_assert(n >= 0);
+ }
+ ds = s->enc_write_ctx;
+ if (s->enc_write_ctx == NULL)
+ enc = NULL;
+ else {
+ int ivlen;
+ enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
+ /* For TLSv1.1 and later explicit IV */
+ if (SSL_USE_EXPLICIT_IV(s)
+ && EVP_CIPHER_mode(enc) == EVP_CIPH_CBC_MODE)
+ ivlen = EVP_CIPHER_iv_length(enc);
+ else
+ ivlen = 0;
+ if (ivlen > 1) {
+ for (ctr = 0; ctr < n_recs; ctr++) {
+ if (recs[ctr].data != recs[ctr].input) {
+ /*
+ * we can't write into the input stream: Can this ever
+ * happen?? (steve)
+ */
+ SSLerr(SSL_F_TLS1_ENC, ERR_R_INTERNAL_ERROR);
+ return -1;
+ } else if (RAND_bytes(recs[ctr].input, ivlen) <= 0) {
+ SSLerr(SSL_F_TLS1_ENC, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+ }
+ }
+ }
+ } else {
+ if (EVP_MD_CTX_md(s->read_hash)) {
+ int n = EVP_MD_CTX_size(s->read_hash);
+ OPENSSL_assert(n >= 0);
+ }
+ ds = s->enc_read_ctx;
+ if (s->enc_read_ctx == NULL)
+ enc = NULL;
+ else
+ enc = EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
+ }
+
+ if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) {
+ for (ctr = 0; ctr < n_recs; ctr++) {
+ memmove(recs[ctr].data, recs[ctr].input, recs[ctr].length);
+ recs[ctr].input = recs[ctr].data;
+ }
+ ret = 1;
+ } else {
+ bs = EVP_CIPHER_block_size(EVP_CIPHER_CTX_cipher(ds));
+
+ if (n_recs > 1) {
+ if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds))
+ & EVP_CIPH_FLAG_PIPELINE)) {
+ /*
+ * We shouldn't have been called with pipeline data if the
+ * cipher doesn't support pipelining
+ */
+ SSLerr(SSL_F_TLS1_ENC, SSL_R_PIPELINE_FAILURE);
+ return -1;
+ }
+ }
+ for (ctr = 0; ctr < n_recs; ctr++) {
+ reclen[ctr] = recs[ctr].length;
+
+ if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds))
+ & EVP_CIPH_FLAG_AEAD_CIPHER) {
+ unsigned char *seq;
+
+ seq = sending ? RECORD_LAYER_get_write_sequence(&s->rlayer)
+ : RECORD_LAYER_get_read_sequence(&s->rlayer);
+
+ if (SSL_IS_DTLS(s)) {
+ /* DTLS does not support pipelining */
+ unsigned char dtlsseq[9], *p = dtlsseq;
+
+ s2n(sending ? DTLS_RECORD_LAYER_get_w_epoch(&s->rlayer) :
+ DTLS_RECORD_LAYER_get_r_epoch(&s->rlayer), p);
+ memcpy(p, &seq[2], 6);
+ memcpy(buf[ctr], dtlsseq, 8);
+ } else {
+ memcpy(buf[ctr], seq, 8);
+ for (i = 7; i >= 0; i--) { /* increment */
+ ++seq[i];
+ if (seq[i] != 0)
+ break;
+ }
+ }
+
+ buf[ctr][8] = recs[ctr].type;
+ buf[ctr][9] = (unsigned char)(s->version >> 8);
+ buf[ctr][10] = (unsigned char)(s->version);
+ buf[ctr][11] = recs[ctr].length >> 8;
+ buf[ctr][12] = recs[ctr].length & 0xff;
+ pad = EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_AEAD_TLS1_AAD,
+ EVP_AEAD_TLS1_AAD_LEN, buf[ctr]);
+ if (pad <= 0)
+ return -1;
+
+ if (sending) {
+ reclen[ctr] += pad;
+ recs[ctr].length += pad;
+ }
+
+ } else if ((bs != 1) && sending) {
+ i = bs - ((int)reclen[ctr] % bs);
+
+ /* Add weird padding of upto 256 bytes */
+
+ /* we need to add 'i' padding bytes of value j */
+ j = i - 1;
+ for (k = (int)reclen[ctr]; k < (int)(reclen[ctr] + i); k++)
+ recs[ctr].input[k] = j;
+ reclen[ctr] += i;
+ recs[ctr].length += i;
+ }
+
+ if (!sending) {
+ if (reclen[ctr] == 0 || reclen[ctr] % bs != 0)
+ return 0;
+ }
+ }
+ if (n_recs > 1) {
+ unsigned char *data[SSL_MAX_PIPELINES];
+
+ /* Set the output buffers */
+ for (ctr = 0; ctr < n_recs; ctr++) {
+ data[ctr] = recs[ctr].data;
+ }
+ if (EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_OUTPUT_BUFS,
+ n_recs, data) <= 0) {
+ SSLerr(SSL_F_TLS1_ENC, SSL_R_PIPELINE_FAILURE);
+ }
+ /* Set the input buffers */
+ for (ctr = 0; ctr < n_recs; ctr++) {
+ data[ctr] = recs[ctr].input;
+ }
+ if (EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_INPUT_BUFS,
+ n_recs, data) <= 0
+ || EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_INPUT_LENS,
+ n_recs, reclen) <= 0) {
+ SSLerr(SSL_F_TLS1_ENC, SSL_R_PIPELINE_FAILURE);
+ return -1;
+ }
+ }
+
+ i = EVP_Cipher(ds, recs[0].data, recs[0].input, reclen[0]);
+ if ((EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds))
+ & EVP_CIPH_FLAG_CUSTOM_CIPHER)
+ ? (i < 0)
+ : (i == 0))
+ return -1; /* AEAD can fail to verify MAC */
+ if (sending == 0) {
+ if (EVP_CIPHER_mode(enc) == EVP_CIPH_GCM_MODE) {
+ for (ctr = 0; ctr < n_recs; ctr++) {
+ recs[ctr].data += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ recs[ctr].input += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ recs[ctr].length -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ }
+ } else if (EVP_CIPHER_mode(enc) == EVP_CIPH_CCM_MODE) {
+ for (ctr = 0; ctr < n_recs; ctr++) {
+ recs[ctr].data += EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ recs[ctr].input += EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ recs[ctr].length -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ }
+ }
+ }
+
+ ret = 1;
+ if (!SSL_READ_ETM(s) && EVP_MD_CTX_md(s->read_hash) != NULL)
+ mac_size = EVP_MD_CTX_size(s->read_hash);
+ if ((bs != 1) && !sending) {
+ int tmpret;
+ for (ctr = 0; ctr < n_recs; ctr++) {
+ tmpret = tls1_cbc_remove_padding(s, &recs[ctr], bs, mac_size);
+ /*
+ * If tmpret == 0 then this means publicly invalid so we can
+ * short circuit things here. Otherwise we must respect constant
+ * time behaviour.
+ */
+ if (tmpret == 0)
+ return 0;
+ ret = constant_time_select_int(constant_time_eq_int(tmpret, 1),
+ ret, -1);
+ }
+ }
+ if (pad && !sending) {
+ for (ctr = 0; ctr < n_recs; ctr++) {
+ recs[ctr].length -= pad;
+ }
+ }
+ }
+ return ret;
+}
+
+int n_ssl3_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
+{
+ unsigned char *mac_sec, *seq;
+ const EVP_MD_CTX *hash;
+ unsigned char *p, rec_char;
+ size_t md_size;
+ int npad;
+ int t;
+
+ if (sending) {
+ mac_sec = &(ssl->s3->write_mac_secret[0]);
+ seq = RECORD_LAYER_get_write_sequence(&ssl->rlayer);
+ hash = ssl->write_hash;
+ } else {
+ mac_sec = &(ssl->s3->read_mac_secret[0]);
+ seq = RECORD_LAYER_get_read_sequence(&ssl->rlayer);
+ hash = ssl->read_hash;
+ }
+
+ t = EVP_MD_CTX_size(hash);
+ if (t < 0)
+ return -1;
+ md_size = t;
+ npad = (48 / md_size) * md_size;
+
+ if (!sending &&
+ EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
+ ssl3_cbc_record_digest_supported(hash)) {
+ /*
+ * This is a CBC-encrypted record. We must avoid leaking any
+ * timing-side channel information about how many blocks of data we
+ * are hashing because that gives an attacker a timing-oracle.
+ */
+
+ /*-
+ * npad is, at most, 48 bytes and that's with MD5:
+ * 16 + 48 + 8 (sequence bytes) + 1 + 2 = 75.
+ *
+ * With SHA-1 (the largest hash speced for SSLv3) the hash size
+ * goes up 4, but npad goes down by 8, resulting in a smaller
+ * total size.
+ */
+ unsigned char header[75];
+ unsigned j = 0;
+ memcpy(header + j, mac_sec, md_size);
+ j += md_size;
+ memcpy(header + j, ssl3_pad_1, npad);
+ j += npad;
+ memcpy(header + j, seq, 8);
+ j += 8;
+ header[j++] = rec->type;
+ header[j++] = rec->length >> 8;
+ header[j++] = rec->length & 0xff;
+
+ /* Final param == is SSLv3 */
+ if (ssl3_cbc_digest_record(hash,
+ md, &md_size,
+ header, rec->input,
+ rec->length + md_size, rec->orig_len,
+ mac_sec, md_size, 1) <= 0)
+ return -1;
+ } else {
+ unsigned int md_size_u;
+ /* Chop the digest off the end :-) */
+ EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
+
+ if (md_ctx == NULL)
+ return -1;
+
+ rec_char = rec->type;
+ p = md;
+ s2n(rec->length, p);
+ if (EVP_MD_CTX_copy_ex(md_ctx, hash) <= 0
+ || EVP_DigestUpdate(md_ctx, mac_sec, md_size) <= 0
+ || EVP_DigestUpdate(md_ctx, ssl3_pad_1, npad) <= 0
+ || EVP_DigestUpdate(md_ctx, seq, 8) <= 0
+ || EVP_DigestUpdate(md_ctx, &rec_char, 1) <= 0
+ || EVP_DigestUpdate(md_ctx, md, 2) <= 0
+ || EVP_DigestUpdate(md_ctx, rec->input, rec->length) <= 0
+ || EVP_DigestFinal_ex(md_ctx, md, NULL) <= 0
+ || EVP_MD_CTX_copy_ex(md_ctx, hash) <= 0
+ || EVP_DigestUpdate(md_ctx, mac_sec, md_size) <= 0
+ || EVP_DigestUpdate(md_ctx, ssl3_pad_2, npad) <= 0
+ || EVP_DigestUpdate(md_ctx, md, md_size) <= 0
+ || EVP_DigestFinal_ex(md_ctx, md, &md_size_u) <= 0) {
+ EVP_MD_CTX_free(md_ctx);
+ return -1;
+ }
+ md_size = md_size_u;
+
+ EVP_MD_CTX_free(md_ctx);
+ }
+
+ ssl3_record_sequence_update(seq);
+ return (md_size);
+}
+
+int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
+{
+ unsigned char *seq;
+ EVP_MD_CTX *hash;
+ size_t md_size;
+ int i;
+ EVP_MD_CTX *hmac = NULL, *mac_ctx;
+ unsigned char header[13];
+ int stream_mac = (sending ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM)
+ : (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_STREAM));
+ int t;
+
+ if (sending) {
+ seq = RECORD_LAYER_get_write_sequence(&ssl->rlayer);
+ hash = ssl->write_hash;
+ } else {
+ seq = RECORD_LAYER_get_read_sequence(&ssl->rlayer);
+ hash = ssl->read_hash;
+ }
+
+ t = EVP_MD_CTX_size(hash);
+ OPENSSL_assert(t >= 0);
+ md_size = t;
+
+ /* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */
+ if (stream_mac) {
+ mac_ctx = hash;
+ } else {
+ hmac = EVP_MD_CTX_new();
+ if (hmac == NULL || !EVP_MD_CTX_copy(hmac, hash)) {
+ EVP_MD_CTX_free(hmac);
+ return -1;
+ }
+ mac_ctx = hmac;
+ }
+
+ if (SSL_IS_DTLS(ssl)) {
+ unsigned char dtlsseq[8], *p = dtlsseq;
+
+ s2n(sending ? DTLS_RECORD_LAYER_get_w_epoch(&ssl->rlayer) :
+ DTLS_RECORD_LAYER_get_r_epoch(&ssl->rlayer), p);
+ memcpy(p, &seq[2], 6);
+
+ memcpy(header, dtlsseq, 8);
+ } else
+ memcpy(header, seq, 8);
+
+ header[8] = rec->type;
+ header[9] = (unsigned char)(ssl->version >> 8);
+ header[10] = (unsigned char)(ssl->version);
+ header[11] = (rec->length) >> 8;
+ header[12] = (rec->length) & 0xff;
+
+ if (!sending && !SSL_READ_ETM(ssl) &&
+ EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
+ ssl3_cbc_record_digest_supported(mac_ctx)) {
+ /*
+ * This is a CBC-encrypted record. We must avoid leaking any
+ * timing-side channel information about how many blocks of data we
+ * are hashing because that gives an attacker a timing-oracle.
+ */
+ /* Final param == not SSLv3 */
+ if (ssl3_cbc_digest_record(mac_ctx,
+ md, &md_size,
+ header, rec->input,
+ rec->length + md_size, rec->orig_len,
+ ssl->s3->read_mac_secret,
+ ssl->s3->read_mac_secret_size, 0) <= 0) {
+ EVP_MD_CTX_free(hmac);
+ return -1;
+ }
+ } else {
+ if (EVP_DigestSignUpdate(mac_ctx, header, sizeof(header)) <= 0
+ || EVP_DigestSignUpdate(mac_ctx, rec->input, rec->length) <= 0
+ || EVP_DigestSignFinal(mac_ctx, md, &md_size) <= 0) {
+ EVP_MD_CTX_free(hmac);
+ return -1;
+ }
+ if (!sending && !SSL_READ_ETM(ssl) && FIPS_mode())
+ if (!tls_fips_digest_extra(ssl->enc_read_ctx,
+ mac_ctx, rec->input,
+ rec->length, rec->orig_len)) {
+ EVP_MD_CTX_free(hmac);
+ return -1;
+ }
+ }
+
+ EVP_MD_CTX_free(hmac);
+
+#ifdef SSL_DEBUG
+ fprintf(stderr, "seq=");
+ {
+ int z;
+ for (z = 0; z < 8; z++)
+ fprintf(stderr, "%02X ", seq[z]);
+ fprintf(stderr, "\n");
+ }
+ fprintf(stderr, "rec=");
+ {
+ unsigned int z;
+ for (z = 0; z < rec->length; z++)
+ fprintf(stderr, "%02X ", rec->data[z]);
+ fprintf(stderr, "\n");
+ }
+#endif
+
+ if (!SSL_IS_DTLS(ssl)) {
+ for (i = 7; i >= 0; i--) {
+ ++seq[i];
+ if (seq[i] != 0)
+ break;
+ }
+ }
+#ifdef SSL_DEBUG
+ {
+ unsigned int z;
+ for (z = 0; z < md_size; z++)
+ fprintf(stderr, "%02X ", md[z]);
+ fprintf(stderr, "\n");
+ }
+#endif
+ return (md_size);
+}
+
+/*-
+ * ssl3_cbc_remove_padding removes padding from the decrypted, SSLv3, CBC
+ * record in |rec| by updating |rec->length| in constant time.
+ *
+ * block_size: the block size of the cipher used to encrypt the record.
+ * returns:
+ * 0: (in non-constant time) if the record is publicly invalid.
+ * 1: if the padding was valid
+ * -1: otherwise.
+ */
+int ssl3_cbc_remove_padding(SSL3_RECORD *rec,
+ unsigned block_size, unsigned mac_size)
+{
+ unsigned padding_length, good;
+ const unsigned overhead = 1 /* padding length byte */ + mac_size;
+
+ /*
+ * These lengths are all public so we can test them in non-constant time.
+ */
+ if (overhead > rec->length)
+ return 0;
+
+ padding_length = rec->data[rec->length - 1];
+ good = constant_time_ge(rec->length, padding_length + overhead);
+ /* SSLv3 requires that the padding is minimal. */
+ good &= constant_time_ge(block_size, padding_length + 1);
+ rec->length -= good & (padding_length + 1);
+ return constant_time_select_int(good, 1, -1);
+}
+
+/*-
+ * tls1_cbc_remove_padding removes the CBC padding from the decrypted, TLS, CBC
+ * record in |rec| in constant time and returns 1 if the padding is valid and
+ * -1 otherwise. It also removes any explicit IV from the start of the record
+ * without leaking any timing about whether there was enough space after the
+ * padding was removed.
+ *
+ * block_size: the block size of the cipher used to encrypt the record.
+ * returns:
+ * 0: (in non-constant time) if the record is publicly invalid.
+ * 1: if the padding was valid
+ * -1: otherwise.
+ */
+int tls1_cbc_remove_padding(const SSL *s,
+ SSL3_RECORD *rec,
+ unsigned block_size, unsigned mac_size)
+{
+ unsigned padding_length, good, to_check, i;
+ const unsigned overhead = 1 /* padding length byte */ + mac_size;
+ /* Check if version requires explicit IV */
+ if (SSL_USE_EXPLICIT_IV(s)) {
+ /*
+ * These lengths are all public so we can test them in non-constant
+ * time.
+ */
+ if (overhead + block_size > rec->length)
+ return 0;
+ /* We can now safely skip explicit IV */
+ rec->data += block_size;
+ rec->input += block_size;
+ rec->length -= block_size;
+ rec->orig_len -= block_size;
+ } else if (overhead > rec->length)
+ return 0;
+
+ padding_length = rec->data[rec->length - 1];
+
+ if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_read_ctx)) &
+ EVP_CIPH_FLAG_AEAD_CIPHER) {
+ /* padding is already verified */
+ rec->length -= padding_length + 1;
+ return 1;
+ }
+
+ good = constant_time_ge(rec->length, overhead + padding_length);
+ /*
+ * The padding consists of a length byte at the end of the record and
+ * then that many bytes of padding, all with the same value as the length
+ * byte. Thus, with the length byte included, there are i+1 bytes of
+ * padding. We can't check just |padding_length+1| bytes because that
+ * leaks decrypted information. Therefore we always have to check the
+ * maximum amount of padding possible. (Again, the length of the record
+ * is public information so we can use it.)
+ */
+ to_check = 256; /* maximum amount of padding, inc length byte. */
+ if (to_check > rec->length)
+ to_check = rec->length;
+
+ for (i = 0; i < to_check; i++) {
+ unsigned char mask = constant_time_ge_8(padding_length, i);
+ unsigned char b = rec->data[rec->length - 1 - i];
+ /*
+ * The final |padding_length+1| bytes should all have the value
+ * |padding_length|. Therefore the XOR should be zero.
+ */
+ good &= ~(mask & (padding_length ^ b));
+ }
+
+ /*
+ * If any of the final |padding_length+1| bytes had the wrong value, one
+ * or more of the lower eight bits of |good| will be cleared.
+ */
+ good = constant_time_eq(0xff, good & 0xff);
+ rec->length -= good & (padding_length + 1);
+
+ return constant_time_select_int(good, 1, -1);
+}
+
+/*-
+ * ssl3_cbc_copy_mac copies |md_size| bytes from the end of |rec| to |out| in
+ * constant time (independent of the concrete value of rec->length, which may
+ * vary within a 256-byte window).
+ *
+ * ssl3_cbc_remove_padding or tls1_cbc_remove_padding must be called prior to
+ * this function.
+ *
+ * On entry:
+ * rec->orig_len >= md_size
+ * md_size <= EVP_MAX_MD_SIZE
+ *
+ * If CBC_MAC_ROTATE_IN_PLACE is defined then the rotation is performed with
+ * variable accesses in a 64-byte-aligned buffer. Assuming that this fits into
+ * a single or pair of cache-lines, then the variable memory accesses don't
+ * actually affect the timing. CPUs with smaller cache-lines [if any] are
+ * not multi-core and are not considered vulnerable to cache-timing attacks.
+ */
+#define CBC_MAC_ROTATE_IN_PLACE
+
+void ssl3_cbc_copy_mac(unsigned char *out,
+ const SSL3_RECORD *rec, unsigned md_size)
+{
+#if defined(CBC_MAC_ROTATE_IN_PLACE)
+ unsigned char rotated_mac_buf[64 + EVP_MAX_MD_SIZE];
+ unsigned char *rotated_mac;
+#else
+ unsigned char rotated_mac[EVP_MAX_MD_SIZE];
+#endif
+
+ /*
+ * mac_end is the index of |rec->data| just after the end of the MAC.
+ */
+ unsigned mac_end = rec->length;
+ unsigned mac_start = mac_end - md_size;
+ unsigned in_mac;
+ /*
+ * scan_start contains the number of bytes that we can ignore because the
+ * MAC's position can only vary by 255 bytes.
+ */
+ unsigned scan_start = 0;
+ unsigned i, j;
+ unsigned rotate_offset;
+
+ OPENSSL_assert(rec->orig_len >= md_size);
+ OPENSSL_assert(md_size <= EVP_MAX_MD_SIZE);
+
+#if defined(CBC_MAC_ROTATE_IN_PLACE)
+ rotated_mac = rotated_mac_buf + ((0 - (size_t)rotated_mac_buf) & 63);
+#endif
+
+ /* This information is public so it's safe to branch based on it. */
+ if (rec->orig_len > md_size + 255 + 1)
+ scan_start = rec->orig_len - (md_size + 255 + 1);
+
+ in_mac = 0;
+ rotate_offset = 0;
+ memset(rotated_mac, 0, md_size);
+ for (i = scan_start, j = 0; i < rec->orig_len; i++) {
+ unsigned mac_started = constant_time_eq(i, mac_start);
+ unsigned mac_ended = constant_time_lt(i, mac_end);
+ unsigned char b = rec->data[i];
+
+ in_mac |= mac_started;
+ in_mac &= mac_ended;
+ rotate_offset |= j & mac_started;
+ rotated_mac[j++] |= b & in_mac;
+ j &= constant_time_lt(j, md_size);
+ }
+
+ /* Now rotate the MAC */
+#if defined(CBC_MAC_ROTATE_IN_PLACE)
+ j = 0;
+ for (i = 0; i < md_size; i++) {
+ /* in case cache-line is 32 bytes, touch second line */
+ ((volatile unsigned char *)rotated_mac)[rotate_offset ^ 32];
+ out[j++] = rotated_mac[rotate_offset++];
+ rotate_offset &= constant_time_lt(rotate_offset, md_size);
+ }
+#else
+ memset(out, 0, md_size);
+ rotate_offset = md_size - rotate_offset;
+ rotate_offset &= constant_time_lt(rotate_offset, md_size);
+ for (i = 0; i < md_size; i++) {
+ for (j = 0; j < md_size; j++)
+ out[j] |= rotated_mac[i] & constant_time_eq_8(j, rotate_offset);
+ rotate_offset++;
+ rotate_offset &= constant_time_lt(rotate_offset, md_size);
+ }
+#endif
+}
+
+int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
+{
+ int i, al;
+ int enc_err;
+ SSL_SESSION *sess;
+ SSL3_RECORD *rr;
+ unsigned int mac_size;
+ unsigned char md[EVP_MAX_MD_SIZE];
+
+ rr = RECORD_LAYER_get_rrec(&s->rlayer);
+ sess = s->session;
+
+ /*
+ * At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length,
+ * and we have that many bytes in s->packet
+ */
+ rr->input = &(RECORD_LAYER_get_packet(&s->rlayer)[DTLS1_RT_HEADER_LENGTH]);
+
+ /*
+ * ok, we can now read from 's->packet' data into 'rr' rr->input points
+ * at rr->length bytes, which need to be copied into rr->data by either
+ * the decryption or by the decompression When the data is 'copied' into
+ * the rr->data buffer, rr->input will be pointed at the new buffer
+ */
+
+ /*
+ * We now have - encrypted [ MAC [ compressed [ plain ] ] ] rr->length
+ * bytes of encrypted compressed stuff.
+ */
+
+ /* check is not needed I believe */
+ if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
+ al = SSL_AD_RECORD_OVERFLOW;
+ SSLerr(SSL_F_DTLS1_PROCESS_RECORD, SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+
+ /* decrypt in place in 'rr->input' */
+ rr->data = rr->input;
+ rr->orig_len = rr->length;
+
+ enc_err = s->method->ssl3_enc->enc(s, rr, 1, 0);
+ /*-
+ * enc_err is:
+ * 0: (in non-constant time) if the record is publically invalid.
+ * 1: if the padding is valid
+ * -1: if the padding is invalid
+ */
+ if (enc_err == 0) {
+ /* For DTLS we simply ignore bad packets. */
+ rr->length = 0;
+ RECORD_LAYER_reset_packet_length(&s->rlayer);
+ goto err;
+ }
+#ifdef SSL_DEBUG
+ printf("dec %d\n", rr->length);
+ {
+ unsigned int z;
+ for (z = 0; z < rr->length; z++)
+ printf("%02X%c", rr->data[z], ((z + 1) % 16) ? ' ' : '\n');
+ }
+ printf("\n");
+#endif
+
+ /* r->length is now the compressed data plus mac */
+ if ((sess != NULL) &&
+ (s->enc_read_ctx != NULL) && (EVP_MD_CTX_md(s->read_hash) != NULL)) {
+ /* s->read_hash != NULL => mac_size != -1 */
+ unsigned char *mac = NULL;
+ unsigned char mac_tmp[EVP_MAX_MD_SIZE];
+ mac_size = EVP_MD_CTX_size(s->read_hash);
+ OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE);
+
+ /*
+ * orig_len is the length of the record before any padding was
+ * removed. This is public information, as is the MAC in use,
+ * therefore we can safely process the record in a different amount
+ * of time if it's too short to possibly contain a MAC.
+ */
+ if (rr->orig_len < mac_size ||
+ /* CBC records must have a padding length byte too. */
+ (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
+ rr->orig_len < mac_size + 1)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_DTLS1_PROCESS_RECORD, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+
+ if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) {
+ /*
+ * We update the length so that the TLS header bytes can be
+ * constructed correctly but we need to extract the MAC in
+ * constant time from within the record, without leaking the
+ * contents of the padding bytes.
+ */
+ mac = mac_tmp;
+ ssl3_cbc_copy_mac(mac_tmp, rr, mac_size);
+ rr->length -= mac_size;
+ } else {
+ /*
+ * In this case there's no padding, so |rec->orig_len| equals
+ * |rec->length| and we checked that there's enough bytes for
+ * |mac_size| above.
+ */
+ rr->length -= mac_size;
+ mac = &rr->data[rr->length];
+ }
+
+ i = s->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ );
+ if (i < 0 || mac == NULL
+ || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0)
+ enc_err = -1;
+ if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size)
+ enc_err = -1;
+ }
+
+ if (enc_err < 0) {
+ /* decryption failed, silently discard message */
+ rr->length = 0;
+ RECORD_LAYER_reset_packet_length(&s->rlayer);
+ goto err;
+ }
+
+ /* r->length is now just compressed */
+ if (s->expand != NULL) {
+ if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
+ al = SSL_AD_RECORD_OVERFLOW;
+ SSLerr(SSL_F_DTLS1_PROCESS_RECORD,
+ SSL_R_COMPRESSED_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+ if (!ssl3_do_uncompress(s, rr)) {
+ al = SSL_AD_DECOMPRESSION_FAILURE;
+ SSLerr(SSL_F_DTLS1_PROCESS_RECORD, SSL_R_BAD_DECOMPRESSION);
+ goto f_err;
+ }
+ }
+
+ if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH) {
+ al = SSL_AD_RECORD_OVERFLOW;
+ SSLerr(SSL_F_DTLS1_PROCESS_RECORD, SSL_R_DATA_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+
+ rr->off = 0;
+ /*-
+ * So at this point the following is true
+ * ssl->s3->rrec.type is the type of record
+ * ssl->s3->rrec.length == number of bytes in record
+ * ssl->s3->rrec.off == offset to first valid byte
+ * ssl->s3->rrec.data == where to take bytes from, increment
+ * after use :-).
+ */
+
+ /* we have pulled in a full packet so zero things */
+ RECORD_LAYER_reset_packet_length(&s->rlayer);
+
+ /* Mark receipt of record. */
+ dtls1_record_bitmap_update(s, bitmap);
+
+ return (1);
+
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ err:
+ return (0);
+}
+
+/*
+ * Retrieve a buffered record that belongs to the current epoch, i.e. processed
+ */
+#define dtls1_get_processed_record(s) \
+ dtls1_retrieve_buffered_record((s), \
+ &(DTLS_RECORD_LAYER_get_processed_rcds(&s->rlayer)))
+
+/*-
+ * Call this to get a new input record.
+ * It will return <= 0 if more data is needed, normally due to an error
+ * or non-blocking IO.
+ * When it finishes, one packet has been decoded and can be found in
+ * ssl->s3->rrec.type - is the type of record
+ * ssl->s3->rrec.data, - data
+ * ssl->s3->rrec.length, - number of bytes
+ */
+/* used only by dtls1_read_bytes */
+int dtls1_get_record(SSL *s)
+{
+ int ssl_major, ssl_minor;
+ int i, n;
+ SSL3_RECORD *rr;
+ unsigned char *p = NULL;
+ unsigned short version;
+ DTLS1_BITMAP *bitmap;
+ unsigned int is_next_epoch;
+
+ rr = RECORD_LAYER_get_rrec(&s->rlayer);
+
+ again:
+ /*
+ * The epoch may have changed. If so, process all the pending records.
+ * This is a non-blocking operation.
+ */
+ if (!dtls1_process_buffered_records(s))
+ return -1;
+
+ /* if we're renegotiating, then there may be buffered records */
+ if (dtls1_get_processed_record(s))
+ return 1;
+
+ /* get something from the wire */
+
+ /* check if we have the header */
+ if ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) ||
+ (RECORD_LAYER_get_packet_length(&s->rlayer) < DTLS1_RT_HEADER_LENGTH)) {
+ n = ssl3_read_n(s, DTLS1_RT_HEADER_LENGTH,
+ SSL3_BUFFER_get_len(&s->rlayer.rbuf), 0, 1);
+ /* read timeout is handled by dtls1_read_bytes */
+ if (n <= 0)
+ return (n); /* error or non-blocking */
+
+ /* this packet contained a partial record, dump it */
+ if (RECORD_LAYER_get_packet_length(&s->rlayer) !=
+ DTLS1_RT_HEADER_LENGTH) {
+ RECORD_LAYER_reset_packet_length(&s->rlayer);
+ goto again;
+ }
+
+ RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY);
+
+ p = RECORD_LAYER_get_packet(&s->rlayer);
+
+ if (s->msg_callback)
+ s->msg_callback(0, 0, SSL3_RT_HEADER, p, DTLS1_RT_HEADER_LENGTH,
+ s, s->msg_callback_arg);
+
+ /* Pull apart the header into the DTLS1_RECORD */
+ rr->type = *(p++);
+ ssl_major = *(p++);
+ ssl_minor = *(p++);
+ version = (ssl_major << 8) | ssl_minor;
+
+ /* sequence number is 64 bits, with top 2 bytes = epoch */
+ n2s(p, rr->epoch);
+
+ memcpy(&(RECORD_LAYER_get_read_sequence(&s->rlayer)[2]), p, 6);
+ p += 6;
+
+ n2s(p, rr->length);
+
+ /*
+ * Lets check the version. We tolerate alerts that don't have the exact
+ * version number (e.g. because of protocol version errors)
+ */
+ if (!s->first_packet && rr->type != SSL3_RT_ALERT) {
+ if (version != s->version) {
+ /* unexpected version, silently discard */
+ rr->length = 0;
+ RECORD_LAYER_reset_packet_length(&s->rlayer);
+ goto again;
+ }
+ }
+
+ if ((version & 0xff00) != (s->version & 0xff00)) {
+ /* wrong version, silently discard record */
+ rr->length = 0;
+ RECORD_LAYER_reset_packet_length(&s->rlayer);
+ goto again;
+ }
+
+ if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
+ /* record too long, silently discard it */
+ rr->length = 0;
+ RECORD_LAYER_reset_packet_length(&s->rlayer);
+ goto again;
+ }
+
+ /* now s->rlayer.rstate == SSL_ST_READ_BODY */
+ }
+
+ /* s->rlayer.rstate == SSL_ST_READ_BODY, get and decode the data */
+
+ if (rr->length >
+ RECORD_LAYER_get_packet_length(&s->rlayer) - DTLS1_RT_HEADER_LENGTH) {
+ /* now s->packet_length == DTLS1_RT_HEADER_LENGTH */
+ i = rr->length;
+ n = ssl3_read_n(s, i, i, 1, 1);
+ /* this packet contained a partial record, dump it */
+ if (n != i) {
+ rr->length = 0;
+ RECORD_LAYER_reset_packet_length(&s->rlayer);
+ goto again;
+ }
+
+ /*
+ * now n == rr->length, and s->packet_length ==
+ * DTLS1_RT_HEADER_LENGTH + rr->length
+ */
+ }
+ /* set state for later operations */
+ RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_HEADER);
+
+ /* match epochs. NULL means the packet is dropped on the floor */
+ bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
+ if (bitmap == NULL) {
+ rr->length = 0;
+ RECORD_LAYER_reset_packet_length(&s->rlayer); /* dump this record */
+ goto again; /* get another record */
+ }
+#ifndef OPENSSL_NO_SCTP
+ /* Only do replay check if no SCTP bio */
+ if (!BIO_dgram_is_sctp(SSL_get_rbio(s))) {
+#endif
+ /* Check whether this is a repeat, or aged record. */
+ /*
+ * TODO: Does it make sense to have replay protection in epoch 0 where
+ * we have no integrity negotiated yet?
+ */
+ if (!dtls1_record_replay_check(s, bitmap)) {
+ rr->length = 0;
+ RECORD_LAYER_reset_packet_length(&s->rlayer); /* dump this record */
+ goto again; /* get another record */
+ }
+#ifndef OPENSSL_NO_SCTP
+ }
+#endif
+
+ /* just read a 0 length packet */
+ if (rr->length == 0)
+ goto again;
+
+ /*
+ * If this record is from the next epoch (either HM or ALERT), and a
+ * handshake is currently in progress, buffer it since it cannot be
+ * processed at this time.
+ */
+ if (is_next_epoch) {
+ if ((SSL_in_init(s) || ossl_statem_get_in_handshake(s))) {
+ if (dtls1_buffer_record
+ (s, &(DTLS_RECORD_LAYER_get_unprocessed_rcds(&s->rlayer)),
+ rr->seq_num) < 0)
+ return -1;
+ }
+ rr->length = 0;
+ RECORD_LAYER_reset_packet_length(&s->rlayer);
+ goto again;
+ }
+
+ if (!dtls1_process_record(s, bitmap)) {
+ rr->length = 0;
+ RECORD_LAYER_reset_packet_length(&s->rlayer); /* dump this record */
+ goto again; /* get another record */
+ }
+
+ return (1);
+
+}
diff --git a/openssl-1.1.0h/ssl/s3_cbc.c b/openssl-1.1.0h/ssl/s3_cbc.c
new file mode 100644
index 0000000..9a228f7
--- /dev/null
+++ b/openssl-1.1.0h/ssl/s3_cbc.c
@@ -0,0 +1,529 @@
+/*
+ * Copyright 2012-2016 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
+ */
+
+#include "internal/constant_time_locl.h"
+#include "ssl_locl.h"
+
+#include <openssl/md5.h>
+#include <openssl/sha.h>
+
+/*
+ * MAX_HASH_BIT_COUNT_BYTES is the maximum number of bytes in the hash's
+ * length field. (SHA-384/512 have 128-bit length.)
+ */
+#define MAX_HASH_BIT_COUNT_BYTES 16
+
+/*
+ * MAX_HASH_BLOCK_SIZE is the maximum hash block size that we'll support.
+ * Currently SHA-384/512 has a 128-byte block size and that's the largest
+ * supported by TLS.)
+ */
+#define MAX_HASH_BLOCK_SIZE 128
+
+/*
+ * u32toLE serialises an unsigned, 32-bit number (n) as four bytes at (p) in
+ * little-endian order. The value of p is advanced by four.
+ */
+#define u32toLE(n, p) \
+ (*((p)++)=(unsigned char)(n), \
+ *((p)++)=(unsigned char)(n>>8), \
+ *((p)++)=(unsigned char)(n>>16), \
+ *((p)++)=(unsigned char)(n>>24))
+
+/*
+ * These functions serialize the state of a hash and thus perform the
+ * standard "final" operation without adding the padding and length that such
+ * a function typically does.
+ */
+static void tls1_md5_final_raw(void *ctx, unsigned char *md_out)
+{
+ MD5_CTX *md5 = ctx;
+ u32toLE(md5->A, md_out);
+ u32toLE(md5->B, md_out);
+ u32toLE(md5->C, md_out);
+ u32toLE(md5->D, md_out);
+}
+
+static void tls1_sha1_final_raw(void *ctx, unsigned char *md_out)
+{
+ SHA_CTX *sha1 = ctx;
+ l2n(sha1->h0, md_out);
+ l2n(sha1->h1, md_out);
+ l2n(sha1->h2, md_out);
+ l2n(sha1->h3, md_out);
+ l2n(sha1->h4, md_out);
+}
+
+static void tls1_sha256_final_raw(void *ctx, unsigned char *md_out)
+{
+ SHA256_CTX *sha256 = ctx;
+ unsigned i;
+
+ for (i = 0; i < 8; i++) {
+ l2n(sha256->h[i], md_out);
+ }
+}
+
+static void tls1_sha512_final_raw(void *ctx, unsigned char *md_out)
+{
+ SHA512_CTX *sha512 = ctx;
+ unsigned i;
+
+ for (i = 0; i < 8; i++) {
+ l2n8(sha512->h[i], md_out);
+ }
+}
+
+#undef LARGEST_DIGEST_CTX
+#define LARGEST_DIGEST_CTX SHA512_CTX
+
+/*
+ * ssl3_cbc_record_digest_supported returns 1 iff |ctx| uses a hash function
+ * which ssl3_cbc_digest_record supports.
+ */
+char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx)
+{
+ if (FIPS_mode())
+ return 0;
+ switch (EVP_MD_CTX_type(ctx)) {
+ case NID_md5:
+ case NID_sha1:
+ case NID_sha224:
+ case NID_sha256:
+ case NID_sha384:
+ case NID_sha512:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/*-
+ * ssl3_cbc_digest_record computes the MAC of a decrypted, padded SSLv3/TLS
+ * record.
+ *
+ * ctx: the EVP_MD_CTX from which we take the hash function.
+ * ssl3_cbc_record_digest_supported must return true for this EVP_MD_CTX.
+ * md_out: the digest output. At most EVP_MAX_MD_SIZE bytes will be written.
+ * md_out_size: if non-NULL, the number of output bytes is written here.
+ * header: the 13-byte, TLS record header.
+ * data: the record data itself, less any preceding explicit IV.
+ * data_plus_mac_size: the secret, reported length of the data and MAC
+ * once the padding has been removed.
+ * data_plus_mac_plus_padding_size: the public length of the whole
+ * record, including padding.
+ * is_sslv3: non-zero if we are to use SSLv3. Otherwise, TLS.
+ *
+ * On entry: by virtue of having been through one of the remove_padding
+ * functions, above, we know that data_plus_mac_size is large enough to contain
+ * a padding byte and MAC. (If the padding was invalid, it might contain the
+ * padding too. )
+ * Returns 1 on success or 0 on error
+ */
+int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
+ unsigned char *md_out,
+ size_t *md_out_size,
+ const unsigned char header[13],
+ const unsigned char *data,
+ size_t data_plus_mac_size,
+ size_t data_plus_mac_plus_padding_size,
+ const unsigned char *mac_secret,
+ unsigned mac_secret_length, char is_sslv3)
+{
+ union {
+ double align;
+ unsigned char c[sizeof(LARGEST_DIGEST_CTX)];
+ } md_state;
+ void (*md_final_raw) (void *ctx, unsigned char *md_out);
+ void (*md_transform) (void *ctx, const unsigned char *block);
+ unsigned md_size, md_block_size = 64;
+ unsigned sslv3_pad_length = 40, header_length, variance_blocks,
+ len, max_mac_bytes, num_blocks,
+ num_starting_blocks, k, mac_end_offset, c, index_a, index_b;
+ unsigned int bits; /* at most 18 bits */
+ unsigned char length_bytes[MAX_HASH_BIT_COUNT_BYTES];
+ /* hmac_pad is the masked HMAC key. */
+ unsigned char hmac_pad[MAX_HASH_BLOCK_SIZE];
+ unsigned char first_block[MAX_HASH_BLOCK_SIZE];
+ unsigned char mac_out[EVP_MAX_MD_SIZE];
+ unsigned i, j, md_out_size_u;
+ EVP_MD_CTX *md_ctx = NULL;
+ /*
+ * mdLengthSize is the number of bytes in the length field that
+ * terminates * the hash.
+ */
+ unsigned md_length_size = 8;
+ char length_is_big_endian = 1;
+ int ret;
+
+ /*
+ * This is a, hopefully redundant, check that allows us to forget about
+ * many possible overflows later in this function.
+ */
+ OPENSSL_assert(data_plus_mac_plus_padding_size < 1024 * 1024);
+
+ switch (EVP_MD_CTX_type(ctx)) {
+ case NID_md5:
+ if (MD5_Init((MD5_CTX *)md_state.c) <= 0)
+ return 0;
+ md_final_raw = tls1_md5_final_raw;
+ md_transform =
+ (void (*)(void *ctx, const unsigned char *block))MD5_Transform;
+ md_size = 16;
+ sslv3_pad_length = 48;
+ length_is_big_endian = 0;
+ break;
+ case NID_sha1:
+ if (SHA1_Init((SHA_CTX *)md_state.c) <= 0)
+ return 0;
+ md_final_raw = tls1_sha1_final_raw;
+ md_transform =
+ (void (*)(void *ctx, const unsigned char *block))SHA1_Transform;
+ md_size = 20;
+ break;
+ case NID_sha224:
+ if (SHA224_Init((SHA256_CTX *)md_state.c) <= 0)
+ return 0;
+ md_final_raw = tls1_sha256_final_raw;
+ md_transform =
+ (void (*)(void *ctx, const unsigned char *block))SHA256_Transform;
+ md_size = 224 / 8;
+ break;
+ case NID_sha256:
+ if (SHA256_Init((SHA256_CTX *)md_state.c) <= 0)
+ return 0;
+ md_final_raw = tls1_sha256_final_raw;
+ md_transform =
+ (void (*)(void *ctx, const unsigned char *block))SHA256_Transform;
+ md_size = 32;
+ break;
+ case NID_sha384:
+ if (SHA384_Init((SHA512_CTX *)md_state.c) <= 0)
+ return 0;
+ md_final_raw = tls1_sha512_final_raw;
+ md_transform =
+ (void (*)(void *ctx, const unsigned char *block))SHA512_Transform;
+ md_size = 384 / 8;
+ md_block_size = 128;
+ md_length_size = 16;
+ break;
+ case NID_sha512:
+ if (SHA512_Init((SHA512_CTX *)md_state.c) <= 0)
+ return 0;
+ md_final_raw = tls1_sha512_final_raw;
+ md_transform =
+ (void (*)(void *ctx, const unsigned char *block))SHA512_Transform;
+ md_size = 64;
+ md_block_size = 128;
+ md_length_size = 16;
+ break;
+ default:
+ /*
+ * ssl3_cbc_record_digest_supported should have been called first to
+ * check that the hash function is supported.
+ */
+ OPENSSL_assert(0);
+ if (md_out_size)
+ *md_out_size = 0;
+ return 0;
+ }
+
+ OPENSSL_assert(md_length_size <= MAX_HASH_BIT_COUNT_BYTES);
+ OPENSSL_assert(md_block_size <= MAX_HASH_BLOCK_SIZE);
+ OPENSSL_assert(md_size <= EVP_MAX_MD_SIZE);
+
+ header_length = 13;
+ if (is_sslv3) {
+ header_length = mac_secret_length + sslv3_pad_length + 8 /* sequence
+ * number */ +
+ 1 /* record type */ +
+ 2 /* record length */ ;
+ }
+
+ /*
+ * variance_blocks is the number of blocks of the hash that we have to
+ * calculate in constant time because they could be altered by the
+ * padding value. In SSLv3, the padding must be minimal so the end of
+ * the plaintext varies by, at most, 15+20 = 35 bytes. (We conservatively
+ * assume that the MAC size varies from 0..20 bytes.) In case the 9 bytes
+ * of hash termination (0x80 + 64-bit length) don't fit in the final
+ * block, we say that the final two blocks can vary based on the padding.
+ * TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not
+ * required to be minimal. Therefore we say that the final six blocks can
+ * vary based on the padding. Later in the function, if the message is
+ * short and there obviously cannot be this many blocks then
+ * variance_blocks can be reduced.
+ */
+ variance_blocks = is_sslv3 ? 2 : 6;
+ /*
+ * From now on we're dealing with the MAC, which conceptually has 13
+ * bytes of `header' before the start of the data (TLS) or 71/75 bytes
+ * (SSLv3)
+ */
+ len = data_plus_mac_plus_padding_size + header_length;
+ /*
+ * max_mac_bytes contains the maximum bytes of bytes in the MAC,
+ * including * |header|, assuming that there's no padding.
+ */
+ max_mac_bytes = len - md_size - 1;
+ /* num_blocks is the maximum number of hash blocks. */
+ num_blocks =
+ (max_mac_bytes + 1 + md_length_size + md_block_size -
+ 1) / md_block_size;
+ /*
+ * In order to calculate the MAC in constant time we have to handle the
+ * final blocks specially because the padding value could cause the end
+ * to appear somewhere in the final |variance_blocks| blocks and we can't
+ * leak where. However, |num_starting_blocks| worth of data can be hashed
+ * right away because no padding value can affect whether they are
+ * plaintext.
+ */
+ num_starting_blocks = 0;
+ /*
+ * k is the starting byte offset into the conceptual header||data where
+ * we start processing.
+ */
+ k = 0;
+ /*
+ * mac_end_offset is the index just past the end of the data to be MACed.
+ */
+ mac_end_offset = data_plus_mac_size + header_length - md_size;
+ /*
+ * c is the index of the 0x80 byte in the final hash block that contains
+ * application data.
+ */
+ c = mac_end_offset % md_block_size;
+ /*
+ * index_a is the hash block number that contains the 0x80 terminating
+ * value.
+ */
+ index_a = mac_end_offset / md_block_size;
+ /*
+ * index_b is the hash block number that contains the 64-bit hash length,
+ * in bits.
+ */
+ index_b = (mac_end_offset + md_length_size) / md_block_size;
+ /*
+ * bits is the hash-length in bits. It includes the additional hash block
+ * for the masked HMAC key, or whole of |header| in the case of SSLv3.
+ */
+
+ /*
+ * For SSLv3, if we're going to have any starting blocks then we need at
+ * least two because the header is larger than a single block.
+ */
+ if (num_blocks > variance_blocks + (is_sslv3 ? 1 : 0)) {
+ num_starting_blocks = num_blocks - variance_blocks;
+ k = md_block_size * num_starting_blocks;
+ }
+
+ bits = 8 * mac_end_offset;
+ if (!is_sslv3) {
+ /*
+ * Compute the initial HMAC block. For SSLv3, the padding and secret
+ * bytes are included in |header| because they take more than a
+ * single block.
+ */
+ bits += 8 * md_block_size;
+ memset(hmac_pad, 0, md_block_size);
+ OPENSSL_assert(mac_secret_length <= sizeof(hmac_pad));
+ memcpy(hmac_pad, mac_secret, mac_secret_length);
+ for (i = 0; i < md_block_size; i++)
+ hmac_pad[i] ^= 0x36;
+
+ md_transform(md_state.c, hmac_pad);
+ }
+
+ if (length_is_big_endian) {
+ memset(length_bytes, 0, md_length_size - 4);
+ length_bytes[md_length_size - 4] = (unsigned char)(bits >> 24);
+ length_bytes[md_length_size - 3] = (unsigned char)(bits >> 16);
+ length_bytes[md_length_size - 2] = (unsigned char)(bits >> 8);
+ length_bytes[md_length_size - 1] = (unsigned char)bits;
+ } else {
+ memset(length_bytes, 0, md_length_size);
+ length_bytes[md_length_size - 5] = (unsigned char)(bits >> 24);
+ length_bytes[md_length_size - 6] = (unsigned char)(bits >> 16);
+ length_bytes[md_length_size - 7] = (unsigned char)(bits >> 8);
+ length_bytes[md_length_size - 8] = (unsigned char)bits;
+ }
+
+ if (k > 0) {
+ if (is_sslv3) {
+ unsigned overhang;
+
+ /*
+ * The SSLv3 header is larger than a single block. overhang is
+ * the number of bytes beyond a single block that the header
+ * consumes: either 7 bytes (SHA1) or 11 bytes (MD5). There are no
+ * ciphersuites in SSLv3 that are not SHA1 or MD5 based and
+ * therefore we can be confident that the header_length will be
+ * greater than |md_block_size|. However we add a sanity check just
+ * in case
+ */
+ if (header_length <= md_block_size) {
+ /* Should never happen */
+ return 0;
+ }
+ overhang = header_length - md_block_size;
+ md_transform(md_state.c, header);
+ memcpy(first_block, header + md_block_size, overhang);
+ memcpy(first_block + overhang, data, md_block_size - overhang);
+ md_transform(md_state.c, first_block);
+ for (i = 1; i < k / md_block_size - 1; i++)
+ md_transform(md_state.c, data + md_block_size * i - overhang);
+ } else {
+ /* k is a multiple of md_block_size. */
+ memcpy(first_block, header, 13);
+ memcpy(first_block + 13, data, md_block_size - 13);
+ md_transform(md_state.c, first_block);
+ for (i = 1; i < k / md_block_size; i++)
+ md_transform(md_state.c, data + md_block_size * i - 13);
+ }
+ }
+
+ memset(mac_out, 0, sizeof(mac_out));
+
+ /*
+ * We now process the final hash blocks. For each block, we construct it
+ * in constant time. If the |i==index_a| then we'll include the 0x80
+ * bytes and zero pad etc. For each block we selectively copy it, in
+ * constant time, to |mac_out|.
+ */
+ for (i = num_starting_blocks; i <= num_starting_blocks + variance_blocks;
+ i++) {
+ unsigned char block[MAX_HASH_BLOCK_SIZE];
+ unsigned char is_block_a = constant_time_eq_8(i, index_a);
+ unsigned char is_block_b = constant_time_eq_8(i, index_b);
+ for (j = 0; j < md_block_size; j++) {
+ unsigned char b = 0, is_past_c, is_past_cp1;
+ if (k < header_length)
+ b = header[k];
+ else if (k < data_plus_mac_plus_padding_size + header_length)
+ b = data[k - header_length];
+ k++;
+
+ is_past_c = is_block_a & constant_time_ge_8(j, c);
+ is_past_cp1 = is_block_a & constant_time_ge_8(j, c + 1);
+ /*
+ * If this is the block containing the end of the application
+ * data, and we are at the offset for the 0x80 value, then
+ * overwrite b with 0x80.
+ */
+ b = constant_time_select_8(is_past_c, 0x80, b);
+ /*
+ * If this the the block containing the end of the application
+ * data and we're past the 0x80 value then just write zero.
+ */
+ b = b & ~is_past_cp1;
+ /*
+ * If this is index_b (the final block), but not index_a (the end
+ * of the data), then the 64-bit length didn't fit into index_a
+ * and we're having to add an extra block of zeros.
+ */
+ b &= ~is_block_b | is_block_a;
+
+ /*
+ * The final bytes of one of the blocks contains the length.
+ */
+ if (j >= md_block_size - md_length_size) {
+ /* If this is index_b, write a length byte. */
+ b = constant_time_select_8(is_block_b,
+ length_bytes[j -
+ (md_block_size -
+ md_length_size)], b);
+ }
+ block[j] = b;
+ }
+
+ md_transform(md_state.c, block);
+ md_final_raw(md_state.c, block);
+ /* If this is index_b, copy the hash value to |mac_out|. */
+ for (j = 0; j < md_size; j++)
+ mac_out[j] |= block[j] & is_block_b;
+ }
+
+ md_ctx = EVP_MD_CTX_new();
+ if (md_ctx == NULL)
+ goto err;
+ if (EVP_DigestInit_ex(md_ctx, EVP_MD_CTX_md(ctx), NULL /* engine */ ) <= 0)
+ goto err;
+ if (is_sslv3) {
+ /* We repurpose |hmac_pad| to contain the SSLv3 pad2 block. */
+ memset(hmac_pad, 0x5c, sslv3_pad_length);
+
+ if (EVP_DigestUpdate(md_ctx, mac_secret, mac_secret_length) <= 0
+ || EVP_DigestUpdate(md_ctx, hmac_pad, sslv3_pad_length) <= 0
+ || EVP_DigestUpdate(md_ctx, mac_out, md_size) <= 0)
+ goto err;
+ } else {
+ /* Complete the HMAC in the standard manner. */
+ for (i = 0; i < md_block_size; i++)
+ hmac_pad[i] ^= 0x6a;
+
+ if (EVP_DigestUpdate(md_ctx, hmac_pad, md_block_size) <= 0
+ || EVP_DigestUpdate(md_ctx, mac_out, md_size) <= 0)
+ goto err;
+ }
+ ret = EVP_DigestFinal(md_ctx, md_out, &md_out_size_u);
+ if (ret && md_out_size)
+ *md_out_size = md_out_size_u;
+ EVP_MD_CTX_free(md_ctx);
+
+ return 1;
+ err:
+ EVP_MD_CTX_free(md_ctx);
+ return 0;
+}
+
+/*
+ * Due to the need to use EVP in FIPS mode we can't reimplement digests but
+ * we can ensure the number of blocks processed is equal for all cases by
+ * digesting additional data.
+ */
+
+int tls_fips_digest_extra(const EVP_CIPHER_CTX *cipher_ctx,
+ EVP_MD_CTX *mac_ctx, const unsigned char *data,
+ size_t data_len, size_t orig_len)
+{
+ size_t block_size, digest_pad, blocks_data, blocks_orig;
+ if (EVP_CIPHER_CTX_mode(cipher_ctx) != EVP_CIPH_CBC_MODE)
+ return 1;
+ block_size = EVP_MD_CTX_block_size(mac_ctx);
+ /*-
+ * We are in FIPS mode if we get this far so we know we have only SHA*
+ * digests and TLS to deal with.
+ * Minimum digest padding length is 17 for SHA384/SHA512 and 9
+ * otherwise.
+ * Additional header is 13 bytes. To get the number of digest blocks
+ * processed round up the amount of data plus padding to the nearest
+ * block length. Block length is 128 for SHA384/SHA512 and 64 otherwise.
+ * So we have:
+ * blocks = (payload_len + digest_pad + 13 + block_size - 1)/block_size
+ * equivalently:
+ * blocks = (payload_len + digest_pad + 12)/block_size + 1
+ * HMAC adds a constant overhead.
+ * We're ultimately only interested in differences so this becomes
+ * blocks = (payload_len + 29)/128
+ * for SHA384/SHA512 and
+ * blocks = (payload_len + 21)/64
+ * otherwise.
+ */
+ digest_pad = block_size == 64 ? 21 : 29;
+ blocks_orig = (orig_len + digest_pad) / block_size;
+ blocks_data = (data_len + digest_pad) / block_size;
+ /*
+ * MAC enough blocks to make up the difference between the original and
+ * actual lengths plus one extra block to ensure this is never a no op.
+ * The "data" pointer should always have enough space to perform this
+ * operation as it is large enough for a maximum length TLS buffer.
+ */
+ return EVP_DigestSignUpdate(mac_ctx, data,
+ (blocks_orig - blocks_data + 1) * block_size);
+}
diff --git a/openssl-1.1.0h/ssl/s3_enc.c b/openssl-1.1.0h/ssl/s3_enc.c
new file mode 100644
index 0000000..e08857d
--- /dev/null
+++ b/openssl-1.1.0h/ssl/s3_enc.c
@@ -0,0 +1,550 @@
+/*
+ * Copyright 1995-2016 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
+ */
+
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <stdio.h>
+#include "ssl_locl.h"
+#include <openssl/evp.h>
+#include <openssl/md5.h>
+
+static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num)
+{
+ EVP_MD_CTX *m5;
+ EVP_MD_CTX *s1;
+ unsigned char buf[16], smd[SHA_DIGEST_LENGTH];
+ unsigned char c = 'A';
+ unsigned int i, j, k;
+ int ret = 0;
+
+#ifdef CHARSET_EBCDIC
+ c = os_toascii[c]; /* 'A' in ASCII */
+#endif
+ k = 0;
+ m5 = EVP_MD_CTX_new();
+ s1 = EVP_MD_CTX_new();
+ if (m5 == NULL || s1 == NULL) {
+ SSLerr(SSL_F_SSL3_GENERATE_KEY_BLOCK, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ EVP_MD_CTX_set_flags(m5, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+ for (i = 0; (int)i < num; i += MD5_DIGEST_LENGTH) {
+ k++;
+ if (k > sizeof(buf)) {
+ /* bug: 'buf' is too small for this ciphersuite */
+ SSLerr(SSL_F_SSL3_GENERATE_KEY_BLOCK, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ for (j = 0; j < k; j++)
+ buf[j] = c;
+ c++;
+ if (!EVP_DigestInit_ex(s1, EVP_sha1(), NULL)
+ || !EVP_DigestUpdate(s1, buf, k)
+ || !EVP_DigestUpdate(s1, s->session->master_key,
+ s->session->master_key_length)
+ || !EVP_DigestUpdate(s1, s->s3->server_random, SSL3_RANDOM_SIZE)
+ || !EVP_DigestUpdate(s1, s->s3->client_random, SSL3_RANDOM_SIZE)
+ || !EVP_DigestFinal_ex(s1, smd, NULL)
+ || !EVP_DigestInit_ex(m5, EVP_md5(), NULL)
+ || !EVP_DigestUpdate(m5, s->session->master_key,
+ s->session->master_key_length)
+ || !EVP_DigestUpdate(m5, smd, SHA_DIGEST_LENGTH))
+ goto err;
+ if ((int)(i + MD5_DIGEST_LENGTH) > num) {
+ if (!EVP_DigestFinal_ex(m5, smd, NULL))
+ goto err;
+ memcpy(km, smd, (num - i));
+ } else {
+ if (!EVP_DigestFinal_ex(m5, km, NULL))
+ goto err;
+ }
+
+ km += MD5_DIGEST_LENGTH;
+ }
+ OPENSSL_cleanse(smd, sizeof(smd));
+ ret = 1;
+ err:
+ EVP_MD_CTX_free(m5);
+ EVP_MD_CTX_free(s1);
+ return ret;
+}
+
+int ssl3_change_cipher_state(SSL *s, int which)
+{
+ unsigned char *p, *mac_secret;
+ unsigned char exp_key[EVP_MAX_KEY_LENGTH];
+ unsigned char exp_iv[EVP_MAX_IV_LENGTH];
+ unsigned char *ms, *key, *iv;
+ EVP_CIPHER_CTX *dd;
+ const EVP_CIPHER *c;
+#ifndef OPENSSL_NO_COMP
+ COMP_METHOD *comp;
+#endif
+ const EVP_MD *m;
+ int n, i, j, k, cl;
+ int reuse_dd = 0;
+
+ c = s->s3->tmp.new_sym_enc;
+ m = s->s3->tmp.new_hash;
+ /* m == NULL will lead to a crash later */
+ OPENSSL_assert(m);
+#ifndef OPENSSL_NO_COMP
+ if (s->s3->tmp.new_compression == NULL)
+ comp = NULL;
+ else
+ comp = s->s3->tmp.new_compression->method;
+#endif
+
+ if (which & SSL3_CC_READ) {
+ if (s->enc_read_ctx != NULL)
+ reuse_dd = 1;
+ else if ((s->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL)
+ goto err;
+ else
+ /*
+ * make sure it's initialised in case we exit later with an error
+ */
+ EVP_CIPHER_CTX_reset(s->enc_read_ctx);
+ dd = s->enc_read_ctx;
+
+ if (ssl_replace_hash(&s->read_hash, m) == NULL) {
+ SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+ goto err2;
+ }
+#ifndef OPENSSL_NO_COMP
+ /* COMPRESS */
+ COMP_CTX_free(s->expand);
+ s->expand = NULL;
+ if (comp != NULL) {
+ s->expand = COMP_CTX_new(comp);
+ if (s->expand == NULL) {
+ SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,
+ SSL_R_COMPRESSION_LIBRARY_ERROR);
+ goto err2;
+ }
+ }
+#endif
+ RECORD_LAYER_reset_read_sequence(&s->rlayer);
+ mac_secret = &(s->s3->read_mac_secret[0]);
+ } else {
+ if (s->enc_write_ctx != NULL)
+ reuse_dd = 1;
+ else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL)
+ goto err;
+ else
+ /*
+ * make sure it's initialised in case we exit later with an error
+ */
+ EVP_CIPHER_CTX_reset(s->enc_write_ctx);
+ dd = s->enc_write_ctx;
+ if (ssl_replace_hash(&s->write_hash, m) == NULL) {
+ SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+ goto err2;
+ }
+#ifndef OPENSSL_NO_COMP
+ /* COMPRESS */
+ COMP_CTX_free(s->compress);
+ s->compress = NULL;
+ if (comp != NULL) {
+ s->compress = COMP_CTX_new(comp);
+ if (s->compress == NULL) {
+ SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,
+ SSL_R_COMPRESSION_LIBRARY_ERROR);
+ goto err2;
+ }
+ }
+#endif
+ RECORD_LAYER_reset_write_sequence(&s->rlayer);
+ mac_secret = &(s->s3->write_mac_secret[0]);
+ }
+
+ if (reuse_dd)
+ EVP_CIPHER_CTX_reset(dd);
+
+ p = s->s3->tmp.key_block;
+ i = EVP_MD_size(m);
+ if (i < 0)
+ goto err2;
+ cl = EVP_CIPHER_key_length(c);
+ j = cl;
+ k = EVP_CIPHER_iv_length(c);
+ if ((which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||
+ (which == SSL3_CHANGE_CIPHER_SERVER_READ)) {
+ ms = &(p[0]);
+ n = i + i;
+ key = &(p[n]);
+ n += j + j;
+ iv = &(p[n]);
+ n += k + k;
+ } else {
+ n = i;
+ ms = &(p[n]);
+ n += i + j;
+ key = &(p[n]);
+ n += j + k;
+ iv = &(p[n]);
+ n += k;
+ }
+
+ if (n > s->s3->tmp.key_block_length) {
+ SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+ goto err2;
+ }
+
+ memcpy(mac_secret, ms, i);
+
+ if (!EVP_CipherInit_ex(dd, c, NULL, key, iv, (which & SSL3_CC_WRITE)))
+ goto err2;
+
+ OPENSSL_cleanse(exp_key, sizeof(exp_key));
+ OPENSSL_cleanse(exp_iv, sizeof(exp_iv));
+ return (1);
+ err:
+ SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
+ err2:
+ OPENSSL_cleanse(exp_key, sizeof(exp_key));
+ OPENSSL_cleanse(exp_iv, sizeof(exp_iv));
+ return (0);
+}
+
+int ssl3_setup_key_block(SSL *s)
+{
+ unsigned char *p;
+ const EVP_CIPHER *c;
+ const EVP_MD *hash;
+ int num;
+ int ret = 0;
+ SSL_COMP *comp;
+
+ if (s->s3->tmp.key_block_length != 0)
+ return (1);
+
+ if (!ssl_cipher_get_evp(s->session, &c, &hash, NULL, NULL, &comp, 0)) {
+ SSLerr(SSL_F_SSL3_SETUP_KEY_BLOCK, SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
+ return (0);
+ }
+
+ s->s3->tmp.new_sym_enc = c;
+ s->s3->tmp.new_hash = hash;
+#ifdef OPENSSL_NO_COMP
+ s->s3->tmp.new_compression = NULL;
+#else
+ s->s3->tmp.new_compression = comp;
+#endif
+
+ num = EVP_MD_size(hash);
+ if (num < 0)
+ return 0;
+
+ num = EVP_CIPHER_key_length(c) + num + EVP_CIPHER_iv_length(c);
+ num *= 2;
+
+ ssl3_cleanup_key_block(s);
+
+ if ((p = OPENSSL_malloc(num)) == NULL)
+ goto err;
+
+ s->s3->tmp.key_block_length = num;
+ s->s3->tmp.key_block = p;
+
+ ret = ssl3_generate_key_block(s, p, num);
+
+ if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) {
+ /*
+ * enable vulnerability countermeasure for CBC ciphers with known-IV
+ * problem (http://www.openssl.org/~bodo/tls-cbc.txt)
+ */
+ s->s3->need_empty_fragments = 1;
+
+ if (s->session->cipher != NULL) {
+ if (s->session->cipher->algorithm_enc == SSL_eNULL)
+ s->s3->need_empty_fragments = 0;
+
+#ifndef OPENSSL_NO_RC4
+ if (s->session->cipher->algorithm_enc == SSL_RC4)
+ s->s3->need_empty_fragments = 0;
+#endif
+ }
+ }
+
+ return ret;
+
+ err:
+ SSLerr(SSL_F_SSL3_SETUP_KEY_BLOCK, ERR_R_MALLOC_FAILURE);
+ return (0);
+}
+
+void ssl3_cleanup_key_block(SSL *s)
+{
+ OPENSSL_clear_free(s->s3->tmp.key_block, s->s3->tmp.key_block_length);
+ s->s3->tmp.key_block = NULL;
+ s->s3->tmp.key_block_length = 0;
+}
+
+int ssl3_init_finished_mac(SSL *s)
+{
+ BIO *buf = BIO_new(BIO_s_mem());
+
+ if (buf == NULL) {
+ SSLerr(SSL_F_SSL3_INIT_FINISHED_MAC, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ ssl3_free_digest_list(s);
+ s->s3->handshake_buffer = buf;
+ (void)BIO_set_close(s->s3->handshake_buffer, BIO_CLOSE);
+ return 1;
+}
+
+/*
+ * Free digest list. Also frees handshake buffer since they are always freed
+ * together.
+ */
+
+void ssl3_free_digest_list(SSL *s)
+{
+ BIO_free(s->s3->handshake_buffer);
+ s->s3->handshake_buffer = NULL;
+ EVP_MD_CTX_free(s->s3->handshake_dgst);
+ s->s3->handshake_dgst = NULL;
+}
+
+int ssl3_finish_mac(SSL *s, const unsigned char *buf, int len)
+{
+ if (s->s3->handshake_dgst == NULL)
+ /* Note: this writes to a memory BIO so a failure is a fatal error */
+ return BIO_write(s->s3->handshake_buffer, (void *)buf, len) == len;
+ else
+ return EVP_DigestUpdate(s->s3->handshake_dgst, buf, len);
+}
+
+int ssl3_digest_cached_records(SSL *s, int keep)
+{
+ const EVP_MD *md;
+ long hdatalen;
+ void *hdata;
+
+ if (s->s3->handshake_dgst == NULL) {
+ hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
+ if (hdatalen <= 0) {
+ SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS,
+ SSL_R_BAD_HANDSHAKE_LENGTH);
+ return 0;
+ }
+
+ s->s3->handshake_dgst = EVP_MD_CTX_new();
+ if (s->s3->handshake_dgst == NULL) {
+ SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ md = ssl_handshake_md(s);
+ if (md == NULL || !EVP_DigestInit_ex(s->s3->handshake_dgst, md, NULL)
+ || !EVP_DigestUpdate(s->s3->handshake_dgst, hdata, hdatalen)) {
+ SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+ if (keep == 0) {
+ BIO_free(s->s3->handshake_buffer);
+ s->s3->handshake_buffer = NULL;
+ }
+
+ return 1;
+}
+
+int ssl3_final_finish_mac(SSL *s, const char *sender, int len, unsigned char *p)
+{
+ int ret;
+ EVP_MD_CTX *ctx = NULL;
+
+ if (!ssl3_digest_cached_records(s, 0))
+ return 0;
+
+ if (EVP_MD_CTX_type(s->s3->handshake_dgst) != NID_md5_sha1) {
+ SSLerr(SSL_F_SSL3_FINAL_FINISH_MAC, SSL_R_NO_REQUIRED_DIGEST);
+ return 0;
+ }
+
+ ctx = EVP_MD_CTX_new();
+ if (ctx == NULL) {
+ SSLerr(SSL_F_SSL3_FINAL_FINISH_MAC, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (!EVP_MD_CTX_copy_ex(ctx, s->s3->handshake_dgst)) {
+ SSLerr(SSL_F_SSL3_FINAL_FINISH_MAC, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ ret = EVP_MD_CTX_size(ctx);
+ if (ret < 0) {
+ EVP_MD_CTX_reset(ctx);
+ return 0;
+ }
+
+ if ((sender != NULL && EVP_DigestUpdate(ctx, sender, len) <= 0)
+ || EVP_MD_CTX_ctrl(ctx, EVP_CTRL_SSL3_MASTER_SECRET,
+ s->session->master_key_length,
+ s->session->master_key) <= 0
+ || EVP_DigestFinal_ex(ctx, p, NULL) <= 0) {
+ SSLerr(SSL_F_SSL3_FINAL_FINISH_MAC, ERR_R_INTERNAL_ERROR);
+ ret = 0;
+ }
+
+ EVP_MD_CTX_free(ctx);
+
+ return ret;
+}
+
+int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
+ int len)
+{
+ static const unsigned char *salt[3] = {
+#ifndef CHARSET_EBCDIC
+ (const unsigned char *)"A",
+ (const unsigned char *)"BB",
+ (const unsigned char *)"CCC",
+#else
+ (const unsigned char *)"\x41",
+ (const unsigned char *)"\x42\x42",
+ (const unsigned char *)"\x43\x43\x43",
+#endif
+ };
+ unsigned char buf[EVP_MAX_MD_SIZE];
+ EVP_MD_CTX *ctx = EVP_MD_CTX_new();
+ int i, ret = 0;
+ unsigned int n;
+
+ if (ctx == NULL) {
+ SSLerr(SSL_F_SSL3_GENERATE_MASTER_SECRET, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ for (i = 0; i < 3; i++) {
+ if (EVP_DigestInit_ex(ctx, s->ctx->sha1, NULL) <= 0
+ || EVP_DigestUpdate(ctx, salt[i],
+ strlen((const char *)salt[i])) <= 0
+ || EVP_DigestUpdate(ctx, p, len) <= 0
+ || EVP_DigestUpdate(ctx, &(s->s3->client_random[0]),
+ SSL3_RANDOM_SIZE) <= 0
+ || EVP_DigestUpdate(ctx, &(s->s3->server_random[0]),
+ SSL3_RANDOM_SIZE) <= 0
+ || EVP_DigestFinal_ex(ctx, buf, &n) <= 0
+ || EVP_DigestInit_ex(ctx, s->ctx->md5, NULL) <= 0
+ || EVP_DigestUpdate(ctx, p, len) <= 0
+ || EVP_DigestUpdate(ctx, buf, n) <= 0
+ || EVP_DigestFinal_ex(ctx, out, &n) <= 0) {
+ SSLerr(SSL_F_SSL3_GENERATE_MASTER_SECRET, ERR_R_INTERNAL_ERROR);
+ ret = 0;
+ break;
+ }
+ out += n;
+ ret += n;
+ }
+ EVP_MD_CTX_free(ctx);
+
+ OPENSSL_cleanse(buf, sizeof(buf));
+ return (ret);
+}
+
+int ssl3_alert_code(int code)
+{
+ switch (code) {
+ case SSL_AD_CLOSE_NOTIFY:
+ return (SSL3_AD_CLOSE_NOTIFY);
+ case SSL_AD_UNEXPECTED_MESSAGE:
+ return (SSL3_AD_UNEXPECTED_MESSAGE);
+ case SSL_AD_BAD_RECORD_MAC:
+ return (SSL3_AD_BAD_RECORD_MAC);
+ case SSL_AD_DECRYPTION_FAILED:
+ return (SSL3_AD_BAD_RECORD_MAC);
+ case SSL_AD_RECORD_OVERFLOW:
+ return (SSL3_AD_BAD_RECORD_MAC);
+ case SSL_AD_DECOMPRESSION_FAILURE:
+ return (SSL3_AD_DECOMPRESSION_FAILURE);
+ case SSL_AD_HANDSHAKE_FAILURE:
+ return (SSL3_AD_HANDSHAKE_FAILURE);
+ case SSL_AD_NO_CERTIFICATE:
+ return (SSL3_AD_NO_CERTIFICATE);
+ case SSL_AD_BAD_CERTIFICATE:
+ return (SSL3_AD_BAD_CERTIFICATE);
+ case SSL_AD_UNSUPPORTED_CERTIFICATE:
+ return (SSL3_AD_UNSUPPORTED_CERTIFICATE);
+ case SSL_AD_CERTIFICATE_REVOKED:
+ return (SSL3_AD_CERTIFICATE_REVOKED);
+ case SSL_AD_CERTIFICATE_EXPIRED:
+ return (SSL3_AD_CERTIFICATE_EXPIRED);
+ case SSL_AD_CERTIFICATE_UNKNOWN:
+ return (SSL3_AD_CERTIFICATE_UNKNOWN);
+ case SSL_AD_ILLEGAL_PARAMETER:
+ return (SSL3_AD_ILLEGAL_PARAMETER);
+ case SSL_AD_UNKNOWN_CA:
+ return (SSL3_AD_BAD_CERTIFICATE);
+ case SSL_AD_ACCESS_DENIED:
+ return (SSL3_AD_HANDSHAKE_FAILURE);
+ case SSL_AD_DECODE_ERROR:
+ return (SSL3_AD_HANDSHAKE_FAILURE);
+ case SSL_AD_DECRYPT_ERROR:
+ return (SSL3_AD_HANDSHAKE_FAILURE);
+ case SSL_AD_EXPORT_RESTRICTION:
+ return (SSL3_AD_HANDSHAKE_FAILURE);
+ case SSL_AD_PROTOCOL_VERSION:
+ return (SSL3_AD_HANDSHAKE_FAILURE);
+ case SSL_AD_INSUFFICIENT_SECURITY:
+ return (SSL3_AD_HANDSHAKE_FAILURE);
+ case SSL_AD_INTERNAL_ERROR:
+ return (SSL3_AD_HANDSHAKE_FAILURE);
+ case SSL_AD_USER_CANCELLED:
+ return (SSL3_AD_HANDSHAKE_FAILURE);
+ case SSL_AD_NO_RENEGOTIATION:
+ return (-1); /* Don't send it :-) */
+ case SSL_AD_UNSUPPORTED_EXTENSION:
+ return (SSL3_AD_HANDSHAKE_FAILURE);
+ case SSL_AD_CERTIFICATE_UNOBTAINABLE:
+ return (SSL3_AD_HANDSHAKE_FAILURE);
+ case SSL_AD_UNRECOGNIZED_NAME:
+ return (SSL3_AD_HANDSHAKE_FAILURE);
+ case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE:
+ return (SSL3_AD_HANDSHAKE_FAILURE);
+ case SSL_AD_BAD_CERTIFICATE_HASH_VALUE:
+ return (SSL3_AD_HANDSHAKE_FAILURE);
+ case SSL_AD_UNKNOWN_PSK_IDENTITY:
+ return (TLS1_AD_UNKNOWN_PSK_IDENTITY);
+ case SSL_AD_INAPPROPRIATE_FALLBACK:
+ return (TLS1_AD_INAPPROPRIATE_FALLBACK);
+ case SSL_AD_NO_APPLICATION_PROTOCOL:
+ return (TLS1_AD_NO_APPLICATION_PROTOCOL);
+ default:
+ return (-1);
+ }
+}
diff --git a/openssl-1.1.0h/ssl/s3_lib.c b/openssl-1.1.0h/ssl/s3_lib.c
new file mode 100644
index 0000000..ad7532b
--- /dev/null
+++ b/openssl-1.1.0h/ssl/s3_lib.c
@@ -0,0 +1,4140 @@
+/*
+ * Copyright 1995-2016 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
+ */
+
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * ECC cipher suite support in OpenSSL originally written by
+ * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
+ *
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <stdio.h>
+#include <openssl/objects.h>
+#include "ssl_locl.h"
+#include <openssl/md5.h>
+#include <openssl/dh.h>
+#include <openssl/rand.h>
+
+#define SSL3_NUM_CIPHERS OSSL_NELEM(ssl3_ciphers)
+
+/*
+ * The list of available ciphers, mostly organized into the following
+ * groups:
+ * Always there
+ * EC
+ * PSK
+ * SRP (within that: RSA EC PSK)
+ * Cipher families: Chacha/poly, Camellila, Gost, IDEA, SEED
+ * Weak ciphers
+ */
+static SSL_CIPHER ssl3_ciphers[] = {
+ {
+ 1,
+ SSL3_TXT_RSA_NULL_MD5,
+ SSL3_CK_RSA_NULL_MD5,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_eNULL,
+ SSL_MD5,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_STRONG_NONE,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 0,
+ 0,
+ },
+ {
+ 1,
+ SSL3_TXT_RSA_NULL_SHA,
+ SSL3_CK_RSA_NULL_SHA,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_eNULL,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_STRONG_NONE | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 0,
+ 0,
+ },
+#ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
+ {
+ 1,
+ SSL3_TXT_RSA_DES_192_CBC3_SHA,
+ SSL3_CK_RSA_DES_192_CBC3_SHA,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_3DES,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 112,
+ 168,
+ },
+ {
+ 1,
+ SSL3_TXT_DHE_DSS_DES_192_CBC3_SHA,
+ SSL3_CK_DHE_DSS_DES_192_CBC3_SHA,
+ SSL_kDHE,
+ SSL_aDSS,
+ SSL_3DES,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 112,
+ 168,
+ },
+ {
+ 1,
+ SSL3_TXT_DHE_RSA_DES_192_CBC3_SHA,
+ SSL3_CK_DHE_RSA_DES_192_CBC3_SHA,
+ SSL_kDHE,
+ SSL_aRSA,
+ SSL_3DES,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 112,
+ 168,
+ },
+ {
+ 1,
+ SSL3_TXT_ADH_DES_192_CBC_SHA,
+ SSL3_CK_ADH_DES_192_CBC_SHA,
+ SSL_kDHE,
+ SSL_aNULL,
+ SSL_3DES,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 112,
+ 168,
+ },
+#endif
+ {
+ 1,
+ TLS1_TXT_RSA_WITH_AES_128_SHA,
+ TLS1_CK_RSA_WITH_AES_128_SHA,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_AES128,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_DSS_WITH_AES_128_SHA,
+ TLS1_CK_DHE_DSS_WITH_AES_128_SHA,
+ SSL_kDHE,
+ SSL_aDSS,
+ SSL_AES128,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_RSA_WITH_AES_128_SHA,
+ TLS1_CK_DHE_RSA_WITH_AES_128_SHA,
+ SSL_kDHE,
+ SSL_aRSA,
+ SSL_AES128,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ADH_WITH_AES_128_SHA,
+ TLS1_CK_ADH_WITH_AES_128_SHA,
+ SSL_kDHE,
+ SSL_aNULL,
+ SSL_AES128,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_WITH_AES_256_SHA,
+ TLS1_CK_RSA_WITH_AES_256_SHA,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_AES256,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_DSS_WITH_AES_256_SHA,
+ TLS1_CK_DHE_DSS_WITH_AES_256_SHA,
+ SSL_kDHE,
+ SSL_aDSS,
+ SSL_AES256,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_RSA_WITH_AES_256_SHA,
+ TLS1_CK_DHE_RSA_WITH_AES_256_SHA,
+ SSL_kDHE,
+ SSL_aRSA,
+ SSL_AES256,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_ADH_WITH_AES_256_SHA,
+ TLS1_CK_ADH_WITH_AES_256_SHA,
+ SSL_kDHE,
+ SSL_aNULL,
+ SSL_AES256,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_WITH_NULL_SHA256,
+ TLS1_CK_RSA_WITH_NULL_SHA256,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_eNULL,
+ SSL_SHA256,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_STRONG_NONE | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 0,
+ 0,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_WITH_AES_128_SHA256,
+ TLS1_CK_RSA_WITH_AES_128_SHA256,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_AES128,
+ SSL_SHA256,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_WITH_AES_256_SHA256,
+ TLS1_CK_RSA_WITH_AES_256_SHA256,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_AES256,
+ SSL_SHA256,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_DSS_WITH_AES_128_SHA256,
+ TLS1_CK_DHE_DSS_WITH_AES_128_SHA256,
+ SSL_kDHE,
+ SSL_aDSS,
+ SSL_AES128,
+ SSL_SHA256,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256,
+ TLS1_CK_DHE_RSA_WITH_AES_128_SHA256,
+ SSL_kDHE,
+ SSL_aRSA,
+ SSL_AES128,
+ SSL_SHA256,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_DSS_WITH_AES_256_SHA256,
+ TLS1_CK_DHE_DSS_WITH_AES_256_SHA256,
+ SSL_kDHE,
+ SSL_aDSS,
+ SSL_AES256,
+ SSL_SHA256,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256,
+ TLS1_CK_DHE_RSA_WITH_AES_256_SHA256,
+ SSL_kDHE,
+ SSL_aRSA,
+ SSL_AES256,
+ SSL_SHA256,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_ADH_WITH_AES_128_SHA256,
+ TLS1_CK_ADH_WITH_AES_128_SHA256,
+ SSL_kDHE,
+ SSL_aNULL,
+ SSL_AES128,
+ SSL_SHA256,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ADH_WITH_AES_256_SHA256,
+ TLS1_CK_ADH_WITH_AES_256_SHA256,
+ SSL_kDHE,
+ SSL_aNULL,
+ SSL_AES256,
+ SSL_SHA256,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256,
+ TLS1_CK_RSA_WITH_AES_128_GCM_SHA256,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_AES128GCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_WITH_AES_256_GCM_SHA384,
+ TLS1_CK_RSA_WITH_AES_256_GCM_SHA384,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_AES256GCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256,
+ TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256,
+ SSL_kDHE,
+ SSL_aRSA,
+ SSL_AES128GCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384,
+ TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384,
+ SSL_kDHE,
+ SSL_aRSA,
+ SSL_AES256GCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_DSS_WITH_AES_128_GCM_SHA256,
+ TLS1_CK_DHE_DSS_WITH_AES_128_GCM_SHA256,
+ SSL_kDHE,
+ SSL_aDSS,
+ SSL_AES128GCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_DSS_WITH_AES_256_GCM_SHA384,
+ TLS1_CK_DHE_DSS_WITH_AES_256_GCM_SHA384,
+ SSL_kDHE,
+ SSL_aDSS,
+ SSL_AES256GCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_ADH_WITH_AES_128_GCM_SHA256,
+ TLS1_CK_ADH_WITH_AES_128_GCM_SHA256,
+ SSL_kDHE,
+ SSL_aNULL,
+ SSL_AES128GCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ADH_WITH_AES_256_GCM_SHA384,
+ TLS1_CK_ADH_WITH_AES_256_GCM_SHA384,
+ SSL_kDHE,
+ SSL_aNULL,
+ SSL_AES256GCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_WITH_AES_128_CCM,
+ TLS1_CK_RSA_WITH_AES_128_CCM,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_AES128CCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_WITH_AES_256_CCM,
+ TLS1_CK_RSA_WITH_AES_256_CCM,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_AES256CCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_RSA_WITH_AES_128_CCM,
+ TLS1_CK_DHE_RSA_WITH_AES_128_CCM,
+ SSL_kDHE,
+ SSL_aRSA,
+ SSL_AES128CCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_RSA_WITH_AES_256_CCM,
+ TLS1_CK_DHE_RSA_WITH_AES_256_CCM,
+ SSL_kDHE,
+ SSL_aRSA,
+ SSL_AES256CCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_WITH_AES_128_CCM_8,
+ TLS1_CK_RSA_WITH_AES_128_CCM_8,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_AES128CCM8,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_WITH_AES_256_CCM_8,
+ TLS1_CK_RSA_WITH_AES_256_CCM_8,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_AES256CCM8,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_RSA_WITH_AES_128_CCM_8,
+ TLS1_CK_DHE_RSA_WITH_AES_128_CCM_8,
+ SSL_kDHE,
+ SSL_aRSA,
+ SSL_AES128CCM8,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_RSA_WITH_AES_256_CCM_8,
+ TLS1_CK_DHE_RSA_WITH_AES_256_CCM_8,
+ SSL_kDHE,
+ SSL_aRSA,
+ SSL_AES256CCM8,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_AES_128_CCM,
+ TLS1_CK_PSK_WITH_AES_128_CCM,
+ SSL_kPSK,
+ SSL_aPSK,
+ SSL_AES128CCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_AES_256_CCM,
+ TLS1_CK_PSK_WITH_AES_256_CCM,
+ SSL_kPSK,
+ SSL_aPSK,
+ SSL_AES256CCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_PSK_WITH_AES_128_CCM,
+ TLS1_CK_DHE_PSK_WITH_AES_128_CCM,
+ SSL_kDHEPSK,
+ SSL_aPSK,
+ SSL_AES128CCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_PSK_WITH_AES_256_CCM,
+ TLS1_CK_DHE_PSK_WITH_AES_256_CCM,
+ SSL_kDHEPSK,
+ SSL_aPSK,
+ SSL_AES256CCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_AES_128_CCM_8,
+ TLS1_CK_PSK_WITH_AES_128_CCM_8,
+ SSL_kPSK,
+ SSL_aPSK,
+ SSL_AES128CCM8,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_AES_256_CCM_8,
+ TLS1_CK_PSK_WITH_AES_256_CCM_8,
+ SSL_kPSK,
+ SSL_aPSK,
+ SSL_AES256CCM8,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_PSK_WITH_AES_128_CCM_8,
+ TLS1_CK_DHE_PSK_WITH_AES_128_CCM_8,
+ SSL_kDHEPSK,
+ SSL_aPSK,
+ SSL_AES128CCM8,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_PSK_WITH_AES_256_CCM_8,
+ TLS1_CK_DHE_PSK_WITH_AES_256_CCM_8,
+ SSL_kDHEPSK,
+ SSL_aPSK,
+ SSL_AES256CCM8,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CCM,
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CCM,
+ SSL_kECDHE,
+ SSL_aECDSA,
+ SSL_AES128CCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CCM,
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CCM,
+ SSL_kECDHE,
+ SSL_aECDSA,
+ SSL_AES256CCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CCM_8,
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CCM_8,
+ SSL_kECDHE,
+ SSL_aECDSA,
+ SSL_AES128CCM8,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CCM_8,
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CCM_8,
+ SSL_kECDHE,
+ SSL_aECDSA,
+ SSL_AES256CCM8,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 256,
+ 256,
+ },
+
+#ifndef OPENSSL_NO_EC
+ {
+ 1,
+ TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA,
+ TLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA,
+ SSL_kECDHE,
+ SSL_aECDSA,
+ SSL_eNULL,
+ SSL_SHA1,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_STRONG_NONE | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 0,
+ 0,
+ },
+# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
+ {
+ 1,
+ TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA,
+ TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA,
+ SSL_kECDHE,
+ SSL_aECDSA,
+ SSL_3DES,
+ SSL_SHA1,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 112,
+ 168,
+ },
+# endif
+ {
+ 1,
+ TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ SSL_kECDHE,
+ SSL_aECDSA,
+ SSL_AES128,
+ SSL_SHA1,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+ SSL_kECDHE,
+ SSL_aECDSA,
+ SSL_AES256,
+ SSL_SHA1,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_RSA_WITH_NULL_SHA,
+ TLS1_CK_ECDHE_RSA_WITH_NULL_SHA,
+ SSL_kECDHE,
+ SSL_aRSA,
+ SSL_eNULL,
+ SSL_SHA1,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_STRONG_NONE | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 0,
+ 0,
+ },
+# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
+ {
+ 1,
+ TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA,
+ TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA,
+ SSL_kECDHE,
+ SSL_aRSA,
+ SSL_3DES,
+ SSL_SHA1,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 112,
+ 168,
+ },
+# endif
+ {
+ 1,
+ TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ SSL_kECDHE,
+ SSL_aRSA,
+ SSL_AES128,
+ SSL_SHA1,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+ TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+ SSL_kECDHE,
+ SSL_aRSA,
+ SSL_AES256,
+ SSL_SHA1,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDH_anon_WITH_NULL_SHA,
+ TLS1_CK_ECDH_anon_WITH_NULL_SHA,
+ SSL_kECDHE,
+ SSL_aNULL,
+ SSL_eNULL,
+ SSL_SHA1,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_STRONG_NONE | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 0,
+ 0,
+ },
+# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
+ {
+ 1,
+ TLS1_TXT_ECDH_anon_WITH_DES_192_CBC3_SHA,
+ TLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA,
+ SSL_kECDHE,
+ SSL_aNULL,
+ SSL_3DES,
+ SSL_SHA1,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 112,
+ 168,
+ },
+# endif
+ {
+ 1,
+ TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA,
+ TLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA,
+ SSL_kECDHE,
+ SSL_aNULL,
+ SSL_AES128,
+ SSL_SHA1,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA,
+ TLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA,
+ SSL_kECDHE,
+ SSL_aNULL,
+ SSL_AES256,
+ SSL_SHA1,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_SHA256,
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256,
+ SSL_kECDHE,
+ SSL_aECDSA,
+ SSL_AES128,
+ SSL_SHA256,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_SHA384,
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384,
+ SSL_kECDHE,
+ SSL_aECDSA,
+ SSL_AES256,
+ SSL_SHA384,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256,
+ TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256,
+ SSL_kECDHE,
+ SSL_aRSA,
+ SSL_AES128,
+ SSL_SHA256,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384,
+ TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384,
+ SSL_kECDHE,
+ SSL_aRSA,
+ SSL_AES256,
+ SSL_SHA384,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ SSL_kECDHE,
+ SSL_aECDSA,
+ SSL_AES128GCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ SSL_kECDHE,
+ SSL_aECDSA,
+ SSL_AES256GCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ SSL_kECDHE,
+ SSL_aRSA,
+ SSL_AES128GCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ SSL_kECDHE,
+ SSL_aRSA,
+ SSL_AES256GCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+#endif /* OPENSSL_NO_EC */
+
+#ifndef OPENSSL_NO_PSK
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_NULL_SHA,
+ TLS1_CK_PSK_WITH_NULL_SHA,
+ SSL_kPSK,
+ SSL_aPSK,
+ SSL_eNULL,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_STRONG_NONE | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 0,
+ 0,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_PSK_WITH_NULL_SHA,
+ TLS1_CK_DHE_PSK_WITH_NULL_SHA,
+ SSL_kDHEPSK,
+ SSL_aPSK,
+ SSL_eNULL,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_STRONG_NONE | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 0,
+ 0,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_PSK_WITH_NULL_SHA,
+ TLS1_CK_RSA_PSK_WITH_NULL_SHA,
+ SSL_kRSAPSK,
+ SSL_aRSA,
+ SSL_eNULL,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_STRONG_NONE | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 0,
+ 0,
+ },
+# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_3DES_EDE_CBC_SHA,
+ TLS1_CK_PSK_WITH_3DES_EDE_CBC_SHA,
+ SSL_kPSK,
+ SSL_aPSK,
+ SSL_3DES,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 112,
+ 168,
+ },
+# endif
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_AES_128_CBC_SHA,
+ TLS1_CK_PSK_WITH_AES_128_CBC_SHA,
+ SSL_kPSK,
+ SSL_aPSK,
+ SSL_AES128,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_AES_256_CBC_SHA,
+ TLS1_CK_PSK_WITH_AES_256_CBC_SHA,
+ SSL_kPSK,
+ SSL_aPSK,
+ SSL_AES256,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
+ {
+ 1,
+ TLS1_TXT_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
+ TLS1_CK_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
+ SSL_kDHEPSK,
+ SSL_aPSK,
+ SSL_3DES,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 112,
+ 168,
+ },
+# endif
+ {
+ 1,
+ TLS1_TXT_DHE_PSK_WITH_AES_128_CBC_SHA,
+ TLS1_CK_DHE_PSK_WITH_AES_128_CBC_SHA,
+ SSL_kDHEPSK,
+ SSL_aPSK,
+ SSL_AES128,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_PSK_WITH_AES_256_CBC_SHA,
+ TLS1_CK_DHE_PSK_WITH_AES_256_CBC_SHA,
+ SSL_kDHEPSK,
+ SSL_aPSK,
+ SSL_AES256,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
+ {
+ 1,
+ TLS1_TXT_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
+ TLS1_CK_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
+ SSL_kRSAPSK,
+ SSL_aRSA,
+ SSL_3DES,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 112,
+ 168,
+ },
+# endif
+ {
+ 1,
+ TLS1_TXT_RSA_PSK_WITH_AES_128_CBC_SHA,
+ TLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA,
+ SSL_kRSAPSK,
+ SSL_aRSA,
+ SSL_AES128,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA,
+ TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA,
+ SSL_kRSAPSK,
+ SSL_aRSA,
+ SSL_AES256,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_AES_128_GCM_SHA256,
+ TLS1_CK_PSK_WITH_AES_128_GCM_SHA256,
+ SSL_kPSK,
+ SSL_aPSK,
+ SSL_AES128GCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_AES_256_GCM_SHA384,
+ TLS1_CK_PSK_WITH_AES_256_GCM_SHA384,
+ SSL_kPSK,
+ SSL_aPSK,
+ SSL_AES256GCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_PSK_WITH_AES_128_GCM_SHA256,
+ TLS1_CK_DHE_PSK_WITH_AES_128_GCM_SHA256,
+ SSL_kDHEPSK,
+ SSL_aPSK,
+ SSL_AES128GCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_PSK_WITH_AES_256_GCM_SHA384,
+ TLS1_CK_DHE_PSK_WITH_AES_256_GCM_SHA384,
+ SSL_kDHEPSK,
+ SSL_aPSK,
+ SSL_AES256GCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_PSK_WITH_AES_128_GCM_SHA256,
+ TLS1_CK_RSA_PSK_WITH_AES_128_GCM_SHA256,
+ SSL_kRSAPSK,
+ SSL_aRSA,
+ SSL_AES128GCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_PSK_WITH_AES_256_GCM_SHA384,
+ TLS1_CK_RSA_PSK_WITH_AES_256_GCM_SHA384,
+ SSL_kRSAPSK,
+ SSL_aRSA,
+ SSL_AES256GCM,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_AES_128_CBC_SHA256,
+ TLS1_CK_PSK_WITH_AES_128_CBC_SHA256,
+ SSL_kPSK,
+ SSL_aPSK,
+ SSL_AES128,
+ SSL_SHA256,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_AES_256_CBC_SHA384,
+ TLS1_CK_PSK_WITH_AES_256_CBC_SHA384,
+ SSL_kPSK,
+ SSL_aPSK,
+ SSL_AES256,
+ SSL_SHA384,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_NULL_SHA256,
+ TLS1_CK_PSK_WITH_NULL_SHA256,
+ SSL_kPSK,
+ SSL_aPSK,
+ SSL_eNULL,
+ SSL_SHA256,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_STRONG_NONE | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 0,
+ 0,
+ },
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_NULL_SHA384,
+ TLS1_CK_PSK_WITH_NULL_SHA384,
+ SSL_kPSK,
+ SSL_aPSK,
+ SSL_eNULL,
+ SSL_SHA384,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_STRONG_NONE | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 0,
+ 0,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_PSK_WITH_AES_128_CBC_SHA256,
+ TLS1_CK_DHE_PSK_WITH_AES_128_CBC_SHA256,
+ SSL_kDHEPSK,
+ SSL_aPSK,
+ SSL_AES128,
+ SSL_SHA256,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_PSK_WITH_AES_256_CBC_SHA384,
+ TLS1_CK_DHE_PSK_WITH_AES_256_CBC_SHA384,
+ SSL_kDHEPSK,
+ SSL_aPSK,
+ SSL_AES256,
+ SSL_SHA384,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_PSK_WITH_NULL_SHA256,
+ TLS1_CK_DHE_PSK_WITH_NULL_SHA256,
+ SSL_kDHEPSK,
+ SSL_aPSK,
+ SSL_eNULL,
+ SSL_SHA256,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_STRONG_NONE | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 0,
+ 0,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_PSK_WITH_NULL_SHA384,
+ TLS1_CK_DHE_PSK_WITH_NULL_SHA384,
+ SSL_kDHEPSK,
+ SSL_aPSK,
+ SSL_eNULL,
+ SSL_SHA384,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_STRONG_NONE | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 0,
+ 0,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_PSK_WITH_AES_128_CBC_SHA256,
+ TLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA256,
+ SSL_kRSAPSK,
+ SSL_aRSA,
+ SSL_AES128,
+ SSL_SHA256,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA384,
+ TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA384,
+ SSL_kRSAPSK,
+ SSL_aRSA,
+ SSL_AES256,
+ SSL_SHA384,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_PSK_WITH_NULL_SHA256,
+ TLS1_CK_RSA_PSK_WITH_NULL_SHA256,
+ SSL_kRSAPSK,
+ SSL_aRSA,
+ SSL_eNULL,
+ SSL_SHA256,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_STRONG_NONE | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 0,
+ 0,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_PSK_WITH_NULL_SHA384,
+ TLS1_CK_RSA_PSK_WITH_NULL_SHA384,
+ SSL_kRSAPSK,
+ SSL_aRSA,
+ SSL_eNULL,
+ SSL_SHA384,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_STRONG_NONE | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 0,
+ 0,
+ },
+# ifndef OPENSSL_NO_EC
+# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
+ {
+ 1,
+ TLS1_TXT_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
+ TLS1_CK_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
+ SSL_kECDHEPSK,
+ SSL_aPSK,
+ SSL_3DES,
+ SSL_SHA1,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 112,
+ 168,
+ },
+# endif
+ {
+ 1,
+ TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA,
+ TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA,
+ SSL_kECDHEPSK,
+ SSL_aPSK,
+ SSL_AES128,
+ SSL_SHA1,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA,
+ TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA,
+ SSL_kECDHEPSK,
+ SSL_aPSK,
+ SSL_AES256,
+ SSL_SHA1,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
+ TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
+ SSL_kECDHEPSK,
+ SSL_aPSK,
+ SSL_AES128,
+ SSL_SHA256,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
+ TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
+ SSL_kECDHEPSK,
+ SSL_aPSK,
+ SSL_AES256,
+ SSL_SHA384,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA,
+ TLS1_CK_ECDHE_PSK_WITH_NULL_SHA,
+ SSL_kECDHEPSK,
+ SSL_aPSK,
+ SSL_eNULL,
+ SSL_SHA1,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_STRONG_NONE | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 0,
+ 0,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA256,
+ TLS1_CK_ECDHE_PSK_WITH_NULL_SHA256,
+ SSL_kECDHEPSK,
+ SSL_aPSK,
+ SSL_eNULL,
+ SSL_SHA256,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_STRONG_NONE | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 0,
+ 0,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA384,
+ TLS1_CK_ECDHE_PSK_WITH_NULL_SHA384,
+ SSL_kECDHEPSK,
+ SSL_aPSK,
+ SSL_eNULL,
+ SSL_SHA384,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_STRONG_NONE | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 0,
+ 0,
+ },
+# endif /* OPENSSL_NO_EC */
+#endif /* OPENSSL_NO_PSK */
+
+#ifndef OPENSSL_NO_SRP
+# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
+ {
+ 1,
+ TLS1_TXT_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
+ TLS1_CK_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
+ SSL_kSRP,
+ SSL_aSRP,
+ SSL_3DES,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 112,
+ 168,
+ },
+ {
+ 1,
+ TLS1_TXT_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
+ TLS1_CK_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
+ SSL_kSRP,
+ SSL_aRSA,
+ SSL_3DES,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 112,
+ 168,
+ },
+ {
+ 1,
+ TLS1_TXT_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
+ TLS1_CK_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
+ SSL_kSRP,
+ SSL_aDSS,
+ SSL_3DES,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 112,
+ 168,
+ },
+# endif
+ {
+ 1,
+ TLS1_TXT_SRP_SHA_WITH_AES_128_CBC_SHA,
+ TLS1_CK_SRP_SHA_WITH_AES_128_CBC_SHA,
+ SSL_kSRP,
+ SSL_aSRP,
+ SSL_AES128,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
+ TLS1_CK_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
+ SSL_kSRP,
+ SSL_aRSA,
+ SSL_AES128,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
+ TLS1_CK_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
+ SSL_kSRP,
+ SSL_aDSS,
+ SSL_AES128,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_SRP_SHA_WITH_AES_256_CBC_SHA,
+ TLS1_CK_SRP_SHA_WITH_AES_256_CBC_SHA,
+ SSL_kSRP,
+ SSL_aSRP,
+ SSL_AES256,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
+ TLS1_CK_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
+ SSL_kSRP,
+ SSL_aRSA,
+ SSL_AES256,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
+ TLS1_CK_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
+ SSL_kSRP,
+ SSL_aDSS,
+ SSL_AES256,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+#endif /* OPENSSL_NO_SRP */
+
+#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
+# ifndef OPENSSL_NO_RSA
+ {
+ 1,
+ TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305,
+ TLS1_CK_DHE_RSA_WITH_CHACHA20_POLY1305,
+ SSL_kDHE,
+ SSL_aRSA,
+ SSL_CHACHA20POLY1305,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 256,
+ 256,
+ },
+# endif /* OPENSSL_NO_RSA */
+
+# ifndef OPENSSL_NO_EC
+ {
+ 1,
+ TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+ TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+ SSL_kECDHE,
+ SSL_aRSA,
+ SSL_CHACHA20POLY1305,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
+ TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
+ SSL_kECDHE,
+ SSL_aECDSA,
+ SSL_CHACHA20POLY1305,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 256,
+ 256,
+ },
+# endif /* OPENSSL_NO_EC */
+
+# ifndef OPENSSL_NO_PSK
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_CHACHA20_POLY1305,
+ TLS1_CK_PSK_WITH_CHACHA20_POLY1305,
+ SSL_kPSK,
+ SSL_aPSK,
+ SSL_CHACHA20POLY1305,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_PSK_WITH_CHACHA20_POLY1305,
+ TLS1_CK_ECDHE_PSK_WITH_CHACHA20_POLY1305,
+ SSL_kECDHEPSK,
+ SSL_aPSK,
+ SSL_CHACHA20POLY1305,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_PSK_WITH_CHACHA20_POLY1305,
+ TLS1_CK_DHE_PSK_WITH_CHACHA20_POLY1305,
+ SSL_kDHEPSK,
+ SSL_aPSK,
+ SSL_CHACHA20POLY1305,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_PSK_WITH_CHACHA20_POLY1305,
+ TLS1_CK_RSA_PSK_WITH_CHACHA20_POLY1305,
+ SSL_kRSAPSK,
+ SSL_aRSA,
+ SSL_CHACHA20POLY1305,
+ SSL_AEAD,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 256,
+ 256,
+ },
+# endif /* OPENSSL_NO_PSK */
+#endif /* !defined(OPENSSL_NO_CHACHA) &&
+ * !defined(OPENSSL_NO_POLY1305) */
+
+#ifndef OPENSSL_NO_CAMELLIA
+ {
+ 1,
+ TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_CAMELLIA128,
+ SSL_SHA256,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,
+ TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,
+ SSL_kEDH,
+ SSL_aDSS,
+ SSL_CAMELLIA128,
+ SSL_SHA256,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ SSL_kEDH,
+ SSL_aRSA,
+ SSL_CAMELLIA128,
+ SSL_SHA256,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA256,
+ TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA256,
+ SSL_kEDH,
+ SSL_aNULL,
+ SSL_CAMELLIA128,
+ SSL_SHA256,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+ TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_CAMELLIA256,
+ SSL_SHA256,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,
+ TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,
+ SSL_kEDH,
+ SSL_aDSS,
+ SSL_CAMELLIA256,
+ SSL_SHA256,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+ TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+ SSL_kEDH,
+ SSL_aRSA,
+ SSL_CAMELLIA256,
+ SSL_SHA256,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA256,
+ TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA256,
+ SSL_kEDH,
+ SSL_aNULL,
+ SSL_CAMELLIA256,
+ SSL_SHA256,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_CAMELLIA256,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
+ TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
+ SSL_kDHE,
+ SSL_aDSS,
+ SSL_CAMELLIA256,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ SSL_kDHE,
+ SSL_aRSA,
+ SSL_CAMELLIA256,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA,
+ TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA,
+ SSL_kDHE,
+ SSL_aNULL,
+ SSL_CAMELLIA256,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_CAMELLIA128,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
+ TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
+ SSL_kDHE,
+ SSL_aDSS,
+ SSL_CAMELLIA128,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ SSL_kDHE,
+ SSL_aRSA,
+ SSL_CAMELLIA128,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA,
+ TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA,
+ SSL_kDHE,
+ SSL_aNULL,
+ SSL_CAMELLIA128,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+
+# ifndef OPENSSL_NO_EC
+ {
+ 1,
+ TLS1_TXT_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
+ TLS1_CK_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
+ SSL_kECDHE,
+ SSL_aECDSA,
+ SSL_CAMELLIA128,
+ SSL_SHA256,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+ TLS1_CK_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+ SSL_kECDHE,
+ SSL_aECDSA,
+ SSL_CAMELLIA256,
+ SSL_SHA384,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ TLS1_CK_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ SSL_kECDHE,
+ SSL_aRSA,
+ SSL_CAMELLIA128,
+ SSL_SHA256,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
+ TLS1_CK_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
+ SSL_kECDHE,
+ SSL_aRSA,
+ SSL_CAMELLIA256,
+ SSL_SHA384,
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+# endif /* OPENSSL_NO_EC */
+
+# ifndef OPENSSL_NO_PSK
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ TLS1_CK_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ SSL_kPSK,
+ SSL_aPSK,
+ SSL_CAMELLIA128,
+ SSL_SHA256,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ TLS1_CK_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ SSL_kPSK,
+ SSL_aPSK,
+ SSL_CAMELLIA256,
+ SSL_SHA384,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ TLS1_CK_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ SSL_kDHEPSK,
+ SSL_aPSK,
+ SSL_CAMELLIA128,
+ SSL_SHA256,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ TLS1_CK_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ SSL_kDHEPSK,
+ SSL_aPSK,
+ SSL_CAMELLIA256,
+ SSL_SHA384,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ TLS1_CK_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ SSL_kRSAPSK,
+ SSL_aRSA,
+ SSL_CAMELLIA128,
+ SSL_SHA256,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ TLS1_CK_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ SSL_kRSAPSK,
+ SSL_aRSA,
+ SSL_CAMELLIA256,
+ SSL_SHA384,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ TLS1_CK_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ SSL_kECDHEPSK,
+ SSL_aPSK,
+ SSL_CAMELLIA128,
+ SSL_SHA256,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ TLS1_CK_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ SSL_kECDHEPSK,
+ SSL_aPSK,
+ SSL_CAMELLIA256,
+ SSL_SHA384,
+ TLS1_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+# endif /* OPENSSL_NO_PSK */
+
+#endif /* OPENSSL_NO_CAMELLIA */
+
+#ifndef OPENSSL_NO_GOST
+ {
+ 1,
+ "GOST2001-GOST89-GOST89",
+ 0x3000081,
+ SSL_kGOST,
+ SSL_aGOST01,
+ SSL_eGOST2814789CNT,
+ SSL_GOST89MAC,
+ TLS1_VERSION, TLS1_2_VERSION,
+ 0, 0,
+ SSL_HIGH,
+ SSL_HANDSHAKE_MAC_GOST94 | TLS1_PRF_GOST94 | TLS1_STREAM_MAC,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ "GOST2001-NULL-GOST94",
+ 0x3000083,
+ SSL_kGOST,
+ SSL_aGOST01,
+ SSL_eNULL,
+ SSL_GOST94,
+ TLS1_VERSION, TLS1_2_VERSION,
+ 0, 0,
+ SSL_STRONG_NONE,
+ SSL_HANDSHAKE_MAC_GOST94 | TLS1_PRF_GOST94,
+ 0,
+ 0,
+ },
+ {
+ 1,
+ "GOST2012-GOST8912-GOST8912",
+ 0x0300ff85,
+ SSL_kGOST,
+ SSL_aGOST12 | SSL_aGOST01,
+ SSL_eGOST2814789CNT12,
+ SSL_GOST89MAC12,
+ TLS1_VERSION, TLS1_2_VERSION,
+ 0, 0,
+ SSL_HIGH,
+ SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_PRF_GOST12_256 | TLS1_STREAM_MAC,
+ 256,
+ 256,
+ },
+ {
+ 1,
+ "GOST2012-NULL-GOST12",
+ 0x0300ff87,
+ SSL_kGOST,
+ SSL_aGOST12 | SSL_aGOST01,
+ SSL_eNULL,
+ SSL_GOST12_256,
+ TLS1_VERSION, TLS1_2_VERSION,
+ 0, 0,
+ SSL_STRONG_NONE,
+ SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_PRF_GOST12_256 | TLS1_STREAM_MAC,
+ 0,
+ 0,
+ },
+#endif /* OPENSSL_NO_GOST */
+
+#ifndef OPENSSL_NO_IDEA
+ {
+ 1,
+ SSL3_TXT_RSA_IDEA_128_SHA,
+ SSL3_CK_RSA_IDEA_128_SHA,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_IDEA,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_1_VERSION,
+ DTLS1_BAD_VER, DTLS1_VERSION,
+ SSL_NOT_DEFAULT | SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+#endif
+
+#ifndef OPENSSL_NO_SEED
+ {
+ 1,
+ TLS1_TXT_RSA_WITH_SEED_SHA,
+ TLS1_CK_RSA_WITH_SEED_SHA,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_SEED,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_DSS_WITH_SEED_SHA,
+ TLS1_CK_DHE_DSS_WITH_SEED_SHA,
+ SSL_kDHE,
+ SSL_aDSS,
+ SSL_SEED,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_RSA_WITH_SEED_SHA,
+ TLS1_CK_DHE_RSA_WITH_SEED_SHA,
+ SSL_kDHE,
+ SSL_aRSA,
+ SSL_SEED,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ADH_WITH_SEED_SHA,
+ TLS1_CK_ADH_WITH_SEED_SHA,
+ SSL_kDHE,
+ SSL_aNULL,
+ SSL_SEED,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ DTLS1_BAD_VER, DTLS1_2_VERSION,
+ SSL_NOT_DEFAULT | SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+#endif /* OPENSSL_NO_SEED */
+
+#ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
+ {
+ 1,
+ SSL3_TXT_RSA_RC4_128_MD5,
+ SSL3_CK_RSA_RC4_128_MD5,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_RC4,
+ SSL_MD5,
+ SSL3_VERSION, TLS1_2_VERSION,
+ 0, 0,
+ SSL_NOT_DEFAULT | SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ SSL3_TXT_RSA_RC4_128_SHA,
+ SSL3_CK_RSA_RC4_128_SHA,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_RC4,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ 0, 0,
+ SSL_NOT_DEFAULT | SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ SSL3_TXT_ADH_RC4_128_MD5,
+ SSL3_CK_ADH_RC4_128_MD5,
+ SSL_kDHE,
+ SSL_aNULL,
+ SSL_RC4,
+ SSL_MD5,
+ SSL3_VERSION, TLS1_2_VERSION,
+ 0, 0,
+ SSL_NOT_DEFAULT | SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+
+# ifndef OPENSSL_NO_EC
+ {
+ 1,
+ TLS1_TXT_ECDHE_PSK_WITH_RC4_128_SHA,
+ TLS1_CK_ECDHE_PSK_WITH_RC4_128_SHA,
+ SSL_kECDHEPSK,
+ SSL_aPSK,
+ SSL_RC4,
+ SSL_SHA1,
+ TLS1_VERSION, TLS1_2_VERSION,
+ 0, 0,
+ SSL_NOT_DEFAULT | SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDH_anon_WITH_RC4_128_SHA,
+ TLS1_CK_ECDH_anon_WITH_RC4_128_SHA,
+ SSL_kECDHE,
+ SSL_aNULL,
+ SSL_RC4,
+ SSL_SHA1,
+ TLS1_VERSION, TLS1_2_VERSION,
+ 0, 0,
+ SSL_NOT_DEFAULT | SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA,
+ TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA,
+ SSL_kECDHE,
+ SSL_aECDSA,
+ SSL_RC4,
+ SSL_SHA1,
+ TLS1_VERSION, TLS1_2_VERSION,
+ 0, 0,
+ SSL_NOT_DEFAULT | SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA,
+ TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA,
+ SSL_kECDHE,
+ SSL_aRSA,
+ SSL_RC4,
+ SSL_SHA1,
+ TLS1_VERSION, TLS1_2_VERSION,
+ 0, 0,
+ SSL_NOT_DEFAULT | SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+# endif /* OPENSSL_NO_EC */
+
+# ifndef OPENSSL_NO_PSK
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_RC4_128_SHA,
+ TLS1_CK_PSK_WITH_RC4_128_SHA,
+ SSL_kPSK,
+ SSL_aPSK,
+ SSL_RC4,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ 0, 0,
+ SSL_NOT_DEFAULT | SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_RSA_PSK_WITH_RC4_128_SHA,
+ TLS1_CK_RSA_PSK_WITH_RC4_128_SHA,
+ SSL_kRSAPSK,
+ SSL_aRSA,
+ SSL_RC4,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ 0, 0,
+ SSL_NOT_DEFAULT | SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+ {
+ 1,
+ TLS1_TXT_DHE_PSK_WITH_RC4_128_SHA,
+ TLS1_CK_DHE_PSK_WITH_RC4_128_SHA,
+ SSL_kDHEPSK,
+ SSL_aPSK,
+ SSL_RC4,
+ SSL_SHA1,
+ SSL3_VERSION, TLS1_2_VERSION,
+ 0, 0,
+ SSL_NOT_DEFAULT | SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+ 128,
+ 128,
+ },
+# endif /* OPENSSL_NO_PSK */
+
+#endif /* OPENSSL_NO_WEAK_SSL_CIPHERS */
+
+};
+
+static int cipher_compare(const void *a, const void *b)
+{
+ const SSL_CIPHER *ap = (const SSL_CIPHER *)a;
+ const SSL_CIPHER *bp = (const SSL_CIPHER *)b;
+
+ if (ap->id == bp->id)
+ return 0;
+ return ap->id < bp->id ? -1 : 1;
+}
+
+void ssl_sort_cipher_list(void)
+{
+ qsort(ssl3_ciphers, OSSL_NELEM(ssl3_ciphers), sizeof(ssl3_ciphers[0]),
+ cipher_compare);
+}
+
+static int ssl_undefined_function_1(SSL *ssl, unsigned char *r, size_t s,
+ const char * t, size_t u,
+ const unsigned char * v, size_t w, int x)
+{
+ (void)r;
+ (void)s;
+ (void)t;
+ (void)u;
+ (void)v;
+ (void)w;
+ (void)x;
+ return ssl_undefined_function(ssl);
+}
+
+const SSL3_ENC_METHOD SSLv3_enc_data = {
+ ssl3_enc,
+ n_ssl3_mac,
+ ssl3_setup_key_block,
+ ssl3_generate_master_secret,
+ ssl3_change_cipher_state,
+ ssl3_final_finish_mac,
+ MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH,
+ SSL3_MD_CLIENT_FINISHED_CONST, 4,
+ SSL3_MD_SERVER_FINISHED_CONST, 4,
+ ssl3_alert_code,
+ ssl_undefined_function_1,
+ 0,
+ SSL3_HM_HEADER_LENGTH,
+ ssl3_set_handshake_header,
+ ssl3_handshake_write
+};
+
+long ssl3_default_timeout(void)
+{
+ /*
+ * 2 hours, the 24 hours mentioned in the SSLv3 spec is way too long for
+ * http, the cache would over fill
+ */
+ return (60 * 60 * 2);
+}
+
+int ssl3_num_ciphers(void)
+{
+ return (SSL3_NUM_CIPHERS);
+}
+
+const SSL_CIPHER *ssl3_get_cipher(unsigned int u)
+{
+ if (u < SSL3_NUM_CIPHERS)
+ return (&(ssl3_ciphers[SSL3_NUM_CIPHERS - 1 - u]));
+ else
+ return (NULL);
+}
+
+int ssl3_set_handshake_header(SSL *s, int htype, unsigned long len)
+{
+ unsigned char *p = (unsigned char *)s->init_buf->data;
+ *(p++) = htype;
+ l2n3(len, p);
+ s->init_num = (int)len + SSL3_HM_HEADER_LENGTH;
+ s->init_off = 0;
+
+ return 1;
+}
+
+int ssl3_handshake_write(SSL *s)
+{
+ return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
+}
+
+int ssl3_new(SSL *s)
+{
+ SSL3_STATE *s3;
+
+ if ((s3 = OPENSSL_zalloc(sizeof(*s3))) == NULL)
+ goto err;
+ s->s3 = s3;
+
+#ifndef OPENSSL_NO_SRP
+ if (!SSL_SRP_CTX_init(s))
+ goto err;
+#endif
+ s->method->ssl_clear(s);
+ return (1);
+ err:
+ return (0);
+}
+
+void ssl3_free(SSL *s)
+{
+ if (s == NULL || s->s3 == NULL)
+ return;
+
+ ssl3_cleanup_key_block(s);
+
+#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
+ EVP_PKEY_free(s->s3->peer_tmp);
+ s->s3->peer_tmp = NULL;
+ EVP_PKEY_free(s->s3->tmp.pkey);
+ s->s3->tmp.pkey = NULL;
+#endif
+
+ sk_X509_NAME_pop_free(s->s3->tmp.ca_names, X509_NAME_free);
+ OPENSSL_free(s->s3->tmp.ciphers_raw);
+ OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen);
+ OPENSSL_free(s->s3->tmp.peer_sigalgs);
+ ssl3_free_digest_list(s);
+ OPENSSL_free(s->s3->alpn_selected);
+ OPENSSL_free(s->s3->alpn_proposed);
+
+#ifndef OPENSSL_NO_SRP
+ SSL_SRP_CTX_free(s);
+#endif
+ OPENSSL_clear_free(s->s3, sizeof(*s->s3));
+ s->s3 = NULL;
+}
+
+void ssl3_clear(SSL *s)
+{
+ ssl3_cleanup_key_block(s);
+ sk_X509_NAME_pop_free(s->s3->tmp.ca_names, X509_NAME_free);
+ OPENSSL_free(s->s3->tmp.ciphers_raw);
+ OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen);
+ OPENSSL_free(s->s3->tmp.peer_sigalgs);
+
+#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
+ EVP_PKEY_free(s->s3->tmp.pkey);
+ EVP_PKEY_free(s->s3->peer_tmp);
+#endif /* !OPENSSL_NO_EC */
+
+ ssl3_free_digest_list(s);
+
+ OPENSSL_free(s->s3->alpn_selected);
+ OPENSSL_free(s->s3->alpn_proposed);
+
+ /* NULL/zero-out everything in the s3 struct */
+ memset(s->s3, 0, sizeof(*s->s3));
+
+ ssl_free_wbio_buffer(s);
+
+ s->version = SSL3_VERSION;
+
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
+ OPENSSL_free(s->next_proto_negotiated);
+ s->next_proto_negotiated = NULL;
+ s->next_proto_negotiated_len = 0;
+#endif
+}
+
+#ifndef OPENSSL_NO_SRP
+static char *srp_password_from_info_cb(SSL *s, void *arg)
+{
+ return OPENSSL_strdup(s->srp_ctx.info);
+}
+#endif
+
+static int ssl3_set_req_cert_type(CERT *c, const unsigned char *p, size_t len);
+
+long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
+{
+ int ret = 0;
+
+ switch (cmd) {
+ case SSL_CTRL_GET_CLIENT_CERT_REQUEST:
+ break;
+ case SSL_CTRL_GET_NUM_RENEGOTIATIONS:
+ ret = s->s3->num_renegotiations;
+ break;
+ case SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS:
+ ret = s->s3->num_renegotiations;
+ s->s3->num_renegotiations = 0;
+ break;
+ case SSL_CTRL_GET_TOTAL_RENEGOTIATIONS:
+ ret = s->s3->total_renegotiations;
+ break;
+ case SSL_CTRL_GET_FLAGS:
+ ret = (int)(s->s3->flags);
+ break;
+#ifndef OPENSSL_NO_DH
+ case SSL_CTRL_SET_TMP_DH:
+ {
+ DH *dh = (DH *)parg;
+ EVP_PKEY *pkdh = NULL;
+ if (dh == NULL) {
+ SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER);
+ return (ret);
+ }
+ pkdh = ssl_dh_to_pkey(dh);
+ if (pkdh == NULL) {
+ SSLerr(SSL_F_SSL3_CTRL, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (!ssl_security(s, SSL_SECOP_TMP_DH,
+ EVP_PKEY_security_bits(pkdh), 0, pkdh)) {
+ SSLerr(SSL_F_SSL3_CTRL, SSL_R_DH_KEY_TOO_SMALL);
+ EVP_PKEY_free(pkdh);
+ return ret;
+ }
+ EVP_PKEY_free(s->cert->dh_tmp);
+ s->cert->dh_tmp = pkdh;
+ ret = 1;
+ }
+ break;
+ case SSL_CTRL_SET_TMP_DH_CB:
+ {
+ SSLerr(SSL_F_SSL3_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return (ret);
+ }
+ case SSL_CTRL_SET_DH_AUTO:
+ s->cert->dh_tmp_auto = larg;
+ return 1;
+#endif
+#ifndef OPENSSL_NO_EC
+ case SSL_CTRL_SET_TMP_ECDH:
+ {
+ const EC_GROUP *group = NULL;
+ int nid;
+
+ if (parg == NULL) {
+ SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ group = EC_KEY_get0_group((const EC_KEY *)parg);
+ if (group == NULL) {
+ SSLerr(SSL_F_SSL3_CTRL, EC_R_MISSING_PARAMETERS);
+ return 0;
+ }
+ nid = EC_GROUP_get_curve_name(group);
+ if (nid == NID_undef)
+ return 0;
+ return tls1_set_curves(&s->tlsext_ellipticcurvelist,
+ &s->tlsext_ellipticcurvelist_length,
+ &nid, 1);
+ }
+ break;
+#endif /* !OPENSSL_NO_EC */
+ case SSL_CTRL_SET_TLSEXT_HOSTNAME:
+ if (larg == TLSEXT_NAMETYPE_host_name) {
+ size_t len;
+
+ OPENSSL_free(s->tlsext_hostname);
+ s->tlsext_hostname = NULL;
+
+ ret = 1;
+ if (parg == NULL)
+ break;
+ len = strlen((char *)parg);
+ if (len == 0 || len > TLSEXT_MAXLEN_host_name) {
+ SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME);
+ return 0;
+ }
+ if ((s->tlsext_hostname = OPENSSL_strdup((char *)parg)) == NULL) {
+ SSLerr(SSL_F_SSL3_CTRL, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ } else {
+ SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE);
+ return 0;
+ }
+ break;
+ case SSL_CTRL_SET_TLSEXT_DEBUG_ARG:
+ s->tlsext_debug_arg = parg;
+ ret = 1;
+ break;
+
+ case SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE:
+ ret = s->tlsext_status_type;
+ break;
+
+ case SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE:
+ s->tlsext_status_type = larg;
+ ret = 1;
+ break;
+
+ case SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS:
+ *(STACK_OF(X509_EXTENSION) **)parg = s->tlsext_ocsp_exts;
+ ret = 1;
+ break;
+
+ case SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS:
+ s->tlsext_ocsp_exts = parg;
+ ret = 1;
+ break;
+
+ case SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS:
+ *(STACK_OF(OCSP_RESPID) **)parg = s->tlsext_ocsp_ids;
+ ret = 1;
+ break;
+
+ case SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS:
+ s->tlsext_ocsp_ids = parg;
+ ret = 1;
+ break;
+
+ case SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP:
+ *(unsigned char **)parg = s->tlsext_ocsp_resp;
+ return s->tlsext_ocsp_resplen;
+
+ case SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP:
+ OPENSSL_free(s->tlsext_ocsp_resp);
+ s->tlsext_ocsp_resp = parg;
+ s->tlsext_ocsp_resplen = larg;
+ ret = 1;
+ break;
+
+#ifndef OPENSSL_NO_HEARTBEATS
+ case SSL_CTRL_DTLS_EXT_SEND_HEARTBEAT:
+ if (SSL_IS_DTLS(s))
+ ret = dtls1_heartbeat(s);
+ break;
+
+ case SSL_CTRL_GET_DTLS_EXT_HEARTBEAT_PENDING:
+ if (SSL_IS_DTLS(s))
+ ret = s->tlsext_hb_pending;
+ break;
+
+ case SSL_CTRL_SET_DTLS_EXT_HEARTBEAT_NO_REQUESTS:
+ if (SSL_IS_DTLS(s)) {
+ if (larg)
+ s->tlsext_heartbeat |= SSL_DTLSEXT_HB_DONT_RECV_REQUESTS;
+ else
+ s->tlsext_heartbeat &= ~SSL_DTLSEXT_HB_DONT_RECV_REQUESTS;
+ ret = 1;
+ }
+ break;
+#endif
+
+ case SSL_CTRL_CHAIN:
+ if (larg)
+ return ssl_cert_set1_chain(s, NULL, (STACK_OF(X509) *)parg);
+ else
+ return ssl_cert_set0_chain(s, NULL, (STACK_OF(X509) *)parg);
+
+ case SSL_CTRL_CHAIN_CERT:
+ if (larg)
+ return ssl_cert_add1_chain_cert(s, NULL, (X509 *)parg);
+ else
+ return ssl_cert_add0_chain_cert(s, NULL, (X509 *)parg);
+
+ case SSL_CTRL_GET_CHAIN_CERTS:
+ *(STACK_OF(X509) **)parg = s->cert->key->chain;
+ break;
+
+ case SSL_CTRL_SELECT_CURRENT_CERT:
+ return ssl_cert_select_current(s->cert, (X509 *)parg);
+
+ case SSL_CTRL_SET_CURRENT_CERT:
+ if (larg == SSL_CERT_SET_SERVER) {
+ CERT_PKEY *cpk;
+ const SSL_CIPHER *cipher;
+ if (!s->server)
+ return 0;
+ cipher = s->s3->tmp.new_cipher;
+ if (!cipher)
+ return 0;
+ /*
+ * No certificate for unauthenticated ciphersuites or using SRP
+ * authentication
+ */
+ if (cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP))
+ return 2;
+ cpk = ssl_get_server_send_pkey(s);
+ if (!cpk)
+ return 0;
+ s->cert->key = cpk;
+ return 1;
+ }
+ return ssl_cert_set_current(s->cert, larg);
+
+#ifndef OPENSSL_NO_EC
+ case SSL_CTRL_GET_CURVES:
+ {
+ unsigned char *clist;
+ size_t clistlen;
+ if (!s->session)
+ return 0;
+ clist = s->session->tlsext_ellipticcurvelist;
+ clistlen = s->session->tlsext_ellipticcurvelist_length / 2;
+ if (parg) {
+ size_t i;
+ int *cptr = parg;
+ unsigned int cid, nid;
+ for (i = 0; i < clistlen; i++) {
+ n2s(clist, cid);
+ nid = tls1_ec_curve_id2nid(cid, NULL);
+ if (nid != 0)
+ cptr[i] = nid;
+ else
+ cptr[i] = TLSEXT_nid_unknown | cid;
+ }
+ }
+ return (int)clistlen;
+ }
+
+ case SSL_CTRL_SET_CURVES:
+ return tls1_set_curves(&s->tlsext_ellipticcurvelist,
+ &s->tlsext_ellipticcurvelist_length, parg, larg);
+
+ case SSL_CTRL_SET_CURVES_LIST:
+ return tls1_set_curves_list(&s->tlsext_ellipticcurvelist,
+ &s->tlsext_ellipticcurvelist_length, parg);
+
+ case SSL_CTRL_GET_SHARED_CURVE:
+ return tls1_shared_curve(s, larg);
+
+#endif
+ case SSL_CTRL_SET_SIGALGS:
+ return tls1_set_sigalgs(s->cert, parg, larg, 0);
+
+ case SSL_CTRL_SET_SIGALGS_LIST:
+ return tls1_set_sigalgs_list(s->cert, parg, 0);
+
+ case SSL_CTRL_SET_CLIENT_SIGALGS:
+ return tls1_set_sigalgs(s->cert, parg, larg, 1);
+
+ case SSL_CTRL_SET_CLIENT_SIGALGS_LIST:
+ return tls1_set_sigalgs_list(s->cert, parg, 1);
+
+ case SSL_CTRL_GET_CLIENT_CERT_TYPES:
+ {
+ const unsigned char **pctype = parg;
+ if (s->server || !s->s3->tmp.cert_req)
+ return 0;
+ if (s->cert->ctypes) {
+ if (pctype)
+ *pctype = s->cert->ctypes;
+ return (int)s->cert->ctype_num;
+ }
+ if (pctype)
+ *pctype = (unsigned char *)s->s3->tmp.ctype;
+ return s->s3->tmp.ctype_num;
+ }
+
+ case SSL_CTRL_SET_CLIENT_CERT_TYPES:
+ if (!s->server)
+ return 0;
+ return ssl3_set_req_cert_type(s->cert, parg, larg);
+
+ case SSL_CTRL_BUILD_CERT_CHAIN:
+ return ssl_build_cert_chain(s, NULL, larg);
+
+ case SSL_CTRL_SET_VERIFY_CERT_STORE:
+ return ssl_cert_set_cert_store(s->cert, parg, 0, larg);
+
+ case SSL_CTRL_SET_CHAIN_CERT_STORE:
+ return ssl_cert_set_cert_store(s->cert, parg, 1, larg);
+
+ case SSL_CTRL_GET_PEER_SIGNATURE_NID:
+ if (SSL_USE_SIGALGS(s)) {
+ if (s->session) {
+ const EVP_MD *sig;
+ sig = s->s3->tmp.peer_md;
+ if (sig) {
+ *(int *)parg = EVP_MD_type(sig);
+ return 1;
+ }
+ }
+ return 0;
+ }
+ /* Might want to do something here for other versions */
+ else
+ return 0;
+
+ case SSL_CTRL_GET_SERVER_TMP_KEY:
+#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC)
+ if (s->server || s->session == NULL || s->s3->peer_tmp == NULL) {
+ return 0;
+ } else {
+ EVP_PKEY_up_ref(s->s3->peer_tmp);
+ *(EVP_PKEY **)parg = s->s3->peer_tmp;
+ return 1;
+ }
+#else
+ return 0;
+#endif
+#ifndef OPENSSL_NO_EC
+ case SSL_CTRL_GET_EC_POINT_FORMATS:
+ {
+ SSL_SESSION *sess = s->session;
+ const unsigned char **pformat = parg;
+ if (!sess || !sess->tlsext_ecpointformatlist)
+ return 0;
+ *pformat = sess->tlsext_ecpointformatlist;
+ return (int)sess->tlsext_ecpointformatlist_length;
+ }
+#endif
+
+ default:
+ break;
+ }
+ return (ret);
+}
+
+long ssl3_callback_ctrl(SSL *s, int cmd, void (*fp) (void))
+{
+ int ret = 0;
+
+ switch (cmd) {
+#ifndef OPENSSL_NO_DH
+ case SSL_CTRL_SET_TMP_DH_CB:
+ {
+ s->cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp;
+ }
+ break;
+#endif
+ case SSL_CTRL_SET_TLSEXT_DEBUG_CB:
+ s->tlsext_debug_cb = (void (*)(SSL *, int, int,
+ const unsigned char *, int, void *))fp;
+ break;
+
+ case SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB:
+ {
+ s->not_resumable_session_cb = (int (*)(SSL *, int))fp;
+ }
+ break;
+ default:
+ break;
+ }
+ return (ret);
+}
+
+long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
+{
+ switch (cmd) {
+#ifndef OPENSSL_NO_DH
+ case SSL_CTRL_SET_TMP_DH:
+ {
+ DH *dh = (DH *)parg;
+ EVP_PKEY *pkdh = NULL;
+ if (dh == NULL) {
+ SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ pkdh = ssl_dh_to_pkey(dh);
+ if (pkdh == NULL) {
+ SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (!ssl_ctx_security(ctx, SSL_SECOP_TMP_DH,
+ EVP_PKEY_security_bits(pkdh), 0, pkdh)) {
+ SSLerr(SSL_F_SSL3_CTX_CTRL, SSL_R_DH_KEY_TOO_SMALL);
+ EVP_PKEY_free(pkdh);
+ return 1;
+ }
+ EVP_PKEY_free(ctx->cert->dh_tmp);
+ ctx->cert->dh_tmp = pkdh;
+ return 1;
+ }
+ /*
+ * break;
+ */
+ case SSL_CTRL_SET_TMP_DH_CB:
+ {
+ SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return (0);
+ }
+ case SSL_CTRL_SET_DH_AUTO:
+ ctx->cert->dh_tmp_auto = larg;
+ return 1;
+#endif
+#ifndef OPENSSL_NO_EC
+ case SSL_CTRL_SET_TMP_ECDH:
+ {
+ const EC_GROUP *group = NULL;
+ int nid;
+
+ if (parg == NULL) {
+ SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ group = EC_KEY_get0_group((const EC_KEY *)parg);
+ if (group == NULL) {
+ SSLerr(SSL_F_SSL3_CTX_CTRL, EC_R_MISSING_PARAMETERS);
+ return 0;
+ }
+ nid = EC_GROUP_get_curve_name(group);
+ if (nid == NID_undef)
+ return 0;
+ return tls1_set_curves(&ctx->tlsext_ellipticcurvelist,
+ &ctx->tlsext_ellipticcurvelist_length,
+ &nid, 1);
+ }
+ /* break; */
+#endif /* !OPENSSL_NO_EC */
+ case SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG:
+ ctx->tlsext_servername_arg = parg;
+ break;
+ case SSL_CTRL_SET_TLSEXT_TICKET_KEYS:
+ case SSL_CTRL_GET_TLSEXT_TICKET_KEYS:
+ {
+ unsigned char *keys = parg;
+ long tlsext_tick_keylen = (sizeof(ctx->tlsext_tick_key_name) +
+ sizeof(ctx->tlsext_tick_hmac_key) +
+ sizeof(ctx->tlsext_tick_aes_key));
+ if (keys == NULL)
+ return tlsext_tick_keylen;
+ if (larg != tlsext_tick_keylen) {
+ SSLerr(SSL_F_SSL3_CTX_CTRL, SSL_R_INVALID_TICKET_KEYS_LENGTH);
+ return 0;
+ }
+ if (cmd == SSL_CTRL_SET_TLSEXT_TICKET_KEYS) {
+ memcpy(ctx->tlsext_tick_key_name, keys,
+ sizeof(ctx->tlsext_tick_key_name));
+ memcpy(ctx->tlsext_tick_hmac_key,
+ keys + sizeof(ctx->tlsext_tick_key_name),
+ sizeof(ctx->tlsext_tick_hmac_key));
+ memcpy(ctx->tlsext_tick_aes_key,
+ keys + sizeof(ctx->tlsext_tick_key_name) +
+ sizeof(ctx->tlsext_tick_hmac_key),
+ sizeof(ctx->tlsext_tick_aes_key));
+ } else {
+ memcpy(keys, ctx->tlsext_tick_key_name,
+ sizeof(ctx->tlsext_tick_key_name));
+ memcpy(keys + sizeof(ctx->tlsext_tick_key_name),
+ ctx->tlsext_tick_hmac_key,
+ sizeof(ctx->tlsext_tick_hmac_key));
+ memcpy(keys + sizeof(ctx->tlsext_tick_key_name) +
+ sizeof(ctx->tlsext_tick_hmac_key),
+ ctx->tlsext_tick_aes_key,
+ sizeof(ctx->tlsext_tick_aes_key));
+ }
+ return 1;
+ }
+
+ case SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE:
+ return ctx->tlsext_status_type;
+
+ case SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE:
+ ctx->tlsext_status_type = larg;
+ break;
+
+ case SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG:
+ ctx->tlsext_status_arg = parg;
+ return 1;
+
+ case SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG:
+ *(void**)parg = ctx->tlsext_status_arg;
+ break;
+
+ case SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB:
+ *(int (**)(SSL*, void*))parg = ctx->tlsext_status_cb;
+ break;
+
+#ifndef OPENSSL_NO_SRP
+ case SSL_CTRL_SET_TLS_EXT_SRP_USERNAME:
+ ctx->srp_ctx.srp_Mask |= SSL_kSRP;
+ OPENSSL_free(ctx->srp_ctx.login);
+ ctx->srp_ctx.login = NULL;
+ if (parg == NULL)
+ break;
+ if (strlen((const char *)parg) > 255 || strlen((const char *)parg) < 1) {
+ SSLerr(SSL_F_SSL3_CTX_CTRL, SSL_R_INVALID_SRP_USERNAME);
+ return 0;
+ }
+ if ((ctx->srp_ctx.login = OPENSSL_strdup((char *)parg)) == NULL) {
+ SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ break;
+ case SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD:
+ ctx->srp_ctx.SRP_give_srp_client_pwd_callback =
+ srp_password_from_info_cb;
+ if (ctx->srp_ctx.info != NULL)
+ OPENSSL_free(ctx->srp_ctx.info);
+ if ((ctx->srp_ctx.info = BUF_strdup((char *)parg)) == NULL) {
+ SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ break;
+ case SSL_CTRL_SET_SRP_ARG:
+ ctx->srp_ctx.srp_Mask |= SSL_kSRP;
+ ctx->srp_ctx.SRP_cb_arg = parg;
+ break;
+
+ case SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH:
+ ctx->srp_ctx.strength = larg;
+ break;
+#endif
+
+#ifndef OPENSSL_NO_EC
+ case SSL_CTRL_SET_CURVES:
+ return tls1_set_curves(&ctx->tlsext_ellipticcurvelist,
+ &ctx->tlsext_ellipticcurvelist_length,
+ parg, larg);
+
+ case SSL_CTRL_SET_CURVES_LIST:
+ return tls1_set_curves_list(&ctx->tlsext_ellipticcurvelist,
+ &ctx->tlsext_ellipticcurvelist_length,
+ parg);
+#endif
+ case SSL_CTRL_SET_SIGALGS:
+ return tls1_set_sigalgs(ctx->cert, parg, larg, 0);
+
+ case SSL_CTRL_SET_SIGALGS_LIST:
+ return tls1_set_sigalgs_list(ctx->cert, parg, 0);
+
+ case SSL_CTRL_SET_CLIENT_SIGALGS:
+ return tls1_set_sigalgs(ctx->cert, parg, larg, 1);
+
+ case SSL_CTRL_SET_CLIENT_SIGALGS_LIST:
+ return tls1_set_sigalgs_list(ctx->cert, parg, 1);
+
+ case SSL_CTRL_SET_CLIENT_CERT_TYPES:
+ return ssl3_set_req_cert_type(ctx->cert, parg, larg);
+
+ case SSL_CTRL_BUILD_CERT_CHAIN:
+ return ssl_build_cert_chain(NULL, ctx, larg);
+
+ case SSL_CTRL_SET_VERIFY_CERT_STORE:
+ return ssl_cert_set_cert_store(ctx->cert, parg, 0, larg);
+
+ case SSL_CTRL_SET_CHAIN_CERT_STORE:
+ return ssl_cert_set_cert_store(ctx->cert, parg, 1, larg);
+
+ /* A Thawte special :-) */
+ case SSL_CTRL_EXTRA_CHAIN_CERT:
+ if (ctx->extra_certs == NULL) {
+ if ((ctx->extra_certs = sk_X509_new_null()) == NULL) {
+ SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+ if (!sk_X509_push(ctx->extra_certs, (X509 *)parg)) {
+ SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ break;
+
+ case SSL_CTRL_GET_EXTRA_CHAIN_CERTS:
+ if (ctx->extra_certs == NULL && larg == 0)
+ *(STACK_OF(X509) **)parg = ctx->cert->key->chain;
+ else
+ *(STACK_OF(X509) **)parg = ctx->extra_certs;
+ break;
+
+ case SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS:
+ sk_X509_pop_free(ctx->extra_certs, X509_free);
+ ctx->extra_certs = NULL;
+ break;
+
+ case SSL_CTRL_CHAIN:
+ if (larg)
+ return ssl_cert_set1_chain(NULL, ctx, (STACK_OF(X509) *)parg);
+ else
+ return ssl_cert_set0_chain(NULL, ctx, (STACK_OF(X509) *)parg);
+
+ case SSL_CTRL_CHAIN_CERT:
+ if (larg)
+ return ssl_cert_add1_chain_cert(NULL, ctx, (X509 *)parg);
+ else
+ return ssl_cert_add0_chain_cert(NULL, ctx, (X509 *)parg);
+
+ case SSL_CTRL_GET_CHAIN_CERTS:
+ *(STACK_OF(X509) **)parg = ctx->cert->key->chain;
+ break;
+
+ case SSL_CTRL_SELECT_CURRENT_CERT:
+ return ssl_cert_select_current(ctx->cert, (X509 *)parg);
+
+ case SSL_CTRL_SET_CURRENT_CERT:
+ return ssl_cert_set_current(ctx->cert, larg);
+
+ default:
+ return (0);
+ }
+ return (1);
+}
+
+long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp) (void))
+{
+ switch (cmd) {
+#ifndef OPENSSL_NO_DH
+ case SSL_CTRL_SET_TMP_DH_CB:
+ {
+ ctx->cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp;
+ }
+ break;
+#endif
+ case SSL_CTRL_SET_TLSEXT_SERVERNAME_CB:
+ ctx->tlsext_servername_callback = (int (*)(SSL *, int *, void *))fp;
+ break;
+
+ case SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB:
+ ctx->tlsext_status_cb = (int (*)(SSL *, void *))fp;
+ break;
+
+ case SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB:
+ ctx->tlsext_ticket_key_cb = (int (*)(SSL *, unsigned char *,
+ unsigned char *,
+ EVP_CIPHER_CTX *,
+ HMAC_CTX *, int))fp;
+ break;
+
+#ifndef OPENSSL_NO_SRP
+ case SSL_CTRL_SET_SRP_VERIFY_PARAM_CB:
+ ctx->srp_ctx.srp_Mask |= SSL_kSRP;
+ ctx->srp_ctx.SRP_verify_param_callback = (int (*)(SSL *, void *))fp;
+ break;
+ case SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB:
+ ctx->srp_ctx.srp_Mask |= SSL_kSRP;
+ ctx->srp_ctx.TLS_ext_srp_username_callback =
+ (int (*)(SSL *, int *, void *))fp;
+ break;
+ case SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB:
+ ctx->srp_ctx.srp_Mask |= SSL_kSRP;
+ ctx->srp_ctx.SRP_give_srp_client_pwd_callback =
+ (char *(*)(SSL *, void *))fp;
+ break;
+#endif
+ case SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB:
+ {
+ ctx->not_resumable_session_cb = (int (*)(SSL *, int))fp;
+ }
+ break;
+ default:
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * This function needs to check if the ciphers required are actually
+ * available
+ */
+const SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p)
+{
+ SSL_CIPHER c;
+ const SSL_CIPHER *cp;
+ uint32_t id;
+
+ id = 0x03000000 | ((uint32_t)p[0] << 8L) | (uint32_t)p[1];
+ c.id = id;
+ cp = OBJ_bsearch_ssl_cipher_id(&c, ssl3_ciphers, SSL3_NUM_CIPHERS);
+ return cp;
+}
+
+int ssl3_put_cipher_by_char(const SSL_CIPHER *c, unsigned char *p)
+{
+ long l;
+
+ if (p != NULL) {
+ l = c->id;
+ if ((l & 0xff000000) != 0x03000000)
+ return (0);
+ p[0] = ((unsigned char)(l >> 8L)) & 0xFF;
+ p[1] = ((unsigned char)(l)) & 0xFF;
+ }
+ return (2);
+}
+
+/*
+ * ssl3_choose_cipher - choose a cipher from those offered by the client
+ * @s: SSL connection
+ * @clnt: ciphers offered by the client
+ * @srvr: ciphers enabled on the server?
+ *
+ * Returns the selected cipher or NULL when no common ciphers.
+ */
+const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
+ STACK_OF(SSL_CIPHER) *srvr)
+{
+ const SSL_CIPHER *c, *ret = NULL;
+ STACK_OF(SSL_CIPHER) *prio, *allow;
+ int i, ii, ok;
+ unsigned long alg_k, alg_a, mask_k, mask_a;
+
+ /* Let's see which ciphers we can support */
+
+#if 0
+ /*
+ * Do not set the compare functions, because this may lead to a
+ * reordering by "id". We want to keep the original ordering. We may pay
+ * a price in performance during sk_SSL_CIPHER_find(), but would have to
+ * pay with the price of sk_SSL_CIPHER_dup().
+ */
+ sk_SSL_CIPHER_set_cmp_func(srvr, ssl_cipher_ptr_id_cmp);
+ sk_SSL_CIPHER_set_cmp_func(clnt, ssl_cipher_ptr_id_cmp);
+#endif
+
+#ifdef CIPHER_DEBUG
+ fprintf(stderr, "Server has %d from %p:\n", sk_SSL_CIPHER_num(srvr),
+ (void *)srvr);
+ for (i = 0; i < sk_SSL_CIPHER_num(srvr); ++i) {
+ c = sk_SSL_CIPHER_value(srvr, i);
+ fprintf(stderr, "%p:%s\n", (void *)c, c->name);
+ }
+ fprintf(stderr, "Client sent %d from %p:\n", sk_SSL_CIPHER_num(clnt),
+ (void *)clnt);
+ for (i = 0; i < sk_SSL_CIPHER_num(clnt); ++i) {
+ c = sk_SSL_CIPHER_value(clnt, i);
+ fprintf(stderr, "%p:%s\n", (void *)c, c->name);
+ }
+#endif
+
+ if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || tls1_suiteb(s)) {
+ prio = srvr;
+ allow = clnt;
+ } else {
+ prio = clnt;
+ allow = srvr;
+ }
+
+ tls1_set_cert_validity(s);
+ ssl_set_masks(s);
+
+ for (i = 0; i < sk_SSL_CIPHER_num(prio); i++) {
+ c = sk_SSL_CIPHER_value(prio, i);
+
+ /* Skip ciphers not supported by the protocol version */
+ if (!SSL_IS_DTLS(s) &&
+ ((s->version < c->min_tls) || (s->version > c->max_tls)))
+ continue;
+ if (SSL_IS_DTLS(s) &&
+ (DTLS_VERSION_LT(s->version, c->min_dtls) ||
+ DTLS_VERSION_GT(s->version, c->max_dtls)))
+ continue;
+
+ mask_k = s->s3->tmp.mask_k;
+ mask_a = s->s3->tmp.mask_a;
+#ifndef OPENSSL_NO_SRP
+ if (s->srp_ctx.srp_Mask & SSL_kSRP) {
+ mask_k |= SSL_kSRP;
+ mask_a |= SSL_aSRP;
+ }
+#endif
+
+ alg_k = c->algorithm_mkey;
+ alg_a = c->algorithm_auth;
+
+#ifndef OPENSSL_NO_PSK
+ /* with PSK there must be server callback set */
+ if ((alg_k & SSL_PSK) && s->psk_server_callback == NULL)
+ continue;
+#endif /* OPENSSL_NO_PSK */
+
+ ok = (alg_k & mask_k) && (alg_a & mask_a);
+#ifdef CIPHER_DEBUG
+ fprintf(stderr, "%d:[%08lX:%08lX:%08lX:%08lX]%p:%s\n", ok, alg_k,
+ alg_a, mask_k, mask_a, (void *)c, c->name);
+#endif
+
+#ifndef OPENSSL_NO_EC
+ /*
+ * if we are considering an ECC cipher suite that uses an ephemeral
+ * EC key check it
+ */
+ if (alg_k & SSL_kECDHE)
+ ok = ok && tls1_check_ec_tmp_key(s, c->id);
+#endif /* OPENSSL_NO_EC */
+
+ if (!ok)
+ continue;
+ ii = sk_SSL_CIPHER_find(allow, c);
+ if (ii >= 0) {
+ /* Check security callback permits this cipher */
+ if (!ssl_security(s, SSL_SECOP_CIPHER_SHARED,
+ c->strength_bits, 0, (void *)c))
+ continue;
+#if !defined(OPENSSL_NO_EC)
+ if ((alg_k & SSL_kECDHE) && (alg_a & SSL_aECDSA)
+ && s->s3->is_probably_safari) {
+ if (!ret)
+ ret = sk_SSL_CIPHER_value(allow, ii);
+ continue;
+ }
+#endif
+ ret = sk_SSL_CIPHER_value(allow, ii);
+ break;
+ }
+ }
+ return (ret);
+}
+
+int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
+{
+ int ret = 0;
+ uint32_t alg_k, alg_a = 0;
+
+ /* If we have custom certificate types set, use them */
+ if (s->cert->ctypes) {
+ memcpy(p, s->cert->ctypes, s->cert->ctype_num);
+ return (int)s->cert->ctype_num;
+ }
+ /* Get mask of algorithms disabled by signature list */
+ ssl_set_sig_mask(&alg_a, s, SSL_SECOP_SIGALG_MASK);
+
+ alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+
+#ifndef OPENSSL_NO_GOST
+ if (s->version >= TLS1_VERSION) {
+ if (alg_k & SSL_kGOST) {
+ p[ret++] = TLS_CT_GOST01_SIGN;
+ p[ret++] = TLS_CT_GOST12_SIGN;
+ p[ret++] = TLS_CT_GOST12_512_SIGN;
+ return (ret);
+ }
+ }
+#endif
+
+ if ((s->version == SSL3_VERSION) && (alg_k & SSL_kDHE)) {
+#ifndef OPENSSL_NO_DH
+# ifndef OPENSSL_NO_RSA
+ p[ret++] = SSL3_CT_RSA_EPHEMERAL_DH;
+# endif
+# ifndef OPENSSL_NO_DSA
+ p[ret++] = SSL3_CT_DSS_EPHEMERAL_DH;
+# endif
+#endif /* !OPENSSL_NO_DH */
+ }
+#ifndef OPENSSL_NO_RSA
+ if (!(alg_a & SSL_aRSA))
+ p[ret++] = SSL3_CT_RSA_SIGN;
+#endif
+#ifndef OPENSSL_NO_DSA
+ if (!(alg_a & SSL_aDSS))
+ p[ret++] = SSL3_CT_DSS_SIGN;
+#endif
+#ifndef OPENSSL_NO_EC
+ /*
+ * ECDSA certs can be used with RSA cipher suites too so we don't
+ * need to check for SSL_kECDH or SSL_kECDHE
+ */
+ if (s->version >= TLS1_VERSION) {
+ if (!(alg_a & SSL_aECDSA))
+ p[ret++] = TLS_CT_ECDSA_SIGN;
+ }
+#endif
+ return (ret);
+}
+
+static int ssl3_set_req_cert_type(CERT *c, const unsigned char *p, size_t len)
+{
+ OPENSSL_free(c->ctypes);
+ c->ctypes = NULL;
+ if (!p || !len)
+ return 1;
+ if (len > 0xff)
+ return 0;
+ c->ctypes = OPENSSL_malloc(len);
+ if (c->ctypes == NULL)
+ return 0;
+ memcpy(c->ctypes, p, len);
+ c->ctype_num = len;
+ return 1;
+}
+
+int ssl3_shutdown(SSL *s)
+{
+ int ret;
+
+ /*
+ * Don't do anything much if we have not done the handshake or we don't
+ * want to send messages :-)
+ */
+ if (s->quiet_shutdown || SSL_in_before(s)) {
+ s->shutdown = (SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
+ return (1);
+ }
+
+ if (!(s->shutdown & SSL_SENT_SHUTDOWN)) {
+ s->shutdown |= SSL_SENT_SHUTDOWN;
+ ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_CLOSE_NOTIFY);
+ /*
+ * our shutdown alert has been sent now, and if it still needs to be
+ * written, s->s3->alert_dispatch will be true
+ */
+ if (s->s3->alert_dispatch)
+ return (-1); /* return WANT_WRITE */
+ } else if (s->s3->alert_dispatch) {
+ /* resend it if not sent */
+ ret = s->method->ssl_dispatch_alert(s);
+ if (ret == -1) {
+ /*
+ * we only get to return -1 here the 2nd/Nth invocation, we must
+ * have already signalled return 0 upon a previous invocation,
+ * return WANT_WRITE
+ */
+ return (ret);
+ }
+ } else if (!(s->shutdown & SSL_RECEIVED_SHUTDOWN)) {
+ /*
+ * If we are waiting for a close from our peer, we are closed
+ */
+ s->method->ssl_read_bytes(s, 0, NULL, NULL, 0, 0);
+ if (!(s->shutdown & SSL_RECEIVED_SHUTDOWN)) {
+ return (-1); /* return WANT_READ */
+ }
+ }
+
+ if ((s->shutdown == (SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN)) &&
+ !s->s3->alert_dispatch)
+ return (1);
+ else
+ return (0);
+}
+
+int ssl3_write(SSL *s, const void *buf, int len)
+{
+ clear_sys_error();
+ if (s->s3->renegotiate)
+ ssl3_renegotiate_check(s);
+
+ return s->method->ssl_write_bytes(s, SSL3_RT_APPLICATION_DATA, buf, len);
+}
+
+static int ssl3_read_internal(SSL *s, void *buf, int len, int peek)
+{
+ int ret;
+
+ clear_sys_error();
+ if (s->s3->renegotiate)
+ ssl3_renegotiate_check(s);
+ s->s3->in_read_app_data = 1;
+ ret =
+ s->method->ssl_read_bytes(s, SSL3_RT_APPLICATION_DATA, NULL, buf, len,
+ peek);
+ if ((ret == -1) && (s->s3->in_read_app_data == 2)) {
+ /*
+ * ssl3_read_bytes decided to call s->handshake_func, which called
+ * ssl3_read_bytes to read handshake data. However, ssl3_read_bytes
+ * actually found application data and thinks that application data
+ * makes sense here; so disable handshake processing and try to read
+ * application data again.
+ */
+ ossl_statem_set_in_handshake(s, 1);
+ ret =
+ s->method->ssl_read_bytes(s, SSL3_RT_APPLICATION_DATA, NULL, buf,
+ len, peek);
+ ossl_statem_set_in_handshake(s, 0);
+ } else
+ s->s3->in_read_app_data = 0;
+
+ return (ret);
+}
+
+int ssl3_read(SSL *s, void *buf, int len)
+{
+ return ssl3_read_internal(s, buf, len, 0);
+}
+
+int ssl3_peek(SSL *s, void *buf, int len)
+{
+ return ssl3_read_internal(s, buf, len, 1);
+}
+
+int ssl3_renegotiate(SSL *s)
+{
+ if (s->handshake_func == NULL)
+ return (1);
+
+ if (s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
+ return (0);
+
+ s->s3->renegotiate = 1;
+ return (1);
+}
+
+int ssl3_renegotiate_check(SSL *s)
+{
+ int ret = 0;
+
+ if (s->s3->renegotiate) {
+ if (!RECORD_LAYER_read_pending(&s->rlayer)
+ && !RECORD_LAYER_write_pending(&s->rlayer)
+ && !SSL_in_init(s)) {
+ /*
+ * if we are the server, and we have sent a 'RENEGOTIATE'
+ * message, we need to set the state machine into the renegotiate
+ * state.
+ */
+ ossl_statem_set_renegotiate(s);
+ s->s3->renegotiate = 0;
+ s->s3->num_renegotiations++;
+ s->s3->total_renegotiations++;
+ ret = 1;
+ }
+ }
+ return (ret);
+}
+
+/*
+ * If we are using default SHA1+MD5 algorithms switch to new SHA256 PRF and
+ * handshake macs if required.
+ *
+ * If PSK and using SHA384 for TLS < 1.2 switch to default.
+ */
+long ssl_get_algorithm2(SSL *s)
+{
+ long alg2;
+ if (s->s3 == NULL || s->s3->tmp.new_cipher == NULL)
+ return -1;
+ alg2 = s->s3->tmp.new_cipher->algorithm2;
+ if (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_SHA256_PRF) {
+ if (alg2 == (SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF))
+ return SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256;
+ } else if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK) {
+ if (alg2 == (SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384))
+ return SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF;
+ }
+ return alg2;
+}
+
+/*
+ * Fill a ClientRandom or ServerRandom field of length len. Returns <= 0 on
+ * failure, 1 on success.
+ */
+int ssl_fill_hello_random(SSL *s, int server, unsigned char *result, int len)
+{
+ int send_time = 0;
+
+ if (len < 4)
+ return 0;
+ if (server)
+ send_time = (s->mode & SSL_MODE_SEND_SERVERHELLO_TIME) != 0;
+ else
+ send_time = (s->mode & SSL_MODE_SEND_CLIENTHELLO_TIME) != 0;
+ if (send_time) {
+ unsigned long Time = (unsigned long)time(NULL);
+ unsigned char *p = result;
+ l2n(Time, p);
+ return RAND_bytes(p, len - 4);
+ } else
+ return RAND_bytes(result, len);
+}
+
+int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen,
+ int free_pms)
+{
+ unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ if (alg_k & SSL_PSK) {
+#ifndef OPENSSL_NO_PSK
+ unsigned char *pskpms, *t;
+ size_t psklen = s->s3->tmp.psklen;
+ size_t pskpmslen;
+
+ /* create PSK premaster_secret */
+
+ /* For plain PSK "other_secret" is psklen zeroes */
+ if (alg_k & SSL_kPSK)
+ pmslen = psklen;
+
+ pskpmslen = 4 + pmslen + psklen;
+ pskpms = OPENSSL_malloc(pskpmslen);
+ if (pskpms == NULL) {
+ s->session->master_key_length = 0;
+ goto err;
+ }
+ t = pskpms;
+ s2n(pmslen, t);
+ if (alg_k & SSL_kPSK)
+ memset(t, 0, pmslen);
+ else
+ memcpy(t, pms, pmslen);
+ t += pmslen;
+ s2n(psklen, t);
+ memcpy(t, s->s3->tmp.psk, psklen);
+
+ OPENSSL_clear_free(s->s3->tmp.psk, psklen);
+ s->s3->tmp.psk = NULL;
+ s->session->master_key_length =
+ s->method->ssl3_enc->generate_master_secret(s,
+ s->session->master_key,
+ pskpms, pskpmslen);
+ OPENSSL_clear_free(pskpms, pskpmslen);
+#else
+ /* Should never happen */
+ s->session->master_key_length = 0;
+ goto err;
+#endif
+ } else {
+ s->session->master_key_length =
+ s->method->ssl3_enc->generate_master_secret(s,
+ s->session->master_key,
+ pms, pmslen);
+ }
+
+ err:
+ if (pms) {
+ if (free_pms)
+ OPENSSL_clear_free(pms, pmslen);
+ else
+ OPENSSL_cleanse(pms, pmslen);
+ }
+ if (s->server == 0)
+ s->s3->tmp.pms = NULL;
+ return s->session->master_key_length >= 0;
+}
+
+/* Generate a private key from parameters */
+EVP_PKEY *ssl_generate_pkey(EVP_PKEY *pm)
+{
+ EVP_PKEY_CTX *pctx = NULL;
+ EVP_PKEY *pkey = NULL;
+
+ if (pm == NULL)
+ return NULL;
+ pctx = EVP_PKEY_CTX_new(pm, NULL);
+ if (pctx == NULL)
+ goto err;
+ if (EVP_PKEY_keygen_init(pctx) <= 0)
+ goto err;
+ if (EVP_PKEY_keygen(pctx, &pkey) <= 0) {
+ EVP_PKEY_free(pkey);
+ pkey = NULL;
+ }
+
+ err:
+ EVP_PKEY_CTX_free(pctx);
+ return pkey;
+}
+#ifndef OPENSSL_NO_EC
+/* Generate a private key a curve ID */
+EVP_PKEY *ssl_generate_pkey_curve(int id)
+{
+ EVP_PKEY_CTX *pctx = NULL;
+ EVP_PKEY *pkey = NULL;
+ unsigned int curve_flags;
+ int nid = tls1_ec_curve_id2nid(id, &curve_flags);
+
+ if (nid == 0)
+ goto err;
+ if ((curve_flags & TLS_CURVE_TYPE) == TLS_CURVE_CUSTOM) {
+ pctx = EVP_PKEY_CTX_new_id(nid, NULL);
+ nid = 0;
+ } else {
+ pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
+ }
+ if (pctx == NULL)
+ goto err;
+ if (EVP_PKEY_keygen_init(pctx) <= 0)
+ goto err;
+ if (nid != 0 && EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, nid) <= 0)
+ goto err;
+ if (EVP_PKEY_keygen(pctx, &pkey) <= 0) {
+ EVP_PKEY_free(pkey);
+ pkey = NULL;
+ }
+
+ err:
+ EVP_PKEY_CTX_free(pctx);
+ return pkey;
+}
+#endif
+
+/* Derive premaster or master secret for ECDH/DH */
+int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey)
+{
+ int rv = 0;
+ unsigned char *pms = NULL;
+ size_t pmslen = 0;
+ EVP_PKEY_CTX *pctx;
+
+ if (privkey == NULL || pubkey == NULL)
+ return 0;
+
+ pctx = EVP_PKEY_CTX_new(privkey, NULL);
+
+ if (EVP_PKEY_derive_init(pctx) <= 0
+ || EVP_PKEY_derive_set_peer(pctx, pubkey) <= 0
+ || EVP_PKEY_derive(pctx, NULL, &pmslen) <= 0) {
+ goto err;
+ }
+
+ pms = OPENSSL_malloc(pmslen);
+ if (pms == NULL)
+ goto err;
+
+ if (EVP_PKEY_derive(pctx, pms, &pmslen) <= 0)
+ goto err;
+
+ if (s->server) {
+ /* For server generate master secret and discard premaster */
+ rv = ssl_generate_master_secret(s, pms, pmslen, 1);
+ pms = NULL;
+ } else {
+ /* For client just save premaster secret */
+ s->s3->tmp.pms = pms;
+ s->s3->tmp.pmslen = pmslen;
+ pms = NULL;
+ rv = 1;
+ }
+
+ err:
+ OPENSSL_clear_free(pms, pmslen);
+ EVP_PKEY_CTX_free(pctx);
+ return rv;
+}
+
+#ifndef OPENSSL_NO_DH
+EVP_PKEY *ssl_dh_to_pkey(DH *dh)
+{
+ EVP_PKEY *ret;
+ if (dh == NULL)
+ return NULL;
+ ret = EVP_PKEY_new();
+ if (EVP_PKEY_set1_DH(ret, dh) <= 0) {
+ EVP_PKEY_free(ret);
+ return NULL;
+ }
+ return ret;
+}
+#endif
diff --git a/openssl-1.1.0h/ssl/s3_msg.c b/openssl-1.1.0h/ssl/s3_msg.c
new file mode 100644
index 0000000..4961cc8
--- /dev/null
+++ b/openssl-1.1.0h/ssl/s3_msg.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright 1995-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
+ */
+
+#define USE_SOCKETS
+#include "ssl_locl.h"
+
+int ssl3_do_change_cipher_spec(SSL *s)
+{
+ int i;
+
+ if (s->server)
+ i = SSL3_CHANGE_CIPHER_SERVER_READ;
+ else
+ i = SSL3_CHANGE_CIPHER_CLIENT_READ;
+
+ if (s->s3->tmp.key_block == NULL) {
+ if (s->session == NULL || s->session->master_key_length == 0) {
+ /* might happen if dtls1_read_bytes() calls this */
+ SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY);
+ return (0);
+ }
+
+ s->session->cipher = s->s3->tmp.new_cipher;
+ if (!s->method->ssl3_enc->setup_key_block(s))
+ return (0);
+ }
+
+ if (!s->method->ssl3_enc->change_cipher_state(s, i))
+ return (0);
+
+ return 1;
+}
+
+int ssl3_send_alert(SSL *s, int level, int desc)
+{
+ /* Map tls/ssl alert value to correct one */
+ desc = s->method->ssl3_enc->alert_value(desc);
+ if (s->version == SSL3_VERSION && desc == SSL_AD_PROTOCOL_VERSION)
+ desc = SSL_AD_HANDSHAKE_FAILURE; /* SSL 3.0 does not have
+ * protocol_version alerts */
+ if (desc < 0)
+ return -1;
+ /* If a fatal one, remove from cache */
+ if ((level == SSL3_AL_FATAL) && (s->session != NULL))
+ SSL_CTX_remove_session(s->session_ctx, s->session);
+
+ s->s3->alert_dispatch = 1;
+ s->s3->send_alert[0] = level;
+ s->s3->send_alert[1] = desc;
+ if (!RECORD_LAYER_write_pending(&s->rlayer)) {
+ /* data still being written out? */
+ return s->method->ssl_dispatch_alert(s);
+ }
+ /*
+ * else data is still being written out, we will get written some time in
+ * the future
+ */
+ return -1;
+}
+
+int ssl3_dispatch_alert(SSL *s)
+{
+ int i, j;
+ unsigned int alertlen;
+ void (*cb) (const SSL *ssl, int type, int val) = NULL;
+
+ s->s3->alert_dispatch = 0;
+ alertlen = 2;
+ i = do_ssl3_write(s, SSL3_RT_ALERT, &s->s3->send_alert[0], &alertlen, 1, 0);
+ if (i <= 0) {
+ s->s3->alert_dispatch = 1;
+ } else {
+ /*
+ * Alert sent to BIO. If it is important, flush it now. If the
+ * message does not get sent due to non-blocking IO, we will not
+ * worry too much.
+ */
+ if (s->s3->send_alert[0] == SSL3_AL_FATAL)
+ (void)BIO_flush(s->wbio);
+
+ if (s->msg_callback)
+ s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert,
+ 2, s, s->msg_callback_arg);
+
+ if (s->info_callback != NULL)
+ cb = s->info_callback;
+ else if (s->ctx->info_callback != NULL)
+ cb = s->ctx->info_callback;
+
+ if (cb != NULL) {
+ j = (s->s3->send_alert[0] << 8) | s->s3->send_alert[1];
+ cb(s, SSL_CB_WRITE_ALERT, j);
+ }
+ }
+ return (i);
+}
diff --git a/openssl-1.1.0h/ssl/ssl_asn1.c b/openssl-1.1.0h/ssl/ssl_asn1.c
new file mode 100644
index 0000000..3e9c1c4
--- /dev/null
+++ b/openssl-1.1.0h/ssl/ssl_asn1.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright 1995-2017 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
+ */
+
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "ssl_locl.h"
+#include "internal/asn1t.h"
+#include <openssl/x509.h>
+
+typedef struct {
+ uint32_t version;
+ int32_t ssl_version;
+ ASN1_OCTET_STRING *cipher;
+ ASN1_OCTET_STRING *comp_id;
+ ASN1_OCTET_STRING *master_key;
+ ASN1_OCTET_STRING *session_id;
+ ASN1_OCTET_STRING *key_arg;
+ int64_t time;
+ int64_t timeout;
+ X509 *peer;
+ ASN1_OCTET_STRING *session_id_context;
+ int32_t verify_result;
+ ASN1_OCTET_STRING *tlsext_hostname;
+ int64_t tlsext_tick_lifetime_hint;
+ ASN1_OCTET_STRING *tlsext_tick;
+#ifndef OPENSSL_NO_PSK
+ ASN1_OCTET_STRING *psk_identity_hint;
+ ASN1_OCTET_STRING *psk_identity;
+#endif
+#ifndef OPENSSL_NO_SRP
+ ASN1_OCTET_STRING *srp_username;
+#endif
+ uint64_t flags;
+} SSL_SESSION_ASN1;
+
+ASN1_SEQUENCE(SSL_SESSION_ASN1) = {
+ ASN1_EMBED(SSL_SESSION_ASN1, version, UINT32),
+ ASN1_EMBED(SSL_SESSION_ASN1, ssl_version, INT32),
+ ASN1_SIMPLE(SSL_SESSION_ASN1, cipher, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(SSL_SESSION_ASN1, session_id, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(SSL_SESSION_ASN1, master_key, ASN1_OCTET_STRING),
+ ASN1_IMP_OPT(SSL_SESSION_ASN1, key_arg, ASN1_OCTET_STRING, 0),
+ ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, time, ZINT64, 1),
+ ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, timeout, ZINT64, 2),
+ ASN1_EXP_OPT(SSL_SESSION_ASN1, peer, X509, 3),
+ ASN1_EXP_OPT(SSL_SESSION_ASN1, session_id_context, ASN1_OCTET_STRING, 4),
+ ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, verify_result, ZINT32, 5),
+ ASN1_EXP_OPT(SSL_SESSION_ASN1, tlsext_hostname, ASN1_OCTET_STRING, 6),
+#ifndef OPENSSL_NO_PSK
+ ASN1_EXP_OPT(SSL_SESSION_ASN1, psk_identity_hint, ASN1_OCTET_STRING, 7),
+ ASN1_EXP_OPT(SSL_SESSION_ASN1, psk_identity, ASN1_OCTET_STRING, 8),
+#endif
+ ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, tlsext_tick_lifetime_hint, ZUINT64, 9),
+ ASN1_EXP_OPT(SSL_SESSION_ASN1, tlsext_tick, ASN1_OCTET_STRING, 10),
+ ASN1_EXP_OPT(SSL_SESSION_ASN1, comp_id, ASN1_OCTET_STRING, 11),
+#ifndef OPENSSL_NO_SRP
+ ASN1_EXP_OPT(SSL_SESSION_ASN1, srp_username, ASN1_OCTET_STRING, 12),
+#endif
+ ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, flags, ZUINT64, 13)
+} static_ASN1_SEQUENCE_END(SSL_SESSION_ASN1)
+
+IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(SSL_SESSION_ASN1)
+
+/* Utility functions for i2d_SSL_SESSION */
+
+/* Initialise OCTET STRING from buffer and length */
+
+static void ssl_session_oinit(ASN1_OCTET_STRING **dest, ASN1_OCTET_STRING *os,
+ unsigned char *data, size_t len)
+{
+ os->data = data;
+ os->length = len;
+ os->flags = 0;
+ *dest = os;
+}
+
+/* Initialise OCTET STRING from string */
+static void ssl_session_sinit(ASN1_OCTET_STRING **dest, ASN1_OCTET_STRING *os,
+ char *data)
+{
+ if (data != NULL)
+ ssl_session_oinit(dest, os, (unsigned char *)data, strlen(data));
+ else
+ *dest = NULL;
+}
+
+int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
+{
+
+ SSL_SESSION_ASN1 as;
+
+ ASN1_OCTET_STRING cipher;
+ unsigned char cipher_data[2];
+ ASN1_OCTET_STRING master_key, session_id, sid_ctx;
+
+#ifndef OPENSSL_NO_COMP
+ ASN1_OCTET_STRING comp_id;
+ unsigned char comp_id_data;
+#endif
+
+ ASN1_OCTET_STRING tlsext_hostname, tlsext_tick;
+
+#ifndef OPENSSL_NO_SRP
+ ASN1_OCTET_STRING srp_username;
+#endif
+
+#ifndef OPENSSL_NO_PSK
+ ASN1_OCTET_STRING psk_identity, psk_identity_hint;
+#endif
+
+ long l;
+
+ if ((in == NULL) || ((in->cipher == NULL) && (in->cipher_id == 0)))
+ return 0;
+
+ memset(&as, 0, sizeof(as));
+
+ as.version = SSL_SESSION_ASN1_VERSION;
+ as.ssl_version = in->ssl_version;
+
+ if (in->cipher == NULL)
+ l = in->cipher_id;
+ else
+ l = in->cipher->id;
+ cipher_data[0] = ((unsigned char)(l >> 8L)) & 0xff;
+ cipher_data[1] = ((unsigned char)(l)) & 0xff;
+
+ ssl_session_oinit(&as.cipher, &cipher, cipher_data, 2);
+
+#ifndef OPENSSL_NO_COMP
+ if (in->compress_meth) {
+ comp_id_data = (unsigned char)in->compress_meth;
+ ssl_session_oinit(&as.comp_id, &comp_id, &comp_id_data, 1);
+ }
+#endif
+
+ ssl_session_oinit(&as.master_key, &master_key,
+ in->master_key, in->master_key_length);
+
+ ssl_session_oinit(&as.session_id, &session_id,
+ in->session_id, in->session_id_length);
+
+ ssl_session_oinit(&as.session_id_context, &sid_ctx,
+ in->sid_ctx, in->sid_ctx_length);
+
+ as.time = in->time;
+ as.timeout = in->timeout;
+ as.verify_result = in->verify_result;
+
+ as.peer = in->peer;
+
+ ssl_session_sinit(&as.tlsext_hostname, &tlsext_hostname,
+ in->tlsext_hostname);
+ if (in->tlsext_tick) {
+ ssl_session_oinit(&as.tlsext_tick, &tlsext_tick,
+ in->tlsext_tick, in->tlsext_ticklen);
+ }
+ if (in->tlsext_tick_lifetime_hint > 0)
+ as.tlsext_tick_lifetime_hint = in->tlsext_tick_lifetime_hint;
+#ifndef OPENSSL_NO_PSK
+ ssl_session_sinit(&as.psk_identity_hint, &psk_identity_hint,
+ in->psk_identity_hint);
+ ssl_session_sinit(&as.psk_identity, &psk_identity, in->psk_identity);
+#endif /* OPENSSL_NO_PSK */
+#ifndef OPENSSL_NO_SRP
+ ssl_session_sinit(&as.srp_username, &srp_username, in->srp_username);
+#endif /* OPENSSL_NO_SRP */
+
+ as.flags = in->flags;
+
+ return i2d_SSL_SESSION_ASN1(&as, pp);
+
+}
+
+/* Utility functions for d2i_SSL_SESSION */
+
+/* OPENSSL_strndup an OCTET STRING */
+
+static int ssl_session_strndup(char **pdst, ASN1_OCTET_STRING *src)
+{
+ OPENSSL_free(*pdst);
+ *pdst = NULL;
+ if (src == NULL)
+ return 1;
+ *pdst = OPENSSL_strndup((char *)src->data, src->length);
+ if (*pdst == NULL)
+ return 0;
+ return 1;
+}
+
+/* Copy an OCTET STRING, return error if it exceeds maximum length */
+
+static int ssl_session_memcpy(unsigned char *dst, unsigned int *pdstlen,
+ ASN1_OCTET_STRING *src, int maxlen)
+{
+ if (src == NULL) {
+ *pdstlen = 0;
+ return 1;
+ }
+ if (src->length > maxlen)
+ return 0;
+ memcpy(dst, src->data, src->length);
+ *pdstlen = src->length;
+ return 1;
+}
+
+SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
+ long length)
+{
+ long id;
+ unsigned int tmpl;
+ const unsigned char *p = *pp;
+ SSL_SESSION_ASN1 *as = NULL;
+ SSL_SESSION *ret = NULL;
+
+ as = d2i_SSL_SESSION_ASN1(NULL, &p, length);
+ /* ASN.1 code returns suitable error */
+ if (as == NULL)
+ goto err;
+
+ if (!a || !*a) {
+ ret = SSL_SESSION_new();
+ if (ret == NULL)
+ goto err;
+ } else {
+ ret = *a;
+ }
+
+ if (as->version != SSL_SESSION_ASN1_VERSION) {
+ SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_UNKNOWN_SSL_VERSION);
+ goto err;
+ }
+
+ if ((as->ssl_version >> 8) != SSL3_VERSION_MAJOR
+ && (as->ssl_version >> 8) != DTLS1_VERSION_MAJOR
+ && as->ssl_version != DTLS1_BAD_VER) {
+ SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_UNSUPPORTED_SSL_VERSION);
+ goto err;
+ }
+
+ ret->ssl_version = (int)as->ssl_version;
+
+ if (as->cipher->length != 2) {
+ SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_CIPHER_CODE_WRONG_LENGTH);
+ goto err;
+ }
+
+ id = 0x03000000L | ((unsigned long)as->cipher->data[0] << 8L)
+ | (unsigned long)as->cipher->data[1];
+
+ ret->cipher = NULL;
+ ret->cipher_id = id;
+
+ if (!ssl_session_memcpy(ret->session_id, &ret->session_id_length,
+ as->session_id, SSL3_MAX_SSL_SESSION_ID_LENGTH))
+ goto err;
+
+ if (!ssl_session_memcpy(ret->master_key, &tmpl,
+ as->master_key, SSL_MAX_MASTER_KEY_LENGTH))
+ goto err;
+
+ ret->master_key_length = tmpl;
+
+ if (as->time != 0)
+ ret->time = as->time;
+ else
+ ret->time = (unsigned long)time(NULL);
+
+ if (as->timeout != 0)
+ ret->timeout = as->timeout;
+ else
+ ret->timeout = 3;
+
+ X509_free(ret->peer);
+ ret->peer = as->peer;
+ as->peer = NULL;
+
+ if (!ssl_session_memcpy(ret->sid_ctx, &ret->sid_ctx_length,
+ as->session_id_context, SSL_MAX_SID_CTX_LENGTH))
+ goto err;
+
+ /* NB: this defaults to zero which is X509_V_OK */
+ ret->verify_result = as->verify_result;
+
+ if (!ssl_session_strndup(&ret->tlsext_hostname, as->tlsext_hostname))
+ goto err;
+
+#ifndef OPENSSL_NO_PSK
+ if (!ssl_session_strndup(&ret->psk_identity_hint, as->psk_identity_hint))
+ goto err;
+ if (!ssl_session_strndup(&ret->psk_identity, as->psk_identity))
+ goto err;
+#endif
+
+ ret->tlsext_tick_lifetime_hint = as->tlsext_tick_lifetime_hint;
+ if (as->tlsext_tick) {
+ ret->tlsext_tick = as->tlsext_tick->data;
+ ret->tlsext_ticklen = as->tlsext_tick->length;
+ as->tlsext_tick->data = NULL;
+ } else {
+ ret->tlsext_tick = NULL;
+ }
+#ifndef OPENSSL_NO_COMP
+ if (as->comp_id) {
+ if (as->comp_id->length != 1) {
+ SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_BAD_LENGTH);
+ goto err;
+ }
+ ret->compress_meth = as->comp_id->data[0];
+ } else {
+ ret->compress_meth = 0;
+ }
+#endif
+
+#ifndef OPENSSL_NO_SRP
+ if (!ssl_session_strndup(&ret->srp_username, as->srp_username))
+ goto err;
+#endif /* OPENSSL_NO_SRP */
+ /* Flags defaults to zero which is fine */
+ ret->flags = as->flags;
+
+ M_ASN1_free_of(as, SSL_SESSION_ASN1);
+
+ if ((a != NULL) && (*a == NULL))
+ *a = ret;
+ *pp = p;
+ return ret;
+
+ err:
+ M_ASN1_free_of(as, SSL_SESSION_ASN1);
+ if ((a == NULL) || (*a != ret))
+ SSL_SESSION_free(ret);
+ return NULL;
+}
diff --git a/openssl-1.1.0h/ssl/ssl_cert.c b/openssl-1.1.0h/ssl/ssl_cert.c
new file mode 100644
index 0000000..deaaeb0
--- /dev/null
+++ b/openssl-1.1.0h/ssl/ssl_cert.c
@@ -0,0 +1,1087 @@
+/*
+ * Copyright 1995-2016 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
+ */
+
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "e_os.h"
+#include "internal/o_dir.h"
+#include <openssl/lhash.h>
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+#include <openssl/x509v3.h>
+#include <openssl/dh.h>
+#include <openssl/bn.h>
+#include <openssl/crypto.h>
+#include "ssl_locl.h"
+#include "internal/thread_once.h"
+
+static int ssl_security_default_callback(const SSL *s, const SSL_CTX *ctx,
+ int op, int bits, int nid, void *other,
+ void *ex);
+
+static CRYPTO_ONCE ssl_x509_store_ctx_once = CRYPTO_ONCE_STATIC_INIT;
+static volatile int ssl_x509_store_ctx_idx = -1;
+
+DEFINE_RUN_ONCE_STATIC(ssl_x509_store_ctx_init)
+{
+ ssl_x509_store_ctx_idx = X509_STORE_CTX_get_ex_new_index(0,
+ "SSL for verify callback",
+ NULL, NULL, NULL);
+ return ssl_x509_store_ctx_idx >= 0;
+}
+
+int SSL_get_ex_data_X509_STORE_CTX_idx(void)
+{
+
+ if (!RUN_ONCE(&ssl_x509_store_ctx_once, ssl_x509_store_ctx_init))
+ return -1;
+ return ssl_x509_store_ctx_idx;
+}
+
+CERT *ssl_cert_new(void)
+{
+ CERT *ret = OPENSSL_zalloc(sizeof(*ret));
+
+ if (ret == NULL) {
+ SSLerr(SSL_F_SSL_CERT_NEW, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ ret->key = &(ret->pkeys[SSL_PKEY_RSA_ENC]);
+ ret->references = 1;
+ ret->sec_cb = ssl_security_default_callback;
+ ret->sec_level = OPENSSL_TLS_SECURITY_LEVEL;
+ ret->sec_ex = NULL;
+ ret->lock = CRYPTO_THREAD_lock_new();
+ if (ret->lock == NULL) {
+ SSLerr(SSL_F_SSL_CERT_NEW, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(ret);
+ return NULL;
+ }
+
+ return ret;
+}
+
+CERT *ssl_cert_dup(CERT *cert)
+{
+ CERT *ret = OPENSSL_zalloc(sizeof(*ret));
+ int i;
+
+ if (ret == NULL) {
+ SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ ret->references = 1;
+ ret->key = &ret->pkeys[cert->key - cert->pkeys];
+ ret->lock = CRYPTO_THREAD_lock_new();
+ if (ret->lock == NULL) {
+ SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(ret);
+ return NULL;
+ }
+#ifndef OPENSSL_NO_DH
+ if (cert->dh_tmp != NULL) {
+ ret->dh_tmp = cert->dh_tmp;
+ EVP_PKEY_up_ref(ret->dh_tmp);
+ }
+ ret->dh_tmp_cb = cert->dh_tmp_cb;
+ ret->dh_tmp_auto = cert->dh_tmp_auto;
+#endif
+
+ for (i = 0; i < SSL_PKEY_NUM; i++) {
+ CERT_PKEY *cpk = cert->pkeys + i;
+ CERT_PKEY *rpk = ret->pkeys + i;
+ if (cpk->x509 != NULL) {
+ rpk->x509 = cpk->x509;
+ X509_up_ref(rpk->x509);
+ }
+
+ if (cpk->privatekey != NULL) {
+ rpk->privatekey = cpk->privatekey;
+ EVP_PKEY_up_ref(cpk->privatekey);
+ }
+
+ if (cpk->chain) {
+ rpk->chain = X509_chain_up_ref(cpk->chain);
+ if (!rpk->chain) {
+ SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+ if (cert->pkeys[i].serverinfo != NULL) {
+ /* Just copy everything. */
+ ret->pkeys[i].serverinfo =
+ OPENSSL_malloc(cert->pkeys[i].serverinfo_length);
+ if (ret->pkeys[i].serverinfo == NULL) {
+ SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ ret->pkeys[i].serverinfo_length = cert->pkeys[i].serverinfo_length;
+ memcpy(ret->pkeys[i].serverinfo,
+ cert->pkeys[i].serverinfo, cert->pkeys[i].serverinfo_length);
+ }
+ }
+
+ /* Configured sigalgs copied across */
+ if (cert->conf_sigalgs) {
+ ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen);
+ if (ret->conf_sigalgs == NULL)
+ goto err;
+ memcpy(ret->conf_sigalgs, cert->conf_sigalgs, cert->conf_sigalgslen);
+ ret->conf_sigalgslen = cert->conf_sigalgslen;
+ } else
+ ret->conf_sigalgs = NULL;
+
+ if (cert->client_sigalgs) {
+ ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen);
+ if (ret->client_sigalgs == NULL)
+ goto err;
+ memcpy(ret->client_sigalgs, cert->client_sigalgs,
+ cert->client_sigalgslen);
+ ret->client_sigalgslen = cert->client_sigalgslen;
+ } else
+ ret->client_sigalgs = NULL;
+ /* Shared sigalgs also NULL */
+ ret->shared_sigalgs = NULL;
+ /* Copy any custom client certificate types */
+ if (cert->ctypes) {
+ ret->ctypes = OPENSSL_malloc(cert->ctype_num);
+ if (ret->ctypes == NULL)
+ goto err;
+ memcpy(ret->ctypes, cert->ctypes, cert->ctype_num);
+ ret->ctype_num = cert->ctype_num;
+ }
+
+ ret->cert_flags = cert->cert_flags;
+
+ ret->cert_cb = cert->cert_cb;
+ ret->cert_cb_arg = cert->cert_cb_arg;
+
+ if (cert->verify_store) {
+ X509_STORE_up_ref(cert->verify_store);
+ ret->verify_store = cert->verify_store;
+ }
+
+ if (cert->chain_store) {
+ X509_STORE_up_ref(cert->chain_store);
+ ret->chain_store = cert->chain_store;
+ }
+
+ ret->sec_cb = cert->sec_cb;
+ ret->sec_level = cert->sec_level;
+ ret->sec_ex = cert->sec_ex;
+
+ if (!custom_exts_copy(&ret->cli_ext, &cert->cli_ext))
+ goto err;
+ if (!custom_exts_copy(&ret->srv_ext, &cert->srv_ext))
+ goto err;
+#ifndef OPENSSL_NO_PSK
+ if (cert->psk_identity_hint) {
+ ret->psk_identity_hint = OPENSSL_strdup(cert->psk_identity_hint);
+ if (ret->psk_identity_hint == NULL)
+ goto err;
+ }
+#endif
+ return ret;
+
+ err:
+ ssl_cert_free(ret);
+
+ return NULL;
+}
+
+/* Free up and clear all certificates and chains */
+
+void ssl_cert_clear_certs(CERT *c)
+{
+ int i;
+ if (c == NULL)
+ return;
+ for (i = 0; i < SSL_PKEY_NUM; i++) {
+ CERT_PKEY *cpk = c->pkeys + i;
+ X509_free(cpk->x509);
+ cpk->x509 = NULL;
+ EVP_PKEY_free(cpk->privatekey);
+ cpk->privatekey = NULL;
+ sk_X509_pop_free(cpk->chain, X509_free);
+ cpk->chain = NULL;
+ OPENSSL_free(cpk->serverinfo);
+ cpk->serverinfo = NULL;
+ cpk->serverinfo_length = 0;
+ }
+}
+
+void ssl_cert_free(CERT *c)
+{
+ int i;
+
+ if (c == NULL)
+ return;
+
+ CRYPTO_atomic_add(&c->references, -1, &i, c->lock);
+ REF_PRINT_COUNT("CERT", c);
+ if (i > 0)
+ return;
+ REF_ASSERT_ISNT(i < 0);
+
+#ifndef OPENSSL_NO_DH
+ EVP_PKEY_free(c->dh_tmp);
+#endif
+
+ ssl_cert_clear_certs(c);
+ OPENSSL_free(c->conf_sigalgs);
+ OPENSSL_free(c->client_sigalgs);
+ OPENSSL_free(c->shared_sigalgs);
+ OPENSSL_free(c->ctypes);
+ X509_STORE_free(c->verify_store);
+ X509_STORE_free(c->chain_store);
+ custom_exts_free(&c->cli_ext);
+ custom_exts_free(&c->srv_ext);
+#ifndef OPENSSL_NO_PSK
+ OPENSSL_free(c->psk_identity_hint);
+#endif
+ CRYPTO_THREAD_lock_free(c->lock);
+ OPENSSL_free(c);
+}
+
+int ssl_cert_set0_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain)
+{
+ int i, r;
+ CERT_PKEY *cpk = s ? s->cert->key : ctx->cert->key;
+ if (!cpk)
+ return 0;
+ for (i = 0; i < sk_X509_num(chain); i++) {
+ r = ssl_security_cert(s, ctx, sk_X509_value(chain, i), 0, 0);
+ if (r != 1) {
+ SSLerr(SSL_F_SSL_CERT_SET0_CHAIN, r);
+ return 0;
+ }
+ }
+ sk_X509_pop_free(cpk->chain, X509_free);
+ cpk->chain = chain;
+ return 1;
+}
+
+int ssl_cert_set1_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain)
+{
+ STACK_OF(X509) *dchain;
+ if (!chain)
+ return ssl_cert_set0_chain(s, ctx, NULL);
+ dchain = X509_chain_up_ref(chain);
+ if (!dchain)
+ return 0;
+ if (!ssl_cert_set0_chain(s, ctx, dchain)) {
+ sk_X509_pop_free(dchain, X509_free);
+ return 0;
+ }
+ return 1;
+}
+
+int ssl_cert_add0_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x)
+{
+ int r;
+ CERT_PKEY *cpk = s ? s->cert->key : ctx->cert->key;
+ if (!cpk)
+ return 0;
+ r = ssl_security_cert(s, ctx, x, 0, 0);
+ if (r != 1) {
+ SSLerr(SSL_F_SSL_CERT_ADD0_CHAIN_CERT, r);
+ return 0;
+ }
+ if (!cpk->chain)
+ cpk->chain = sk_X509_new_null();
+ if (!cpk->chain || !sk_X509_push(cpk->chain, x))
+ return 0;
+ return 1;
+}
+
+int ssl_cert_add1_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x)
+{
+ if (!ssl_cert_add0_chain_cert(s, ctx, x))
+ return 0;
+ X509_up_ref(x);
+ return 1;
+}
+
+int ssl_cert_select_current(CERT *c, X509 *x)
+{
+ int i;
+ if (x == NULL)
+ return 0;
+ for (i = 0; i < SSL_PKEY_NUM; i++) {
+ CERT_PKEY *cpk = c->pkeys + i;
+ if (cpk->x509 == x && cpk->privatekey) {
+ c->key = cpk;
+ return 1;
+ }
+ }
+
+ for (i = 0; i < SSL_PKEY_NUM; i++) {
+ CERT_PKEY *cpk = c->pkeys + i;
+ if (cpk->privatekey && cpk->x509 && !X509_cmp(cpk->x509, x)) {
+ c->key = cpk;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int ssl_cert_set_current(CERT *c, long op)
+{
+ int i, idx;
+ if (!c)
+ return 0;
+ if (op == SSL_CERT_SET_FIRST)
+ idx = 0;
+ else if (op == SSL_CERT_SET_NEXT) {
+ idx = (int)(c->key - c->pkeys + 1);
+ if (idx >= SSL_PKEY_NUM)
+ return 0;
+ } else
+ return 0;
+ for (i = idx; i < SSL_PKEY_NUM; i++) {
+ CERT_PKEY *cpk = c->pkeys + i;
+ if (cpk->x509 && cpk->privatekey) {
+ c->key = cpk;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void ssl_cert_set_cert_cb(CERT *c, int (*cb) (SSL *ssl, void *arg), void *arg)
+{
+ c->cert_cb = cb;
+ c->cert_cb_arg = arg;
+}
+
+int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk)
+{
+ X509 *x;
+ int i = 0;
+ X509_STORE *verify_store;
+ X509_STORE_CTX *ctx = NULL;
+ X509_VERIFY_PARAM *param;
+
+ if ((sk == NULL) || (sk_X509_num(sk) == 0))
+ return 0;
+
+ if (s->cert->verify_store)
+ verify_store = s->cert->verify_store;
+ else
+ verify_store = s->ctx->cert_store;
+
+ ctx = X509_STORE_CTX_new();
+ if (ctx == NULL) {
+ SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ x = sk_X509_value(sk, 0);
+ if (!X509_STORE_CTX_init(ctx, verify_store, x, sk)) {
+ SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_X509_LIB);
+ goto end;
+ }
+ param = X509_STORE_CTX_get0_param(ctx);
+ /*
+ * XXX: Separate @AUTHSECLEVEL and @TLSSECLEVEL would be useful at some
+ * point, for now a single @SECLEVEL sets the same policy for TLS crypto
+ * and PKI authentication.
+ */
+ X509_VERIFY_PARAM_set_auth_level(param, SSL_get_security_level(s));
+
+ /* Set suite B flags if needed */
+ X509_STORE_CTX_set_flags(ctx, tls1_suiteb(s));
+ if (!X509_STORE_CTX_set_ex_data
+ (ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), s)) {
+ goto end;
+ }
+
+ /* Verify via DANE if enabled */
+ if (DANETLS_ENABLED(&s->dane))
+ X509_STORE_CTX_set0_dane(ctx, &s->dane);
+
+ /*
+ * We need to inherit the verify parameters. These can be determined by
+ * the context: if its a server it will verify SSL client certificates or
+ * vice versa.
+ */
+
+ X509_STORE_CTX_set_default(ctx, s->server ? "ssl_client" : "ssl_server");
+ /*
+ * Anything non-default in "s->param" should overwrite anything in the ctx.
+ */
+ X509_VERIFY_PARAM_set1(param, s->param);
+
+ if (s->verify_callback)
+ X509_STORE_CTX_set_verify_cb(ctx, s->verify_callback);
+
+ if (s->ctx->app_verify_callback != NULL)
+ i = s->ctx->app_verify_callback(ctx, s->ctx->app_verify_arg);
+ else
+ i = X509_verify_cert(ctx);
+
+ s->verify_result = X509_STORE_CTX_get_error(ctx);
+ sk_X509_pop_free(s->verified_chain, X509_free);
+ s->verified_chain = NULL;
+ if (X509_STORE_CTX_get0_chain(ctx) != NULL) {
+ s->verified_chain = X509_STORE_CTX_get1_chain(ctx);
+ if (s->verified_chain == NULL) {
+ SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_MALLOC_FAILURE);
+ i = 0;
+ }
+ }
+
+ /* Move peername from the store context params to the SSL handle's */
+ X509_VERIFY_PARAM_move_peername(s->param, param);
+
+ end:
+ X509_STORE_CTX_free(ctx);
+ return i;
+}
+
+static void set_client_CA_list(STACK_OF(X509_NAME) **ca_list,
+ STACK_OF(X509_NAME) *name_list)
+{
+ sk_X509_NAME_pop_free(*ca_list, X509_NAME_free);
+ *ca_list = name_list;
+}
+
+STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk)
+{
+ int i;
+ STACK_OF(X509_NAME) *ret;
+ X509_NAME *name;
+
+ ret = sk_X509_NAME_new_null();
+ if (ret == NULL) {
+ SSLerr(SSL_F_SSL_DUP_CA_LIST, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ for (i = 0; i < sk_X509_NAME_num(sk); i++) {
+ name = X509_NAME_dup(sk_X509_NAME_value(sk, i));
+ if (name == NULL || !sk_X509_NAME_push(ret, name)) {
+ sk_X509_NAME_pop_free(ret, X509_NAME_free);
+ X509_NAME_free(name);
+ return NULL;
+ }
+ }
+ return (ret);
+}
+
+void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list)
+{
+ set_client_CA_list(&(s->client_CA), name_list);
+}
+
+void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list)
+{
+ set_client_CA_list(&(ctx->client_CA), name_list);
+}
+
+STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx)
+{
+ return (ctx->client_CA);
+}
+
+STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s)
+{
+ if (!s->server) { /* we are in the client */
+ if (((s->version >> 8) == SSL3_VERSION_MAJOR) && (s->s3 != NULL))
+ return (s->s3->tmp.ca_names);
+ else
+ return (NULL);
+ } else {
+ if (s->client_CA != NULL)
+ return (s->client_CA);
+ else
+ return (s->ctx->client_CA);
+ }
+}
+
+static int add_client_CA(STACK_OF(X509_NAME) **sk, X509 *x)
+{
+ X509_NAME *name;
+
+ if (x == NULL)
+ return (0);
+ if ((*sk == NULL) && ((*sk = sk_X509_NAME_new_null()) == NULL))
+ return (0);
+
+ if ((name = X509_NAME_dup(X509_get_subject_name(x))) == NULL)
+ return (0);
+
+ if (!sk_X509_NAME_push(*sk, name)) {
+ X509_NAME_free(name);
+ return (0);
+ }
+ return (1);
+}
+
+int SSL_add_client_CA(SSL *ssl, X509 *x)
+{
+ return (add_client_CA(&(ssl->client_CA), x));
+}
+
+int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x)
+{
+ return (add_client_CA(&(ctx->client_CA), x));
+}
+
+static int xname_sk_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
+{
+ return (X509_NAME_cmp(*a, *b));
+}
+
+static int xname_cmp(const X509_NAME *a, const X509_NAME *b)
+{
+ return X509_NAME_cmp(a, b);
+}
+
+static unsigned long xname_hash(const X509_NAME *a)
+{
+ return X509_NAME_hash((X509_NAME *)a);
+}
+
+/**
+ * Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed;
+ * it doesn't really have anything to do with clients (except that a common use
+ * for a stack of CAs is to send it to the client). Actually, it doesn't have
+ * much to do with CAs, either, since it will load any old cert.
+ * \param file the file containing one or more certs.
+ * \return a ::STACK containing the certs.
+ */
+STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file)
+{
+ BIO *in = BIO_new(BIO_s_file());
+ X509 *x = NULL;
+ X509_NAME *xn = NULL;
+ STACK_OF(X509_NAME) *ret = NULL;
+ LHASH_OF(X509_NAME) *name_hash = lh_X509_NAME_new(xname_hash, xname_cmp);
+
+ if ((name_hash == NULL) || (in == NULL)) {
+ SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!BIO_read_filename(in, file))
+ goto err;
+
+ for (;;) {
+ if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
+ break;
+ if (ret == NULL) {
+ ret = sk_X509_NAME_new_null();
+ if (ret == NULL) {
+ SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+ if ((xn = X509_get_subject_name(x)) == NULL)
+ goto err;
+ /* check for duplicates */
+ xn = X509_NAME_dup(xn);
+ if (xn == NULL)
+ goto err;
+ if (lh_X509_NAME_retrieve(name_hash, xn) != NULL) {
+ /* Duplicate. */
+ X509_NAME_free(xn);
+ xn = NULL;
+ } else {
+ lh_X509_NAME_insert(name_hash, xn);
+ if (!sk_X509_NAME_push(ret, xn))
+ goto err;
+ }
+ }
+ goto done;
+
+ err:
+ X509_NAME_free(xn);
+ sk_X509_NAME_pop_free(ret, X509_NAME_free);
+ ret = NULL;
+ done:
+ BIO_free(in);
+ X509_free(x);
+ lh_X509_NAME_free(name_hash);
+ if (ret != NULL)
+ ERR_clear_error();
+ return (ret);
+}
+
+/**
+ * Add a file of certs to a stack.
+ * \param stack the stack to add to.
+ * \param file the file to add from. All certs in this file that are not
+ * already in the stack will be added.
+ * \return 1 for success, 0 for failure. Note that in the case of failure some
+ * certs may have been added to \c stack.
+ */
+
+int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
+ const char *file)
+{
+ BIO *in;
+ X509 *x = NULL;
+ X509_NAME *xn = NULL;
+ int ret = 1;
+ int (*oldcmp) (const X509_NAME *const *a, const X509_NAME *const *b);
+
+ oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_sk_cmp);
+
+ in = BIO_new(BIO_s_file());
+
+ if (in == NULL) {
+ SSLerr(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!BIO_read_filename(in, file))
+ goto err;
+
+ for (;;) {
+ if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
+ break;
+ if ((xn = X509_get_subject_name(x)) == NULL)
+ goto err;
+ xn = X509_NAME_dup(xn);
+ if (xn == NULL)
+ goto err;
+ if (sk_X509_NAME_find(stack, xn) >= 0) {
+ /* Duplicate. */
+ X509_NAME_free(xn);
+ } else if (!sk_X509_NAME_push(stack, xn)) {
+ X509_NAME_free(xn);
+ goto err;
+ }
+ }
+
+ ERR_clear_error();
+ goto done;
+
+ err:
+ ret = 0;
+ done:
+ BIO_free(in);
+ X509_free(x);
+ (void)sk_X509_NAME_set_cmp_func(stack, oldcmp);
+ return ret;
+}
+
+/**
+ * Add a directory of certs to a stack.
+ * \param stack the stack to append to.
+ * \param dir the directory to append from. All files in this directory will be
+ * examined as potential certs. Any that are acceptable to
+ * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will be
+ * included.
+ * \return 1 for success, 0 for failure. Note that in the case of failure some
+ * certs may have been added to \c stack.
+ */
+
+int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
+ const char *dir)
+{
+ OPENSSL_DIR_CTX *d = NULL;
+ const char *filename;
+ int ret = 0;
+
+ /* Note that a side effect is that the CAs will be sorted by name */
+
+ while ((filename = OPENSSL_DIR_read(&d, dir))) {
+ char buf[1024];
+ int r;
+
+ if (strlen(dir) + strlen(filename) + 2 > sizeof(buf)) {
+ SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK,
+ SSL_R_PATH_TOO_LONG);
+ goto err;
+ }
+#ifdef OPENSSL_SYS_VMS
+ r = BIO_snprintf(buf, sizeof(buf), "%s%s", dir, filename);
+#else
+ r = BIO_snprintf(buf, sizeof(buf), "%s/%s", dir, filename);
+#endif
+ if (r <= 0 || r >= (int)sizeof(buf))
+ goto err;
+ if (!SSL_add_file_cert_subjects_to_stack(stack, buf))
+ goto err;
+ }
+
+ if (errno) {
+ SYSerr(SYS_F_OPENDIR, get_last_sys_error());
+ ERR_add_error_data(3, "OPENSSL_DIR_read(&ctx, '", dir, "')");
+ SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK, ERR_R_SYS_LIB);
+ goto err;
+ }
+
+ ret = 1;
+
+ err:
+ if (d)
+ OPENSSL_DIR_end(&d);
+
+ return ret;
+}
+
+/* Add a certificate to a BUF_MEM structure */
+
+static int ssl_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x)
+{
+ int n;
+ unsigned char *p;
+
+ n = i2d_X509(x, NULL);
+ if (n < 0 || !BUF_MEM_grow_clean(buf, (int)(n + (*l) + 3))) {
+ SSLerr(SSL_F_SSL_ADD_CERT_TO_BUF, ERR_R_BUF_LIB);
+ return 0;
+ }
+ p = (unsigned char *)&(buf->data[*l]);
+ l2n3(n, p);
+ n = i2d_X509(x, &p);
+ if (n < 0) {
+ /* Shouldn't happen */
+ SSLerr(SSL_F_SSL_ADD_CERT_TO_BUF, ERR_R_BUF_LIB);
+ return 0;
+ }
+ *l += n + 3;
+
+ return 1;
+}
+
+/* Add certificate chain to internal SSL BUF_MEM structure */
+int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l)
+{
+ BUF_MEM *buf = s->init_buf;
+ int i, chain_count;
+ X509 *x;
+ STACK_OF(X509) *extra_certs;
+ STACK_OF(X509) *chain = NULL;
+ X509_STORE *chain_store;
+
+ /* TLSv1 sends a chain with nothing in it, instead of an alert */
+ if (!BUF_MEM_grow_clean(buf, 10)) {
+ SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, ERR_R_BUF_LIB);
+ return 0;
+ }
+
+ if (!cpk || !cpk->x509)
+ return 1;
+
+ x = cpk->x509;
+
+ /*
+ * If we have a certificate specific chain use it, else use parent ctx.
+ */
+ if (cpk->chain)
+ 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) {
+ X509_STORE_CTX *xs_ctx = X509_STORE_CTX_new();
+
+ if (xs_ctx == NULL) {
+ SSLerr(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);
+ SSLerr(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);
+ SSLerr(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_buf(buf, l, x)) {
+ 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) {
+ SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, i);
+ return 0;
+ }
+ if (!ssl_add_cert_to_buf(buf, l, x))
+ return 0;
+ for (i = 0; i < sk_X509_num(extra_certs); i++) {
+ x = sk_X509_value(extra_certs, i);
+ if (!ssl_add_cert_to_buf(buf, l, x))
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* Build a certificate chain for current certificate */
+int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags)
+{
+ CERT *c = s ? s->cert : ctx->cert;
+ CERT_PKEY *cpk = c->key;
+ X509_STORE *chain_store = NULL;
+ X509_STORE_CTX *xs_ctx = NULL;
+ STACK_OF(X509) *chain = NULL, *untrusted = NULL;
+ X509 *x;
+ int i, rv = 0;
+ unsigned long error;
+
+ if (!cpk->x509) {
+ SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_NO_CERTIFICATE_SET);
+ goto err;
+ }
+ /* Rearranging and check the chain: add everything to a store */
+ if (flags & SSL_BUILD_CHAIN_FLAG_CHECK) {
+ chain_store = X509_STORE_new();
+ if (chain_store == NULL)
+ goto err;
+ for (i = 0; i < sk_X509_num(cpk->chain); i++) {
+ x = sk_X509_value(cpk->chain, i);
+ if (!X509_STORE_add_cert(chain_store, x)) {
+ error = ERR_peek_last_error();
+ if (ERR_GET_LIB(error) != ERR_LIB_X509 ||
+ ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE)
+ goto err;
+ ERR_clear_error();
+ }
+ }
+ /* Add EE cert too: it might be self signed */
+ if (!X509_STORE_add_cert(chain_store, cpk->x509)) {
+ error = ERR_peek_last_error();
+ if (ERR_GET_LIB(error) != ERR_LIB_X509 ||
+ ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE)
+ goto err;
+ ERR_clear_error();
+ }
+ } else {
+ if (c->chain_store)
+ chain_store = c->chain_store;
+ else if (s)
+ chain_store = s->ctx->cert_store;
+ else
+ chain_store = ctx->cert_store;
+
+ if (flags & SSL_BUILD_CHAIN_FLAG_UNTRUSTED)
+ untrusted = cpk->chain;
+ }
+
+ xs_ctx = X509_STORE_CTX_new();
+ if (xs_ctx == NULL) {
+ SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!X509_STORE_CTX_init(xs_ctx, chain_store, cpk->x509, untrusted)) {
+ SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_X509_LIB);
+ goto err;
+ }
+ /* Set suite B flags if needed */
+ X509_STORE_CTX_set_flags(xs_ctx,
+ c->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS);
+
+ i = X509_verify_cert(xs_ctx);
+ if (i <= 0 && flags & SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR) {
+ if (flags & SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR)
+ ERR_clear_error();
+ i = 1;
+ rv = 2;
+ }
+ if (i > 0)
+ chain = X509_STORE_CTX_get1_chain(xs_ctx);
+ if (i <= 0) {
+ SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_CERTIFICATE_VERIFY_FAILED);
+ i = X509_STORE_CTX_get_error(xs_ctx);
+ ERR_add_error_data(2, "Verify error:",
+ X509_verify_cert_error_string(i));
+
+ goto err;
+ }
+ /* Remove EE certificate from chain */
+ x = sk_X509_shift(chain);
+ X509_free(x);
+ if (flags & SSL_BUILD_CHAIN_FLAG_NO_ROOT) {
+ if (sk_X509_num(chain) > 0) {
+ /* See if last cert is self signed */
+ x = sk_X509_value(chain, sk_X509_num(chain) - 1);
+ if (X509_get_extension_flags(x) & EXFLAG_SS) {
+ x = sk_X509_pop(chain);
+ X509_free(x);
+ }
+ }
+ }
+ /*
+ * Check security level of all CA certificates: EE will have been checked
+ * already.
+ */
+ for (i = 0; i < sk_X509_num(chain); i++) {
+ x = sk_X509_value(chain, i);
+ rv = ssl_security_cert(s, ctx, x, 0, 0);
+ if (rv != 1) {
+ SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, rv);
+ sk_X509_pop_free(chain, X509_free);
+ rv = 0;
+ goto err;
+ }
+ }
+ sk_X509_pop_free(cpk->chain, X509_free);
+ cpk->chain = chain;
+ if (rv == 0)
+ rv = 1;
+ err:
+ if (flags & SSL_BUILD_CHAIN_FLAG_CHECK)
+ X509_STORE_free(chain_store);
+ X509_STORE_CTX_free(xs_ctx);
+
+ return rv;
+}
+
+int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, int ref)
+{
+ X509_STORE **pstore;
+ if (chain)
+ pstore = &c->chain_store;
+ else
+ pstore = &c->verify_store;
+ X509_STORE_free(*pstore);
+ *pstore = store;
+ if (ref && store)
+ X509_STORE_up_ref(store);
+ return 1;
+}
+
+static int ssl_security_default_callback(const SSL *s, const SSL_CTX *ctx,
+ int op, int bits, int nid, void *other,
+ void *ex)
+{
+ int level, minbits;
+ static const int minbits_table[5] = { 80, 112, 128, 192, 256 };
+ if (ctx)
+ level = SSL_CTX_get_security_level(ctx);
+ else
+ level = SSL_get_security_level(s);
+
+ if (level <= 0) {
+ /*
+ * No EDH keys weaker than 1024-bits even at level 0, otherwise,
+ * anything goes.
+ */
+ if (op == SSL_SECOP_TMP_DH && bits < 80)
+ return 0;
+ return 1;
+ }
+ if (level > 5)
+ level = 5;
+ minbits = minbits_table[level - 1];
+ switch (op) {
+ case SSL_SECOP_CIPHER_SUPPORTED:
+ case SSL_SECOP_CIPHER_SHARED:
+ case SSL_SECOP_CIPHER_CHECK:
+ {
+ const SSL_CIPHER *c = other;
+ /* No ciphers below security level */
+ if (bits < minbits)
+ return 0;
+ /* No unauthenticated ciphersuites */
+ if (c->algorithm_auth & SSL_aNULL)
+ return 0;
+ /* No MD5 mac ciphersuites */
+ if (c->algorithm_mac & SSL_MD5)
+ return 0;
+ /* SHA1 HMAC is 160 bits of security */
+ if (minbits > 160 && c->algorithm_mac & SSL_SHA1)
+ return 0;
+ /* Level 2: no RC4 */
+ if (level >= 2 && c->algorithm_enc == SSL_RC4)
+ return 0;
+ /* Level 3: forward secure ciphersuites only */
+ if (level >= 3 && !(c->algorithm_mkey & (SSL_kEDH | SSL_kEECDH)))
+ return 0;
+ break;
+ }
+ case SSL_SECOP_VERSION:
+ if (!SSL_IS_DTLS(s)) {
+ /* SSLv3 not allowed at level 2 */
+ if (nid <= SSL3_VERSION && level >= 2)
+ return 0;
+ /* TLS v1.1 and above only for level 3 */
+ if (nid <= TLS1_VERSION && level >= 3)
+ return 0;
+ /* TLS v1.2 only for level 4 and above */
+ if (nid <= TLS1_1_VERSION && level >= 4)
+ return 0;
+ } else {
+ /* DTLS v1.2 only for level 4 and above */
+ if (DTLS_VERSION_LT(nid, DTLS1_2_VERSION) && level >= 4)
+ return 0;
+ }
+ break;
+
+ case SSL_SECOP_COMPRESSION:
+ if (level >= 2)
+ return 0;
+ break;
+ case SSL_SECOP_TICKET:
+ if (level >= 3)
+ return 0;
+ break;
+ default:
+ if (bits < minbits)
+ return 0;
+ }
+ return 1;
+}
+
+int ssl_security(const SSL *s, int op, int bits, int nid, void *other)
+{
+ return s->cert->sec_cb(s, NULL, op, bits, nid, other, s->cert->sec_ex);
+}
+
+int ssl_ctx_security(const SSL_CTX *ctx, int op, int bits, int nid, void *other)
+{
+ return ctx->cert->sec_cb(NULL, ctx, op, bits, nid, other,
+ ctx->cert->sec_ex);
+}
diff --git a/openssl-1.1.0h/ssl/ssl_ciph.c b/openssl-1.1.0h/ssl/ssl_ciph.c
new file mode 100644
index 0000000..7a393cb
--- /dev/null
+++ b/openssl-1.1.0h/ssl/ssl_ciph.c
@@ -0,0 +1,1962 @@
+/*
+ * Copyright 1995-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
+ */
+
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <openssl/objects.h>
+#include <openssl/comp.h>
+#include <openssl/engine.h>
+#include <openssl/crypto.h>
+#include "ssl_locl.h"
+#include "internal/thread_once.h"
+
+#define SSL_ENC_DES_IDX 0
+#define SSL_ENC_3DES_IDX 1
+#define SSL_ENC_RC4_IDX 2
+#define SSL_ENC_RC2_IDX 3
+#define SSL_ENC_IDEA_IDX 4
+#define SSL_ENC_NULL_IDX 5
+#define SSL_ENC_AES128_IDX 6
+#define SSL_ENC_AES256_IDX 7
+#define SSL_ENC_CAMELLIA128_IDX 8
+#define SSL_ENC_CAMELLIA256_IDX 9
+#define SSL_ENC_GOST89_IDX 10
+#define SSL_ENC_SEED_IDX 11
+#define SSL_ENC_AES128GCM_IDX 12
+#define SSL_ENC_AES256GCM_IDX 13
+#define SSL_ENC_AES128CCM_IDX 14
+#define SSL_ENC_AES256CCM_IDX 15
+#define SSL_ENC_AES128CCM8_IDX 16
+#define SSL_ENC_AES256CCM8_IDX 17
+#define SSL_ENC_GOST8912_IDX 18
+#define SSL_ENC_CHACHA_IDX 19
+#define SSL_ENC_NUM_IDX 20
+
+/* NB: make sure indices in these tables match values above */
+
+typedef struct {
+ uint32_t mask;
+ int nid;
+} ssl_cipher_table;
+
+/* Table of NIDs for each cipher */
+static const ssl_cipher_table ssl_cipher_table_cipher[SSL_ENC_NUM_IDX] = {
+ {SSL_DES, NID_des_cbc}, /* SSL_ENC_DES_IDX 0 */
+ {SSL_3DES, NID_des_ede3_cbc}, /* SSL_ENC_3DES_IDX 1 */
+ {SSL_RC4, NID_rc4}, /* SSL_ENC_RC4_IDX 2 */
+ {SSL_RC2, NID_rc2_cbc}, /* SSL_ENC_RC2_IDX 3 */
+ {SSL_IDEA, NID_idea_cbc}, /* SSL_ENC_IDEA_IDX 4 */
+ {SSL_eNULL, NID_undef}, /* SSL_ENC_NULL_IDX 5 */
+ {SSL_AES128, NID_aes_128_cbc}, /* SSL_ENC_AES128_IDX 6 */
+ {SSL_AES256, NID_aes_256_cbc}, /* SSL_ENC_AES256_IDX 7 */
+ {SSL_CAMELLIA128, NID_camellia_128_cbc}, /* SSL_ENC_CAMELLIA128_IDX 8 */
+ {SSL_CAMELLIA256, NID_camellia_256_cbc}, /* SSL_ENC_CAMELLIA256_IDX 9 */
+ {SSL_eGOST2814789CNT, NID_gost89_cnt}, /* SSL_ENC_GOST89_IDX 10 */
+ {SSL_SEED, NID_seed_cbc}, /* SSL_ENC_SEED_IDX 11 */
+ {SSL_AES128GCM, NID_aes_128_gcm}, /* SSL_ENC_AES128GCM_IDX 12 */
+ {SSL_AES256GCM, NID_aes_256_gcm}, /* SSL_ENC_AES256GCM_IDX 13 */
+ {SSL_AES128CCM, NID_aes_128_ccm}, /* SSL_ENC_AES128CCM_IDX 14 */
+ {SSL_AES256CCM, NID_aes_256_ccm}, /* SSL_ENC_AES256CCM_IDX 15 */
+ {SSL_AES128CCM8, NID_aes_128_ccm}, /* SSL_ENC_AES128CCM8_IDX 16 */
+ {SSL_AES256CCM8, NID_aes_256_ccm}, /* SSL_ENC_AES256CCM8_IDX 17 */
+ {SSL_eGOST2814789CNT12, NID_gost89_cnt_12}, /* SSL_ENC_GOST8912_IDX */
+ {SSL_CHACHA20POLY1305, NID_chacha20_poly1305},
+};
+
+static const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX] = {
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL
+};
+
+#define SSL_COMP_NULL_IDX 0
+#define SSL_COMP_ZLIB_IDX 1
+#define SSL_COMP_NUM_IDX 2
+
+static STACK_OF(SSL_COMP) *ssl_comp_methods = NULL;
+
+#ifndef OPENSSL_NO_COMP
+static CRYPTO_ONCE ssl_load_builtin_comp_once = CRYPTO_ONCE_STATIC_INIT;
+#endif
+
+/*
+ * Constant SSL_MAX_DIGEST equal to size of digests array should be defined
+ * in the ssl_locl.h
+ */
+
+#define SSL_MD_NUM_IDX SSL_MAX_DIGEST
+
+/* NB: make sure indices in this table matches values above */
+static const ssl_cipher_table ssl_cipher_table_mac[SSL_MD_NUM_IDX] = {
+ {SSL_MD5, NID_md5}, /* SSL_MD_MD5_IDX 0 */
+ {SSL_SHA1, NID_sha1}, /* SSL_MD_SHA1_IDX 1 */
+ {SSL_GOST94, NID_id_GostR3411_94}, /* SSL_MD_GOST94_IDX 2 */
+ {SSL_GOST89MAC, NID_id_Gost28147_89_MAC}, /* SSL_MD_GOST89MAC_IDX 3 */
+ {SSL_SHA256, NID_sha256}, /* SSL_MD_SHA256_IDX 4 */
+ {SSL_SHA384, NID_sha384}, /* SSL_MD_SHA384_IDX 5 */
+ {SSL_GOST12_256, NID_id_GostR3411_2012_256}, /* SSL_MD_GOST12_256_IDX 6 */
+ {SSL_GOST89MAC12, NID_gost_mac_12}, /* SSL_MD_GOST89MAC12_IDX 7 */
+ {SSL_GOST12_512, NID_id_GostR3411_2012_512}, /* SSL_MD_GOST12_512_IDX 8 */
+ {0, NID_md5_sha1}, /* SSL_MD_MD5_SHA1_IDX 9 */
+ {0, NID_sha224}, /* SSL_MD_SHA224_IDX 10 */
+ {0, NID_sha512} /* SSL_MD_SHA512_IDX 11 */
+};
+
+static const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX] = {
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+/* *INDENT-OFF* */
+static const ssl_cipher_table ssl_cipher_table_kx[] = {
+ {SSL_kRSA, NID_kx_rsa},
+ {SSL_kECDHE, NID_kx_ecdhe},
+ {SSL_kDHE, NID_kx_dhe},
+ {SSL_kECDHEPSK, NID_kx_ecdhe_psk},
+ {SSL_kDHEPSK, NID_kx_dhe_psk},
+ {SSL_kRSAPSK, NID_kx_rsa_psk},
+ {SSL_kPSK, NID_kx_psk},
+ {SSL_kSRP, NID_kx_srp},
+ {SSL_kGOST, NID_kx_gost}
+};
+
+static const ssl_cipher_table ssl_cipher_table_auth[] = {
+ {SSL_aRSA, NID_auth_rsa},
+ {SSL_aECDSA, NID_auth_ecdsa},
+ {SSL_aPSK, NID_auth_psk},
+ {SSL_aDSS, NID_auth_dss},
+ {SSL_aGOST01, NID_auth_gost01},
+ {SSL_aGOST12, NID_auth_gost12},
+ {SSL_aSRP, NID_auth_srp},
+ {SSL_aNULL, NID_auth_null}
+};
+/* *INDENT-ON* */
+
+/* Utility function for table lookup */
+static int ssl_cipher_info_find(const ssl_cipher_table * table,
+ size_t table_cnt, uint32_t mask)
+{
+ size_t i;
+ for (i = 0; i < table_cnt; i++, table++) {
+ if (table->mask == mask)
+ return i;
+ }
+ return -1;
+}
+
+#define ssl_cipher_info_lookup(table, x) \
+ ssl_cipher_info_find(table, OSSL_NELEM(table), x)
+
+/*
+ * PKEY_TYPE for GOST89MAC is known in advance, but, because implementation
+ * is engine-provided, we'll fill it only if corresponding EVP_PKEY_METHOD is
+ * found
+ */
+static int ssl_mac_pkey_id[SSL_MD_NUM_IDX] = {
+ /* MD5, SHA, GOST94, MAC89 */
+ EVP_PKEY_HMAC, EVP_PKEY_HMAC, EVP_PKEY_HMAC, NID_undef,
+ /* SHA256, SHA384, GOST2012_256, MAC89-12 */
+ EVP_PKEY_HMAC, EVP_PKEY_HMAC, EVP_PKEY_HMAC, NID_undef,
+ /* GOST2012_512 */
+ EVP_PKEY_HMAC,
+};
+
+static int ssl_mac_secret_size[SSL_MD_NUM_IDX];
+
+#define CIPHER_ADD 1
+#define CIPHER_KILL 2
+#define CIPHER_DEL 3
+#define CIPHER_ORD 4
+#define CIPHER_SPECIAL 5
+/*
+ * Bump the ciphers to the top of the list.
+ * This rule isn't currently supported by the public cipherstring API.
+ */
+#define CIPHER_BUMP 6
+
+typedef struct cipher_order_st {
+ const SSL_CIPHER *cipher;
+ int active;
+ int dead;
+ struct cipher_order_st *next, *prev;
+} CIPHER_ORDER;
+
+static const SSL_CIPHER cipher_aliases[] = {
+ /* "ALL" doesn't include eNULL (must be specifically enabled) */
+ {0, SSL_TXT_ALL, 0, 0, 0, ~SSL_eNULL},
+ /* "COMPLEMENTOFALL" */
+ {0, SSL_TXT_CMPALL, 0, 0, 0, SSL_eNULL},
+
+ /*
+ * "COMPLEMENTOFDEFAULT" (does *not* include ciphersuites not found in
+ * ALL!)
+ */
+ {0, SSL_TXT_CMPDEF, 0, 0, 0, 0, 0, 0, 0, 0, 0, SSL_NOT_DEFAULT},
+
+ /*
+ * key exchange aliases (some of those using only a single bit here
+ * combine multiple key exchange algs according to the RFCs, e.g. kDHE
+ * combines DHE_DSS and DHE_RSA)
+ */
+ {0, SSL_TXT_kRSA, 0, SSL_kRSA},
+
+ {0, SSL_TXT_kEDH, 0, SSL_kDHE},
+ {0, SSL_TXT_kDHE, 0, SSL_kDHE},
+ {0, SSL_TXT_DH, 0, SSL_kDHE},
+
+ {0, SSL_TXT_kEECDH, 0, SSL_kECDHE},
+ {0, SSL_TXT_kECDHE, 0, SSL_kECDHE},
+ {0, SSL_TXT_ECDH, 0, SSL_kECDHE},
+
+ {0, SSL_TXT_kPSK, 0, SSL_kPSK},
+ {0, SSL_TXT_kRSAPSK, 0, SSL_kRSAPSK},
+ {0, SSL_TXT_kECDHEPSK, 0, SSL_kECDHEPSK},
+ {0, SSL_TXT_kDHEPSK, 0, SSL_kDHEPSK},
+ {0, SSL_TXT_kSRP, 0, SSL_kSRP},
+ {0, SSL_TXT_kGOST, 0, SSL_kGOST},
+
+ /* server authentication aliases */
+ {0, SSL_TXT_aRSA, 0, 0, SSL_aRSA},
+ {0, SSL_TXT_aDSS, 0, 0, SSL_aDSS},
+ {0, SSL_TXT_DSS, 0, 0, SSL_aDSS},
+ {0, SSL_TXT_aNULL, 0, 0, SSL_aNULL},
+ {0, SSL_TXT_aECDSA, 0, 0, SSL_aECDSA},
+ {0, SSL_TXT_ECDSA, 0, 0, SSL_aECDSA},
+ {0, SSL_TXT_aPSK, 0, 0, SSL_aPSK},
+ {0, SSL_TXT_aGOST01, 0, 0, SSL_aGOST01},
+ {0, SSL_TXT_aGOST12, 0, 0, SSL_aGOST12},
+ {0, SSL_TXT_aGOST, 0, 0, SSL_aGOST01 | SSL_aGOST12},
+ {0, SSL_TXT_aSRP, 0, 0, SSL_aSRP},
+
+ /* aliases combining key exchange and server authentication */
+ {0, SSL_TXT_EDH, 0, SSL_kDHE, ~SSL_aNULL},
+ {0, SSL_TXT_DHE, 0, SSL_kDHE, ~SSL_aNULL},
+ {0, SSL_TXT_EECDH, 0, SSL_kECDHE, ~SSL_aNULL},
+ {0, SSL_TXT_ECDHE, 0, SSL_kECDHE, ~SSL_aNULL},
+ {0, SSL_TXT_NULL, 0, 0, 0, SSL_eNULL},
+ {0, SSL_TXT_RSA, 0, SSL_kRSA, SSL_aRSA},
+ {0, SSL_TXT_ADH, 0, SSL_kDHE, SSL_aNULL},
+ {0, SSL_TXT_AECDH, 0, SSL_kECDHE, SSL_aNULL},
+ {0, SSL_TXT_PSK, 0, SSL_PSK},
+ {0, SSL_TXT_SRP, 0, SSL_kSRP},
+
+ /* symmetric encryption aliases */
+ {0, SSL_TXT_3DES, 0, 0, 0, SSL_3DES},
+ {0, SSL_TXT_RC4, 0, 0, 0, SSL_RC4},
+ {0, SSL_TXT_RC2, 0, 0, 0, SSL_RC2},
+ {0, SSL_TXT_IDEA, 0, 0, 0, SSL_IDEA},
+ {0, SSL_TXT_SEED, 0, 0, 0, SSL_SEED},
+ {0, SSL_TXT_eNULL, 0, 0, 0, SSL_eNULL},
+ {0, SSL_TXT_GOST, 0, 0, 0, SSL_eGOST2814789CNT | SSL_eGOST2814789CNT12},
+ {0, SSL_TXT_AES128, 0, 0, 0,
+ SSL_AES128 | SSL_AES128GCM | SSL_AES128CCM | SSL_AES128CCM8},
+ {0, SSL_TXT_AES256, 0, 0, 0,
+ SSL_AES256 | SSL_AES256GCM | SSL_AES256CCM | SSL_AES256CCM8},
+ {0, SSL_TXT_AES, 0, 0, 0, SSL_AES},
+ {0, SSL_TXT_AES_GCM, 0, 0, 0, SSL_AES128GCM | SSL_AES256GCM},
+ {0, SSL_TXT_AES_CCM, 0, 0, 0,
+ SSL_AES128CCM | SSL_AES256CCM | SSL_AES128CCM8 | SSL_AES256CCM8},
+ {0, SSL_TXT_AES_CCM_8, 0, 0, 0, SSL_AES128CCM8 | SSL_AES256CCM8},
+ {0, SSL_TXT_CAMELLIA128, 0, 0, 0, SSL_CAMELLIA128},
+ {0, SSL_TXT_CAMELLIA256, 0, 0, 0, SSL_CAMELLIA256},
+ {0, SSL_TXT_CAMELLIA, 0, 0, 0, SSL_CAMELLIA},
+ {0, SSL_TXT_CHACHA20, 0, 0, 0, SSL_CHACHA20},
+
+ /* MAC aliases */
+ {0, SSL_TXT_MD5, 0, 0, 0, 0, SSL_MD5},
+ {0, SSL_TXT_SHA1, 0, 0, 0, 0, SSL_SHA1},
+ {0, SSL_TXT_SHA, 0, 0, 0, 0, SSL_SHA1},
+ {0, SSL_TXT_GOST94, 0, 0, 0, 0, SSL_GOST94},
+ {0, SSL_TXT_GOST89MAC, 0, 0, 0, 0, SSL_GOST89MAC | SSL_GOST89MAC12},
+ {0, SSL_TXT_SHA256, 0, 0, 0, 0, SSL_SHA256},
+ {0, SSL_TXT_SHA384, 0, 0, 0, 0, SSL_SHA384},
+ {0, SSL_TXT_GOST12, 0, 0, 0, 0, SSL_GOST12_256},
+
+ /* protocol version aliases */
+ {0, SSL_TXT_SSLV3, 0, 0, 0, 0, 0, SSL3_VERSION},
+ {0, SSL_TXT_TLSV1, 0, 0, 0, 0, 0, TLS1_VERSION},
+ {0, "TLSv1.0", 0, 0, 0, 0, 0, TLS1_VERSION},
+ {0, SSL_TXT_TLSV1_2, 0, 0, 0, 0, 0, TLS1_2_VERSION},
+
+ /* strength classes */
+ {0, SSL_TXT_LOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, SSL_LOW},
+ {0, SSL_TXT_MEDIUM, 0, 0, 0, 0, 0, 0, 0, 0, 0, SSL_MEDIUM},
+ {0, SSL_TXT_HIGH, 0, 0, 0, 0, 0, 0, 0, 0, 0, SSL_HIGH},
+ /* FIPS 140-2 approved ciphersuite */
+ {0, SSL_TXT_FIPS, 0, 0, 0, ~SSL_eNULL, 0, 0, 0, 0, 0, SSL_FIPS},
+
+ /* "EDH-" aliases to "DHE-" labels (for backward compatibility) */
+ {0, SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA, 0,
+ SSL_kDHE, SSL_aDSS, SSL_3DES, SSL_SHA1, 0, 0, 0, 0, SSL_HIGH | SSL_FIPS},
+ {0, SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA, 0,
+ SSL_kDHE, SSL_aRSA, SSL_3DES, SSL_SHA1, 0, 0, 0, 0, SSL_HIGH | SSL_FIPS},
+
+};
+
+/*
+ * Search for public key algorithm with given name and return its pkey_id if
+ * it is available. Otherwise return 0
+ */
+#ifdef OPENSSL_NO_ENGINE
+
+static int get_optional_pkey_id(const char *pkey_name)
+{
+ const EVP_PKEY_ASN1_METHOD *ameth;
+ int pkey_id = 0;
+ ameth = EVP_PKEY_asn1_find_str(NULL, pkey_name, -1);
+ if (ameth && EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL,
+ ameth) > 0) {
+ return pkey_id;
+ }
+ return 0;
+}
+
+#else
+
+static int get_optional_pkey_id(const char *pkey_name)
+{
+ const EVP_PKEY_ASN1_METHOD *ameth;
+ ENGINE *tmpeng = NULL;
+ int pkey_id = 0;
+ ameth = EVP_PKEY_asn1_find_str(&tmpeng, pkey_name, -1);
+ if (ameth) {
+ if (EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL,
+ ameth) <= 0)
+ pkey_id = 0;
+ }
+ ENGINE_finish(tmpeng);
+ return pkey_id;
+}
+
+#endif
+
+/* masks of disabled algorithms */
+static uint32_t disabled_enc_mask;
+static uint32_t disabled_mac_mask;
+static uint32_t disabled_mkey_mask;
+static uint32_t disabled_auth_mask;
+
+void ssl_load_ciphers(void)
+{
+ size_t i;
+ const ssl_cipher_table *t;
+
+ disabled_enc_mask = 0;
+ ssl_sort_cipher_list();
+ for (i = 0, t = ssl_cipher_table_cipher; i < SSL_ENC_NUM_IDX; i++, t++) {
+ if (t->nid == NID_undef) {
+ ssl_cipher_methods[i] = NULL;
+ } else {
+ const EVP_CIPHER *cipher = EVP_get_cipherbynid(t->nid);
+ ssl_cipher_methods[i] = cipher;
+ if (cipher == NULL)
+ disabled_enc_mask |= t->mask;
+ }
+ }
+#ifdef SSL_FORBID_ENULL
+ disabled_enc_mask |= SSL_eNULL;
+#endif
+ disabled_mac_mask = 0;
+ for (i = 0, t = ssl_cipher_table_mac; i < SSL_MD_NUM_IDX; i++, t++) {
+ const EVP_MD *md = EVP_get_digestbynid(t->nid);
+ ssl_digest_methods[i] = md;
+ if (md == NULL) {
+ disabled_mac_mask |= t->mask;
+ } else {
+ ssl_mac_secret_size[i] = EVP_MD_size(md);
+ OPENSSL_assert(ssl_mac_secret_size[i] >= 0);
+ }
+ }
+ /* Make sure we can access MD5 and SHA1 */
+ OPENSSL_assert(ssl_digest_methods[SSL_MD_MD5_IDX] != NULL);
+ OPENSSL_assert(ssl_digest_methods[SSL_MD_SHA1_IDX] != NULL);
+
+ disabled_mkey_mask = 0;
+ disabled_auth_mask = 0;
+
+#ifdef OPENSSL_NO_RSA
+ disabled_mkey_mask |= SSL_kRSA | SSL_kRSAPSK;
+ disabled_auth_mask |= SSL_aRSA;
+#endif
+#ifdef OPENSSL_NO_DSA
+ disabled_auth_mask |= SSL_aDSS;
+#endif
+#ifdef OPENSSL_NO_DH
+ disabled_mkey_mask |= SSL_kDHE | SSL_kDHEPSK;
+#endif
+#ifdef OPENSSL_NO_EC
+ disabled_mkey_mask |= SSL_kECDHEPSK;
+ disabled_auth_mask |= SSL_aECDSA;
+#endif
+#ifdef OPENSSL_NO_PSK
+ disabled_mkey_mask |= SSL_PSK;
+ disabled_auth_mask |= SSL_aPSK;
+#endif
+#ifdef OPENSSL_NO_SRP
+ disabled_mkey_mask |= SSL_kSRP;
+#endif
+
+ /*
+ * Check for presence of GOST 34.10 algorithms, and if they are not
+ * present, disable appropriate auth and key exchange
+ */
+ ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX] = get_optional_pkey_id("gost-mac");
+ if (ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX]) {
+ ssl_mac_secret_size[SSL_MD_GOST89MAC_IDX] = 32;
+ } else {
+ disabled_mac_mask |= SSL_GOST89MAC;
+ }
+
+ ssl_mac_pkey_id[SSL_MD_GOST89MAC12_IDX] =
+ get_optional_pkey_id("gost-mac-12");
+ if (ssl_mac_pkey_id[SSL_MD_GOST89MAC12_IDX]) {
+ ssl_mac_secret_size[SSL_MD_GOST89MAC12_IDX] = 32;
+ } else {
+ disabled_mac_mask |= SSL_GOST89MAC12;
+ }
+
+ if (!get_optional_pkey_id("gost2001"))
+ disabled_auth_mask |= SSL_aGOST01 | SSL_aGOST12;
+ if (!get_optional_pkey_id("gost2012_256"))
+ disabled_auth_mask |= SSL_aGOST12;
+ if (!get_optional_pkey_id("gost2012_512"))
+ disabled_auth_mask |= SSL_aGOST12;
+ /*
+ * Disable GOST key exchange if no GOST signature algs are available *
+ */
+ if ((disabled_auth_mask & (SSL_aGOST01 | SSL_aGOST12)) ==
+ (SSL_aGOST01 | SSL_aGOST12))
+ disabled_mkey_mask |= SSL_kGOST;
+}
+
+#ifndef OPENSSL_NO_COMP
+
+static int sk_comp_cmp(const SSL_COMP *const *a, const SSL_COMP *const *b)
+{
+ return ((*a)->id - (*b)->id);
+}
+
+DEFINE_RUN_ONCE_STATIC(do_load_builtin_compressions)
+{
+ SSL_COMP *comp = NULL;
+ COMP_METHOD *method = COMP_zlib();
+
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
+ ssl_comp_methods = sk_SSL_COMP_new(sk_comp_cmp);
+
+ if (COMP_get_type(method) != NID_undef && ssl_comp_methods != NULL) {
+ comp = OPENSSL_malloc(sizeof(*comp));
+ if (comp != NULL) {
+ comp->method = method;
+ comp->id = SSL_COMP_ZLIB_IDX;
+ comp->name = COMP_get_name(method);
+ sk_SSL_COMP_push(ssl_comp_methods, comp);
+ sk_SSL_COMP_sort(ssl_comp_methods);
+ }
+ }
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
+ return 1;
+}
+
+static int load_builtin_compressions(void)
+{
+ return RUN_ONCE(&ssl_load_builtin_comp_once, do_load_builtin_compressions);
+}
+#endif
+
+int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
+ const EVP_MD **md, int *mac_pkey_type,
+ int *mac_secret_size, SSL_COMP **comp, int use_etm)
+{
+ int i;
+ const SSL_CIPHER *c;
+
+ c = s->cipher;
+ if (c == NULL)
+ return (0);
+ if (comp != NULL) {
+ SSL_COMP ctmp;
+#ifndef OPENSSL_NO_COMP
+ if (!load_builtin_compressions()) {
+ /*
+ * Currently don't care, since a failure only means that
+ * ssl_comp_methods is NULL, which is perfectly OK
+ */
+ }
+#endif
+ *comp = NULL;
+ ctmp.id = s->compress_meth;
+ if (ssl_comp_methods != NULL) {
+ i = sk_SSL_COMP_find(ssl_comp_methods, &ctmp);
+ if (i >= 0)
+ *comp = sk_SSL_COMP_value(ssl_comp_methods, i);
+ else
+ *comp = NULL;
+ }
+ /* If were only interested in comp then return success */
+ if ((enc == NULL) && (md == NULL))
+ return 1;
+ }
+
+ if ((enc == NULL) || (md == NULL))
+ return 0;
+
+ i = ssl_cipher_info_lookup(ssl_cipher_table_cipher, c->algorithm_enc);
+
+ if (i == -1)
+ *enc = NULL;
+ else {
+ if (i == SSL_ENC_NULL_IDX)
+ *enc = EVP_enc_null();
+ else
+ *enc = ssl_cipher_methods[i];
+ }
+
+ i = ssl_cipher_info_lookup(ssl_cipher_table_mac, c->algorithm_mac);
+ if (i == -1) {
+ *md = NULL;
+ if (mac_pkey_type != NULL)
+ *mac_pkey_type = NID_undef;
+ if (mac_secret_size != NULL)
+ *mac_secret_size = 0;
+ if (c->algorithm_mac == SSL_AEAD)
+ mac_pkey_type = NULL;
+ } else {
+ *md = ssl_digest_methods[i];
+ if (mac_pkey_type != NULL)
+ *mac_pkey_type = ssl_mac_pkey_id[i];
+ if (mac_secret_size != NULL)
+ *mac_secret_size = ssl_mac_secret_size[i];
+ }
+
+ if ((*enc != NULL) &&
+ (*md != NULL || (EVP_CIPHER_flags(*enc) & EVP_CIPH_FLAG_AEAD_CIPHER))
+ && (!mac_pkey_type || *mac_pkey_type != NID_undef)) {
+ const EVP_CIPHER *evp;
+
+ if (use_etm)
+ return 1;
+
+ if (s->ssl_version >> 8 != TLS1_VERSION_MAJOR ||
+ s->ssl_version < TLS1_VERSION)
+ return 1;
+
+ if (FIPS_mode())
+ return 1;
+
+ if (c->algorithm_enc == SSL_RC4 &&
+ c->algorithm_mac == SSL_MD5 &&
+ (evp = EVP_get_cipherbyname("RC4-HMAC-MD5")))
+ *enc = evp, *md = NULL;
+ else if (c->algorithm_enc == SSL_AES128 &&
+ c->algorithm_mac == SSL_SHA1 &&
+ (evp = EVP_get_cipherbyname("AES-128-CBC-HMAC-SHA1")))
+ *enc = evp, *md = NULL;
+ else if (c->algorithm_enc == SSL_AES256 &&
+ c->algorithm_mac == SSL_SHA1 &&
+ (evp = EVP_get_cipherbyname("AES-256-CBC-HMAC-SHA1")))
+ *enc = evp, *md = NULL;
+ else if (c->algorithm_enc == SSL_AES128 &&
+ c->algorithm_mac == SSL_SHA256 &&
+ (evp = EVP_get_cipherbyname("AES-128-CBC-HMAC-SHA256")))
+ *enc = evp, *md = NULL;
+ else if (c->algorithm_enc == SSL_AES256 &&
+ c->algorithm_mac == SSL_SHA256 &&
+ (evp = EVP_get_cipherbyname("AES-256-CBC-HMAC-SHA256")))
+ *enc = evp, *md = NULL;
+ return (1);
+ } else
+ return (0);
+}
+
+const EVP_MD *ssl_md(int idx)
+{
+ idx &= SSL_HANDSHAKE_MAC_MASK;
+ if (idx < 0 || idx >= SSL_MD_NUM_IDX)
+ return NULL;
+ return ssl_digest_methods[idx];
+}
+
+const EVP_MD *ssl_handshake_md(SSL *s)
+{
+ return ssl_md(ssl_get_algorithm2(s));
+}
+
+const EVP_MD *ssl_prf_md(SSL *s)
+{
+ return ssl_md(ssl_get_algorithm2(s) >> TLS1_PRF_DGST_SHIFT);
+}
+
+#define ITEM_SEP(a) \
+ (((a) == ':') || ((a) == ' ') || ((a) == ';') || ((a) == ','))
+
+static void ll_append_tail(CIPHER_ORDER **head, CIPHER_ORDER *curr,
+ CIPHER_ORDER **tail)
+{
+ if (curr == *tail)
+ return;
+ if (curr == *head)
+ *head = curr->next;
+ if (curr->prev != NULL)
+ curr->prev->next = curr->next;
+ if (curr->next != NULL)
+ curr->next->prev = curr->prev;
+ (*tail)->next = curr;
+ curr->prev = *tail;
+ curr->next = NULL;
+ *tail = curr;
+}
+
+static void ll_append_head(CIPHER_ORDER **head, CIPHER_ORDER *curr,
+ CIPHER_ORDER **tail)
+{
+ if (curr == *head)
+ return;
+ if (curr == *tail)
+ *tail = curr->prev;
+ if (curr->next != NULL)
+ curr->next->prev = curr->prev;
+ if (curr->prev != NULL)
+ curr->prev->next = curr->next;
+ (*head)->prev = curr;
+ curr->next = *head;
+ curr->prev = NULL;
+ *head = curr;
+}
+
+static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method,
+ int num_of_ciphers,
+ uint32_t disabled_mkey,
+ uint32_t disabled_auth,
+ uint32_t disabled_enc,
+ uint32_t disabled_mac,
+ CIPHER_ORDER *co_list,
+ CIPHER_ORDER **head_p,
+ CIPHER_ORDER **tail_p)
+{
+ int i, co_list_num;
+ const SSL_CIPHER *c;
+
+ /*
+ * We have num_of_ciphers descriptions compiled in, depending on the
+ * method selected (SSLv3, TLSv1 etc).
+ * These will later be sorted in a linked list with at most num
+ * entries.
+ */
+
+ /* Get the initial list of ciphers */
+ co_list_num = 0; /* actual count of ciphers */
+ for (i = 0; i < num_of_ciphers; i++) {
+ c = ssl_method->get_cipher(i);
+ /* drop those that use any of that is not available */
+ if (c == NULL || !c->valid)
+ continue;
+ if (FIPS_mode() && (c->algo_strength & SSL_FIPS))
+ continue;
+ if ((c->algorithm_mkey & disabled_mkey) ||
+ (c->algorithm_auth & disabled_auth) ||
+ (c->algorithm_enc & disabled_enc) ||
+ (c->algorithm_mac & disabled_mac))
+ continue;
+ if (((ssl_method->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS) == 0) &&
+ c->min_tls == 0)
+ continue;
+ if (((ssl_method->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS) != 0) &&
+ c->min_dtls == 0)
+ continue;
+
+ co_list[co_list_num].cipher = c;
+ co_list[co_list_num].next = NULL;
+ co_list[co_list_num].prev = NULL;
+ co_list[co_list_num].active = 0;
+ co_list_num++;
+ /*
+ * if (!sk_push(ca_list,(char *)c)) goto err;
+ */
+ }
+
+ /*
+ * Prepare linked list from list entries
+ */
+ if (co_list_num > 0) {
+ co_list[0].prev = NULL;
+
+ if (co_list_num > 1) {
+ co_list[0].next = &co_list[1];
+
+ for (i = 1; i < co_list_num - 1; i++) {
+ co_list[i].prev = &co_list[i - 1];
+ co_list[i].next = &co_list[i + 1];
+ }
+
+ co_list[co_list_num - 1].prev = &co_list[co_list_num - 2];
+ }
+
+ co_list[co_list_num - 1].next = NULL;
+
+ *head_p = &co_list[0];
+ *tail_p = &co_list[co_list_num - 1];
+ }
+}
+
+static void ssl_cipher_collect_aliases(const SSL_CIPHER **ca_list,
+ int num_of_group_aliases,
+ uint32_t disabled_mkey,
+ uint32_t disabled_auth,
+ uint32_t disabled_enc,
+ uint32_t disabled_mac,
+ CIPHER_ORDER *head)
+{
+ CIPHER_ORDER *ciph_curr;
+ const SSL_CIPHER **ca_curr;
+ int i;
+ uint32_t mask_mkey = ~disabled_mkey;
+ uint32_t mask_auth = ~disabled_auth;
+ uint32_t mask_enc = ~disabled_enc;
+ uint32_t mask_mac = ~disabled_mac;
+
+ /*
+ * First, add the real ciphers as already collected
+ */
+ ciph_curr = head;
+ ca_curr = ca_list;
+ while (ciph_curr != NULL) {
+ *ca_curr = ciph_curr->cipher;
+ ca_curr++;
+ ciph_curr = ciph_curr->next;
+ }
+
+ /*
+ * Now we add the available ones from the cipher_aliases[] table.
+ * They represent either one or more algorithms, some of which
+ * in any affected category must be supported (set in enabled_mask),
+ * or represent a cipher strength value (will be added in any case because algorithms=0).
+ */
+ for (i = 0; i < num_of_group_aliases; i++) {
+ uint32_t algorithm_mkey = cipher_aliases[i].algorithm_mkey;
+ uint32_t algorithm_auth = cipher_aliases[i].algorithm_auth;
+ uint32_t algorithm_enc = cipher_aliases[i].algorithm_enc;
+ uint32_t algorithm_mac = cipher_aliases[i].algorithm_mac;
+
+ if (algorithm_mkey)
+ if ((algorithm_mkey & mask_mkey) == 0)
+ continue;
+
+ if (algorithm_auth)
+ if ((algorithm_auth & mask_auth) == 0)
+ continue;
+
+ if (algorithm_enc)
+ if ((algorithm_enc & mask_enc) == 0)
+ continue;
+
+ if (algorithm_mac)
+ if ((algorithm_mac & mask_mac) == 0)
+ continue;
+
+ *ca_curr = (SSL_CIPHER *)(cipher_aliases + i);
+ ca_curr++;
+ }
+
+ *ca_curr = NULL; /* end of list */
+}
+
+static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
+ uint32_t alg_auth, uint32_t alg_enc,
+ uint32_t alg_mac, int min_tls,
+ uint32_t algo_strength, int rule,
+ int32_t strength_bits, CIPHER_ORDER **head_p,
+ CIPHER_ORDER **tail_p)
+{
+ CIPHER_ORDER *head, *tail, *curr, *next, *last;
+ const SSL_CIPHER *cp;
+ int reverse = 0;
+
+#ifdef CIPHER_DEBUG
+ fprintf(stderr,
+ "Applying rule %d with %08x/%08x/%08x/%08x/%08x %08x (%d)\n",
+ rule, alg_mkey, alg_auth, alg_enc, alg_mac, min_tls,
+ algo_strength, strength_bits);
+#endif
+
+ if (rule == CIPHER_DEL || rule == CIPHER_BUMP)
+ reverse = 1; /* needed to maintain sorting between currently
+ * deleted ciphers */
+
+ head = *head_p;
+ tail = *tail_p;
+
+ if (reverse) {
+ next = tail;
+ last = head;
+ } else {
+ next = head;
+ last = tail;
+ }
+
+ curr = NULL;
+ for (;;) {
+ if (curr == last)
+ break;
+
+ curr = next;
+
+ if (curr == NULL)
+ break;
+
+ next = reverse ? curr->prev : curr->next;
+
+ cp = curr->cipher;
+
+ /*
+ * Selection criteria is either the value of strength_bits
+ * or the algorithms used.
+ */
+ if (strength_bits >= 0) {
+ if (strength_bits != cp->strength_bits)
+ continue;
+ } else {
+#ifdef CIPHER_DEBUG
+ fprintf(stderr,
+ "\nName: %s:\nAlgo = %08x/%08x/%08x/%08x/%08x Algo_strength = %08x\n",
+ cp->name, cp->algorithm_mkey, cp->algorithm_auth,
+ cp->algorithm_enc, cp->algorithm_mac, cp->min_tls,
+ cp->algo_strength);
+#endif
+ if (alg_mkey && !(alg_mkey & cp->algorithm_mkey))
+ continue;
+ if (alg_auth && !(alg_auth & cp->algorithm_auth))
+ continue;
+ if (alg_enc && !(alg_enc & cp->algorithm_enc))
+ continue;
+ if (alg_mac && !(alg_mac & cp->algorithm_mac))
+ continue;
+ if (min_tls && (min_tls != cp->min_tls))
+ continue;
+ if ((algo_strength & SSL_STRONG_MASK)
+ && !(algo_strength & SSL_STRONG_MASK & cp->algo_strength))
+ continue;
+ if ((algo_strength & SSL_DEFAULT_MASK)
+ && !(algo_strength & SSL_DEFAULT_MASK & cp->algo_strength))
+ continue;
+ }
+
+#ifdef CIPHER_DEBUG
+ fprintf(stderr, "Action = %d\n", rule);
+#endif
+
+ /* add the cipher if it has not been added yet. */
+ if (rule == CIPHER_ADD) {
+ /* reverse == 0 */
+ if (!curr->active) {
+ ll_append_tail(&head, curr, &tail);
+ curr->active = 1;
+ }
+ }
+ /* Move the added cipher to this location */
+ else if (rule == CIPHER_ORD) {
+ /* reverse == 0 */
+ if (curr->active) {
+ ll_append_tail(&head, curr, &tail);
+ }
+ } else if (rule == CIPHER_DEL) {
+ /* reverse == 1 */
+ if (curr->active) {
+ /*
+ * most recently deleted ciphersuites get best positions for
+ * any future CIPHER_ADD (note that the CIPHER_DEL loop works
+ * in reverse to maintain the order)
+ */
+ ll_append_head(&head, curr, &tail);
+ curr->active = 0;
+ }
+ } else if (rule == CIPHER_BUMP) {
+ if (curr->active)
+ ll_append_head(&head, curr, &tail);
+ } else if (rule == CIPHER_KILL) {
+ /* reverse == 0 */
+ if (head == curr)
+ head = curr->next;
+ else
+ curr->prev->next = curr->next;
+ if (tail == curr)
+ tail = curr->prev;
+ curr->active = 0;
+ if (curr->next != NULL)
+ curr->next->prev = curr->prev;
+ if (curr->prev != NULL)
+ curr->prev->next = curr->next;
+ curr->next = NULL;
+ curr->prev = NULL;
+ }
+ }
+
+ *head_p = head;
+ *tail_p = tail;
+}
+
+static int ssl_cipher_strength_sort(CIPHER_ORDER **head_p,
+ CIPHER_ORDER **tail_p)
+{
+ int32_t max_strength_bits;
+ int i, *number_uses;
+ CIPHER_ORDER *curr;
+
+ /*
+ * This routine sorts the ciphers with descending strength. The sorting
+ * must keep the pre-sorted sequence, so we apply the normal sorting
+ * routine as '+' movement to the end of the list.
+ */
+ max_strength_bits = 0;
+ curr = *head_p;
+ while (curr != NULL) {
+ if (curr->active && (curr->cipher->strength_bits > max_strength_bits))
+ max_strength_bits = curr->cipher->strength_bits;
+ curr = curr->next;
+ }
+
+ number_uses = OPENSSL_zalloc(sizeof(int) * (max_strength_bits + 1));
+ if (number_uses == NULL) {
+ SSLerr(SSL_F_SSL_CIPHER_STRENGTH_SORT, ERR_R_MALLOC_FAILURE);
+ return (0);
+ }
+
+ /*
+ * Now find the strength_bits values actually used
+ */
+ curr = *head_p;
+ while (curr != NULL) {
+ if (curr->active)
+ number_uses[curr->cipher->strength_bits]++;
+ curr = curr->next;
+ }
+ /*
+ * Go through the list of used strength_bits values in descending
+ * order.
+ */
+ for (i = max_strength_bits; i >= 0; i--)
+ if (number_uses[i] > 0)
+ ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ORD, i, head_p,
+ tail_p);
+
+ OPENSSL_free(number_uses);
+ return (1);
+}
+
+static int ssl_cipher_process_rulestr(const char *rule_str,
+ CIPHER_ORDER **head_p,
+ CIPHER_ORDER **tail_p,
+ const SSL_CIPHER **ca_list, CERT *c)
+{
+ uint32_t alg_mkey, alg_auth, alg_enc, alg_mac, algo_strength;
+ int min_tls;
+ const char *l, *buf;
+ int j, multi, found, rule, retval, ok, buflen;
+ uint32_t cipher_id = 0;
+ char ch;
+
+ retval = 1;
+ l = rule_str;
+ for (;;) {
+ ch = *l;
+
+ if (ch == '\0')
+ break; /* done */
+ if (ch == '-') {
+ rule = CIPHER_DEL;
+ l++;
+ } else if (ch == '+') {
+ rule = CIPHER_ORD;
+ l++;
+ } else if (ch == '!') {
+ rule = CIPHER_KILL;
+ l++;
+ } else if (ch == '@') {
+ rule = CIPHER_SPECIAL;
+ l++;
+ } else {
+ rule = CIPHER_ADD;
+ }
+
+ if (ITEM_SEP(ch)) {
+ l++;
+ continue;
+ }
+
+ alg_mkey = 0;
+ alg_auth = 0;
+ alg_enc = 0;
+ alg_mac = 0;
+ min_tls = 0;
+ algo_strength = 0;
+
+ for (;;) {
+ ch = *l;
+ buf = l;
+ buflen = 0;
+#ifndef CHARSET_EBCDIC
+ while (((ch >= 'A') && (ch <= 'Z')) ||
+ ((ch >= '0') && (ch <= '9')) ||
+ ((ch >= 'a') && (ch <= 'z')) ||
+ (ch == '-') || (ch == '.') || (ch == '='))
+#else
+ while (isalnum((unsigned char)ch) || (ch == '-') || (ch == '.')
+ || (ch == '='))
+#endif
+ {
+ ch = *(++l);
+ buflen++;
+ }
+
+ if (buflen == 0) {
+ /*
+ * We hit something we cannot deal with,
+ * it is no command or separator nor
+ * alphanumeric, so we call this an error.
+ */
+ SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_INVALID_COMMAND);
+ retval = found = 0;
+ l++;
+ break;
+ }
+
+ if (rule == CIPHER_SPECIAL) {
+ found = 0; /* unused -- avoid compiler warning */
+ break; /* special treatment */
+ }
+
+ /* check for multi-part specification */
+ if (ch == '+') {
+ multi = 1;
+ l++;
+ } else
+ multi = 0;
+
+ /*
+ * Now search for the cipher alias in the ca_list. Be careful
+ * with the strncmp, because the "buflen" limitation
+ * will make the rule "ADH:SOME" and the cipher
+ * "ADH-MY-CIPHER" look like a match for buflen=3.
+ * So additionally check whether the cipher name found
+ * has the correct length. We can save a strlen() call:
+ * just checking for the '\0' at the right place is
+ * sufficient, we have to strncmp() anyway. (We cannot
+ * use strcmp(), because buf is not '\0' terminated.)
+ */
+ j = found = 0;
+ cipher_id = 0;
+ while (ca_list[j]) {
+ if (strncmp(buf, ca_list[j]->name, buflen) == 0
+ && (ca_list[j]->name[buflen] == '\0')) {
+ found = 1;
+ break;
+ } else
+ j++;
+ }
+
+ if (!found)
+ break; /* ignore this entry */
+
+ if (ca_list[j]->algorithm_mkey) {
+ if (alg_mkey) {
+ alg_mkey &= ca_list[j]->algorithm_mkey;
+ if (!alg_mkey) {
+ found = 0;
+ break;
+ }
+ } else
+ alg_mkey = ca_list[j]->algorithm_mkey;
+ }
+
+ if (ca_list[j]->algorithm_auth) {
+ if (alg_auth) {
+ alg_auth &= ca_list[j]->algorithm_auth;
+ if (!alg_auth) {
+ found = 0;
+ break;
+ }
+ } else
+ alg_auth = ca_list[j]->algorithm_auth;
+ }
+
+ if (ca_list[j]->algorithm_enc) {
+ if (alg_enc) {
+ alg_enc &= ca_list[j]->algorithm_enc;
+ if (!alg_enc) {
+ found = 0;
+ break;
+ }
+ } else
+ alg_enc = ca_list[j]->algorithm_enc;
+ }
+
+ if (ca_list[j]->algorithm_mac) {
+ if (alg_mac) {
+ alg_mac &= ca_list[j]->algorithm_mac;
+ if (!alg_mac) {
+ found = 0;
+ break;
+ }
+ } else
+ alg_mac = ca_list[j]->algorithm_mac;
+ }
+
+ if (ca_list[j]->algo_strength & SSL_STRONG_MASK) {
+ if (algo_strength & SSL_STRONG_MASK) {
+ algo_strength &=
+ (ca_list[j]->algo_strength & SSL_STRONG_MASK) |
+ ~SSL_STRONG_MASK;
+ if (!(algo_strength & SSL_STRONG_MASK)) {
+ found = 0;
+ break;
+ }
+ } else
+ algo_strength = ca_list[j]->algo_strength & SSL_STRONG_MASK;
+ }
+
+ if (ca_list[j]->algo_strength & SSL_DEFAULT_MASK) {
+ if (algo_strength & SSL_DEFAULT_MASK) {
+ algo_strength &=
+ (ca_list[j]->algo_strength & SSL_DEFAULT_MASK) |
+ ~SSL_DEFAULT_MASK;
+ if (!(algo_strength & SSL_DEFAULT_MASK)) {
+ found = 0;
+ break;
+ }
+ } else
+ algo_strength |=
+ ca_list[j]->algo_strength & SSL_DEFAULT_MASK;
+ }
+
+ if (ca_list[j]->valid) {
+ /*
+ * explicit ciphersuite found; its protocol version does not
+ * become part of the search pattern!
+ */
+
+ cipher_id = ca_list[j]->id;
+ } else {
+ /*
+ * not an explicit ciphersuite; only in this case, the
+ * protocol version is considered part of the search pattern
+ */
+
+ if (ca_list[j]->min_tls) {
+ if (min_tls != 0 && min_tls != ca_list[j]->min_tls) {
+ found = 0;
+ break;
+ } else {
+ min_tls = ca_list[j]->min_tls;
+ }
+ }
+ }
+
+ if (!multi)
+ break;
+ }
+
+ /*
+ * Ok, we have the rule, now apply it
+ */
+ if (rule == CIPHER_SPECIAL) { /* special command */
+ ok = 0;
+ if ((buflen == 8) && strncmp(buf, "STRENGTH", 8) == 0)
+ ok = ssl_cipher_strength_sort(head_p, tail_p);
+ else if (buflen == 10 && strncmp(buf, "SECLEVEL=", 9) == 0) {
+ int level = buf[9] - '0';
+ if (level < 0 || level > 5) {
+ SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR,
+ SSL_R_INVALID_COMMAND);
+ } else {
+ c->sec_level = level;
+ ok = 1;
+ }
+ } else
+ SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_INVALID_COMMAND);
+ if (ok == 0)
+ retval = 0;
+ /*
+ * We do not support any "multi" options
+ * together with "@", so throw away the
+ * rest of the command, if any left, until
+ * end or ':' is found.
+ */
+ while ((*l != '\0') && !ITEM_SEP(*l))
+ l++;
+ } else if (found) {
+ ssl_cipher_apply_rule(cipher_id,
+ alg_mkey, alg_auth, alg_enc, alg_mac,
+ min_tls, algo_strength, rule, -1, head_p,
+ tail_p);
+ } else {
+ while ((*l != '\0') && !ITEM_SEP(*l))
+ l++;
+ }
+ if (*l == '\0')
+ break; /* done */
+ }
+
+ return (retval);
+}
+
+#ifndef OPENSSL_NO_EC
+static int check_suiteb_cipher_list(const SSL_METHOD *meth, CERT *c,
+ const char **prule_str)
+{
+ unsigned int suiteb_flags = 0, suiteb_comb2 = 0;
+ if (strncmp(*prule_str, "SUITEB128ONLY", 13) == 0) {
+ suiteb_flags = SSL_CERT_FLAG_SUITEB_128_LOS_ONLY;
+ } else if (strncmp(*prule_str, "SUITEB128C2", 11) == 0) {
+ suiteb_comb2 = 1;
+ suiteb_flags = SSL_CERT_FLAG_SUITEB_128_LOS;
+ } else if (strncmp(*prule_str, "SUITEB128", 9) == 0) {
+ suiteb_flags = SSL_CERT_FLAG_SUITEB_128_LOS;
+ } else if (strncmp(*prule_str, "SUITEB192", 9) == 0) {
+ suiteb_flags = SSL_CERT_FLAG_SUITEB_192_LOS;
+ }
+
+ if (suiteb_flags) {
+ c->cert_flags &= ~SSL_CERT_FLAG_SUITEB_128_LOS;
+ c->cert_flags |= suiteb_flags;
+ } else
+ suiteb_flags = c->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS;
+
+ if (!suiteb_flags)
+ return 1;
+ /* Check version: if TLS 1.2 ciphers allowed we can use Suite B */
+
+ if (!(meth->ssl3_enc->enc_flags & SSL_ENC_FLAG_TLS1_2_CIPHERS)) {
+ SSLerr(SSL_F_CHECK_SUITEB_CIPHER_LIST,
+ SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE);
+ return 0;
+ }
+# ifndef OPENSSL_NO_EC
+ switch (suiteb_flags) {
+ case SSL_CERT_FLAG_SUITEB_128_LOS:
+ if (suiteb_comb2)
+ *prule_str = "ECDHE-ECDSA-AES256-GCM-SHA384";
+ else
+ *prule_str =
+ "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384";
+ break;
+ case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY:
+ *prule_str = "ECDHE-ECDSA-AES128-GCM-SHA256";
+ break;
+ case SSL_CERT_FLAG_SUITEB_192_LOS:
+ *prule_str = "ECDHE-ECDSA-AES256-GCM-SHA384";
+ break;
+ }
+ return 1;
+# else
+ SSLerr(SSL_F_CHECK_SUITEB_CIPHER_LIST, SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE);
+ return 0;
+# endif
+}
+#endif
+
+STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, STACK_OF(SSL_CIPHER)
+ **cipher_list, STACK_OF(SSL_CIPHER)
+ **cipher_list_by_id,
+ const char *rule_str, CERT *c)
+{
+ int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases;
+ uint32_t disabled_mkey, disabled_auth, disabled_enc, disabled_mac;
+ STACK_OF(SSL_CIPHER) *cipherstack, *tmp_cipher_list;
+ const char *rule_p;
+ CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr;
+ const SSL_CIPHER **ca_list = NULL;
+
+ /*
+ * Return with error if nothing to do.
+ */
+ if (rule_str == NULL || cipher_list == NULL || cipher_list_by_id == NULL)
+ return NULL;
+#ifndef OPENSSL_NO_EC
+ if (!check_suiteb_cipher_list(ssl_method, c, &rule_str))
+ return NULL;
+#endif
+
+ /*
+ * To reduce the work to do we only want to process the compiled
+ * in algorithms, so we first get the mask of disabled ciphers.
+ */
+
+ disabled_mkey = disabled_mkey_mask;
+ disabled_auth = disabled_auth_mask;
+ disabled_enc = disabled_enc_mask;
+ disabled_mac = disabled_mac_mask;
+
+ /*
+ * Now we have to collect the available ciphers from the compiled
+ * in ciphers. We cannot get more than the number compiled in, so
+ * it is used for allocation.
+ */
+ num_of_ciphers = ssl_method->num_ciphers();
+
+ co_list = OPENSSL_malloc(sizeof(*co_list) * num_of_ciphers);
+ if (co_list == NULL) {
+ SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
+ return (NULL); /* Failure */
+ }
+
+ ssl_cipher_collect_ciphers(ssl_method, num_of_ciphers,
+ disabled_mkey, disabled_auth, disabled_enc,
+ disabled_mac, co_list, &head, &tail);
+
+ /* Now arrange all ciphers by preference. */
+
+ /*
+ * Everything else being equal, prefer ephemeral ECDH over other key
+ * exchange mechanisms.
+ * For consistency, prefer ECDSA over RSA (though this only matters if the
+ * server has both certificates, and is using the DEFAULT, or a client
+ * preference).
+ */
+ ssl_cipher_apply_rule(0, SSL_kECDHE, SSL_aECDSA, 0, 0, 0, 0, CIPHER_ADD,
+ -1, &head, &tail);
+ ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head,
+ &tail);
+ ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head,
+ &tail);
+
+ /* Within each strength group, we prefer GCM over CHACHA... */
+ ssl_cipher_apply_rule(0, 0, 0, SSL_AESGCM, 0, 0, 0, CIPHER_ADD, -1,
+ &head, &tail);
+ ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20, 0, 0, 0, CIPHER_ADD, -1,
+ &head, &tail);
+
+ /*
+ * ...and generally, our preferred cipher is AES.
+ * Note that AEADs will be bumped to take preference after sorting by
+ * strength.
+ */
+ ssl_cipher_apply_rule(0, 0, 0, SSL_AES ^ SSL_AESGCM, 0, 0, 0, CIPHER_ADD,
+ -1, &head, &tail);
+
+ /* Temporarily enable everything else for sorting */
+ ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head, &tail);
+
+ /* Low priority for MD5 */
+ ssl_cipher_apply_rule(0, 0, 0, 0, SSL_MD5, 0, 0, CIPHER_ORD, -1, &head,
+ &tail);
+
+ /*
+ * Move anonymous ciphers to the end. Usually, these will remain
+ * disabled. (For applications that allow them, they aren't too bad, but
+ * we prefer authenticated ciphers.)
+ */
+ ssl_cipher_apply_rule(0, 0, SSL_aNULL, 0, 0, 0, 0, CIPHER_ORD, -1, &head,
+ &tail);
+
+ ssl_cipher_apply_rule(0, SSL_kRSA, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head,
+ &tail);
+ ssl_cipher_apply_rule(0, SSL_kPSK, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head,
+ &tail);
+
+ /* RC4 is sort-of broken -- move the the end */
+ ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, 0, 0, 0, CIPHER_ORD, -1, &head,
+ &tail);
+
+ /*
+ * Now sort by symmetric encryption strength. The above ordering remains
+ * in force within each class
+ */
+ if (!ssl_cipher_strength_sort(&head, &tail)) {
+ OPENSSL_free(co_list);
+ return NULL;
+ }
+
+ /*
+ * Partially overrule strength sort to prefer TLS 1.2 ciphers/PRFs.
+ * TODO(openssl-team): is there an easier way to accomplish all this?
+ */
+ ssl_cipher_apply_rule(0, 0, 0, 0, 0, TLS1_2_VERSION, 0, CIPHER_BUMP, -1,
+ &head, &tail);
+
+ /*
+ * Irrespective of strength, enforce the following order:
+ * (EC)DHE + AEAD > (EC)DHE > rest of AEAD > rest.
+ * Within each group, ciphers remain sorted by strength and previous
+ * preference, i.e.,
+ * 1) ECDHE > DHE
+ * 2) GCM > CHACHA
+ * 3) AES > rest
+ * 4) TLS 1.2 > legacy
+ *
+ * Because we now bump ciphers to the top of the list, we proceed in
+ * reverse order of preference.
+ */
+ ssl_cipher_apply_rule(0, 0, 0, 0, SSL_AEAD, 0, 0, CIPHER_BUMP, -1,
+ &head, &tail);
+ ssl_cipher_apply_rule(0, SSL_kDHE | SSL_kECDHE, 0, 0, 0, 0, 0,
+ CIPHER_BUMP, -1, &head, &tail);
+ ssl_cipher_apply_rule(0, SSL_kDHE | SSL_kECDHE, 0, 0, SSL_AEAD, 0, 0,
+ CIPHER_BUMP, -1, &head, &tail);
+
+ /* Now disable everything (maintaining the ordering!) */
+ ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, &tail);
+
+ /*
+ * We also need cipher aliases for selecting based on the rule_str.
+ * There might be two types of entries in the rule_str: 1) names
+ * of ciphers themselves 2) aliases for groups of ciphers.
+ * For 1) we need the available ciphers and for 2) the cipher
+ * groups of cipher_aliases added together in one list (otherwise
+ * we would be happy with just the cipher_aliases table).
+ */
+ num_of_group_aliases = OSSL_NELEM(cipher_aliases);
+ num_of_alias_max = num_of_ciphers + num_of_group_aliases + 1;
+ ca_list = OPENSSL_malloc(sizeof(*ca_list) * num_of_alias_max);
+ if (ca_list == NULL) {
+ OPENSSL_free(co_list);
+ SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
+ return (NULL); /* Failure */
+ }
+ ssl_cipher_collect_aliases(ca_list, num_of_group_aliases,
+ disabled_mkey, disabled_auth, disabled_enc,
+ disabled_mac, head);
+
+ /*
+ * If the rule_string begins with DEFAULT, apply the default rule
+ * before using the (possibly available) additional rules.
+ */
+ ok = 1;
+ rule_p = rule_str;
+ if (strncmp(rule_str, "DEFAULT", 7) == 0) {
+ ok = ssl_cipher_process_rulestr(SSL_DEFAULT_CIPHER_LIST,
+ &head, &tail, ca_list, c);
+ rule_p += 7;
+ if (*rule_p == ':')
+ rule_p++;
+ }
+
+ if (ok && (strlen(rule_p) > 0))
+ ok = ssl_cipher_process_rulestr(rule_p, &head, &tail, ca_list, c);
+
+ OPENSSL_free(ca_list); /* Not needed anymore */
+
+ if (!ok) { /* Rule processing failure */
+ OPENSSL_free(co_list);
+ return (NULL);
+ }
+
+ /*
+ * Allocate new "cipherstack" for the result, return with error
+ * if we cannot get one.
+ */
+ if ((cipherstack = sk_SSL_CIPHER_new_null()) == NULL) {
+ OPENSSL_free(co_list);
+ return (NULL);
+ }
+
+ /*
+ * The cipher selection for the list is done. The ciphers are added
+ * to the resulting precedence to the STACK_OF(SSL_CIPHER).
+ */
+ for (curr = head; curr != NULL; curr = curr->next) {
+ if (curr->active
+ && (!FIPS_mode() || curr->cipher->algo_strength & SSL_FIPS)) {
+ if (!sk_SSL_CIPHER_push(cipherstack, curr->cipher)) {
+ OPENSSL_free(co_list);
+ sk_SSL_CIPHER_free(cipherstack);
+ return NULL;
+ }
+#ifdef CIPHER_DEBUG
+ fprintf(stderr, "<%s>\n", curr->cipher->name);
+#endif
+ }
+ }
+ OPENSSL_free(co_list); /* Not needed any longer */
+
+ tmp_cipher_list = sk_SSL_CIPHER_dup(cipherstack);
+ if (tmp_cipher_list == NULL) {
+ sk_SSL_CIPHER_free(cipherstack);
+ return NULL;
+ }
+ sk_SSL_CIPHER_free(*cipher_list);
+ *cipher_list = cipherstack;
+ if (*cipher_list_by_id != NULL)
+ sk_SSL_CIPHER_free(*cipher_list_by_id);
+ *cipher_list_by_id = tmp_cipher_list;
+ (void)sk_SSL_CIPHER_set_cmp_func(*cipher_list_by_id, ssl_cipher_ptr_id_cmp);
+
+ sk_SSL_CIPHER_sort(*cipher_list_by_id);
+ return (cipherstack);
+}
+
+char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
+{
+ const char *ver;
+ const char *kx, *au, *enc, *mac;
+ uint32_t alg_mkey, alg_auth, alg_enc, alg_mac;
+ static const char *format = "%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s\n";
+
+ if (buf == NULL) {
+ len = 128;
+ buf = OPENSSL_malloc(len);
+ if (buf == NULL)
+ return NULL;
+ } else if (len < 128)
+ return NULL;
+
+ alg_mkey = cipher->algorithm_mkey;
+ alg_auth = cipher->algorithm_auth;
+ alg_enc = cipher->algorithm_enc;
+ alg_mac = cipher->algorithm_mac;
+
+ ver = ssl_protocol_to_string(cipher->min_tls);
+
+ switch (alg_mkey) {
+ case SSL_kRSA:
+ kx = "RSA";
+ break;
+ case SSL_kDHE:
+ kx = "DH";
+ break;
+ case SSL_kECDHE:
+ kx = "ECDH";
+ break;
+ case SSL_kPSK:
+ kx = "PSK";
+ break;
+ case SSL_kRSAPSK:
+ kx = "RSAPSK";
+ break;
+ case SSL_kECDHEPSK:
+ kx = "ECDHEPSK";
+ break;
+ case SSL_kDHEPSK:
+ kx = "DHEPSK";
+ break;
+ case SSL_kSRP:
+ kx = "SRP";
+ break;
+ case SSL_kGOST:
+ kx = "GOST";
+ break;
+ default:
+ kx = "unknown";
+ }
+
+ switch (alg_auth) {
+ case SSL_aRSA:
+ au = "RSA";
+ break;
+ case SSL_aDSS:
+ au = "DSS";
+ break;
+ case SSL_aNULL:
+ au = "None";
+ break;
+ case SSL_aECDSA:
+ au = "ECDSA";
+ break;
+ case SSL_aPSK:
+ au = "PSK";
+ break;
+ case SSL_aSRP:
+ au = "SRP";
+ break;
+ case SSL_aGOST01:
+ au = "GOST01";
+ break;
+ /* New GOST ciphersuites have both SSL_aGOST12 and SSL_aGOST01 bits */
+ case (SSL_aGOST12 | SSL_aGOST01):
+ au = "GOST12";
+ break;
+ default:
+ au = "unknown";
+ break;
+ }
+
+ switch (alg_enc) {
+ case SSL_DES:
+ enc = "DES(56)";
+ break;
+ case SSL_3DES:
+ enc = "3DES(168)";
+ break;
+ case SSL_RC4:
+ enc = "RC4(128)";
+ break;
+ case SSL_RC2:
+ enc = "RC2(128)";
+ break;
+ case SSL_IDEA:
+ enc = "IDEA(128)";
+ break;
+ case SSL_eNULL:
+ enc = "None";
+ break;
+ case SSL_AES128:
+ enc = "AES(128)";
+ break;
+ case SSL_AES256:
+ enc = "AES(256)";
+ break;
+ case SSL_AES128GCM:
+ enc = "AESGCM(128)";
+ break;
+ case SSL_AES256GCM:
+ enc = "AESGCM(256)";
+ break;
+ case SSL_AES128CCM:
+ enc = "AESCCM(128)";
+ break;
+ case SSL_AES256CCM:
+ enc = "AESCCM(256)";
+ break;
+ case SSL_AES128CCM8:
+ enc = "AESCCM8(128)";
+ break;
+ case SSL_AES256CCM8:
+ enc = "AESCCM8(256)";
+ break;
+ case SSL_CAMELLIA128:
+ enc = "Camellia(128)";
+ break;
+ case SSL_CAMELLIA256:
+ enc = "Camellia(256)";
+ break;
+ case SSL_SEED:
+ enc = "SEED(128)";
+ break;
+ case SSL_eGOST2814789CNT:
+ case SSL_eGOST2814789CNT12:
+ enc = "GOST89(256)";
+ break;
+ case SSL_CHACHA20POLY1305:
+ enc = "CHACHA20/POLY1305(256)";
+ break;
+ default:
+ enc = "unknown";
+ break;
+ }
+
+ switch (alg_mac) {
+ case SSL_MD5:
+ mac = "MD5";
+ break;
+ case SSL_SHA1:
+ mac = "SHA1";
+ break;
+ case SSL_SHA256:
+ mac = "SHA256";
+ break;
+ case SSL_SHA384:
+ mac = "SHA384";
+ break;
+ case SSL_AEAD:
+ mac = "AEAD";
+ break;
+ case SSL_GOST89MAC:
+ case SSL_GOST89MAC12:
+ mac = "GOST89";
+ break;
+ case SSL_GOST94:
+ mac = "GOST94";
+ break;
+ case SSL_GOST12_256:
+ case SSL_GOST12_512:
+ mac = "GOST2012";
+ break;
+ default:
+ mac = "unknown";
+ break;
+ }
+
+ BIO_snprintf(buf, len, format, cipher->name, ver, kx, au, enc, mac);
+
+ return (buf);
+}
+
+const char *SSL_CIPHER_get_version(const SSL_CIPHER *c)
+{
+ if (c == NULL)
+ return "(NONE)";
+
+ /*
+ * Backwards-compatibility crutch. In almost all contexts we report TLS
+ * 1.0 as "TLSv1", but for ciphers we report "TLSv1.0".
+ */
+ if (c->min_tls == TLS1_VERSION)
+ return "TLSv1.0";
+ return ssl_protocol_to_string(c->min_tls);
+}
+
+/* return the actual cipher being used */
+const char *SSL_CIPHER_get_name(const SSL_CIPHER *c)
+{
+ if (c != NULL)
+ return (c->name);
+ return ("(NONE)");
+}
+
+/* number of bits for symmetric cipher */
+int SSL_CIPHER_get_bits(const SSL_CIPHER *c, int *alg_bits)
+{
+ int ret = 0;
+
+ if (c != NULL) {
+ if (alg_bits != NULL)
+ *alg_bits = (int)c->alg_bits;
+ ret = (int)c->strength_bits;
+ }
+ return ret;
+}
+
+uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *c)
+{
+ return c->id;
+}
+
+SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n)
+{
+ SSL_COMP *ctmp;
+ int i, nn;
+
+ if ((n == 0) || (sk == NULL))
+ return (NULL);
+ nn = sk_SSL_COMP_num(sk);
+ for (i = 0; i < nn; i++) {
+ ctmp = sk_SSL_COMP_value(sk, i);
+ if (ctmp->id == n)
+ return (ctmp);
+ }
+ return (NULL);
+}
+
+#ifdef OPENSSL_NO_COMP
+STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void)
+{
+ return NULL;
+}
+
+STACK_OF(SSL_COMP) *SSL_COMP_set0_compression_methods(STACK_OF(SSL_COMP)
+ *meths)
+{
+ return meths;
+}
+
+int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm)
+{
+ return 1;
+}
+
+#else
+STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void)
+{
+ load_builtin_compressions();
+ return (ssl_comp_methods);
+}
+
+STACK_OF(SSL_COMP) *SSL_COMP_set0_compression_methods(STACK_OF(SSL_COMP)
+ *meths)
+{
+ STACK_OF(SSL_COMP) *old_meths = ssl_comp_methods;
+ ssl_comp_methods = meths;
+ return old_meths;
+}
+
+static void cmeth_free(SSL_COMP *cm)
+{
+ OPENSSL_free(cm);
+}
+
+void ssl_comp_free_compression_methods_int(void)
+{
+ STACK_OF(SSL_COMP) *old_meths = ssl_comp_methods;
+ ssl_comp_methods = NULL;
+ sk_SSL_COMP_pop_free(old_meths, cmeth_free);
+}
+
+int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm)
+{
+ SSL_COMP *comp;
+
+ if (cm == NULL || COMP_get_type(cm) == NID_undef)
+ return 1;
+
+ /*-
+ * According to draft-ietf-tls-compression-04.txt, the
+ * compression number ranges should be the following:
+ *
+ * 0 to 63: methods defined by the IETF
+ * 64 to 192: external party methods assigned by IANA
+ * 193 to 255: reserved for private use
+ */
+ if (id < 193 || id > 255) {
+ SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD,
+ SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE);
+ return 1;
+ }
+
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
+ comp = OPENSSL_malloc(sizeof(*comp));
+ if (comp == NULL) {
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
+ SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD, ERR_R_MALLOC_FAILURE);
+ return (1);
+ }
+
+ comp->id = id;
+ comp->method = cm;
+ load_builtin_compressions();
+ if (ssl_comp_methods && sk_SSL_COMP_find(ssl_comp_methods, comp) >= 0) {
+ OPENSSL_free(comp);
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
+ SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD,
+ SSL_R_DUPLICATE_COMPRESSION_ID);
+ return (1);
+ }
+ if (ssl_comp_methods == NULL || !sk_SSL_COMP_push(ssl_comp_methods, comp)) {
+ OPENSSL_free(comp);
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
+ SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD, ERR_R_MALLOC_FAILURE);
+ return (1);
+ }
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
+ return (0);
+}
+#endif
+
+const char *SSL_COMP_get_name(const COMP_METHOD *comp)
+{
+#ifndef OPENSSL_NO_COMP
+ return comp ? COMP_get_name(comp) : NULL;
+#else
+ return NULL;
+#endif
+}
+
+const char *SSL_COMP_get0_name(const SSL_COMP *comp)
+{
+#ifndef OPENSSL_NO_COMP
+ return comp->name;
+#else
+ return NULL;
+#endif
+}
+
+int SSL_COMP_get_id(const SSL_COMP *comp)
+{
+#ifndef OPENSSL_NO_COMP
+ return comp->id;
+#else
+ return -1;
+#endif
+}
+
+/* For a cipher return the index corresponding to the certificate type */
+int ssl_cipher_get_cert_index(const SSL_CIPHER *c)
+{
+ uint32_t alg_a;
+
+ alg_a = c->algorithm_auth;
+
+ if (alg_a & SSL_aECDSA)
+ return SSL_PKEY_ECC;
+ else if (alg_a & SSL_aDSS)
+ return SSL_PKEY_DSA_SIGN;
+ else if (alg_a & SSL_aRSA)
+ return SSL_PKEY_RSA_ENC;
+ else if (alg_a & SSL_aGOST12)
+ return SSL_PKEY_GOST_EC;
+ else if (alg_a & SSL_aGOST01)
+ return SSL_PKEY_GOST01;
+
+ return -1;
+}
+
+const SSL_CIPHER *ssl_get_cipher_by_char(SSL *ssl, const unsigned char *ptr)
+{
+ const SSL_CIPHER *c = ssl->method->get_cipher_by_char(ptr);
+
+ if (c == NULL || c->valid == 0)
+ return NULL;
+ return c;
+}
+
+const SSL_CIPHER *SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr)
+{
+ return ssl->method->get_cipher_by_char(ptr);
+}
+
+int SSL_CIPHER_get_cipher_nid(const SSL_CIPHER *c)
+{
+ int i;
+ if (c == NULL)
+ return NID_undef;
+ i = ssl_cipher_info_lookup(ssl_cipher_table_cipher, c->algorithm_enc);
+ if (i == -1)
+ return NID_undef;
+ return ssl_cipher_table_cipher[i].nid;
+}
+
+int SSL_CIPHER_get_digest_nid(const SSL_CIPHER *c)
+{
+ int i = ssl_cipher_info_lookup(ssl_cipher_table_mac, c->algorithm_mac);
+
+ if (i == -1)
+ return NID_undef;
+ return ssl_cipher_table_mac[i].nid;
+}
+
+int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *c)
+{
+ int i = ssl_cipher_info_lookup(ssl_cipher_table_kx, c->algorithm_mkey);
+
+ if (i == -1)
+ return NID_undef;
+ return ssl_cipher_table_kx[i].nid;
+}
+
+int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *c)
+{
+ int i = ssl_cipher_info_lookup(ssl_cipher_table_auth, c->algorithm_auth);
+
+ if (i == -1)
+ return NID_undef;
+ return ssl_cipher_table_auth[i].nid;
+}
+
+int SSL_CIPHER_is_aead(const SSL_CIPHER *c)
+{
+ return (c->algorithm_mac & SSL_AEAD) ? 1 : 0;
+}
diff --git a/openssl-1.1.0h/ssl/ssl_conf.c b/openssl-1.1.0h/ssl/ssl_conf.c
new file mode 100644
index 0000000..7f89488
--- /dev/null
+++ b/openssl-1.1.0h/ssl/ssl_conf.c
@@ -0,0 +1,893 @@
+/*
+ * Copyright 2012-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
+ */
+
+#include <stdio.h>
+#include "ssl_locl.h"
+#include <openssl/conf.h>
+#include <openssl/objects.h>
+#include <openssl/dh.h>
+
+/*
+ * structure holding name tables. This is used for permitted elements in lists
+ * such as TLSv1.
+ */
+
+typedef struct {
+ const char *name;
+ int namelen;
+ unsigned int name_flags;
+ unsigned long option_value;
+} ssl_flag_tbl;
+
+/* Switch table: use for single command line switches like no_tls2 */
+typedef struct {
+ unsigned long option_value;
+ unsigned int name_flags;
+} ssl_switch_tbl;
+
+/* Sense of name is inverted e.g. "TLSv1" will clear SSL_OP_NO_TLSv1 */
+#define SSL_TFLAG_INV 0x1
+/* Mask for type of flag referred to */
+#define SSL_TFLAG_TYPE_MASK 0xf00
+/* Flag is for options */
+#define SSL_TFLAG_OPTION 0x000
+/* Flag is for cert_flags */
+#define SSL_TFLAG_CERT 0x100
+/* Flag is for verify mode */
+#define SSL_TFLAG_VFY 0x200
+/* Option can only be used for clients */
+#define SSL_TFLAG_CLIENT SSL_CONF_FLAG_CLIENT
+/* Option can only be used for servers */
+#define SSL_TFLAG_SERVER SSL_CONF_FLAG_SERVER
+#define SSL_TFLAG_BOTH (SSL_TFLAG_CLIENT|SSL_TFLAG_SERVER)
+
+#define SSL_FLAG_TBL(str, flag) \
+ {str, (int)(sizeof(str) - 1), SSL_TFLAG_BOTH, flag}
+#define SSL_FLAG_TBL_SRV(str, flag) \
+ {str, (int)(sizeof(str) - 1), SSL_TFLAG_SERVER, flag}
+#define SSL_FLAG_TBL_CLI(str, flag) \
+ {str, (int)(sizeof(str) - 1), SSL_TFLAG_CLIENT, flag}
+#define SSL_FLAG_TBL_INV(str, flag) \
+ {str, (int)(sizeof(str) - 1), SSL_TFLAG_INV|SSL_TFLAG_BOTH, flag}
+#define SSL_FLAG_TBL_SRV_INV(str, flag) \
+ {str, (int)(sizeof(str) - 1), SSL_TFLAG_INV|SSL_TFLAG_SERVER, flag}
+#define SSL_FLAG_TBL_CERT(str, flag) \
+ {str, (int)(sizeof(str) - 1), SSL_TFLAG_CERT|SSL_TFLAG_BOTH, flag}
+
+#define SSL_FLAG_VFY_CLI(str, flag) \
+ {str, (int)(sizeof(str) - 1), SSL_TFLAG_VFY | SSL_TFLAG_CLIENT, flag}
+#define SSL_FLAG_VFY_SRV(str, flag) \
+ {str, (int)(sizeof(str) - 1), SSL_TFLAG_VFY | SSL_TFLAG_SERVER, flag}
+
+/*
+ * Opaque structure containing SSL configuration context.
+ */
+
+struct ssl_conf_ctx_st {
+ /*
+ * Various flags indicating (among other things) which options we will
+ * recognise.
+ */
+ unsigned int flags;
+ /* Prefix and length of commands */
+ char *prefix;
+ size_t prefixlen;
+ /* SSL_CTX or SSL structure to perform operations on */
+ SSL_CTX *ctx;
+ SSL *ssl;
+ /* Pointer to SSL or SSL_CTX options field or NULL if none */
+ uint32_t *poptions;
+ /* Certificate filenames for each type */
+ char *cert_filename[SSL_PKEY_NUM];
+ /* Pointer to SSL or SSL_CTX cert_flags or NULL if none */
+ uint32_t *pcert_flags;
+ /* Pointer to SSL or SSL_CTX verify_mode or NULL if none */
+ uint32_t *pvfy_flags;
+ /* Pointer to SSL or SSL_CTX min_version field or NULL if none */
+ int *min_version;
+ /* Pointer to SSL or SSL_CTX max_version field or NULL if none */
+ int *max_version;
+ /* Current flag table being worked on */
+ const ssl_flag_tbl *tbl;
+ /* Size of table */
+ size_t ntbl;
+ /* Client CA names */
+ STACK_OF(X509_NAME) *canames;
+};
+
+static void ssl_set_option(SSL_CONF_CTX *cctx, unsigned int name_flags,
+ unsigned long option_value, int onoff)
+{
+ uint32_t *pflags;
+ if (cctx->poptions == NULL)
+ return;
+ if (name_flags & SSL_TFLAG_INV)
+ onoff ^= 1;
+ switch (name_flags & SSL_TFLAG_TYPE_MASK) {
+
+ case SSL_TFLAG_CERT:
+ pflags = cctx->pcert_flags;
+ break;
+
+ case SSL_TFLAG_VFY:
+ pflags = cctx->pvfy_flags;
+ break;
+
+ case SSL_TFLAG_OPTION:
+ pflags = cctx->poptions;
+ break;
+
+ default:
+ return;
+
+ }
+ if (onoff)
+ *pflags |= option_value;
+ else
+ *pflags &= ~option_value;
+}
+
+static int ssl_match_option(SSL_CONF_CTX *cctx, const ssl_flag_tbl *tbl,
+ const char *name, int namelen, int onoff)
+{
+ /* If name not relevant for context skip */
+ if (!(cctx->flags & tbl->name_flags & SSL_TFLAG_BOTH))
+ return 0;
+ if (namelen == -1) {
+ if (strcmp(tbl->name, name))
+ return 0;
+ } else if (tbl->namelen != namelen || strncasecmp(tbl->name, name, namelen))
+ return 0;
+ ssl_set_option(cctx, tbl->name_flags, tbl->option_value, onoff);
+ return 1;
+}
+
+static int ssl_set_option_list(const char *elem, int len, void *usr)
+{
+ SSL_CONF_CTX *cctx = usr;
+ size_t i;
+ const ssl_flag_tbl *tbl;
+ int onoff = 1;
+ /*
+ * len == -1 indicates not being called in list context, just for single
+ * command line switches, so don't allow +, -.
+ */
+ if (elem == NULL)
+ return 0;
+ if (len != -1) {
+ if (*elem == '+') {
+ elem++;
+ len--;
+ onoff = 1;
+ } else if (*elem == '-') {
+ elem++;
+ len--;
+ onoff = 0;
+ }
+ }
+ for (i = 0, tbl = cctx->tbl; i < cctx->ntbl; i++, tbl++) {
+ if (ssl_match_option(cctx, tbl, elem, len, onoff))
+ return 1;
+ }
+ return 0;
+}
+
+/* Set supported signature algorithms */
+static int cmd_SignatureAlgorithms(SSL_CONF_CTX *cctx, const char *value)
+{
+ int rv;
+ if (cctx->ssl)
+ rv = SSL_set1_sigalgs_list(cctx->ssl, value);
+ /* NB: ctx == NULL performs syntax checking only */
+ else
+ rv = SSL_CTX_set1_sigalgs_list(cctx->ctx, value);
+ return rv > 0;
+}
+
+/* Set supported client signature algorithms */
+static int cmd_ClientSignatureAlgorithms(SSL_CONF_CTX *cctx, const char *value)
+{
+ int rv;
+ if (cctx->ssl)
+ rv = SSL_set1_client_sigalgs_list(cctx->ssl, value);
+ /* NB: ctx == NULL performs syntax checking only */
+ else
+ rv = SSL_CTX_set1_client_sigalgs_list(cctx->ctx, value);
+ return rv > 0;
+}
+
+static int cmd_Curves(SSL_CONF_CTX *cctx, const char *value)
+{
+ int rv;
+ if (cctx->ssl)
+ rv = SSL_set1_curves_list(cctx->ssl, value);
+ /* NB: ctx == NULL performs syntax checking only */
+ else
+ rv = SSL_CTX_set1_curves_list(cctx->ctx, value);
+ return rv > 0;
+}
+
+#ifndef OPENSSL_NO_EC
+/* ECDH temporary parameters */
+static int cmd_ECDHParameters(SSL_CONF_CTX *cctx, const char *value)
+{
+ int rv = 1;
+ EC_KEY *ecdh;
+ int nid;
+
+ /* Ignore values supported by 1.0.2 for the automatic selection */
+ if ((cctx->flags & SSL_CONF_FLAG_FILE) &&
+ strcasecmp(value, "+automatic") == 0)
+ return 1;
+ if ((cctx->flags & SSL_CONF_FLAG_CMDLINE) &&
+ strcmp(value, "auto") == 0)
+ return 1;
+
+ nid = EC_curve_nist2nid(value);
+ if (nid == NID_undef)
+ nid = OBJ_sn2nid(value);
+ if (nid == 0)
+ return 0;
+ ecdh = EC_KEY_new_by_curve_name(nid);
+ if (!ecdh)
+ return 0;
+ if (cctx->ctx)
+ rv = SSL_CTX_set_tmp_ecdh(cctx->ctx, ecdh);
+ else if (cctx->ssl)
+ rv = SSL_set_tmp_ecdh(cctx->ssl, ecdh);
+ EC_KEY_free(ecdh);
+
+ return rv > 0;
+}
+#endif
+static int cmd_CipherString(SSL_CONF_CTX *cctx, const char *value)
+{
+ int rv = 1;
+ if (cctx->ctx)
+ rv = SSL_CTX_set_cipher_list(cctx->ctx, value);
+ if (cctx->ssl)
+ rv = SSL_set_cipher_list(cctx->ssl, value);
+ return rv > 0;
+}
+
+static int cmd_Protocol(SSL_CONF_CTX *cctx, const char *value)
+{
+ static const ssl_flag_tbl ssl_protocol_list[] = {
+ SSL_FLAG_TBL_INV("ALL", SSL_OP_NO_SSL_MASK),
+ SSL_FLAG_TBL_INV("SSLv2", SSL_OP_NO_SSLv2),
+ SSL_FLAG_TBL_INV("SSLv3", SSL_OP_NO_SSLv3),
+ SSL_FLAG_TBL_INV("TLSv1", SSL_OP_NO_TLSv1),
+ SSL_FLAG_TBL_INV("TLSv1.1", SSL_OP_NO_TLSv1_1),
+ SSL_FLAG_TBL_INV("TLSv1.2", SSL_OP_NO_TLSv1_2),
+ SSL_FLAG_TBL_INV("DTLSv1", SSL_OP_NO_DTLSv1),
+ SSL_FLAG_TBL_INV("DTLSv1.2", SSL_OP_NO_DTLSv1_2)
+ };
+ cctx->tbl = ssl_protocol_list;
+ cctx->ntbl = OSSL_NELEM(ssl_protocol_list);
+ return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx);
+}
+
+/*
+ * protocol_from_string - converts a protocol version string to a number
+ *
+ * Returns -1 on failure or the version on success
+ */
+static int protocol_from_string(const char *value)
+{
+ struct protocol_versions {
+ const char *name;
+ int version;
+ };
+ static const struct protocol_versions versions[] = {
+ {"None", 0},
+ {"SSLv3", SSL3_VERSION},
+ {"TLSv1", TLS1_VERSION},
+ {"TLSv1.1", TLS1_1_VERSION},
+ {"TLSv1.2", TLS1_2_VERSION},
+ {"DTLSv1", DTLS1_VERSION},
+ {"DTLSv1.2", DTLS1_2_VERSION}
+ };
+ size_t i;
+ size_t n = OSSL_NELEM(versions);
+
+ for (i = 0; i < n; i++)
+ if (strcmp(versions[i].name, value) == 0)
+ return versions[i].version;
+ return -1;
+}
+
+static int min_max_proto(SSL_CONF_CTX *cctx, const char *value, int *bound)
+{
+ int method_version;
+ int new_version;
+
+ if (cctx->ctx != NULL)
+ method_version = cctx->ctx->method->version;
+ else if (cctx->ssl != NULL)
+ method_version = cctx->ssl->ctx->method->version;
+ else
+ return 0;
+ if ((new_version = protocol_from_string(value)) < 0)
+ return 0;
+ return ssl_set_version_bound(method_version, new_version, bound);
+}
+
+/*
+ * cmd_MinProtocol - Set min protocol version
+ * @cctx: config structure to save settings in
+ * @value: The min protocol version in string form
+ *
+ * Returns 1 on success and 0 on failure.
+ */
+static int cmd_MinProtocol(SSL_CONF_CTX *cctx, const char *value)
+{
+ return min_max_proto(cctx, value, cctx->min_version);
+}
+
+/*
+ * cmd_MaxProtocol - Set max protocol version
+ * @cctx: config structure to save settings in
+ * @value: The max protocol version in string form
+ *
+ * Returns 1 on success and 0 on failure.
+ */
+static int cmd_MaxProtocol(SSL_CONF_CTX *cctx, const char *value)
+{
+ return min_max_proto(cctx, value, cctx->max_version);
+}
+
+static int cmd_Options(SSL_CONF_CTX *cctx, const char *value)
+{
+ static const ssl_flag_tbl ssl_option_list[] = {
+ SSL_FLAG_TBL_INV("SessionTicket", SSL_OP_NO_TICKET),
+ SSL_FLAG_TBL_INV("EmptyFragments",
+ SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS),
+ SSL_FLAG_TBL("Bugs", SSL_OP_ALL),
+ SSL_FLAG_TBL_INV("Compression", SSL_OP_NO_COMPRESSION),
+ SSL_FLAG_TBL_SRV("ServerPreference", SSL_OP_CIPHER_SERVER_PREFERENCE),
+ SSL_FLAG_TBL_SRV("NoResumptionOnRenegotiation",
+ SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION),
+ SSL_FLAG_TBL_SRV("DHSingle", SSL_OP_SINGLE_DH_USE),
+ SSL_FLAG_TBL_SRV("ECDHSingle", SSL_OP_SINGLE_ECDH_USE),
+ SSL_FLAG_TBL("UnsafeLegacyRenegotiation",
+ SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION),
+ SSL_FLAG_TBL_INV("EncryptThenMac", SSL_OP_NO_ENCRYPT_THEN_MAC),
+ SSL_FLAG_TBL("NoRenegotiation", SSL_OP_NO_RENEGOTIATION),
+ };
+ if (value == NULL)
+ return -3;
+ cctx->tbl = ssl_option_list;
+ cctx->ntbl = OSSL_NELEM(ssl_option_list);
+ return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx);
+}
+
+static int cmd_VerifyMode(SSL_CONF_CTX *cctx, const char *value)
+{
+ static const ssl_flag_tbl ssl_vfy_list[] = {
+ SSL_FLAG_VFY_CLI("Peer", SSL_VERIFY_PEER),
+ SSL_FLAG_VFY_SRV("Request", SSL_VERIFY_PEER),
+ SSL_FLAG_VFY_SRV("Require",
+ SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT),
+ SSL_FLAG_VFY_SRV("Once", SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE)
+ };
+ if (value == NULL)
+ return -3;
+ cctx->tbl = ssl_vfy_list;
+ cctx->ntbl = OSSL_NELEM(ssl_vfy_list);
+ return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx);
+}
+
+static int cmd_Certificate(SSL_CONF_CTX *cctx, const char *value)
+{
+ int rv = 1;
+ CERT *c = NULL;
+ if (cctx->ctx) {
+ rv = SSL_CTX_use_certificate_chain_file(cctx->ctx, value);
+ c = cctx->ctx->cert;
+ }
+ if (cctx->ssl) {
+ rv = SSL_use_certificate_chain_file(cctx->ssl, value);
+ c = cctx->ssl->cert;
+ }
+ if (rv > 0 && c && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) {
+ char **pfilename = &cctx->cert_filename[c->key - c->pkeys];
+ OPENSSL_free(*pfilename);
+ *pfilename = OPENSSL_strdup(value);
+ if (!*pfilename)
+ rv = 0;
+ }
+
+ return rv > 0;
+}
+
+static int cmd_PrivateKey(SSL_CONF_CTX *cctx, const char *value)
+{
+ int rv = 1;
+ if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE))
+ return -2;
+ if (cctx->ctx)
+ rv = SSL_CTX_use_PrivateKey_file(cctx->ctx, value, SSL_FILETYPE_PEM);
+ if (cctx->ssl)
+ rv = SSL_use_PrivateKey_file(cctx->ssl, value, SSL_FILETYPE_PEM);
+ return rv > 0;
+}
+
+static int cmd_ServerInfoFile(SSL_CONF_CTX *cctx, const char *value)
+{
+ int rv = 1;
+ if (cctx->ctx)
+ rv = SSL_CTX_use_serverinfo_file(cctx->ctx, value);
+ return rv > 0;
+}
+
+static int do_store(SSL_CONF_CTX *cctx,
+ const char *CAfile, const char *CApath, int verify_store)
+{
+ CERT *cert;
+ X509_STORE **st;
+ if (cctx->ctx)
+ cert = cctx->ctx->cert;
+ else if (cctx->ssl)
+ cert = cctx->ssl->cert;
+ else
+ return 1;
+ st = verify_store ? &cert->verify_store : &cert->chain_store;
+ if (*st == NULL) {
+ *st = X509_STORE_new();
+ if (*st == NULL)
+ return 0;
+ }
+ return X509_STORE_load_locations(*st, CAfile, CApath) > 0;
+}
+
+static int cmd_ChainCAPath(SSL_CONF_CTX *cctx, const char *value)
+{
+ return do_store(cctx, NULL, value, 0);
+}
+
+static int cmd_ChainCAFile(SSL_CONF_CTX *cctx, const char *value)
+{
+ return do_store(cctx, value, NULL, 0);
+}
+
+static int cmd_VerifyCAPath(SSL_CONF_CTX *cctx, const char *value)
+{
+ return do_store(cctx, NULL, value, 1);
+}
+
+static int cmd_VerifyCAFile(SSL_CONF_CTX *cctx, const char *value)
+{
+ return do_store(cctx, value, NULL, 1);
+}
+
+static int cmd_ClientCAFile(SSL_CONF_CTX *cctx, const char *value)
+{
+ if (cctx->canames == NULL)
+ cctx->canames = sk_X509_NAME_new_null();
+ if (cctx->canames == NULL)
+ return 0;
+ return SSL_add_file_cert_subjects_to_stack(cctx->canames, value);
+}
+
+static int cmd_ClientCAPath(SSL_CONF_CTX *cctx, const char *value)
+{
+ if (cctx->canames == NULL)
+ cctx->canames = sk_X509_NAME_new_null();
+ if (cctx->canames == NULL)
+ return 0;
+ return SSL_add_dir_cert_subjects_to_stack(cctx->canames, value);
+}
+
+#ifndef OPENSSL_NO_DH
+static int cmd_DHParameters(SSL_CONF_CTX *cctx, const char *value)
+{
+ int rv = 0;
+ DH *dh = NULL;
+ BIO *in = NULL;
+ if (cctx->ctx || cctx->ssl) {
+ in = BIO_new(BIO_s_file());
+ if (in == NULL)
+ goto end;
+ if (BIO_read_filename(in, value) <= 0)
+ goto end;
+ dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
+ if (dh == NULL)
+ goto end;
+ } else
+ return 1;
+ if (cctx->ctx)
+ rv = SSL_CTX_set_tmp_dh(cctx->ctx, dh);
+ if (cctx->ssl)
+ rv = SSL_set_tmp_dh(cctx->ssl, dh);
+ end:
+ DH_free(dh);
+ BIO_free(in);
+ return rv > 0;
+}
+#endif
+typedef struct {
+ int (*cmd) (SSL_CONF_CTX *cctx, const char *value);
+ const char *str_file;
+ const char *str_cmdline;
+ unsigned short flags;
+ unsigned short value_type;
+} ssl_conf_cmd_tbl;
+
+/* Table of supported parameters */
+
+#define SSL_CONF_CMD(name, cmdopt, flags, type) \
+ {cmd_##name, #name, cmdopt, flags, type}
+
+#define SSL_CONF_CMD_STRING(name, cmdopt, flags) \
+ SSL_CONF_CMD(name, cmdopt, flags, SSL_CONF_TYPE_STRING)
+
+#define SSL_CONF_CMD_SWITCH(name, flags) \
+ {0, NULL, name, flags, SSL_CONF_TYPE_NONE}
+
+/* See apps/apps.h if you change this table. */
+static const ssl_conf_cmd_tbl ssl_conf_cmds[] = {
+ SSL_CONF_CMD_SWITCH("no_ssl3", 0),
+ SSL_CONF_CMD_SWITCH("no_tls1", 0),
+ SSL_CONF_CMD_SWITCH("no_tls1_1", 0),
+ SSL_CONF_CMD_SWITCH("no_tls1_2", 0),
+ SSL_CONF_CMD_SWITCH("bugs", 0),
+ SSL_CONF_CMD_SWITCH("no_comp", 0),
+ SSL_CONF_CMD_SWITCH("comp", 0),
+ SSL_CONF_CMD_SWITCH("ecdh_single", SSL_CONF_FLAG_SERVER),
+ SSL_CONF_CMD_SWITCH("no_ticket", 0),
+ SSL_CONF_CMD_SWITCH("serverpref", SSL_CONF_FLAG_SERVER),
+ SSL_CONF_CMD_SWITCH("legacy_renegotiation", 0),
+ SSL_CONF_CMD_SWITCH("legacy_server_connect", SSL_CONF_FLAG_SERVER),
+ SSL_CONF_CMD_SWITCH("no_renegotiation", 0),
+ SSL_CONF_CMD_SWITCH("no_resumption_on_reneg", SSL_CONF_FLAG_SERVER),
+ SSL_CONF_CMD_SWITCH("no_legacy_server_connect", SSL_CONF_FLAG_SERVER),
+ SSL_CONF_CMD_SWITCH("strict", 0),
+ SSL_CONF_CMD_STRING(SignatureAlgorithms, "sigalgs", 0),
+ SSL_CONF_CMD_STRING(ClientSignatureAlgorithms, "client_sigalgs", 0),
+ SSL_CONF_CMD_STRING(Curves, "curves", 0),
+#ifndef OPENSSL_NO_EC
+ SSL_CONF_CMD_STRING(ECDHParameters, "named_curve", SSL_CONF_FLAG_SERVER),
+#endif
+ SSL_CONF_CMD_STRING(CipherString, "cipher", 0),
+ SSL_CONF_CMD_STRING(Protocol, NULL, 0),
+ SSL_CONF_CMD_STRING(MinProtocol, "min_protocol", 0),
+ SSL_CONF_CMD_STRING(MaxProtocol, "max_protocol", 0),
+ SSL_CONF_CMD_STRING(Options, NULL, 0),
+ SSL_CONF_CMD_STRING(VerifyMode, NULL, 0),
+ SSL_CONF_CMD(Certificate, "cert", SSL_CONF_FLAG_CERTIFICATE,
+ SSL_CONF_TYPE_FILE),
+ SSL_CONF_CMD(PrivateKey, "key", SSL_CONF_FLAG_CERTIFICATE,
+ SSL_CONF_TYPE_FILE),
+ SSL_CONF_CMD(ServerInfoFile, NULL,
+ SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
+ SSL_CONF_TYPE_FILE),
+ SSL_CONF_CMD(ChainCAPath, "chainCApath", SSL_CONF_FLAG_CERTIFICATE,
+ SSL_CONF_TYPE_DIR),
+ SSL_CONF_CMD(ChainCAFile, "chainCAfile", SSL_CONF_FLAG_CERTIFICATE,
+ SSL_CONF_TYPE_FILE),
+ SSL_CONF_CMD(VerifyCAPath, "verifyCApath", SSL_CONF_FLAG_CERTIFICATE,
+ SSL_CONF_TYPE_DIR),
+ SSL_CONF_CMD(VerifyCAFile, "verifyCAfile", SSL_CONF_FLAG_CERTIFICATE,
+ SSL_CONF_TYPE_FILE),
+ SSL_CONF_CMD(ClientCAFile, NULL,
+ SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
+ SSL_CONF_TYPE_FILE),
+ SSL_CONF_CMD(ClientCAPath, NULL,
+ SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
+ SSL_CONF_TYPE_DIR),
+#ifndef OPENSSL_NO_DH
+ SSL_CONF_CMD(DHParameters, "dhparam",
+ SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
+ SSL_CONF_TYPE_FILE)
+#endif
+};
+
+/* Supported switches: must match order of switches in ssl_conf_cmds */
+static const ssl_switch_tbl ssl_cmd_switches[] = {
+ {SSL_OP_NO_SSLv3, 0}, /* no_ssl3 */
+ {SSL_OP_NO_TLSv1, 0}, /* no_tls1 */
+ {SSL_OP_NO_TLSv1_1, 0}, /* no_tls1_1 */
+ {SSL_OP_NO_TLSv1_2, 0}, /* no_tls1_2 */
+ {SSL_OP_ALL, 0}, /* bugs */
+ {SSL_OP_NO_COMPRESSION, 0}, /* no_comp */
+ {SSL_OP_NO_COMPRESSION, SSL_TFLAG_INV}, /* comp */
+ {SSL_OP_SINGLE_ECDH_USE, 0}, /* ecdh_single */
+ {SSL_OP_NO_TICKET, 0}, /* no_ticket */
+ {SSL_OP_CIPHER_SERVER_PREFERENCE, 0}, /* serverpref */
+ /* legacy_renegotiation */
+ {SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION, 0},
+ /* legacy_server_connect */
+ {SSL_OP_LEGACY_SERVER_CONNECT, 0},
+ /* no_renegotiation */
+ {SSL_OP_NO_RENEGOTIATION, 0},
+ /* no_resumption_on_reneg */
+ {SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION, 0},
+ /* no_legacy_server_connect */
+ {SSL_OP_LEGACY_SERVER_CONNECT, SSL_TFLAG_INV},
+ {SSL_CERT_FLAG_TLS_STRICT, SSL_TFLAG_CERT}, /* strict */
+};
+
+static int ssl_conf_cmd_skip_prefix(SSL_CONF_CTX *cctx, const char **pcmd)
+{
+ if (!pcmd || !*pcmd)
+ return 0;
+ /* If a prefix is set, check and skip */
+ if (cctx->prefix) {
+ if (strlen(*pcmd) <= cctx->prefixlen)
+ return 0;
+ if (cctx->flags & SSL_CONF_FLAG_CMDLINE &&
+ strncmp(*pcmd, cctx->prefix, cctx->prefixlen))
+ return 0;
+ if (cctx->flags & SSL_CONF_FLAG_FILE &&
+ strncasecmp(*pcmd, cctx->prefix, cctx->prefixlen))
+ return 0;
+ *pcmd += cctx->prefixlen;
+ } else if (cctx->flags & SSL_CONF_FLAG_CMDLINE) {
+ if (**pcmd != '-' || !(*pcmd)[1])
+ return 0;
+ *pcmd += 1;
+ }
+ return 1;
+}
+
+/* Determine if a command is allowed according to cctx flags */
+static int ssl_conf_cmd_allowed(SSL_CONF_CTX *cctx, const ssl_conf_cmd_tbl * t)
+{
+ unsigned int tfl = t->flags;
+ unsigned int cfl = cctx->flags;
+ if ((tfl & SSL_CONF_FLAG_SERVER) && !(cfl & SSL_CONF_FLAG_SERVER))
+ return 0;
+ if ((tfl & SSL_CONF_FLAG_CLIENT) && !(cfl & SSL_CONF_FLAG_CLIENT))
+ return 0;
+ if ((tfl & SSL_CONF_FLAG_CERTIFICATE)
+ && !(cfl & SSL_CONF_FLAG_CERTIFICATE))
+ return 0;
+ return 1;
+}
+
+static const ssl_conf_cmd_tbl *ssl_conf_cmd_lookup(SSL_CONF_CTX *cctx,
+ const char *cmd)
+{
+ const ssl_conf_cmd_tbl *t;
+ size_t i;
+ if (cmd == NULL)
+ return NULL;
+
+ /* Look for matching parameter name in table */
+ for (i = 0, t = ssl_conf_cmds; i < OSSL_NELEM(ssl_conf_cmds); i++, t++) {
+ if (ssl_conf_cmd_allowed(cctx, t)) {
+ if (cctx->flags & SSL_CONF_FLAG_CMDLINE) {
+ if (t->str_cmdline && strcmp(t->str_cmdline, cmd) == 0)
+ return t;
+ }
+ if (cctx->flags & SSL_CONF_FLAG_FILE) {
+ if (t->str_file && strcasecmp(t->str_file, cmd) == 0)
+ return t;
+ }
+ }
+ }
+ return NULL;
+}
+
+static int ctrl_switch_option(SSL_CONF_CTX *cctx, const ssl_conf_cmd_tbl * cmd)
+{
+ /* Find index of command in table */
+ size_t idx = cmd - ssl_conf_cmds;
+ const ssl_switch_tbl *scmd;
+ /* Sanity check index */
+ if (idx >= OSSL_NELEM(ssl_cmd_switches))
+ return 0;
+ /* Obtain switches entry with same index */
+ scmd = ssl_cmd_switches + idx;
+ ssl_set_option(cctx, scmd->name_flags, scmd->option_value, 1);
+ return 1;
+}
+
+int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value)
+{
+ const ssl_conf_cmd_tbl *runcmd;
+ if (cmd == NULL) {
+ SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_INVALID_NULL_CMD_NAME);
+ return 0;
+ }
+
+ if (!ssl_conf_cmd_skip_prefix(cctx, &cmd))
+ return -2;
+
+ runcmd = ssl_conf_cmd_lookup(cctx, cmd);
+
+ if (runcmd) {
+ int rv;
+ if (runcmd->value_type == SSL_CONF_TYPE_NONE) {
+ return ctrl_switch_option(cctx, runcmd);
+ }
+ if (value == NULL)
+ return -3;
+ rv = runcmd->cmd(cctx, value);
+ if (rv > 0)
+ return 2;
+ if (rv == -2)
+ return -2;
+ if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) {
+ SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_BAD_VALUE);
+ ERR_add_error_data(4, "cmd=", cmd, ", value=", value);
+ }
+ return 0;
+ }
+
+ if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) {
+ SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_UNKNOWN_CMD_NAME);
+ ERR_add_error_data(2, "cmd=", cmd);
+ }
+
+ return -2;
+}
+
+int SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv)
+{
+ int rv;
+ const char *arg = NULL, *argn;
+ if (pargc && *pargc == 0)
+ return 0;
+ if (!pargc || *pargc > 0)
+ arg = **pargv;
+ if (arg == NULL)
+ return 0;
+ if (!pargc || *pargc > 1)
+ argn = (*pargv)[1];
+ else
+ argn = NULL;
+ cctx->flags &= ~SSL_CONF_FLAG_FILE;
+ cctx->flags |= SSL_CONF_FLAG_CMDLINE;
+ rv = SSL_CONF_cmd(cctx, arg, argn);
+ if (rv > 0) {
+ /* Success: update pargc, pargv */
+ (*pargv) += rv;
+ if (pargc)
+ (*pargc) -= rv;
+ return rv;
+ }
+ /* Unknown switch: indicate no arguments processed */
+ if (rv == -2)
+ return 0;
+ /* Some error occurred processing command, return fatal error */
+ if (rv == 0)
+ return -1;
+ return rv;
+}
+
+int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd)
+{
+ if (ssl_conf_cmd_skip_prefix(cctx, &cmd)) {
+ const ssl_conf_cmd_tbl *runcmd;
+ runcmd = ssl_conf_cmd_lookup(cctx, cmd);
+ if (runcmd)
+ return runcmd->value_type;
+ }
+ return SSL_CONF_TYPE_UNKNOWN;
+}
+
+SSL_CONF_CTX *SSL_CONF_CTX_new(void)
+{
+ SSL_CONF_CTX *ret = OPENSSL_zalloc(sizeof(*ret));
+
+ return ret;
+}
+
+int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx)
+{
+ /* See if any certificates are missing private keys */
+ size_t i;
+ CERT *c = NULL;
+ if (cctx->ctx)
+ c = cctx->ctx->cert;
+ else if (cctx->ssl)
+ c = cctx->ssl->cert;
+ if (c && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) {
+ for (i = 0; i < SSL_PKEY_NUM; i++) {
+ const char *p = cctx->cert_filename[i];
+ /*
+ * If missing private key try to load one from certificate file
+ */
+ if (p && !c->pkeys[i].privatekey) {
+ if (!cmd_PrivateKey(cctx, p))
+ return 0;
+ }
+ }
+ }
+ if (cctx->canames) {
+ if (cctx->ssl)
+ SSL_set_client_CA_list(cctx->ssl, cctx->canames);
+ else if (cctx->ctx)
+ SSL_CTX_set_client_CA_list(cctx->ctx, cctx->canames);
+ else
+ sk_X509_NAME_pop_free(cctx->canames, X509_NAME_free);
+ cctx->canames = NULL;
+ }
+ return 1;
+}
+
+void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx)
+{
+ if (cctx) {
+ size_t i;
+ for (i = 0; i < SSL_PKEY_NUM; i++)
+ OPENSSL_free(cctx->cert_filename[i]);
+ OPENSSL_free(cctx->prefix);
+ sk_X509_NAME_pop_free(cctx->canames, X509_NAME_free);
+ OPENSSL_free(cctx);
+ }
+}
+
+unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags)
+{
+ cctx->flags |= flags;
+ return cctx->flags;
+}
+
+unsigned int SSL_CONF_CTX_clear_flags(SSL_CONF_CTX *cctx, unsigned int flags)
+{
+ cctx->flags &= ~flags;
+ return cctx->flags;
+}
+
+int SSL_CONF_CTX_set1_prefix(SSL_CONF_CTX *cctx, const char *pre)
+{
+ char *tmp = NULL;
+ if (pre) {
+ tmp = OPENSSL_strdup(pre);
+ if (tmp == NULL)
+ return 0;
+ }
+ OPENSSL_free(cctx->prefix);
+ cctx->prefix = tmp;
+ if (tmp)
+ cctx->prefixlen = strlen(tmp);
+ else
+ cctx->prefixlen = 0;
+ return 1;
+}
+
+void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl)
+{
+ cctx->ssl = ssl;
+ cctx->ctx = NULL;
+ if (ssl) {
+ cctx->poptions = &ssl->options;
+ cctx->min_version = &ssl->min_proto_version;
+ cctx->max_version = &ssl->max_proto_version;
+ cctx->pcert_flags = &ssl->cert->cert_flags;
+ cctx->pvfy_flags = &ssl->verify_mode;
+ } else {
+ cctx->poptions = NULL;
+ cctx->min_version = NULL;
+ cctx->max_version = NULL;
+ cctx->pcert_flags = NULL;
+ cctx->pvfy_flags = NULL;
+ }
+}
+
+void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx)
+{
+ cctx->ctx = ctx;
+ cctx->ssl = NULL;
+ if (ctx) {
+ cctx->poptions = &ctx->options;
+ cctx->min_version = &ctx->min_proto_version;
+ cctx->max_version = &ctx->max_proto_version;
+ cctx->pcert_flags = &ctx->cert->cert_flags;
+ cctx->pvfy_flags = &ctx->verify_mode;
+ } else {
+ cctx->poptions = NULL;
+ cctx->min_version = NULL;
+ cctx->max_version = NULL;
+ cctx->pcert_flags = NULL;
+ cctx->pvfy_flags = NULL;
+ }
+}
diff --git a/openssl-1.1.0h/ssl/ssl_err.c b/openssl-1.1.0h/ssl/ssl_err.c
new file mode 100644
index 0000000..580861e
--- /dev/null
+++ b/openssl-1.1.0h/ssl/ssl_err.c
@@ -0,0 +1,689 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-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
+ */
+
+#include <stdio.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+
+# define ERR_FUNC(func) ERR_PACK(ERR_LIB_SSL,func,0)
+# define ERR_REASON(reason) ERR_PACK(ERR_LIB_SSL,0,reason)
+
+static ERR_STRING_DATA SSL_str_functs[] = {
+ {ERR_FUNC(SSL_F_CHECK_SUITEB_CIPHER_LIST), "check_suiteb_cipher_list"},
+ {ERR_FUNC(SSL_F_CT_MOVE_SCTS), "ct_move_scts"},
+ {ERR_FUNC(SSL_F_CT_STRICT), "ct_strict"},
+ {ERR_FUNC(SSL_F_D2I_SSL_SESSION), "d2i_SSL_SESSION"},
+ {ERR_FUNC(SSL_F_DANE_CTX_ENABLE), "dane_ctx_enable"},
+ {ERR_FUNC(SSL_F_DANE_MTYPE_SET), "dane_mtype_set"},
+ {ERR_FUNC(SSL_F_DANE_TLSA_ADD), "dane_tlsa_add"},
+ {ERR_FUNC(SSL_F_DO_DTLS1_WRITE), "do_dtls1_write"},
+ {ERR_FUNC(SSL_F_DO_SSL3_WRITE), "do_ssl3_write"},
+ {ERR_FUNC(SSL_F_DTLS1_BUFFER_RECORD), "dtls1_buffer_record"},
+ {ERR_FUNC(SSL_F_DTLS1_CHECK_TIMEOUT_NUM), "dtls1_check_timeout_num"},
+ {ERR_FUNC(SSL_F_DTLS1_HEARTBEAT), "dtls1_heartbeat"},
+ {ERR_FUNC(SSL_F_DTLS1_PREPROCESS_FRAGMENT), "dtls1_preprocess_fragment"},
+ {ERR_FUNC(SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS),
+ "dtls1_process_buffered_records"},
+ {ERR_FUNC(SSL_F_DTLS1_PROCESS_RECORD), "dtls1_process_record"},
+ {ERR_FUNC(SSL_F_DTLS1_READ_BYTES), "dtls1_read_bytes"},
+ {ERR_FUNC(SSL_F_DTLS1_READ_FAILED), "dtls1_read_failed"},
+ {ERR_FUNC(SSL_F_DTLS1_RETRANSMIT_MESSAGE), "dtls1_retransmit_message"},
+ {ERR_FUNC(SSL_F_DTLS1_WRITE_APP_DATA_BYTES),
+ "dtls1_write_app_data_bytes"},
+ {ERR_FUNC(SSL_F_DTLSV1_LISTEN), "DTLSv1_listen"},
+ {ERR_FUNC(SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC),
+ "dtls_construct_change_cipher_spec"},
+ {ERR_FUNC(SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST),
+ "dtls_construct_hello_verify_request"},
+ {ERR_FUNC(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE),
+ "dtls_get_reassembled_message"},
+ {ERR_FUNC(SSL_F_DTLS_PROCESS_HELLO_VERIFY), "dtls_process_hello_verify"},
+ {ERR_FUNC(SSL_F_DTLS_WAIT_FOR_DRY), "dtls_wait_for_dry"},
+ {ERR_FUNC(SSL_F_OPENSSL_INIT_SSL), "OPENSSL_init_ssl"},
+ {ERR_FUNC(SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION),
+ "ossl_statem_client_read_transition"},
+ {ERR_FUNC(SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION),
+ "ossl_statem_server_read_transition"},
+ {ERR_FUNC(SSL_F_READ_STATE_MACHINE), "read_state_machine"},
+ {ERR_FUNC(SSL_F_SSL3_CHANGE_CIPHER_STATE), "ssl3_change_cipher_state"},
+ {ERR_FUNC(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM),
+ "ssl3_check_cert_and_algorithm"},
+ {ERR_FUNC(SSL_F_SSL3_CTRL), "ssl3_ctrl"},
+ {ERR_FUNC(SSL_F_SSL3_CTX_CTRL), "ssl3_ctx_ctrl"},
+ {ERR_FUNC(SSL_F_SSL3_DIGEST_CACHED_RECORDS),
+ "ssl3_digest_cached_records"},
+ {ERR_FUNC(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC),
+ "ssl3_do_change_cipher_spec"},
+ {ERR_FUNC(SSL_F_SSL3_FINAL_FINISH_MAC), "ssl3_final_finish_mac"},
+ {ERR_FUNC(SSL_F_SSL3_GENERATE_KEY_BLOCK), "ssl3_generate_key_block"},
+ {ERR_FUNC(SSL_F_SSL3_GENERATE_MASTER_SECRET),
+ "ssl3_generate_master_secret"},
+ {ERR_FUNC(SSL_F_SSL3_GET_RECORD), "ssl3_get_record"},
+ {ERR_FUNC(SSL_F_SSL3_INIT_FINISHED_MAC), "ssl3_init_finished_mac"},
+ {ERR_FUNC(SSL_F_SSL3_OUTPUT_CERT_CHAIN), "ssl3_output_cert_chain"},
+ {ERR_FUNC(SSL_F_SSL3_READ_BYTES), "ssl3_read_bytes"},
+ {ERR_FUNC(SSL_F_SSL3_READ_N), "ssl3_read_n"},
+ {ERR_FUNC(SSL_F_SSL3_SETUP_KEY_BLOCK), "ssl3_setup_key_block"},
+ {ERR_FUNC(SSL_F_SSL3_SETUP_READ_BUFFER), "ssl3_setup_read_buffer"},
+ {ERR_FUNC(SSL_F_SSL3_SETUP_WRITE_BUFFER), "ssl3_setup_write_buffer"},
+ {ERR_FUNC(SSL_F_SSL3_TAKE_MAC), "ssl3_take_mac"},
+ {ERR_FUNC(SSL_F_SSL3_WRITE_BYTES), "ssl3_write_bytes"},
+ {ERR_FUNC(SSL_F_SSL3_WRITE_PENDING), "ssl3_write_pending"},
+ {ERR_FUNC(SSL_F_SSL_ADD_CERT_CHAIN), "ssl_add_cert_chain"},
+ {ERR_FUNC(SSL_F_SSL_ADD_CERT_TO_BUF), "ssl_add_cert_to_buf"},
+ {ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT),
+ "ssl_add_clienthello_renegotiate_ext"},
+ {ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT),
+ "ssl_add_clienthello_tlsext"},
+ {ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT),
+ "ssl_add_clienthello_use_srtp_ext"},
+ {ERR_FUNC(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK),
+ "SSL_add_dir_cert_subjects_to_stack"},
+ {ERR_FUNC(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK),
+ "SSL_add_file_cert_subjects_to_stack"},
+ {ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT),
+ "ssl_add_serverhello_renegotiate_ext"},
+ {ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT),
+ "ssl_add_serverhello_tlsext"},
+ {ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT),
+ "ssl_add_serverhello_use_srtp_ext"},
+ {ERR_FUNC(SSL_F_SSL_BAD_METHOD), "ssl_bad_method"},
+ {ERR_FUNC(SSL_F_SSL_BUILD_CERT_CHAIN), "ssl_build_cert_chain"},
+ {ERR_FUNC(SSL_F_SSL_BYTES_TO_CIPHER_LIST), "ssl_bytes_to_cipher_list"},
+ {ERR_FUNC(SSL_F_SSL_CERT_ADD0_CHAIN_CERT), "ssl_cert_add0_chain_cert"},
+ {ERR_FUNC(SSL_F_SSL_CERT_DUP), "ssl_cert_dup"},
+ {ERR_FUNC(SSL_F_SSL_CERT_NEW), "ssl_cert_new"},
+ {ERR_FUNC(SSL_F_SSL_CERT_SET0_CHAIN), "ssl_cert_set0_chain"},
+ {ERR_FUNC(SSL_F_SSL_CHECK_PRIVATE_KEY), "SSL_check_private_key"},
+ {ERR_FUNC(SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT),
+ "ssl_check_serverhello_tlsext"},
+ {ERR_FUNC(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG),
+ "ssl_check_srvr_ecc_cert_and_alg"},
+ {ERR_FUNC(SSL_F_SSL_CIPHER_PROCESS_RULESTR),
+ "ssl_cipher_process_rulestr"},
+ {ERR_FUNC(SSL_F_SSL_CIPHER_STRENGTH_SORT), "ssl_cipher_strength_sort"},
+ {ERR_FUNC(SSL_F_SSL_CLEAR), "SSL_clear"},
+ {ERR_FUNC(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD),
+ "SSL_COMP_add_compression_method"},
+ {ERR_FUNC(SSL_F_SSL_CONF_CMD), "SSL_CONF_cmd"},
+ {ERR_FUNC(SSL_F_SSL_CREATE_CIPHER_LIST), "ssl_create_cipher_list"},
+ {ERR_FUNC(SSL_F_SSL_CTRL), "SSL_ctrl"},
+ {ERR_FUNC(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY), "SSL_CTX_check_private_key"},
+ {ERR_FUNC(SSL_F_SSL_CTX_ENABLE_CT), "SSL_CTX_enable_ct"},
+ {ERR_FUNC(SSL_F_SSL_CTX_MAKE_PROFILES), "ssl_ctx_make_profiles"},
+ {ERR_FUNC(SSL_F_SSL_CTX_NEW), "SSL_CTX_new"},
+ {ERR_FUNC(SSL_F_SSL_CTX_SET_ALPN_PROTOS), "SSL_CTX_set_alpn_protos"},
+ {ERR_FUNC(SSL_F_SSL_CTX_SET_CIPHER_LIST), "SSL_CTX_set_cipher_list"},
+ {ERR_FUNC(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE),
+ "SSL_CTX_set_client_cert_engine"},
+ {ERR_FUNC(SSL_F_SSL_CTX_SET_CT_VALIDATION_CALLBACK),
+ "SSL_CTX_set_ct_validation_callback"},
+ {ERR_FUNC(SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT),
+ "SSL_CTX_set_session_id_context"},
+ {ERR_FUNC(SSL_F_SSL_CTX_SET_SSL_VERSION), "SSL_CTX_set_ssl_version"},
+ {ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE), "SSL_CTX_use_certificate"},
+ {ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1),
+ "SSL_CTX_use_certificate_ASN1"},
+ {ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE),
+ "SSL_CTX_use_certificate_file"},
+ {ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY), "SSL_CTX_use_PrivateKey"},
+ {ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1),
+ "SSL_CTX_use_PrivateKey_ASN1"},
+ {ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE),
+ "SSL_CTX_use_PrivateKey_file"},
+ {ERR_FUNC(SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT),
+ "SSL_CTX_use_psk_identity_hint"},
+ {ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY), "SSL_CTX_use_RSAPrivateKey"},
+ {ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1),
+ "SSL_CTX_use_RSAPrivateKey_ASN1"},
+ {ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE),
+ "SSL_CTX_use_RSAPrivateKey_file"},
+ {ERR_FUNC(SSL_F_SSL_CTX_USE_SERVERINFO), "SSL_CTX_use_serverinfo"},
+ {ERR_FUNC(SSL_F_SSL_CTX_USE_SERVERINFO_FILE),
+ "SSL_CTX_use_serverinfo_file"},
+ {ERR_FUNC(SSL_F_SSL_DANE_DUP), "ssl_dane_dup"},
+ {ERR_FUNC(SSL_F_SSL_DANE_ENABLE), "SSL_dane_enable"},
+ {ERR_FUNC(SSL_F_SSL_DO_CONFIG), "ssl_do_config"},
+ {ERR_FUNC(SSL_F_SSL_DO_HANDSHAKE), "SSL_do_handshake"},
+ {ERR_FUNC(SSL_F_SSL_DUP_CA_LIST), "SSL_dup_CA_list"},
+ {ERR_FUNC(SSL_F_SSL_ENABLE_CT), "SSL_enable_ct"},
+ {ERR_FUNC(SSL_F_SSL_GET_NEW_SESSION), "ssl_get_new_session"},
+ {ERR_FUNC(SSL_F_SSL_GET_PREV_SESSION), "ssl_get_prev_session"},
+ {ERR_FUNC(SSL_F_SSL_GET_SERVER_CERT_INDEX), "ssl_get_server_cert_index"},
+ {ERR_FUNC(SSL_F_SSL_GET_SIGN_PKEY), "ssl_get_sign_pkey"},
+ {ERR_FUNC(SSL_F_SSL_INIT_WBIO_BUFFER), "ssl_init_wbio_buffer"},
+ {ERR_FUNC(SSL_F_SSL_LOAD_CLIENT_CA_FILE), "SSL_load_client_CA_file"},
+ {ERR_FUNC(SSL_F_SSL_MODULE_INIT), "ssl_module_init"},
+ {ERR_FUNC(SSL_F_SSL_NEW), "SSL_new"},
+ {ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT),
+ "ssl_parse_clienthello_renegotiate_ext"},
+ {ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT),
+ "ssl_parse_clienthello_tlsext"},
+ {ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT),
+ "ssl_parse_clienthello_use_srtp_ext"},
+ {ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT),
+ "ssl_parse_serverhello_renegotiate_ext"},
+ {ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT),
+ "ssl_parse_serverhello_tlsext"},
+ {ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT),
+ "ssl_parse_serverhello_use_srtp_ext"},
+ {ERR_FUNC(SSL_F_SSL_PEEK), "SSL_peek"},
+ {ERR_FUNC(SSL_F_SSL_READ), "SSL_read"},
+ {ERR_FUNC(SSL_F_SSL_RENEGOTIATE), "SSL_renegotiate"},
+ {ERR_FUNC(SSL_F_SSL_RENEGOTIATE_ABBREVIATED),
+ "SSL_renegotiate_abbreviated"},
+ {ERR_FUNC(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT),
+ "ssl_scan_clienthello_tlsext"},
+ {ERR_FUNC(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT),
+ "ssl_scan_serverhello_tlsext"},
+ {ERR_FUNC(SSL_F_SSL_SESSION_DUP), "ssl_session_dup"},
+ {ERR_FUNC(SSL_F_SSL_SESSION_NEW), "SSL_SESSION_new"},
+ {ERR_FUNC(SSL_F_SSL_SESSION_PRINT_FP), "SSL_SESSION_print_fp"},
+ {ERR_FUNC(SSL_F_SSL_SESSION_SET1_ID), "SSL_SESSION_set1_id"},
+ {ERR_FUNC(SSL_F_SSL_SESSION_SET1_ID_CONTEXT),
+ "SSL_SESSION_set1_id_context"},
+ {ERR_FUNC(SSL_F_SSL_SET_ALPN_PROTOS), "SSL_set_alpn_protos"},
+ {ERR_FUNC(SSL_F_SSL_SET_CERT), "ssl_set_cert"},
+ {ERR_FUNC(SSL_F_SSL_SET_CIPHER_LIST), "SSL_set_cipher_list"},
+ {ERR_FUNC(SSL_F_SSL_SET_CT_VALIDATION_CALLBACK),
+ "SSL_set_ct_validation_callback"},
+ {ERR_FUNC(SSL_F_SSL_SET_FD), "SSL_set_fd"},
+ {ERR_FUNC(SSL_F_SSL_SET_PKEY), "ssl_set_pkey"},
+ {ERR_FUNC(SSL_F_SSL_SET_RFD), "SSL_set_rfd"},
+ {ERR_FUNC(SSL_F_SSL_SET_SESSION), "SSL_set_session"},
+ {ERR_FUNC(SSL_F_SSL_SET_SESSION_ID_CONTEXT),
+ "SSL_set_session_id_context"},
+ {ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT),
+ "SSL_set_session_ticket_ext"},
+ {ERR_FUNC(SSL_F_SSL_SET_WFD), "SSL_set_wfd"},
+ {ERR_FUNC(SSL_F_SSL_SHUTDOWN), "SSL_shutdown"},
+ {ERR_FUNC(SSL_F_SSL_SRP_CTX_INIT), "SSL_SRP_CTX_init"},
+ {ERR_FUNC(SSL_F_SSL_START_ASYNC_JOB), "ssl_start_async_job"},
+ {ERR_FUNC(SSL_F_SSL_UNDEFINED_FUNCTION), "ssl_undefined_function"},
+ {ERR_FUNC(SSL_F_SSL_UNDEFINED_VOID_FUNCTION),
+ "ssl_undefined_void_function"},
+ {ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE), "SSL_use_certificate"},
+ {ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE_ASN1), "SSL_use_certificate_ASN1"},
+ {ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE_FILE), "SSL_use_certificate_file"},
+ {ERR_FUNC(SSL_F_SSL_USE_PRIVATEKEY), "SSL_use_PrivateKey"},
+ {ERR_FUNC(SSL_F_SSL_USE_PRIVATEKEY_ASN1), "SSL_use_PrivateKey_ASN1"},
+ {ERR_FUNC(SSL_F_SSL_USE_PRIVATEKEY_FILE), "SSL_use_PrivateKey_file"},
+ {ERR_FUNC(SSL_F_SSL_USE_PSK_IDENTITY_HINT), "SSL_use_psk_identity_hint"},
+ {ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY), "SSL_use_RSAPrivateKey"},
+ {ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1),
+ "SSL_use_RSAPrivateKey_ASN1"},
+ {ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE),
+ "SSL_use_RSAPrivateKey_file"},
+ {ERR_FUNC(SSL_F_SSL_VALIDATE_CT), "ssl_validate_ct"},
+ {ERR_FUNC(SSL_F_SSL_VERIFY_CERT_CHAIN), "ssl_verify_cert_chain"},
+ {ERR_FUNC(SSL_F_SSL_WRITE), "SSL_write"},
+ {ERR_FUNC(SSL_F_STATE_MACHINE), "state_machine"},
+ {ERR_FUNC(SSL_F_TLS12_CHECK_PEER_SIGALG), "tls12_check_peer_sigalg"},
+ {ERR_FUNC(SSL_F_TLS1_CHANGE_CIPHER_STATE), "tls1_change_cipher_state"},
+ {ERR_FUNC(SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS),
+ "tls1_check_duplicate_extensions"},
+ {ERR_FUNC(SSL_F_TLS1_ENC), "tls1_enc"},
+ {ERR_FUNC(SSL_F_TLS1_EXPORT_KEYING_MATERIAL),
+ "tls1_export_keying_material"},
+ {ERR_FUNC(SSL_F_TLS1_GET_CURVELIST), "tls1_get_curvelist"},
+ {ERR_FUNC(SSL_F_TLS1_PRF), "tls1_PRF"},
+ {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "tls1_setup_key_block"},
+ {ERR_FUNC(SSL_F_TLS1_SET_SERVER_SIGALGS), "tls1_set_server_sigalgs"},
+ {ERR_FUNC(SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK),
+ "tls_client_key_exchange_post_work"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST),
+ "tls_construct_certificate_request"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CKE_DHE), "tls_construct_cke_dhe"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CKE_ECDHE), "tls_construct_cke_ecdhe"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CKE_GOST), "tls_construct_cke_gost"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE),
+ "tls_construct_cke_psk_preamble"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CKE_RSA), "tls_construct_cke_rsa"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CKE_SRP), "tls_construct_cke_srp"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE),
+ "tls_construct_client_certificate"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO),
+ "tls_construct_client_hello"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE),
+ "tls_construct_client_key_exchange"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY),
+ "tls_construct_client_verify"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_FINISHED), "tls_construct_finished"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_HELLO_REQUEST),
+ "tls_construct_hello_request"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET),
+ "tls_construct_new_session_ticket"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE),
+ "tls_construct_server_certificate"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_DONE), "tls_construct_server_done"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_HELLO),
+ "tls_construct_server_hello"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE),
+ "tls_construct_server_key_exchange"},
+ {ERR_FUNC(SSL_F_TLS_GET_MESSAGE_BODY), "tls_get_message_body"},
+ {ERR_FUNC(SSL_F_TLS_GET_MESSAGE_HEADER), "tls_get_message_header"},
+ {ERR_FUNC(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO),
+ "tls_post_process_client_hello"},
+ {ERR_FUNC(SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE),
+ "tls_post_process_client_key_exchange"},
+ {ERR_FUNC(SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE),
+ "tls_prepare_client_certificate"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST),
+ "tls_process_certificate_request"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_CERT_STATUS), "tls_process_cert_status"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_CERT_VERIFY), "tls_process_cert_verify"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC),
+ "tls_process_change_cipher_spec"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_CKE_DHE), "tls_process_cke_dhe"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_CKE_ECDHE), "tls_process_cke_ecdhe"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_CKE_GOST), "tls_process_cke_gost"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE),
+ "tls_process_cke_psk_preamble"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_CKE_RSA), "tls_process_cke_rsa"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_CKE_SRP), "tls_process_cke_srp"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE),
+ "tls_process_client_certificate"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_CLIENT_HELLO), "tls_process_client_hello"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE),
+ "tls_process_client_key_exchange"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_FINISHED), "tls_process_finished"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_KEY_EXCHANGE), "tls_process_key_exchange"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET),
+ "tls_process_new_session_ticket"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_NEXT_PROTO), "tls_process_next_proto"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE),
+ "tls_process_server_certificate"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_SERVER_DONE), "tls_process_server_done"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_SERVER_HELLO), "tls_process_server_hello"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_SKE_DHE), "tls_process_ske_dhe"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_SKE_ECDHE), "tls_process_ske_ecdhe"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE),
+ "tls_process_ske_psk_preamble"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_SKE_SRP), "tls_process_ske_srp"},
+ {ERR_FUNC(SSL_F_USE_CERTIFICATE_CHAIN_FILE),
+ "use_certificate_chain_file"},
+ {0, NULL}
+};
+
+static ERR_STRING_DATA SSL_str_reasons[] = {
+ {ERR_REASON(SSL_R_APP_DATA_IN_HANDSHAKE), "app data in handshake"},
+ {ERR_REASON(SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT),
+ "attempt to reuse session in different context"},
+ {ERR_REASON(SSL_R_AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE),
+ "at least TLS 1.0 needed in FIPS mode"},
+ {ERR_REASON(SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE),
+ "at least (D)TLS 1.2 needed in Suite B mode"},
+ {ERR_REASON(SSL_R_BAD_CHANGE_CIPHER_SPEC), "bad change cipher spec"},
+ {ERR_REASON(SSL_R_BAD_DATA), "bad data"},
+ {ERR_REASON(SSL_R_BAD_DATA_RETURNED_BY_CALLBACK),
+ "bad data returned by callback"},
+ {ERR_REASON(SSL_R_BAD_DECOMPRESSION), "bad decompression"},
+ {ERR_REASON(SSL_R_BAD_DH_VALUE), "bad dh value"},
+ {ERR_REASON(SSL_R_BAD_DIGEST_LENGTH), "bad digest length"},
+ {ERR_REASON(SSL_R_BAD_ECC_CERT), "bad ecc cert"},
+ {ERR_REASON(SSL_R_BAD_ECPOINT), "bad ecpoint"},
+ {ERR_REASON(SSL_R_BAD_HANDSHAKE_LENGTH), "bad handshake length"},
+ {ERR_REASON(SSL_R_BAD_HELLO_REQUEST), "bad hello request"},
+ {ERR_REASON(SSL_R_BAD_LENGTH), "bad length"},
+ {ERR_REASON(SSL_R_BAD_PACKET_LENGTH), "bad packet length"},
+ {ERR_REASON(SSL_R_BAD_PROTOCOL_VERSION_NUMBER),
+ "bad protocol version number"},
+ {ERR_REASON(SSL_R_BAD_RSA_ENCRYPT), "bad rsa encrypt"},
+ {ERR_REASON(SSL_R_BAD_SIGNATURE), "bad signature"},
+ {ERR_REASON(SSL_R_BAD_SRP_A_LENGTH), "bad srp a length"},
+ {ERR_REASON(SSL_R_BAD_SRP_PARAMETERS), "bad srp parameters"},
+ {ERR_REASON(SSL_R_BAD_SRTP_MKI_VALUE), "bad srtp mki value"},
+ {ERR_REASON(SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST),
+ "bad srtp protection profile list"},
+ {ERR_REASON(SSL_R_BAD_SSL_FILETYPE), "bad ssl filetype"},
+ {ERR_REASON(SSL_R_BAD_VALUE), "bad value"},
+ {ERR_REASON(SSL_R_BAD_WRITE_RETRY), "bad write retry"},
+ {ERR_REASON(SSL_R_BIO_NOT_SET), "bio not set"},
+ {ERR_REASON(SSL_R_BLOCK_CIPHER_PAD_IS_WRONG),
+ "block cipher pad is wrong"},
+ {ERR_REASON(SSL_R_BN_LIB), "bn lib"},
+ {ERR_REASON(SSL_R_CA_DN_LENGTH_MISMATCH), "ca dn length mismatch"},
+ {ERR_REASON(SSL_R_CA_KEY_TOO_SMALL), "ca key too small"},
+ {ERR_REASON(SSL_R_CA_MD_TOO_WEAK), "ca md too weak"},
+ {ERR_REASON(SSL_R_CCS_RECEIVED_EARLY), "ccs received early"},
+ {ERR_REASON(SSL_R_CERTIFICATE_VERIFY_FAILED),
+ "certificate verify failed"},
+ {ERR_REASON(SSL_R_CERT_CB_ERROR), "cert cb error"},
+ {ERR_REASON(SSL_R_CERT_LENGTH_MISMATCH), "cert length mismatch"},
+ {ERR_REASON(SSL_R_CIPHER_CODE_WRONG_LENGTH), "cipher code wrong length"},
+ {ERR_REASON(SSL_R_CIPHER_OR_HASH_UNAVAILABLE),
+ "cipher or hash unavailable"},
+ {ERR_REASON(SSL_R_CLIENTHELLO_TLSEXT), "clienthello tlsext"},
+ {ERR_REASON(SSL_R_COMPRESSED_LENGTH_TOO_LONG),
+ "compressed length too long"},
+ {ERR_REASON(SSL_R_COMPRESSION_DISABLED), "compression disabled"},
+ {ERR_REASON(SSL_R_COMPRESSION_FAILURE), "compression failure"},
+ {ERR_REASON(SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE),
+ "compression id not within private range"},
+ {ERR_REASON(SSL_R_COMPRESSION_LIBRARY_ERROR),
+ "compression library error"},
+ {ERR_REASON(SSL_R_CONNECTION_TYPE_NOT_SET), "connection type not set"},
+ {ERR_REASON(SSL_R_CONTEXT_NOT_DANE_ENABLED), "context not dane enabled"},
+ {ERR_REASON(SSL_R_COOKIE_GEN_CALLBACK_FAILURE),
+ "cookie gen callback failure"},
+ {ERR_REASON(SSL_R_COOKIE_MISMATCH), "cookie mismatch"},
+ {ERR_REASON(SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED),
+ "custom ext handler already installed"},
+ {ERR_REASON(SSL_R_DANE_ALREADY_ENABLED), "dane already enabled"},
+ {ERR_REASON(SSL_R_DANE_CANNOT_OVERRIDE_MTYPE_FULL),
+ "dane cannot override mtype full"},
+ {ERR_REASON(SSL_R_DANE_NOT_ENABLED), "dane not enabled"},
+ {ERR_REASON(SSL_R_DANE_TLSA_BAD_CERTIFICATE),
+ "dane tlsa bad certificate"},
+ {ERR_REASON(SSL_R_DANE_TLSA_BAD_CERTIFICATE_USAGE),
+ "dane tlsa bad certificate usage"},
+ {ERR_REASON(SSL_R_DANE_TLSA_BAD_DATA_LENGTH),
+ "dane tlsa bad data length"},
+ {ERR_REASON(SSL_R_DANE_TLSA_BAD_DIGEST_LENGTH),
+ "dane tlsa bad digest length"},
+ {ERR_REASON(SSL_R_DANE_TLSA_BAD_MATCHING_TYPE),
+ "dane tlsa bad matching type"},
+ {ERR_REASON(SSL_R_DANE_TLSA_BAD_PUBLIC_KEY), "dane tlsa bad public key"},
+ {ERR_REASON(SSL_R_DANE_TLSA_BAD_SELECTOR), "dane tlsa bad selector"},
+ {ERR_REASON(SSL_R_DANE_TLSA_NULL_DATA), "dane tlsa null data"},
+ {ERR_REASON(SSL_R_DATA_BETWEEN_CCS_AND_FINISHED),
+ "data between ccs and finished"},
+ {ERR_REASON(SSL_R_DATA_LENGTH_TOO_LONG), "data length too long"},
+ {ERR_REASON(SSL_R_DECRYPTION_FAILED), "decryption failed"},
+ {ERR_REASON(SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC),
+ "decryption failed or bad record mac"},
+ {ERR_REASON(SSL_R_DH_KEY_TOO_SMALL), "dh key too small"},
+ {ERR_REASON(SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG),
+ "dh public value length is wrong"},
+ {ERR_REASON(SSL_R_DIGEST_CHECK_FAILED), "digest check failed"},
+ {ERR_REASON(SSL_R_DTLS_MESSAGE_TOO_BIG), "dtls message too big"},
+ {ERR_REASON(SSL_R_DUPLICATE_COMPRESSION_ID), "duplicate compression id"},
+ {ERR_REASON(SSL_R_ECC_CERT_NOT_FOR_SIGNING), "ecc cert not for signing"},
+ {ERR_REASON(SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE),
+ "ecdh required for suiteb mode"},
+ {ERR_REASON(SSL_R_EE_KEY_TOO_SMALL), "ee key too small"},
+ {ERR_REASON(SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST),
+ "empty srtp protection profile list"},
+ {ERR_REASON(SSL_R_ENCRYPTED_LENGTH_TOO_LONG),
+ "encrypted length too long"},
+ {ERR_REASON(SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST),
+ "error in received cipher list"},
+ {ERR_REASON(SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN),
+ "error setting tlsa base domain"},
+ {ERR_REASON(SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE),
+ "exceeds max fragment size"},
+ {ERR_REASON(SSL_R_EXCESSIVE_MESSAGE_SIZE), "excessive message size"},
+ {ERR_REASON(SSL_R_EXTRA_DATA_IN_MESSAGE), "extra data in message"},
+ {ERR_REASON(SSL_R_FAILED_TO_INIT_ASYNC), "failed to init async"},
+ {ERR_REASON(SSL_R_FRAGMENTED_CLIENT_HELLO), "fragmented client hello"},
+ {ERR_REASON(SSL_R_GOT_A_FIN_BEFORE_A_CCS), "got a fin before a ccs"},
+ {ERR_REASON(SSL_R_HTTPS_PROXY_REQUEST), "https proxy request"},
+ {ERR_REASON(SSL_R_HTTP_REQUEST), "http request"},
+ {ERR_REASON(SSL_R_ILLEGAL_SUITEB_DIGEST), "illegal Suite B digest"},
+ {ERR_REASON(SSL_R_INAPPROPRIATE_FALLBACK), "inappropriate fallback"},
+ {ERR_REASON(SSL_R_INCONSISTENT_COMPRESSION), "inconsistent compression"},
+ {ERR_REASON(SSL_R_INCONSISTENT_EXTMS), "inconsistent extms"},
+ {ERR_REASON(SSL_R_INVALID_COMMAND), "invalid command"},
+ {ERR_REASON(SSL_R_INVALID_COMPRESSION_ALGORITHM),
+ "invalid compression algorithm"},
+ {ERR_REASON(SSL_R_INVALID_CONFIGURATION_NAME),
+ "invalid configuration name"},
+ {ERR_REASON(SSL_R_INVALID_CT_VALIDATION_TYPE),
+ "invalid ct validation type"},
+ {ERR_REASON(SSL_R_INVALID_NULL_CMD_NAME), "invalid null cmd name"},
+ {ERR_REASON(SSL_R_INVALID_SEQUENCE_NUMBER), "invalid sequence number"},
+ {ERR_REASON(SSL_R_INVALID_SERVERINFO_DATA), "invalid serverinfo data"},
+ {ERR_REASON(SSL_R_INVALID_SRP_USERNAME), "invalid srp username"},
+ {ERR_REASON(SSL_R_INVALID_STATUS_RESPONSE), "invalid status response"},
+ {ERR_REASON(SSL_R_INVALID_TICKET_KEYS_LENGTH),
+ "invalid ticket keys length"},
+ {ERR_REASON(SSL_R_LENGTH_MISMATCH), "length mismatch"},
+ {ERR_REASON(SSL_R_LENGTH_TOO_LONG), "length too long"},
+ {ERR_REASON(SSL_R_LENGTH_TOO_SHORT), "length too short"},
+ {ERR_REASON(SSL_R_LIBRARY_BUG), "library bug"},
+ {ERR_REASON(SSL_R_LIBRARY_HAS_NO_CIPHERS), "library has no ciphers"},
+ {ERR_REASON(SSL_R_MISSING_DSA_SIGNING_CERT), "missing dsa signing cert"},
+ {ERR_REASON(SSL_R_MISSING_ECDSA_SIGNING_CERT),
+ "missing ecdsa signing cert"},
+ {ERR_REASON(SSL_R_MISSING_RSA_CERTIFICATE), "missing rsa certificate"},
+ {ERR_REASON(SSL_R_MISSING_RSA_ENCRYPTING_CERT),
+ "missing rsa encrypting cert"},
+ {ERR_REASON(SSL_R_MISSING_RSA_SIGNING_CERT), "missing rsa signing cert"},
+ {ERR_REASON(SSL_R_MISSING_SRP_PARAM), "can't find SRP server param"},
+ {ERR_REASON(SSL_R_MISSING_TMP_DH_KEY), "missing tmp dh key"},
+ {ERR_REASON(SSL_R_MISSING_TMP_ECDH_KEY), "missing tmp ecdh key"},
+ {ERR_REASON(SSL_R_NO_CERTIFICATES_RETURNED), "no certificates returned"},
+ {ERR_REASON(SSL_R_NO_CERTIFICATE_ASSIGNED), "no certificate assigned"},
+ {ERR_REASON(SSL_R_NO_CERTIFICATE_SET), "no certificate set"},
+ {ERR_REASON(SSL_R_NO_CIPHERS_AVAILABLE), "no ciphers available"},
+ {ERR_REASON(SSL_R_NO_CIPHERS_SPECIFIED), "no ciphers specified"},
+ {ERR_REASON(SSL_R_NO_CIPHER_MATCH), "no cipher match"},
+ {ERR_REASON(SSL_R_NO_CLIENT_CERT_METHOD), "no client cert method"},
+ {ERR_REASON(SSL_R_NO_COMPRESSION_SPECIFIED), "no compression specified"},
+ {ERR_REASON(SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER),
+ "Peer haven't sent GOST certificate, required for selected ciphersuite"},
+ {ERR_REASON(SSL_R_NO_METHOD_SPECIFIED), "no method specified"},
+ {ERR_REASON(SSL_R_NO_PEM_EXTENSIONS), "no pem extensions"},
+ {ERR_REASON(SSL_R_NO_PRIVATE_KEY_ASSIGNED), "no private key assigned"},
+ {ERR_REASON(SSL_R_NO_PROTOCOLS_AVAILABLE), "no protocols available"},
+ {ERR_REASON(SSL_R_NO_RENEGOTIATION), "no renegotiation"},
+ {ERR_REASON(SSL_R_NO_REQUIRED_DIGEST), "no required digest"},
+ {ERR_REASON(SSL_R_NO_SHARED_CIPHER), "no shared cipher"},
+ {ERR_REASON(SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS),
+ "no shared signature algorithms"},
+ {ERR_REASON(SSL_R_NO_SRTP_PROFILES), "no srtp profiles"},
+ {ERR_REASON(SSL_R_NO_VALID_SCTS), "no valid scts"},
+ {ERR_REASON(SSL_R_NO_VERIFY_COOKIE_CALLBACK),
+ "no verify cookie callback"},
+ {ERR_REASON(SSL_R_NULL_SSL_CTX), "null ssl ctx"},
+ {ERR_REASON(SSL_R_NULL_SSL_METHOD_PASSED), "null ssl method passed"},
+ {ERR_REASON(SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED),
+ "old session cipher not returned"},
+ {ERR_REASON(SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED),
+ "old session compression algorithm not returned"},
+ {ERR_REASON(SSL_R_PACKET_LENGTH_TOO_LONG), "packet length too long"},
+ {ERR_REASON(SSL_R_PARSE_TLSEXT), "parse tlsext"},
+ {ERR_REASON(SSL_R_PATH_TOO_LONG), "path too long"},
+ {ERR_REASON(SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE),
+ "peer did not return a certificate"},
+ {ERR_REASON(SSL_R_PEM_NAME_BAD_PREFIX), "pem name bad prefix"},
+ {ERR_REASON(SSL_R_PEM_NAME_TOO_SHORT), "pem name too short"},
+ {ERR_REASON(SSL_R_PIPELINE_FAILURE), "pipeline failure"},
+ {ERR_REASON(SSL_R_PROTOCOL_IS_SHUTDOWN), "protocol is shutdown"},
+ {ERR_REASON(SSL_R_PSK_IDENTITY_NOT_FOUND), "psk identity not found"},
+ {ERR_REASON(SSL_R_PSK_NO_CLIENT_CB), "psk no client cb"},
+ {ERR_REASON(SSL_R_PSK_NO_SERVER_CB), "psk no server cb"},
+ {ERR_REASON(SSL_R_READ_BIO_NOT_SET), "read bio not set"},
+ {ERR_REASON(SSL_R_READ_TIMEOUT_EXPIRED), "read timeout expired"},
+ {ERR_REASON(SSL_R_RECORD_LENGTH_MISMATCH), "record length mismatch"},
+ {ERR_REASON(SSL_R_RECORD_TOO_SMALL), "record too small"},
+ {ERR_REASON(SSL_R_RENEGOTIATE_EXT_TOO_LONG), "renegotiate ext too long"},
+ {ERR_REASON(SSL_R_RENEGOTIATION_ENCODING_ERR),
+ "renegotiation encoding err"},
+ {ERR_REASON(SSL_R_RENEGOTIATION_MISMATCH), "renegotiation mismatch"},
+ {ERR_REASON(SSL_R_REQUIRED_CIPHER_MISSING), "required cipher missing"},
+ {ERR_REASON(SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING),
+ "required compression algorithm missing"},
+ {ERR_REASON(SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING),
+ "scsv received when renegotiating"},
+ {ERR_REASON(SSL_R_SCT_VERIFICATION_FAILED), "sct verification failed"},
+ {ERR_REASON(SSL_R_SERVERHELLO_TLSEXT), "serverhello tlsext"},
+ {ERR_REASON(SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED),
+ "session id context uninitialized"},
+ {ERR_REASON(SSL_R_SHUTDOWN_WHILE_IN_INIT), "shutdown while in init"},
+ {ERR_REASON(SSL_R_SIGNATURE_ALGORITHMS_ERROR),
+ "signature algorithms error"},
+ {ERR_REASON(SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE),
+ "signature for non signing certificate"},
+ {ERR_REASON(SSL_R_SRP_A_CALC), "error with the srp params"},
+ {ERR_REASON(SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES),
+ "srtp could not allocate profiles"},
+ {ERR_REASON(SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG),
+ "srtp protection profile list too long"},
+ {ERR_REASON(SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE),
+ "srtp unknown protection profile"},
+ {ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME),
+ "ssl3 ext invalid servername"},
+ {ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE),
+ "ssl3 ext invalid servername type"},
+ {ERR_REASON(SSL_R_SSL3_SESSION_ID_TOO_LONG), "ssl3 session id too long"},
+ {ERR_REASON(SSL_R_SSLV3_ALERT_BAD_CERTIFICATE),
+ "sslv3 alert bad certificate"},
+ {ERR_REASON(SSL_R_SSLV3_ALERT_BAD_RECORD_MAC),
+ "sslv3 alert bad record mac"},
+ {ERR_REASON(SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED),
+ "sslv3 alert certificate expired"},
+ {ERR_REASON(SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED),
+ "sslv3 alert certificate revoked"},
+ {ERR_REASON(SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN),
+ "sslv3 alert certificate unknown"},
+ {ERR_REASON(SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE),
+ "sslv3 alert decompression failure"},
+ {ERR_REASON(SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE),
+ "sslv3 alert handshake failure"},
+ {ERR_REASON(SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER),
+ "sslv3 alert illegal parameter"},
+ {ERR_REASON(SSL_R_SSLV3_ALERT_NO_CERTIFICATE),
+ "sslv3 alert no certificate"},
+ {ERR_REASON(SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE),
+ "sslv3 alert unexpected message"},
+ {ERR_REASON(SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE),
+ "sslv3 alert unsupported certificate"},
+ {ERR_REASON(SSL_R_SSL_COMMAND_SECTION_EMPTY),
+ "ssl command section empty"},
+ {ERR_REASON(SSL_R_SSL_COMMAND_SECTION_NOT_FOUND),
+ "ssl command section not found"},
+ {ERR_REASON(SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION),
+ "ssl ctx has no default ssl version"},
+ {ERR_REASON(SSL_R_SSL_HANDSHAKE_FAILURE), "ssl handshake failure"},
+ {ERR_REASON(SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS),
+ "ssl library has no ciphers"},
+ {ERR_REASON(SSL_R_SSL_NEGATIVE_LENGTH), "ssl negative length"},
+ {ERR_REASON(SSL_R_SSL_SECTION_EMPTY), "ssl section empty"},
+ {ERR_REASON(SSL_R_SSL_SECTION_NOT_FOUND), "ssl section not found"},
+ {ERR_REASON(SSL_R_SSL_SESSION_ID_CALLBACK_FAILED),
+ "ssl session id callback failed"},
+ {ERR_REASON(SSL_R_SSL_SESSION_ID_CONFLICT), "ssl session id conflict"},
+ {ERR_REASON(SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG),
+ "ssl session id context too long"},
+ {ERR_REASON(SSL_R_SSL_SESSION_ID_TOO_LONG),
+ "ssl session id too long"},
+ {ERR_REASON(SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH),
+ "ssl session id has bad length"},
+ {ERR_REASON(SSL_R_SSL_SESSION_VERSION_MISMATCH),
+ "ssl session version mismatch"},
+ {ERR_REASON(SSL_R_TLSV1_ALERT_ACCESS_DENIED),
+ "tlsv1 alert access denied"},
+ {ERR_REASON(SSL_R_TLSV1_ALERT_DECODE_ERROR), "tlsv1 alert decode error"},
+ {ERR_REASON(SSL_R_TLSV1_ALERT_DECRYPTION_FAILED),
+ "tlsv1 alert decryption failed"},
+ {ERR_REASON(SSL_R_TLSV1_ALERT_DECRYPT_ERROR),
+ "tlsv1 alert decrypt error"},
+ {ERR_REASON(SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION),
+ "tlsv1 alert export restriction"},
+ {ERR_REASON(SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK),
+ "tlsv1 alert inappropriate fallback"},
+ {ERR_REASON(SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY),
+ "tlsv1 alert insufficient security"},
+ {ERR_REASON(SSL_R_TLSV1_ALERT_INTERNAL_ERROR),
+ "tlsv1 alert internal error"},
+ {ERR_REASON(SSL_R_TLSV1_ALERT_NO_RENEGOTIATION),
+ "tlsv1 alert no renegotiation"},
+ {ERR_REASON(SSL_R_TLSV1_ALERT_PROTOCOL_VERSION),
+ "tlsv1 alert protocol version"},
+ {ERR_REASON(SSL_R_TLSV1_ALERT_RECORD_OVERFLOW),
+ "tlsv1 alert record overflow"},
+ {ERR_REASON(SSL_R_TLSV1_ALERT_UNKNOWN_CA), "tlsv1 alert unknown ca"},
+ {ERR_REASON(SSL_R_TLSV1_ALERT_USER_CANCELLED),
+ "tlsv1 alert user cancelled"},
+ {ERR_REASON(SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE),
+ "tlsv1 bad certificate hash value"},
+ {ERR_REASON(SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE),
+ "tlsv1 bad certificate status response"},
+ {ERR_REASON(SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE),
+ "tlsv1 certificate unobtainable"},
+ {ERR_REASON(SSL_R_TLSV1_UNRECOGNIZED_NAME), "tlsv1 unrecognized name"},
+ {ERR_REASON(SSL_R_TLSV1_UNSUPPORTED_EXTENSION),
+ "tlsv1 unsupported extension"},
+ {ERR_REASON(SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT),
+ "peer does not accept heartbeats"},
+ {ERR_REASON(SSL_R_TLS_HEARTBEAT_PENDING),
+ "heartbeat request already pending"},
+ {ERR_REASON(SSL_R_TLS_ILLEGAL_EXPORTER_LABEL),
+ "tls illegal exporter label"},
+ {ERR_REASON(SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST),
+ "tls invalid ecpointformat list"},
+ {ERR_REASON(SSL_R_TOO_MANY_WARN_ALERTS), "too many warn alerts"},
+ {ERR_REASON(SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS),
+ "unable to find ecdh parameters"},
+ {ERR_REASON(SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS),
+ "unable to find public key parameters"},
+ {ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES),
+ "unable to load ssl3 md5 routines"},
+ {ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES),
+ "unable to load ssl3 sha1 routines"},
+ {ERR_REASON(SSL_R_UNEXPECTED_MESSAGE), "unexpected message"},
+ {ERR_REASON(SSL_R_UNEXPECTED_RECORD), "unexpected record"},
+ {ERR_REASON(SSL_R_UNINITIALIZED), "uninitialized"},
+ {ERR_REASON(SSL_R_UNKNOWN_ALERT_TYPE), "unknown alert type"},
+ {ERR_REASON(SSL_R_UNKNOWN_CERTIFICATE_TYPE), "unknown certificate type"},
+ {ERR_REASON(SSL_R_UNKNOWN_CIPHER_RETURNED), "unknown cipher returned"},
+ {ERR_REASON(SSL_R_UNKNOWN_CIPHER_TYPE), "unknown cipher type"},
+ {ERR_REASON(SSL_R_UNKNOWN_CMD_NAME), "unknown cmd name"},
+ {ERR_REASON(SSL_R_UNKNOWN_COMMAND), "unknown command"},
+ {ERR_REASON(SSL_R_UNKNOWN_DIGEST), "unknown digest"},
+ {ERR_REASON(SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE),
+ "unknown key exchange type"},
+ {ERR_REASON(SSL_R_UNKNOWN_PKEY_TYPE), "unknown pkey type"},
+ {ERR_REASON(SSL_R_UNKNOWN_PROTOCOL), "unknown protocol"},
+ {ERR_REASON(SSL_R_UNKNOWN_SSL_VERSION), "unknown ssl version"},
+ {ERR_REASON(SSL_R_UNKNOWN_STATE), "unknown state"},
+ {ERR_REASON(SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED),
+ "unsafe legacy renegotiation disabled"},
+ {ERR_REASON(SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM),
+ "unsupported compression algorithm"},
+ {ERR_REASON(SSL_R_UNSUPPORTED_ELLIPTIC_CURVE),
+ "unsupported elliptic curve"},
+ {ERR_REASON(SSL_R_UNSUPPORTED_PROTOCOL), "unsupported protocol"},
+ {ERR_REASON(SSL_R_UNSUPPORTED_SSL_VERSION), "unsupported ssl version"},
+ {ERR_REASON(SSL_R_UNSUPPORTED_STATUS_TYPE), "unsupported status type"},
+ {ERR_REASON(SSL_R_USE_SRTP_NOT_NEGOTIATED), "use srtp not negotiated"},
+ {ERR_REASON(SSL_R_VERSION_TOO_HIGH), "version too high"},
+ {ERR_REASON(SSL_R_VERSION_TOO_LOW), "version too low"},
+ {ERR_REASON(SSL_R_WRONG_CERTIFICATE_TYPE), "wrong certificate type"},
+ {ERR_REASON(SSL_R_WRONG_CIPHER_RETURNED), "wrong cipher returned"},
+ {ERR_REASON(SSL_R_WRONG_CURVE), "wrong curve"},
+ {ERR_REASON(SSL_R_WRONG_SIGNATURE_LENGTH), "wrong signature length"},
+ {ERR_REASON(SSL_R_WRONG_SIGNATURE_SIZE), "wrong signature size"},
+ {ERR_REASON(SSL_R_WRONG_SIGNATURE_TYPE), "wrong signature type"},
+ {ERR_REASON(SSL_R_WRONG_SSL_VERSION), "wrong ssl version"},
+ {ERR_REASON(SSL_R_WRONG_VERSION_NUMBER), "wrong version number"},
+ {ERR_REASON(SSL_R_X509_LIB), "x509 lib"},
+ {ERR_REASON(SSL_R_X509_VERIFICATION_SETUP_PROBLEMS),
+ "x509 verification setup problems"},
+ {0, NULL}
+};
+
+#endif
+
+int ERR_load_SSL_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+
+ if (ERR_func_error_string(SSL_str_functs[0].error) == NULL) {
+ ERR_load_strings(0, SSL_str_functs);
+ ERR_load_strings(0, SSL_str_reasons);
+ }
+#endif
+ return 1;
+}
diff --git a/openssl-1.1.0h/ssl/ssl_init.c b/openssl-1.1.0h/ssl/ssl_init.c
new file mode 100644
index 0000000..3e62d48
--- /dev/null
+++ b/openssl-1.1.0h/ssl/ssl_init.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2016 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
+ */
+
+#include "e_os.h"
+
+#include "internal/err.h"
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <assert.h>
+#include "ssl_locl.h"
+#include "internal/thread_once.h"
+
+static int stopped;
+
+static void ssl_library_stop(void);
+
+static CRYPTO_ONCE ssl_base = CRYPTO_ONCE_STATIC_INIT;
+static int ssl_base_inited = 0;
+DEFINE_RUN_ONCE_STATIC(ossl_init_ssl_base)
+{
+#ifdef OPENSSL_INIT_DEBUG
+ fprintf(stderr, "OPENSSL_INIT: ossl_init_ssl_base: "
+ "Adding SSL ciphers and digests\n");
+#endif
+#ifndef OPENSSL_NO_DES
+ EVP_add_cipher(EVP_des_cbc());
+ EVP_add_cipher(EVP_des_ede3_cbc());
+#endif
+#ifndef OPENSSL_NO_IDEA
+ EVP_add_cipher(EVP_idea_cbc());
+#endif
+#ifndef OPENSSL_NO_RC4
+ EVP_add_cipher(EVP_rc4());
+# ifndef OPENSSL_NO_MD5
+ EVP_add_cipher(EVP_rc4_hmac_md5());
+# endif
+#endif
+#ifndef OPENSSL_NO_RC2
+ EVP_add_cipher(EVP_rc2_cbc());
+ /*
+ * Not actually used for SSL/TLS but this makes PKCS#12 work if an
+ * application only calls SSL_library_init().
+ */
+ EVP_add_cipher(EVP_rc2_40_cbc());
+#endif
+ EVP_add_cipher(EVP_aes_128_cbc());
+ EVP_add_cipher(EVP_aes_192_cbc());
+ EVP_add_cipher(EVP_aes_256_cbc());
+ EVP_add_cipher(EVP_aes_128_gcm());
+ EVP_add_cipher(EVP_aes_256_gcm());
+ EVP_add_cipher(EVP_aes_128_ccm());
+ EVP_add_cipher(EVP_aes_256_ccm());
+ EVP_add_cipher(EVP_aes_128_cbc_hmac_sha1());
+ EVP_add_cipher(EVP_aes_256_cbc_hmac_sha1());
+ EVP_add_cipher(EVP_aes_128_cbc_hmac_sha256());
+ EVP_add_cipher(EVP_aes_256_cbc_hmac_sha256());
+#ifndef OPENSSL_NO_CAMELLIA
+ EVP_add_cipher(EVP_camellia_128_cbc());
+ EVP_add_cipher(EVP_camellia_256_cbc());
+#endif
+#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
+ EVP_add_cipher(EVP_chacha20_poly1305());
+#endif
+
+#ifndef OPENSSL_NO_SEED
+ EVP_add_cipher(EVP_seed_cbc());
+#endif
+
+#ifndef OPENSSL_NO_MD5
+ EVP_add_digest(EVP_md5());
+ EVP_add_digest_alias(SN_md5, "ssl3-md5");
+ EVP_add_digest(EVP_md5_sha1());
+#endif
+ EVP_add_digest(EVP_sha1()); /* RSA with sha1 */
+ EVP_add_digest_alias(SN_sha1, "ssl3-sha1");
+ EVP_add_digest_alias(SN_sha1WithRSAEncryption, SN_sha1WithRSA);
+ EVP_add_digest(EVP_sha224());
+ EVP_add_digest(EVP_sha256());
+ EVP_add_digest(EVP_sha384());
+ EVP_add_digest(EVP_sha512());
+#ifndef OPENSSL_NO_COMP
+# ifdef OPENSSL_INIT_DEBUG
+ fprintf(stderr, "OPENSSL_INIT: ossl_init_ssl_base: "
+ "SSL_COMP_get_compression_methods()\n");
+# endif
+ /*
+ * This will initialise the built-in compression algorithms. The value
+ * returned is a STACK_OF(SSL_COMP), but that can be discarded safely
+ */
+ SSL_COMP_get_compression_methods();
+#endif
+ /* initialize cipher/digest methods table */
+ ssl_load_ciphers();
+
+#ifdef OPENSSL_INIT_DEBUG
+ fprintf(stderr, "OPENSSL_INIT: ossl_init_ssl_base: "
+ "SSL_add_ssl_module()\n");
+#endif
+ SSL_add_ssl_module();
+ /*
+ * We ignore an error return here. Not much we can do - but not that bad
+ * either. We can still safely continue.
+ */
+ OPENSSL_atexit(ssl_library_stop);
+ ssl_base_inited = 1;
+ return 1;
+}
+
+static CRYPTO_ONCE ssl_strings = CRYPTO_ONCE_STATIC_INIT;
+static int ssl_strings_inited = 0;
+DEFINE_RUN_ONCE_STATIC(ossl_init_load_ssl_strings)
+{
+ /*
+ * OPENSSL_NO_AUTOERRINIT is provided here to prevent at compile time
+ * pulling in all the error strings during static linking
+ */
+#if !defined(OPENSSL_NO_ERR) && !defined(OPENSSL_NO_AUTOERRINIT)
+# ifdef OPENSSL_INIT_DEBUG
+ fprintf(stderr, "OPENSSL_INIT: ossl_init_load_ssl_strings: "
+ "ERR_load_SSL_strings()\n");
+# endif
+ ERR_load_SSL_strings();
+#endif
+ ssl_strings_inited = 1;
+ return 1;
+}
+
+DEFINE_RUN_ONCE_STATIC(ossl_init_no_load_ssl_strings)
+{
+ /* Do nothing in this case */
+ return 1;
+}
+
+static void ssl_library_stop(void)
+{
+ /* Might be explicitly called and also by atexit */
+ if (stopped)
+ return;
+ stopped = 1;
+
+ if (ssl_base_inited) {
+#ifndef OPENSSL_NO_COMP
+# ifdef OPENSSL_INIT_DEBUG
+ fprintf(stderr, "OPENSSL_INIT: ssl_library_stop: "
+ "ssl_comp_free_compression_methods_int()\n");
+# endif
+ ssl_comp_free_compression_methods_int();
+#endif
+ }
+
+ if (ssl_strings_inited) {
+#ifdef OPENSSL_INIT_DEBUG
+ fprintf(stderr, "OPENSSL_INIT: ssl_library_stop: "
+ "err_free_strings_int()\n");
+#endif
+ /*
+ * If both crypto and ssl error strings are inited we will end up
+ * calling err_free_strings_int() twice - but that's ok. The second
+ * time will be a no-op. It's easier to do that than to try and track
+ * between the two libraries whether they have both been inited.
+ */
+ err_free_strings_int();
+ }
+}
+
+/*
+ * If this function is called with a non NULL settings value then it must be
+ * called prior to any threads making calls to any OpenSSL functions,
+ * i.e. passing a non-null settings value is assumed to be single-threaded.
+ */
+int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS * settings)
+{
+ static int stoperrset = 0;
+
+ if (stopped) {
+ if (!stoperrset) {
+ /*
+ * We only ever set this once to avoid getting into an infinite
+ * loop where the error system keeps trying to init and fails so
+ * sets an error etc
+ */
+ stoperrset = 1;
+ SSLerr(SSL_F_OPENSSL_INIT_SSL, ERR_R_INIT_FAIL);
+ }
+ return 0;
+ }
+
+ if (!RUN_ONCE(&ssl_base, ossl_init_ssl_base))
+ return 0;
+
+ if (!OPENSSL_init_crypto(opts | OPENSSL_INIT_ADD_ALL_CIPHERS
+ | OPENSSL_INIT_ADD_ALL_DIGESTS, settings))
+ return 0;
+
+ if ((opts & OPENSSL_INIT_NO_LOAD_SSL_STRINGS)
+ && !RUN_ONCE(&ssl_strings, ossl_init_no_load_ssl_strings))
+ return 0;
+
+ if ((opts & OPENSSL_INIT_LOAD_SSL_STRINGS)
+ && !RUN_ONCE(&ssl_strings, ossl_init_load_ssl_strings))
+ return 0;
+
+ return 1;
+}
diff --git a/openssl-1.1.0h/ssl/ssl_lib.c b/openssl-1.1.0h/ssl/ssl_lib.c
new file mode 100644
index 0000000..8a190d2
--- /dev/null
+++ b/openssl-1.1.0h/ssl/ssl_lib.c
@@ -0,0 +1,4476 @@
+/*
+ * Copyright 1995-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
+ */
+
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include "ssl_locl.h"
+#include <openssl/objects.h>
+#include <openssl/lhash.h>
+#include <openssl/x509v3.h>
+#include <openssl/rand.h>
+#include <openssl/ocsp.h>
+#include <openssl/dh.h>
+#include <openssl/engine.h>
+#include <openssl/async.h>
+#include <openssl/ct.h>
+
+const char SSL_version_str[] = OPENSSL_VERSION_TEXT;
+
+static int ssl_undefined_function_1(SSL *ssl, SSL3_RECORD *r, unsigned int s,
+ int t)
+{
+ (void)r;
+ (void)s;
+ (void)t;
+ return ssl_undefined_function(ssl);
+}
+
+static int ssl_undefined_function_2(SSL *ssl, SSL3_RECORD *r, unsigned char *s,
+ int t)
+{
+ (void)r;
+ (void)s;
+ (void)t;
+ return ssl_undefined_function(ssl);
+}
+
+static int ssl_undefined_function_3(SSL *ssl, unsigned char *r,
+ unsigned char *s, int t)
+{
+ (void)r;
+ (void)s;
+ (void)t;
+ return ssl_undefined_function(ssl);
+}
+
+static int ssl_undefined_function_4(SSL *ssl, int r)
+{
+ (void)r;
+ return ssl_undefined_function(ssl);
+}
+
+static int ssl_undefined_function_5(SSL *ssl, const char *r, int s,
+ unsigned char *t)
+{
+ (void)r;
+ (void)s;
+ (void)t;
+ return ssl_undefined_function(ssl);
+}
+
+static int ssl_undefined_function_6(int r)
+{
+ (void)r;
+ return ssl_undefined_function(NULL);
+}
+
+static int ssl_undefined_function_7(SSL *ssl, unsigned char *r, size_t s,
+ const char *t, size_t u,
+ const unsigned char *v, size_t w, int x)
+{
+ (void)r;
+ (void)s;
+ (void)t;
+ (void)u;
+ (void)v;
+ (void)w;
+ (void)x;
+ return ssl_undefined_function(ssl);
+}
+
+SSL3_ENC_METHOD ssl3_undef_enc_method = {
+ ssl_undefined_function_1,
+ ssl_undefined_function_2,
+ ssl_undefined_function,
+ ssl_undefined_function_3,
+ ssl_undefined_function_4,
+ ssl_undefined_function_5,
+ 0, /* finish_mac_length */
+ NULL, /* client_finished_label */
+ 0, /* client_finished_label_len */
+ NULL, /* server_finished_label */
+ 0, /* server_finished_label_len */
+ ssl_undefined_function_6,
+ ssl_undefined_function_7,
+};
+
+struct ssl_async_args {
+ SSL *s;
+ void *buf;
+ int num;
+ enum { READFUNC, WRITEFUNC, OTHERFUNC } type;
+ union {
+ int (*func_read) (SSL *, void *, int);
+ int (*func_write) (SSL *, const void *, int);
+ int (*func_other) (SSL *);
+ } f;
+};
+
+static const struct {
+ uint8_t mtype;
+ uint8_t ord;
+ int nid;
+} dane_mds[] = {
+ {
+ DANETLS_MATCHING_FULL, 0, NID_undef
+ },
+ {
+ DANETLS_MATCHING_2256, 1, NID_sha256
+ },
+ {
+ DANETLS_MATCHING_2512, 2, NID_sha512
+ },
+};
+
+static int dane_ctx_enable(struct dane_ctx_st *dctx)
+{
+ const EVP_MD **mdevp;
+ uint8_t *mdord;
+ uint8_t mdmax = DANETLS_MATCHING_LAST;
+ int n = ((int)mdmax) + 1; /* int to handle PrivMatch(255) */
+ size_t i;
+
+ if (dctx->mdevp != NULL)
+ return 1;
+
+ mdevp = OPENSSL_zalloc(n * sizeof(*mdevp));
+ mdord = OPENSSL_zalloc(n * sizeof(*mdord));
+
+ if (mdord == NULL || mdevp == NULL) {
+ OPENSSL_free(mdord);
+ OPENSSL_free(mdevp);
+ SSLerr(SSL_F_DANE_CTX_ENABLE, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ /* Install default entries */
+ for (i = 0; i < OSSL_NELEM(dane_mds); ++i) {
+ const EVP_MD *md;
+
+ if (dane_mds[i].nid == NID_undef ||
+ (md = EVP_get_digestbynid(dane_mds[i].nid)) == NULL)
+ continue;
+ mdevp[dane_mds[i].mtype] = md;
+ mdord[dane_mds[i].mtype] = dane_mds[i].ord;
+ }
+
+ dctx->mdevp = mdevp;
+ dctx->mdord = mdord;
+ dctx->mdmax = mdmax;
+
+ return 1;
+}
+
+static void dane_ctx_final(struct dane_ctx_st *dctx)
+{
+ OPENSSL_free(dctx->mdevp);
+ dctx->mdevp = NULL;
+
+ OPENSSL_free(dctx->mdord);
+ dctx->mdord = NULL;
+ dctx->mdmax = 0;
+}
+
+static void tlsa_free(danetls_record *t)
+{
+ if (t == NULL)
+ return;
+ OPENSSL_free(t->data);
+ EVP_PKEY_free(t->spki);
+ OPENSSL_free(t);
+}
+
+static void dane_final(SSL_DANE *dane)
+{
+ sk_danetls_record_pop_free(dane->trecs, tlsa_free);
+ dane->trecs = NULL;
+
+ sk_X509_pop_free(dane->certs, X509_free);
+ dane->certs = NULL;
+
+ X509_free(dane->mcert);
+ dane->mcert = NULL;
+ dane->mtlsa = NULL;
+ dane->mdpth = -1;
+ dane->pdpth = -1;
+}
+
+/*
+ * dane_copy - Copy dane configuration, sans verification state.
+ */
+static int ssl_dane_dup(SSL *to, SSL *from)
+{
+ int num;
+ int i;
+
+ if (!DANETLS_ENABLED(&from->dane))
+ return 1;
+
+ dane_final(&to->dane);
+ to->dane.flags = from->dane.flags;
+ to->dane.dctx = &to->ctx->dane;
+ to->dane.trecs = sk_danetls_record_new_null();
+
+ if (to->dane.trecs == NULL) {
+ SSLerr(SSL_F_SSL_DANE_DUP, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ num = sk_danetls_record_num(from->dane.trecs);
+ for (i = 0; i < num; ++i) {
+ danetls_record *t = sk_danetls_record_value(from->dane.trecs, i);
+
+ if (SSL_dane_tlsa_add(to, t->usage, t->selector, t->mtype,
+ t->data, t->dlen) <= 0)
+ return 0;
+ }
+ return 1;
+}
+
+static int dane_mtype_set(struct dane_ctx_st *dctx,
+ const EVP_MD *md, uint8_t mtype, uint8_t ord)
+{
+ int i;
+
+ if (mtype == DANETLS_MATCHING_FULL && md != NULL) {
+ SSLerr(SSL_F_DANE_MTYPE_SET, SSL_R_DANE_CANNOT_OVERRIDE_MTYPE_FULL);
+ return 0;
+ }
+
+ if (mtype > dctx->mdmax) {
+ const EVP_MD **mdevp;
+ uint8_t *mdord;
+ int n = ((int)mtype) + 1;
+
+ mdevp = OPENSSL_realloc(dctx->mdevp, n * sizeof(*mdevp));
+ if (mdevp == NULL) {
+ SSLerr(SSL_F_DANE_MTYPE_SET, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ dctx->mdevp = mdevp;
+
+ mdord = OPENSSL_realloc(dctx->mdord, n * sizeof(*mdord));
+ if (mdord == NULL) {
+ SSLerr(SSL_F_DANE_MTYPE_SET, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ dctx->mdord = mdord;
+
+ /* Zero-fill any gaps */
+ for (i = dctx->mdmax + 1; i < mtype; ++i) {
+ mdevp[i] = NULL;
+ mdord[i] = 0;
+ }
+
+ dctx->mdmax = mtype;
+ }
+
+ dctx->mdevp[mtype] = md;
+ /* Coerce ordinal of disabled matching types to 0 */
+ dctx->mdord[mtype] = (md == NULL) ? 0 : ord;
+
+ return 1;
+}
+
+static const EVP_MD *tlsa_md_get(SSL_DANE *dane, uint8_t mtype)
+{
+ if (mtype > dane->dctx->mdmax)
+ return NULL;
+ return dane->dctx->mdevp[mtype];
+}
+
+static int dane_tlsa_add(SSL_DANE *dane,
+ uint8_t usage,
+ uint8_t selector,
+ uint8_t mtype, unsigned const char *data, size_t dlen)
+{
+ danetls_record *t;
+ const EVP_MD *md = NULL;
+ int ilen = (int)dlen;
+ int i;
+ int num;
+
+ if (dane->trecs == NULL) {
+ SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_NOT_ENABLED);
+ return -1;
+ }
+
+ if (ilen < 0 || dlen != (size_t)ilen) {
+ SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_DATA_LENGTH);
+ return 0;
+ }
+
+ if (usage > DANETLS_USAGE_LAST) {
+ SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_CERTIFICATE_USAGE);
+ return 0;
+ }
+
+ if (selector > DANETLS_SELECTOR_LAST) {
+ SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_SELECTOR);
+ return 0;
+ }
+
+ if (mtype != DANETLS_MATCHING_FULL) {
+ md = tlsa_md_get(dane, mtype);
+ if (md == NULL) {
+ SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_MATCHING_TYPE);
+ return 0;
+ }
+ }
+
+ if (md != NULL && dlen != (size_t)EVP_MD_size(md)) {
+ SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_DIGEST_LENGTH);
+ return 0;
+ }
+ if (!data) {
+ SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_NULL_DATA);
+ return 0;
+ }
+
+ if ((t = OPENSSL_zalloc(sizeof(*t))) == NULL) {
+ SSLerr(SSL_F_DANE_TLSA_ADD, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+
+ t->usage = usage;
+ t->selector = selector;
+ t->mtype = mtype;
+ t->data = OPENSSL_malloc(ilen);
+ if (t->data == NULL) {
+ tlsa_free(t);
+ SSLerr(SSL_F_DANE_TLSA_ADD, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ memcpy(t->data, data, ilen);
+ t->dlen = ilen;
+
+ /* Validate and cache full certificate or public key */
+ if (mtype == DANETLS_MATCHING_FULL) {
+ const unsigned char *p = data;
+ X509 *cert = NULL;
+ EVP_PKEY *pkey = NULL;
+
+ switch (selector) {
+ case DANETLS_SELECTOR_CERT:
+ if (!d2i_X509(&cert, &p, dlen) || p < data ||
+ dlen != (size_t)(p - data)) {
+ tlsa_free(t);
+ SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_CERTIFICATE);
+ return 0;
+ }
+ if (X509_get0_pubkey(cert) == NULL) {
+ tlsa_free(t);
+ SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_CERTIFICATE);
+ return 0;
+ }
+
+ if ((DANETLS_USAGE_BIT(usage) & DANETLS_TA_MASK) == 0) {
+ X509_free(cert);
+ break;
+ }
+
+ /*
+ * For usage DANE-TA(2), we support authentication via "2 0 0" TLSA
+ * records that contain full certificates of trust-anchors that are
+ * not present in the wire chain. For usage PKIX-TA(0), we augment
+ * the chain with untrusted Full(0) certificates from DNS, in case
+ * they are missing from the chain.
+ */
+ if ((dane->certs == NULL &&
+ (dane->certs = sk_X509_new_null()) == NULL) ||
+ !sk_X509_push(dane->certs, cert)) {
+ SSLerr(SSL_F_DANE_TLSA_ADD, ERR_R_MALLOC_FAILURE);
+ X509_free(cert);
+ tlsa_free(t);
+ return -1;
+ }
+ break;
+
+ case DANETLS_SELECTOR_SPKI:
+ if (!d2i_PUBKEY(&pkey, &p, dlen) || p < data ||
+ dlen != (size_t)(p - data)) {
+ tlsa_free(t);
+ SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_PUBLIC_KEY);
+ return 0;
+ }
+
+ /*
+ * For usage DANE-TA(2), we support authentication via "2 1 0" TLSA
+ * records that contain full bare keys of trust-anchors that are
+ * not present in the wire chain.
+ */
+ if (usage == DANETLS_USAGE_DANE_TA)
+ t->spki = pkey;
+ else
+ EVP_PKEY_free(pkey);
+ break;
+ }
+ }
+
+ /*-
+ * Find the right insertion point for the new record.
+ *
+ * See crypto/x509/x509_vfy.c. We sort DANE-EE(3) records first, so that
+ * they can be processed first, as they require no chain building, and no
+ * expiration or hostname checks. Because DANE-EE(3) is numerically
+ * largest, this is accomplished via descending sort by "usage".
+ *
+ * We also sort in descending order by matching ordinal to simplify
+ * the implementation of digest agility in the verification code.
+ *
+ * The choice of order for the selector is not significant, so we
+ * use the same descending order for consistency.
+ */
+ num = sk_danetls_record_num(dane->trecs);
+ for (i = 0; i < num; ++i) {
+ danetls_record *rec = sk_danetls_record_value(dane->trecs, i);
+
+ if (rec->usage > usage)
+ continue;
+ if (rec->usage < usage)
+ break;
+ if (rec->selector > selector)
+ continue;
+ if (rec->selector < selector)
+ break;
+ if (dane->dctx->mdord[rec->mtype] > dane->dctx->mdord[mtype])
+ continue;
+ break;
+ }
+
+ if (!sk_danetls_record_insert(dane->trecs, t, i)) {
+ tlsa_free(t);
+ SSLerr(SSL_F_DANE_TLSA_ADD, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ dane->umask |= DANETLS_USAGE_BIT(usage);
+
+ return 1;
+}
+
+/*
+ * Return 0 if there is only one version configured and it was disabled
+ * at configure time. Return 1 otherwise.
+ */
+static int ssl_check_allowed_versions(int min_version, int max_version)
+{
+ int minisdtls = 0, maxisdtls = 0;
+
+ /* Figure out if we're doing DTLS versions or TLS versions */
+ if (min_version == DTLS1_BAD_VER
+ || min_version >> 8 == DTLS1_VERSION_MAJOR)
+ minisdtls = 1;
+ if (max_version == DTLS1_BAD_VER
+ || max_version >> 8 == DTLS1_VERSION_MAJOR)
+ maxisdtls = 1;
+ /* A wildcard version of 0 could be DTLS or TLS. */
+ if ((minisdtls && !maxisdtls && max_version != 0)
+ || (maxisdtls && !minisdtls && min_version != 0)) {
+ /* Mixing DTLS and TLS versions will lead to sadness; deny it. */
+ return 0;
+ }
+
+ if (minisdtls || maxisdtls) {
+ /* Do DTLS version checks. */
+ if (min_version == 0)
+ /* Ignore DTLS1_BAD_VER */
+ min_version = DTLS1_VERSION;
+ if (max_version == 0)
+ max_version = DTLS1_2_VERSION;
+#ifdef OPENSSL_NO_DTLS1_2
+ if (max_version == DTLS1_2_VERSION)
+ max_version = DTLS1_VERSION;
+#endif
+#ifdef OPENSSL_NO_DTLS1
+ if (min_version == DTLS1_VERSION)
+ min_version = DTLS1_2_VERSION;
+#endif
+ /* Done massaging versions; do the check. */
+ if (0
+#ifdef OPENSSL_NO_DTLS1
+ || (DTLS_VERSION_GE(min_version, DTLS1_VERSION)
+ && DTLS_VERSION_GE(DTLS1_VERSION, max_version))
+#endif
+#ifdef OPENSSL_NO_DTLS1_2
+ || (DTLS_VERSION_GE(min_version, DTLS1_2_VERSION)
+ && DTLS_VERSION_GE(DTLS1_2_VERSION, max_version))
+#endif
+ )
+ return 0;
+ } else {
+ /* Regular TLS version checks. */
+ if (min_version == 0)
+ min_version = SSL3_VERSION;
+ if (max_version == 0)
+ max_version = TLS1_2_VERSION;
+#ifdef OPENSSL_NO_TLS1_2
+ if (max_version == TLS1_2_VERSION)
+ max_version = TLS1_1_VERSION;
+#endif
+#ifdef OPENSSL_NO_TLS1_1
+ if (max_version == TLS1_1_VERSION)
+ max_version = TLS1_VERSION;
+#endif
+#ifdef OPENSSL_NO_TLS1
+ if (max_version == TLS1_VERSION)
+ max_version = SSL3_VERSION;
+#endif
+#ifdef OPENSSL_NO_SSL3
+ if (min_version == SSL3_VERSION)
+ min_version = TLS1_VERSION;
+#endif
+#ifdef OPENSSL_NO_TLS1
+ if (min_version == TLS1_VERSION)
+ min_version = TLS1_1_VERSION;
+#endif
+#ifdef OPENSSL_NO_TLS1_1
+ if (min_version == TLS1_1_VERSION)
+ min_version = TLS1_2_VERSION;
+#endif
+ /* Done massaging versions; do the check. */
+ if (0
+#ifdef OPENSSL_NO_SSL3
+ || (min_version <= SSL3_VERSION && SSL3_VERSION <= max_version)
+#endif
+#ifdef OPENSSL_NO_TLS1
+ || (min_version <= TLS1_VERSION && TLS1_VERSION <= max_version)
+#endif
+#ifdef OPENSSL_NO_TLS1_1
+ || (min_version <= TLS1_1_VERSION && TLS1_1_VERSION <= max_version)
+#endif
+#ifdef OPENSSL_NO_TLS1_2
+ || (min_version <= TLS1_2_VERSION && TLS1_2_VERSION <= max_version)
+#endif
+ )
+ return 0;
+ }
+ return 1;
+}
+
+static void clear_ciphers(SSL *s)
+{
+ /* clear the current cipher */
+ ssl_clear_cipher_ctx(s);
+ ssl_clear_hash_ctx(&s->read_hash);
+ ssl_clear_hash_ctx(&s->write_hash);
+}
+
+int SSL_clear(SSL *s)
+{
+ if (s->method == NULL) {
+ SSLerr(SSL_F_SSL_CLEAR, SSL_R_NO_METHOD_SPECIFIED);
+ return (0);
+ }
+
+ if (ssl_clear_bad_session(s)) {
+ SSL_SESSION_free(s->session);
+ s->session = NULL;
+ }
+
+ s->error = 0;
+ s->hit = 0;
+ s->shutdown = 0;
+
+ if (s->renegotiate) {
+ SSLerr(SSL_F_SSL_CLEAR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ ossl_statem_clear(s);
+
+ s->version = s->method->version;
+ s->client_version = s->version;
+ s->rwstate = SSL_NOTHING;
+
+ BUF_MEM_free(s->init_buf);
+ s->init_buf = NULL;
+ clear_ciphers(s);
+ s->first_packet = 0;
+
+ /* Reset DANE verification result state */
+ s->dane.mdpth = -1;
+ s->dane.pdpth = -1;
+ X509_free(s->dane.mcert);
+ s->dane.mcert = NULL;
+ s->dane.mtlsa = NULL;
+
+ /* Clear the verification result peername */
+ X509_VERIFY_PARAM_move_peername(s->param, NULL);
+
+ /*
+ * Check to see if we were changed into a different method, if so, revert
+ * back if we are not doing session-id reuse.
+ */
+ if (!ossl_statem_get_in_handshake(s) && (s->session == NULL)
+ && (s->method != s->ctx->method)) {
+ s->method->ssl_free(s);
+ s->method = s->ctx->method;
+ if (!s->method->ssl_new(s))
+ return (0);
+ } else
+ s->method->ssl_clear(s);
+
+ RECORD_LAYER_clear(&s->rlayer);
+
+ return (1);
+}
+
+/** Used to change an SSL_CTXs default SSL method type */
+int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth)
+{
+ STACK_OF(SSL_CIPHER) *sk;
+
+ ctx->method = meth;
+
+ sk = ssl_create_cipher_list(ctx->method, &(ctx->cipher_list),
+ &(ctx->cipher_list_by_id),
+ SSL_DEFAULT_CIPHER_LIST, ctx->cert);
+ if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= 0)) {
+ SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION, SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS);
+ return (0);
+ }
+ return (1);
+}
+
+SSL *SSL_new(SSL_CTX *ctx)
+{
+ SSL *s;
+
+ if (ctx == NULL) {
+ SSLerr(SSL_F_SSL_NEW, SSL_R_NULL_SSL_CTX);
+ return (NULL);
+ }
+ if (ctx->method == NULL) {
+ SSLerr(SSL_F_SSL_NEW, SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION);
+ return (NULL);
+ }
+
+ s = OPENSSL_zalloc(sizeof(*s));
+ if (s == NULL)
+ goto err;
+
+ s->lock = CRYPTO_THREAD_lock_new();
+ if (s->lock == NULL) {
+ SSLerr(SSL_F_SSL_NEW, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(s);
+ return NULL;
+ }
+
+ RECORD_LAYER_init(&s->rlayer, s);
+
+ s->options = ctx->options;
+ s->dane.flags = ctx->dane.flags;
+ s->min_proto_version = ctx->min_proto_version;
+ s->max_proto_version = ctx->max_proto_version;
+ s->mode = ctx->mode;
+ s->max_cert_list = ctx->max_cert_list;
+ s->references = 1;
+
+ /*
+ * Earlier library versions used to copy the pointer to the CERT, not
+ * its contents; only when setting new parameters for the per-SSL
+ * copy, ssl_cert_new would be called (and the direct reference to
+ * the per-SSL_CTX settings would be lost, but those still were
+ * indirectly accessed for various purposes, and for that reason they
+ * used to be known as s->ctx->default_cert). Now we don't look at the
+ * SSL_CTX's CERT after having duplicated it once.
+ */
+ s->cert = ssl_cert_dup(ctx->cert);
+ if (s->cert == NULL)
+ goto err;
+
+ RECORD_LAYER_set_read_ahead(&s->rlayer, ctx->read_ahead);
+ s->msg_callback = ctx->msg_callback;
+ s->msg_callback_arg = ctx->msg_callback_arg;
+ s->verify_mode = ctx->verify_mode;
+ s->not_resumable_session_cb = ctx->not_resumable_session_cb;
+ s->sid_ctx_length = ctx->sid_ctx_length;
+ OPENSSL_assert(s->sid_ctx_length <= sizeof(s->sid_ctx));
+ memcpy(&s->sid_ctx, &ctx->sid_ctx, sizeof(s->sid_ctx));
+ s->verify_callback = ctx->default_verify_callback;
+ s->generate_session_id = ctx->generate_session_id;
+
+ s->param = X509_VERIFY_PARAM_new();
+ if (s->param == NULL)
+ goto err;
+ X509_VERIFY_PARAM_inherit(s->param, ctx->param);
+ s->quiet_shutdown = ctx->quiet_shutdown;
+ s->max_send_fragment = ctx->max_send_fragment;
+ s->split_send_fragment = ctx->split_send_fragment;
+ s->max_pipelines = ctx->max_pipelines;
+ if (s->max_pipelines > 1)
+ RECORD_LAYER_set_read_ahead(&s->rlayer, 1);
+ if (ctx->default_read_buf_len > 0)
+ SSL_set_default_read_buffer_len(s, ctx->default_read_buf_len);
+
+ SSL_CTX_up_ref(ctx);
+ s->ctx = ctx;
+ s->tlsext_debug_cb = 0;
+ s->tlsext_debug_arg = NULL;
+ s->tlsext_ticket_expected = 0;
+ s->tlsext_status_type = ctx->tlsext_status_type;
+ s->tlsext_status_expected = 0;
+ s->tlsext_ocsp_ids = NULL;
+ s->tlsext_ocsp_exts = NULL;
+ s->tlsext_ocsp_resp = NULL;
+ s->tlsext_ocsp_resplen = -1;
+ SSL_CTX_up_ref(ctx);
+ s->session_ctx = ctx;
+#ifndef OPENSSL_NO_EC
+ if (ctx->tlsext_ecpointformatlist) {
+ s->tlsext_ecpointformatlist =
+ OPENSSL_memdup(ctx->tlsext_ecpointformatlist,
+ ctx->tlsext_ecpointformatlist_length);
+ if (!s->tlsext_ecpointformatlist)
+ goto err;
+ s->tlsext_ecpointformatlist_length =
+ ctx->tlsext_ecpointformatlist_length;
+ }
+ if (ctx->tlsext_ellipticcurvelist) {
+ s->tlsext_ellipticcurvelist =
+ OPENSSL_memdup(ctx->tlsext_ellipticcurvelist,
+ ctx->tlsext_ellipticcurvelist_length);
+ if (!s->tlsext_ellipticcurvelist)
+ goto err;
+ s->tlsext_ellipticcurvelist_length =
+ ctx->tlsext_ellipticcurvelist_length;
+ }
+#endif
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ s->next_proto_negotiated = NULL;
+#endif
+
+ if (s->ctx->alpn_client_proto_list) {
+ s->alpn_client_proto_list =
+ OPENSSL_malloc(s->ctx->alpn_client_proto_list_len);
+ if (s->alpn_client_proto_list == NULL)
+ goto err;
+ memcpy(s->alpn_client_proto_list, s->ctx->alpn_client_proto_list,
+ s->ctx->alpn_client_proto_list_len);
+ s->alpn_client_proto_list_len = s->ctx->alpn_client_proto_list_len;
+ }
+
+ s->verified_chain = NULL;
+ s->verify_result = X509_V_OK;
+
+ s->default_passwd_callback = ctx->default_passwd_callback;
+ s->default_passwd_callback_userdata = ctx->default_passwd_callback_userdata;
+
+ s->method = ctx->method;
+
+ if (!s->method->ssl_new(s))
+ goto err;
+
+ s->server = (ctx->method->ssl_accept == ssl_undefined_function) ? 0 : 1;
+
+ if (!SSL_clear(s))
+ goto err;
+
+ if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data))
+ goto err;
+
+#ifndef OPENSSL_NO_PSK
+ s->psk_client_callback = ctx->psk_client_callback;
+ s->psk_server_callback = ctx->psk_server_callback;
+#endif
+
+ s->job = NULL;
+
+#ifndef OPENSSL_NO_CT
+ if (!SSL_set_ct_validation_callback(s, ctx->ct_validation_callback,
+ ctx->ct_validation_callback_arg))
+ goto err;
+#endif
+
+ return s;
+ err:
+ SSL_free(s);
+ SSLerr(SSL_F_SSL_NEW, ERR_R_MALLOC_FAILURE);
+ return NULL;
+}
+
+int SSL_is_dtls(const SSL *s)
+{
+ return SSL_IS_DTLS(s) ? 1 : 0;
+}
+
+int SSL_up_ref(SSL *s)
+{
+ int i;
+
+ if (CRYPTO_atomic_add(&s->references, 1, &i, s->lock) <= 0)
+ return 0;
+
+ REF_PRINT_COUNT("SSL", s);
+ REF_ASSERT_ISNT(i < 2);
+ return ((i > 1) ? 1 : 0);
+}
+
+int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const unsigned char *sid_ctx,
+ unsigned int sid_ctx_len)
+{
+ if (sid_ctx_len > sizeof(ctx->sid_ctx)) {
+ SSLerr(SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT,
+ SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
+ return 0;
+ }
+ ctx->sid_ctx_length = sid_ctx_len;
+ memcpy(ctx->sid_ctx, sid_ctx, sid_ctx_len);
+
+ return 1;
+}
+
+int SSL_set_session_id_context(SSL *ssl, const unsigned char *sid_ctx,
+ unsigned int sid_ctx_len)
+{
+ if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) {
+ SSLerr(SSL_F_SSL_SET_SESSION_ID_CONTEXT,
+ SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
+ return 0;
+ }
+ ssl->sid_ctx_length = sid_ctx_len;
+ memcpy(ssl->sid_ctx, sid_ctx, sid_ctx_len);
+
+ return 1;
+}
+
+int SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb)
+{
+ CRYPTO_THREAD_write_lock(ctx->lock);
+ ctx->generate_session_id = cb;
+ CRYPTO_THREAD_unlock(ctx->lock);
+ return 1;
+}
+
+int SSL_set_generate_session_id(SSL *ssl, GEN_SESSION_CB cb)
+{
+ CRYPTO_THREAD_write_lock(ssl->lock);
+ ssl->generate_session_id = cb;
+ CRYPTO_THREAD_unlock(ssl->lock);
+ return 1;
+}
+
+int SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id,
+ unsigned int id_len)
+{
+ /*
+ * A quick examination of SSL_SESSION_hash and SSL_SESSION_cmp shows how
+ * we can "construct" a session to give us the desired check - i.e. to
+ * find if there's a session in the hash table that would conflict with
+ * any new session built out of this id/id_len and the ssl_version in use
+ * by this SSL.
+ */
+ SSL_SESSION r, *p;
+
+ if (id_len > sizeof(r.session_id))
+ return 0;
+
+ r.ssl_version = ssl->version;
+ r.session_id_length = id_len;
+ memcpy(r.session_id, id, id_len);
+
+ CRYPTO_THREAD_read_lock(ssl->session_ctx->lock);
+ p = lh_SSL_SESSION_retrieve(ssl->session_ctx->sessions, &r);
+ CRYPTO_THREAD_unlock(ssl->session_ctx->lock);
+ return (p != NULL);
+}
+
+int SSL_CTX_set_purpose(SSL_CTX *s, int purpose)
+{
+ return X509_VERIFY_PARAM_set_purpose(s->param, purpose);
+}
+
+int SSL_set_purpose(SSL *s, int purpose)
+{
+ return X509_VERIFY_PARAM_set_purpose(s->param, purpose);
+}
+
+int SSL_CTX_set_trust(SSL_CTX *s, int trust)
+{
+ return X509_VERIFY_PARAM_set_trust(s->param, trust);
+}
+
+int SSL_set_trust(SSL *s, int trust)
+{
+ return X509_VERIFY_PARAM_set_trust(s->param, trust);
+}
+
+int SSL_set1_host(SSL *s, const char *hostname)
+{
+ return X509_VERIFY_PARAM_set1_host(s->param, hostname, 0);
+}
+
+int SSL_add1_host(SSL *s, const char *hostname)
+{
+ return X509_VERIFY_PARAM_add1_host(s->param, hostname, 0);
+}
+
+void SSL_set_hostflags(SSL *s, unsigned int flags)
+{
+ X509_VERIFY_PARAM_set_hostflags(s->param, flags);
+}
+
+const char *SSL_get0_peername(SSL *s)
+{
+ return X509_VERIFY_PARAM_get0_peername(s->param);
+}
+
+int SSL_CTX_dane_enable(SSL_CTX *ctx)
+{
+ return dane_ctx_enable(&ctx->dane);
+}
+
+unsigned long SSL_CTX_dane_set_flags(SSL_CTX *ctx, unsigned long flags)
+{
+ unsigned long orig = ctx->dane.flags;
+
+ ctx->dane.flags |= flags;
+ return orig;
+}
+
+unsigned long SSL_CTX_dane_clear_flags(SSL_CTX *ctx, unsigned long flags)
+{
+ unsigned long orig = ctx->dane.flags;
+
+ ctx->dane.flags &= ~flags;
+ return orig;
+}
+
+int SSL_dane_enable(SSL *s, const char *basedomain)
+{
+ SSL_DANE *dane = &s->dane;
+
+ if (s->ctx->dane.mdmax == 0) {
+ SSLerr(SSL_F_SSL_DANE_ENABLE, SSL_R_CONTEXT_NOT_DANE_ENABLED);
+ return 0;
+ }
+ if (dane->trecs != NULL) {
+ SSLerr(SSL_F_SSL_DANE_ENABLE, SSL_R_DANE_ALREADY_ENABLED);
+ return 0;
+ }
+
+ /*
+ * Default SNI name. This rejects empty names, while set1_host below
+ * accepts them and disables host name checks. To avoid side-effects with
+ * invalid input, set the SNI name first.
+ */
+ if (s->tlsext_hostname == NULL) {
+ if (!SSL_set_tlsext_host_name(s, basedomain)) {
+ SSLerr(SSL_F_SSL_DANE_ENABLE, SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN);
+ return -1;
+ }
+ }
+
+ /* Primary RFC6125 reference identifier */
+ if (!X509_VERIFY_PARAM_set1_host(s->param, basedomain, 0)) {
+ SSLerr(SSL_F_SSL_DANE_ENABLE, SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN);
+ return -1;
+ }
+
+ dane->mdpth = -1;
+ dane->pdpth = -1;
+ dane->dctx = &s->ctx->dane;
+ dane->trecs = sk_danetls_record_new_null();
+
+ if (dane->trecs == NULL) {
+ SSLerr(SSL_F_SSL_DANE_ENABLE, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ return 1;
+}
+
+unsigned long SSL_dane_set_flags(SSL *ssl, unsigned long flags)
+{
+ unsigned long orig = ssl->dane.flags;
+
+ ssl->dane.flags |= flags;
+ return orig;
+}
+
+unsigned long SSL_dane_clear_flags(SSL *ssl, unsigned long flags)
+{
+ unsigned long orig = ssl->dane.flags;
+
+ ssl->dane.flags &= ~flags;
+ return orig;
+}
+
+int SSL_get0_dane_authority(SSL *s, X509 **mcert, EVP_PKEY **mspki)
+{
+ SSL_DANE *dane = &s->dane;
+
+ if (!DANETLS_ENABLED(dane) || s->verify_result != X509_V_OK)
+ return -1;
+ if (dane->mtlsa) {
+ if (mcert)
+ *mcert = dane->mcert;
+ if (mspki)
+ *mspki = (dane->mcert == NULL) ? dane->mtlsa->spki : NULL;
+ }
+ return dane->mdpth;
+}
+
+int SSL_get0_dane_tlsa(SSL *s, uint8_t *usage, uint8_t *selector,
+ uint8_t *mtype, unsigned const char **data, size_t *dlen)
+{
+ SSL_DANE *dane = &s->dane;
+
+ if (!DANETLS_ENABLED(dane) || s->verify_result != X509_V_OK)
+ return -1;
+ if (dane->mtlsa) {
+ if (usage)
+ *usage = dane->mtlsa->usage;
+ if (selector)
+ *selector = dane->mtlsa->selector;
+ if (mtype)
+ *mtype = dane->mtlsa->mtype;
+ if (data)
+ *data = dane->mtlsa->data;
+ if (dlen)
+ *dlen = dane->mtlsa->dlen;
+ }
+ return dane->mdpth;
+}
+
+SSL_DANE *SSL_get0_dane(SSL *s)
+{
+ return &s->dane;
+}
+
+int SSL_dane_tlsa_add(SSL *s, uint8_t usage, uint8_t selector,
+ uint8_t mtype, unsigned const char *data, size_t dlen)
+{
+ return dane_tlsa_add(&s->dane, usage, selector, mtype, data, dlen);
+}
+
+int SSL_CTX_dane_mtype_set(SSL_CTX *ctx, const EVP_MD *md, uint8_t mtype,
+ uint8_t ord)
+{
+ return dane_mtype_set(&ctx->dane, md, mtype, ord);
+}
+
+int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm)
+{
+ return X509_VERIFY_PARAM_set1(ctx->param, vpm);
+}
+
+int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm)
+{
+ return X509_VERIFY_PARAM_set1(ssl->param, vpm);
+}
+
+X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx)
+{
+ return ctx->param;
+}
+
+X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl)
+{
+ return ssl->param;
+}
+
+void SSL_certs_clear(SSL *s)
+{
+ ssl_cert_clear_certs(s->cert);
+}
+
+void SSL_free(SSL *s)
+{
+ int i;
+
+ if (s == NULL)
+ return;
+
+ CRYPTO_atomic_add(&s->references, -1, &i, s->lock);
+ REF_PRINT_COUNT("SSL", s);
+ if (i > 0)
+ return;
+ REF_ASSERT_ISNT(i < 0);
+
+ X509_VERIFY_PARAM_free(s->param);
+ dane_final(&s->dane);
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data);
+
+ ssl_free_wbio_buffer(s);
+
+ BIO_free_all(s->wbio);
+ BIO_free_all(s->rbio);
+
+ BUF_MEM_free(s->init_buf);
+
+ /* add extra stuff */
+ sk_SSL_CIPHER_free(s->cipher_list);
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
+
+ /* Make the next call work :-) */
+ if (s->session != NULL) {
+ ssl_clear_bad_session(s);
+ SSL_SESSION_free(s->session);
+ }
+
+ clear_ciphers(s);
+
+ ssl_cert_free(s->cert);
+ /* Free up if allocated */
+
+ OPENSSL_free(s->tlsext_hostname);
+ SSL_CTX_free(s->session_ctx);
+#ifndef OPENSSL_NO_EC
+ OPENSSL_free(s->tlsext_ecpointformatlist);
+ OPENSSL_free(s->tlsext_ellipticcurvelist);
+#endif /* OPENSSL_NO_EC */
+ sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts, X509_EXTENSION_free);
+#ifndef OPENSSL_NO_OCSP
+ sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids, OCSP_RESPID_free);
+#endif
+#ifndef OPENSSL_NO_CT
+ SCT_LIST_free(s->scts);
+ OPENSSL_free(s->tlsext_scts);
+#endif
+ OPENSSL_free(s->tlsext_ocsp_resp);
+ OPENSSL_free(s->alpn_client_proto_list);
+
+ sk_X509_NAME_pop_free(s->client_CA, X509_NAME_free);
+
+ sk_X509_pop_free(s->verified_chain, X509_free);
+
+ if (s->method != NULL)
+ s->method->ssl_free(s);
+
+ RECORD_LAYER_release(&s->rlayer);
+
+ SSL_CTX_free(s->ctx);
+
+ ASYNC_WAIT_CTX_free(s->waitctx);
+
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
+ OPENSSL_free(s->next_proto_negotiated);
+#endif
+
+#ifndef OPENSSL_NO_SRTP
+ sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles);
+#endif
+
+ CRYPTO_THREAD_lock_free(s->lock);
+
+ OPENSSL_free(s);
+}
+
+void SSL_set0_rbio(SSL *s, BIO *rbio)
+{
+ BIO_free_all(s->rbio);
+ s->rbio = rbio;
+}
+
+void SSL_set0_wbio(SSL *s, BIO *wbio)
+{
+ /*
+ * If the output buffering BIO is still in place, remove it
+ */
+ if (s->bbio != NULL)
+ s->wbio = BIO_pop(s->wbio);
+
+ BIO_free_all(s->wbio);
+ s->wbio = wbio;
+
+ /* Re-attach |bbio| to the new |wbio|. */
+ if (s->bbio != NULL)
+ s->wbio = BIO_push(s->bbio, s->wbio);
+}
+
+void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio)
+{
+ /*
+ * For historical reasons, this function has many different cases in
+ * ownership handling.
+ */
+
+ /* If nothing has changed, do nothing */
+ if (rbio == SSL_get_rbio(s) && wbio == SSL_get_wbio(s))
+ return;
+
+ /*
+ * If the two arguments are equal then one fewer reference is granted by the
+ * caller than we want to take
+ */
+ if (rbio != NULL && rbio == wbio)
+ BIO_up_ref(rbio);
+
+ /*
+ * If only the wbio is changed only adopt one reference.
+ */
+ if (rbio == SSL_get_rbio(s)) {
+ SSL_set0_wbio(s, wbio);
+ return;
+ }
+ /*
+ * There is an asymmetry here for historical reasons. If only the rbio is
+ * changed AND the rbio and wbio were originally different, then we only
+ * adopt one reference.
+ */
+ if (wbio == SSL_get_wbio(s) && SSL_get_rbio(s) != SSL_get_wbio(s)) {
+ SSL_set0_rbio(s, rbio);
+ return;
+ }
+
+ /* Otherwise, adopt both references. */
+ SSL_set0_rbio(s, rbio);
+ SSL_set0_wbio(s, wbio);
+}
+
+BIO *SSL_get_rbio(const SSL *s)
+{
+ return s->rbio;
+}
+
+BIO *SSL_get_wbio(const SSL *s)
+{
+ if (s->bbio != NULL) {
+ /*
+ * If |bbio| is active, the true caller-configured BIO is its
+ * |next_bio|.
+ */
+ return BIO_next(s->bbio);
+ }
+ return s->wbio;
+}
+
+int SSL_get_fd(const SSL *s)
+{
+ return SSL_get_rfd(s);
+}
+
+int SSL_get_rfd(const SSL *s)
+{
+ int ret = -1;
+ BIO *b, *r;
+
+ b = SSL_get_rbio(s);
+ r = BIO_find_type(b, BIO_TYPE_DESCRIPTOR);
+ if (r != NULL)
+ BIO_get_fd(r, &ret);
+ return (ret);
+}
+
+int SSL_get_wfd(const SSL *s)
+{
+ int ret = -1;
+ BIO *b, *r;
+
+ b = SSL_get_wbio(s);
+ r = BIO_find_type(b, BIO_TYPE_DESCRIPTOR);
+ if (r != NULL)
+ BIO_get_fd(r, &ret);
+ return (ret);
+}
+
+#ifndef OPENSSL_NO_SOCK
+int SSL_set_fd(SSL *s, int fd)
+{
+ int ret = 0;
+ BIO *bio = NULL;
+
+ bio = BIO_new(BIO_s_socket());
+
+ if (bio == NULL) {
+ SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
+ goto err;
+ }
+ BIO_set_fd(bio, fd, BIO_NOCLOSE);
+ SSL_set_bio(s, bio, bio);
+ ret = 1;
+ err:
+ return (ret);
+}
+
+int SSL_set_wfd(SSL *s, int fd)
+{
+ BIO *rbio = SSL_get_rbio(s);
+
+ if (rbio == NULL || BIO_method_type(rbio) != BIO_TYPE_SOCKET
+ || (int)BIO_get_fd(rbio, NULL) != fd) {
+ BIO *bio = BIO_new(BIO_s_socket());
+
+ if (bio == NULL) {
+ SSLerr(SSL_F_SSL_SET_WFD, ERR_R_BUF_LIB);
+ return 0;
+ }
+ BIO_set_fd(bio, fd, BIO_NOCLOSE);
+ SSL_set0_wbio(s, bio);
+ } else {
+ BIO_up_ref(rbio);
+ SSL_set0_wbio(s, rbio);
+ }
+ return 1;
+}
+
+int SSL_set_rfd(SSL *s, int fd)
+{
+ BIO *wbio = SSL_get_wbio(s);
+
+ if (wbio == NULL || BIO_method_type(wbio) != BIO_TYPE_SOCKET
+ || ((int)BIO_get_fd(wbio, NULL) != fd)) {
+ BIO *bio = BIO_new(BIO_s_socket());
+
+ if (bio == NULL) {
+ SSLerr(SSL_F_SSL_SET_RFD, ERR_R_BUF_LIB);
+ return 0;
+ }
+ BIO_set_fd(bio, fd, BIO_NOCLOSE);
+ SSL_set0_rbio(s, bio);
+ } else {
+ BIO_up_ref(wbio);
+ SSL_set0_rbio(s, wbio);
+ }
+
+ return 1;
+}
+#endif
+
+/* return length of latest Finished message we sent, copy to 'buf' */
+size_t SSL_get_finished(const SSL *s, void *buf, size_t count)
+{
+ size_t ret = 0;
+
+ if (s->s3 != NULL) {
+ ret = s->s3->tmp.finish_md_len;
+ if (count > ret)
+ count = ret;
+ memcpy(buf, s->s3->tmp.finish_md, count);
+ }
+ return ret;
+}
+
+/* return length of latest Finished message we expected, copy to 'buf' */
+size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count)
+{
+ size_t ret = 0;
+
+ if (s->s3 != NULL) {
+ ret = s->s3->tmp.peer_finish_md_len;
+ if (count > ret)
+ count = ret;
+ memcpy(buf, s->s3->tmp.peer_finish_md, count);
+ }
+ return ret;
+}
+
+int SSL_get_verify_mode(const SSL *s)
+{
+ return (s->verify_mode);
+}
+
+int SSL_get_verify_depth(const SSL *s)
+{
+ return X509_VERIFY_PARAM_get_depth(s->param);
+}
+
+int (*SSL_get_verify_callback(const SSL *s)) (int, X509_STORE_CTX *) {
+ return (s->verify_callback);
+}
+
+int SSL_CTX_get_verify_mode(const SSL_CTX *ctx)
+{
+ return (ctx->verify_mode);
+}
+
+int SSL_CTX_get_verify_depth(const SSL_CTX *ctx)
+{
+ return X509_VERIFY_PARAM_get_depth(ctx->param);
+}
+
+int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx)) (int, X509_STORE_CTX *) {
+ return (ctx->default_verify_callback);
+}
+
+void SSL_set_verify(SSL *s, int mode,
+ int (*callback) (int ok, X509_STORE_CTX *ctx))
+{
+ s->verify_mode = mode;
+ if (callback != NULL)
+ s->verify_callback = callback;
+}
+
+void SSL_set_verify_depth(SSL *s, int depth)
+{
+ X509_VERIFY_PARAM_set_depth(s->param, depth);
+}
+
+void SSL_set_read_ahead(SSL *s, int yes)
+{
+ RECORD_LAYER_set_read_ahead(&s->rlayer, yes);
+}
+
+int SSL_get_read_ahead(const SSL *s)
+{
+ return RECORD_LAYER_get_read_ahead(&s->rlayer);
+}
+
+int SSL_pending(const SSL *s)
+{
+ /*
+ * SSL_pending cannot work properly if read-ahead is enabled
+ * (SSL_[CTX_]ctrl(..., SSL_CTRL_SET_READ_AHEAD, 1, NULL)), and it is
+ * impossible to fix since SSL_pending cannot report errors that may be
+ * observed while scanning the new data. (Note that SSL_pending() is
+ * often used as a boolean value, so we'd better not return -1.)
+ */
+ return (s->method->ssl_pending(s));
+}
+
+int SSL_has_pending(const SSL *s)
+{
+ /*
+ * Similar to SSL_pending() but returns a 1 to indicate that we have
+ * unprocessed data available or 0 otherwise (as opposed to the number of
+ * bytes available). Unlike SSL_pending() this will take into account
+ * read_ahead data. A 1 return simply indicates that we have unprocessed
+ * data. That data may not result in any application data, or we may fail
+ * to parse the records for some reason.
+ */
+ if (RECORD_LAYER_processed_read_pending(&s->rlayer))
+ return 1;
+
+ return RECORD_LAYER_read_pending(&s->rlayer);
+}
+
+X509 *SSL_get_peer_certificate(const SSL *s)
+{
+ X509 *r;
+
+ if ((s == NULL) || (s->session == NULL))
+ r = NULL;
+ else
+ r = s->session->peer;
+
+ if (r == NULL)
+ return (r);
+
+ X509_up_ref(r);
+
+ return (r);
+}
+
+STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s)
+{
+ STACK_OF(X509) *r;
+
+ if ((s == NULL) || (s->session == NULL))
+ r = NULL;
+ else
+ r = s->session->peer_chain;
+
+ /*
+ * If we are a client, cert_chain includes the peer's own certificate; if
+ * we are a server, it does not.
+ */
+
+ return (r);
+}
+
+/*
+ * Now in theory, since the calling process own 't' it should be safe to
+ * modify. We need to be able to read f without being hassled
+ */
+int SSL_copy_session_id(SSL *t, const SSL *f)
+{
+ int i;
+ /* Do we need to to SSL locking? */
+ if (!SSL_set_session(t, SSL_get_session(f))) {
+ return 0;
+ }
+
+ /*
+ * what if we are setup for one protocol version but want to talk another
+ */
+ if (t->method != f->method) {
+ t->method->ssl_free(t);
+ t->method = f->method;
+ if (t->method->ssl_new(t) == 0)
+ return 0;
+ }
+
+ CRYPTO_atomic_add(&f->cert->references, 1, &i, f->cert->lock);
+ ssl_cert_free(t->cert);
+ t->cert = f->cert;
+ if (!SSL_set_session_id_context(t, f->sid_ctx, f->sid_ctx_length)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Fix this so it checks all the valid key/cert options */
+int SSL_CTX_check_private_key(const SSL_CTX *ctx)
+{
+ if ((ctx == NULL) || (ctx->cert->key->x509 == NULL)) {
+ SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY, SSL_R_NO_CERTIFICATE_ASSIGNED);
+ return (0);
+ }
+ if (ctx->cert->key->privatekey == NULL) {
+ SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY, SSL_R_NO_PRIVATE_KEY_ASSIGNED);
+ return (0);
+ }
+ return (X509_check_private_key
+ (ctx->cert->key->x509, ctx->cert->key->privatekey));
+}
+
+/* Fix this function so that it takes an optional type parameter */
+int SSL_check_private_key(const SSL *ssl)
+{
+ if (ssl == NULL) {
+ SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY, ERR_R_PASSED_NULL_PARAMETER);
+ return (0);
+ }
+ if (ssl->cert->key->x509 == NULL) {
+ SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY, SSL_R_NO_CERTIFICATE_ASSIGNED);
+ return (0);
+ }
+ if (ssl->cert->key->privatekey == NULL) {
+ SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY, SSL_R_NO_PRIVATE_KEY_ASSIGNED);
+ return (0);
+ }
+ return (X509_check_private_key(ssl->cert->key->x509,
+ ssl->cert->key->privatekey));
+}
+
+int SSL_waiting_for_async(SSL *s)
+{
+ if (s->job)
+ return 1;
+
+ return 0;
+}
+
+int SSL_get_all_async_fds(SSL *s, OSSL_ASYNC_FD *fds, size_t *numfds)
+{
+ ASYNC_WAIT_CTX *ctx = s->waitctx;
+
+ if (ctx == NULL)
+ return 0;
+ return ASYNC_WAIT_CTX_get_all_fds(ctx, fds, numfds);
+}
+
+int SSL_get_changed_async_fds(SSL *s, OSSL_ASYNC_FD *addfd, size_t *numaddfds,
+ OSSL_ASYNC_FD *delfd, size_t *numdelfds)
+{
+ ASYNC_WAIT_CTX *ctx = s->waitctx;
+
+ if (ctx == NULL)
+ return 0;
+ return ASYNC_WAIT_CTX_get_changed_fds(ctx, addfd, numaddfds, delfd,
+ numdelfds);
+}
+
+int SSL_accept(SSL *s)
+{
+ if (s->handshake_func == NULL) {
+ /* Not properly initialized yet */
+ SSL_set_accept_state(s);
+ }
+
+ return SSL_do_handshake(s);
+}
+
+int SSL_connect(SSL *s)
+{
+ if (s->handshake_func == NULL) {
+ /* Not properly initialized yet */
+ SSL_set_connect_state(s);
+ }
+
+ return SSL_do_handshake(s);
+}
+
+long SSL_get_default_timeout(const SSL *s)
+{
+ return (s->method->get_timeout());
+}
+
+static int ssl_start_async_job(SSL *s, struct ssl_async_args *args,
+ int (*func) (void *))
+{
+ int ret;
+ if (s->waitctx == NULL) {
+ s->waitctx = ASYNC_WAIT_CTX_new();
+ if (s->waitctx == NULL)
+ return -1;
+ }
+ switch (ASYNC_start_job(&s->job, s->waitctx, &ret, func, args,
+ sizeof(struct ssl_async_args))) {
+ case ASYNC_ERR:
+ s->rwstate = SSL_NOTHING;
+ SSLerr(SSL_F_SSL_START_ASYNC_JOB, SSL_R_FAILED_TO_INIT_ASYNC);
+ return -1;
+ case ASYNC_PAUSE:
+ s->rwstate = SSL_ASYNC_PAUSED;
+ return -1;
+ case ASYNC_NO_JOBS:
+ s->rwstate = SSL_ASYNC_NO_JOBS;
+ return -1;
+ case ASYNC_FINISH:
+ s->job = NULL;
+ return ret;
+ default:
+ s->rwstate = SSL_NOTHING;
+ SSLerr(SSL_F_SSL_START_ASYNC_JOB, ERR_R_INTERNAL_ERROR);
+ /* Shouldn't happen */
+ return -1;
+ }
+}
+
+static int ssl_io_intern(void *vargs)
+{
+ struct ssl_async_args *args;
+ SSL *s;
+ void *buf;
+ int num;
+
+ args = (struct ssl_async_args *)vargs;
+ s = args->s;
+ buf = args->buf;
+ num = args->num;
+ switch (args->type) {
+ case READFUNC:
+ return args->f.func_read(s, buf, num);
+ case WRITEFUNC:
+ return args->f.func_write(s, buf, num);
+ case OTHERFUNC:
+ return args->f.func_other(s);
+ }
+ return -1;
+}
+
+int SSL_read(SSL *s, void *buf, int num)
+{
+ if (s->handshake_func == NULL) {
+ SSLerr(SSL_F_SSL_READ, SSL_R_UNINITIALIZED);
+ return -1;
+ }
+
+ if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
+ s->rwstate = SSL_NOTHING;
+ return (0);
+ }
+
+ if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
+ struct ssl_async_args args;
+
+ args.s = s;
+ args.buf = buf;
+ args.num = num;
+ args.type = READFUNC;
+ args.f.func_read = s->method->ssl_read;
+
+ return ssl_start_async_job(s, &args, ssl_io_intern);
+ } else {
+ return s->method->ssl_read(s, buf, num);
+ }
+}
+
+int SSL_peek(SSL *s, void *buf, int num)
+{
+ if (s->handshake_func == NULL) {
+ SSLerr(SSL_F_SSL_PEEK, SSL_R_UNINITIALIZED);
+ return -1;
+ }
+
+ if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
+ return (0);
+ }
+ if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
+ struct ssl_async_args args;
+
+ args.s = s;
+ args.buf = buf;
+ args.num = num;
+ args.type = READFUNC;
+ args.f.func_read = s->method->ssl_peek;
+
+ return ssl_start_async_job(s, &args, ssl_io_intern);
+ } else {
+ return s->method->ssl_peek(s, buf, num);
+ }
+}
+
+int SSL_write(SSL *s, const void *buf, int num)
+{
+ if (s->handshake_func == NULL) {
+ SSLerr(SSL_F_SSL_WRITE, SSL_R_UNINITIALIZED);
+ return -1;
+ }
+
+ if (s->shutdown & SSL_SENT_SHUTDOWN) {
+ s->rwstate = SSL_NOTHING;
+ SSLerr(SSL_F_SSL_WRITE, SSL_R_PROTOCOL_IS_SHUTDOWN);
+ return (-1);
+ }
+
+ if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
+ struct ssl_async_args args;
+
+ args.s = s;
+ args.buf = (void *)buf;
+ args.num = num;
+ args.type = WRITEFUNC;
+ args.f.func_write = s->method->ssl_write;
+
+ return ssl_start_async_job(s, &args, ssl_io_intern);
+ } else {
+ return s->method->ssl_write(s, buf, num);
+ }
+}
+
+int SSL_shutdown(SSL *s)
+{
+ /*
+ * Note that this function behaves differently from what one might
+ * expect. Return values are 0 for no success (yet), 1 for success; but
+ * calling it once is usually not enough, even if blocking I/O is used
+ * (see ssl3_shutdown).
+ */
+
+ if (s->handshake_func == NULL) {
+ SSLerr(SSL_F_SSL_SHUTDOWN, SSL_R_UNINITIALIZED);
+ return -1;
+ }
+
+ if (!SSL_in_init(s)) {
+ if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
+ struct ssl_async_args args;
+
+ args.s = s;
+ args.type = OTHERFUNC;
+ args.f.func_other = s->method->ssl_shutdown;
+
+ return ssl_start_async_job(s, &args, ssl_io_intern);
+ } else {
+ return s->method->ssl_shutdown(s);
+ }
+ } else {
+ SSLerr(SSL_F_SSL_SHUTDOWN, SSL_R_SHUTDOWN_WHILE_IN_INIT);
+ return -1;
+ }
+}
+
+int SSL_renegotiate(SSL *s)
+{
+ if ((s->options & SSL_OP_NO_RENEGOTIATION)) {
+ SSLerr(SSL_F_SSL_RENEGOTIATE, SSL_R_NO_RENEGOTIATION);
+ return 0;
+ }
+
+ if (s->renegotiate == 0)
+ s->renegotiate = 1;
+
+ s->new_session = 1;
+
+ return (s->method->ssl_renegotiate(s));
+}
+
+int SSL_renegotiate_abbreviated(SSL *s)
+{
+ if ((s->options & SSL_OP_NO_RENEGOTIATION)) {
+ SSLerr(SSL_F_SSL_RENEGOTIATE_ABBREVIATED, SSL_R_NO_RENEGOTIATION);
+ return 0;
+ }
+
+ if (s->renegotiate == 0)
+ s->renegotiate = 1;
+
+ s->new_session = 0;
+
+ return (s->method->ssl_renegotiate(s));
+}
+
+int SSL_renegotiate_pending(SSL *s)
+{
+ /*
+ * becomes true when negotiation is requested; false again once a
+ * handshake has finished
+ */
+ return (s->renegotiate != 0);
+}
+
+long SSL_ctrl(SSL *s, int cmd, long larg, void *parg)
+{
+ long l;
+
+ switch (cmd) {
+ case SSL_CTRL_GET_READ_AHEAD:
+ return (RECORD_LAYER_get_read_ahead(&s->rlayer));
+ case SSL_CTRL_SET_READ_AHEAD:
+ l = RECORD_LAYER_get_read_ahead(&s->rlayer);
+ RECORD_LAYER_set_read_ahead(&s->rlayer, larg);
+ return (l);
+
+ case SSL_CTRL_SET_MSG_CALLBACK_ARG:
+ s->msg_callback_arg = parg;
+ return 1;
+
+ case SSL_CTRL_MODE:
+ return (s->mode |= larg);
+ case SSL_CTRL_CLEAR_MODE:
+ return (s->mode &= ~larg);
+ case SSL_CTRL_GET_MAX_CERT_LIST:
+ return (s->max_cert_list);
+ case SSL_CTRL_SET_MAX_CERT_LIST:
+ l = s->max_cert_list;
+ s->max_cert_list = larg;
+ return (l);
+ case SSL_CTRL_SET_MAX_SEND_FRAGMENT:
+ if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH)
+ return 0;
+ s->max_send_fragment = larg;
+ if (s->max_send_fragment < s->split_send_fragment)
+ s->split_send_fragment = s->max_send_fragment;
+ return 1;
+ case SSL_CTRL_SET_SPLIT_SEND_FRAGMENT:
+ if ((unsigned int)larg > s->max_send_fragment || larg == 0)
+ return 0;
+ s->split_send_fragment = larg;
+ return 1;
+ case SSL_CTRL_SET_MAX_PIPELINES:
+ if (larg < 1 || larg > SSL_MAX_PIPELINES)
+ return 0;
+ s->max_pipelines = larg;
+ if (larg > 1)
+ RECORD_LAYER_set_read_ahead(&s->rlayer, 1);
+ return 1;
+ case SSL_CTRL_GET_RI_SUPPORT:
+ if (s->s3)
+ return s->s3->send_connection_binding;
+ else
+ return 0;
+ case SSL_CTRL_CERT_FLAGS:
+ return (s->cert->cert_flags |= larg);
+ case SSL_CTRL_CLEAR_CERT_FLAGS:
+ return (s->cert->cert_flags &= ~larg);
+
+ case SSL_CTRL_GET_RAW_CIPHERLIST:
+ if (parg) {
+ if (s->s3->tmp.ciphers_raw == NULL)
+ return 0;
+ *(unsigned char **)parg = s->s3->tmp.ciphers_raw;
+ return (int)s->s3->tmp.ciphers_rawlen;
+ } else {
+ return TLS_CIPHER_LEN;
+ }
+ case SSL_CTRL_GET_EXTMS_SUPPORT:
+ if (!s->session || SSL_in_init(s) || ossl_statem_get_in_handshake(s))
+ return -1;
+ if (s->session->flags & SSL_SESS_FLAG_EXTMS)
+ return 1;
+ else
+ return 0;
+ case SSL_CTRL_SET_MIN_PROTO_VERSION:
+ return ssl_check_allowed_versions(larg, s->max_proto_version)
+ && ssl_set_version_bound(s->ctx->method->version, (int)larg,
+ &s->min_proto_version);
+ case SSL_CTRL_GET_MIN_PROTO_VERSION:
+ return s->min_proto_version;
+ case SSL_CTRL_SET_MAX_PROTO_VERSION:
+ return ssl_check_allowed_versions(s->min_proto_version, larg)
+ && ssl_set_version_bound(s->ctx->method->version, (int)larg,
+ &s->max_proto_version);
+ case SSL_CTRL_GET_MAX_PROTO_VERSION:
+ return s->max_proto_version;
+ default:
+ return (s->method->ssl_ctrl(s, cmd, larg, parg));
+ }
+}
+
+long SSL_callback_ctrl(SSL *s, int cmd, void (*fp) (void))
+{
+ switch (cmd) {
+ case SSL_CTRL_SET_MSG_CALLBACK:
+ s->msg_callback = (void (*)
+ (int write_p, int version, int content_type,
+ const void *buf, size_t len, SSL *ssl,
+ void *arg))(fp);
+ return 1;
+
+ default:
+ return (s->method->ssl_callback_ctrl(s, cmd, fp));
+ }
+}
+
+LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx)
+{
+ return ctx->sessions;
+}
+
+long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
+{
+ long l;
+ /* For some cases with ctx == NULL perform syntax checks */
+ if (ctx == NULL) {
+ switch (cmd) {
+#ifndef OPENSSL_NO_EC
+ case SSL_CTRL_SET_CURVES_LIST:
+ return tls1_set_curves_list(NULL, NULL, parg);
+#endif
+ case SSL_CTRL_SET_SIGALGS_LIST:
+ case SSL_CTRL_SET_CLIENT_SIGALGS_LIST:
+ return tls1_set_sigalgs_list(NULL, parg, 0);
+ default:
+ return 0;
+ }
+ }
+
+ switch (cmd) {
+ case SSL_CTRL_GET_READ_AHEAD:
+ return (ctx->read_ahead);
+ case SSL_CTRL_SET_READ_AHEAD:
+ l = ctx->read_ahead;
+ ctx->read_ahead = larg;
+ return (l);
+
+ case SSL_CTRL_SET_MSG_CALLBACK_ARG:
+ ctx->msg_callback_arg = parg;
+ return 1;
+
+ case SSL_CTRL_GET_MAX_CERT_LIST:
+ return (ctx->max_cert_list);
+ case SSL_CTRL_SET_MAX_CERT_LIST:
+ l = ctx->max_cert_list;
+ ctx->max_cert_list = larg;
+ return (l);
+
+ case SSL_CTRL_SET_SESS_CACHE_SIZE:
+ l = ctx->session_cache_size;
+ ctx->session_cache_size = larg;
+ return (l);
+ case SSL_CTRL_GET_SESS_CACHE_SIZE:
+ return (ctx->session_cache_size);
+ case SSL_CTRL_SET_SESS_CACHE_MODE:
+ l = ctx->session_cache_mode;
+ ctx->session_cache_mode = larg;
+ return (l);
+ case SSL_CTRL_GET_SESS_CACHE_MODE:
+ return (ctx->session_cache_mode);
+
+ case SSL_CTRL_SESS_NUMBER:
+ return (lh_SSL_SESSION_num_items(ctx->sessions));
+ case SSL_CTRL_SESS_CONNECT:
+ return (ctx->stats.sess_connect);
+ case SSL_CTRL_SESS_CONNECT_GOOD:
+ return (ctx->stats.sess_connect_good);
+ case SSL_CTRL_SESS_CONNECT_RENEGOTIATE:
+ return (ctx->stats.sess_connect_renegotiate);
+ case SSL_CTRL_SESS_ACCEPT:
+ return (ctx->stats.sess_accept);
+ case SSL_CTRL_SESS_ACCEPT_GOOD:
+ return (ctx->stats.sess_accept_good);
+ case SSL_CTRL_SESS_ACCEPT_RENEGOTIATE:
+ return (ctx->stats.sess_accept_renegotiate);
+ case SSL_CTRL_SESS_HIT:
+ return (ctx->stats.sess_hit);
+ case SSL_CTRL_SESS_CB_HIT:
+ return (ctx->stats.sess_cb_hit);
+ case SSL_CTRL_SESS_MISSES:
+ return (ctx->stats.sess_miss);
+ case SSL_CTRL_SESS_TIMEOUTS:
+ return (ctx->stats.sess_timeout);
+ case SSL_CTRL_SESS_CACHE_FULL:
+ return (ctx->stats.sess_cache_full);
+ case SSL_CTRL_MODE:
+ return (ctx->mode |= larg);
+ case SSL_CTRL_CLEAR_MODE:
+ return (ctx->mode &= ~larg);
+ case SSL_CTRL_SET_MAX_SEND_FRAGMENT:
+ if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH)
+ return 0;
+ ctx->max_send_fragment = larg;
+ if (ctx->max_send_fragment < ctx->split_send_fragment)
+ ctx->split_send_fragment = ctx->max_send_fragment;
+ return 1;
+ case SSL_CTRL_SET_SPLIT_SEND_FRAGMENT:
+ if ((unsigned int)larg > ctx->max_send_fragment || larg == 0)
+ return 0;
+ ctx->split_send_fragment = larg;
+ return 1;
+ case SSL_CTRL_SET_MAX_PIPELINES:
+ if (larg < 1 || larg > SSL_MAX_PIPELINES)
+ return 0;
+ ctx->max_pipelines = larg;
+ return 1;
+ case SSL_CTRL_CERT_FLAGS:
+ return (ctx->cert->cert_flags |= larg);
+ case SSL_CTRL_CLEAR_CERT_FLAGS:
+ return (ctx->cert->cert_flags &= ~larg);
+ case SSL_CTRL_SET_MIN_PROTO_VERSION:
+ return ssl_check_allowed_versions(larg, ctx->max_proto_version)
+ && ssl_set_version_bound(ctx->method->version, (int)larg,
+ &ctx->min_proto_version);
+ case SSL_CTRL_GET_MIN_PROTO_VERSION:
+ return ctx->min_proto_version;
+ case SSL_CTRL_SET_MAX_PROTO_VERSION:
+ return ssl_check_allowed_versions(ctx->min_proto_version, larg)
+ && ssl_set_version_bound(ctx->method->version, (int)larg,
+ &ctx->max_proto_version);
+ case SSL_CTRL_GET_MAX_PROTO_VERSION:
+ return ctx->max_proto_version;
+ default:
+ return (ctx->method->ssl_ctx_ctrl(ctx, cmd, larg, parg));
+ }
+}
+
+long SSL_CTX_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp) (void))
+{
+ switch (cmd) {
+ case SSL_CTRL_SET_MSG_CALLBACK:
+ ctx->msg_callback = (void (*)
+ (int write_p, int version, int content_type,
+ const void *buf, size_t len, SSL *ssl,
+ void *arg))(fp);
+ return 1;
+
+ default:
+ return (ctx->method->ssl_ctx_callback_ctrl(ctx, cmd, fp));
+ }
+}
+
+int ssl_cipher_id_cmp(const SSL_CIPHER *a, const SSL_CIPHER *b)
+{
+ if (a->id > b->id)
+ return 1;
+ if (a->id < b->id)
+ return -1;
+ return 0;
+}
+
+int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap,
+ const SSL_CIPHER *const *bp)
+{
+ if ((*ap)->id > (*bp)->id)
+ return 1;
+ if ((*ap)->id < (*bp)->id)
+ return -1;
+ return 0;
+}
+
+/** return a STACK of the ciphers available for the SSL and in order of
+ * preference */
+STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s)
+{
+ if (s != NULL) {
+ if (s->cipher_list != NULL) {
+ return (s->cipher_list);
+ } else if ((s->ctx != NULL) && (s->ctx->cipher_list != NULL)) {
+ return (s->ctx->cipher_list);
+ }
+ }
+ return (NULL);
+}
+
+STACK_OF(SSL_CIPHER) *SSL_get_client_ciphers(const SSL *s)
+{
+ if ((s == NULL) || (s->session == NULL) || !s->server)
+ return NULL;
+ return s->session->ciphers;
+}
+
+STACK_OF(SSL_CIPHER) *SSL_get1_supported_ciphers(SSL *s)
+{
+ STACK_OF(SSL_CIPHER) *sk = NULL, *ciphers;
+ int i;
+ ciphers = SSL_get_ciphers(s);
+ if (!ciphers)
+ return NULL;
+ ssl_set_client_disabled(s);
+ for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
+ const SSL_CIPHER *c = sk_SSL_CIPHER_value(ciphers, i);
+ if (!ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0)) {
+ if (!sk)
+ sk = sk_SSL_CIPHER_new_null();
+ if (!sk)
+ return NULL;
+ if (!sk_SSL_CIPHER_push(sk, c)) {
+ sk_SSL_CIPHER_free(sk);
+ return NULL;
+ }
+ }
+ }
+ return sk;
+}
+
+/** return a STACK of the ciphers available for the SSL and in order of
+ * algorithm id */
+STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s)
+{
+ if (s != NULL) {
+ if (s->cipher_list_by_id != NULL) {
+ return (s->cipher_list_by_id);
+ } else if ((s->ctx != NULL) && (s->ctx->cipher_list_by_id != NULL)) {
+ return (s->ctx->cipher_list_by_id);
+ }
+ }
+ return (NULL);
+}
+
+/** The old interface to get the same thing as SSL_get_ciphers() */
+const char *SSL_get_cipher_list(const SSL *s, int n)
+{
+ const SSL_CIPHER *c;
+ STACK_OF(SSL_CIPHER) *sk;
+
+ if (s == NULL)
+ return (NULL);
+ sk = SSL_get_ciphers(s);
+ if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= n))
+ return (NULL);
+ c = sk_SSL_CIPHER_value(sk, n);
+ if (c == NULL)
+ return (NULL);
+ return (c->name);
+}
+
+/** return a STACK of the ciphers available for the SSL_CTX and in order of
+ * preference */
+STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx)
+{
+ if (ctx != NULL)
+ return ctx->cipher_list;
+ return NULL;
+}
+
+/** specify the ciphers to be used by default by the SSL_CTX */
+int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str)
+{
+ STACK_OF(SSL_CIPHER) *sk;
+
+ sk = ssl_create_cipher_list(ctx->method, &ctx->cipher_list,
+ &ctx->cipher_list_by_id, str, ctx->cert);
+ /*
+ * ssl_create_cipher_list may return an empty stack if it was unable to
+ * find a cipher matching the given rule string (for example if the rule
+ * string specifies a cipher which has been disabled). This is not an
+ * error as far as ssl_create_cipher_list is concerned, and hence
+ * ctx->cipher_list and ctx->cipher_list_by_id has been updated.
+ */
+ if (sk == NULL)
+ return 0;
+ else if (sk_SSL_CIPHER_num(sk) == 0) {
+ SSLerr(SSL_F_SSL_CTX_SET_CIPHER_LIST, SSL_R_NO_CIPHER_MATCH);
+ return 0;
+ }
+ return 1;
+}
+
+/** specify the ciphers to be used by the SSL */
+int SSL_set_cipher_list(SSL *s, const char *str)
+{
+ STACK_OF(SSL_CIPHER) *sk;
+
+ sk = ssl_create_cipher_list(s->ctx->method, &s->cipher_list,
+ &s->cipher_list_by_id, str, s->cert);
+ /* see comment in SSL_CTX_set_cipher_list */
+ if (sk == NULL)
+ return 0;
+ else if (sk_SSL_CIPHER_num(sk) == 0) {
+ SSLerr(SSL_F_SSL_SET_CIPHER_LIST, SSL_R_NO_CIPHER_MATCH);
+ return 0;
+ }
+ return 1;
+}
+
+char *SSL_get_shared_ciphers(const SSL *s, char *buf, int len)
+{
+ char *p;
+ STACK_OF(SSL_CIPHER) *sk;
+ const SSL_CIPHER *c;
+ int i;
+
+ if ((s->session == NULL) || (s->session->ciphers == NULL) || (len < 2))
+ return (NULL);
+
+ p = buf;
+ sk = s->session->ciphers;
+
+ if (sk_SSL_CIPHER_num(sk) == 0)
+ return NULL;
+
+ for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
+ int n;
+
+ c = sk_SSL_CIPHER_value(sk, i);
+ n = strlen(c->name);
+ if (n + 1 > len) {
+ if (p != buf)
+ --p;
+ *p = '\0';
+ return buf;
+ }
+ memcpy(p, c->name, n + 1);
+ p += n;
+ *(p++) = ':';
+ len -= n + 1;
+ }
+ p[-1] = '\0';
+ return (buf);
+}
+
+/** return a servername extension value if provided in Client Hello, or NULL.
+ * So far, only host_name types are defined (RFC 3546).
+ */
+
+const char *SSL_get_servername(const SSL *s, const int type)
+{
+ if (type != TLSEXT_NAMETYPE_host_name)
+ return NULL;
+
+ return s->session && !s->tlsext_hostname ?
+ s->session->tlsext_hostname : s->tlsext_hostname;
+}
+
+int SSL_get_servername_type(const SSL *s)
+{
+ if (s->session
+ && (!s->tlsext_hostname ? s->session->
+ tlsext_hostname : s->tlsext_hostname))
+ return TLSEXT_NAMETYPE_host_name;
+ return -1;
+}
+
+/*
+ * SSL_select_next_proto implements the standard protocol selection. It is
+ * expected that this function is called from the callback set by
+ * SSL_CTX_set_next_proto_select_cb. The protocol data is assumed to be a
+ * vector of 8-bit, length prefixed byte strings. The length byte itself is
+ * not included in the length. A byte string of length 0 is invalid. No byte
+ * string may be truncated. The current, but experimental algorithm for
+ * selecting the protocol is: 1) If the server doesn't support NPN then this
+ * is indicated to the callback. In this case, the client application has to
+ * abort the connection or have a default application level protocol. 2) If
+ * the server supports NPN, but advertises an empty list then the client
+ * selects the first protocol in its list, but indicates via the API that this
+ * fallback case was enacted. 3) Otherwise, the client finds the first
+ * protocol in the server's list that it supports and selects this protocol.
+ * This is because it's assumed that the server has better information about
+ * which protocol a client should use. 4) If the client doesn't support any
+ * of the server's advertised protocols, then this is treated the same as
+ * case 2. It returns either OPENSSL_NPN_NEGOTIATED if a common protocol was
+ * found, or OPENSSL_NPN_NO_OVERLAP if the fallback case was reached.
+ */
+int SSL_select_next_proto(unsigned char **out, unsigned char *outlen,
+ const unsigned char *server,
+ unsigned int server_len,
+ const unsigned char *client, unsigned int client_len)
+{
+ unsigned int i, j;
+ const unsigned char *result;
+ int status = OPENSSL_NPN_UNSUPPORTED;
+
+ /*
+ * For each protocol in server preference order, see if we support it.
+ */
+ for (i = 0; i < server_len;) {
+ for (j = 0; j < client_len;) {
+ if (server[i] == client[j] &&
+ memcmp(&server[i + 1], &client[j + 1], server[i]) == 0) {
+ /* We found a match */
+ result = &server[i];
+ status = OPENSSL_NPN_NEGOTIATED;
+ goto found;
+ }
+ j += client[j];
+ j++;
+ }
+ i += server[i];
+ i++;
+ }
+
+ /* There's no overlap between our protocols and the server's list. */
+ result = client;
+ status = OPENSSL_NPN_NO_OVERLAP;
+
+ found:
+ *out = (unsigned char *)result + 1;
+ *outlen = result[0];
+ return status;
+}
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+/*
+ * SSL_get0_next_proto_negotiated sets *data and *len to point to the
+ * client's requested protocol for this connection and returns 0. If the
+ * client didn't request any protocol, then *data is set to NULL. Note that
+ * the client can request any protocol it chooses. The value returned from
+ * this function need not be a member of the list of supported protocols
+ * provided by the callback.
+ */
+void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data,
+ unsigned *len)
+{
+ *data = s->next_proto_negotiated;
+ if (!*data) {
+ *len = 0;
+ } else {
+ *len = s->next_proto_negotiated_len;
+ }
+}
+
+/*
+ * SSL_CTX_set_next_protos_advertised_cb sets a callback that is called when
+ * a TLS server needs a list of supported protocols for Next Protocol
+ * Negotiation. The returned list must be in wire format. The list is
+ * returned by setting |out| to point to it and |outlen| to its length. This
+ * memory will not be modified, but one should assume that the SSL* keeps a
+ * reference to it. The callback should return SSL_TLSEXT_ERR_OK if it
+ * wishes to advertise. Otherwise, no such extension will be included in the
+ * ServerHello.
+ */
+void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *ctx,
+ int (*cb) (SSL *ssl,
+ const unsigned char
+ **out,
+ unsigned int *outlen,
+ void *arg), void *arg)
+{
+ ctx->next_protos_advertised_cb = cb;
+ ctx->next_protos_advertised_cb_arg = arg;
+}
+
+/*
+ * SSL_CTX_set_next_proto_select_cb sets a callback that is called when a
+ * client needs to select a protocol from the server's provided list. |out|
+ * must be set to point to the selected protocol (which may be within |in|).
+ * The length of the protocol name must be written into |outlen|. The
+ * server's advertised protocols are provided in |in| and |inlen|. The
+ * callback can assume that |in| is syntactically valid. The client must
+ * select a protocol. It is fatal to the connection if this callback returns
+ * a value other than SSL_TLSEXT_ERR_OK.
+ */
+void SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx,
+ int (*cb) (SSL *s, unsigned char **out,
+ unsigned char *outlen,
+ const unsigned char *in,
+ unsigned int inlen,
+ void *arg), void *arg)
+{
+ ctx->next_proto_select_cb = cb;
+ ctx->next_proto_select_cb_arg = arg;
+}
+#endif
+
+/*
+ * SSL_CTX_set_alpn_protos sets the ALPN protocol list on |ctx| to |protos|.
+ * |protos| must be in wire-format (i.e. a series of non-empty, 8-bit
+ * length-prefixed strings). Returns 0 on success.
+ */
+int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos,
+ unsigned int protos_len)
+{
+ OPENSSL_free(ctx->alpn_client_proto_list);
+ ctx->alpn_client_proto_list = OPENSSL_memdup(protos, protos_len);
+ if (ctx->alpn_client_proto_list == NULL) {
+ SSLerr(SSL_F_SSL_CTX_SET_ALPN_PROTOS, ERR_R_MALLOC_FAILURE);
+ return 1;
+ }
+ ctx->alpn_client_proto_list_len = protos_len;
+
+ return 0;
+}
+
+/*
+ * SSL_set_alpn_protos sets the ALPN protocol list on |ssl| to |protos|.
+ * |protos| must be in wire-format (i.e. a series of non-empty, 8-bit
+ * length-prefixed strings). Returns 0 on success.
+ */
+int SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos,
+ unsigned int protos_len)
+{
+ OPENSSL_free(ssl->alpn_client_proto_list);
+ ssl->alpn_client_proto_list = OPENSSL_memdup(protos, protos_len);
+ if (ssl->alpn_client_proto_list == NULL) {
+ SSLerr(SSL_F_SSL_SET_ALPN_PROTOS, ERR_R_MALLOC_FAILURE);
+ return 1;
+ }
+ ssl->alpn_client_proto_list_len = protos_len;
+
+ return 0;
+}
+
+/*
+ * SSL_CTX_set_alpn_select_cb sets a callback function on |ctx| that is
+ * called during ClientHello processing in order to select an ALPN protocol
+ * from the client's list of offered protocols.
+ */
+void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx,
+ int (*cb) (SSL *ssl,
+ const unsigned char **out,
+ unsigned char *outlen,
+ const unsigned char *in,
+ unsigned int inlen,
+ void *arg), void *arg)
+{
+ ctx->alpn_select_cb = cb;
+ ctx->alpn_select_cb_arg = arg;
+}
+
+/*
+ * SSL_get0_alpn_selected gets the selected ALPN protocol (if any) from |ssl|.
+ * On return it sets |*data| to point to |*len| bytes of protocol name
+ * (not including the leading length-prefix byte). If the server didn't
+ * respond with a negotiated protocol then |*len| will be zero.
+ */
+void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data,
+ unsigned int *len)
+{
+ *data = NULL;
+ if (ssl->s3)
+ *data = ssl->s3->alpn_selected;
+ if (*data == NULL)
+ *len = 0;
+ else
+ *len = ssl->s3->alpn_selected_len;
+}
+
+int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen,
+ const char *label, size_t llen,
+ const unsigned char *context, size_t contextlen,
+ int use_context)
+{
+ if (s->version < TLS1_VERSION && s->version != DTLS1_BAD_VER)
+ return -1;
+
+ return s->method->ssl3_enc->export_keying_material(s, out, olen, label,
+ llen, context,
+ contextlen, use_context);
+}
+
+static unsigned long ssl_session_hash(const SSL_SESSION *a)
+{
+ const unsigned char *session_id = a->session_id;
+ unsigned long l;
+ unsigned char tmp_storage[4];
+
+ if (a->session_id_length < sizeof(tmp_storage)) {
+ memset(tmp_storage, 0, sizeof(tmp_storage));
+ memcpy(tmp_storage, a->session_id, a->session_id_length);
+ session_id = tmp_storage;
+ }
+
+ l = (unsigned long)
+ ((unsigned long)session_id[0]) |
+ ((unsigned long)session_id[1] << 8L) |
+ ((unsigned long)session_id[2] << 16L) |
+ ((unsigned long)session_id[3] << 24L);
+ return (l);
+}
+
+/*
+ * NB: If this function (or indeed the hash function which uses a sort of
+ * coarser function than this one) is changed, ensure
+ * SSL_CTX_has_matching_session_id() is checked accordingly. It relies on
+ * being able to construct an SSL_SESSION that will collide with any existing
+ * session with a matching session ID.
+ */
+static int ssl_session_cmp(const SSL_SESSION *a, const SSL_SESSION *b)
+{
+ if (a->ssl_version != b->ssl_version)
+ return (1);
+ if (a->session_id_length != b->session_id_length)
+ return (1);
+ return (memcmp(a->session_id, b->session_id, a->session_id_length));
+}
+
+/*
+ * These wrapper functions should remain rather than redeclaring
+ * SSL_SESSION_hash and SSL_SESSION_cmp for void* types and casting each
+ * variable. The reason is that the functions aren't static, they're exposed
+ * via ssl.h.
+ */
+
+SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
+{
+ SSL_CTX *ret = NULL;
+
+ if (meth == NULL) {
+ SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_NULL_SSL_METHOD_PASSED);
+ return (NULL);
+ }
+
+ if (!OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL))
+ return NULL;
+
+ if (FIPS_mode() && (meth->version < TLS1_VERSION)) {
+ SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE);
+ return NULL;
+ }
+
+ if (SSL_get_ex_data_X509_STORE_CTX_idx() < 0) {
+ SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_X509_VERIFICATION_SETUP_PROBLEMS);
+ goto err;
+ }
+ ret = OPENSSL_zalloc(sizeof(*ret));
+ if (ret == NULL)
+ goto err;
+
+ ret->method = meth;
+ ret->min_proto_version = 0;
+ ret->max_proto_version = 0;
+ ret->session_cache_mode = SSL_SESS_CACHE_SERVER;
+ ret->session_cache_size = SSL_SESSION_CACHE_MAX_SIZE_DEFAULT;
+ /* We take the system default. */
+ ret->session_timeout = meth->get_timeout();
+ ret->references = 1;
+ ret->lock = CRYPTO_THREAD_lock_new();
+ if (ret->lock == NULL) {
+ SSLerr(SSL_F_SSL_CTX_NEW, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(ret);
+ return NULL;
+ }
+ ret->max_cert_list = SSL_MAX_CERT_LIST_DEFAULT;
+ ret->verify_mode = SSL_VERIFY_NONE;
+ if ((ret->cert = ssl_cert_new()) == NULL)
+ goto err;
+
+ ret->sessions = lh_SSL_SESSION_new(ssl_session_hash, ssl_session_cmp);
+ if (ret->sessions == NULL)
+ goto err;
+ ret->cert_store = X509_STORE_new();
+ if (ret->cert_store == NULL)
+ goto err;
+#ifndef OPENSSL_NO_CT
+ ret->ctlog_store = CTLOG_STORE_new();
+ if (ret->ctlog_store == NULL)
+ goto err;
+#endif
+ if (!ssl_create_cipher_list(ret->method,
+ &ret->cipher_list, &ret->cipher_list_by_id,
+ SSL_DEFAULT_CIPHER_LIST, ret->cert)
+ || sk_SSL_CIPHER_num(ret->cipher_list) <= 0) {
+ SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_LIBRARY_HAS_NO_CIPHERS);
+ goto err2;
+ }
+
+ ret->param = X509_VERIFY_PARAM_new();
+ if (ret->param == NULL)
+ goto err;
+
+ if ((ret->md5 = EVP_get_digestbyname("ssl3-md5")) == NULL) {
+ SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES);
+ goto err2;
+ }
+ if ((ret->sha1 = EVP_get_digestbyname("ssl3-sha1")) == NULL) {
+ SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES);
+ goto err2;
+ }
+
+ if ((ret->client_CA = sk_X509_NAME_new_null()) == NULL)
+ goto err;
+
+ if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_CTX, ret, &ret->ex_data))
+ goto err;
+
+ /* No compression for DTLS */
+ if (!(meth->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS))
+ ret->comp_methods = SSL_COMP_get_compression_methods();
+
+ ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH;
+ ret->split_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH;
+
+ /* Setup RFC5077 ticket keys */
+ if ((RAND_bytes(ret->tlsext_tick_key_name,
+ sizeof(ret->tlsext_tick_key_name)) <= 0)
+ || (RAND_bytes(ret->tlsext_tick_hmac_key,
+ sizeof(ret->tlsext_tick_hmac_key)) <= 0)
+ || (RAND_bytes(ret->tlsext_tick_aes_key,
+ sizeof(ret->tlsext_tick_aes_key)) <= 0))
+ ret->options |= SSL_OP_NO_TICKET;
+
+#ifndef OPENSSL_NO_SRP
+ if (!SSL_CTX_SRP_CTX_init(ret))
+ goto err;
+#endif
+#ifndef OPENSSL_NO_ENGINE
+# ifdef OPENSSL_SSL_CLIENT_ENGINE_AUTO
+# define eng_strx(x) #x
+# define eng_str(x) eng_strx(x)
+ /* Use specific client engine automatically... ignore errors */
+ {
+ ENGINE *eng;
+ eng = ENGINE_by_id(eng_str(OPENSSL_SSL_CLIENT_ENGINE_AUTO));
+ if (!eng) {
+ ERR_clear_error();
+ ENGINE_load_builtin_engines();
+ eng = ENGINE_by_id(eng_str(OPENSSL_SSL_CLIENT_ENGINE_AUTO));
+ }
+ if (!eng || !SSL_CTX_set_client_cert_engine(ret, eng))
+ ERR_clear_error();
+ }
+# endif
+#endif
+ /*
+ * Default is to connect to non-RI servers. When RI is more widely
+ * deployed might change this.
+ */
+ ret->options |= SSL_OP_LEGACY_SERVER_CONNECT;
+ /*
+ * Disable compression by default to prevent CRIME. Applications can
+ * re-enable compression by configuring
+ * SSL_CTX_clear_options(ctx, SSL_OP_NO_COMPRESSION);
+ * or by using the SSL_CONF library.
+ */
+ ret->options |= SSL_OP_NO_COMPRESSION;
+
+ ret->tlsext_status_type = -1;
+
+ return ret;
+ err:
+ SSLerr(SSL_F_SSL_CTX_NEW, ERR_R_MALLOC_FAILURE);
+ err2:
+ SSL_CTX_free(ret);
+ return NULL;
+}
+
+int SSL_CTX_up_ref(SSL_CTX *ctx)
+{
+ int i;
+
+ if (CRYPTO_atomic_add(&ctx->references, 1, &i, ctx->lock) <= 0)
+ return 0;
+
+ REF_PRINT_COUNT("SSL_CTX", ctx);
+ REF_ASSERT_ISNT(i < 2);
+ return ((i > 1) ? 1 : 0);
+}
+
+void SSL_CTX_free(SSL_CTX *a)
+{
+ int i;
+
+ if (a == NULL)
+ return;
+
+ CRYPTO_atomic_add(&a->references, -1, &i, a->lock);
+ REF_PRINT_COUNT("SSL_CTX", a);
+ if (i > 0)
+ return;
+ REF_ASSERT_ISNT(i < 0);
+
+ X509_VERIFY_PARAM_free(a->param);
+ dane_ctx_final(&a->dane);
+
+ /*
+ * Free internal session cache. However: the remove_cb() may reference
+ * the ex_data of SSL_CTX, thus the ex_data store can only be removed
+ * after the sessions were flushed.
+ * As the ex_data handling routines might also touch the session cache,
+ * the most secure solution seems to be: empty (flush) the cache, then
+ * free ex_data, then finally free the cache.
+ * (See ticket [openssl.org #212].)
+ */
+ if (a->sessions != NULL)
+ SSL_CTX_flush_sessions(a, 0);
+
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data);
+ lh_SSL_SESSION_free(a->sessions);
+ X509_STORE_free(a->cert_store);
+#ifndef OPENSSL_NO_CT
+ CTLOG_STORE_free(a->ctlog_store);
+#endif
+ sk_SSL_CIPHER_free(a->cipher_list);
+ sk_SSL_CIPHER_free(a->cipher_list_by_id);
+ ssl_cert_free(a->cert);
+ sk_X509_NAME_pop_free(a->client_CA, X509_NAME_free);
+ sk_X509_pop_free(a->extra_certs, X509_free);
+ a->comp_methods = NULL;
+#ifndef OPENSSL_NO_SRTP
+ sk_SRTP_PROTECTION_PROFILE_free(a->srtp_profiles);
+#endif
+#ifndef OPENSSL_NO_SRP
+ SSL_CTX_SRP_CTX_free(a);
+#endif
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE_finish(a->client_cert_engine);
+#endif
+
+#ifndef OPENSSL_NO_EC
+ OPENSSL_free(a->tlsext_ecpointformatlist);
+ OPENSSL_free(a->tlsext_ellipticcurvelist);
+#endif
+ OPENSSL_free(a->alpn_client_proto_list);
+
+ CRYPTO_THREAD_lock_free(a->lock);
+
+ OPENSSL_free(a);
+}
+
+void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb)
+{
+ ctx->default_passwd_callback = cb;
+}
+
+void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u)
+{
+ ctx->default_passwd_callback_userdata = u;
+}
+
+pem_password_cb *SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx)
+{
+ return ctx->default_passwd_callback;
+}
+
+void *SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx)
+{
+ return ctx->default_passwd_callback_userdata;
+}
+
+void SSL_set_default_passwd_cb(SSL *s, pem_password_cb *cb)
+{
+ s->default_passwd_callback = cb;
+}
+
+void SSL_set_default_passwd_cb_userdata(SSL *s, void *u)
+{
+ s->default_passwd_callback_userdata = u;
+}
+
+pem_password_cb *SSL_get_default_passwd_cb(SSL *s)
+{
+ return s->default_passwd_callback;
+}
+
+void *SSL_get_default_passwd_cb_userdata(SSL *s)
+{
+ return s->default_passwd_callback_userdata;
+}
+
+void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,
+ int (*cb) (X509_STORE_CTX *, void *),
+ void *arg)
+{
+ ctx->app_verify_callback = cb;
+ ctx->app_verify_arg = arg;
+}
+
+void SSL_CTX_set_verify(SSL_CTX *ctx, int mode,
+ int (*cb) (int, X509_STORE_CTX *))
+{
+ ctx->verify_mode = mode;
+ ctx->default_verify_callback = cb;
+}
+
+void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth)
+{
+ X509_VERIFY_PARAM_set_depth(ctx->param, depth);
+}
+
+void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb) (SSL *ssl, void *arg), void *arg)
+{
+ ssl_cert_set_cert_cb(c->cert, cb, arg);
+}
+
+void SSL_set_cert_cb(SSL *s, int (*cb) (SSL *ssl, void *arg), void *arg)
+{
+ ssl_cert_set_cert_cb(s->cert, cb, arg);
+}
+
+void ssl_set_masks(SSL *s)
+{
+#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_GOST)
+ CERT_PKEY *cpk;
+#endif
+ CERT *c = s->cert;
+ uint32_t *pvalid = s->s3->tmp.valid_flags;
+ int rsa_enc, rsa_sign, dh_tmp, dsa_sign;
+ unsigned long mask_k, mask_a;
+#ifndef OPENSSL_NO_EC
+ int have_ecc_cert, ecdsa_ok;
+ X509 *x = NULL;
+#endif
+ if (c == NULL)
+ return;
+
+#ifndef OPENSSL_NO_DH
+ dh_tmp = (c->dh_tmp != NULL || c->dh_tmp_cb != NULL || c->dh_tmp_auto);
+#else
+ dh_tmp = 0;
+#endif
+
+ rsa_enc = pvalid[SSL_PKEY_RSA_ENC] & CERT_PKEY_VALID;
+ rsa_sign = pvalid[SSL_PKEY_RSA_SIGN] & CERT_PKEY_SIGN;
+ dsa_sign = pvalid[SSL_PKEY_DSA_SIGN] & CERT_PKEY_SIGN;
+#ifndef OPENSSL_NO_EC
+ have_ecc_cert = pvalid[SSL_PKEY_ECC] & CERT_PKEY_VALID;
+#endif
+ mask_k = 0;
+ mask_a = 0;
+
+#ifdef CIPHER_DEBUG
+ fprintf(stderr, "dht=%d re=%d rs=%d ds=%d\n",
+ dh_tmp, rsa_enc, rsa_sign, dsa_sign);
+#endif
+
+#ifndef OPENSSL_NO_GOST
+ cpk = &(c->pkeys[SSL_PKEY_GOST12_512]);
+ if (cpk->x509 != NULL && cpk->privatekey != NULL) {
+ mask_k |= SSL_kGOST;
+ mask_a |= SSL_aGOST12;
+ }
+ cpk = &(c->pkeys[SSL_PKEY_GOST12_256]);
+ if (cpk->x509 != NULL && cpk->privatekey != NULL) {
+ mask_k |= SSL_kGOST;
+ mask_a |= SSL_aGOST12;
+ }
+ cpk = &(c->pkeys[SSL_PKEY_GOST01]);
+ if (cpk->x509 != NULL && cpk->privatekey != NULL) {
+ mask_k |= SSL_kGOST;
+ mask_a |= SSL_aGOST01;
+ }
+#endif
+
+ if (rsa_enc)
+ mask_k |= SSL_kRSA;
+
+ if (dh_tmp)
+ mask_k |= SSL_kDHE;
+
+ if (rsa_enc || rsa_sign) {
+ mask_a |= SSL_aRSA;
+ }
+
+ if (dsa_sign) {
+ mask_a |= SSL_aDSS;
+ }
+
+ mask_a |= SSL_aNULL;
+
+ /*
+ * An ECC certificate may be usable for ECDH and/or ECDSA cipher suites
+ * depending on the key usage extension.
+ */
+#ifndef OPENSSL_NO_EC
+ if (have_ecc_cert) {
+ uint32_t ex_kusage;
+ cpk = &c->pkeys[SSL_PKEY_ECC];
+ x = cpk->x509;
+ ex_kusage = X509_get_key_usage(x);
+ ecdsa_ok = ex_kusage & X509v3_KU_DIGITAL_SIGNATURE;
+ if (!(pvalid[SSL_PKEY_ECC] & CERT_PKEY_SIGN))
+ ecdsa_ok = 0;
+ if (ecdsa_ok)
+ mask_a |= SSL_aECDSA;
+ }
+#endif
+
+#ifndef OPENSSL_NO_EC
+ mask_k |= SSL_kECDHE;
+#endif
+
+#ifndef OPENSSL_NO_PSK
+ mask_k |= SSL_kPSK;
+ mask_a |= SSL_aPSK;
+ if (mask_k & SSL_kRSA)
+ mask_k |= SSL_kRSAPSK;
+ if (mask_k & SSL_kDHE)
+ mask_k |= SSL_kDHEPSK;
+ if (mask_k & SSL_kECDHE)
+ mask_k |= SSL_kECDHEPSK;
+#endif
+
+ s->s3->tmp.mask_k = mask_k;
+ s->s3->tmp.mask_a = mask_a;
+}
+
+#ifndef OPENSSL_NO_EC
+
+int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s)
+{
+ if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aECDSA) {
+ /* key usage, if present, must allow signing */
+ if (!(X509_get_key_usage(x) & X509v3_KU_DIGITAL_SIGNATURE)) {
+ SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG,
+ SSL_R_ECC_CERT_NOT_FOR_SIGNING);
+ return 0;
+ }
+ }
+ return 1; /* all checks are ok */
+}
+
+#endif
+
+static int ssl_get_server_cert_index(const SSL *s)
+{
+ int idx;
+ idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
+ if (idx == SSL_PKEY_RSA_ENC && !s->cert->pkeys[SSL_PKEY_RSA_ENC].x509)
+ idx = SSL_PKEY_RSA_SIGN;
+ if (idx == SSL_PKEY_GOST_EC) {
+ if (s->cert->pkeys[SSL_PKEY_GOST12_512].x509)
+ idx = SSL_PKEY_GOST12_512;
+ else if (s->cert->pkeys[SSL_PKEY_GOST12_256].x509)
+ idx = SSL_PKEY_GOST12_256;
+ else if (s->cert->pkeys[SSL_PKEY_GOST01].x509)
+ idx = SSL_PKEY_GOST01;
+ else
+ idx = -1;
+ }
+ if (idx == -1)
+ SSLerr(SSL_F_SSL_GET_SERVER_CERT_INDEX, ERR_R_INTERNAL_ERROR);
+ return idx;
+}
+
+CERT_PKEY *ssl_get_server_send_pkey(SSL *s)
+{
+ CERT *c;
+ int i;
+
+ c = s->cert;
+ if (!s->s3 || !s->s3->tmp.new_cipher)
+ return NULL;
+ ssl_set_masks(s);
+
+ i = ssl_get_server_cert_index(s);
+
+ /* This may or may not be an error. */
+ if (i < 0)
+ return NULL;
+
+ /* May be NULL. */
+ return &c->pkeys[i];
+}
+
+EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *cipher,
+ const EVP_MD **pmd)
+{
+ unsigned long alg_a;
+ CERT *c;
+ int idx = -1;
+
+ alg_a = cipher->algorithm_auth;
+ c = s->cert;
+
+ if ((alg_a & SSL_aDSS) && (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
+ idx = SSL_PKEY_DSA_SIGN;
+ else if (alg_a & SSL_aRSA) {
+ if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL)
+ idx = SSL_PKEY_RSA_SIGN;
+ else if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL)
+ idx = SSL_PKEY_RSA_ENC;
+ } else if ((alg_a & SSL_aECDSA) &&
+ (c->pkeys[SSL_PKEY_ECC].privatekey != NULL))
+ idx = SSL_PKEY_ECC;
+ if (idx == -1) {
+ SSLerr(SSL_F_SSL_GET_SIGN_PKEY, ERR_R_INTERNAL_ERROR);
+ return (NULL);
+ }
+ if (pmd)
+ *pmd = s->s3->tmp.md[idx];
+ return c->pkeys[idx].privatekey;
+}
+
+int ssl_get_server_cert_serverinfo(SSL *s, const unsigned char **serverinfo,
+ size_t *serverinfo_length)
+{
+ CERT *c = NULL;
+ int i = 0;
+ *serverinfo_length = 0;
+
+ c = s->cert;
+ i = ssl_get_server_cert_index(s);
+
+ if (i == -1)
+ return 0;
+ if (c->pkeys[i].serverinfo == NULL)
+ return 0;
+
+ *serverinfo = c->pkeys[i].serverinfo;
+ *serverinfo_length = c->pkeys[i].serverinfo_length;
+ return 1;
+}
+
+void ssl_update_cache(SSL *s, int mode)
+{
+ int i;
+
+ /*
+ * If the session_id_length is 0, we are not supposed to cache it, and it
+ * would be rather hard to do anyway :-)
+ */
+ if (s->session->session_id_length == 0)
+ return;
+
+ /*
+ * If sid_ctx_length is 0 there is no specific application context
+ * associated with this session, so when we try to resume it and
+ * SSL_VERIFY_PEER is requested, we have no indication that this is
+ * actually a session for the proper application context, and the
+ * *handshake* will fail, not just the resumption attempt.
+ * Do not cache these sessions that are not resumable.
+ */
+ if (s->session->sid_ctx_length == 0
+ && (s->verify_mode & SSL_VERIFY_PEER) != 0)
+ return;
+
+ i = s->session_ctx->session_cache_mode;
+ if ((i & mode) && (!s->hit)
+ && ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE)
+ || SSL_CTX_add_session(s->session_ctx, s->session))
+ && (s->session_ctx->new_session_cb != NULL)) {
+ SSL_SESSION_up_ref(s->session);
+ if (!s->session_ctx->new_session_cb(s, s->session))
+ SSL_SESSION_free(s->session);
+ }
+
+ /* auto flush every 255 connections */
+ if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) && ((i & mode) == mode)) {
+ if ((((mode & SSL_SESS_CACHE_CLIENT)
+ ? s->session_ctx->stats.sess_connect_good
+ : s->session_ctx->stats.sess_accept_good) & 0xff) == 0xff) {
+ SSL_CTX_flush_sessions(s->session_ctx, (unsigned long)time(NULL));
+ }
+ }
+}
+
+const SSL_METHOD *SSL_CTX_get_ssl_method(SSL_CTX *ctx)
+{
+ return ctx->method;
+}
+
+const SSL_METHOD *SSL_get_ssl_method(SSL *s)
+{
+ return (s->method);
+}
+
+int SSL_set_ssl_method(SSL *s, const SSL_METHOD *meth)
+{
+ int ret = 1;
+
+ if (s->method != meth) {
+ const SSL_METHOD *sm = s->method;
+ int (*hf) (SSL *) = s->handshake_func;
+
+ if (sm->version == meth->version)
+ s->method = meth;
+ else {
+ sm->ssl_free(s);
+ s->method = meth;
+ ret = s->method->ssl_new(s);
+ }
+
+ if (hf == sm->ssl_connect)
+ s->handshake_func = meth->ssl_connect;
+ else if (hf == sm->ssl_accept)
+ s->handshake_func = meth->ssl_accept;
+ }
+ return (ret);
+}
+
+int SSL_get_error(const SSL *s, int i)
+{
+ int reason;
+ unsigned long l;
+ BIO *bio;
+
+ if (i > 0)
+ return (SSL_ERROR_NONE);
+
+ /*
+ * Make things return SSL_ERROR_SYSCALL when doing SSL_do_handshake etc,
+ * where we do encode the error
+ */
+ if ((l = ERR_peek_error()) != 0) {
+ if (ERR_GET_LIB(l) == ERR_LIB_SYS)
+ return (SSL_ERROR_SYSCALL);
+ else
+ return (SSL_ERROR_SSL);
+ }
+
+ if (i < 0) {
+ if (SSL_want_read(s)) {
+ bio = SSL_get_rbio(s);
+ if (BIO_should_read(bio))
+ return (SSL_ERROR_WANT_READ);
+ else if (BIO_should_write(bio))
+ /*
+ * This one doesn't make too much sense ... We never try to write
+ * to the rbio, and an application program where rbio and wbio
+ * are separate couldn't even know what it should wait for.
+ * However if we ever set s->rwstate incorrectly (so that we have
+ * SSL_want_read(s) instead of SSL_want_write(s)) and rbio and
+ * wbio *are* the same, this test works around that bug; so it
+ * might be safer to keep it.
+ */
+ return (SSL_ERROR_WANT_WRITE);
+ else if (BIO_should_io_special(bio)) {
+ reason = BIO_get_retry_reason(bio);
+ if (reason == BIO_RR_CONNECT)
+ return (SSL_ERROR_WANT_CONNECT);
+ else if (reason == BIO_RR_ACCEPT)
+ return (SSL_ERROR_WANT_ACCEPT);
+ else
+ return (SSL_ERROR_SYSCALL); /* unknown */
+ }
+ }
+
+ if (SSL_want_write(s)) {
+ /*
+ * Access wbio directly - in order to use the buffered bio if
+ * present
+ */
+ bio = s->wbio;
+ if (BIO_should_write(bio))
+ return (SSL_ERROR_WANT_WRITE);
+ else if (BIO_should_read(bio))
+ /*
+ * See above (SSL_want_read(s) with BIO_should_write(bio))
+ */
+ return (SSL_ERROR_WANT_READ);
+ else if (BIO_should_io_special(bio)) {
+ reason = BIO_get_retry_reason(bio);
+ if (reason == BIO_RR_CONNECT)
+ return (SSL_ERROR_WANT_CONNECT);
+ else if (reason == BIO_RR_ACCEPT)
+ return (SSL_ERROR_WANT_ACCEPT);
+ else
+ return (SSL_ERROR_SYSCALL);
+ }
+ }
+ if (SSL_want_x509_lookup(s)) {
+ return (SSL_ERROR_WANT_X509_LOOKUP);
+ }
+ if (SSL_want_async(s)) {
+ return SSL_ERROR_WANT_ASYNC;
+ }
+ if (SSL_want_async_job(s)) {
+ return SSL_ERROR_WANT_ASYNC_JOB;
+ }
+ }
+
+ if (i == 0) {
+ if ((s->shutdown & SSL_RECEIVED_SHUTDOWN) &&
+ (s->s3->warn_alert == SSL_AD_CLOSE_NOTIFY))
+ return (SSL_ERROR_ZERO_RETURN);
+ }
+ return (SSL_ERROR_SYSCALL);
+}
+
+static int ssl_do_handshake_intern(void *vargs)
+{
+ struct ssl_async_args *args;
+ SSL *s;
+
+ args = (struct ssl_async_args *)vargs;
+ s = args->s;
+
+ return s->handshake_func(s);
+}
+
+int SSL_do_handshake(SSL *s)
+{
+ int ret = 1;
+
+ if (s->handshake_func == NULL) {
+ SSLerr(SSL_F_SSL_DO_HANDSHAKE, SSL_R_CONNECTION_TYPE_NOT_SET);
+ return -1;
+ }
+
+ s->method->ssl_renegotiate_check(s);
+
+ if (SSL_in_init(s) || SSL_in_before(s)) {
+ if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
+ struct ssl_async_args args;
+
+ args.s = s;
+
+ ret = ssl_start_async_job(s, &args, ssl_do_handshake_intern);
+ } else {
+ ret = s->handshake_func(s);
+ }
+ }
+ return ret;
+}
+
+void SSL_set_accept_state(SSL *s)
+{
+ s->server = 1;
+ s->shutdown = 0;
+ ossl_statem_clear(s);
+ s->handshake_func = s->method->ssl_accept;
+ clear_ciphers(s);
+}
+
+void SSL_set_connect_state(SSL *s)
+{
+ s->server = 0;
+ s->shutdown = 0;
+ ossl_statem_clear(s);
+ s->handshake_func = s->method->ssl_connect;
+ clear_ciphers(s);
+}
+
+int ssl_undefined_function(SSL *s)
+{
+ SSLerr(SSL_F_SSL_UNDEFINED_FUNCTION, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return (0);
+}
+
+int ssl_undefined_void_function(void)
+{
+ SSLerr(SSL_F_SSL_UNDEFINED_VOID_FUNCTION,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return (0);
+}
+
+int ssl_undefined_const_function(const SSL *s)
+{
+ return (0);
+}
+
+const SSL_METHOD *ssl_bad_method(int ver)
+{
+ SSLerr(SSL_F_SSL_BAD_METHOD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return (NULL);
+}
+
+const char *ssl_protocol_to_string(int version)
+{
+ if (version == TLS1_2_VERSION)
+ return "TLSv1.2";
+ else if (version == TLS1_1_VERSION)
+ return "TLSv1.1";
+ else if (version == TLS1_VERSION)
+ return "TLSv1";
+ else if (version == SSL3_VERSION)
+ return "SSLv3";
+ else if (version == DTLS1_BAD_VER)
+ return "DTLSv0.9";
+ else if (version == DTLS1_VERSION)
+ return "DTLSv1";
+ else if (version == DTLS1_2_VERSION)
+ return "DTLSv1.2";
+ else
+ return ("unknown");
+}
+
+const char *SSL_get_version(const SSL *s)
+{
+ return ssl_protocol_to_string(s->version);
+}
+
+SSL *SSL_dup(SSL *s)
+{
+ STACK_OF(X509_NAME) *sk;
+ X509_NAME *xn;
+ SSL *ret;
+ int i;
+
+ /* If we're not quiescent, just up_ref! */
+ if (!SSL_in_init(s) || !SSL_in_before(s)) {
+ CRYPTO_atomic_add(&s->references, 1, &i, s->lock);
+ return s;
+ }
+
+ /*
+ * Otherwise, copy configuration state, and session if set.
+ */
+ if ((ret = SSL_new(SSL_get_SSL_CTX(s))) == NULL)
+ return (NULL);
+
+ if (s->session != NULL) {
+ /*
+ * Arranges to share the same session via up_ref. This "copies"
+ * session-id, SSL_METHOD, sid_ctx, and 'cert'
+ */
+ if (!SSL_copy_session_id(ret, s))
+ goto err;
+ } else {
+ /*
+ * No session has been established yet, so we have to expect that
+ * s->cert or ret->cert will be changed later -- they should not both
+ * point to the same object, and thus we can't use
+ * SSL_copy_session_id.
+ */
+ if (!SSL_set_ssl_method(ret, s->method))
+ goto err;
+
+ if (s->cert != NULL) {
+ ssl_cert_free(ret->cert);
+ ret->cert = ssl_cert_dup(s->cert);
+ if (ret->cert == NULL)
+ goto err;
+ }
+
+ if (!SSL_set_session_id_context(ret, s->sid_ctx, s->sid_ctx_length))
+ goto err;
+ }
+
+ if (!ssl_dane_dup(ret, s))
+ goto err;
+ ret->version = s->version;
+ ret->options = s->options;
+ ret->mode = s->mode;
+ SSL_set_max_cert_list(ret, SSL_get_max_cert_list(s));
+ SSL_set_read_ahead(ret, SSL_get_read_ahead(s));
+ ret->msg_callback = s->msg_callback;
+ ret->msg_callback_arg = s->msg_callback_arg;
+ SSL_set_verify(ret, SSL_get_verify_mode(s), SSL_get_verify_callback(s));
+ SSL_set_verify_depth(ret, SSL_get_verify_depth(s));
+ ret->generate_session_id = s->generate_session_id;
+
+ SSL_set_info_callback(ret, SSL_get_info_callback(s));
+
+ /* copy app data, a little dangerous perhaps */
+ if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL, &ret->ex_data, &s->ex_data))
+ goto err;
+
+ /* setup rbio, and wbio */
+ if (s->rbio != NULL) {
+ if (!BIO_dup_state(s->rbio, (char *)&ret->rbio))
+ goto err;
+ }
+ if (s->wbio != NULL) {
+ if (s->wbio != s->rbio) {
+ if (!BIO_dup_state(s->wbio, (char *)&ret->wbio))
+ goto err;
+ } else {
+ BIO_up_ref(ret->rbio);
+ ret->wbio = ret->rbio;
+ }
+ }
+
+ ret->server = s->server;
+ if (s->handshake_func) {
+ if (s->server)
+ SSL_set_accept_state(ret);
+ else
+ SSL_set_connect_state(ret);
+ }
+ ret->shutdown = s->shutdown;
+ ret->hit = s->hit;
+
+ ret->default_passwd_callback = s->default_passwd_callback;
+ ret->default_passwd_callback_userdata = s->default_passwd_callback_userdata;
+
+ X509_VERIFY_PARAM_inherit(ret->param, s->param);
+
+ /* dup the cipher_list and cipher_list_by_id stacks */
+ if (s->cipher_list != NULL) {
+ if ((ret->cipher_list = sk_SSL_CIPHER_dup(s->cipher_list)) == NULL)
+ goto err;
+ }
+ if (s->cipher_list_by_id != NULL)
+ if ((ret->cipher_list_by_id = sk_SSL_CIPHER_dup(s->cipher_list_by_id))
+ == NULL)
+ goto err;
+
+ /* Dup the client_CA list */
+ if (s->client_CA != NULL) {
+ if ((sk = sk_X509_NAME_dup(s->client_CA)) == NULL)
+ goto err;
+ ret->client_CA = sk;
+ for (i = 0; i < sk_X509_NAME_num(sk); i++) {
+ xn = sk_X509_NAME_value(sk, i);
+ if (sk_X509_NAME_set(sk, i, X509_NAME_dup(xn)) == NULL) {
+ X509_NAME_free(xn);
+ goto err;
+ }
+ }
+ }
+ return ret;
+
+ err:
+ SSL_free(ret);
+ return NULL;
+}
+
+void ssl_clear_cipher_ctx(SSL *s)
+{
+ if (s->enc_read_ctx != NULL) {
+ EVP_CIPHER_CTX_free(s->enc_read_ctx);
+ s->enc_read_ctx = NULL;
+ }
+ if (s->enc_write_ctx != NULL) {
+ EVP_CIPHER_CTX_free(s->enc_write_ctx);
+ s->enc_write_ctx = NULL;
+ }
+#ifndef OPENSSL_NO_COMP
+ COMP_CTX_free(s->expand);
+ s->expand = NULL;
+ COMP_CTX_free(s->compress);
+ s->compress = NULL;
+#endif
+}
+
+X509 *SSL_get_certificate(const SSL *s)
+{
+ if (s->cert != NULL)
+ return (s->cert->key->x509);
+ else
+ return (NULL);
+}
+
+EVP_PKEY *SSL_get_privatekey(const SSL *s)
+{
+ if (s->cert != NULL)
+ return (s->cert->key->privatekey);
+ else
+ return (NULL);
+}
+
+X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx)
+{
+ if (ctx->cert != NULL)
+ return ctx->cert->key->x509;
+ else
+ return NULL;
+}
+
+EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx)
+{
+ if (ctx->cert != NULL)
+ return ctx->cert->key->privatekey;
+ else
+ return NULL;
+}
+
+const SSL_CIPHER *SSL_get_current_cipher(const SSL *s)
+{
+ if ((s->session != NULL) && (s->session->cipher != NULL))
+ return (s->session->cipher);
+ return (NULL);
+}
+
+const COMP_METHOD *SSL_get_current_compression(SSL *s)
+{
+#ifndef OPENSSL_NO_COMP
+ return s->compress ? COMP_CTX_get_method(s->compress) : NULL;
+#else
+ return NULL;
+#endif
+}
+
+const COMP_METHOD *SSL_get_current_expansion(SSL *s)
+{
+#ifndef OPENSSL_NO_COMP
+ return s->expand ? COMP_CTX_get_method(s->expand) : NULL;
+#else
+ return NULL;
+#endif
+}
+
+int ssl_init_wbio_buffer(SSL *s)
+{
+ BIO *bbio;
+
+ if (s->bbio != NULL) {
+ /* Already buffered. */
+ return 1;
+ }
+
+ bbio = BIO_new(BIO_f_buffer());
+ if (bbio == NULL || !BIO_set_read_buffer_size(bbio, 1)) {
+ BIO_free(bbio);
+ SSLerr(SSL_F_SSL_INIT_WBIO_BUFFER, ERR_R_BUF_LIB);
+ return 0;
+ }
+ s->bbio = bbio;
+ s->wbio = BIO_push(bbio, s->wbio);
+
+ return 1;
+}
+
+void ssl_free_wbio_buffer(SSL *s)
+{
+ /* callers ensure s is never null */
+ if (s->bbio == NULL)
+ return;
+
+ s->wbio = BIO_pop(s->wbio);
+ assert(s->wbio != NULL);
+ BIO_free(s->bbio);
+ s->bbio = NULL;
+}
+
+void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode)
+{
+ ctx->quiet_shutdown = mode;
+}
+
+int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx)
+{
+ return (ctx->quiet_shutdown);
+}
+
+void SSL_set_quiet_shutdown(SSL *s, int mode)
+{
+ s->quiet_shutdown = mode;
+}
+
+int SSL_get_quiet_shutdown(const SSL *s)
+{
+ return (s->quiet_shutdown);
+}
+
+void SSL_set_shutdown(SSL *s, int mode)
+{
+ s->shutdown = mode;
+}
+
+int SSL_get_shutdown(const SSL *s)
+{
+ return s->shutdown;
+}
+
+int SSL_version(const SSL *s)
+{
+ return s->version;
+}
+
+int SSL_client_version(const SSL *s)
+{
+ return s->client_version;
+}
+
+SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl)
+{
+ return ssl->ctx;
+}
+
+SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx)
+{
+ CERT *new_cert;
+ if (ssl->ctx == ctx)
+ return ssl->ctx;
+ if (ctx == NULL)
+ ctx = ssl->session_ctx;
+ new_cert = ssl_cert_dup(ctx->cert);
+ if (new_cert == NULL) {
+ return NULL;
+ }
+
+ if (!custom_exts_copy_flags(&new_cert->srv_ext, &ssl->cert->srv_ext)) {
+ ssl_cert_free(new_cert);
+ return NULL;
+ }
+
+ ssl_cert_free(ssl->cert);
+ ssl->cert = new_cert;
+
+ /*
+ * Program invariant: |sid_ctx| has fixed size (SSL_MAX_SID_CTX_LENGTH),
+ * so setter APIs must prevent invalid lengths from entering the system.
+ */
+ OPENSSL_assert(ssl->sid_ctx_length <= sizeof(ssl->sid_ctx));
+
+ /*
+ * If the session ID context matches that of the parent SSL_CTX,
+ * inherit it from the new SSL_CTX as well. If however the context does
+ * not match (i.e., it was set per-ssl with SSL_set_session_id_context),
+ * leave it unchanged.
+ */
+ if ((ssl->ctx != NULL) &&
+ (ssl->sid_ctx_length == ssl->ctx->sid_ctx_length) &&
+ (memcmp(ssl->sid_ctx, ssl->ctx->sid_ctx, ssl->sid_ctx_length) == 0)) {
+ ssl->sid_ctx_length = ctx->sid_ctx_length;
+ memcpy(&ssl->sid_ctx, &ctx->sid_ctx, sizeof(ssl->sid_ctx));
+ }
+
+ SSL_CTX_up_ref(ctx);
+ SSL_CTX_free(ssl->ctx); /* decrement reference count */
+ ssl->ctx = ctx;
+
+ return ssl->ctx;
+}
+
+int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx)
+{
+ return (X509_STORE_set_default_paths(ctx->cert_store));
+}
+
+int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx)
+{
+ X509_LOOKUP *lookup;
+
+ lookup = X509_STORE_add_lookup(ctx->cert_store, X509_LOOKUP_hash_dir());
+ if (lookup == NULL)
+ return 0;
+ X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
+
+ /* Clear any errors if the default directory does not exist */
+ ERR_clear_error();
+
+ return 1;
+}
+
+int SSL_CTX_set_default_verify_file(SSL_CTX *ctx)
+{
+ X509_LOOKUP *lookup;
+
+ lookup = X509_STORE_add_lookup(ctx->cert_store, X509_LOOKUP_file());
+ if (lookup == NULL)
+ return 0;
+
+ X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
+
+ /* Clear any errors if the default file does not exist */
+ ERR_clear_error();
+
+ return 1;
+}
+
+int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
+ const char *CApath)
+{
+ return (X509_STORE_load_locations(ctx->cert_store, CAfile, CApath));
+}
+
+void SSL_set_info_callback(SSL *ssl,
+ void (*cb) (const SSL *ssl, int type, int val))
+{
+ ssl->info_callback = cb;
+}
+
+/*
+ * One compiler (Diab DCC) doesn't like argument names in returned function
+ * pointer.
+ */
+void (*SSL_get_info_callback(const SSL *ssl)) (const SSL * /* ssl */ ,
+ int /* type */ ,
+ int /* val */ ) {
+ return ssl->info_callback;
+}
+
+void SSL_set_verify_result(SSL *ssl, long arg)
+{
+ ssl->verify_result = arg;
+}
+
+long SSL_get_verify_result(const SSL *ssl)
+{
+ return (ssl->verify_result);
+}
+
+size_t SSL_get_client_random(const SSL *ssl, unsigned char *out, size_t outlen)
+{
+ if (outlen == 0)
+ return sizeof(ssl->s3->client_random);
+ if (outlen > sizeof(ssl->s3->client_random))
+ outlen = sizeof(ssl->s3->client_random);
+ memcpy(out, ssl->s3->client_random, outlen);
+ return outlen;
+}
+
+size_t SSL_get_server_random(const SSL *ssl, unsigned char *out, size_t outlen)
+{
+ if (outlen == 0)
+ return sizeof(ssl->s3->server_random);
+ if (outlen > sizeof(ssl->s3->server_random))
+ outlen = sizeof(ssl->s3->server_random);
+ memcpy(out, ssl->s3->server_random, outlen);
+ return outlen;
+}
+
+size_t SSL_SESSION_get_master_key(const SSL_SESSION *session,
+ unsigned char *out, size_t outlen)
+{
+ if (session->master_key_length < 0) {
+ /* Should never happen */
+ return 0;
+ }
+ if (outlen == 0)
+ return session->master_key_length;
+ if (outlen > (size_t)session->master_key_length)
+ outlen = session->master_key_length;
+ memcpy(out, session->master_key, outlen);
+ return outlen;
+}
+
+int SSL_set_ex_data(SSL *s, int idx, void *arg)
+{
+ return (CRYPTO_set_ex_data(&s->ex_data, idx, arg));
+}
+
+void *SSL_get_ex_data(const SSL *s, int idx)
+{
+ return (CRYPTO_get_ex_data(&s->ex_data, idx));
+}
+
+int SSL_CTX_set_ex_data(SSL_CTX *s, int idx, void *arg)
+{
+ return (CRYPTO_set_ex_data(&s->ex_data, idx, arg));
+}
+
+void *SSL_CTX_get_ex_data(const SSL_CTX *s, int idx)
+{
+ return (CRYPTO_get_ex_data(&s->ex_data, idx));
+}
+
+int ssl_ok(SSL *s)
+{
+ return (1);
+}
+
+X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx)
+{
+ return (ctx->cert_store);
+}
+
+void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *store)
+{
+ X509_STORE_free(ctx->cert_store);
+ ctx->cert_store = store;
+}
+
+int SSL_want(const SSL *s)
+{
+ return (s->rwstate);
+}
+
+/**
+ * \brief Set the callback for generating temporary DH keys.
+ * \param ctx the SSL context.
+ * \param dh the callback
+ */
+
+#ifndef OPENSSL_NO_DH
+void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
+ DH *(*dh) (SSL *ssl, int is_export,
+ int keylength))
+{
+ SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_TMP_DH_CB, (void (*)(void))dh);
+}
+
+void SSL_set_tmp_dh_callback(SSL *ssl, DH *(*dh) (SSL *ssl, int is_export,
+ int keylength))
+{
+ SSL_callback_ctrl(ssl, SSL_CTRL_SET_TMP_DH_CB, (void (*)(void))dh);
+}
+#endif
+
+#ifndef OPENSSL_NO_PSK
+int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint)
+{
+ if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) {
+ SSLerr(SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG);
+ return 0;
+ }
+ OPENSSL_free(ctx->cert->psk_identity_hint);
+ if (identity_hint != NULL) {
+ ctx->cert->psk_identity_hint = OPENSSL_strdup(identity_hint);
+ if (ctx->cert->psk_identity_hint == NULL)
+ return 0;
+ } else
+ ctx->cert->psk_identity_hint = NULL;
+ return 1;
+}
+
+int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint)
+{
+ if (s == NULL)
+ return 0;
+
+ if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) {
+ SSLerr(SSL_F_SSL_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG);
+ return 0;
+ }
+ OPENSSL_free(s->cert->psk_identity_hint);
+ if (identity_hint != NULL) {
+ s->cert->psk_identity_hint = OPENSSL_strdup(identity_hint);
+ if (s->cert->psk_identity_hint == NULL)
+ return 0;
+ } else
+ s->cert->psk_identity_hint = NULL;
+ return 1;
+}
+
+const char *SSL_get_psk_identity_hint(const SSL *s)
+{
+ if (s == NULL || s->session == NULL)
+ return NULL;
+ return (s->session->psk_identity_hint);
+}
+
+const char *SSL_get_psk_identity(const SSL *s)
+{
+ if (s == NULL || s->session == NULL)
+ return NULL;
+ return (s->session->psk_identity);
+}
+
+void SSL_set_psk_client_callback(SSL *s,
+ unsigned int (*cb) (SSL *ssl,
+ const char *hint,
+ char *identity,
+ unsigned int
+ max_identity_len,
+ unsigned char *psk,
+ unsigned int max_psk_len))
+{
+ s->psk_client_callback = cb;
+}
+
+void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx,
+ unsigned int (*cb) (SSL *ssl,
+ const char *hint,
+ char *identity,
+ unsigned int
+ max_identity_len,
+ unsigned char *psk,
+ unsigned int
+ max_psk_len))
+{
+ ctx->psk_client_callback = cb;
+}
+
+void SSL_set_psk_server_callback(SSL *s,
+ unsigned int (*cb) (SSL *ssl,
+ const char *identity,
+ unsigned char *psk,
+ unsigned int max_psk_len))
+{
+ s->psk_server_callback = cb;
+}
+
+void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx,
+ unsigned int (*cb) (SSL *ssl,
+ const char *identity,
+ unsigned char *psk,
+ unsigned int
+ max_psk_len))
+{
+ ctx->psk_server_callback = cb;
+}
+#endif
+
+void SSL_CTX_set_msg_callback(SSL_CTX *ctx,
+ void (*cb) (int write_p, int version,
+ int content_type, const void *buf,
+ size_t len, SSL *ssl, void *arg))
+{
+ SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb);
+}
+
+void SSL_set_msg_callback(SSL *ssl,
+ void (*cb) (int write_p, int version,
+ int content_type, const void *buf,
+ size_t len, SSL *ssl, void *arg))
+{
+ SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb);
+}
+
+void SSL_CTX_set_not_resumable_session_callback(SSL_CTX *ctx,
+ int (*cb) (SSL *ssl,
+ int
+ is_forward_secure))
+{
+ SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB,
+ (void (*)(void))cb);
+}
+
+void SSL_set_not_resumable_session_callback(SSL *ssl,
+ int (*cb) (SSL *ssl,
+ int is_forward_secure))
+{
+ SSL_callback_ctrl(ssl, SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB,
+ (void (*)(void))cb);
+}
+
+/*
+ * Allocates new EVP_MD_CTX and sets pointer to it into given pointer
+ * variable, freeing EVP_MD_CTX previously stored in that variable, if any.
+ * If EVP_MD pointer is passed, initializes ctx with this |md|.
+ * Returns the newly allocated ctx;
+ */
+
+EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash, const EVP_MD *md)
+{
+ ssl_clear_hash_ctx(hash);
+ *hash = EVP_MD_CTX_new();
+ if (*hash == NULL || (md && EVP_DigestInit_ex(*hash, md, NULL) <= 0)) {
+ EVP_MD_CTX_free(*hash);
+ *hash = NULL;
+ return NULL;
+ }
+ return *hash;
+}
+
+void ssl_clear_hash_ctx(EVP_MD_CTX **hash)
+{
+
+ if (*hash)
+ EVP_MD_CTX_free(*hash);
+ *hash = NULL;
+}
+
+/* Retrieve handshake hashes */
+int ssl_handshake_hash(SSL *s, unsigned char *out, int outlen)
+{
+ EVP_MD_CTX *ctx = NULL;
+ EVP_MD_CTX *hdgst = s->s3->handshake_dgst;
+ int ret = EVP_MD_CTX_size(hdgst);
+ if (ret < 0 || ret > outlen) {
+ ret = 0;
+ goto err;
+ }
+ ctx = EVP_MD_CTX_new();
+ if (ctx == NULL) {
+ ret = 0;
+ goto err;
+ }
+ if (!EVP_MD_CTX_copy_ex(ctx, hdgst)
+ || EVP_DigestFinal_ex(ctx, out, NULL) <= 0)
+ ret = 0;
+ err:
+ EVP_MD_CTX_free(ctx);
+ return ret;
+}
+
+int SSL_session_reused(SSL *s)
+{
+ return s->hit;
+}
+
+int SSL_is_server(const SSL *s)
+{
+ return s->server;
+}
+
+#if OPENSSL_API_COMPAT < 0x10100000L
+void SSL_set_debug(SSL *s, int debug)
+{
+ /* Old function was do-nothing anyway... */
+ (void)s;
+ (void)debug;
+}
+#endif
+
+void SSL_set_security_level(SSL *s, int level)
+{
+ s->cert->sec_level = level;
+}
+
+int SSL_get_security_level(const SSL *s)
+{
+ return s->cert->sec_level;
+}
+
+void SSL_set_security_callback(SSL *s,
+ int (*cb) (const SSL *s, const SSL_CTX *ctx,
+ int op, int bits, int nid,
+ void *other, void *ex))
+{
+ s->cert->sec_cb = cb;
+}
+
+int (*SSL_get_security_callback(const SSL *s)) (const SSL *s,
+ const SSL_CTX *ctx, int op,
+ int bits, int nid, void *other,
+ void *ex) {
+ return s->cert->sec_cb;
+}
+
+void SSL_set0_security_ex_data(SSL *s, void *ex)
+{
+ s->cert->sec_ex = ex;
+}
+
+void *SSL_get0_security_ex_data(const SSL *s)
+{
+ return s->cert->sec_ex;
+}
+
+void SSL_CTX_set_security_level(SSL_CTX *ctx, int level)
+{
+ ctx->cert->sec_level = level;
+}
+
+int SSL_CTX_get_security_level(const SSL_CTX *ctx)
+{
+ return ctx->cert->sec_level;
+}
+
+void SSL_CTX_set_security_callback(SSL_CTX *ctx,
+ int (*cb) (const SSL *s, const SSL_CTX *ctx,
+ int op, int bits, int nid,
+ void *other, void *ex))
+{
+ ctx->cert->sec_cb = cb;
+}
+
+int (*SSL_CTX_get_security_callback(const SSL_CTX *ctx)) (const SSL *s,
+ const SSL_CTX *ctx,
+ int op, int bits,
+ int nid,
+ void *other,
+ void *ex) {
+ return ctx->cert->sec_cb;
+}
+
+void SSL_CTX_set0_security_ex_data(SSL_CTX *ctx, void *ex)
+{
+ ctx->cert->sec_ex = ex;
+}
+
+void *SSL_CTX_get0_security_ex_data(const SSL_CTX *ctx)
+{
+ return ctx->cert->sec_ex;
+}
+
+/*
+ * Get/Set/Clear options in SSL_CTX or SSL, formerly macros, now functions that
+ * can return unsigned long, instead of the generic long return value from the
+ * control interface.
+ */
+unsigned long SSL_CTX_get_options(const SSL_CTX *ctx)
+{
+ return ctx->options;
+}
+
+unsigned long SSL_get_options(const SSL *s)
+{
+ return s->options;
+}
+
+unsigned long SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op)
+{
+ return ctx->options |= op;
+}
+
+unsigned long SSL_set_options(SSL *s, unsigned long op)
+{
+ return s->options |= op;
+}
+
+unsigned long SSL_CTX_clear_options(SSL_CTX *ctx, unsigned long op)
+{
+ return ctx->options &= ~op;
+}
+
+unsigned long SSL_clear_options(SSL *s, unsigned long op)
+{
+ return s->options &= ~op;
+}
+
+STACK_OF(X509) *SSL_get0_verified_chain(const SSL *s)
+{
+ return s->verified_chain;
+}
+
+IMPLEMENT_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER, ssl_cipher_id);
+
+#ifndef OPENSSL_NO_CT
+
+/*
+ * Moves SCTs from the |src| stack to the |dst| stack.
+ * The source of each SCT will be set to |origin|.
+ * If |dst| points to a NULL pointer, a new stack will be created and owned by
+ * the caller.
+ * Returns the number of SCTs moved, or a negative integer if an error occurs.
+ */
+static int ct_move_scts(STACK_OF(SCT) **dst, STACK_OF(SCT) *src,
+ sct_source_t origin)
+{
+ int scts_moved = 0;
+ SCT *sct = NULL;
+
+ if (*dst == NULL) {
+ *dst = sk_SCT_new_null();
+ if (*dst == NULL) {
+ SSLerr(SSL_F_CT_MOVE_SCTS, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ while ((sct = sk_SCT_pop(src)) != NULL) {
+ if (SCT_set_source(sct, origin) != 1)
+ goto err;
+
+ if (sk_SCT_push(*dst, sct) <= 0)
+ goto err;
+ scts_moved += 1;
+ }
+
+ return scts_moved;
+ err:
+ if (sct != NULL)
+ sk_SCT_push(src, sct); /* Put the SCT back */
+ return -1;
+}
+
+/*
+ * Look for data collected during ServerHello and parse if found.
+ * Returns the number of SCTs extracted.
+ */
+static int ct_extract_tls_extension_scts(SSL *s)
+{
+ int scts_extracted = 0;
+
+ if (s->tlsext_scts != NULL) {
+ const unsigned char *p = s->tlsext_scts;
+ STACK_OF(SCT) *scts = o2i_SCT_LIST(NULL, &p, s->tlsext_scts_len);
+
+ scts_extracted = ct_move_scts(&s->scts, scts, SCT_SOURCE_TLS_EXTENSION);
+
+ SCT_LIST_free(scts);
+ }
+
+ return scts_extracted;
+}
+
+/*
+ * Checks for an OCSP response and then attempts to extract any SCTs found if it
+ * contains an SCT X509 extension. They will be stored in |s->scts|.
+ * Returns:
+ * - The number of SCTs extracted, assuming an OCSP response exists.
+ * - 0 if no OCSP response exists or it contains no SCTs.
+ * - A negative integer if an error occurs.
+ */
+static int ct_extract_ocsp_response_scts(SSL *s)
+{
+# ifndef OPENSSL_NO_OCSP
+ int scts_extracted = 0;
+ const unsigned char *p;
+ OCSP_BASICRESP *br = NULL;
+ OCSP_RESPONSE *rsp = NULL;
+ STACK_OF(SCT) *scts = NULL;
+ int i;
+
+ if (s->tlsext_ocsp_resp == NULL || s->tlsext_ocsp_resplen == 0)
+ goto err;
+
+ p = s->tlsext_ocsp_resp;
+ rsp = d2i_OCSP_RESPONSE(NULL, &p, s->tlsext_ocsp_resplen);
+ if (rsp == NULL)
+ goto err;
+
+ br = OCSP_response_get1_basic(rsp);
+ if (br == NULL)
+ goto err;
+
+ for (i = 0; i < OCSP_resp_count(br); ++i) {
+ OCSP_SINGLERESP *single = OCSP_resp_get0(br, i);
+
+ if (single == NULL)
+ continue;
+
+ scts =
+ OCSP_SINGLERESP_get1_ext_d2i(single, NID_ct_cert_scts, NULL, NULL);
+ scts_extracted =
+ ct_move_scts(&s->scts, scts, SCT_SOURCE_OCSP_STAPLED_RESPONSE);
+ if (scts_extracted < 0)
+ goto err;
+ }
+ err:
+ SCT_LIST_free(scts);
+ OCSP_BASICRESP_free(br);
+ OCSP_RESPONSE_free(rsp);
+ return scts_extracted;
+# else
+ /* Behave as if no OCSP response exists */
+ return 0;
+# endif
+}
+
+/*
+ * Attempts to extract SCTs from the peer certificate.
+ * Return the number of SCTs extracted, or a negative integer if an error
+ * occurs.
+ */
+static int ct_extract_x509v3_extension_scts(SSL *s)
+{
+ int scts_extracted = 0;
+ X509 *cert = s->session != NULL ? s->session->peer : NULL;
+
+ if (cert != NULL) {
+ STACK_OF(SCT) *scts =
+ X509_get_ext_d2i(cert, NID_ct_precert_scts, NULL, NULL);
+
+ scts_extracted =
+ ct_move_scts(&s->scts, scts, SCT_SOURCE_X509V3_EXTENSION);
+
+ SCT_LIST_free(scts);
+ }
+
+ return scts_extracted;
+}
+
+/*
+ * Attempts to find all received SCTs by checking TLS extensions, the OCSP
+ * response (if it exists) and X509v3 extensions in the certificate.
+ * Returns NULL if an error occurs.
+ */
+const STACK_OF(SCT) *SSL_get0_peer_scts(SSL *s)
+{
+ if (!s->scts_parsed) {
+ if (ct_extract_tls_extension_scts(s) < 0 ||
+ ct_extract_ocsp_response_scts(s) < 0 ||
+ ct_extract_x509v3_extension_scts(s) < 0)
+ goto err;
+
+ s->scts_parsed = 1;
+ }
+ return s->scts;
+ err:
+ return NULL;
+}
+
+static int ct_permissive(const CT_POLICY_EVAL_CTX * ctx,
+ const STACK_OF(SCT) *scts, void *unused_arg)
+{
+ return 1;
+}
+
+static int ct_strict(const CT_POLICY_EVAL_CTX * ctx,
+ const STACK_OF(SCT) *scts, void *unused_arg)
+{
+ int count = scts != NULL ? sk_SCT_num(scts) : 0;
+ int i;
+
+ for (i = 0; i < count; ++i) {
+ SCT *sct = sk_SCT_value(scts, i);
+ int status = SCT_get_validation_status(sct);
+
+ if (status == SCT_VALIDATION_STATUS_VALID)
+ return 1;
+ }
+ SSLerr(SSL_F_CT_STRICT, SSL_R_NO_VALID_SCTS);
+ return 0;
+}
+
+int SSL_set_ct_validation_callback(SSL *s, ssl_ct_validation_cb callback,
+ void *arg)
+{
+ /*
+ * Since code exists that uses the custom extension handler for CT, look
+ * for this and throw an error if they have already registered to use CT.
+ */
+ if (callback != NULL && SSL_CTX_has_client_custom_ext(s->ctx,
+ TLSEXT_TYPE_signed_certificate_timestamp))
+ {
+ SSLerr(SSL_F_SSL_SET_CT_VALIDATION_CALLBACK,
+ SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED);
+ return 0;
+ }
+
+ if (callback != NULL) {
+ /*
+ * If we are validating CT, then we MUST accept SCTs served via OCSP
+ */
+ if (!SSL_set_tlsext_status_type(s, TLSEXT_STATUSTYPE_ocsp))
+ return 0;
+ }
+
+ s->ct_validation_callback = callback;
+ s->ct_validation_callback_arg = arg;
+
+ return 1;
+}
+
+int SSL_CTX_set_ct_validation_callback(SSL_CTX *ctx,
+ ssl_ct_validation_cb callback, void *arg)
+{
+ /*
+ * Since code exists that uses the custom extension handler for CT, look for
+ * this and throw an error if they have already registered to use CT.
+ */
+ if (callback != NULL && SSL_CTX_has_client_custom_ext(ctx,
+ TLSEXT_TYPE_signed_certificate_timestamp))
+ {
+ SSLerr(SSL_F_SSL_CTX_SET_CT_VALIDATION_CALLBACK,
+ SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED);
+ return 0;
+ }
+
+ ctx->ct_validation_callback = callback;
+ ctx->ct_validation_callback_arg = arg;
+ return 1;
+}
+
+int SSL_ct_is_enabled(const SSL *s)
+{
+ return s->ct_validation_callback != NULL;
+}
+
+int SSL_CTX_ct_is_enabled(const SSL_CTX *ctx)
+{
+ return ctx->ct_validation_callback != NULL;
+}
+
+int ssl_validate_ct(SSL *s)
+{
+ int ret = 0;
+ X509 *cert = s->session != NULL ? s->session->peer : NULL;
+ X509 *issuer;
+ SSL_DANE *dane = &s->dane;
+ CT_POLICY_EVAL_CTX *ctx = NULL;
+ const STACK_OF(SCT) *scts;
+
+ /*
+ * If no callback is set, the peer is anonymous, or its chain is invalid,
+ * skip SCT validation - just return success. Applications that continue
+ * handshakes without certificates, with unverified chains, or pinned leaf
+ * certificates are outside the scope of the WebPKI and CT.
+ *
+ * The above exclusions notwithstanding the vast majority of peers will
+ * have rather ordinary certificate chains validated by typical
+ * applications that perform certificate verification and therefore will
+ * process SCTs when enabled.
+ */
+ if (s->ct_validation_callback == NULL || cert == NULL ||
+ s->verify_result != X509_V_OK ||
+ s->verified_chain == NULL || sk_X509_num(s->verified_chain) <= 1)
+ return 1;
+
+ /*
+ * CT not applicable for chains validated via DANE-TA(2) or DANE-EE(3)
+ * trust-anchors. See https://tools.ietf.org/html/rfc7671#section-4.2
+ */
+ if (DANETLS_ENABLED(dane) && dane->mtlsa != NULL) {
+ switch (dane->mtlsa->usage) {
+ case DANETLS_USAGE_DANE_TA:
+ case DANETLS_USAGE_DANE_EE:
+ return 1;
+ }
+ }
+
+ ctx = CT_POLICY_EVAL_CTX_new();
+ if (ctx == NULL) {
+ SSLerr(SSL_F_SSL_VALIDATE_CT, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+
+ issuer = sk_X509_value(s->verified_chain, 1);
+ CT_POLICY_EVAL_CTX_set1_cert(ctx, cert);
+ CT_POLICY_EVAL_CTX_set1_issuer(ctx, issuer);
+ CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(ctx, s->ctx->ctlog_store);
+ CT_POLICY_EVAL_CTX_set_time(
+ ctx, (uint64_t)SSL_SESSION_get_time(SSL_get0_session(s)) * 1000);
+
+ scts = SSL_get0_peer_scts(s);
+
+ /*
+ * This function returns success (> 0) only when all the SCTs are valid, 0
+ * when some are invalid, and < 0 on various internal errors (out of
+ * memory, etc.). Having some, or even all, invalid SCTs is not sufficient
+ * reason to abort the handshake, that decision is up to the callback.
+ * Therefore, we error out only in the unexpected case that the return
+ * value is negative.
+ *
+ * XXX: One might well argue that the return value of this function is an
+ * unfortunate design choice. Its job is only to determine the validation
+ * status of each of the provided SCTs. So long as it correctly separates
+ * the wheat from the chaff it should return success. Failure in this case
+ * ought to correspond to an inability to carry out its duties.
+ */
+ if (SCT_LIST_validate(scts, ctx) < 0) {
+ SSLerr(SSL_F_SSL_VALIDATE_CT, SSL_R_SCT_VERIFICATION_FAILED);
+ goto end;
+ }
+
+ ret = s->ct_validation_callback(ctx, scts, s->ct_validation_callback_arg);
+ if (ret < 0)
+ ret = 0; /* This function returns 0 on failure */
+
+ end:
+ CT_POLICY_EVAL_CTX_free(ctx);
+ /*
+ * With SSL_VERIFY_NONE the session may be cached and re-used despite a
+ * failure return code here. Also the application may wish the complete
+ * the handshake, and then disconnect cleanly at a higher layer, after
+ * checking the verification status of the completed connection.
+ *
+ * We therefore force a certificate verification failure which will be
+ * visible via SSL_get_verify_result() and cached as part of any resumed
+ * session.
+ *
+ * Note: the permissive callback is for information gathering only, always
+ * returns success, and does not affect verification status. Only the
+ * strict callback or a custom application-specified callback can trigger
+ * connection failure or record a verification error.
+ */
+ if (ret <= 0)
+ s->verify_result = X509_V_ERR_NO_VALID_SCTS;
+ return ret;
+}
+
+int SSL_CTX_enable_ct(SSL_CTX *ctx, int validation_mode)
+{
+ switch (validation_mode) {
+ default:
+ SSLerr(SSL_F_SSL_CTX_ENABLE_CT, SSL_R_INVALID_CT_VALIDATION_TYPE);
+ return 0;
+ case SSL_CT_VALIDATION_PERMISSIVE:
+ return SSL_CTX_set_ct_validation_callback(ctx, ct_permissive, NULL);
+ case SSL_CT_VALIDATION_STRICT:
+ return SSL_CTX_set_ct_validation_callback(ctx, ct_strict, NULL);
+ }
+}
+
+int SSL_enable_ct(SSL *s, int validation_mode)
+{
+ switch (validation_mode) {
+ default:
+ SSLerr(SSL_F_SSL_ENABLE_CT, SSL_R_INVALID_CT_VALIDATION_TYPE);
+ return 0;
+ case SSL_CT_VALIDATION_PERMISSIVE:
+ return SSL_set_ct_validation_callback(s, ct_permissive, NULL);
+ case SSL_CT_VALIDATION_STRICT:
+ return SSL_set_ct_validation_callback(s, ct_strict, NULL);
+ }
+}
+
+int SSL_CTX_set_default_ctlog_list_file(SSL_CTX *ctx)
+{
+ return CTLOG_STORE_load_default_file(ctx->ctlog_store);
+}
+
+int SSL_CTX_set_ctlog_list_file(SSL_CTX *ctx, const char *path)
+{
+ return CTLOG_STORE_load_file(ctx->ctlog_store, path);
+}
+
+void SSL_CTX_set0_ctlog_store(SSL_CTX *ctx, CTLOG_STORE * logs)
+{
+ CTLOG_STORE_free(ctx->ctlog_store);
+ ctx->ctlog_store = logs;
+}
+
+const CTLOG_STORE *SSL_CTX_get0_ctlog_store(const SSL_CTX *ctx)
+{
+ return ctx->ctlog_store;
+}
+
+#endif
diff --git a/openssl-1.1.0h/ssl/ssl_locl.h b/openssl-1.1.0h/ssl/ssl_locl.h
new file mode 100644
index 0000000..d86bd7e
--- /dev/null
+++ b/openssl-1.1.0h/ssl/ssl_locl.h
@@ -0,0 +1,2133 @@
+/*
+ * Copyright 1995-2016 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
+ */
+
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#ifndef HEADER_SSL_LOCL_H
+# define HEADER_SSL_LOCL_H
+# include <stdlib.h>
+# include <time.h>
+# include <string.h>
+# include <errno.h>
+
+# include "e_os.h"
+# if defined(__unix) || defined(__unix__)
+# include <sys/time.h> /* struct timeval for DTLS */
+# endif
+
+# include <openssl/buffer.h>
+# include <openssl/comp.h>
+# include <openssl/bio.h>
+# include <openssl/stack.h>
+# include <openssl/rsa.h>
+# include <openssl/dsa.h>
+# include <openssl/err.h>
+# include <openssl/ssl.h>
+# include <openssl/async.h>
+# include <openssl/symhacks.h>
+# include <openssl/ct.h>
+# include "record/record.h"
+# include "statem/statem.h"
+# include "packet_locl.h"
+# include "internal/dane.h"
+
+# ifdef OPENSSL_BUILD_SHLIBSSL
+# undef OPENSSL_EXTERN
+# define OPENSSL_EXTERN OPENSSL_EXPORT
+# endif
+
+# undef PKCS1_CHECK
+
+# define c2l(c,l) (l = ((unsigned long)(*((c)++))) , \
+ l|=(((unsigned long)(*((c)++)))<< 8), \
+ l|=(((unsigned long)(*((c)++)))<<16), \
+ l|=(((unsigned long)(*((c)++)))<<24))
+
+/* NOTE - c is not incremented as per c2l */
+# define c2ln(c,l1,l2,n) { \
+ c+=n; \
+ l1=l2=0; \
+ switch (n) { \
+ case 8: l2 =((unsigned long)(*(--(c))))<<24; \
+ case 7: l2|=((unsigned long)(*(--(c))))<<16; \
+ case 6: l2|=((unsigned long)(*(--(c))))<< 8; \
+ case 5: l2|=((unsigned long)(*(--(c)))); \
+ case 4: l1 =((unsigned long)(*(--(c))))<<24; \
+ case 3: l1|=((unsigned long)(*(--(c))))<<16; \
+ case 2: l1|=((unsigned long)(*(--(c))))<< 8; \
+ case 1: l1|=((unsigned long)(*(--(c)))); \
+ } \
+ }
+
+# define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
+ *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>16)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>24)&0xff))
+
+# define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24, \
+ l|=((unsigned long)(*((c)++)))<<16, \
+ l|=((unsigned long)(*((c)++)))<< 8, \
+ l|=((unsigned long)(*((c)++))))
+
+# define n2l8(c,l) (l =((uint64_t)(*((c)++)))<<56, \
+ l|=((uint64_t)(*((c)++)))<<48, \
+ l|=((uint64_t)(*((c)++)))<<40, \
+ l|=((uint64_t)(*((c)++)))<<32, \
+ l|=((uint64_t)(*((c)++)))<<24, \
+ l|=((uint64_t)(*((c)++)))<<16, \
+ l|=((uint64_t)(*((c)++)))<< 8, \
+ l|=((uint64_t)(*((c)++))))
+
+
+# define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>16)&0xff), \
+ *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
+ *((c)++)=(unsigned char)(((l) )&0xff))
+
+# define l2n6(l,c) (*((c)++)=(unsigned char)(((l)>>40)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>32)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>24)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>16)&0xff), \
+ *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
+ *((c)++)=(unsigned char)(((l) )&0xff))
+
+# define l2n8(l,c) (*((c)++)=(unsigned char)(((l)>>56)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>48)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>40)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>32)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>24)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>16)&0xff), \
+ *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
+ *((c)++)=(unsigned char)(((l) )&0xff))
+
+/* NOTE - c is not incremented as per l2c */
+# define l2cn(l1,l2,c,n) { \
+ c+=n; \
+ switch (n) { \
+ case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \
+ case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \
+ case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \
+ case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \
+ case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \
+ case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \
+ case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \
+ case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \
+ } \
+ }
+
+# define n2s(c,s) ((s=(((unsigned int)((c)[0]))<< 8)| \
+ (((unsigned int)((c)[1])) )),(c)+=2)
+# define s2n(s,c) (((c)[0]=(unsigned char)(((s)>> 8)&0xff), \
+ (c)[1]=(unsigned char)(((s) )&0xff)),(c)+=2)
+
+# define n2l3(c,l) ((l =(((unsigned long)((c)[0]))<<16)| \
+ (((unsigned long)((c)[1]))<< 8)| \
+ (((unsigned long)((c)[2])) )),(c)+=3)
+
+# define l2n3(l,c) (((c)[0]=(unsigned char)(((l)>>16)&0xff), \
+ (c)[1]=(unsigned char)(((l)>> 8)&0xff), \
+ (c)[2]=(unsigned char)(((l) )&0xff)),(c)+=3)
+
+/*
+ * DTLS version numbers are strange because they're inverted. Except for
+ * DTLS1_BAD_VER, which should be considered "lower" than the rest.
+ */
+# define dtls_ver_ordinal(v1) (((v1) == DTLS1_BAD_VER) ? 0xff00 : (v1))
+# define DTLS_VERSION_GT(v1, v2) (dtls_ver_ordinal(v1) < dtls_ver_ordinal(v2))
+# define DTLS_VERSION_GE(v1, v2) (dtls_ver_ordinal(v1) <= dtls_ver_ordinal(v2))
+# define DTLS_VERSION_LT(v1, v2) (dtls_ver_ordinal(v1) > dtls_ver_ordinal(v2))
+# define DTLS_VERSION_LE(v1, v2) (dtls_ver_ordinal(v1) >= dtls_ver_ordinal(v2))
+
+/* LOCAL STUFF */
+
+# define SSL_DECRYPT 0
+# define SSL_ENCRYPT 1
+
+# define TWO_BYTE_BIT 0x80
+# define SEC_ESC_BIT 0x40
+# define TWO_BYTE_MASK 0x7fff
+# define THREE_BYTE_MASK 0x3fff
+
+# define INC32(a) ((a)=((a)+1)&0xffffffffL)
+# define DEC32(a) ((a)=((a)-1)&0xffffffffL)
+# define MAX_MAC_SIZE 20 /* up from 16 for SSLv3 */
+
+/*
+ * Define the Bitmasks for SSL_CIPHER.algorithms.
+ * This bits are used packed as dense as possible. If new methods/ciphers
+ * etc will be added, the bits a likely to change, so this information
+ * is for internal library use only, even though SSL_CIPHER.algorithms
+ * can be publicly accessed.
+ * Use the according functions for cipher management instead.
+ *
+ * The bit mask handling in the selection and sorting scheme in
+ * ssl_create_cipher_list() has only limited capabilities, reflecting
+ * that the different entities within are mutually exclusive:
+ * ONLY ONE BIT PER MASK CAN BE SET AT A TIME.
+ */
+
+/* Bits for algorithm_mkey (key exchange algorithm) */
+/* RSA key exchange */
+# define SSL_kRSA 0x00000001U
+/* tmp DH key no DH cert */
+# define SSL_kDHE 0x00000002U
+/* synonym */
+# define SSL_kEDH SSL_kDHE
+/* ephemeral ECDH */
+# define SSL_kECDHE 0x00000004U
+/* synonym */
+# define SSL_kEECDH SSL_kECDHE
+/* PSK */
+# define SSL_kPSK 0x00000008U
+/* GOST key exchange */
+# define SSL_kGOST 0x00000010U
+/* SRP */
+# define SSL_kSRP 0x00000020U
+
+# define SSL_kRSAPSK 0x00000040U
+# define SSL_kECDHEPSK 0x00000080U
+# define SSL_kDHEPSK 0x00000100U
+
+/* all PSK */
+
+# define SSL_PSK (SSL_kPSK | SSL_kRSAPSK | SSL_kECDHEPSK | SSL_kDHEPSK)
+
+/* Bits for algorithm_auth (server authentication) */
+/* RSA auth */
+# define SSL_aRSA 0x00000001U
+/* DSS auth */
+# define SSL_aDSS 0x00000002U
+/* no auth (i.e. use ADH or AECDH) */
+# define SSL_aNULL 0x00000004U
+/* ECDSA auth*/
+# define SSL_aECDSA 0x00000008U
+/* PSK auth */
+# define SSL_aPSK 0x00000010U
+/* GOST R 34.10-2001 signature auth */
+# define SSL_aGOST01 0x00000020U
+/* SRP auth */
+# define SSL_aSRP 0x00000040U
+/* GOST R 34.10-2012 signature auth */
+# define SSL_aGOST12 0x00000080U
+
+/* Bits for algorithm_enc (symmetric encryption) */
+# define SSL_DES 0x00000001U
+# define SSL_3DES 0x00000002U
+# define SSL_RC4 0x00000004U
+# define SSL_RC2 0x00000008U
+# define SSL_IDEA 0x00000010U
+# define SSL_eNULL 0x00000020U
+# define SSL_AES128 0x00000040U
+# define SSL_AES256 0x00000080U
+# define SSL_CAMELLIA128 0x00000100U
+# define SSL_CAMELLIA256 0x00000200U
+# define SSL_eGOST2814789CNT 0x00000400U
+# define SSL_SEED 0x00000800U
+# define SSL_AES128GCM 0x00001000U
+# define SSL_AES256GCM 0x00002000U
+# define SSL_AES128CCM 0x00004000U
+# define SSL_AES256CCM 0x00008000U
+# define SSL_AES128CCM8 0x00010000U
+# define SSL_AES256CCM8 0x00020000U
+# define SSL_eGOST2814789CNT12 0x00040000U
+# define SSL_CHACHA20POLY1305 0x00080000U
+
+# define SSL_AESGCM (SSL_AES128GCM | SSL_AES256GCM)
+# define SSL_AESCCM (SSL_AES128CCM | SSL_AES256CCM | SSL_AES128CCM8 | SSL_AES256CCM8)
+# define SSL_AES (SSL_AES128|SSL_AES256|SSL_AESGCM|SSL_AESCCM)
+# define SSL_CAMELLIA (SSL_CAMELLIA128|SSL_CAMELLIA256)
+# define SSL_CHACHA20 (SSL_CHACHA20POLY1305)
+
+/* Bits for algorithm_mac (symmetric authentication) */
+
+# define SSL_MD5 0x00000001U
+# define SSL_SHA1 0x00000002U
+# define SSL_GOST94 0x00000004U
+# define SSL_GOST89MAC 0x00000008U
+# define SSL_SHA256 0x00000010U
+# define SSL_SHA384 0x00000020U
+/* Not a real MAC, just an indication it is part of cipher */
+# define SSL_AEAD 0x00000040U
+# define SSL_GOST12_256 0x00000080U
+# define SSL_GOST89MAC12 0x00000100U
+# define SSL_GOST12_512 0x00000200U
+
+/*
+ * When adding new digest in the ssl_ciph.c and increment SSL_MD_NUM_IDX make
+ * sure to update this constant too
+ */
+
+# define SSL_MD_MD5_IDX 0
+# define SSL_MD_SHA1_IDX 1
+# define SSL_MD_GOST94_IDX 2
+# define SSL_MD_GOST89MAC_IDX 3
+# define SSL_MD_SHA256_IDX 4
+# define SSL_MD_SHA384_IDX 5
+# define SSL_MD_GOST12_256_IDX 6
+# define SSL_MD_GOST89MAC12_IDX 7
+# define SSL_MD_GOST12_512_IDX 8
+# define SSL_MD_MD5_SHA1_IDX 9
+# define SSL_MD_SHA224_IDX 10
+# define SSL_MD_SHA512_IDX 11
+# define SSL_MAX_DIGEST 12
+
+/* Bits for algorithm2 (handshake digests and other extra flags) */
+
+/* Bits 0-7 are handshake MAC */
+# define SSL_HANDSHAKE_MAC_MASK 0xFF
+# define SSL_HANDSHAKE_MAC_MD5_SHA1 SSL_MD_MD5_SHA1_IDX
+# define SSL_HANDSHAKE_MAC_SHA256 SSL_MD_SHA256_IDX
+# define SSL_HANDSHAKE_MAC_SHA384 SSL_MD_SHA384_IDX
+# define SSL_HANDSHAKE_MAC_GOST94 SSL_MD_GOST94_IDX
+# define SSL_HANDSHAKE_MAC_GOST12_256 SSL_MD_GOST12_256_IDX
+# define SSL_HANDSHAKE_MAC_GOST12_512 SSL_MD_GOST12_512_IDX
+# define SSL_HANDSHAKE_MAC_DEFAULT SSL_HANDSHAKE_MAC_MD5_SHA1
+
+/* Bits 8-15 bits are PRF */
+# define TLS1_PRF_DGST_SHIFT 8
+# define TLS1_PRF_SHA1_MD5 (SSL_MD_MD5_SHA1_IDX << TLS1_PRF_DGST_SHIFT)
+# define TLS1_PRF_SHA256 (SSL_MD_SHA256_IDX << TLS1_PRF_DGST_SHIFT)
+# define TLS1_PRF_SHA384 (SSL_MD_SHA384_IDX << TLS1_PRF_DGST_SHIFT)
+# define TLS1_PRF_GOST94 (SSL_MD_GOST94_IDX << TLS1_PRF_DGST_SHIFT)
+# define TLS1_PRF_GOST12_256 (SSL_MD_GOST12_256_IDX << TLS1_PRF_DGST_SHIFT)
+# define TLS1_PRF_GOST12_512 (SSL_MD_GOST12_512_IDX << TLS1_PRF_DGST_SHIFT)
+# define TLS1_PRF (SSL_MD_MD5_SHA1_IDX << TLS1_PRF_DGST_SHIFT)
+
+/*
+ * Stream MAC for GOST ciphersuites from cryptopro draft (currently this also
+ * goes into algorithm2)
+ */
+# define TLS1_STREAM_MAC 0x10000
+
+# define SSL_STRONG_MASK 0x0000001FU
+# define SSL_DEFAULT_MASK 0X00000020U
+
+# define SSL_STRONG_NONE 0x00000001U
+# define SSL_LOW 0x00000002U
+# define SSL_MEDIUM 0x00000004U
+# define SSL_HIGH 0x00000008U
+# define SSL_FIPS 0x00000010U
+# define SSL_NOT_DEFAULT 0x00000020U
+
+/* we have used 0000003f - 26 bits left to go */
+
+/* Check if an SSL structure is using DTLS */
+# define SSL_IS_DTLS(s) (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS)
+/* See if we need explicit IV */
+# define SSL_USE_EXPLICIT_IV(s) \
+ (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_EXPLICIT_IV)
+/*
+ * See if we use signature algorithms extension and signature algorithm
+ * before signatures.
+ */
+# define SSL_USE_SIGALGS(s) \
+ (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_SIGALGS)
+/*
+ * Allow TLS 1.2 ciphersuites: applies to DTLS 1.2 as well as TLS 1.2: may
+ * apply to others in future.
+ */
+# define SSL_USE_TLS1_2_CIPHERS(s) \
+ (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_TLS1_2_CIPHERS)
+/*
+ * Determine if a client can use TLS 1.2 ciphersuites: can't rely on method
+ * flags because it may not be set to correct version yet.
+ */
+# define SSL_CLIENT_USE_TLS1_2_CIPHERS(s) \
+ ((!SSL_IS_DTLS(s) && s->client_version >= TLS1_2_VERSION) || \
+ (SSL_IS_DTLS(s) && DTLS_VERSION_GE(s->client_version, DTLS1_2_VERSION)))
+/*
+ * Determine if a client should send signature algorithms extension:
+ * as with TLS1.2 cipher we can't rely on method flags.
+ */
+# define SSL_CLIENT_USE_SIGALGS(s) \
+ SSL_CLIENT_USE_TLS1_2_CIPHERS(s)
+
+# define SSL_READ_ETM(s) (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC_READ)
+# define SSL_WRITE_ETM(s) (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE)
+
+/* Mostly for SSLv3 */
+# define SSL_PKEY_RSA_ENC 0
+# define SSL_PKEY_RSA_SIGN 1
+# define SSL_PKEY_DSA_SIGN 2
+# define SSL_PKEY_ECC 3
+# define SSL_PKEY_GOST01 4
+# define SSL_PKEY_GOST12_256 5
+# define SSL_PKEY_GOST12_512 6
+# define SSL_PKEY_NUM 7
+/*
+ * Pseudo-constant. GOST cipher suites can use different certs for 1
+ * SSL_CIPHER. So let's see which one we have in fact.
+ */
+# define SSL_PKEY_GOST_EC SSL_PKEY_NUM+1
+
+/*-
+ * SSL_kRSA <- RSA_ENC
+ * SSL_kDH <- DH_ENC & (RSA_ENC | RSA_SIGN | DSA_SIGN)
+ * SSL_kDHE <- RSA_ENC | RSA_SIGN | DSA_SIGN
+ * SSL_aRSA <- RSA_ENC | RSA_SIGN
+ * SSL_aDSS <- DSA_SIGN
+ */
+
+/*-
+#define CERT_INVALID 0
+#define CERT_PUBLIC_KEY 1
+#define CERT_PRIVATE_KEY 2
+*/
+
+/* CipherSuite length. SSLv3 and all TLS versions. */
+# define TLS_CIPHER_LEN 2
+/* used to hold info on the particular ciphers used */
+struct ssl_cipher_st {
+ uint32_t valid;
+ const char *name; /* text name */
+ uint32_t id; /* id, 4 bytes, first is version */
+ /*
+ * changed in 1.0.0: these four used to be portions of a single value
+ * 'algorithms'
+ */
+ uint32_t algorithm_mkey; /* key exchange algorithm */
+ uint32_t algorithm_auth; /* server authentication */
+ uint32_t algorithm_enc; /* symmetric encryption */
+ uint32_t algorithm_mac; /* symmetric authentication */
+ int min_tls; /* minimum SSL/TLS protocol version */
+ int max_tls; /* maximum SSL/TLS protocol version */
+ int min_dtls; /* minimum DTLS protocol version */
+ int max_dtls; /* maximum DTLS protocol version */
+ uint32_t algo_strength; /* strength and export flags */
+ uint32_t algorithm2; /* Extra flags */
+ int32_t strength_bits; /* Number of bits really used */
+ uint32_t alg_bits; /* Number of bits for algorithm */
+};
+
+/* Used to hold SSL/TLS functions */
+struct ssl_method_st {
+ int version;
+ unsigned flags;
+ unsigned long mask;
+ int (*ssl_new) (SSL *s);
+ void (*ssl_clear) (SSL *s);
+ void (*ssl_free) (SSL *s);
+ int (*ssl_accept) (SSL *s);
+ int (*ssl_connect) (SSL *s);
+ int (*ssl_read) (SSL *s, void *buf, int len);
+ int (*ssl_peek) (SSL *s, void *buf, int len);
+ int (*ssl_write) (SSL *s, const void *buf, int len);
+ int (*ssl_shutdown) (SSL *s);
+ int (*ssl_renegotiate) (SSL *s);
+ int (*ssl_renegotiate_check) (SSL *s);
+ int (*ssl_read_bytes) (SSL *s, int type, int *recvd_type,
+ unsigned char *buf, int len, int peek);
+ int (*ssl_write_bytes) (SSL *s, int type, const void *buf_, int len);
+ int (*ssl_dispatch_alert) (SSL *s);
+ long (*ssl_ctrl) (SSL *s, int cmd, long larg, void *parg);
+ long (*ssl_ctx_ctrl) (SSL_CTX *ctx, int cmd, long larg, void *parg);
+ const SSL_CIPHER *(*get_cipher_by_char) (const unsigned char *ptr);
+ int (*put_cipher_by_char) (const SSL_CIPHER *cipher, unsigned char *ptr);
+ int (*ssl_pending) (const SSL *s);
+ int (*num_ciphers) (void);
+ const SSL_CIPHER *(*get_cipher) (unsigned ncipher);
+ long (*get_timeout) (void);
+ const struct ssl3_enc_method *ssl3_enc; /* Extra SSLv3/TLS stuff */
+ int (*ssl_version) (void);
+ long (*ssl_callback_ctrl) (SSL *s, int cb_id, void (*fp) (void));
+ long (*ssl_ctx_callback_ctrl) (SSL_CTX *s, int cb_id, void (*fp) (void));
+};
+
+/*-
+ * Lets make this into an ASN.1 type structure as follows
+ * SSL_SESSION_ID ::= SEQUENCE {
+ * version INTEGER, -- structure version number
+ * SSLversion INTEGER, -- SSL version number
+ * Cipher OCTET STRING, -- the 3 byte cipher ID
+ * Session_ID OCTET STRING, -- the Session ID
+ * Master_key OCTET STRING, -- the master key
+ * Key_Arg [ 0 ] IMPLICIT OCTET STRING, -- the optional Key argument
+ * Time [ 1 ] EXPLICIT INTEGER, -- optional Start Time
+ * Timeout [ 2 ] EXPLICIT INTEGER, -- optional Timeout ins seconds
+ * Peer [ 3 ] EXPLICIT X509, -- optional Peer Certificate
+ * Session_ID_context [ 4 ] EXPLICIT OCTET STRING, -- the Session ID context
+ * Verify_result [ 5 ] EXPLICIT INTEGER, -- X509_V_... code for `Peer'
+ * HostName [ 6 ] EXPLICIT OCTET STRING, -- optional HostName from servername TLS extension
+ * PSK_identity_hint [ 7 ] EXPLICIT OCTET STRING, -- optional PSK identity hint
+ * PSK_identity [ 8 ] EXPLICIT OCTET STRING, -- optional PSK identity
+ * Ticket_lifetime_hint [9] EXPLICIT INTEGER, -- server's lifetime hint for session ticket
+ * Ticket [10] EXPLICIT OCTET STRING, -- session ticket (clients only)
+ * Compression_meth [11] EXPLICIT OCTET STRING, -- optional compression method
+ * SRP_username [ 12 ] EXPLICIT OCTET STRING -- optional SRP username
+ * flags [ 13 ] EXPLICIT INTEGER -- optional flags
+ * }
+ * Look in ssl/ssl_asn1.c for more details
+ * I'm using EXPLICIT tags so I can read the damn things using asn1parse :-).
+ */
+struct ssl_session_st {
+ int ssl_version; /* what ssl version session info is being kept
+ * in here? */
+ int master_key_length;
+ unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH];
+ /* session_id - valid? */
+ unsigned int session_id_length;
+ unsigned char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH];
+ /*
+ * this is used to determine whether the session is being reused in the
+ * appropriate context. It is up to the application to set this, via
+ * SSL_new
+ */
+ unsigned int sid_ctx_length;
+ unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
+# ifndef OPENSSL_NO_PSK
+ char *psk_identity_hint;
+ char *psk_identity;
+# endif
+ /*
+ * Used to indicate that session resumption is not allowed. Applications
+ * can also set this bit for a new session via not_resumable_session_cb
+ * to disable session caching and tickets.
+ */
+ int not_resumable;
+ /* This is the cert and type for the other end. */
+ X509 *peer;
+ int peer_type;
+ /* Certificate chain peer sent */
+ STACK_OF(X509) *peer_chain;
+ /*
+ * when app_verify_callback accepts a session where the peer's
+ * certificate is not ok, we must remember the error for session reuse:
+ */
+ long verify_result; /* only for servers */
+ int references;
+ long timeout;
+ long time;
+ unsigned int compress_meth; /* Need to lookup the method */
+ const SSL_CIPHER *cipher;
+ unsigned long cipher_id; /* when ASN.1 loaded, this needs to be used to
+ * load the 'cipher' structure */
+ STACK_OF(SSL_CIPHER) *ciphers; /* shared ciphers? */
+ CRYPTO_EX_DATA ex_data; /* application specific data */
+ /*
+ * These are used to make removal of session-ids more efficient and to
+ * implement a maximum cache size.
+ */
+ struct ssl_session_st *prev, *next;
+ char *tlsext_hostname;
+# ifndef OPENSSL_NO_EC
+ size_t tlsext_ecpointformatlist_length;
+ unsigned char *tlsext_ecpointformatlist; /* peer's list */
+ size_t tlsext_ellipticcurvelist_length;
+ unsigned char *tlsext_ellipticcurvelist; /* peer's list */
+# endif /* OPENSSL_NO_EC */
+ /* RFC4507 info */
+ unsigned char *tlsext_tick; /* Session ticket */
+ size_t tlsext_ticklen; /* Session ticket length */
+ unsigned long tlsext_tick_lifetime_hint; /* Session lifetime hint in
+ * seconds */
+# ifndef OPENSSL_NO_SRP
+ char *srp_username;
+# endif
+ uint32_t flags;
+ CRYPTO_RWLOCK *lock;
+};
+
+/* Extended master secret support */
+# define SSL_SESS_FLAG_EXTMS 0x1
+
+# ifndef OPENSSL_NO_SRP
+
+typedef struct srp_ctx_st {
+ /* param for all the callbacks */
+ void *SRP_cb_arg;
+ /* set client Hello login callback */
+ int (*TLS_ext_srp_username_callback) (SSL *, int *, void *);
+ /* set SRP N/g param callback for verification */
+ int (*SRP_verify_param_callback) (SSL *, void *);
+ /* set SRP client passwd callback */
+ char *(*SRP_give_srp_client_pwd_callback) (SSL *, void *);
+ char *login;
+ BIGNUM *N, *g, *s, *B, *A;
+ BIGNUM *a, *b, *v;
+ char *info;
+ int strength;
+ unsigned long srp_Mask;
+} SRP_CTX;
+
+# endif
+
+struct ssl_comp_st {
+ int id;
+ const char *name;
+ COMP_METHOD *method;
+};
+
+DEFINE_LHASH_OF(SSL_SESSION);
+/* Needed in ssl_cert.c */
+DEFINE_LHASH_OF(X509_NAME);
+
+# define TLSEXT_KEYNAME_LENGTH 16
+
+struct ssl_ctx_st {
+ const SSL_METHOD *method;
+ STACK_OF(SSL_CIPHER) *cipher_list;
+ /* same as above but sorted for lookup */
+ STACK_OF(SSL_CIPHER) *cipher_list_by_id;
+ struct x509_store_st /* X509_STORE */ *cert_store;
+ LHASH_OF(SSL_SESSION) *sessions;
+ /*
+ * Most session-ids that will be cached, default is
+ * SSL_SESSION_CACHE_MAX_SIZE_DEFAULT. 0 is unlimited.
+ */
+ unsigned long session_cache_size;
+ struct ssl_session_st *session_cache_head;
+ struct ssl_session_st *session_cache_tail;
+ /*
+ * This can have one of 2 values, ored together, SSL_SESS_CACHE_CLIENT,
+ * SSL_SESS_CACHE_SERVER, Default is SSL_SESSION_CACHE_SERVER, which
+ * means only SSL_accept will cache SSL_SESSIONS.
+ */
+ uint32_t session_cache_mode;
+ /*
+ * If timeout is not 0, it is the default timeout value set when
+ * SSL_new() is called. This has been put in to make life easier to set
+ * things up
+ */
+ long session_timeout;
+ /*
+ * If this callback is not null, it will be called each time a session id
+ * is added to the cache. If this function returns 1, it means that the
+ * callback will do a SSL_SESSION_free() when it has finished using it.
+ * Otherwise, on 0, it means the callback has finished with it. If
+ * remove_session_cb is not null, it will be called when a session-id is
+ * removed from the cache. After the call, OpenSSL will
+ * SSL_SESSION_free() it.
+ */
+ int (*new_session_cb) (struct ssl_st *ssl, SSL_SESSION *sess);
+ void (*remove_session_cb) (struct ssl_ctx_st *ctx, SSL_SESSION *sess);
+ SSL_SESSION *(*get_session_cb) (struct ssl_st *ssl,
+ const unsigned char *data, int len,
+ int *copy);
+ struct {
+ int sess_connect; /* SSL new conn - started */
+ int sess_connect_renegotiate; /* SSL reneg - requested */
+ int sess_connect_good; /* SSL new conne/reneg - finished */
+ int sess_accept; /* SSL new accept - started */
+ int sess_accept_renegotiate; /* SSL reneg - requested */
+ int sess_accept_good; /* SSL accept/reneg - finished */
+ int sess_miss; /* session lookup misses */
+ int sess_timeout; /* reuse attempt on timeouted session */
+ int sess_cache_full; /* session removed due to full cache */
+ int sess_hit; /* session reuse actually done */
+ int sess_cb_hit; /* session-id that was not in the cache was
+ * passed back via the callback. This
+ * indicates that the application is supplying
+ * session-id's from other processes - spooky
+ * :-) */
+ } stats;
+
+ int references;
+
+ /* if defined, these override the X509_verify_cert() calls */
+ int (*app_verify_callback) (X509_STORE_CTX *, void *);
+ void *app_verify_arg;
+ /*
+ * before OpenSSL 0.9.7, 'app_verify_arg' was ignored
+ * ('app_verify_callback' was called with just one argument)
+ */
+
+ /* Default password callback. */
+ pem_password_cb *default_passwd_callback;
+
+ /* Default password callback user data. */
+ void *default_passwd_callback_userdata;
+
+ /* get client cert callback */
+ int (*client_cert_cb) (SSL *ssl, X509 **x509, EVP_PKEY **pkey);
+
+ /* cookie generate callback */
+ int (*app_gen_cookie_cb) (SSL *ssl, unsigned char *cookie,
+ unsigned int *cookie_len);
+
+ /* verify cookie callback */
+ int (*app_verify_cookie_cb) (SSL *ssl, const unsigned char *cookie,
+ unsigned int cookie_len);
+
+ CRYPTO_EX_DATA ex_data;
+
+ const EVP_MD *md5; /* For SSLv3/TLSv1 'ssl3-md5' */
+ const EVP_MD *sha1; /* For SSLv3/TLSv1 'ssl3->sha1' */
+
+ STACK_OF(X509) *extra_certs;
+ STACK_OF(SSL_COMP) *comp_methods; /* stack of SSL_COMP, SSLv3/TLSv1 */
+
+ /* Default values used when no per-SSL value is defined follow */
+
+ /* used if SSL's info_callback is NULL */
+ void (*info_callback) (const SSL *ssl, int type, int val);
+
+ /* what we put in client cert requests */
+ STACK_OF(X509_NAME) *client_CA;
+
+ /*
+ * Default values to use in SSL structures follow (these are copied by
+ * SSL_new)
+ */
+
+ uint32_t options;
+ uint32_t mode;
+ int min_proto_version;
+ int max_proto_version;
+ long max_cert_list;
+
+ struct cert_st /* CERT */ *cert;
+ int read_ahead;
+
+ /* callback that allows applications to peek at protocol messages */
+ void (*msg_callback) (int write_p, int version, int content_type,
+ const void *buf, size_t len, SSL *ssl, void *arg);
+ void *msg_callback_arg;
+
+ uint32_t verify_mode;
+ unsigned int sid_ctx_length;
+ unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
+ /* called 'verify_callback' in the SSL */
+ int (*default_verify_callback) (int ok, X509_STORE_CTX *ctx);
+
+ /* Default generate session ID callback. */
+ GEN_SESSION_CB generate_session_id;
+
+ X509_VERIFY_PARAM *param;
+
+ int quiet_shutdown;
+
+# ifndef OPENSSL_NO_CT
+ CTLOG_STORE *ctlog_store; /* CT Log Store */
+ /*
+ * Validates that the SCTs (Signed Certificate Timestamps) are sufficient.
+ * If they are not, the connection should be aborted.
+ */
+ ssl_ct_validation_cb ct_validation_callback;
+ void *ct_validation_callback_arg;
+# endif
+
+ /*
+ * If we're using more than one pipeline how should we divide the data
+ * up between the pipes?
+ */
+ unsigned int split_send_fragment;
+ /*
+ * Maximum amount of data to send in one fragment. actual record size can
+ * be more than this due to padding and MAC overheads.
+ */
+ unsigned int max_send_fragment;
+
+ /* Up to how many pipelines should we use? If 0 then 1 is assumed */
+ unsigned int max_pipelines;
+
+ /* The default read buffer length to use (0 means not set) */
+ size_t default_read_buf_len;
+
+# ifndef OPENSSL_NO_ENGINE
+ /*
+ * Engine to pass requests for client certs to
+ */
+ ENGINE *client_cert_engine;
+# endif
+
+ /* TLS extensions servername callback */
+ int (*tlsext_servername_callback) (SSL *, int *, void *);
+ void *tlsext_servername_arg;
+ /* RFC 4507 session ticket keys */
+ unsigned char tlsext_tick_key_name[TLSEXT_KEYNAME_LENGTH];
+ unsigned char tlsext_tick_hmac_key[32];
+ unsigned char tlsext_tick_aes_key[32];
+ /* Callback to support customisation of ticket key setting */
+ int (*tlsext_ticket_key_cb) (SSL *ssl,
+ unsigned char *name, unsigned char *iv,
+ EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc);
+
+ /* certificate status request info */
+ /* Callback for status request */
+ int (*tlsext_status_cb) (SSL *ssl, void *arg);
+ void *tlsext_status_arg;
+
+# ifndef OPENSSL_NO_PSK
+ unsigned int (*psk_client_callback) (SSL *ssl, const char *hint,
+ char *identity,
+ unsigned int max_identity_len,
+ unsigned char *psk,
+ unsigned int max_psk_len);
+ unsigned int (*psk_server_callback) (SSL *ssl, const char *identity,
+ unsigned char *psk,
+ unsigned int max_psk_len);
+# endif
+
+# ifndef OPENSSL_NO_SRP
+ SRP_CTX srp_ctx; /* ctx for SRP authentication */
+# endif
+
+# ifndef OPENSSL_NO_NEXTPROTONEG
+ /* Next protocol negotiation information */
+
+ /*
+ * For a server, this contains a callback function by which the set of
+ * advertised protocols can be provided.
+ */
+ int (*next_protos_advertised_cb) (SSL *s, const unsigned char **buf,
+ unsigned int *len, void *arg);
+ void *next_protos_advertised_cb_arg;
+ /*
+ * For a client, this contains a callback function that selects the next
+ * protocol from the list provided by the server.
+ */
+ int (*next_proto_select_cb) (SSL *s, unsigned char **out,
+ unsigned char *outlen,
+ const unsigned char *in,
+ unsigned int inlen, void *arg);
+ void *next_proto_select_cb_arg;
+# endif
+
+ /*
+ * ALPN information (we are in the process of transitioning from NPN to
+ * ALPN.)
+ */
+
+ /*-
+ * For a server, this contains a callback function that allows the
+ * server to select the protocol for the connection.
+ * out: on successful return, this must point to the raw protocol
+ * name (without the length prefix).
+ * outlen: on successful return, this contains the length of |*out|.
+ * in: points to the client's list of supported protocols in
+ * wire-format.
+ * inlen: the length of |in|.
+ */
+ int (*alpn_select_cb) (SSL *s,
+ const unsigned char **out,
+ unsigned char *outlen,
+ const unsigned char *in,
+ unsigned int inlen, void *arg);
+ void *alpn_select_cb_arg;
+
+ /*
+ * For a client, this contains the list of supported protocols in wire
+ * format.
+ */
+ unsigned char *alpn_client_proto_list;
+ unsigned alpn_client_proto_list_len;
+
+ /* Shared DANE context */
+ struct dane_ctx_st dane;
+
+ /* SRTP profiles we are willing to do from RFC 5764 */
+ STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;
+ /*
+ * Callback for disabling session caching and ticket support on a session
+ * basis, depending on the chosen cipher.
+ */
+ int (*not_resumable_session_cb) (SSL *ssl, int is_forward_secure);
+# ifndef OPENSSL_NO_EC
+ /* EC extension values inherited by SSL structure */
+ size_t tlsext_ecpointformatlist_length;
+ unsigned char *tlsext_ecpointformatlist;
+ size_t tlsext_ellipticcurvelist_length;
+ unsigned char *tlsext_ellipticcurvelist;
+# endif /* OPENSSL_NO_EC */
+
+ /* ext status type used for CSR extension (OCSP Stapling) */
+ int tlsext_status_type;
+
+ CRYPTO_RWLOCK *lock;
+};
+
+struct ssl_st {
+ /*
+ * protocol version (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION,
+ * DTLS1_VERSION)
+ */
+ int version;
+ /* SSLv3 */
+ const SSL_METHOD *method;
+ /*
+ * There are 2 BIO's even though they are normally both the same. This
+ * is so data can be read and written to different handlers
+ */
+ /* used by SSL_read */
+ BIO *rbio;
+ /* used by SSL_write */
+ BIO *wbio;
+ /* used during session-id reuse to concatenate messages */
+ BIO *bbio;
+ /*
+ * This holds a variable that indicates what we were doing when a 0 or -1
+ * is returned. This is needed for non-blocking IO so we know what
+ * request needs re-doing when in SSL_accept or SSL_connect
+ */
+ int rwstate;
+ int (*handshake_func) (SSL *);
+ /*
+ * Imagine that here's a boolean member "init" that is switched as soon
+ * as SSL_set_{accept/connect}_state is called for the first time, so
+ * that "state" and "handshake_func" are properly initialized. But as
+ * handshake_func is == 0 until then, we use this test instead of an
+ * "init" member.
+ */
+ /* are we the server side? */
+ int server;
+ /*
+ * Generate a new session or reuse an old one.
+ * NB: For servers, the 'new' session may actually be a previously
+ * cached session or even the previous session unless
+ * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set
+ */
+ int new_session;
+ /* don't send shutdown packets */
+ int quiet_shutdown;
+ /* we have shut things down, 0x01 sent, 0x02 for received */
+ int shutdown;
+ /* where we are */
+ OSSL_STATEM statem;
+ BUF_MEM *init_buf; /* buffer used during init */
+ void *init_msg; /* pointer to handshake message body, set by
+ * ssl3_get_message() */
+ int init_num; /* amount read/written */
+ int init_off; /* amount read/written */
+ struct ssl3_state_st *s3; /* SSLv3 variables */
+ struct dtls1_state_st *d1; /* DTLSv1 variables */
+ /* callback that allows applications to peek at protocol messages */
+ void (*msg_callback) (int write_p, int version, int content_type,
+ const void *buf, size_t len, SSL *ssl, void *arg);
+ void *msg_callback_arg;
+ int hit; /* reusing a previous session */
+ X509_VERIFY_PARAM *param;
+ /* Per connection DANE state */
+ SSL_DANE dane;
+ /* crypto */
+ STACK_OF(SSL_CIPHER) *cipher_list;
+ STACK_OF(SSL_CIPHER) *cipher_list_by_id;
+ /*
+ * These are the ones being used, the ones in SSL_SESSION are the ones to
+ * be 'copied' into these ones
+ */
+ uint32_t mac_flags;
+ EVP_CIPHER_CTX *enc_read_ctx; /* cryptographic state */
+ EVP_MD_CTX *read_hash; /* used for mac generation */
+ COMP_CTX *compress; /* compression */
+ COMP_CTX *expand; /* uncompress */
+ EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */
+ EVP_MD_CTX *write_hash; /* used for mac generation */
+ /* session info */
+ /* client cert? */
+ /* This is used to hold the server certificate used */
+ struct cert_st /* CERT */ *cert;
+ /*
+ * the session_id_context is used to ensure sessions are only reused in
+ * the appropriate context
+ */
+ unsigned int sid_ctx_length;
+ unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
+ /* This can also be in the session once a session is established */
+ SSL_SESSION *session;
+ /* Default generate session ID callback. */
+ GEN_SESSION_CB generate_session_id;
+ /* Used in SSL3 */
+ /*
+ * 0 don't care about verify failure.
+ * 1 fail if verify fails
+ */
+ uint32_t verify_mode;
+ /* fail if callback returns 0 */
+ int (*verify_callback) (int ok, X509_STORE_CTX *ctx);
+ /* optional informational callback */
+ void (*info_callback) (const SSL *ssl, int type, int val);
+ /* error bytes to be written */
+ int error;
+ /* actual code */
+ int error_code;
+# ifndef OPENSSL_NO_PSK
+ unsigned int (*psk_client_callback) (SSL *ssl, const char *hint,
+ char *identity,
+ unsigned int max_identity_len,
+ unsigned char *psk,
+ unsigned int max_psk_len);
+ unsigned int (*psk_server_callback) (SSL *ssl, const char *identity,
+ unsigned char *psk,
+ unsigned int max_psk_len);
+# endif
+ SSL_CTX *ctx;
+ /* Verified chain of peer */
+ STACK_OF(X509) *verified_chain;
+ long verify_result;
+ /* extra application data */
+ CRYPTO_EX_DATA ex_data;
+ /* for server side, keep the list of CA_dn we can use */
+ STACK_OF(X509_NAME) *client_CA;
+ int references;
+ /* protocol behaviour */
+ uint32_t options;
+ /* API behaviour */
+ uint32_t mode;
+ int min_proto_version;
+ int max_proto_version;
+ long max_cert_list;
+ int first_packet;
+ /* what was passed, used for SSLv3/TLS rollback check */
+ int client_version;
+ /*
+ * If we're using more than one pipeline how should we divide the data
+ * up between the pipes?
+ */
+ unsigned int split_send_fragment;
+ /*
+ * Maximum amount of data to send in one fragment. actual record size can
+ * be more than this due to padding and MAC overheads.
+ */
+ unsigned int max_send_fragment;
+ /* Up to how many pipelines should we use? If 0 then 1 is assumed */
+ unsigned int max_pipelines;
+ /* TLS extension debug callback */
+ void (*tlsext_debug_cb) (SSL *s, int client_server, int type,
+ const unsigned char *data, int len, void *arg);
+ void *tlsext_debug_arg;
+ char *tlsext_hostname;
+ /*-
+ * no further mod of servername
+ * 0 : call the servername extension callback.
+ * 1 : prepare 2, allow last ack just after in server callback.
+ * 2 : don't call servername callback, no ack in server hello
+ */
+ int servername_done;
+ /* certificate status request info */
+ /* Status type or -1 if no status type */
+ int tlsext_status_type;
+# ifndef OPENSSL_NO_CT
+ /*
+ * Validates that the SCTs (Signed Certificate Timestamps) are sufficient.
+ * If they are not, the connection should be aborted.
+ */
+ ssl_ct_validation_cb ct_validation_callback;
+ /* User-supplied argument tha tis passed to the ct_validation_callback */
+ void *ct_validation_callback_arg;
+ /*
+ * Consolidated stack of SCTs from all sources.
+ * Lazily populated by CT_get_peer_scts(SSL*)
+ */
+ STACK_OF(SCT) *scts;
+ /* Raw extension data, if seen */
+ unsigned char *tlsext_scts;
+ /* Length of raw extension data, if seen */
+ uint16_t tlsext_scts_len;
+ /* Have we attempted to find/parse SCTs yet? */
+ int scts_parsed;
+# endif
+ /* Expect OCSP CertificateStatus message */
+ int tlsext_status_expected;
+ /* OCSP status request only */
+ STACK_OF(OCSP_RESPID) *tlsext_ocsp_ids;
+ X509_EXTENSIONS *tlsext_ocsp_exts;
+ /* OCSP response received or to be sent */
+ unsigned char *tlsext_ocsp_resp;
+ int tlsext_ocsp_resplen;
+ /* RFC4507 session ticket expected to be received or sent */
+ int tlsext_ticket_expected;
+# ifndef OPENSSL_NO_EC
+ size_t tlsext_ecpointformatlist_length;
+ /* our list */
+ unsigned char *tlsext_ecpointformatlist;
+ size_t tlsext_ellipticcurvelist_length;
+ /* our list */
+ unsigned char *tlsext_ellipticcurvelist;
+# endif /* OPENSSL_NO_EC */
+ /* TLS Session Ticket extension override */
+ TLS_SESSION_TICKET_EXT *tlsext_session_ticket;
+ /* TLS Session Ticket extension callback */
+ tls_session_ticket_ext_cb_fn tls_session_ticket_ext_cb;
+ void *tls_session_ticket_ext_cb_arg;
+ /* TLS pre-shared secret session resumption */
+ tls_session_secret_cb_fn tls_session_secret_cb;
+ void *tls_session_secret_cb_arg;
+ SSL_CTX *session_ctx; /* initial ctx, used to store sessions */
+# ifndef OPENSSL_NO_NEXTPROTONEG
+ /*
+ * Next protocol negotiation. For the client, this is the protocol that
+ * we sent in NextProtocol and is set when handling ServerHello
+ * extensions. For a server, this is the client's selected_protocol from
+ * NextProtocol and is set when handling the NextProtocol message, before
+ * the Finished message.
+ */
+ unsigned char *next_proto_negotiated;
+ unsigned char next_proto_negotiated_len;
+# endif
+ /* What we'll do */
+ STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;
+ /* What's been chosen */
+ SRTP_PROTECTION_PROFILE *srtp_profile;
+ /*-
+ * Is use of the Heartbeat extension negotiated?
+ * 0: disabled
+ * 1: enabled
+ * 2: enabled, but not allowed to send Requests
+ */
+ unsigned int tlsext_heartbeat;
+ /* Indicates if a HeartbeatRequest is in flight */
+ unsigned int tlsext_hb_pending;
+ /* HeartbeatRequest sequence number */
+ unsigned int tlsext_hb_seq;
+ /*
+ * For a client, this contains the list of supported protocols in wire
+ * format.
+ */
+ unsigned char *alpn_client_proto_list;
+ unsigned alpn_client_proto_list_len;
+
+ /* Set to one if we have negotiated ETM */
+ int tlsext_use_etm;
+
+ /*-
+ * 1 if we are renegotiating.
+ * 2 if we are a server and are inside a handshake
+ * (i.e. not just sending a HelloRequest)
+ */
+ int renegotiate;
+# ifndef OPENSSL_NO_SRP
+ /* ctx for SRP authentication */
+ SRP_CTX srp_ctx;
+# endif
+ /*
+ * Callback for disabling session caching and ticket support on a session
+ * basis, depending on the chosen cipher.
+ */
+ int (*not_resumable_session_cb) (SSL *ssl, int is_forward_secure);
+ RECORD_LAYER rlayer;
+ /* Default password callback. */
+ pem_password_cb *default_passwd_callback;
+ /* Default password callback user data. */
+ void *default_passwd_callback_userdata;
+ /* Async Job info */
+ ASYNC_JOB *job;
+ ASYNC_WAIT_CTX *waitctx;
+ CRYPTO_RWLOCK *lock;
+};
+
+typedef struct ssl3_state_st {
+ long flags;
+ int read_mac_secret_size;
+ unsigned char read_mac_secret[EVP_MAX_MD_SIZE];
+ int write_mac_secret_size;
+ unsigned char write_mac_secret[EVP_MAX_MD_SIZE];
+ unsigned char server_random[SSL3_RANDOM_SIZE];
+ unsigned char client_random[SSL3_RANDOM_SIZE];
+ /* flags for countermeasure against known-IV weakness */
+ int need_empty_fragments;
+ int empty_fragment_done;
+ /* used during startup, digest all incoming/outgoing packets */
+ BIO *handshake_buffer;
+ /*
+ * When handshake digest is determined, buffer is hashed and
+ * freed and MD_CTX for the required digest is stored here.
+ */
+ EVP_MD_CTX *handshake_dgst;
+ /*
+ * Set whenever an expected ChangeCipherSpec message is processed.
+ * Unset when the peer's Finished message is received.
+ * Unexpected ChangeCipherSpec messages trigger a fatal alert.
+ */
+ int change_cipher_spec;
+ int warn_alert;
+ int fatal_alert;
+ /*
+ * we allow one fatal and one warning alert to be outstanding, send close
+ * alert via the warning alert
+ */
+ int alert_dispatch;
+ unsigned char send_alert[2];
+ /*
+ * This flag is set when we should renegotiate ASAP, basically when there
+ * is no more data in the read or write buffers
+ */
+ int renegotiate;
+ int total_renegotiations;
+ int num_renegotiations;
+ int in_read_app_data;
+ struct {
+ /* actually only need to be 16+20 for SSLv3 and 12 for TLS */
+ unsigned char finish_md[EVP_MAX_MD_SIZE * 2];
+ int finish_md_len;
+ unsigned char peer_finish_md[EVP_MAX_MD_SIZE * 2];
+ int peer_finish_md_len;
+ unsigned long message_size;
+ int message_type;
+ /* used to hold the new cipher we are going to use */
+ const SSL_CIPHER *new_cipher;
+# if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
+ EVP_PKEY *pkey; /* holds short lived DH/ECDH key */
+# endif
+ /* used for certificate requests */
+ int cert_req;
+ int ctype_num;
+ char ctype[SSL3_CT_NUMBER];
+ STACK_OF(X509_NAME) *ca_names;
+ int key_block_length;
+ unsigned char *key_block;
+ const EVP_CIPHER *new_sym_enc;
+ const EVP_MD *new_hash;
+ int new_mac_pkey_type;
+ int new_mac_secret_size;
+# ifndef OPENSSL_NO_COMP
+ const SSL_COMP *new_compression;
+# else
+ char *new_compression;
+# endif
+ int cert_request;
+ /* Raw values of the cipher list from a client */
+ unsigned char *ciphers_raw;
+ size_t ciphers_rawlen;
+ /* Temporary storage for premaster secret */
+ unsigned char *pms;
+ size_t pmslen;
+# ifndef OPENSSL_NO_PSK
+ /* Temporary storage for PSK key */
+ unsigned char *psk;
+ size_t psklen;
+# endif
+ /*
+ * signature algorithms peer reports: e.g. supported signature
+ * algorithms extension for server or as part of a certificate
+ * request for client.
+ */
+ unsigned char *peer_sigalgs;
+ /* Size of above array */
+ size_t peer_sigalgslen;
+ /* Digest peer uses for signing */
+ const EVP_MD *peer_md;
+ /* Array of digests used for signing */
+ const EVP_MD *md[SSL_PKEY_NUM];
+ /*
+ * Set if corresponding CERT_PKEY can be used with current
+ * SSL session: e.g. appropriate curve, signature algorithms etc.
+ * If zero it can't be used at all.
+ */
+ uint32_t valid_flags[SSL_PKEY_NUM];
+ /*
+ * For servers the following masks are for the key and auth algorithms
+ * that are supported by the certs below. For clients they are masks of
+ * *disabled* algorithms based on the current session.
+ */
+ uint32_t mask_k;
+ uint32_t mask_a;
+ /*
+ * The following are used by the client to see if a cipher is allowed or
+ * not. It contains the minimum and maximum version the client's using
+ * based on what it knows so far.
+ */
+ int min_ver;
+ int max_ver;
+ } tmp;
+
+ /* Connection binding to prevent renegotiation attacks */
+ unsigned char previous_client_finished[EVP_MAX_MD_SIZE];
+ unsigned char previous_client_finished_len;
+ unsigned char previous_server_finished[EVP_MAX_MD_SIZE];
+ unsigned char previous_server_finished_len;
+ int send_connection_binding; /* TODOEKR */
+
+# ifndef OPENSSL_NO_NEXTPROTONEG
+ /*
+ * Set if we saw the Next Protocol Negotiation extension from our peer.
+ */
+ int next_proto_neg_seen;
+# endif
+
+ /*
+ * ALPN information (we are in the process of transitioning from NPN to
+ * ALPN.)
+ */
+
+ /*
+ * In a server these point to the selected ALPN protocol after the
+ * ClientHello has been processed. In a client these contain the protocol
+ * that the server selected once the ServerHello has been processed.
+ */
+ unsigned char *alpn_selected;
+ size_t alpn_selected_len;
+ /* used by the server to know what options were proposed */
+ unsigned char *alpn_proposed;
+ size_t alpn_proposed_len;
+ /* used by the client to know if it actually sent alpn */
+ int alpn_sent;
+
+# ifndef OPENSSL_NO_EC
+ /*
+ * This is set to true if we believe that this is a version of Safari
+ * running on OS X 10.6 or newer. We wish to know this because Safari on
+ * 10.8 .. 10.8.3 has broken ECDHE-ECDSA support.
+ */
+ char is_probably_safari;
+# endif /* !OPENSSL_NO_EC */
+
+ /* For clients: peer temporary key */
+# if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
+ EVP_PKEY *peer_tmp;
+# endif
+
+} SSL3_STATE;
+
+/* DTLS structures */
+
+# ifndef OPENSSL_NO_SCTP
+# define DTLS1_SCTP_AUTH_LABEL "EXPORTER_DTLS_OVER_SCTP"
+# endif
+
+/* Max MTU overhead we know about so far is 40 for IPv6 + 8 for UDP */
+# define DTLS1_MAX_MTU_OVERHEAD 48
+
+/*
+ * Flag used in message reuse to indicate the buffer contains the record
+ * header as well as the the handshake message header.
+ */
+# define DTLS1_SKIP_RECORD_HEADER 2
+
+struct dtls1_retransmit_state {
+ EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */
+ EVP_MD_CTX *write_hash; /* used for mac generation */
+ COMP_CTX *compress; /* compression */
+ SSL_SESSION *session;
+ unsigned short epoch;
+};
+
+struct hm_header_st {
+ unsigned char type;
+ unsigned long msg_len;
+ unsigned short seq;
+ unsigned long frag_off;
+ unsigned long frag_len;
+ unsigned int is_ccs;
+ struct dtls1_retransmit_state saved_retransmit_state;
+};
+
+struct dtls1_timeout_st {
+ /* Number of read timeouts so far */
+ unsigned int read_timeouts;
+ /* Number of write timeouts so far */
+ unsigned int write_timeouts;
+ /* Number of alerts received so far */
+ unsigned int num_alerts;
+};
+
+typedef struct hm_fragment_st {
+ struct hm_header_st msg_header;
+ unsigned char *fragment;
+ unsigned char *reassembly;
+} hm_fragment;
+
+typedef struct pqueue_st pqueue;
+typedef struct pitem_st pitem;
+
+struct pitem_st {
+ unsigned char priority[8]; /* 64-bit value in big-endian encoding */
+ void *data;
+ pitem *next;
+};
+
+typedef struct pitem_st *piterator;
+
+pitem *pitem_new(unsigned char *prio64be, void *data);
+void pitem_free(pitem *item);
+pqueue *pqueue_new(void);
+void pqueue_free(pqueue *pq);
+pitem *pqueue_insert(pqueue *pq, pitem *item);
+pitem *pqueue_peek(pqueue *pq);
+pitem *pqueue_pop(pqueue *pq);
+pitem *pqueue_find(pqueue *pq, unsigned char *prio64be);
+pitem *pqueue_iterator(pqueue *pq);
+pitem *pqueue_next(piterator *iter);
+int pqueue_size(pqueue *pq);
+
+typedef struct dtls1_state_st {
+ unsigned char cookie[DTLS1_COOKIE_LENGTH];
+ unsigned int cookie_len;
+ unsigned int cookie_verified;
+ /* handshake message numbers */
+ unsigned short handshake_write_seq;
+ unsigned short next_handshake_write_seq;
+ unsigned short handshake_read_seq;
+ /* Buffered handshake messages */
+ pqueue *buffered_messages;
+ /* Buffered (sent) handshake records */
+ pqueue *sent_messages;
+ unsigned int link_mtu; /* max on-the-wire DTLS packet size */
+ unsigned int mtu; /* max DTLS packet size */
+ struct hm_header_st w_msg_hdr;
+ struct hm_header_st r_msg_hdr;
+ struct dtls1_timeout_st timeout;
+ /*
+ * Indicates when the last handshake msg or heartbeat sent will timeout
+ */
+ struct timeval next_timeout;
+ /* Timeout duration */
+ unsigned short timeout_duration;
+ unsigned int retransmitting;
+# ifndef OPENSSL_NO_SCTP
+ int shutdown_received;
+# endif
+} DTLS1_STATE;
+
+# ifndef OPENSSL_NO_EC
+/*
+ * From ECC-TLS draft, used in encoding the curve type in ECParameters
+ */
+# define EXPLICIT_PRIME_CURVE_TYPE 1
+# define EXPLICIT_CHAR2_CURVE_TYPE 2
+# define NAMED_CURVE_TYPE 3
+# endif /* OPENSSL_NO_EC */
+
+typedef struct cert_pkey_st {
+ X509 *x509;
+ EVP_PKEY *privatekey;
+ /* Chain for this certificate */
+ STACK_OF(X509) *chain;
+ /*-
+ * serverinfo data for this certificate. The data is in TLS Extension
+ * wire format, specifically it's a series of records like:
+ * uint16_t extension_type; // (RFC 5246, 7.4.1.4, Extension)
+ * uint16_t length;
+ * uint8_t data[length];
+ */
+ unsigned char *serverinfo;
+ size_t serverinfo_length;
+} CERT_PKEY;
+/* Retrieve Suite B flags */
+# define tls1_suiteb(s) (s->cert->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS)
+/* Uses to check strict mode: suite B modes are always strict */
+# define SSL_CERT_FLAGS_CHECK_TLS_STRICT \
+ (SSL_CERT_FLAG_SUITEB_128_LOS|SSL_CERT_FLAG_TLS_STRICT)
+
+typedef struct {
+ unsigned short ext_type;
+ /*
+ * Per-connection flags relating to this extension type: not used if
+ * part of an SSL_CTX structure.
+ */
+ uint32_t ext_flags;
+ 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_method;
+
+/* ext_flags values */
+
+/*
+ * Indicates an extension has been received. Used to check for unsolicited or
+ * duplicate extensions.
+ */
+# define SSL_EXT_FLAG_RECEIVED 0x1
+/*
+ * Indicates an extension has been sent: used to enable sending of
+ * corresponding ServerHello extension.
+ */
+# define SSL_EXT_FLAG_SENT 0x2
+
+typedef struct {
+ custom_ext_method *meths;
+ size_t meths_count;
+} custom_ext_methods;
+
+typedef struct cert_st {
+ /* Current active set */
+ /*
+ * ALWAYS points to an element of the pkeys array
+ * Probably it would make more sense to store
+ * an index, not a pointer.
+ */
+ CERT_PKEY *key;
+# ifndef OPENSSL_NO_DH
+ EVP_PKEY *dh_tmp;
+ DH *(*dh_tmp_cb) (SSL *ssl, int is_export, int keysize);
+ int dh_tmp_auto;
+# endif
+ /* Flags related to certificates */
+ uint32_t cert_flags;
+ CERT_PKEY pkeys[SSL_PKEY_NUM];
+ /*
+ * Certificate types (received or sent) in certificate request message.
+ * On receive this is only set if number of certificate types exceeds
+ * SSL3_CT_NUMBER.
+ */
+ unsigned char *ctypes;
+ size_t ctype_num;
+ /*
+ * supported signature algorithms. When set on a client this is sent in
+ * the client hello as the supported signature algorithms extension. For
+ * servers it represents the signature algorithms we are willing to use.
+ */
+ unsigned char *conf_sigalgs;
+ /* Size of above array */
+ size_t conf_sigalgslen;
+ /*
+ * Client authentication signature algorithms, if not set then uses
+ * conf_sigalgs. On servers these will be the signature algorithms sent
+ * to the client in a cerificate request for TLS 1.2. On a client this
+ * represents the signature algortithms we are willing to use for client
+ * authentication.
+ */
+ unsigned char *client_sigalgs;
+ /* Size of above array */
+ size_t client_sigalgslen;
+ /*
+ * Signature algorithms shared by client and server: cached because these
+ * are used most often.
+ */
+ TLS_SIGALGS *shared_sigalgs;
+ size_t shared_sigalgslen;
+ /*
+ * Certificate setup callback: if set is called whenever a certificate
+ * may be required (client or server). the callback can then examine any
+ * appropriate parameters and setup any certificates required. This
+ * allows advanced applications to select certificates on the fly: for
+ * example based on supported signature algorithms or curves.
+ */
+ int (*cert_cb) (SSL *ssl, void *arg);
+ void *cert_cb_arg;
+ /*
+ * Optional X509_STORE for chain building or certificate validation If
+ * NULL the parent SSL_CTX store is used instead.
+ */
+ X509_STORE *chain_store;
+ X509_STORE *verify_store;
+ /* Custom extension methods for server and client */
+ custom_ext_methods cli_ext;
+ custom_ext_methods srv_ext;
+ /* Security callback */
+ int (*sec_cb) (const SSL *s, const SSL_CTX *ctx, int op, int bits, int nid,
+ void *other, void *ex);
+ /* Security level */
+ int sec_level;
+ void *sec_ex;
+# ifndef OPENSSL_NO_PSK
+ /* If not NULL psk identity hint to use for servers */
+ char *psk_identity_hint;
+# endif
+ int references; /* >1 only if SSL_copy_session_id is used */
+ CRYPTO_RWLOCK *lock;
+} CERT;
+
+/* Structure containing decoded values of signature algorithms extension */
+struct tls_sigalgs_st {
+ /* NID of hash algorithm */
+ int hash_nid;
+ /* NID of signature algorithm */
+ int sign_nid;
+ /* Combined hash and signature NID */
+ int signandhash_nid;
+ /* Raw values used in extension */
+ unsigned char rsign;
+ unsigned char rhash;
+};
+
+# define FP_ICC (int (*)(const void *,const void *))
+
+/*
+ * This is for the SSLv3/TLSv1.0 differences in crypto/hash stuff It is a bit
+ * of a mess of functions, but hell, think of it as an opaque structure :-)
+ */
+typedef struct ssl3_enc_method {
+ int (*enc) (SSL *, SSL3_RECORD *, unsigned int, int);
+ int (*mac) (SSL *, SSL3_RECORD *, unsigned char *, int);
+ int (*setup_key_block) (SSL *);
+ int (*generate_master_secret) (SSL *, unsigned char *, unsigned char *,
+ int);
+ int (*change_cipher_state) (SSL *, int);
+ int (*final_finish_mac) (SSL *, const char *, int, unsigned char *);
+ int finish_mac_length;
+ const char *client_finished_label;
+ int client_finished_label_len;
+ const char *server_finished_label;
+ int server_finished_label_len;
+ int (*alert_value) (int);
+ int (*export_keying_material) (SSL *, unsigned char *, size_t,
+ const char *, size_t,
+ const unsigned char *, size_t,
+ int use_context);
+ /* Various flags indicating protocol version requirements */
+ uint32_t enc_flags;
+ /* Handshake header length */
+ unsigned int hhlen;
+ /* Set the handshake header */
+ int (*set_handshake_header) (SSL *s, int type, unsigned long len);
+ /* Write out handshake message */
+ int (*do_write) (SSL *s);
+} SSL3_ENC_METHOD;
+
+# define SSL_HM_HEADER_LENGTH(s) s->method->ssl3_enc->hhlen
+# define ssl_handshake_start(s) \
+ (((unsigned char *)s->init_buf->data) + s->method->ssl3_enc->hhlen)
+# define ssl_set_handshake_header(s, htype, len) \
+ s->method->ssl3_enc->set_handshake_header(s, htype, len)
+# define ssl_do_write(s) s->method->ssl3_enc->do_write(s)
+
+/* Values for enc_flags */
+
+/* Uses explicit IV for CBC mode */
+# define SSL_ENC_FLAG_EXPLICIT_IV 0x1
+/* Uses signature algorithms extension */
+# define SSL_ENC_FLAG_SIGALGS 0x2
+/* Uses SHA256 default PRF */
+# define SSL_ENC_FLAG_SHA256_PRF 0x4
+/* Is DTLS */
+# define SSL_ENC_FLAG_DTLS 0x8
+/*
+ * Allow TLS 1.2 ciphersuites: applies to DTLS 1.2 as well as TLS 1.2: may
+ * apply to others in future.
+ */
+# define SSL_ENC_FLAG_TLS1_2_CIPHERS 0x10
+
+# ifndef OPENSSL_NO_COMP
+/* Used for holding the relevant compression methods loaded into SSL_CTX */
+typedef struct ssl3_comp_st {
+ int comp_id; /* The identifier byte for this compression
+ * type */
+ char *name; /* Text name used for the compression type */
+ COMP_METHOD *method; /* The method :-) */
+} SSL3_COMP;
+# endif
+
+extern SSL3_ENC_METHOD ssl3_undef_enc_method;
+
+__owur const SSL_METHOD *ssl_bad_method(int ver);
+__owur const SSL_METHOD *sslv3_method(void);
+__owur const SSL_METHOD *sslv3_server_method(void);
+__owur const SSL_METHOD *sslv3_client_method(void);
+__owur const SSL_METHOD *tlsv1_method(void);
+__owur const SSL_METHOD *tlsv1_server_method(void);
+__owur const SSL_METHOD *tlsv1_client_method(void);
+__owur const SSL_METHOD *tlsv1_1_method(void);
+__owur const SSL_METHOD *tlsv1_1_server_method(void);
+__owur const SSL_METHOD *tlsv1_1_client_method(void);
+__owur const SSL_METHOD *tlsv1_2_method(void);
+__owur const SSL_METHOD *tlsv1_2_server_method(void);
+__owur const SSL_METHOD *tlsv1_2_client_method(void);
+__owur const SSL_METHOD *dtlsv1_method(void);
+__owur const SSL_METHOD *dtlsv1_server_method(void);
+__owur const SSL_METHOD *dtlsv1_client_method(void);
+__owur const SSL_METHOD *dtls_bad_ver_client_method(void);
+__owur const SSL_METHOD *dtlsv1_2_method(void);
+__owur const SSL_METHOD *dtlsv1_2_server_method(void);
+__owur const SSL_METHOD *dtlsv1_2_client_method(void);
+
+extern const SSL3_ENC_METHOD TLSv1_enc_data;
+extern const SSL3_ENC_METHOD TLSv1_1_enc_data;
+extern const SSL3_ENC_METHOD TLSv1_2_enc_data;
+extern const SSL3_ENC_METHOD SSLv3_enc_data;
+extern const SSL3_ENC_METHOD DTLSv1_enc_data;
+extern const SSL3_ENC_METHOD DTLSv1_2_enc_data;
+
+/*
+ * Flags for SSL methods
+ */
+# define SSL_METHOD_NO_FIPS (1U<<0)
+# define SSL_METHOD_NO_SUITEB (1U<<1)
+
+# define IMPLEMENT_tls_meth_func(version, flags, mask, func_name, s_accept, \
+ s_connect, enc_data) \
+const SSL_METHOD *func_name(void) \
+ { \
+ static const SSL_METHOD func_name##_data= { \
+ version, \
+ flags, \
+ mask, \
+ tls1_new, \
+ tls1_clear, \
+ tls1_free, \
+ s_accept, \
+ s_connect, \
+ ssl3_read, \
+ ssl3_peek, \
+ ssl3_write, \
+ ssl3_shutdown, \
+ ssl3_renegotiate, \
+ ssl3_renegotiate_check, \
+ ssl3_read_bytes, \
+ ssl3_write_bytes, \
+ ssl3_dispatch_alert, \
+ ssl3_ctrl, \
+ ssl3_ctx_ctrl, \
+ ssl3_get_cipher_by_char, \
+ ssl3_put_cipher_by_char, \
+ ssl3_pending, \
+ ssl3_num_ciphers, \
+ ssl3_get_cipher, \
+ tls1_default_timeout, \
+ &enc_data, \
+ ssl_undefined_void_function, \
+ ssl3_callback_ctrl, \
+ ssl3_ctx_callback_ctrl, \
+ }; \
+ return &func_name##_data; \
+ }
+
+# define IMPLEMENT_ssl3_meth_func(func_name, s_accept, s_connect) \
+const SSL_METHOD *func_name(void) \
+ { \
+ static const SSL_METHOD func_name##_data= { \
+ SSL3_VERSION, \
+ SSL_METHOD_NO_FIPS | SSL_METHOD_NO_SUITEB, \
+ SSL_OP_NO_SSLv3, \
+ ssl3_new, \
+ ssl3_clear, \
+ ssl3_free, \
+ s_accept, \
+ s_connect, \
+ ssl3_read, \
+ ssl3_peek, \
+ ssl3_write, \
+ ssl3_shutdown, \
+ ssl3_renegotiate, \
+ ssl3_renegotiate_check, \
+ ssl3_read_bytes, \
+ ssl3_write_bytes, \
+ ssl3_dispatch_alert, \
+ ssl3_ctrl, \
+ ssl3_ctx_ctrl, \
+ ssl3_get_cipher_by_char, \
+ ssl3_put_cipher_by_char, \
+ ssl3_pending, \
+ ssl3_num_ciphers, \
+ ssl3_get_cipher, \
+ ssl3_default_timeout, \
+ &SSLv3_enc_data, \
+ ssl_undefined_void_function, \
+ ssl3_callback_ctrl, \
+ ssl3_ctx_callback_ctrl, \
+ }; \
+ return &func_name##_data; \
+ }
+
+# define IMPLEMENT_dtls1_meth_func(version, flags, mask, func_name, s_accept, \
+ s_connect, enc_data) \
+const SSL_METHOD *func_name(void) \
+ { \
+ static const SSL_METHOD func_name##_data= { \
+ version, \
+ flags, \
+ mask, \
+ dtls1_new, \
+ dtls1_clear, \
+ dtls1_free, \
+ s_accept, \
+ s_connect, \
+ ssl3_read, \
+ ssl3_peek, \
+ ssl3_write, \
+ dtls1_shutdown, \
+ ssl3_renegotiate, \
+ ssl3_renegotiate_check, \
+ dtls1_read_bytes, \
+ dtls1_write_app_data_bytes, \
+ dtls1_dispatch_alert, \
+ dtls1_ctrl, \
+ ssl3_ctx_ctrl, \
+ ssl3_get_cipher_by_char, \
+ ssl3_put_cipher_by_char, \
+ ssl3_pending, \
+ ssl3_num_ciphers, \
+ ssl3_get_cipher, \
+ dtls1_default_timeout, \
+ &enc_data, \
+ ssl_undefined_void_function, \
+ ssl3_callback_ctrl, \
+ ssl3_ctx_callback_ctrl, \
+ }; \
+ return &func_name##_data; \
+ }
+
+struct openssl_ssl_test_functions {
+ int (*p_ssl_init_wbio_buffer) (SSL *s);
+ int (*p_ssl3_setup_buffers) (SSL *s);
+# ifndef OPENSSL_NO_HEARTBEATS
+ int (*p_dtls1_process_heartbeat) (SSL *s,
+ unsigned char *p, unsigned int length);
+# endif
+};
+
+const char *ssl_protocol_to_string(int version);
+
+# ifndef OPENSSL_UNIT_TEST
+
+void ssl_clear_cipher_ctx(SSL *s);
+int ssl_clear_bad_session(SSL *s);
+__owur CERT *ssl_cert_new(void);
+__owur CERT *ssl_cert_dup(CERT *cert);
+void ssl_cert_clear_certs(CERT *c);
+void ssl_cert_free(CERT *c);
+__owur int ssl_get_new_session(SSL *s, int session);
+__owur int ssl_get_prev_session(SSL *s, const PACKET *ext,
+ const PACKET *session_id);
+__owur SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket);
+__owur int ssl_cipher_id_cmp(const SSL_CIPHER *a, const SSL_CIPHER *b);
+DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER, ssl_cipher_id);
+__owur int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap,
+ const SSL_CIPHER *const *bp);
+__owur STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *meth,
+ STACK_OF(SSL_CIPHER) **pref,
+ STACK_OF(SSL_CIPHER)
+ **sorted,
+ const char *rule_str,
+ CERT *c);
+void ssl_update_cache(SSL *s, int mode);
+__owur int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
+ const EVP_MD **md, int *mac_pkey_type,
+ int *mac_secret_size, SSL_COMP **comp,
+ int use_etm);
+__owur int ssl_cipher_get_cert_index(const SSL_CIPHER *c);
+__owur const SSL_CIPHER *ssl_get_cipher_by_char(SSL *ssl,
+ const unsigned char *ptr);
+__owur int ssl_cert_set0_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain);
+__owur int ssl_cert_set1_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain);
+__owur int ssl_cert_add0_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x);
+__owur int ssl_cert_add1_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x);
+__owur int ssl_cert_select_current(CERT *c, X509 *x);
+__owur int ssl_cert_set_current(CERT *c, long arg);
+__owur X509 *ssl_cert_get0_next_certificate(CERT *c, int first);
+void ssl_cert_set_cert_cb(CERT *c, int (*cb) (SSL *ssl, void *arg), void *arg);
+
+__owur int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk);
+__owur int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l);
+__owur int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags);
+__owur int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain,
+ int ref);
+
+__owur int ssl_security(const SSL *s, int op, int bits, int nid, void *other);
+__owur int ssl_ctx_security(const SSL_CTX *ctx, int op, int bits, int nid,
+ void *other);
+
+int ssl_undefined_function(SSL *s);
+__owur int ssl_undefined_void_function(void);
+__owur int ssl_undefined_const_function(const SSL *s);
+__owur CERT_PKEY *ssl_get_server_send_pkey(SSL *s);
+__owur int ssl_get_server_cert_serverinfo(SSL *s,
+ const unsigned char **serverinfo,
+ size_t *serverinfo_length);
+__owur EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *c,
+ const EVP_MD **pmd);
+__owur int ssl_cert_type(const X509 *x, const EVP_PKEY *pkey);
+void ssl_set_masks(SSL *s);
+__owur STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s);
+__owur int ssl_verify_alarm_type(long type);
+void ssl_sort_cipher_list(void);
+void ssl_load_ciphers(void);
+__owur int ssl_fill_hello_random(SSL *s, int server, unsigned char *field,
+ int len);
+__owur int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen,
+ int free_pms);
+__owur EVP_PKEY *ssl_generate_pkey(EVP_PKEY *pm);
+__owur int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey);
+__owur EVP_PKEY *ssl_dh_to_pkey(DH *dh);
+
+__owur const SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p);
+__owur int ssl3_put_cipher_by_char(const SSL_CIPHER *c, unsigned char *p);
+int ssl3_init_finished_mac(SSL *s);
+__owur int ssl3_setup_key_block(SSL *s);
+__owur int ssl3_change_cipher_state(SSL *s, int which);
+void ssl3_cleanup_key_block(SSL *s);
+__owur int ssl3_do_write(SSL *s, int type);
+int ssl3_send_alert(SSL *s, int level, int desc);
+__owur int ssl3_generate_master_secret(SSL *s, unsigned char *out,
+ unsigned char *p, int len);
+__owur int ssl3_get_req_cert_type(SSL *s, unsigned char *p);
+__owur int ssl3_num_ciphers(void);
+__owur const SSL_CIPHER *ssl3_get_cipher(unsigned int u);
+int ssl3_renegotiate(SSL *ssl);
+int ssl3_renegotiate_check(SSL *ssl);
+__owur int ssl3_dispatch_alert(SSL *s);
+__owur int ssl3_final_finish_mac(SSL *s, const char *sender, int slen,
+ unsigned char *p);
+__owur int ssl3_finish_mac(SSL *s, const unsigned char *buf, int len);
+void ssl3_free_digest_list(SSL *s);
+__owur unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk);
+__owur const SSL_CIPHER *ssl3_choose_cipher(SSL *ssl,
+ STACK_OF(SSL_CIPHER) *clnt,
+ STACK_OF(SSL_CIPHER) *srvr);
+__owur int ssl3_digest_cached_records(SSL *s, int keep);
+__owur int ssl3_new(SSL *s);
+void ssl3_free(SSL *s);
+__owur int ssl3_read(SSL *s, void *buf, int len);
+__owur int ssl3_peek(SSL *s, void *buf, int len);
+__owur int ssl3_write(SSL *s, const void *buf, int len);
+__owur int ssl3_shutdown(SSL *s);
+void ssl3_clear(SSL *s);
+__owur long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg);
+__owur long ssl3_ctx_ctrl(SSL_CTX *s, int cmd, long larg, void *parg);
+__owur long ssl3_callback_ctrl(SSL *s, int cmd, void (*fp) (void));
+__owur long ssl3_ctx_callback_ctrl(SSL_CTX *s, int cmd, void (*fp) (void));
+
+__owur int ssl3_do_change_cipher_spec(SSL *ssl);
+__owur long ssl3_default_timeout(void);
+
+__owur int ssl3_set_handshake_header(SSL *s, int htype, unsigned long len);
+__owur int ssl3_handshake_write(SSL *s);
+
+__owur int ssl_allow_compression(SSL *s);
+
+__owur int ssl_version_supported(const SSL *s, int version);
+
+__owur int ssl_set_client_hello_version(SSL *s);
+__owur int ssl_check_version_downgrade(SSL *s);
+__owur int ssl_set_version_bound(int method_version, int version, int *bound);
+__owur int ssl_choose_server_version(SSL *s);
+__owur int ssl_choose_client_version(SSL *s, int version);
+int ssl_get_client_min_max_version(const SSL *s, int *min_version,
+ int *max_version);
+
+__owur long tls1_default_timeout(void);
+__owur int dtls1_do_write(SSL *s, int type);
+void dtls1_set_message_header(SSL *s,
+ unsigned char mt,
+ unsigned long len,
+ unsigned long frag_off, unsigned long frag_len);
+
+__owur int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf,
+ int len);
+
+__owur int dtls1_read_failed(SSL *s, int code);
+__owur int dtls1_buffer_message(SSL *s, int ccs);
+__owur int dtls1_retransmit_message(SSL *s, unsigned short seq, int *found);
+__owur int dtls1_get_queue_priority(unsigned short seq, int is_ccs);
+int dtls1_retransmit_buffered_messages(SSL *s);
+void dtls1_clear_received_buffer(SSL *s);
+void dtls1_clear_sent_buffer(SSL *s);
+void dtls1_get_message_header(unsigned char *data,
+ struct hm_header_st *msg_hdr);
+__owur long dtls1_default_timeout(void);
+__owur struct timeval *dtls1_get_timeout(SSL *s, struct timeval *timeleft);
+__owur int dtls1_check_timeout_num(SSL *s);
+__owur int dtls1_handle_timeout(SSL *s);
+void dtls1_start_timer(SSL *s);
+void dtls1_stop_timer(SSL *s);
+__owur int dtls1_is_timer_expired(SSL *s);
+void dtls1_double_timeout(SSL *s);
+__owur unsigned int dtls_raw_hello_verify_request(unsigned char *buf,
+ unsigned char *cookie,
+ unsigned char cookie_len);
+__owur int dtls1_send_newsession_ticket(SSL *s);
+__owur unsigned int dtls1_min_mtu(SSL *s);
+void dtls1_hm_fragment_free(hm_fragment *frag);
+__owur int dtls1_query_mtu(SSL *s);
+
+__owur int tls1_new(SSL *s);
+void tls1_free(SSL *s);
+void tls1_clear(SSL *s);
+long tls1_ctrl(SSL *s, int cmd, long larg, void *parg);
+long tls1_callback_ctrl(SSL *s, int cmd, void (*fp) (void));
+
+__owur int dtls1_new(SSL *s);
+void dtls1_free(SSL *s);
+void dtls1_clear(SSL *s);
+long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg);
+__owur int dtls1_shutdown(SSL *s);
+
+__owur int dtls1_dispatch_alert(SSL *s);
+
+__owur int ssl_init_wbio_buffer(SSL *s);
+void ssl_free_wbio_buffer(SSL *s);
+
+__owur int tls1_change_cipher_state(SSL *s, int which);
+__owur int tls1_setup_key_block(SSL *s);
+__owur int tls1_final_finish_mac(SSL *s,
+ const char *str, int slen, unsigned char *p);
+__owur int tls1_generate_master_secret(SSL *s, unsigned char *out,
+ unsigned char *p, int len);
+__owur int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen,
+ const char *label, size_t llen,
+ const unsigned char *p, size_t plen,
+ int use_context);
+__owur int tls1_alert_code(int code);
+__owur int ssl3_alert_code(int code);
+__owur int ssl_ok(SSL *s);
+
+# ifndef OPENSSL_NO_EC
+__owur int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s);
+# endif
+
+SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n);
+
+# ifndef OPENSSL_NO_EC
+/* Flags values from tls1_ec_curve_id2nid() */
+/* Mask for curve type */
+# define TLS_CURVE_TYPE 0x3
+# define TLS_CURVE_PRIME 0x0
+# define TLS_CURVE_CHAR2 0x1
+# define TLS_CURVE_CUSTOM 0x2
+__owur int tls1_ec_curve_id2nid(int curve_id, unsigned int *pflags);
+__owur int tls1_ec_nid2curve_id(int nid);
+__owur int tls1_check_curve(SSL *s, const unsigned char *p, size_t len);
+__owur int tls1_shared_curve(SSL *s, int nmatch);
+__owur int tls1_set_curves(unsigned char **pext, size_t *pextlen,
+ int *curves, size_t ncurves);
+__owur int tls1_set_curves_list(unsigned char **pext, size_t *pextlen,
+ const char *str);
+__owur int tls1_check_ec_tmp_key(SSL *s, unsigned long id);
+__owur EVP_PKEY *ssl_generate_pkey_curve(int id);
+# endif /* OPENSSL_NO_EC */
+
+__owur int tls1_shared_list(SSL *s,
+ const unsigned char *l1, size_t l1len,
+ const unsigned char *l2, size_t l2len, int nmatch);
+__owur unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf,
+ unsigned char *limit, int *al);
+__owur unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
+ unsigned char *limit, int *al);
+__owur int ssl_parse_clienthello_tlsext(SSL *s, PACKET *pkt);
+void ssl_set_default_md(SSL *s);
+__owur int tls1_set_server_sigalgs(SSL *s);
+__owur int ssl_check_clienthello_tlsext_late(SSL *s, int *al);
+__owur int ssl_parse_serverhello_tlsext(SSL *s, PACKET *pkt);
+__owur int ssl_prepare_clienthello_tlsext(SSL *s);
+__owur int ssl_prepare_serverhello_tlsext(SSL *s);
+
+# ifndef OPENSSL_NO_HEARTBEATS
+__owur int dtls1_heartbeat(SSL *s);
+__owur int dtls1_process_heartbeat(SSL *s, unsigned char *p,
+ unsigned int length);
+# endif
+
+__owur int tls_check_serverhello_tlsext_early(SSL *s, const PACKET *ext,
+ const PACKET *session_id,
+ SSL_SESSION **ret);
+
+__owur int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk,
+ const EVP_MD *md);
+__owur int tls12_get_sigid(const EVP_PKEY *pk);
+__owur const EVP_MD *tls12_get_hash(unsigned char hash_alg);
+void ssl_set_sig_mask(uint32_t *pmask_a, SSL *s, int op);
+
+__owur int tls1_set_sigalgs_list(CERT *c, const char *str, int client);
+__owur int tls1_set_sigalgs(CERT *c, const int *salg, size_t salglen,
+ int client);
+int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
+ int idx);
+void tls1_set_cert_validity(SSL *s);
+
+# ifndef OPENSSL_NO_CT
+__owur int ssl_validate_ct(SSL *s);
+# endif
+
+# ifndef OPENSSL_NO_DH
+__owur DH *ssl_get_auto_dh(SSL *s);
+# endif
+
+__owur int ssl_security_cert(SSL *s, SSL_CTX *ctx, X509 *x, int vfy, int is_ee);
+__owur int ssl_security_cert_chain(SSL *s, STACK_OF(X509) *sk, X509 *ex,
+ int vfy);
+
+__owur EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash, const EVP_MD *md);
+void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
+__owur int ssl_add_serverhello_renegotiate_ext(SSL *s, unsigned char *p,
+ int *len, int maxlen);
+__owur int ssl_parse_serverhello_renegotiate_ext(SSL *s, PACKET *pkt, int *al);
+__owur int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p,
+ int *len, int maxlen);
+__owur int ssl_parse_clienthello_renegotiate_ext(SSL *s, PACKET *pkt, int *al);
+__owur long ssl_get_algorithm2(SSL *s);
+__owur size_t tls12_copy_sigalgs(SSL *s, unsigned char *out,
+ const unsigned char *psig, size_t psiglen);
+__owur int tls1_save_sigalgs(SSL *s, const unsigned char *data, int dsize);
+__owur int tls1_process_sigalgs(SSL *s);
+__owur size_t tls12_get_psigalgs(SSL *s, int sent, const unsigned char **psigs);
+__owur int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
+ const unsigned char *sig, EVP_PKEY *pkey);
+void ssl_set_client_disabled(SSL *s);
+__owur int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op, int echde);
+
+__owur int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len,
+ int maxlen);
+__owur int ssl_parse_clienthello_use_srtp_ext(SSL *s, PACKET *pkt, int *al);
+__owur int ssl_add_serverhello_use_srtp_ext(SSL *s, unsigned char *p, int *len,
+ int maxlen);
+__owur int ssl_parse_serverhello_use_srtp_ext(SSL *s, PACKET *pkt, int *al);
+
+__owur int ssl_handshake_hash(SSL *s, unsigned char *out, int outlen);
+__owur const EVP_MD *ssl_md(int idx);
+__owur const EVP_MD *ssl_handshake_md(SSL *s);
+__owur const EVP_MD *ssl_prf_md(SSL *s);
+
+/* s3_cbc.c */
+__owur char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx);
+__owur int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
+ unsigned char *md_out,
+ size_t *md_out_size,
+ const unsigned char header[13],
+ const unsigned char *data,
+ size_t data_plus_mac_size,
+ size_t data_plus_mac_plus_padding_size,
+ const unsigned char *mac_secret,
+ unsigned mac_secret_length, char is_sslv3);
+
+__owur int tls_fips_digest_extra(const EVP_CIPHER_CTX *cipher_ctx,
+ EVP_MD_CTX *mac_ctx, const unsigned char *data,
+ size_t data_len, size_t orig_len);
+
+__owur int srp_generate_server_master_secret(SSL *s);
+__owur int srp_generate_client_master_secret(SSL *s);
+__owur int srp_verify_server_param(SSL *s, int *al);
+
+/* t1_ext.c */
+
+void custom_ext_init(custom_ext_methods *meths);
+
+__owur int custom_ext_parse(SSL *s, int server,
+ unsigned int ext_type,
+ const unsigned char *ext_data, size_t ext_size,
+ int *al);
+__owur int custom_ext_add(SSL *s, int server, unsigned char **pret,
+ unsigned char *limit, int *al);
+
+__owur int custom_exts_copy(custom_ext_methods *dst,
+ const custom_ext_methods *src);
+__owur int custom_exts_copy_flags(custom_ext_methods *dst,
+ const custom_ext_methods *src);
+void custom_exts_free(custom_ext_methods *exts);
+
+void ssl_comp_free_compression_methods_int(void);
+
+# else
+
+# define ssl_init_wbio_buffer SSL_test_functions()->p_ssl_init_wbio_buffer
+# define ssl3_setup_buffers SSL_test_functions()->p_ssl3_setup_buffers
+# define dtls1_process_heartbeat SSL_test_functions()->p_dtls1_process_heartbeat
+
+# endif
+#endif
diff --git a/openssl-1.1.0h/ssl/ssl_mcnf.c b/openssl-1.1.0h/ssl/ssl_mcnf.c
new file mode 100644
index 0000000..c2d9dba
--- /dev/null
+++ b/openssl-1.1.0h/ssl/ssl_mcnf.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2015-2016 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
+ */
+
+#include <stdio.h>
+#include <openssl/conf.h>
+#include <openssl/ssl.h>
+#include "ssl_locl.h"
+
+/* SSL library configuration module. */
+
+struct ssl_conf_name {
+ /* Name of this set of commands */
+ char *name;
+ /* List of commands */
+ struct ssl_conf_cmd *cmds;
+ /* Number of commands */
+ size_t cmd_count;
+};
+
+struct ssl_conf_cmd {
+ /* Command */
+ char *cmd;
+ /* Argument */
+ char *arg;
+};
+
+static struct ssl_conf_name *ssl_names;
+static size_t ssl_names_count;
+
+static void ssl_module_free(CONF_IMODULE *md)
+{
+ size_t i, j;
+ if (ssl_names == NULL)
+ return;
+ for (i = 0; i < ssl_names_count; i++) {
+ struct ssl_conf_name *tname = ssl_names + i;
+ OPENSSL_free(tname->name);
+ for (j = 0; j < tname->cmd_count; j++) {
+ OPENSSL_free(tname->cmds[j].cmd);
+ OPENSSL_free(tname->cmds[j].arg);
+ }
+ OPENSSL_free(tname->cmds);
+ }
+ OPENSSL_free(ssl_names);
+ ssl_names = NULL;
+ ssl_names_count = 0;
+}
+
+static int ssl_module_init(CONF_IMODULE *md, const CONF *cnf)
+{
+ size_t i, j, cnt;
+ int rv = 0;
+ const char *ssl_conf_section;
+ STACK_OF(CONF_VALUE) *cmd_lists;
+ ssl_conf_section = CONF_imodule_get_value(md);
+ cmd_lists = NCONF_get_section(cnf, ssl_conf_section);
+ if (sk_CONF_VALUE_num(cmd_lists) <= 0) {
+ if (cmd_lists == NULL)
+ SSLerr(SSL_F_SSL_MODULE_INIT, SSL_R_SSL_SECTION_NOT_FOUND);
+ else
+ SSLerr(SSL_F_SSL_MODULE_INIT, SSL_R_SSL_SECTION_EMPTY);
+ ERR_add_error_data(2, "section=", ssl_conf_section);
+ goto err;
+ }
+ cnt = sk_CONF_VALUE_num(cmd_lists);
+ ssl_names = OPENSSL_zalloc(sizeof(*ssl_names) * cnt);
+ ssl_names_count = cnt;
+ for (i = 0; i < ssl_names_count; i++) {
+ struct ssl_conf_name *ssl_name = ssl_names + i;
+ CONF_VALUE *sect = sk_CONF_VALUE_value(cmd_lists, i);
+ STACK_OF(CONF_VALUE) *cmds = NCONF_get_section(cnf, sect->value);
+ if (sk_CONF_VALUE_num(cmds) <= 0) {
+ if (cmds == NULL)
+ SSLerr(SSL_F_SSL_MODULE_INIT,
+ SSL_R_SSL_COMMAND_SECTION_NOT_FOUND);
+ else
+ SSLerr(SSL_F_SSL_MODULE_INIT, SSL_R_SSL_COMMAND_SECTION_EMPTY);
+ ERR_add_error_data(4, "name=", sect->name, ", value=", sect->value);
+ goto err;
+ }
+ ssl_name->name = BUF_strdup(sect->name);
+ if (ssl_name->name == NULL)
+ goto err;
+ cnt = sk_CONF_VALUE_num(cmds);
+ ssl_name->cmds = OPENSSL_zalloc(cnt * sizeof(struct ssl_conf_cmd));
+ if (ssl_name->cmds == NULL)
+ goto err;
+ ssl_name->cmd_count = cnt;
+ for (j = 0; j < cnt; j++) {
+ const char *name;
+ CONF_VALUE *cmd_conf = sk_CONF_VALUE_value(cmds, j);
+ struct ssl_conf_cmd *cmd = ssl_name->cmds + j;
+ /* Skip any initial dot in name */
+ name = strchr(cmd_conf->name, '.');
+ if (name != NULL)
+ name++;
+ else
+ name = cmd_conf->name;
+ cmd->cmd = BUF_strdup(name);
+ cmd->arg = BUF_strdup(cmd_conf->value);
+ if (cmd->cmd == NULL || cmd->arg == NULL)
+ goto err;
+ }
+
+ }
+ rv = 1;
+ err:
+ if (rv == 0)
+ ssl_module_free(md);
+ return rv;
+}
+
+void SSL_add_ssl_module(void)
+{
+ CONF_module_add("ssl_conf", ssl_module_init, ssl_module_free);
+}
+
+static const struct ssl_conf_name *ssl_name_find(const char *name)
+{
+ size_t i;
+ const struct ssl_conf_name *nm;
+ if (name == NULL)
+ return NULL;
+ for (i = 0, nm = ssl_names; i < ssl_names_count; i++, nm++) {
+ if (strcmp(nm->name, name) == 0)
+ return nm;
+ }
+ return NULL;
+}
+
+static int ssl_do_config(SSL *s, SSL_CTX *ctx, const char *name)
+{
+ SSL_CONF_CTX *cctx = NULL;
+ size_t i;
+ int rv = 0;
+ unsigned int flags;
+ const SSL_METHOD *meth;
+ const struct ssl_conf_name *nm;
+ struct ssl_conf_cmd *cmd;
+ if (s == NULL && ctx == NULL) {
+ SSLerr(SSL_F_SSL_DO_CONFIG, ERR_R_PASSED_NULL_PARAMETER);
+ goto err;
+ }
+ nm = ssl_name_find(name);
+ if (nm == NULL) {
+ SSLerr(SSL_F_SSL_DO_CONFIG, SSL_R_INVALID_CONFIGURATION_NAME);
+ ERR_add_error_data(2, "name=", name);
+ goto err;
+ }
+ cctx = SSL_CONF_CTX_new();
+ if (cctx == NULL)
+ goto err;
+ flags = SSL_CONF_FLAG_FILE;
+ flags |= SSL_CONF_FLAG_CERTIFICATE | SSL_CONF_FLAG_REQUIRE_PRIVATE;
+ if (s != NULL) {
+ meth = s->method;
+ SSL_CONF_CTX_set_ssl(cctx, s);
+ } else {
+ meth = ctx->method;
+ SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
+ }
+ if (meth->ssl_accept != ssl_undefined_function)
+ flags |= SSL_CONF_FLAG_SERVER;
+ if (meth->ssl_connect != ssl_undefined_function)
+ flags |= SSL_CONF_FLAG_CLIENT;
+ SSL_CONF_CTX_set_flags(cctx, flags);
+ for (i = 0, cmd = nm->cmds; i < nm->cmd_count; i++, cmd++) {
+ rv = SSL_CONF_cmd(cctx, cmd->cmd, cmd->arg);
+ if (rv <= 0) {
+ if (rv == -2)
+ SSLerr(SSL_F_SSL_DO_CONFIG, SSL_R_UNKNOWN_COMMAND);
+ else
+ SSLerr(SSL_F_SSL_DO_CONFIG, SSL_R_BAD_VALUE);
+ ERR_add_error_data(6, "section=", name, ", cmd=", cmd->cmd,
+ ", arg=", cmd->arg);
+ goto err;
+ }
+ }
+ rv = SSL_CONF_CTX_finish(cctx);
+ err:
+ SSL_CONF_CTX_free(cctx);
+ return rv <= 0 ? 0 : 1;
+}
+
+int SSL_config(SSL *s, const char *name)
+{
+ return ssl_do_config(s, NULL, name);
+}
+
+int SSL_CTX_config(SSL_CTX *ctx, const char *name)
+{
+ return ssl_do_config(NULL, ctx, name);
+}
diff --git a/openssl-1.1.0h/ssl/ssl_rsa.c b/openssl-1.1.0h/ssl/ssl_rsa.c
new file mode 100644
index 0000000..a94fb13
--- /dev/null
+++ b/openssl-1.1.0h/ssl/ssl_rsa.c
@@ -0,0 +1,964 @@
+/*
+ * Copyright 1995-2016 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
+ */
+
+#include <stdio.h>
+#include "ssl_locl.h"
+#include <openssl/bio.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+
+static int ssl_set_cert(CERT *c, X509 *x509);
+static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey);
+int SSL_use_certificate(SSL *ssl, X509 *x)
+{
+ int rv;
+ if (x == NULL) {
+ SSLerr(SSL_F_SSL_USE_CERTIFICATE, ERR_R_PASSED_NULL_PARAMETER);
+ return (0);
+ }
+ rv = ssl_security_cert(ssl, NULL, x, 0, 1);
+ if (rv != 1) {
+ SSLerr(SSL_F_SSL_USE_CERTIFICATE, rv);
+ return 0;
+ }
+
+ return (ssl_set_cert(ssl->cert, x));
+}
+
+int SSL_use_certificate_file(SSL *ssl, const char *file, int type)
+{
+ int j;
+ BIO *in;
+ int ret = 0;
+ X509 *x = NULL;
+
+ in = BIO_new(BIO_s_file());
+ if (in == NULL) {
+ SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, ERR_R_BUF_LIB);
+ goto end;
+ }
+
+ if (BIO_read_filename(in, file) <= 0) {
+ SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, ERR_R_SYS_LIB);
+ goto end;
+ }
+ if (type == SSL_FILETYPE_ASN1) {
+ j = ERR_R_ASN1_LIB;
+ x = d2i_X509_bio(in, NULL);
+ } else if (type == SSL_FILETYPE_PEM) {
+ j = ERR_R_PEM_LIB;
+ x = PEM_read_bio_X509(in, NULL, ssl->default_passwd_callback,
+ ssl->default_passwd_callback_userdata);
+ } else {
+ SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, SSL_R_BAD_SSL_FILETYPE);
+ goto end;
+ }
+
+ if (x == NULL) {
+ SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, j);
+ goto end;
+ }
+
+ ret = SSL_use_certificate(ssl, x);
+ end:
+ X509_free(x);
+ BIO_free(in);
+ return (ret);
+}
+
+int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len)
+{
+ X509 *x;
+ int ret;
+
+ x = d2i_X509(NULL, &d, (long)len);
+ if (x == NULL) {
+ SSLerr(SSL_F_SSL_USE_CERTIFICATE_ASN1, ERR_R_ASN1_LIB);
+ return (0);
+ }
+
+ ret = SSL_use_certificate(ssl, x);
+ X509_free(x);
+ return (ret);
+}
+
+#ifndef OPENSSL_NO_RSA
+int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa)
+{
+ EVP_PKEY *pkey;
+ int ret;
+
+ if (rsa == NULL) {
+ SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER);
+ return (0);
+ }
+ if ((pkey = EVP_PKEY_new()) == NULL) {
+ SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY, ERR_R_EVP_LIB);
+ return (0);
+ }
+
+ RSA_up_ref(rsa);
+ if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0) {
+ RSA_free(rsa);
+ EVP_PKEY_free(pkey);
+ return 0;
+ }
+
+ ret = ssl_set_pkey(ssl->cert, pkey);
+ EVP_PKEY_free(pkey);
+ return (ret);
+}
+#endif
+
+static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey)
+{
+ int i;
+ i = ssl_cert_type(NULL, pkey);
+ if (i < 0) {
+ SSLerr(SSL_F_SSL_SET_PKEY, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+ return (0);
+ }
+
+ if (c->pkeys[i].x509 != NULL) {
+ EVP_PKEY *pktmp;
+ pktmp = X509_get0_pubkey(c->pkeys[i].x509);
+ if (pktmp == NULL) {
+ SSLerr(SSL_F_SSL_SET_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 (!X509_check_private_key(c->pkeys[i].x509, pkey)) {
+ X509_free(c->pkeys[i].x509);
+ c->pkeys[i].x509 = NULL;
+ return 0;
+ }
+ }
+
+ EVP_PKEY_free(c->pkeys[i].privatekey);
+ EVP_PKEY_up_ref(pkey);
+ c->pkeys[i].privatekey = pkey;
+ c->key = &(c->pkeys[i]);
+ return (1);
+}
+
+#ifndef OPENSSL_NO_RSA
+int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type)
+{
+ int j, ret = 0;
+ BIO *in;
+ RSA *rsa = NULL;
+
+ in = BIO_new(BIO_s_file());
+ if (in == NULL) {
+ SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, ERR_R_BUF_LIB);
+ goto end;
+ }
+
+ if (BIO_read_filename(in, file) <= 0) {
+ SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, ERR_R_SYS_LIB);
+ goto end;
+ }
+ if (type == SSL_FILETYPE_ASN1) {
+ j = ERR_R_ASN1_LIB;
+ rsa = d2i_RSAPrivateKey_bio(in, NULL);
+ } else if (type == SSL_FILETYPE_PEM) {
+ j = ERR_R_PEM_LIB;
+ rsa = PEM_read_bio_RSAPrivateKey(in, NULL,
+ ssl->default_passwd_callback,
+ ssl->default_passwd_callback_userdata);
+ } else {
+ SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, SSL_R_BAD_SSL_FILETYPE);
+ goto end;
+ }
+ if (rsa == NULL) {
+ SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, j);
+ goto end;
+ }
+ ret = SSL_use_RSAPrivateKey(ssl, rsa);
+ RSA_free(rsa);
+ end:
+ BIO_free(in);
+ return (ret);
+}
+
+int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const unsigned char *d, long len)
+{
+ int ret;
+ const unsigned char *p;
+ RSA *rsa;
+
+ p = d;
+ if ((rsa = d2i_RSAPrivateKey(NULL, &p, (long)len)) == NULL) {
+ SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1, ERR_R_ASN1_LIB);
+ return (0);
+ }
+
+ ret = SSL_use_RSAPrivateKey(ssl, rsa);
+ RSA_free(rsa);
+ return (ret);
+}
+#endif /* !OPENSSL_NO_RSA */
+
+int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey)
+{
+ int ret;
+
+ if (pkey == NULL) {
+ SSLerr(SSL_F_SSL_USE_PRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER);
+ return (0);
+ }
+ ret = ssl_set_pkey(ssl->cert, pkey);
+ return (ret);
+}
+
+int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type)
+{
+ int j, ret = 0;
+ BIO *in;
+ EVP_PKEY *pkey = NULL;
+
+ in = BIO_new(BIO_s_file());
+ if (in == NULL) {
+ SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE, ERR_R_BUF_LIB);
+ goto end;
+ }
+
+ if (BIO_read_filename(in, file) <= 0) {
+ SSLerr(SSL_F_SSL_USE_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_PRIVATEKEY_FILE, SSL_R_BAD_SSL_FILETYPE);
+ goto end;
+ }
+ if (pkey == NULL) {
+ SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE, j);
+ goto end;
+ }
+ ret = SSL_use_PrivateKey(ssl, pkey);
+ EVP_PKEY_free(pkey);
+ end:
+ BIO_free(in);
+ return (ret);
+}
+
+int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const unsigned char *d,
+ long len)
+{
+ int ret;
+ const unsigned char *p;
+ EVP_PKEY *pkey;
+
+ p = d;
+ if ((pkey = d2i_PrivateKey(type, NULL, &p, (long)len)) == NULL) {
+ SSLerr(SSL_F_SSL_USE_PRIVATEKEY_ASN1, ERR_R_ASN1_LIB);
+ return (0);
+ }
+
+ ret = SSL_use_PrivateKey(ssl, pkey);
+ EVP_PKEY_free(pkey);
+ return (ret);
+}
+
+int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x)
+{
+ int rv;
+ if (x == NULL) {
+ SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE, ERR_R_PASSED_NULL_PARAMETER);
+ return (0);
+ }
+ rv = ssl_security_cert(NULL, ctx, x, 0, 1);
+ if (rv != 1) {
+ SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE, rv);
+ return 0;
+ }
+ return (ssl_set_cert(ctx->cert, x));
+}
+
+static int ssl_set_cert(CERT *c, X509 *x)
+{
+ EVP_PKEY *pkey;
+ int i;
+
+ pkey = X509_get0_pubkey(x);
+ if (pkey == NULL) {
+ SSLerr(SSL_F_SSL_SET_CERT, SSL_R_X509_LIB);
+ return (0);
+ }
+
+ i = ssl_cert_type(x, pkey);
+ if (i < 0) {
+ SSLerr(SSL_F_SSL_SET_CERT, 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_CERT, SSL_R_ECC_CERT_NOT_FOR_SIGNING);
+ return 0;
+ }
+#endif
+ if (c->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->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->pkeys[i].privatekey) == EVP_PKEY_RSA
+ && RSA_flags(EVP_PKEY_get0_RSA(c->pkeys[i].privatekey)) &
+ RSA_METHOD_FLAG_NO_CHECK) ;
+ else
+#endif /* OPENSSL_NO_RSA */
+ if (!X509_check_private_key(x, c->pkeys[i].privatekey)) {
+ /*
+ * don't fail for a cert/key mismatch, just free current private
+ * key (when switching to a different cert & key, first this
+ * function should be used, then ssl_set_pkey
+ */
+ EVP_PKEY_free(c->pkeys[i].privatekey);
+ c->pkeys[i].privatekey = NULL;
+ /* clear error queue */
+ ERR_clear_error();
+ }
+ }
+
+ X509_free(c->pkeys[i].x509);
+ X509_up_ref(x);
+ c->pkeys[i].x509 = x;
+ c->key = &(c->pkeys[i]);
+
+ return 1;
+}
+
+int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type)
+{
+ int j;
+ BIO *in;
+ int ret = 0;
+ X509 *x = NULL;
+
+ in = BIO_new(BIO_s_file());
+ if (in == NULL) {
+ SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_BUF_LIB);
+ goto end;
+ }
+
+ if (BIO_read_filename(in, file) <= 0) {
+ SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_SYS_LIB);
+ goto end;
+ }
+ if (type == SSL_FILETYPE_ASN1) {
+ j = ERR_R_ASN1_LIB;
+ x = d2i_X509_bio(in, NULL);
+ } else if (type == SSL_FILETYPE_PEM) {
+ j = ERR_R_PEM_LIB;
+ x = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback,
+ ctx->default_passwd_callback_userdata);
+ } else {
+ SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, SSL_R_BAD_SSL_FILETYPE);
+ goto end;
+ }
+
+ if (x == NULL) {
+ SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, j);
+ goto end;
+ }
+
+ ret = SSL_CTX_use_certificate(ctx, x);
+ end:
+ X509_free(x);
+ BIO_free(in);
+ return (ret);
+}
+
+int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d)
+{
+ X509 *x;
+ int ret;
+
+ x = d2i_X509(NULL, &d, (long)len);
+ if (x == NULL) {
+ SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1, ERR_R_ASN1_LIB);
+ return (0);
+ }
+
+ ret = SSL_CTX_use_certificate(ctx, x);
+ X509_free(x);
+ return (ret);
+}
+
+#ifndef OPENSSL_NO_RSA
+int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa)
+{
+ int ret;
+ EVP_PKEY *pkey;
+
+ if (rsa == NULL) {
+ SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER);
+ return (0);
+ }
+ if ((pkey = EVP_PKEY_new()) == NULL) {
+ SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY, ERR_R_EVP_LIB);
+ return (0);
+ }
+
+ RSA_up_ref(rsa);
+ if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0) {
+ RSA_free(rsa);
+ EVP_PKEY_free(pkey);
+ return 0;
+ }
+
+ ret = ssl_set_pkey(ctx->cert, pkey);
+ EVP_PKEY_free(pkey);
+ return (ret);
+}
+
+int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type)
+{
+ int j, ret = 0;
+ BIO *in;
+ RSA *rsa = NULL;
+
+ in = BIO_new(BIO_s_file());
+ if (in == NULL) {
+ SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE, ERR_R_BUF_LIB);
+ goto end;
+ }
+
+ if (BIO_read_filename(in, file) <= 0) {
+ SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE, ERR_R_SYS_LIB);
+ goto end;
+ }
+ if (type == SSL_FILETYPE_ASN1) {
+ j = ERR_R_ASN1_LIB;
+ rsa = d2i_RSAPrivateKey_bio(in, NULL);
+ } else if (type == SSL_FILETYPE_PEM) {
+ j = ERR_R_PEM_LIB;
+ rsa = PEM_read_bio_RSAPrivateKey(in, NULL,
+ ctx->default_passwd_callback,
+ ctx->default_passwd_callback_userdata);
+ } else {
+ SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE, SSL_R_BAD_SSL_FILETYPE);
+ goto end;
+ }
+ if (rsa == NULL) {
+ SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE, j);
+ goto end;
+ }
+ ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
+ RSA_free(rsa);
+ end:
+ BIO_free(in);
+ return (ret);
+}
+
+int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d,
+ long len)
+{
+ int ret;
+ const unsigned char *p;
+ RSA *rsa;
+
+ p = d;
+ if ((rsa = d2i_RSAPrivateKey(NULL, &p, (long)len)) == NULL) {
+ SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1, ERR_R_ASN1_LIB);
+ return (0);
+ }
+
+ ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
+ RSA_free(rsa);
+ return (ret);
+}
+#endif /* !OPENSSL_NO_RSA */
+
+int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey)
+{
+ if (pkey == NULL) {
+ SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER);
+ return (0);
+ }
+ return (ssl_set_pkey(ctx->cert, pkey));
+}
+
+int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type)
+{
+ int j, ret = 0;
+ BIO *in;
+ EVP_PKEY *pkey = NULL;
+
+ in = BIO_new(BIO_s_file());
+ if (in == NULL) {
+ SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_BUF_LIB);
+ goto end;
+ }
+
+ if (BIO_read_filename(in, file) <= 0) {
+ SSLerr(SSL_F_SSL_CTX_USE_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_PRIVATEKEY_FILE, SSL_R_BAD_SSL_FILETYPE);
+ goto end;
+ }
+ if (pkey == NULL) {
+ SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, j);
+ goto end;
+ }
+ ret = SSL_CTX_use_PrivateKey(ctx, pkey);
+ EVP_PKEY_free(pkey);
+ end:
+ BIO_free(in);
+ return (ret);
+}
+
+int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx,
+ const unsigned char *d, long len)
+{
+ int ret;
+ const unsigned char *p;
+ EVP_PKEY *pkey;
+
+ p = d;
+ if ((pkey = d2i_PrivateKey(type, NULL, &p, (long)len)) == NULL) {
+ SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1, ERR_R_ASN1_LIB);
+ return (0);
+ }
+
+ ret = SSL_CTX_use_PrivateKey(ctx, pkey);
+ EVP_PKEY_free(pkey);
+ return (ret);
+}
+
+/*
+ * Read a file that contains our certificate in "PEM" format, possibly
+ * followed by a sequence of CA certificates that should be sent to the peer
+ * in the Certificate message.
+ */
+static int use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl, const char *file)
+{
+ BIO *in;
+ int ret = 0;
+ X509 *x = NULL;
+ pem_password_cb *passwd_callback;
+ void *passwd_callback_userdata;
+
+ ERR_clear_error(); /* clear error stack for
+ * SSL_CTX_use_certificate() */
+
+ if (ctx != NULL) {
+ passwd_callback = ctx->default_passwd_callback;
+ passwd_callback_userdata = ctx->default_passwd_callback_userdata;
+ } else {
+ passwd_callback = ssl->default_passwd_callback;
+ passwd_callback_userdata = ssl->default_passwd_callback_userdata;
+ }
+
+ in = BIO_new(BIO_s_file());
+ if (in == NULL) {
+ SSLerr(SSL_F_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB);
+ goto end;
+ }
+
+ if (BIO_read_filename(in, file) <= 0) {
+ SSLerr(SSL_F_USE_CERTIFICATE_CHAIN_FILE, ERR_R_SYS_LIB);
+ goto end;
+ }
+
+ x = PEM_read_bio_X509_AUX(in, NULL, passwd_callback,
+ passwd_callback_userdata);
+ if (x == NULL) {
+ SSLerr(SSL_F_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB);
+ goto end;
+ }
+
+ if (ctx)
+ ret = SSL_CTX_use_certificate(ctx, x);
+ else
+ ret = SSL_use_certificate(ssl, x);
+
+ if (ERR_peek_error() != 0)
+ ret = 0; /* Key/certificate mismatch doesn't imply
+ * ret==0 ... */
+ if (ret) {
+ /*
+ * If we could set up our certificate, now proceed to the CA
+ * certificates.
+ */
+ X509 *ca;
+ int r;
+ unsigned long err;
+
+ if (ctx)
+ r = SSL_CTX_clear_chain_certs(ctx);
+ else
+ r = SSL_clear_chain_certs(ssl);
+
+ if (r == 0) {
+ ret = 0;
+ goto end;
+ }
+
+ while ((ca = PEM_read_bio_X509(in, NULL, passwd_callback,
+ passwd_callback_userdata))
+ != NULL) {
+ if (ctx)
+ r = SSL_CTX_add0_chain_cert(ctx, ca);
+ else
+ r = SSL_add0_chain_cert(ssl, ca);
+ /*
+ * Note that we must not free ca if it was successfully added to
+ * the chain (while we must free the main certificate, since its
+ * reference count is increased by SSL_CTX_use_certificate).
+ */
+ if (!r) {
+ X509_free(ca);
+ ret = 0;
+ goto end;
+ }
+ }
+ /* When the while loop ends, it's usually just EOF. */
+ err = ERR_peek_last_error();
+ if (ERR_GET_LIB(err) == ERR_LIB_PEM
+ && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)
+ ERR_clear_error();
+ else
+ ret = 0; /* some real error */
+ }
+
+ end:
+ X509_free(x);
+ BIO_free(in);
+ return (ret);
+}
+
+int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file)
+{
+ return use_certificate_chain_file(ctx, NULL, file);
+}
+
+int SSL_use_certificate_chain_file(SSL *ssl, const char *file)
+{
+ return use_certificate_chain_file(NULL, ssl, file);
+}
+
+static int serverinfo_find_extension(const unsigned char *serverinfo,
+ size_t serverinfo_length,
+ unsigned int extension_type,
+ const unsigned char **extension_data,
+ size_t *extension_length)
+{
+ *extension_data = NULL;
+ *extension_length = 0;
+ if (serverinfo == NULL || serverinfo_length == 0)
+ return -1;
+ for (;;) {
+ unsigned int type = 0;
+ size_t len = 0;
+
+ /* end of serverinfo */
+ if (serverinfo_length == 0)
+ return 0; /* Extension not found */
+
+ /* read 2-byte type field */
+ if (serverinfo_length < 2)
+ return -1; /* Error */
+ type = (serverinfo[0] << 8) + serverinfo[1];
+ serverinfo += 2;
+ serverinfo_length -= 2;
+
+ /* read 2-byte len field */
+ if (serverinfo_length < 2)
+ return -1; /* Error */
+ len = (serverinfo[0] << 8) + serverinfo[1];
+ serverinfo += 2;
+ serverinfo_length -= 2;
+
+ if (len > serverinfo_length)
+ return -1; /* Error */
+
+ if (type == extension_type) {
+ *extension_data = serverinfo;
+ *extension_length = len;
+ return 1; /* Success */
+ }
+
+ serverinfo += len;
+ serverinfo_length -= len;
+ }
+ /* Unreachable */
+}
+
+static int serverinfo_srv_parse_cb(SSL *s, unsigned int ext_type,
+ const unsigned char *in,
+ size_t inlen, int *al, void *arg)
+{
+
+ if (inlen != 0) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ return 1;
+}
+
+static int serverinfo_srv_add_cb(SSL *s, unsigned int ext_type,
+ const unsigned char **out, size_t *outlen,
+ int *al, void *arg)
+{
+ const unsigned char *serverinfo = NULL;
+ size_t serverinfo_length = 0;
+
+ /* Is there serverinfo data for the chosen server cert? */
+ if ((ssl_get_server_cert_serverinfo(s, &serverinfo,
+ &serverinfo_length)) != 0) {
+ /* Find the relevant extension from the serverinfo */
+ int retval = serverinfo_find_extension(serverinfo, serverinfo_length,
+ ext_type, out, outlen);
+ if (retval == -1) {
+ *al = SSL_AD_DECODE_ERROR;
+ return -1; /* Error */
+ }
+ if (retval == 0)
+ return 0; /* No extension found, don't send extension */
+ return 1; /* Send extension */
+ }
+ return 0; /* No serverinfo data found, don't send
+ * extension */
+}
+
+/*
+ * With a NULL context, this function just checks that the serverinfo data
+ * parses correctly. With a non-NULL context, it registers callbacks for
+ * the included extensions.
+ */
+static int serverinfo_process_buffer(const unsigned char *serverinfo,
+ size_t serverinfo_length, SSL_CTX *ctx)
+{
+ if (serverinfo == NULL || serverinfo_length == 0)
+ return 0;
+ for (;;) {
+ unsigned int ext_type = 0;
+ size_t len = 0;
+
+ /* end of serverinfo */
+ if (serverinfo_length == 0)
+ return 1;
+
+ /* read 2-byte type field */
+ if (serverinfo_length < 2)
+ return 0;
+ /* FIXME: check for types we understand explicitly? */
+
+ /* Register callbacks for extensions */
+ ext_type = (serverinfo[0] << 8) + serverinfo[1];
+ if (ctx) {
+ int have_ext_cbs = 0;
+ size_t i;
+ custom_ext_methods *exts = &ctx->cert->srv_ext;
+ custom_ext_method *meth = exts->meths;
+
+ for (i = 0; i < exts->meths_count; i++, meth++) {
+ if (ext_type == meth->ext_type) {
+ have_ext_cbs = 1;
+ break;
+ }
+ }
+
+ if (!have_ext_cbs && !SSL_CTX_add_server_custom_ext(ctx, ext_type,
+ serverinfo_srv_add_cb,
+ NULL, NULL,
+ serverinfo_srv_parse_cb,
+ NULL))
+ return 0;
+ }
+
+ serverinfo += 2;
+ serverinfo_length -= 2;
+
+ /* read 2-byte len field */
+ if (serverinfo_length < 2)
+ return 0;
+ len = (serverinfo[0] << 8) + serverinfo[1];
+ serverinfo += 2;
+ serverinfo_length -= 2;
+
+ if (len > serverinfo_length)
+ return 0;
+
+ serverinfo += len;
+ serverinfo_length -= len;
+ }
+}
+
+int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo,
+ size_t serverinfo_length)
+{
+ unsigned char *new_serverinfo;
+
+ if (ctx == NULL || serverinfo == NULL || serverinfo_length == 0) {
+ SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if (!serverinfo_process_buffer(serverinfo, serverinfo_length, NULL)) {
+ SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, SSL_R_INVALID_SERVERINFO_DATA);
+ return 0;
+ }
+ if (ctx->cert->key == NULL) {
+ SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ new_serverinfo = OPENSSL_realloc(ctx->cert->key->serverinfo,
+ serverinfo_length);
+ if (new_serverinfo == NULL) {
+ SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ ctx->cert->key->serverinfo = new_serverinfo;
+ memcpy(ctx->cert->key->serverinfo, serverinfo, serverinfo_length);
+ ctx->cert->key->serverinfo_length = serverinfo_length;
+
+ /*
+ * Now that the serverinfo is validated and stored, go ahead and
+ * register callbacks.
+ */
+ if (!serverinfo_process_buffer(serverinfo, serverinfo_length, ctx)) {
+ SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, SSL_R_INVALID_SERVERINFO_DATA);
+ return 0;
+ }
+ return 1;
+}
+
+int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file)
+{
+ unsigned char *serverinfo = NULL;
+ unsigned char *tmp;
+ size_t serverinfo_length = 0;
+ unsigned char *extension = 0;
+ long extension_length = 0;
+ char *name = NULL;
+ char *header = NULL;
+ char namePrefix[] = "SERVERINFO FOR ";
+ int ret = 0;
+ BIO *bin = NULL;
+ size_t num_extensions = 0;
+
+ if (ctx == NULL || file == NULL) {
+ SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_PASSED_NULL_PARAMETER);
+ goto end;
+ }
+
+ bin = BIO_new(BIO_s_file());
+ if (bin == NULL) {
+ SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_BUF_LIB);
+ goto end;
+ }
+ if (BIO_read_filename(bin, file) <= 0) {
+ SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_SYS_LIB);
+ goto end;
+ }
+
+ for (num_extensions = 0;; num_extensions++) {
+ if (PEM_read_bio(bin, &name, &header, &extension, &extension_length)
+ == 0) {
+ /*
+ * There must be at least one extension in this file
+ */
+ if (num_extensions == 0) {
+ SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE,
+ SSL_R_NO_PEM_EXTENSIONS);
+ goto end;
+ } else /* End of file, we're done */
+ break;
+ }
+ /* Check that PEM name starts with "BEGIN SERVERINFO FOR " */
+ if (strlen(name) < strlen(namePrefix)) {
+ SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, SSL_R_PEM_NAME_TOO_SHORT);
+ goto end;
+ }
+ if (strncmp(name, namePrefix, strlen(namePrefix)) != 0) {
+ SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE,
+ SSL_R_PEM_NAME_BAD_PREFIX);
+ goto end;
+ }
+ /*
+ * Check that the decoded PEM data is plausible (valid length field)
+ */
+ if (extension_length < 4
+ || (extension[2] << 8) + extension[3] != extension_length - 4) {
+ SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, SSL_R_BAD_DATA);
+ goto end;
+ }
+ /* Append the decoded extension to the serverinfo buffer */
+ tmp = OPENSSL_realloc(serverinfo, serverinfo_length + extension_length);
+ if (tmp == NULL) {
+ SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+ serverinfo = tmp;
+ memcpy(serverinfo + serverinfo_length, extension, extension_length);
+ serverinfo_length += extension_length;
+
+ OPENSSL_free(name);
+ name = NULL;
+ OPENSSL_free(header);
+ header = NULL;
+ OPENSSL_free(extension);
+ extension = NULL;
+ }
+
+ ret = SSL_CTX_use_serverinfo(ctx, serverinfo, serverinfo_length);
+ end:
+ /* SSL_CTX_use_serverinfo makes a local copy of the serverinfo. */
+ OPENSSL_free(name);
+ OPENSSL_free(header);
+ OPENSSL_free(extension);
+ OPENSSL_free(serverinfo);
+ BIO_free(bin);
+ return ret;
+}
diff --git a/openssl-1.1.0h/ssl/ssl_sess.c b/openssl-1.1.0h/ssl/ssl_sess.c
new file mode 100644
index 0000000..0dea8b5
--- /dev/null
+++ b/openssl-1.1.0h/ssl/ssl_sess.c
@@ -0,0 +1,1179 @@
+/*
+ * Copyright 1995-2016 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
+ */
+
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <stdio.h>
+#include <openssl/lhash.h>
+#include <openssl/rand.h>
+#include <openssl/engine.h>
+#include "ssl_locl.h"
+
+static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
+static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s);
+static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck);
+
+SSL_SESSION *SSL_get_session(const SSL *ssl)
+/* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */
+{
+ return (ssl->session);
+}
+
+SSL_SESSION *SSL_get1_session(SSL *ssl)
+/* variant of SSL_get_session: caller really gets something */
+{
+ SSL_SESSION *sess;
+ /*
+ * Need to lock this all up rather than just use CRYPTO_add so that
+ * somebody doesn't free ssl->session between when we check it's non-null
+ * and when we up the reference count.
+ */
+ CRYPTO_THREAD_read_lock(ssl->lock);
+ sess = ssl->session;
+ if (sess)
+ SSL_SESSION_up_ref(sess);
+ CRYPTO_THREAD_unlock(ssl->lock);
+ return sess;
+}
+
+int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg)
+{
+ return (CRYPTO_set_ex_data(&s->ex_data, idx, arg));
+}
+
+void *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx)
+{
+ return (CRYPTO_get_ex_data(&s->ex_data, idx));
+}
+
+SSL_SESSION *SSL_SESSION_new(void)
+{
+ SSL_SESSION *ss;
+
+ ss = OPENSSL_zalloc(sizeof(*ss));
+ if (ss == NULL) {
+ SSLerr(SSL_F_SSL_SESSION_NEW, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */
+ ss->references = 1;
+ ss->timeout = 60 * 5 + 4; /* 5 minute timeout by default */
+ ss->time = (unsigned long)time(NULL);
+ ss->lock = CRYPTO_THREAD_lock_new();
+ if (ss->lock == NULL) {
+ SSLerr(SSL_F_SSL_SESSION_NEW, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(ss);
+ return NULL;
+ }
+
+ if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data)) {
+ CRYPTO_THREAD_lock_free(ss->lock);
+ OPENSSL_free(ss);
+ return NULL;
+ }
+ return ss;
+}
+
+/*
+ * Create a new SSL_SESSION and duplicate the contents of |src| into it. If
+ * ticket == 0 then no ticket information is duplicated, otherwise it is.
+ */
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket)
+{
+ SSL_SESSION *dest;
+
+ dest = OPENSSL_malloc(sizeof(*src));
+ if (dest == NULL) {
+ goto err;
+ }
+ memcpy(dest, src, sizeof(*dest));
+
+ /*
+ * Set the various pointers to NULL so that we can call SSL_SESSION_free in
+ * the case of an error whilst halfway through constructing dest
+ */
+#ifndef OPENSSL_NO_PSK
+ dest->psk_identity_hint = NULL;
+ dest->psk_identity = NULL;
+#endif
+ dest->ciphers = NULL;
+ dest->tlsext_hostname = NULL;
+#ifndef OPENSSL_NO_EC
+ dest->tlsext_ecpointformatlist = NULL;
+ dest->tlsext_ellipticcurvelist = NULL;
+#endif
+ dest->tlsext_tick = NULL;
+#ifndef OPENSSL_NO_SRP
+ dest->srp_username = NULL;
+#endif
+ dest->peer_chain = NULL;
+ dest->peer = NULL;
+ memset(&dest->ex_data, 0, sizeof(dest->ex_data));
+
+ /* We deliberately don't copy the prev and next pointers */
+ dest->prev = NULL;
+ dest->next = NULL;
+
+ dest->references = 1;
+
+ dest->lock = CRYPTO_THREAD_lock_new();
+ if (dest->lock == NULL)
+ goto err;
+
+ if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, dest, &dest->ex_data))
+ goto err;
+
+ if (src->peer != NULL) {
+ if (!X509_up_ref(src->peer))
+ goto err;
+ dest->peer = src->peer;
+ }
+
+ if (src->peer_chain != NULL) {
+ dest->peer_chain = X509_chain_up_ref(src->peer_chain);
+ if (dest->peer_chain == NULL)
+ goto err;
+ }
+#ifndef OPENSSL_NO_PSK
+ if (src->psk_identity_hint) {
+ dest->psk_identity_hint = OPENSSL_strdup(src->psk_identity_hint);
+ if (dest->psk_identity_hint == NULL) {
+ goto err;
+ }
+ }
+ if (src->psk_identity) {
+ dest->psk_identity = OPENSSL_strdup(src->psk_identity);
+ if (dest->psk_identity == NULL) {
+ goto err;
+ }
+ }
+#endif
+
+ if (src->ciphers != NULL) {
+ dest->ciphers = sk_SSL_CIPHER_dup(src->ciphers);
+ if (dest->ciphers == NULL)
+ goto err;
+ }
+
+ if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION,
+ &dest->ex_data, &src->ex_data)) {
+ goto err;
+ }
+
+ if (src->tlsext_hostname) {
+ dest->tlsext_hostname = OPENSSL_strdup(src->tlsext_hostname);
+ if (dest->tlsext_hostname == NULL) {
+ goto err;
+ }
+ }
+#ifndef OPENSSL_NO_EC
+ if (src->tlsext_ecpointformatlist) {
+ dest->tlsext_ecpointformatlist =
+ OPENSSL_memdup(src->tlsext_ecpointformatlist,
+ src->tlsext_ecpointformatlist_length);
+ if (dest->tlsext_ecpointformatlist == NULL)
+ goto err;
+ }
+ if (src->tlsext_ellipticcurvelist) {
+ dest->tlsext_ellipticcurvelist =
+ OPENSSL_memdup(src->tlsext_ellipticcurvelist,
+ src->tlsext_ellipticcurvelist_length);
+ if (dest->tlsext_ellipticcurvelist == NULL)
+ goto err;
+ }
+#endif
+
+ if (ticket != 0 && src->tlsext_tick != NULL) {
+ dest->tlsext_tick =
+ OPENSSL_memdup(src->tlsext_tick, src->tlsext_ticklen);
+ if (dest->tlsext_tick == NULL)
+ goto err;
+ } else {
+ dest->tlsext_tick_lifetime_hint = 0;
+ dest->tlsext_ticklen = 0;
+ }
+
+#ifndef OPENSSL_NO_SRP
+ if (src->srp_username) {
+ dest->srp_username = OPENSSL_strdup(src->srp_username);
+ if (dest->srp_username == NULL) {
+ goto err;
+ }
+ }
+#endif
+
+ return dest;
+ err:
+ SSLerr(SSL_F_SSL_SESSION_DUP, ERR_R_MALLOC_FAILURE);
+ SSL_SESSION_free(dest);
+ return NULL;
+}
+
+const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len)
+{
+ if (len)
+ *len = s->session_id_length;
+ return s->session_id;
+}
+const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *s,
+ unsigned int *len)
+{
+ if (len != NULL)
+ *len = s->sid_ctx_length;
+ return s->sid_ctx;
+}
+
+unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s)
+{
+ return s->compress_meth;
+}
+
+/*
+ * SSLv3/TLSv1 has 32 bytes (256 bits) of session ID space. As such, filling
+ * the ID with random junk repeatedly until we have no conflict is going to
+ * complete in one iteration pretty much "most" of the time (btw:
+ * understatement). So, if it takes us 10 iterations and we still can't avoid
+ * a conflict - well that's a reasonable point to call it quits. Either the
+ * RAND code is broken or someone is trying to open roughly very close to
+ * 2^256 SSL sessions to our server. How you might store that many sessions
+ * is perhaps a more interesting question ...
+ */
+
+#define MAX_SESS_ID_ATTEMPTS 10
+static int def_generate_session_id(const SSL *ssl, unsigned char *id,
+ unsigned int *id_len)
+{
+ unsigned int retry = 0;
+ do
+ if (RAND_bytes(id, *id_len) <= 0)
+ return 0;
+ while (SSL_has_matching_session_id(ssl, id, *id_len) &&
+ (++retry < MAX_SESS_ID_ATTEMPTS)) ;
+ if (retry < MAX_SESS_ID_ATTEMPTS)
+ return 1;
+ /* else - woops a session_id match */
+ /*
+ * XXX We should also check the external cache -- but the probability of
+ * a collision is negligible, and we could not prevent the concurrent
+ * creation of sessions with identical IDs since we currently don't have
+ * means to atomically check whether a session ID already exists and make
+ * a reservation for it if it does not (this problem applies to the
+ * internal cache as well).
+ */
+ return 0;
+}
+
+int ssl_get_new_session(SSL *s, int session)
+{
+ /* This gets used by clients and servers. */
+
+ unsigned int tmp;
+ SSL_SESSION *ss = NULL;
+ GEN_SESSION_CB cb = def_generate_session_id;
+
+ if ((ss = SSL_SESSION_new()) == NULL)
+ return (0);
+
+ /* If the context has a default timeout, use it */
+ if (s->session_ctx->session_timeout == 0)
+ ss->timeout = SSL_get_default_timeout(s);
+ else
+ ss->timeout = s->session_ctx->session_timeout;
+
+ SSL_SESSION_free(s->session);
+ s->session = NULL;
+
+ if (session) {
+ if (s->version == SSL3_VERSION) {
+ ss->ssl_version = SSL3_VERSION;
+ ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
+ } else if (s->version == TLS1_VERSION) {
+ ss->ssl_version = TLS1_VERSION;
+ ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
+ } else if (s->version == TLS1_1_VERSION) {
+ ss->ssl_version = TLS1_1_VERSION;
+ ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
+ } else if (s->version == TLS1_2_VERSION) {
+ ss->ssl_version = TLS1_2_VERSION;
+ ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
+ } else if (s->version == DTLS1_BAD_VER) {
+ ss->ssl_version = DTLS1_BAD_VER;
+ ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
+ } else if (s->version == DTLS1_VERSION) {
+ ss->ssl_version = DTLS1_VERSION;
+ ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
+ } else if (s->version == DTLS1_2_VERSION) {
+ ss->ssl_version = DTLS1_2_VERSION;
+ ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
+ } else {
+ SSLerr(SSL_F_SSL_GET_NEW_SESSION, SSL_R_UNSUPPORTED_SSL_VERSION);
+ SSL_SESSION_free(ss);
+ return (0);
+ }
+
+ /*-
+ * If RFC5077 ticket, use empty session ID (as server).
+ * Note that:
+ * (a) ssl_get_prev_session() does lookahead into the
+ * ClientHello extensions to find the session ticket.
+ * When ssl_get_prev_session() fails, statem_srvr.c calls
+ * ssl_get_new_session() in tls_process_client_hello().
+ * At that point, it has not yet parsed the extensions,
+ * however, because of the lookahead, it already knows
+ * whether a ticket is expected or not.
+ *
+ * (b) statem_clnt.c calls ssl_get_new_session() before parsing
+ * ServerHello extensions, and before recording the session
+ * ID received from the server, so this block is a noop.
+ */
+ if (s->tlsext_ticket_expected) {
+ ss->session_id_length = 0;
+ goto sess_id_done;
+ }
+
+ /* Choose which callback will set the session ID */
+ CRYPTO_THREAD_read_lock(s->lock);
+ CRYPTO_THREAD_read_lock(s->session_ctx->lock);
+ if (s->generate_session_id)
+ cb = s->generate_session_id;
+ else if (s->session_ctx->generate_session_id)
+ cb = s->session_ctx->generate_session_id;
+ CRYPTO_THREAD_unlock(s->session_ctx->lock);
+ CRYPTO_THREAD_unlock(s->lock);
+ /* Choose a session ID */
+ memset(ss->session_id, 0, ss->session_id_length);
+ tmp = ss->session_id_length;
+ if (!cb(s, ss->session_id, &tmp)) {
+ /* The callback failed */
+ SSLerr(SSL_F_SSL_GET_NEW_SESSION,
+ SSL_R_SSL_SESSION_ID_CALLBACK_FAILED);
+ SSL_SESSION_free(ss);
+ return (0);
+ }
+ /*
+ * Don't allow the callback to set the session length to zero. nor
+ * set it higher than it was.
+ */
+ if (tmp == 0 || tmp > ss->session_id_length) {
+ /* The callback set an illegal length */
+ SSLerr(SSL_F_SSL_GET_NEW_SESSION,
+ SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH);
+ SSL_SESSION_free(ss);
+ return (0);
+ }
+ ss->session_id_length = tmp;
+ /* Finally, check for a conflict */
+ if (SSL_has_matching_session_id(s, ss->session_id,
+ ss->session_id_length)) {
+ SSLerr(SSL_F_SSL_GET_NEW_SESSION, SSL_R_SSL_SESSION_ID_CONFLICT);
+ SSL_SESSION_free(ss);
+ return (0);
+ }
+
+ sess_id_done:
+ if (s->tlsext_hostname) {
+ ss->tlsext_hostname = OPENSSL_strdup(s->tlsext_hostname);
+ if (ss->tlsext_hostname == NULL) {
+ SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR);
+ SSL_SESSION_free(ss);
+ return 0;
+ }
+ }
+ } else {
+ ss->session_id_length = 0;
+ }
+
+ if (s->sid_ctx_length > sizeof(ss->sid_ctx)) {
+ SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR);
+ SSL_SESSION_free(ss);
+ return 0;
+ }
+ memcpy(ss->sid_ctx, s->sid_ctx, s->sid_ctx_length);
+ ss->sid_ctx_length = s->sid_ctx_length;
+ s->session = ss;
+ ss->ssl_version = s->version;
+ ss->verify_result = X509_V_OK;
+
+ /* If client supports extended master secret set it in session */
+ if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS)
+ ss->flags |= SSL_SESS_FLAG_EXTMS;
+
+ return (1);
+}
+
+/*-
+ * ssl_get_prev attempts to find an SSL_SESSION to be used to resume this
+ * connection. It is only called by servers.
+ *
+ * ext: ClientHello extensions (including length prefix)
+ * session_id: ClientHello session ID.
+ *
+ * Returns:
+ * -1: error
+ * 0: a session may have been found.
+ *
+ * Side effects:
+ * - If a session is found then s->session is pointed at it (after freeing an
+ * existing session if need be) and s->verify_result is set from the session.
+ * - Both for new and resumed sessions, s->tlsext_ticket_expected is set to 1
+ * if the server should issue a new session ticket (to 0 otherwise).
+ */
+int ssl_get_prev_session(SSL *s, const PACKET *ext, const PACKET *session_id)
+{
+ /* This is used only by servers. */
+
+ SSL_SESSION *ret = NULL;
+ int fatal = 0;
+ int try_session_cache = 1;
+ int r;
+
+ if (PACKET_remaining(session_id) == 0)
+ try_session_cache = 0;
+
+ /* sets s->tlsext_ticket_expected and extended master secret flag */
+ r = tls_check_serverhello_tlsext_early(s, ext, session_id, &ret);
+ switch (r) {
+ case -1: /* Error during processing */
+ fatal = 1;
+ goto err;
+ case 0: /* No ticket found */
+ case 1: /* Zero length ticket found */
+ break; /* Ok to carry on processing session id. */
+ case 2: /* Ticket found but not decrypted. */
+ case 3: /* Ticket decrypted, *ret has been set. */
+ try_session_cache = 0;
+ break;
+ default:
+ abort();
+ }
+
+ if (try_session_cache &&
+ ret == NULL &&
+ !(s->session_ctx->session_cache_mode &
+ SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) {
+ SSL_SESSION data;
+ size_t local_len;
+ data.ssl_version = s->version;
+ memset(data.session_id, 0, sizeof(data.session_id));
+ if (!PACKET_copy_all(session_id, data.session_id,
+ sizeof(data.session_id), &local_len)) {
+ goto err;
+ }
+ data.session_id_length = local_len;
+ CRYPTO_THREAD_read_lock(s->session_ctx->lock);
+ ret = lh_SSL_SESSION_retrieve(s->session_ctx->sessions, &data);
+ if (ret != NULL) {
+ /* don't allow other threads to steal it: */
+ SSL_SESSION_up_ref(ret);
+ }
+ CRYPTO_THREAD_unlock(s->session_ctx->lock);
+ if (ret == NULL)
+ s->session_ctx->stats.sess_miss++;
+ }
+
+ if (try_session_cache &&
+ ret == NULL && s->session_ctx->get_session_cb != NULL) {
+ int copy = 1;
+ ret = s->session_ctx->get_session_cb(s, PACKET_data(session_id),
+ PACKET_remaining(session_id),
+ &copy);
+
+ if (ret != NULL) {
+ s->session_ctx->stats.sess_cb_hit++;
+
+ /*
+ * Increment reference count now if the session callback asks us
+ * to do so (note that if the session structures returned by the
+ * callback are shared between threads, it must handle the
+ * reference count itself [i.e. copy == 0], or things won't be
+ * thread-safe).
+ */
+ if (copy)
+ SSL_SESSION_up_ref(ret);
+
+ /*
+ * Add the externally cached session to the internal cache as
+ * well if and only if we are supposed to.
+ */
+ if (!
+ (s->session_ctx->session_cache_mode &
+ SSL_SESS_CACHE_NO_INTERNAL_STORE)) {
+ /*
+ * Either return value of SSL_CTX_add_session should not
+ * interrupt the session resumption process. The return
+ * value is intentionally ignored.
+ */
+ SSL_CTX_add_session(s->session_ctx, ret);
+ }
+ }
+ }
+
+ if (ret == NULL)
+ goto err;
+
+ /* Now ret is non-NULL and we own one of its reference counts. */
+
+ if (ret->sid_ctx_length != s->sid_ctx_length
+ || memcmp(ret->sid_ctx, s->sid_ctx, ret->sid_ctx_length)) {
+ /*
+ * We have the session requested by the client, but we don't want to
+ * use it in this context.
+ */
+ goto err; /* treat like cache miss */
+ }
+
+ if ((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) {
+ /*
+ * We can't be sure if this session is being used out of context,
+ * which is especially important for SSL_VERIFY_PEER. The application
+ * should have used SSL[_CTX]_set_session_id_context. For this error
+ * case, we generate an error instead of treating the event like a
+ * cache miss (otherwise it would be easy for applications to
+ * effectively disable the session cache by accident without anyone
+ * noticing).
+ */
+
+ SSLerr(SSL_F_SSL_GET_PREV_SESSION,
+ SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
+ fatal = 1;
+ goto err;
+ }
+
+ if (ret->cipher == NULL) {
+ unsigned char buf[5], *p;
+ unsigned long l;
+
+ p = buf;
+ l = ret->cipher_id;
+ l2n(l, p);
+ if ((ret->ssl_version >> 8) >= SSL3_VERSION_MAJOR)
+ ret->cipher = ssl_get_cipher_by_char(s, &(buf[2]));
+ else
+ ret->cipher = ssl_get_cipher_by_char(s, &(buf[1]));
+ if (ret->cipher == NULL)
+ goto err;
+ }
+
+ if (ret->timeout < (long)(time(NULL) - ret->time)) { /* timeout */
+ s->session_ctx->stats.sess_timeout++;
+ if (try_session_cache) {
+ /* session was from the cache, so remove it */
+ SSL_CTX_remove_session(s->session_ctx, ret);
+ }
+ goto err;
+ }
+
+ /* Check extended master secret extension consistency */
+ if (ret->flags & SSL_SESS_FLAG_EXTMS) {
+ /* If old session includes extms, but new does not: abort handshake */
+ if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS)) {
+ SSLerr(SSL_F_SSL_GET_PREV_SESSION, SSL_R_INCONSISTENT_EXTMS);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ fatal = 1;
+ goto err;
+ }
+ } else if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) {
+ /* If new session includes extms, but old does not: do not resume */
+ goto err;
+ }
+
+ s->session_ctx->stats.sess_hit++;
+
+ SSL_SESSION_free(s->session);
+ s->session = ret;
+ s->verify_result = s->session->verify_result;
+ return 1;
+
+ err:
+ if (ret != NULL) {
+ SSL_SESSION_free(ret);
+
+ if (!try_session_cache) {
+ /*
+ * The session was from a ticket, so we should issue a ticket for
+ * the new session
+ */
+ s->tlsext_ticket_expected = 1;
+ }
+ }
+ if (fatal)
+ return -1;
+ else
+ return 0;
+}
+
+int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
+{
+ int ret = 0;
+ SSL_SESSION *s;
+
+ /*
+ * add just 1 reference count for the SSL_CTX's session cache even though
+ * it has two ways of access: each session is in a doubly linked list and
+ * an lhash
+ */
+ SSL_SESSION_up_ref(c);
+ /*
+ * if session c is in already in cache, we take back the increment later
+ */
+
+ CRYPTO_THREAD_write_lock(ctx->lock);
+ s = lh_SSL_SESSION_insert(ctx->sessions, c);
+
+ /*
+ * s != NULL iff we already had a session with the given PID. In this
+ * case, s == c should hold (then we did not really modify
+ * ctx->sessions), or we're in trouble.
+ */
+ if (s != NULL && s != c) {
+ /* We *are* in trouble ... */
+ SSL_SESSION_list_remove(ctx, s);
+ SSL_SESSION_free(s);
+ /*
+ * ... so pretend the other session did not exist in cache (we cannot
+ * handle two SSL_SESSION structures with identical session ID in the
+ * same cache, which could happen e.g. when two threads concurrently
+ * obtain the same session from an external cache)
+ */
+ s = NULL;
+ } else if (s == NULL &&
+ lh_SSL_SESSION_retrieve(ctx->sessions, c) == NULL) {
+ /* s == NULL can also mean OOM error in lh_SSL_SESSION_insert ... */
+
+ /*
+ * ... so take back the extra reference and also don't add
+ * the session to the SSL_SESSION_list at this time
+ */
+ s = c;
+ }
+
+ /* Put at the head of the queue unless it is already in the cache */
+ if (s == NULL)
+ SSL_SESSION_list_add(ctx, c);
+
+ if (s != NULL) {
+ /*
+ * existing cache entry -- decrement previously incremented reference
+ * count because it already takes into account the cache
+ */
+
+ SSL_SESSION_free(s); /* s == c */
+ ret = 0;
+ } else {
+ /*
+ * new cache entry -- remove old ones if cache has become too large
+ */
+
+ ret = 1;
+
+ if (SSL_CTX_sess_get_cache_size(ctx) > 0) {
+ while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) {
+ if (!remove_session_lock(ctx, ctx->session_cache_tail, 0))
+ break;
+ else
+ ctx->stats.sess_cache_full++;
+ }
+ }
+ }
+ CRYPTO_THREAD_unlock(ctx->lock);
+ return ret;
+}
+
+int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c)
+{
+ return remove_session_lock(ctx, c, 1);
+}
+
+static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck)
+{
+ SSL_SESSION *r;
+ int ret = 0;
+
+ if ((c != NULL) && (c->session_id_length != 0)) {
+ if (lck)
+ CRYPTO_THREAD_write_lock(ctx->lock);
+ if ((r = lh_SSL_SESSION_retrieve(ctx->sessions, c)) == c) {
+ ret = 1;
+ r = lh_SSL_SESSION_delete(ctx->sessions, c);
+ SSL_SESSION_list_remove(ctx, c);
+ }
+ c->not_resumable = 1;
+
+ if (lck)
+ CRYPTO_THREAD_unlock(ctx->lock);
+
+ if (ret)
+ SSL_SESSION_free(r);
+
+ if (ctx->remove_session_cb != NULL)
+ ctx->remove_session_cb(ctx, c);
+ } else
+ ret = 0;
+ return (ret);
+}
+
+void SSL_SESSION_free(SSL_SESSION *ss)
+{
+ int i;
+
+ if (ss == NULL)
+ return;
+
+ CRYPTO_atomic_add(&ss->references, -1, &i, ss->lock);
+ REF_PRINT_COUNT("SSL_SESSION", ss);
+ if (i > 0)
+ return;
+ REF_ASSERT_ISNT(i < 0);
+
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
+
+ OPENSSL_cleanse(ss->master_key, sizeof(ss->master_key));
+ OPENSSL_cleanse(ss->session_id, sizeof(ss->session_id));
+ X509_free(ss->peer);
+ sk_X509_pop_free(ss->peer_chain, X509_free);
+ sk_SSL_CIPHER_free(ss->ciphers);
+ OPENSSL_free(ss->tlsext_hostname);
+ OPENSSL_free(ss->tlsext_tick);
+#ifndef OPENSSL_NO_EC
+ ss->tlsext_ecpointformatlist_length = 0;
+ OPENSSL_free(ss->tlsext_ecpointformatlist);
+ ss->tlsext_ellipticcurvelist_length = 0;
+ OPENSSL_free(ss->tlsext_ellipticcurvelist);
+#endif /* OPENSSL_NO_EC */
+#ifndef OPENSSL_NO_PSK
+ OPENSSL_free(ss->psk_identity_hint);
+ OPENSSL_free(ss->psk_identity);
+#endif
+#ifndef OPENSSL_NO_SRP
+ OPENSSL_free(ss->srp_username);
+#endif
+ CRYPTO_THREAD_lock_free(ss->lock);
+ OPENSSL_clear_free(ss, sizeof(*ss));
+}
+
+int SSL_SESSION_up_ref(SSL_SESSION *ss)
+{
+ int i;
+
+ if (CRYPTO_atomic_add(&ss->references, 1, &i, ss->lock) <= 0)
+ return 0;
+
+ REF_PRINT_COUNT("SSL_SESSION", ss);
+ REF_ASSERT_ISNT(i < 2);
+ return ((i > 1) ? 1 : 0);
+}
+
+int SSL_set_session(SSL *s, SSL_SESSION *session)
+{
+ ssl_clear_bad_session(s);
+ if (s->ctx->method != s->method) {
+ if (!SSL_set_ssl_method(s, s->ctx->method))
+ return 0;
+ }
+
+ if (session != NULL) {
+ SSL_SESSION_up_ref(session);
+ s->verify_result = session->verify_result;
+ }
+ SSL_SESSION_free(s->session);
+ s->session = session;
+
+ return 1;
+}
+
+int SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid,
+ unsigned int sid_len)
+{
+ if (sid_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
+ SSLerr(SSL_F_SSL_SESSION_SET1_ID,
+ SSL_R_SSL_SESSION_ID_TOO_LONG);
+ return 0;
+ }
+ s->session_id_length = sid_len;
+ if (sid != s->session_id)
+ memcpy(s->session_id, sid, sid_len);
+ return 1;
+}
+
+long SSL_SESSION_set_timeout(SSL_SESSION *s, long t)
+{
+ if (s == NULL)
+ return (0);
+ s->timeout = t;
+ return (1);
+}
+
+long SSL_SESSION_get_timeout(const SSL_SESSION *s)
+{
+ if (s == NULL)
+ return (0);
+ return (s->timeout);
+}
+
+long SSL_SESSION_get_time(const SSL_SESSION *s)
+{
+ if (s == NULL)
+ return (0);
+ return (s->time);
+}
+
+long SSL_SESSION_set_time(SSL_SESSION *s, long t)
+{
+ if (s == NULL)
+ return (0);
+ s->time = t;
+ return (t);
+}
+
+int SSL_SESSION_get_protocol_version(const SSL_SESSION *s)
+{
+ return s->ssl_version;
+}
+
+const SSL_CIPHER *SSL_SESSION_get0_cipher(const SSL_SESSION *s)
+{
+ return s->cipher;
+}
+
+const char *SSL_SESSION_get0_hostname(const SSL_SESSION *s)
+{
+ return s->tlsext_hostname;
+}
+
+int SSL_SESSION_has_ticket(const SSL_SESSION *s)
+{
+ return (s->tlsext_ticklen > 0) ? 1 : 0;
+}
+
+unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s)
+{
+ return s->tlsext_tick_lifetime_hint;
+}
+
+void SSL_SESSION_get0_ticket(const SSL_SESSION *s, const unsigned char **tick,
+ size_t *len)
+{
+ *len = s->tlsext_ticklen;
+ if (tick != NULL)
+ *tick = s->tlsext_tick;
+}
+
+X509 *SSL_SESSION_get0_peer(SSL_SESSION *s)
+{
+ return s->peer;
+}
+
+int SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx,
+ unsigned int sid_ctx_len)
+{
+ if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) {
+ SSLerr(SSL_F_SSL_SESSION_SET1_ID_CONTEXT,
+ SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
+ return 0;
+ }
+ s->sid_ctx_length = sid_ctx_len;
+ if (sid_ctx != s->sid_ctx)
+ memcpy(s->sid_ctx, sid_ctx, sid_ctx_len);
+
+ return 1;
+}
+
+long SSL_CTX_set_timeout(SSL_CTX *s, long t)
+{
+ long l;
+ if (s == NULL)
+ return (0);
+ l = s->session_timeout;
+ s->session_timeout = t;
+ return (l);
+}
+
+long SSL_CTX_get_timeout(const SSL_CTX *s)
+{
+ if (s == NULL)
+ return (0);
+ return (s->session_timeout);
+}
+
+int SSL_set_session_secret_cb(SSL *s,
+ int (*tls_session_secret_cb) (SSL *s,
+ void *secret,
+ int *secret_len,
+ STACK_OF(SSL_CIPHER)
+ *peer_ciphers,
+ const SSL_CIPHER
+ **cipher,
+ void *arg),
+ void *arg)
+{
+ if (s == NULL)
+ return (0);
+ s->tls_session_secret_cb = tls_session_secret_cb;
+ s->tls_session_secret_cb_arg = arg;
+ return (1);
+}
+
+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
+ void *arg)
+{
+ if (s == NULL)
+ return (0);
+ s->tls_session_ticket_ext_cb = cb;
+ s->tls_session_ticket_ext_cb_arg = arg;
+ return (1);
+}
+
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
+{
+ if (s->version >= TLS1_VERSION) {
+ OPENSSL_free(s->tlsext_session_ticket);
+ s->tlsext_session_ticket = NULL;
+ s->tlsext_session_ticket =
+ OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len);
+ if (s->tlsext_session_ticket == NULL) {
+ SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (ext_data) {
+ s->tlsext_session_ticket->length = ext_len;
+ s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1;
+ memcpy(s->tlsext_session_ticket->data, ext_data, ext_len);
+ } else {
+ s->tlsext_session_ticket->length = 0;
+ s->tlsext_session_ticket->data = NULL;
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+typedef struct timeout_param_st {
+ SSL_CTX *ctx;
+ long time;
+ LHASH_OF(SSL_SESSION) *cache;
+} TIMEOUT_PARAM;
+
+static void timeout_cb(SSL_SESSION *s, TIMEOUT_PARAM *p)
+{
+ if ((p->time == 0) || (p->time > (s->time + s->timeout))) { /* timeout */
+ /*
+ * The reason we don't call SSL_CTX_remove_session() is to save on
+ * locking overhead
+ */
+ (void)lh_SSL_SESSION_delete(p->cache, s);
+ SSL_SESSION_list_remove(p->ctx, s);
+ s->not_resumable = 1;
+ if (p->ctx->remove_session_cb != NULL)
+ p->ctx->remove_session_cb(p->ctx, s);
+ SSL_SESSION_free(s);
+ }
+}
+
+IMPLEMENT_LHASH_DOALL_ARG(SSL_SESSION, TIMEOUT_PARAM);
+
+void SSL_CTX_flush_sessions(SSL_CTX *s, long t)
+{
+ unsigned long i;
+ TIMEOUT_PARAM tp;
+
+ tp.ctx = s;
+ tp.cache = s->sessions;
+ if (tp.cache == NULL)
+ return;
+ tp.time = t;
+ CRYPTO_THREAD_write_lock(s->lock);
+ i = lh_SSL_SESSION_get_down_load(s->sessions);
+ lh_SSL_SESSION_set_down_load(s->sessions, 0);
+ lh_SSL_SESSION_doall_TIMEOUT_PARAM(tp.cache, timeout_cb, &tp);
+ lh_SSL_SESSION_set_down_load(s->sessions, i);
+ CRYPTO_THREAD_unlock(s->lock);
+}
+
+int ssl_clear_bad_session(SSL *s)
+{
+ if ((s->session != NULL) &&
+ !(s->shutdown & SSL_SENT_SHUTDOWN) &&
+ !(SSL_in_init(s) || SSL_in_before(s))) {
+ SSL_CTX_remove_session(s->session_ctx, s->session);
+ return (1);
+ } else
+ return (0);
+}
+
+/* locked by SSL_CTX in the calling function */
+static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s)
+{
+ if ((s->next == NULL) || (s->prev == NULL))
+ return;
+
+ if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail)) {
+ /* last element in list */
+ if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) {
+ /* only one element in list */
+ ctx->session_cache_head = NULL;
+ ctx->session_cache_tail = NULL;
+ } else {
+ ctx->session_cache_tail = s->prev;
+ s->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail);
+ }
+ } else {
+ if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) {
+ /* first element in list */
+ ctx->session_cache_head = s->next;
+ s->next->prev = (SSL_SESSION *)&(ctx->session_cache_head);
+ } else {
+ /* middle of list */
+ s->next->prev = s->prev;
+ s->prev->next = s->next;
+ }
+ }
+ s->prev = s->next = NULL;
+}
+
+static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s)
+{
+ if ((s->next != NULL) && (s->prev != NULL))
+ SSL_SESSION_list_remove(ctx, s);
+
+ if (ctx->session_cache_head == NULL) {
+ ctx->session_cache_head = s;
+ ctx->session_cache_tail = s;
+ s->prev = (SSL_SESSION *)&(ctx->session_cache_head);
+ s->next = (SSL_SESSION *)&(ctx->session_cache_tail);
+ } else {
+ s->next = ctx->session_cache_head;
+ s->next->prev = s;
+ s->prev = (SSL_SESSION *)&(ctx->session_cache_head);
+ ctx->session_cache_head = s;
+ }
+}
+
+void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
+ int (*cb) (struct ssl_st *ssl, SSL_SESSION *sess))
+{
+ ctx->new_session_cb = cb;
+}
+
+int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx)) (SSL *ssl, SSL_SESSION *sess) {
+ return ctx->new_session_cb;
+}
+
+void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx,
+ void (*cb) (SSL_CTX *ctx, SSL_SESSION *sess))
+{
+ ctx->remove_session_cb = cb;
+}
+
+void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx)) (SSL_CTX *ctx,
+ SSL_SESSION *sess) {
+ return ctx->remove_session_cb;
+}
+
+void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
+ SSL_SESSION *(*cb) (struct ssl_st *ssl,
+ const unsigned char *data,
+ int len, int *copy))
+{
+ ctx->get_session_cb = cb;
+}
+
+SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx)) (SSL *ssl,
+ const unsigned char
+ *data, int len,
+ int *copy) {
+ return ctx->get_session_cb;
+}
+
+void SSL_CTX_set_info_callback(SSL_CTX *ctx,
+ void (*cb) (const SSL *ssl, int type, int val))
+{
+ ctx->info_callback = cb;
+}
+
+void (*SSL_CTX_get_info_callback(SSL_CTX *ctx)) (const SSL *ssl, int type,
+ int val) {
+ return ctx->info_callback;
+}
+
+void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx,
+ int (*cb) (SSL *ssl, X509 **x509,
+ EVP_PKEY **pkey))
+{
+ ctx->client_cert_cb = cb;
+}
+
+int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx)) (SSL *ssl, X509 **x509,
+ EVP_PKEY **pkey) {
+ return ctx->client_cert_cb;
+}
+
+#ifndef OPENSSL_NO_ENGINE
+int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e)
+{
+ if (!ENGINE_init(e)) {
+ SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, ERR_R_ENGINE_LIB);
+ return 0;
+ }
+ if (!ENGINE_get_ssl_client_cert_function(e)) {
+ SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE,
+ SSL_R_NO_CLIENT_CERT_METHOD);
+ ENGINE_finish(e);
+ return 0;
+ }
+ ctx->client_cert_engine = e;
+ return 1;
+}
+#endif
+
+void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx,
+ int (*cb) (SSL *ssl,
+ unsigned char *cookie,
+ unsigned int *cookie_len))
+{
+ ctx->app_gen_cookie_cb = cb;
+}
+
+void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx,
+ int (*cb) (SSL *ssl,
+ const unsigned char *cookie,
+ unsigned int cookie_len))
+{
+ ctx->app_verify_cookie_cb = cb;
+}
+
+IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION)
diff --git a/openssl-1.1.0h/ssl/ssl_stat.c b/openssl-1.1.0h/ssl/ssl_stat.c
new file mode 100644
index 0000000..ad7a019
--- /dev/null
+++ b/openssl-1.1.0h/ssl/ssl_stat.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright 1995-2017 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
+ */
+
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <stdio.h>
+#include "ssl_locl.h"
+
+const char *SSL_state_string_long(const SSL *s)
+{
+ if (ossl_statem_in_error(s))
+ return "error";
+
+ switch (SSL_get_state(s)) {
+ case TLS_ST_CR_CERT_STATUS:
+ return "SSLv3/TLS read certificate status";
+ case TLS_ST_CW_NEXT_PROTO:
+ return "SSLv3/TLS write next proto";
+ case TLS_ST_SR_NEXT_PROTO:
+ return "SSLv3/TLS read next proto";
+ case TLS_ST_SW_CERT_STATUS:
+ return "SSLv3/TLS write certificate status";
+ case TLS_ST_BEFORE:
+ return "before SSL initialization";
+ case TLS_ST_OK:
+ return "SSL negotiation finished successfully";
+ case TLS_ST_CW_CLNT_HELLO:
+ return "SSLv3/TLS write client hello";
+ case TLS_ST_CR_SRVR_HELLO:
+ return "SSLv3/TLS read server hello";
+ case TLS_ST_CR_CERT:
+ return "SSLv3/TLS read server certificate";
+ case TLS_ST_CR_KEY_EXCH:
+ return "SSLv3/TLS read server key exchange";
+ case TLS_ST_CR_CERT_REQ:
+ return "SSLv3/TLS read server certificate request";
+ case TLS_ST_CR_SESSION_TICKET:
+ return "SSLv3/TLS read server session ticket";
+ case TLS_ST_CR_SRVR_DONE:
+ return "SSLv3/TLS read server done";
+ case TLS_ST_CW_CERT:
+ return "SSLv3/TLS write client certificate";
+ case TLS_ST_CW_KEY_EXCH:
+ return "SSLv3/TLS write client key exchange";
+ case TLS_ST_CW_CERT_VRFY:
+ return "SSLv3/TLS write certificate verify";
+ case TLS_ST_CW_CHANGE:
+ case TLS_ST_SW_CHANGE:
+ return "SSLv3/TLS write change cipher spec";
+ case TLS_ST_CW_FINISHED:
+ case TLS_ST_SW_FINISHED:
+ return "SSLv3/TLS write finished";
+ case TLS_ST_CR_CHANGE:
+ case TLS_ST_SR_CHANGE:
+ return "SSLv3/TLS read change cipher spec";
+ case TLS_ST_CR_FINISHED:
+ case TLS_ST_SR_FINISHED:
+ return "SSLv3/TLS read finished";
+ case TLS_ST_SR_CLNT_HELLO:
+ return "SSLv3/TLS read client hello";
+ case TLS_ST_SW_HELLO_REQ:
+ return "SSLv3/TLS write hello request";
+ case TLS_ST_SW_SRVR_HELLO:
+ return "SSLv3/TLS write server hello";
+ case TLS_ST_SW_CERT:
+ return "SSLv3/TLS write certificate";
+ case TLS_ST_SW_KEY_EXCH:
+ return "SSLv3/TLS write key exchange";
+ case TLS_ST_SW_CERT_REQ:
+ return "SSLv3/TLS write certificate request";
+ case TLS_ST_SW_SESSION_TICKET:
+ return "SSLv3/TLS write session ticket";
+ case TLS_ST_SW_SRVR_DONE:
+ return "SSLv3/TLS write server done";
+ case TLS_ST_SR_CERT:
+ return "SSLv3/TLS read client certificate";
+ case TLS_ST_SR_KEY_EXCH:
+ return "SSLv3/TLS read client key exchange";
+ case TLS_ST_SR_CERT_VRFY:
+ return "SSLv3/TLS read certificate verify";
+ case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
+ return "DTLS1 read hello verify request";
+ case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
+ return "DTLS1 write hello verify request";
+ default:
+ return "unknown state";
+ }
+}
+
+const char *SSL_state_string(const SSL *s)
+{
+ if (ossl_statem_in_error(s))
+ return "SSLERR";
+
+ switch (SSL_get_state(s)) {
+ case TLS_ST_SR_NEXT_PROTO:
+ return "TRNP";
+ case TLS_ST_SW_SESSION_TICKET:
+ return "TWST";
+ case TLS_ST_SW_CERT_STATUS:
+ return "TWCS";
+ case TLS_ST_CR_CERT_STATUS:
+ return "TRCS";
+ case TLS_ST_CR_SESSION_TICKET:
+ return "TRST";
+ case TLS_ST_CW_NEXT_PROTO:
+ return "TWNP";
+ case TLS_ST_BEFORE:
+ return "PINIT ";
+ case TLS_ST_OK:
+ return "SSLOK ";
+ case TLS_ST_CW_CLNT_HELLO:
+ return "TWCH";
+ case TLS_ST_CR_SRVR_HELLO:
+ return "TRSH";
+ case TLS_ST_CR_CERT:
+ return "TRSC";
+ case TLS_ST_CR_KEY_EXCH:
+ return "TRSKE";
+ case TLS_ST_CR_CERT_REQ:
+ return "TRCR";
+ case TLS_ST_CR_SRVR_DONE:
+ return "TRSD";
+ case TLS_ST_CW_CERT:
+ return "TWCC";
+ case TLS_ST_CW_KEY_EXCH:
+ return "TWCKE";
+ case TLS_ST_CW_CERT_VRFY:
+ return "TWCV";
+ case TLS_ST_SW_CHANGE:
+ case TLS_ST_CW_CHANGE:
+ return "TWCCS";
+ case TLS_ST_SW_FINISHED:
+ case TLS_ST_CW_FINISHED:
+ return "TWFIN";
+ case TLS_ST_SR_CHANGE:
+ case TLS_ST_CR_CHANGE:
+ return "TRCCS";
+ case TLS_ST_SR_FINISHED:
+ case TLS_ST_CR_FINISHED:
+ return "TRFIN";
+ case TLS_ST_SW_HELLO_REQ:
+ return "TWHR";
+ case TLS_ST_SR_CLNT_HELLO:
+ return "TRCH";
+ case TLS_ST_SW_SRVR_HELLO:
+ return "TWSH";
+ case TLS_ST_SW_CERT:
+ return "TWSC";
+ case TLS_ST_SW_KEY_EXCH:
+ return "TWSKE";
+ case TLS_ST_SW_CERT_REQ:
+ return "TWCR";
+ case TLS_ST_SW_SRVR_DONE:
+ return "TWSD";
+ case TLS_ST_SR_CERT:
+ return "TRCC";
+ case TLS_ST_SR_KEY_EXCH:
+ return "TRCKE";
+ case TLS_ST_SR_CERT_VRFY:
+ return "TRCV";
+ case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
+ return "DRCHV";
+ case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
+ return "DWCHV";
+ default:
+ return "UNKWN ";
+ }
+}
+
+const char *SSL_alert_type_string_long(int value)
+{
+ switch (value >> 8) {
+ case SSL3_AL_WARNING:
+ return "warning";
+ case SSL3_AL_FATAL:
+ return "fatal";
+ default:
+ return "unknown";
+ }
+}
+
+const char *SSL_alert_type_string(int value)
+{
+ switch (value >> 8) {
+ case SSL3_AL_WARNING:
+ return "W";
+ case SSL3_AL_FATAL:
+ return "F";
+ default:
+ return "U";
+ }
+}
+
+const char *SSL_alert_desc_string(int value)
+{
+ switch (value & 0xff) {
+ case SSL3_AD_CLOSE_NOTIFY:
+ return "CN";
+ case SSL3_AD_UNEXPECTED_MESSAGE:
+ return "UM";
+ case SSL3_AD_BAD_RECORD_MAC:
+ return "BM";
+ case SSL3_AD_DECOMPRESSION_FAILURE:
+ return "DF";
+ case SSL3_AD_HANDSHAKE_FAILURE:
+ return "HF";
+ case SSL3_AD_NO_CERTIFICATE:
+ return "NC";
+ case SSL3_AD_BAD_CERTIFICATE:
+ return "BC";
+ case SSL3_AD_UNSUPPORTED_CERTIFICATE:
+ return "UC";
+ case SSL3_AD_CERTIFICATE_REVOKED:
+ return "CR";
+ case SSL3_AD_CERTIFICATE_EXPIRED:
+ return "CE";
+ case SSL3_AD_CERTIFICATE_UNKNOWN:
+ return "CU";
+ case SSL3_AD_ILLEGAL_PARAMETER:
+ return "IP";
+ case TLS1_AD_DECRYPTION_FAILED:
+ return "DC";
+ case TLS1_AD_RECORD_OVERFLOW:
+ return "RO";
+ case TLS1_AD_UNKNOWN_CA:
+ return "CA";
+ case TLS1_AD_ACCESS_DENIED:
+ return "AD";
+ case TLS1_AD_DECODE_ERROR:
+ return "DE";
+ case TLS1_AD_DECRYPT_ERROR:
+ return "CY";
+ case TLS1_AD_EXPORT_RESTRICTION:
+ return "ER";
+ case TLS1_AD_PROTOCOL_VERSION:
+ return "PV";
+ case TLS1_AD_INSUFFICIENT_SECURITY:
+ return "IS";
+ case TLS1_AD_INTERNAL_ERROR:
+ return "IE";
+ case TLS1_AD_USER_CANCELLED:
+ return "US";
+ case TLS1_AD_NO_RENEGOTIATION:
+ return "NR";
+ case TLS1_AD_UNSUPPORTED_EXTENSION:
+ return "UE";
+ case TLS1_AD_CERTIFICATE_UNOBTAINABLE:
+ return "CO";
+ case TLS1_AD_UNRECOGNIZED_NAME:
+ return "UN";
+ case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE:
+ return "BR";
+ case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE:
+ return "BH";
+ case TLS1_AD_UNKNOWN_PSK_IDENTITY:
+ return "UP";
+ default:
+ return "UK";
+ }
+}
+
+const char *SSL_alert_desc_string_long(int value)
+{
+ switch (value & 0xff) {
+ case SSL3_AD_CLOSE_NOTIFY:
+ return "close notify";
+ case SSL3_AD_UNEXPECTED_MESSAGE:
+ return "unexpected_message";
+ case SSL3_AD_BAD_RECORD_MAC:
+ return "bad record mac";
+ case SSL3_AD_DECOMPRESSION_FAILURE:
+ return "decompression failure";
+ case SSL3_AD_HANDSHAKE_FAILURE:
+ return "handshake failure";
+ case SSL3_AD_NO_CERTIFICATE:
+ return "no certificate";
+ case SSL3_AD_BAD_CERTIFICATE:
+ return "bad certificate";
+ case SSL3_AD_UNSUPPORTED_CERTIFICATE:
+ return "unsupported certificate";
+ case SSL3_AD_CERTIFICATE_REVOKED:
+ return "certificate revoked";
+ case SSL3_AD_CERTIFICATE_EXPIRED:
+ return "certificate expired";
+ case SSL3_AD_CERTIFICATE_UNKNOWN:
+ return "certificate unknown";
+ case SSL3_AD_ILLEGAL_PARAMETER:
+ return "illegal parameter";
+ case TLS1_AD_DECRYPTION_FAILED:
+ return "decryption failed";
+ case TLS1_AD_RECORD_OVERFLOW:
+ return "record overflow";
+ case TLS1_AD_UNKNOWN_CA:
+ return "unknown CA";
+ case TLS1_AD_ACCESS_DENIED:
+ return "access denied";
+ case TLS1_AD_DECODE_ERROR:
+ return "decode error";
+ case TLS1_AD_DECRYPT_ERROR:
+ return "decrypt error";
+ case TLS1_AD_EXPORT_RESTRICTION:
+ return "export restriction";
+ case TLS1_AD_PROTOCOL_VERSION:
+ return "protocol version";
+ case TLS1_AD_INSUFFICIENT_SECURITY:
+ return "insufficient security";
+ case TLS1_AD_INTERNAL_ERROR:
+ return "internal error";
+ case TLS1_AD_USER_CANCELLED:
+ return "user canceled";
+ case TLS1_AD_NO_RENEGOTIATION:
+ return "no renegotiation";
+ case TLS1_AD_UNSUPPORTED_EXTENSION:
+ return "unsupported extension";
+ case TLS1_AD_CERTIFICATE_UNOBTAINABLE:
+ return "certificate unobtainable";
+ case TLS1_AD_UNRECOGNIZED_NAME:
+ return "unrecognized name";
+ case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE:
+ return "bad certificate status response";
+ case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE:
+ return "bad certificate hash value";
+ case TLS1_AD_UNKNOWN_PSK_IDENTITY:
+ return "unknown PSK identity";
+ case TLS1_AD_NO_APPLICATION_PROTOCOL:
+ return "no application protocol";
+ default:
+ return "unknown";
+ }
+}
diff --git a/openssl-1.1.0h/ssl/ssl_txt.c b/openssl-1.1.0h/ssl/ssl_txt.c
new file mode 100644
index 0000000..dbbf9d9
--- /dev/null
+++ b/openssl-1.1.0h/ssl/ssl_txt.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright 1995-2016 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
+ */
+
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <stdio.h>
+#include <openssl/buffer.h>
+#include "ssl_locl.h"
+
+#ifndef OPENSSL_NO_STDIO
+int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *x)
+{
+ BIO *b;
+ int ret;
+
+ if ((b = BIO_new(BIO_s_file())) == NULL) {
+ SSLerr(SSL_F_SSL_SESSION_PRINT_FP, ERR_R_BUF_LIB);
+ return (0);
+ }
+ BIO_set_fp(b, fp, BIO_NOCLOSE);
+ ret = SSL_SESSION_print(b, x);
+ BIO_free(b);
+ return (ret);
+}
+#endif
+
+int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x)
+{
+ unsigned int i;
+ const char *s;
+
+ if (x == NULL)
+ goto err;
+ if (BIO_puts(bp, "SSL-Session:\n") <= 0)
+ goto err;
+ s = ssl_protocol_to_string(x->ssl_version);
+ if (BIO_printf(bp, " Protocol : %s\n", s) <= 0)
+ goto err;
+
+ if (x->cipher == NULL) {
+ if (((x->cipher_id) & 0xff000000) == 0x02000000) {
+ if (BIO_printf
+ (bp, " Cipher : %06lX\n", x->cipher_id & 0xffffff) <= 0)
+ goto err;
+ } else {
+ if (BIO_printf
+ (bp, " Cipher : %04lX\n", x->cipher_id & 0xffff) <= 0)
+ goto err;
+ }
+ } else {
+ if (BIO_printf
+ (bp, " Cipher : %s\n",
+ ((x->cipher == NULL) ? "unknown" : x->cipher->name)) <= 0)
+ goto err;
+ }
+ if (BIO_puts(bp, " Session-ID: ") <= 0)
+ goto err;
+ for (i = 0; i < x->session_id_length; i++) {
+ if (BIO_printf(bp, "%02X", x->session_id[i]) <= 0)
+ goto err;
+ }
+ if (BIO_puts(bp, "\n Session-ID-ctx: ") <= 0)
+ goto err;
+ for (i = 0; i < x->sid_ctx_length; i++) {
+ if (BIO_printf(bp, "%02X", x->sid_ctx[i]) <= 0)
+ goto err;
+ }
+ if (BIO_puts(bp, "\n Master-Key: ") <= 0)
+ goto err;
+ for (i = 0; i < (unsigned int)x->master_key_length; i++) {
+ if (BIO_printf(bp, "%02X", x->master_key[i]) <= 0)
+ goto err;
+ }
+#ifndef OPENSSL_NO_PSK
+ if (BIO_puts(bp, "\n PSK identity: ") <= 0)
+ goto err;
+ if (BIO_printf(bp, "%s", x->psk_identity ? x->psk_identity : "None") <= 0)
+ goto err;
+ if (BIO_puts(bp, "\n PSK identity hint: ") <= 0)
+ goto err;
+ if (BIO_printf
+ (bp, "%s", x->psk_identity_hint ? x->psk_identity_hint : "None") <= 0)
+ goto err;
+#endif
+#ifndef OPENSSL_NO_SRP
+ if (BIO_puts(bp, "\n SRP username: ") <= 0)
+ goto err;
+ if (BIO_printf(bp, "%s", x->srp_username ? x->srp_username : "None") <= 0)
+ goto err;
+#endif
+ if (x->tlsext_tick_lifetime_hint) {
+ if (BIO_printf(bp,
+ "\n TLS session ticket lifetime hint: %ld (seconds)",
+ x->tlsext_tick_lifetime_hint) <= 0)
+ goto err;
+ }
+ if (x->tlsext_tick) {
+ if (BIO_puts(bp, "\n TLS session ticket:\n") <= 0)
+ goto err;
+ if (BIO_dump_indent
+ (bp, (const char *)x->tlsext_tick, x->tlsext_ticklen, 4)
+ <= 0)
+ goto err;
+ }
+#ifndef OPENSSL_NO_COMP
+ if (x->compress_meth != 0) {
+ SSL_COMP *comp = NULL;
+
+ if (!ssl_cipher_get_evp(x, NULL, NULL, NULL, NULL, &comp, 0))
+ goto err;
+ if (comp == NULL) {
+ if (BIO_printf(bp, "\n Compression: %d", x->compress_meth) <= 0)
+ goto err;
+ } else {
+ if (BIO_printf(bp, "\n Compression: %d (%s)", comp->id,
+ comp->name) <= 0)
+ goto err;
+ }
+ }
+#endif
+ if (x->time != 0L) {
+ if (BIO_printf(bp, "\n Start Time: %ld", x->time) <= 0)
+ goto err;
+ }
+ if (x->timeout != 0L) {
+ if (BIO_printf(bp, "\n Timeout : %ld (sec)", x->timeout) <= 0)
+ goto err;
+ }
+ if (BIO_puts(bp, "\n") <= 0)
+ goto err;
+
+ if (BIO_puts(bp, " Verify return code: ") <= 0)
+ goto err;
+ if (BIO_printf(bp, "%ld (%s)\n", x->verify_result,
+ X509_verify_cert_error_string(x->verify_result)) <= 0)
+ goto err;
+
+ if (BIO_printf(bp, " Extended master secret: %s\n",
+ x->flags & SSL_SESS_FLAG_EXTMS ? "yes" : "no") <= 0)
+ goto err;
+
+ return (1);
+ err:
+ return (0);
+}
+
+/*
+ * print session id and master key in NSS keylog format (RSA
+ * Session-ID:<session id> Master-Key:<master key>)
+ */
+int SSL_SESSION_print_keylog(BIO *bp, const SSL_SESSION *x)
+{
+ unsigned int i;
+
+ if (x == NULL)
+ goto err;
+ if (x->session_id_length == 0 || x->master_key_length == 0)
+ goto err;
+
+ /*
+ * the RSA prefix is required by the format's definition although there's
+ * nothing RSA-specific in the output, therefore, we don't have to check if
+ * the cipher suite is based on RSA
+ */
+ if (BIO_puts(bp, "RSA ") <= 0)
+ goto err;
+
+ if (BIO_puts(bp, "Session-ID:") <= 0)
+ goto err;
+ for (i = 0; i < x->session_id_length; i++) {
+ if (BIO_printf(bp, "%02X", x->session_id[i]) <= 0)
+ goto err;
+ }
+ if (BIO_puts(bp, " Master-Key:") <= 0)
+ goto err;
+ for (i = 0; i < (unsigned int)x->master_key_length; i++) {
+ if (BIO_printf(bp, "%02X", x->master_key[i]) <= 0)
+ goto err;
+ }
+ if (BIO_puts(bp, "\n") <= 0)
+ goto err;
+
+ return (1);
+ err:
+ return (0);
+}
diff --git a/openssl-1.1.0h/ssl/ssl_utst.c b/openssl-1.1.0h/ssl/ssl_utst.c
new file mode 100644
index 0000000..09e76d1
--- /dev/null
+++ b/openssl-1.1.0h/ssl/ssl_utst.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2014-2016 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
+ */
+
+#include "ssl_locl.h"
+
+#ifndef OPENSSL_NO_UNIT_TEST
+
+static const struct openssl_ssl_test_functions ssl_test_functions = {
+ ssl_init_wbio_buffer,
+ ssl3_setup_buffers,
+# ifndef OPENSSL_NO_HEARTBEATS
+# undef dtls1_process_heartbeat
+ dtls1_process_heartbeat
+# endif
+};
+
+const struct openssl_ssl_test_functions *SSL_test_functions(void)
+{
+ return &ssl_test_functions;
+}
+
+#endif
diff --git a/openssl-1.1.0h/ssl/statem/README b/openssl-1.1.0h/ssl/statem/README
new file mode 100644
index 0000000..145c69d
--- /dev/null
+++ b/openssl-1.1.0h/ssl/statem/README
@@ -0,0 +1,63 @@
+State Machine Design
+====================
+
+This file provides some guidance on the thinking behind the design of the
+state machine code to aid future maintenance.
+
+The state machine code replaces an older state machine present in OpenSSL
+versions 1.0.2 and below. The new state machine has the following objectives:
+ - Remove duplication of state code between client and server
+ - Remove duplication of state code between TLS and DTLS
+ - Simplify transitions and bring the logic together in a single location
+ so that it is easier to validate
+ - Remove duplication of code between each of the message handling functions
+ - Receive a message first and then work out whether that is a valid
+ transition - not the other way around (the other way causes lots of issues
+ where we are expecting one type of message next but actually get something
+ else)
+ - Separate message flow state from handshake state (in order to better
+ understand each)
+ - message flow state = when to flush buffers; handling restarts in the
+ event of NBIO events; handling the common flow of steps for reading a
+ message and the common flow of steps for writing a message etc
+ - handshake state = what handshake message are we working on now
+ - Control complexity: only the state machine can change state: keep all
+ the state changes local to the state machine component
+
+The message flow state machine is divided into a reading sub-state machine and a
+writing sub-state machine. See the source comments in statem.c for a more
+detailed description of the various states and transitions possible.
+
+Conceptually the state machine component is designed as follows:
+
+ libssl
+ |
+---------------------------|-----statem.h--------------------------------------
+ |
+ _______V____________________
+ | |
+ | statem.c |
+ | |
+ | Core state machine code |
+ |____________________________|
+ statem_locl.h ^ ^
+ _________| |_______
+ | |
+ _____________|____________ _____________|____________
+ | | | |
+ | statem_clnt.c | | statem_srvr.c |
+ | | | |
+ | TLS/DTLS client specific | | TLS/DTLS server specific |
+ | state machine code | | state machine code |
+ |__________________________| |__________________________|
+ | |_______________|__ |
+ | ________________| | |
+ | | | |
+ ____________V_______V________ ________V______V_______________
+ | | | |
+ | statem_both.c | | statem_dtls.c |
+ | | | |
+ | Non core functions common | | Non core functions common to |
+ | to both servers and clients | | both DTLS servers and clients |
+ |_____________________________| |_______________________________|
+
diff --git a/openssl-1.1.0h/ssl/statem/statem.c b/openssl-1.1.0h/ssl/statem/statem.c
new file mode 100644
index 0000000..b91ec0a
--- /dev/null
+++ b/openssl-1.1.0h/ssl/statem/statem.c
@@ -0,0 +1,860 @@
+/*
+ * Copyright 2015-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
+ */
+
+#include <openssl/rand.h>
+#include "../ssl_locl.h"
+#include "statem_locl.h"
+
+/*
+ * This file implements the SSL/TLS/DTLS 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 | | | |
+ * | -------------------- -------------------- | | |
+ * | | | |
+ * --------------------------------------------- -------------------
+ *
+ */
+
+/* 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 int state_machine(SSL *s, int server);
+static void init_read_state_machine(SSL *s);
+static SUB_STATE_RETURN read_state_machine(SSL *s);
+static void init_write_state_machine(SSL *s);
+static SUB_STATE_RETURN write_state_machine(SSL *s);
+
+OSSL_HANDSHAKE_STATE SSL_get_state(const SSL *ssl)
+{
+ return ssl->statem.hand_state;
+}
+
+int SSL_in_init(SSL *s)
+{
+ return s->statem.in_init;
+}
+
+int SSL_is_init_finished(SSL *s)
+{
+ return !(s->statem.in_init) && (s->statem.hand_state == TLS_ST_OK);
+}
+
+int SSL_in_before(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(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(SSL *s)
+{
+ s->statem.state = MSG_FLOW_RENEGOTIATE;
+ s->statem.in_init = 1;
+}
+
+/*
+ * Put the state machine into an error state. This is a permanent error for
+ * the current connection.
+ */
+void ossl_statem_set_error(SSL *s)
+{
+ s->statem.state = MSG_FLOW_ERROR;
+}
+
+/*
+ * Discover whether the current connection is in the error state.
+ *
+ * Valid return values are:
+ * 1: Yes
+ * 0: No
+ */
+int ossl_statem_in_error(const SSL *s)
+{
+ if (s->statem.state == MSG_FLOW_ERROR)
+ return 1;
+
+ return 0;
+}
+
+void ossl_statem_set_in_init(SSL *s, int init)
+{
+ s->statem.in_init = init;
+}
+
+int ossl_statem_get_in_handshake(SSL *s)
+{
+ return s->statem.in_handshake;
+}
+
+void ossl_statem_set_in_handshake(SSL *s, int inhand)
+{
+ if (inhand)
+ s->statem.in_handshake++;
+ else
+ s->statem.in_handshake--;
+}
+
+void ossl_statem_set_hello_verify_done(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() 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(SSL *s)
+{
+ return state_machine(s, 0);
+}
+
+int ossl_statem_accept(SSL *s)
+{
+ return state_machine(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_RENEGOTIATE state and finish in MSG_FLOW_FINISHED. Valid states and
+ * transitions are as follows:
+ *
+ * MSG_FLOW_UNINITED MSG_FLOW_RENEGOTIATE
+ * | |
+ * +-----------------------+
+ * 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
+ */
+static int state_machine(SSL *s, int server)
+{
+ BUF_MEM *buf = NULL;
+ unsigned long Time = (unsigned long)time(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;
+ }
+
+ RAND_add(&Time, sizeof(Time), 0);
+ ERR_clear_error();
+ clear_sys_error();
+
+ cb = get_callback(s);
+
+ st->in_handshake++;
+ if (!SSL_in_init(s) || SSL_in_before(s)) {
+ if (!SSL_clear(s))
+ return -1;
+ }
+#ifndef OPENSSL_NO_SCTP
+ if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) {
+ /*
+ * Notify SCTP BIO socket to enter handshake mode and prevent stream
+ * identifier other than 0.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE,
+ st->in_handshake, NULL);
+ }
+#endif
+
+#ifndef OPENSSL_NO_HEARTBEATS
+ /*
+ * If we're awaiting a HeartbeatResponse, pretend we already got and
+ * don't await it anymore, because Heartbeats don't make sense during
+ * handshakes anyway.
+ */
+ if (s->tlsext_hb_pending) {
+ if (SSL_IS_DTLS(s))
+ dtls1_stop_timer(s);
+ s->tlsext_hb_pending = 0;
+ s->tlsext_hb_seq++;
+ }
+#endif
+
+ /* Initialise state machine */
+
+ if (st->state == MSG_FLOW_RENEGOTIATE) {
+ s->renegotiate = 1;
+ if (!server)
+ s->ctx->stats.sess_connect_renegotiate++;
+ }
+
+ if (st->state == MSG_FLOW_UNINITED || st->state == MSG_FLOW_RENEGOTIATE) {
+ if (st->state == MSG_FLOW_UNINITED) {
+ st->hand_state = TLS_ST_BEFORE;
+ }
+
+ s->server = server;
+ if (cb != NULL)
+ cb(s, SSL_CB_HANDSHAKE_START, 1);
+
+ if (SSL_IS_DTLS(s)) {
+ if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00) &&
+ (server || (s->version & 0xff00) != (DTLS1_BAD_VER & 0xff00))) {
+ SSLerr(SSL_F_STATE_MACHINE, ERR_R_INTERNAL_ERROR);
+ goto end;
+ }
+ } else {
+ if ((s->version >> 8) != SSL3_VERSION_MAJOR) {
+ SSLerr(SSL_F_STATE_MACHINE, ERR_R_INTERNAL_ERROR);
+ goto end;
+ }
+ }
+
+ if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) {
+ SSLerr(SSL_F_STATE_MACHINE, SSL_R_VERSION_TOO_LOW);
+ goto end;
+ }
+
+ if (s->init_buf == NULL) {
+ if ((buf = BUF_MEM_new()) == NULL) {
+ goto end;
+ }
+ if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
+ goto end;
+ }
+ s->init_buf = buf;
+ buf = NULL;
+ }
+
+ if (!ssl3_setup_buffers(s)) {
+ goto end;
+ }
+ s->init_num = 0;
+
+ /*
+ * Should have been reset by tls_process_finished, 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 (!SSL_IS_DTLS(s) || !BIO_dgram_is_sctp(SSL_get_wbio(s)))
+#endif
+ if (!ssl_init_wbio_buffer(s)) {
+ goto end;
+ }
+
+ if (!server || st->state != MSG_FLOW_RENEGOTIATE) {
+ if (!ssl3_init_finished_mac(s)) {
+ ossl_statem_set_error(s);
+ goto end;
+ }
+ }
+
+ if (server) {
+ if (st->state != MSG_FLOW_RENEGOTIATE) {
+ s->ctx->stats.sess_accept++;
+ } else if ((s->options & SSL_OP_NO_RENEGOTIATION)) {
+ /*
+ * Shouldn't happen? The record layer should have prevented this
+ */
+ SSLerr(SSL_F_STATE_MACHINE, ERR_R_INTERNAL_ERROR);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ ossl_statem_set_error(s);
+ goto end;
+ } else if (!s->s3->send_connection_binding &&
+ !(s->options &
+ SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) {
+ /*
+ * Server attempting to renegotiate with client that doesn't
+ * support secure renegotiation.
+ */
+ SSLerr(SSL_F_STATE_MACHINE,
+ SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ ossl_statem_set_error(s);
+ goto end;
+ } else {
+ /*
+ * st->state == MSG_FLOW_RENEGOTIATE, we will just send a
+ * HelloRequest
+ */
+ s->ctx->stats.sess_accept_renegotiate++;
+ }
+
+ s->s3->tmp.cert_request = 0;
+ } else {
+ s->ctx->stats.sess_connect++;
+
+ /* mark client_random uninitialized */
+ memset(s->s3->client_random, 0, sizeof(s->s3->client_random));
+ s->hit = 0;
+
+ s->s3->tmp.cert_req = 0;
+
+ if (SSL_IS_DTLS(s)) {
+ st->use_timer = 1;
+ }
+ }
+
+ st->state = MSG_FLOW_WRITING;
+ init_write_state_machine(s);
+ st->read_state_first_init = 1;
+ }
+
+ while (st->state != MSG_FLOW_FINISHED) {
+ if (st->state == MSG_FLOW_READING) {
+ ssret = read_state_machine(s);
+ if (ssret == SUB_STATE_FINISHED) {
+ st->state = MSG_FLOW_WRITING;
+ init_write_state_machine(s);
+ } else {
+ /* NBIO or error */
+ goto end;
+ }
+ } else if (st->state == MSG_FLOW_WRITING) {
+ ssret = write_state_machine(s);
+ if (ssret == SUB_STATE_FINISHED) {
+ st->state = MSG_FLOW_READING;
+ init_read_state_machine(s);
+ } else if (ssret == SUB_STATE_END_HANDSHAKE) {
+ st->state = MSG_FLOW_FINISHED;
+ } else {
+ /* NBIO or error */
+ goto end;
+ }
+ } else {
+ /* Error */
+ ossl_statem_set_error(s);
+ goto end;
+ }
+ }
+
+ st->state = MSG_FLOW_UNINITED;
+ ret = 1;
+
+ end:
+ st->in_handshake--;
+
+#ifndef OPENSSL_NO_SCTP
+ if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) {
+ /*
+ * Notify SCTP BIO socket to leave handshake mode and allow stream
+ * identifier other than 0.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE,
+ st->in_handshake, NULL);
+ }
+#endif
+
+ 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(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(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+ int ret, mt;
+ unsigned long 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);
+ unsigned long (*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;
+ process_message = ossl_statem_server_process_message;
+ max_message_size = ossl_statem_server_max_message_size;
+ post_process_message = ossl_statem_server_post_process_message;
+ } else {
+ transition = ossl_statem_client_read_transition;
+ process_message = ossl_statem_client_process_message;
+ max_message_size = ossl_statem_client_max_message_size;
+ post_process_message = ossl_statem_client_post_process_message;
+ }
+
+ 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 */
+ if (SSL_IS_DTLS(s)) {
+ /*
+ * In DTLS we get the whole message in one go - header and body
+ */
+ ret = dtls_get_message(s, &mt, &len);
+ } else {
+ ret = tls_get_message_header(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)) {
+ ossl_statem_set_error(s);
+ return SUB_STATE_ERROR;
+ }
+
+ if (s->s3->tmp.message_size > max_message_size(s)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+ SSLerr(SSL_F_READ_STATE_MACHINE, SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ return SUB_STATE_ERROR;
+ }
+
+ /* dtls_get_message already did this */
+ if (!SSL_IS_DTLS(s)
+ && s->s3->tmp.message_size > 0
+ && !grow_init_buf(s, s->s3->tmp.message_size
+ + SSL3_HM_HEADER_LENGTH)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ SSLerr(SSL_F_READ_STATE_MACHINE, ERR_R_BUF_LIB);
+ return SUB_STATE_ERROR;
+ }
+
+ st->read_state = READ_STATE_BODY;
+ /* Fall through */
+
+ case READ_STATE_BODY:
+ if (!SSL_IS_DTLS(s)) {
+ /* We already got this above for DTLS */
+ ret = tls_get_message_body(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)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ SSLerr(SSL_F_READ_STATE_MACHINE, ERR_R_INTERNAL_ERROR);
+ return SUB_STATE_ERROR;
+ }
+ ret = process_message(s, &pkt);
+
+ /* Discard the packet data */
+ s->init_num = 0;
+
+ switch (ret) {
+ case MSG_PROCESS_ERROR:
+ return SUB_STATE_ERROR;
+
+ case MSG_PROCESS_FINISHED_READING:
+ if (SSL_IS_DTLS(s)) {
+ dtls1_stop_timer(s);
+ }
+ 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) {
+ default:
+ return SUB_STATE_ERROR;
+
+ case WORK_FINISHED_CONTINUE:
+ st->read_state = READ_STATE_HEADER;
+ break;
+
+ case WORK_FINISHED_STOP:
+ if (SSL_IS_DTLS(s)) {
+ dtls1_stop_timer(s);
+ }
+ return SUB_STATE_FINISHED;
+ }
+ break;
+
+ default:
+ /* Shouldn't happen */
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ SSLerr(SSL_F_READ_STATE_MACHINE, ERR_R_INTERNAL_ERROR);
+ ossl_statem_set_error(s);
+ 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) {
+ if (SSL_IS_DTLS(s))
+ return dtls1_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC);
+ else
+ return ssl3_do_write(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(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(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 (*construct_message) (SSL *s);
+ void (*cb) (const SSL *ssl, int type, int val) = NULL;
+
+ cb = get_callback(s);
+
+ if (s->server) {
+ transition = ossl_statem_server_write_transition;
+ pre_work = ossl_statem_server_pre_work;
+ post_work = ossl_statem_server_post_work;
+ construct_message = ossl_statem_server_construct_message;
+ } else {
+ transition = ossl_statem_client_write_transition;
+ pre_work = ossl_statem_client_pre_work;
+ post_work = ossl_statem_client_post_work;
+ construct_message = ossl_statem_client_construct_message;
+ }
+
+ 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;
+
+ default:
+ return SUB_STATE_ERROR;
+ }
+ break;
+
+ case WRITE_STATE_PRE_WORK:
+ switch (st->write_state_work = pre_work(s, st->write_state_work)) {
+ default:
+ return SUB_STATE_ERROR;
+
+ case WORK_FINISHED_CONTINUE:
+ st->write_state = WRITE_STATE_SEND;
+ break;
+
+ case WORK_FINISHED_STOP:
+ return SUB_STATE_END_HANDSHAKE;
+ }
+ if (construct_message(s) == 0)
+ return SUB_STATE_ERROR;
+
+ /* Fall through */
+
+ case WRITE_STATE_SEND:
+ if (SSL_IS_DTLS(s) && st->use_timer) {
+ dtls1_start_timer(s);
+ }
+ 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)) {
+ default:
+ return SUB_STATE_ERROR;
+
+ case WORK_FINISHED_CONTINUE:
+ st->write_state = WRITE_STATE_TRANSITION;
+ break;
+
+ case WORK_FINISHED_STOP:
+ return SUB_STATE_END_HANDSHAKE;
+ }
+ break;
+
+ default:
+ return SUB_STATE_ERROR;
+ }
+ }
+}
+
+/*
+ * Flush the write BIO
+ */
+int statem_flush(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 sent 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(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ if (st->state == MSG_FLOW_UNINITED || st->state == MSG_FLOW_RENEGOTIATE)
+ 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;
+}
diff --git a/openssl-1.1.0h/ssl/statem/statem.h b/openssl-1.1.0h/ssl/statem/statem.h
new file mode 100644
index 0000000..c669ee9
--- /dev/null
+++ b/openssl-1.1.0h/ssl/statem/statem.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2015-2016 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
+ */
+
+/*****************************************************************************
+ * *
+ * 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,
+ /* We're done working and there shouldn't be anything else to do after */
+ WORK_FINISHED_STOP,
+ /* We're done working move onto the next thing */
+ WORK_FINISHED_CONTINUE,
+ /* We're working on phase A */
+ WORK_MORE_A,
+ /* We're working on phase B */
+ WORK_MORE_B
+} WORK_STATE;
+
+/* Write transition return codes */
+typedef enum {
+ /* Something went wrong */
+ WRITE_TRAN_ERROR,
+ /* A transition was successfully completed and we should continue */
+ WRITE_TRAN_CONTINUE,
+ /* There is no more write work to be done */
+ WRITE_TRAN_FINISHED
+} WRITE_TRAN;
+
+/* Message flow states */
+typedef enum {
+ /* No handshake in progress */
+ MSG_FLOW_UNINITED,
+ /* A permanent error with this connection */
+ MSG_FLOW_ERROR,
+ /* We are about to renegotiate */
+ MSG_FLOW_RENEGOTIATE,
+ /* We are reading messages */
+ MSG_FLOW_READING,
+ /* We are writing messages */
+ MSG_FLOW_WRITING,
+ /* Handshake has finished */
+ MSG_FLOW_FINISHED
+} MSG_FLOW_STATE;
+
+/* Read states */
+typedef enum {
+ READ_STATE_HEADER,
+ READ_STATE_BODY,
+ READ_STATE_POST_PROCESS
+} READ_STATE;
+
+/* Write states */
+typedef enum {
+ WRITE_STATE_TRANSITION,
+ WRITE_STATE_PRE_WORK,
+ WRITE_STATE_SEND,
+ WRITE_STATE_POST_WORK
+} WRITE_STATE;
+
+/*****************************************************************************
+ * *
+ * 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 {
+ MSG_FLOW_STATE state;
+ WRITE_STATE write_state;
+ WORK_STATE write_state_work;
+ READ_STATE read_state;
+ WORK_STATE read_state_work;
+ OSSL_HANDSHAKE_STATE hand_state;
+ int in_init;
+ int read_state_first_init;
+ /* true when we are actually in SSL_accept() or SSL_connect() */
+ int in_handshake;
+ /* Should we skip the CertificateVerify message? */
+ unsigned int no_cert_verify;
+ int use_timer;
+};
+typedef struct ossl_statem_st OSSL_STATEM;
+
+/*****************************************************************************
+ * *
+ * 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(SSL *s);
+__owur int ossl_statem_connect(SSL *s);
+void ossl_statem_clear(SSL *s);
+void ossl_statem_set_renegotiate(SSL *s);
+void ossl_statem_set_error(SSL *s);
+int ossl_statem_in_error(const SSL *s);
+void ossl_statem_set_in_init(SSL *s, int init);
+int ossl_statem_get_in_handshake(SSL *s);
+void ossl_statem_set_in_handshake(SSL *s, int inhand);
+void ossl_statem_set_hello_verify_done(SSL *s);
+__owur int ossl_statem_app_data_allowed(SSL *s);
diff --git a/openssl-1.1.0h/ssl/statem/statem_clnt.c b/openssl-1.1.0h/ssl/statem/statem_clnt.c
new file mode 100644
index 0000000..6fa3f1d
--- /dev/null
+++ b/openssl-1.1.0h/ssl/statem/statem_clnt.c
@@ -0,0 +1,2946 @@
+/*
+ * Copyright 1995-2016 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
+ */
+
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * ECC cipher suite support in OpenSSL originally written by
+ * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
+ *
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <stdio.h>
+#include "../ssl_locl.h"
+#include "statem_locl.h"
+#include <openssl/buffer.h>
+#include <openssl/rand.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/md5.h>
+#include <openssl/dh.h>
+#include <openssl/bn.h>
+#include <openssl/engine.h>
+
+static ossl_inline int cert_req_allowed(SSL *s);
+static int key_exchange_expected(SSL *s);
+static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b);
+static int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk,
+ unsigned char *p);
+
+/*
+ * 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)
+{
+ long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+
+ /*
+ * Can't skip server key exchange if this is an ephemeral
+ * ciphersuite or for SRP
+ */
+ if (alg_k & (SSL_kDHE | SSL_kECDHE | SSL_kDHEPSK | SSL_kECDHEPSK
+ | SSL_kSRP)) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * ossl_statem_client_read_transition() 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: Success (transition allowed)
+ * 0: Error (transition not allowed)
+ */
+int ossl_statem_client_read_transition(SSL *s, int mt)
+{
+ OSSL_STATEM *st = &s->statem;
+ int ske_expected;
+
+ switch (st->hand_state) {
+ case TLS_ST_CW_CLNT_HELLO:
+ if (mt == SSL3_MT_SERVER_HELLO) {
+ st->hand_state = TLS_ST_CR_SRVR_HELLO;
+ return 1;
+ }
+
+ if (SSL_IS_DTLS(s)) {
+ if (mt == DTLS1_MT_HELLO_VERIFY_REQUEST) {
+ st->hand_state = DTLS_ST_CR_HELLO_VERIFY_REQUEST;
+ return 1;
+ }
+ }
+ break;
+
+ case TLS_ST_CR_SRVR_HELLO:
+ if (s->hit) {
+ if (s->tlsext_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 (SSL_IS_DTLS(s) && mt == DTLS1_MT_HELLO_VERIFY_REQUEST) {
+ st->hand_state = DTLS_ST_CR_HELLO_VERIFY_REQUEST;
+ return 1;
+ } else if (s->version >= TLS1_VERSION
+ && s->tls_session_secret_cb != NULL
+ && s->session->tlsext_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
+ * |tlsext_status_expected| is set
+ */
+ if (s->tlsext_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->tlsext_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;
+
+ default:
+ break;
+ }
+
+ err:
+ /* No valid transition found */
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL3_AD_UNEXPECTED_MESSAGE);
+ SSLerr(SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION, SSL_R_UNEXPECTED_MESSAGE);
+ return 0;
+}
+
+/*
+ * client_write_transition() 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(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ case TLS_ST_OK:
+ /* Renegotiation - fall through */
+ case TLS_ST_BEFORE:
+ st->hand_state = TLS_ST_CW_CLNT_HELLO;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_CW_CLNT_HELLO:
+ /*
+ * No transition at the end of writing because we don't know what
+ * we will be sent
+ */
+ return WRITE_TRAN_FINISHED;
+
+ case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
+ st->hand_state = TLS_ST_CW_CLNT_HELLO;
+ return WRITE_TRAN_CONTINUE;
+
+ 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 defined(OPENSSL_NO_NEXTPROTONEG)
+ st->hand_state = TLS_ST_CW_FINISHED;
+#else
+ if (!SSL_IS_DTLS(s) && s->s3->next_proto_neg_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;
+ ossl_statem_set_in_init(s, 0);
+ 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;
+ ossl_statem_set_in_init(s, 0);
+ return WRITE_TRAN_CONTINUE;
+ }
+
+ default:
+ /* Shouldn't happen */
+ return WRITE_TRAN_ERROR;
+ }
+}
+
+/*
+ * 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(SSL *s, WORK_STATE wst)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ case TLS_ST_CW_CLNT_HELLO:
+ s->shutdown = 0;
+ if (SSL_IS_DTLS(s)) {
+ /* every DTLS ClientHello resets Finished MAC */
+ if (!ssl3_init_finished_mac(s)) {
+ ossl_statem_set_error(s);
+ return WORK_ERROR;
+ }
+ }
+ break;
+
+ case TLS_ST_CW_CHANGE:
+ if (SSL_IS_DTLS(s)) {
+ if (s->hit) {
+ /*
+ * We're into the last flight so we don't retransmit these
+ * messages unless we need to.
+ */
+ st->use_timer = 0;
+ }
+#ifndef OPENSSL_NO_SCTP
+ if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
+ return dtls_wait_for_dry(s);
+#endif
+ }
+ return WORK_FINISHED_CONTINUE;
+
+ case TLS_ST_OK:
+ return tls_finish_handshake(s, wst);
+
+ default:
+ /* No pre work to be done */
+ break;
+ }
+
+ 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(SSL *s, WORK_STATE wst)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ s->init_num = 0;
+
+ switch (st->hand_state) {
+ case TLS_ST_CW_CLNT_HELLO:
+ if (wst == WORK_MORE_A && statem_flush(s) != 1)
+ return WORK_MORE_A;
+
+ if (SSL_IS_DTLS(s)) {
+ /* Treat the next message as the first packet */
+ s->first_packet = 1;
+ }
+ break;
+
+ case TLS_ST_CW_KEY_EXCH:
+ if (tls_client_key_exchange_post_work(s) == 0)
+ return WORK_ERROR;
+ break;
+
+ case TLS_ST_CW_CHANGE:
+ s->session->cipher = s->s3->tmp.new_cipher;
+#ifdef OPENSSL_NO_COMP
+ s->session->compress_meth = 0;
+#else
+ if (s->s3->tmp.new_compression == NULL)
+ s->session->compress_meth = 0;
+ else
+ s->session->compress_meth = s->s3->tmp.new_compression->id;
+#endif
+ if (!s->method->ssl3_enc->setup_key_block(s))
+ return WORK_ERROR;
+
+ if (!s->method->ssl3_enc->change_cipher_state(s,
+ SSL3_CHANGE_CIPHER_CLIENT_WRITE))
+ return WORK_ERROR;
+
+ if (SSL_IS_DTLS(s)) {
+#ifndef OPENSSL_NO_SCTP
+ if (s->hit) {
+ /*
+ * Change to new shared key of SCTP-Auth, will be ignored if
+ * no SCTP used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
+ 0, NULL);
+ }
+#endif
+
+ dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
+ }
+ break;
+
+ case TLS_ST_CW_FINISHED:
+#ifndef OPENSSL_NO_SCTP
+ if (wst == WORK_MORE_A && SSL_IS_DTLS(s) && s->hit == 0) {
+ /*
+ * Change to new shared key of SCTP-Auth, will be ignored if
+ * no SCTP used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
+ 0, NULL);
+ }
+#endif
+ if (statem_flush(s) != 1)
+ return WORK_MORE_B;
+ break;
+
+ default:
+ /* No post work to be done */
+ break;
+ }
+
+ return WORK_FINISHED_CONTINUE;
+}
+
+/*
+ * Construct a message to be sent from the client to the server.
+ *
+ * Valid return values are:
+ * 1: Success
+ * 0: Error
+ */
+int ossl_statem_client_construct_message(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ case TLS_ST_CW_CLNT_HELLO:
+ return tls_construct_client_hello(s);
+
+ case TLS_ST_CW_CERT:
+ return tls_construct_client_certificate(s);
+
+ case TLS_ST_CW_KEY_EXCH:
+ return tls_construct_client_key_exchange(s);
+
+ case TLS_ST_CW_CERT_VRFY:
+ return tls_construct_client_verify(s);
+
+ case TLS_ST_CW_CHANGE:
+ if (SSL_IS_DTLS(s))
+ return dtls_construct_change_cipher_spec(s);
+ else
+ return tls_construct_change_cipher_spec(s);
+
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
+ case TLS_ST_CW_NEXT_PROTO:
+ return tls_construct_next_proto(s);
+#endif
+ case TLS_ST_CW_FINISHED:
+ return tls_construct_finished(s,
+ s->method->
+ ssl3_enc->client_finished_label,
+ s->method->
+ ssl3_enc->client_finished_label_len);
+
+ default:
+ /* Shouldn't happen */
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * Returns the maximum allowed length for the current message that we are
+ * reading. Excludes the message header.
+ */
+unsigned long ossl_statem_client_max_message_size(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ case TLS_ST_CR_SRVR_HELLO:
+ return SERVER_HELLO_MAX_LENGTH;
+
+ case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
+ return HELLO_VERIFY_REQUEST_MAX_LENGTH;
+
+ case TLS_ST_CR_CERT:
+ return s->max_cert_list;
+
+ 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:
+ if (s->version == DTLS1_BAD_VER)
+ return 3;
+ 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;
+
+ default:
+ /* Shouldn't happen */
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * Process a message that the client has been received from the server.
+ */
+MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ case TLS_ST_CR_SRVR_HELLO:
+ return tls_process_server_hello(s, pkt);
+
+ case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
+ return dtls_process_hello_verify(s, pkt);
+
+ case TLS_ST_CR_CERT:
+ return tls_process_server_certificate(s, pkt);
+
+ case TLS_ST_CR_CERT_STATUS:
+ return tls_process_cert_status(s, pkt);
+
+ case TLS_ST_CR_KEY_EXCH:
+ return tls_process_key_exchange(s, pkt);
+
+ case TLS_ST_CR_CERT_REQ:
+ return tls_process_certificate_request(s, pkt);
+
+ case TLS_ST_CR_SRVR_DONE:
+ return tls_process_server_done(s, pkt);
+
+ case TLS_ST_CR_CHANGE:
+ return tls_process_change_cipher_spec(s, pkt);
+
+ case TLS_ST_CR_SESSION_TICKET:
+ return tls_process_new_session_ticket(s, pkt);
+
+ case TLS_ST_CR_FINISHED:
+ return tls_process_finished(s, pkt);
+
+ default:
+ /* Shouldn't happen */
+ break;
+ }
+
+ return MSG_PROCESS_ERROR;
+}
+
+/*
+ * Perform any further processing required following the receipt of a message
+ * from the server
+ */
+WORK_STATE ossl_statem_client_post_process_message(SSL *s, WORK_STATE wst)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ case TLS_ST_CR_CERT_REQ:
+ return tls_prepare_client_certificate(s, wst);
+
+ default:
+ break;
+ }
+
+ /* Shouldn't happen */
+ return WORK_ERROR;
+}
+
+int tls_construct_client_hello(SSL *s)
+{
+ unsigned char *buf;
+ unsigned char *p, *d;
+ int i;
+ int protverr;
+ unsigned long l;
+ int al = 0;
+#ifndef OPENSSL_NO_COMP
+ int j;
+ SSL_COMP *comp;
+#endif
+ SSL_SESSION *sess = s->session;
+
+ buf = (unsigned char *)s->init_buf->data;
+
+ /* Work out what SSL/TLS/DTLS version to use */
+ protverr = ssl_set_client_hello_version(s);
+ if (protverr != 0) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, protverr);
+ goto err;
+ }
+
+ if ((sess == NULL) || !ssl_version_supported(s, sess->ssl_version) ||
+ /*
+ * In the case of EAP-FAST, we can have a pre-shared
+ * "ticket" without a session ID.
+ */
+ (!sess->session_id_length && !sess->tlsext_tick) ||
+ (sess->not_resumable)) {
+ if (!ssl_get_new_session(s, 0))
+ goto err;
+ }
+ /* else use the pre-loaded session */
+
+ p = s->s3->client_random;
+
+ /*
+ * for DTLS if client_random is initialized, reuse it, we are
+ * required to use same upon reply to HelloVerify
+ */
+ if (SSL_IS_DTLS(s)) {
+ size_t idx;
+ i = 1;
+ for (idx = 0; idx < sizeof(s->s3->client_random); idx++) {
+ if (p[idx]) {
+ i = 0;
+ break;
+ }
+ }
+ } else
+ i = 1;
+
+ if (i && ssl_fill_hello_random(s, 0, p, sizeof(s->s3->client_random)) <= 0)
+ goto err;
+
+ /* Do the message type and length last */
+ d = p = ssl_handshake_start(s);
+
+ /*-
+ * 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.
+ */
+ *(p++) = s->client_version >> 8;
+ *(p++) = s->client_version & 0xff;
+
+ /* Random stuff */
+ memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
+ p += SSL3_RANDOM_SIZE;
+
+ /* Session ID */
+ if (s->new_session)
+ i = 0;
+ else
+ i = s->session->session_id_length;
+ *(p++) = i;
+ if (i != 0) {
+ if (i > (int)sizeof(s->session->session_id)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ memcpy(p, s->session->session_id, i);
+ p += i;
+ }
+
+ /* cookie stuff for DTLS */
+ if (SSL_IS_DTLS(s)) {
+ if (s->d1->cookie_len > sizeof(s->d1->cookie)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ *(p++) = s->d1->cookie_len;
+ memcpy(p, s->d1->cookie, s->d1->cookie_len);
+ p += s->d1->cookie_len;
+ }
+
+ /* Ciphers supported */
+ i = ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &(p[2]));
+ if (i == 0) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, SSL_R_NO_CIPHERS_AVAILABLE);
+ goto err;
+ }
+#ifdef OPENSSL_MAX_TLS1_2_CIPHER_LENGTH
+ /*
+ * 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
+ && i > OPENSSL_MAX_TLS1_2_CIPHER_LENGTH)
+ i = OPENSSL_MAX_TLS1_2_CIPHER_LENGTH & ~1;
+#endif
+ s2n(i, p);
+ p += i;
+
+ /* COMPRESSION */
+#ifdef OPENSSL_NO_COMP
+ *(p++) = 1;
+#else
+
+ if (!ssl_allow_compression(s) || !s->ctx->comp_methods)
+ j = 0;
+ else
+ j = sk_SSL_COMP_num(s->ctx->comp_methods);
+ *(p++) = 1 + j;
+ for (i = 0; i < j; i++) {
+ comp = sk_SSL_COMP_value(s->ctx->comp_methods, i);
+ *(p++) = comp->id;
+ }
+#endif
+ *(p++) = 0; /* Add the NULL method */
+
+ /* TLS extensions */
+ if (ssl_prepare_clienthello_tlsext(s) <= 0) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
+ goto err;
+ }
+ if ((p =
+ ssl_add_clienthello_tlsext(s, p, buf + SSL3_RT_MAX_PLAIN_LENGTH,
+ &al)) == NULL) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ l = p - d;
+ if (!ssl_set_handshake_header(s, SSL3_MT_CLIENT_HELLO, l)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ return 1;
+ err:
+ ossl_statem_set_error(s);
+ return 0;
+}
+
+MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, PACKET *pkt)
+{
+ int al;
+ unsigned int cookie_len;
+ PACKET cookiepkt;
+
+ if (!PACKET_forward(pkt, 2)
+ || !PACKET_get_length_prefixed_1(pkt, &cookiepkt)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_DTLS_PROCESS_HELLO_VERIFY, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+
+ cookie_len = PACKET_remaining(&cookiepkt);
+ if (cookie_len > sizeof(s->d1->cookie)) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_DTLS_PROCESS_HELLO_VERIFY, SSL_R_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+
+ if (!PACKET_copy_bytes(&cookiepkt, s->d1->cookie, cookie_len)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_DTLS_PROCESS_HELLO_VERIFY, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ s->d1->cookie_len = cookie_len;
+
+ return MSG_PROCESS_FINISHED_READING;
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ ossl_statem_set_error(s);
+ return MSG_PROCESS_ERROR;
+}
+
+MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
+{
+ STACK_OF(SSL_CIPHER) *sk;
+ const SSL_CIPHER *c;
+ PACKET session_id;
+ size_t session_id_len;
+ const unsigned char *cipherchars;
+ int i, al = SSL_AD_INTERNAL_ERROR;
+ unsigned int compression;
+ unsigned int sversion;
+ int protverr;
+#ifndef OPENSSL_NO_COMP
+ SSL_COMP *comp;
+#endif
+
+ if (!PACKET_get_net_2(pkt, &sversion)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+
+ protverr = ssl_choose_client_version(s, sversion);
+ if (protverr != 0) {
+ al = SSL_AD_PROTOCOL_VERSION;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, protverr);
+ goto f_err;
+ }
+
+ /* load the server hello data */
+ /* load the server random */
+ if (!PACKET_copy_bytes(pkt, s->s3->server_random, SSL3_RANDOM_SIZE)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+
+ s->hit = 0;
+
+ /* Get the session-id. */
+ if (!PACKET_get_length_prefixed_1(pkt, &session_id)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ session_id_len = PACKET_remaining(&session_id);
+ if (session_id_len > sizeof(s->session->session_id)
+ || session_id_len > SSL3_SESSION_ID_SIZE) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_SSL3_SESSION_ID_TOO_LONG);
+ goto f_err;
+ }
+
+ if (!PACKET_get_bytes(pkt, &cipherchars, TLS_CIPHER_LEN)) {
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+ al = SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
+
+ /*
+ * 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->tls_session_secret_cb &&
+ s->session->tlsext_tick) {
+ const SSL_CIPHER *pref_cipher = NULL;
+ s->session->master_key_length = sizeof(s->session->master_key);
+ if (s->tls_session_secret_cb(s, s->session->master_key,
+ &s->session->master_key_length,
+ NULL, &pref_cipher,
+ s->tls_session_secret_cb_arg)) {
+ s->session->cipher = pref_cipher ?
+ pref_cipher : ssl_get_cipher_by_char(s, cipherchars);
+ } else {
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_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) {
+ 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 */
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
+ goto f_err;
+ }
+ s->hit = 1;
+ } else {
+ /*
+ * If we were trying for session-id reuse but the server
+ * didn't echo the ID, 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) {
+ s->ctx->stats.sess_miss++;
+ if (!ssl_get_new_session(s, 0)) {
+ goto f_err;
+ }
+ }
+
+ s->session->ssl_version = s->version;
+ 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) {
+ al = SSL_AD_PROTOCOL_VERSION;
+
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_SSL_SESSION_VERSION_MISMATCH);
+ goto f_err;
+ }
+
+ c = ssl_get_cipher_by_char(s, cipherchars);
+ if (c == NULL) {
+ /* unknown cipher */
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_UNKNOWN_CIPHER_RETURNED);
+ goto f_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 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)) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_WRONG_CIPHER_RETURNED);
+ goto f_err;
+ }
+
+ 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 */
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_WRONG_CIPHER_RETURNED);
+ goto f_err;
+ }
+
+ /*
+ * 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)
+ s->session->cipher_id = s->session->cipher->id;
+ if (s->hit && (s->session->cipher_id != c->id)) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
+ goto f_err;
+ }
+ s->s3->tmp.new_cipher = c;
+ /* lets get the compression algorithm */
+ /* COMPRESSION */
+ if (!PACKET_get_1(pkt, &compression)) {
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+ al = SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
+#ifdef OPENSSL_NO_COMP
+ if (compression != 0) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+ goto f_err;
+ }
+ /*
+ * If compression is disabled we'd better not try to resume a session
+ * using compression.
+ */
+ if (s->session->compress_meth != 0) {
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_INCONSISTENT_COMPRESSION);
+ goto f_err;
+ }
+#else
+ if (s->hit && compression != s->session->compress_meth) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED);
+ goto f_err;
+ }
+ if (compression == 0)
+ comp = NULL;
+ else if (!ssl_allow_compression(s)) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_COMPRESSION_DISABLED);
+ goto f_err;
+ } else {
+ comp = ssl3_comp_find(s->ctx->comp_methods, compression);
+ }
+
+ if (compression != 0 && comp == NULL) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+ goto f_err;
+ } else {
+ s->s3->tmp.new_compression = comp;
+ }
+#endif
+
+ /* TLS extensions */
+ if (!ssl_parse_serverhello_tlsext(s, pkt)) {
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_PARSE_TLSEXT);
+ goto err;
+ }
+
+ if (PACKET_remaining(pkt) != 0) {
+ /* wrong packet length */
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_BAD_PACKET_LENGTH);
+ goto f_err;
+ }
+#ifndef OPENSSL_NO_SCTP
+ if (SSL_IS_DTLS(s) && s->hit) {
+ unsigned char sctpauthkey[64];
+ char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
+
+ /*
+ * Add new shared key for SCTP-Auth, will be ignored if
+ * no SCTP used.
+ */
+ memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
+ sizeof(DTLS1_SCTP_AUTH_LABEL));
+
+ if (SSL_export_keying_material(s, sctpauthkey,
+ sizeof(sctpauthkey),
+ labelbuffer,
+ sizeof(labelbuffer), NULL, 0, 0) <= 0)
+ goto err;
+
+ BIO_ctrl(SSL_get_wbio(s),
+ BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
+ sizeof(sctpauthkey), sctpauthkey);
+ }
+#endif
+
+ return MSG_PROCESS_CONTINUE_READING;
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ err:
+ ossl_statem_set_error(s);
+ return MSG_PROCESS_ERROR;
+}
+
+MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
+{
+ int al, i, ret = MSG_PROCESS_ERROR, exp_idx;
+ unsigned long cert_list_len, cert_len;
+ X509 *x = NULL;
+ const unsigned char *certstart, *certbytes;
+ STACK_OF(X509) *sk = NULL;
+ EVP_PKEY *pkey = NULL;
+
+ if ((sk = sk_X509_new_null()) == NULL) {
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!PACKET_get_net_3(pkt, &cert_list_len)
+ || PACKET_remaining(pkt) != cert_list_len) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ while (PACKET_remaining(pkt)) {
+ if (!PACKET_get_net_3(pkt, &cert_len)
+ || !PACKET_get_bytes(pkt, &certbytes, cert_len)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+ SSL_R_CERT_LENGTH_MISMATCH);
+ goto f_err;
+ }
+
+ certstart = certbytes;
+ x = d2i_X509(NULL, (const unsigned char **)&certbytes, cert_len);
+ if (x == NULL) {
+ al = SSL_AD_BAD_CERTIFICATE;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_ASN1_LIB);
+ goto f_err;
+ }
+ if (certbytes != (certstart + cert_len)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+ SSL_R_CERT_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ if (!sk_X509_push(sk, x)) {
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ x = NULL;
+ }
+
+ 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) {
+ al = ssl_verify_alarm_type(s->verify_result);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+ SSL_R_CERTIFICATE_VERIFY_FAILED);
+ goto f_err;
+ }
+ ERR_clear_error(); /* but we keep s->verify_result */
+ if (i > 1) {
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, i);
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ goto f_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;
+ al = SSL3_AL_FATAL;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+ SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS);
+ goto f_err;
+ }
+
+ i = ssl_cert_type(x, pkey);
+ if (i < 0) {
+ x = NULL;
+ al = SSL3_AL_FATAL;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+ SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+ goto f_err;
+ }
+
+ exp_idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
+ if (exp_idx >= 0 && i != exp_idx
+ && (exp_idx != SSL_PKEY_GOST_EC ||
+ (i != SSL_PKEY_GOST12_512 && i != SSL_PKEY_GOST12_256
+ && i != SSL_PKEY_GOST01))) {
+ x = NULL;
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+ SSL_R_WRONG_CERTIFICATE_TYPE);
+ goto f_err;
+ }
+ s->session->peer_type = i;
+
+ 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;
+ goto done;
+
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ err:
+ ossl_statem_set_error(s);
+ done:
+ X509_free(x);
+ sk_X509_pop_free(sk, X509_free);
+ return ret;
+}
+
+static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt, int *al)
+{
+#ifndef OPENSSL_NO_PSK
+ PACKET psk_identity_hint;
+
+ /* PSK ciphersuites are preceded by an identity hint */
+
+ if (!PACKET_get_length_prefixed_2(pkt, &psk_identity_hint)) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE, SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+
+ /*
+ * Store PSK identity hint for later use, hint is used in
+ * tls_construct_client_key_exchange. Assume that the maximum length of
+ * a PSK identity hint can be as long as the maximum length of a PSK
+ * identity.
+ */
+ if (PACKET_remaining(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN) {
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE, SSL_R_DATA_LENGTH_TOO_LONG);
+ return 0;
+ }
+
+ if (PACKET_remaining(&psk_identity_hint) == 0) {
+ OPENSSL_free(s->session->psk_identity_hint);
+ s->session->psk_identity_hint = NULL;
+ } else if (!PACKET_strndup(&psk_identity_hint,
+ &s->session->psk_identity_hint)) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+
+ return 1;
+#else
+ SSLerr(SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+#endif
+}
+
+static int tls_process_ske_srp(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
+{
+#ifndef OPENSSL_NO_SRP
+ PACKET prime, generator, salt, server_pub;
+
+ if (!PACKET_get_length_prefixed_2(pkt, &prime)
+ || !PACKET_get_length_prefixed_2(pkt, &generator)
+ || !PACKET_get_length_prefixed_1(pkt, &salt)
+ || !PACKET_get_length_prefixed_2(pkt, &server_pub)) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_SKE_SRP, SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+
+ if ((s->srp_ctx.N =
+ BN_bin2bn(PACKET_data(&prime),
+ PACKET_remaining(&prime), NULL)) == NULL
+ || (s->srp_ctx.g =
+ BN_bin2bn(PACKET_data(&generator),
+ PACKET_remaining(&generator), NULL)) == NULL
+ || (s->srp_ctx.s =
+ BN_bin2bn(PACKET_data(&salt),
+ PACKET_remaining(&salt), NULL)) == NULL
+ || (s->srp_ctx.B =
+ BN_bin2bn(PACKET_data(&server_pub),
+ PACKET_remaining(&server_pub), NULL)) == NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_SKE_SRP, ERR_R_BN_LIB);
+ return 0;
+ }
+
+ if (!srp_verify_server_param(s, al)) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_SKE_SRP, SSL_R_BAD_SRP_PARAMETERS);
+ return 0;
+ }
+
+ /* We must check if there is a certificate */
+ if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aRSA | SSL_aDSS))
+ *pkey = X509_get0_pubkey(s->session->peer);
+
+ return 1;
+#else
+ SSLerr(SSL_F_TLS_PROCESS_SKE_SRP, ERR_R_INTERNAL_ERROR);
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+#endif
+}
+
+static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
+{
+#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)) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(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) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ p = BN_bin2bn(PACKET_data(&prime), PACKET_remaining(&prime), NULL);
+ g = BN_bin2bn(PACKET_data(&generator), PACKET_remaining(&generator), NULL);
+ bnpub_key = BN_bin2bn(PACKET_data(&pub_key), PACKET_remaining(&pub_key),
+ NULL);
+ if (p == NULL || g == NULL || bnpub_key == NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ /* test non-zero pubkey */
+ if (BN_is_zero(bnpub_key)) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, SSL_R_BAD_DH_VALUE);
+ goto err;
+ }
+
+ if (!DH_set0_pqg(dh, p, NULL, g)) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(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) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, SSL_R_BAD_DH_VALUE);
+ goto err;
+ }
+
+ if (!DH_set0_key(dh, bnpub_key, NULL)) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(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)) {
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, SSL_R_DH_KEY_TOO_SMALL);
+ goto err;
+ }
+
+ if (EVP_PKEY_assign_DH(peer_tmp, dh) == 0) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(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
+ SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, ERR_R_INTERNAL_ERROR);
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+#endif
+}
+
+static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
+{
+#ifndef OPENSSL_NO_EC
+ PACKET encoded_pt;
+ const unsigned char *ecparams;
+ int curve_nid;
+ unsigned int curve_flags;
+ EVP_PKEY_CTX *pctx = NULL;
+
+ /*
+ * Extract elliptic curve parameters and the server's ephemeral ECDH
+ * public key. For now we only support named (not generic) curves and
+ * ECParameters in this case is just three bytes.
+ */
+ if (!PACKET_get_bytes(pkt, &ecparams, 3)) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, SSL_R_LENGTH_TOO_SHORT);
+ return 0;
+ }
+ /*
+ * Check curve is one of our preferences, if not server has sent an
+ * invalid curve. ECParameters is 3 bytes.
+ */
+ if (!tls1_check_curve(s, ecparams, 3)) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, SSL_R_WRONG_CURVE);
+ return 0;
+ }
+
+ curve_nid = tls1_ec_curve_id2nid(*(ecparams + 2), &curve_flags);
+
+ if (curve_nid == 0) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE,
+ SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
+ return 0;
+ }
+
+ if ((curve_flags & TLS_CURVE_TYPE) == TLS_CURVE_CUSTOM) {
+ EVP_PKEY *key = EVP_PKEY_new();
+
+ if (key == NULL || !EVP_PKEY_set_type(key, curve_nid)) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, ERR_R_EVP_LIB);
+ EVP_PKEY_free(key);
+ return 0;
+ }
+ s->s3->peer_tmp = key;
+ } else {
+ /* Set up EVP_PKEY with named curve as parameters */
+ pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
+ if (pctx == NULL
+ || EVP_PKEY_paramgen_init(pctx) <= 0
+ || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, curve_nid) <= 0
+ || EVP_PKEY_paramgen(pctx, &s->s3->peer_tmp) <= 0) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, ERR_R_EVP_LIB);
+ EVP_PKEY_CTX_free(pctx);
+ return 0;
+ }
+ EVP_PKEY_CTX_free(pctx);
+ pctx = NULL;
+ }
+
+ if (!PACKET_get_length_prefixed_1(pkt, &encoded_pt)) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(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))) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(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_aRSA)
+ *pkey = X509_get0_pubkey(s->session->peer);
+ /* else anonymous ECDH, so no certificate or pkey. */
+
+ return 1;
+#else
+ SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, ERR_R_INTERNAL_ERROR);
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+#endif
+}
+
+MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
+{
+ int al = -1;
+ long alg_k;
+ EVP_PKEY *pkey = 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, &al))
+ goto err;
+ }
+
+ /* Nothing else to do for plain PSK or RSAPSK */
+ if (alg_k & (SSL_kPSK | SSL_kRSAPSK)) {
+ } else if (alg_k & SSL_kSRP) {
+ if (!tls_process_ske_srp(s, pkt, &pkey, &al))
+ goto err;
+ } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
+ if (!tls_process_ske_dhe(s, pkt, &pkey, &al))
+ goto err;
+ } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
+ if (!tls_process_ske_ecdhe(s, pkt, &pkey, &al))
+ goto err;
+ } else if (alg_k) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, 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;
+ EVP_MD_CTX *md_ctx;
+
+ /*
+ * |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, &params,
+ PACKET_remaining(&save_param_start) -
+ PACKET_remaining(pkt))) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (SSL_USE_SIGALGS(s)) {
+ const unsigned char *sigalgs;
+ int rv;
+ if (!PACKET_get_bytes(pkt, &sigalgs, 2)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
+ goto err;
+ }
+ rv = tls12_check_peer_sigalg(&md, s, sigalgs, pkey);
+ if (rv == -1) {
+ al = SSL_AD_INTERNAL_ERROR;
+ goto err;
+ } else if (rv == 0) {
+ al = SSL_AD_DECODE_ERROR;
+ goto err;
+ }
+#ifdef SSL_DEBUG
+ fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
+#endif
+ } else if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
+ md = EVP_md5_sha1();
+ } else {
+ md = EVP_sha1();
+ }
+
+ if (!PACKET_get_length_prefixed_2(pkt, &signature)
+ || PACKET_remaining(pkt) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+ maxsig = EVP_PKEY_size(pkey);
+ if (maxsig < 0) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /*
+ * Check signature length
+ */
+ if (PACKET_remaining(&signature) > (size_t)maxsig) {
+ /* wrong packet length */
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+ SSL_R_WRONG_SIGNATURE_LENGTH);
+ goto err;
+ }
+
+ md_ctx = EVP_MD_CTX_new();
+ if (md_ctx == NULL) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (EVP_VerifyInit_ex(md_ctx, md, NULL) <= 0
+ || 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, PACKET_data(&params),
+ PACKET_remaining(&params)) <= 0) {
+ EVP_MD_CTX_free(md_ctx);
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
+ goto err;
+ }
+ if (EVP_VerifyFinal(md_ctx, PACKET_data(&signature),
+ PACKET_remaining(&signature), pkey) <= 0) {
+ /* bad signature */
+ EVP_MD_CTX_free(md_ctx);
+ al = SSL_AD_DECRYPT_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_SIGNATURE);
+ goto err;
+ }
+ EVP_MD_CTX_free(md_ctx);
+ } 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(s)) {
+ /* Otherwise this shouldn't happen */
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ } else {
+ al = SSL_AD_DECODE_ERROR;
+ }
+ goto err;
+ }
+ /* still data left over */
+ if (PACKET_remaining(pkt) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_EXTRA_DATA_IN_MESSAGE);
+ goto err;
+ }
+ }
+
+ return MSG_PROCESS_CONTINUE_READING;
+ err:
+ if (al != -1)
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ ossl_statem_set_error(s);
+ return MSG_PROCESS_ERROR;
+}
+
+MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
+{
+ int ret = MSG_PROCESS_ERROR;
+ unsigned int list_len, ctype_num, i, name_len;
+ X509_NAME *xn = NULL;
+ const unsigned char *data;
+ const unsigned char *namestart, *namebytes;
+ STACK_OF(X509_NAME) *ca_sk = NULL;
+
+ if ((ca_sk = sk_X509_NAME_new(ca_dn_cmp)) == NULL) {
+ SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* get the certificate types */
+ if (!PACKET_get_1(pkt, &ctype_num)
+ || !PACKET_get_bytes(pkt, &data, ctype_num)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+ OPENSSL_free(s->cert->ctypes);
+ s->cert->ctypes = NULL;
+ if (ctype_num > SSL3_CT_NUMBER) {
+ /* If we exceed static buffer copy all to cert structure */
+ s->cert->ctypes = OPENSSL_malloc(ctype_num);
+ if (s->cert->ctypes == NULL) {
+ SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ memcpy(s->cert->ctypes, data, ctype_num);
+ s->cert->ctype_num = (size_t)ctype_num;
+ ctype_num = SSL3_CT_NUMBER;
+ }
+ for (i = 0; i < ctype_num; i++)
+ s->s3->tmp.ctype[i] = data[i];
+
+ if (SSL_USE_SIGALGS(s)) {
+ if (!PACKET_get_net_2(pkt, &list_len)
+ || !PACKET_get_bytes(pkt, &data, list_len)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ /* Clear certificate digests and validity flags */
+ for (i = 0; i < SSL_PKEY_NUM; i++) {
+ s->s3->tmp.md[i] = NULL;
+ s->s3->tmp.valid_flags[i] = 0;
+ }
+ if ((list_len & 1) || !tls1_save_sigalgs(s, data, list_len)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+ SSL_R_SIGNATURE_ALGORITHMS_ERROR);
+ goto err;
+ }
+ if (!tls1_process_sigalgs(s)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ } else {
+ ssl_set_default_md(s);
+ }
+
+ /* get the CA RDNs */
+ if (!PACKET_get_net_2(pkt, &list_len)
+ || PACKET_remaining(pkt) != list_len) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ while (PACKET_remaining(pkt)) {
+ if (!PACKET_get_net_2(pkt, &name_len)
+ || !PACKET_get_bytes(pkt, &namebytes, name_len)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ namestart = namebytes;
+
+ if ((xn = d2i_X509_NAME(NULL, (const unsigned char **)&namebytes,
+ name_len)) == NULL) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_ASN1_LIB);
+ goto err;
+ }
+
+ if (namebytes != (namestart + name_len)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+ SSL_R_CA_DN_LENGTH_MISMATCH);
+ goto err;
+ }
+ if (!sk_X509_NAME_push(ca_sk, xn)) {
+ SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ xn = NULL;
+ }
+
+ /* we should setup a certificate to return.... */
+ s->s3->tmp.cert_req = 1;
+ s->s3->tmp.ctype_num = ctype_num;
+ sk_X509_NAME_pop_free(s->s3->tmp.ca_names, X509_NAME_free);
+ s->s3->tmp.ca_names = ca_sk;
+ ca_sk = NULL;
+
+ ret = MSG_PROCESS_CONTINUE_PROCESSING;
+ goto done;
+ err:
+ ossl_statem_set_error(s);
+ done:
+ X509_NAME_free(xn);
+ sk_X509_NAME_pop_free(ca_sk, X509_NAME_free);
+ return ret;
+}
+
+static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
+{
+ return (X509_NAME_cmp(*a, *b));
+}
+
+MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
+{
+ int al;
+ unsigned int ticklen;
+ unsigned long ticket_lifetime_hint;
+
+ if (!PACKET_get_net_4(pkt, &ticket_lifetime_hint)
+ || !PACKET_get_net_2(pkt, &ticklen)
+ || PACKET_remaining(pkt) != ticklen) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+
+ /* Server is allowed to change its mind and send an empty ticket. */
+ if (ticklen == 0)
+ return MSG_PROCESS_CONTINUE_READING;
+
+ if (s->session->session_id_length > 0) {
+ int i = s->session_ctx->session_cache_mode;
+ SSL_SESSION *new_sess;
+ /*
+ * We reused an existing session, so we need to replace it with a new
+ * one
+ */
+ if (i & SSL_SESS_CACHE_CLIENT) {
+ /*
+ * Remove the old session from the cache. We carry on if this fails
+ */
+ SSL_CTX_remove_session(s->session_ctx, s->session);
+ }
+
+ if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+
+ SSL_SESSION_free(s->session);
+ s->session = new_sess;
+ }
+
+ OPENSSL_free(s->session->tlsext_tick);
+ s->session->tlsext_ticklen = 0;
+
+ s->session->tlsext_tick = OPENSSL_malloc(ticklen);
+ if (s->session->tlsext_tick == NULL) {
+ SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!PACKET_copy_bytes(pkt, s->session->tlsext_tick, ticklen)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+
+ s->session->tlsext_tick_lifetime_hint = ticket_lifetime_hint;
+ s->session->tlsext_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.
+ */
+ if (!EVP_Digest(s->session->tlsext_tick, ticklen,
+ s->session->session_id, &s->session->session_id_length,
+ EVP_sha256(), NULL)) {
+ SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, ERR_R_EVP_LIB);
+ goto err;
+ }
+ return MSG_PROCESS_CONTINUE_READING;
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ err:
+ ossl_statem_set_error(s);
+ return MSG_PROCESS_ERROR;
+}
+
+MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt)
+{
+ int al;
+ unsigned long resplen;
+ unsigned int type;
+
+ if (!PACKET_get_1(pkt, &type)
+ || type != TLSEXT_STATUSTYPE_ocsp) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CERT_STATUS, SSL_R_UNSUPPORTED_STATUS_TYPE);
+ goto f_err;
+ }
+ if (!PACKET_get_net_3(pkt, &resplen)
+ || PACKET_remaining(pkt) != resplen) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CERT_STATUS, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ s->tlsext_ocsp_resp = OPENSSL_malloc(resplen);
+ if (s->tlsext_ocsp_resp == NULL) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CERT_STATUS, ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+ if (!PACKET_copy_bytes(pkt, s->tlsext_ocsp_resp, resplen)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CERT_STATUS, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ s->tlsext_ocsp_resplen = resplen;
+ return MSG_PROCESS_CONTINUE_READING;
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ ossl_statem_set_error(s);
+ return MSG_PROCESS_ERROR;
+}
+
+MSG_PROCESS_RETURN tls_process_server_done(SSL *s, PACKET *pkt)
+{
+ if (PACKET_remaining(pkt) > 0) {
+ /* should contain no data */
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_DONE, SSL_R_LENGTH_MISMATCH);
+ ossl_statem_set_error(s);
+ return MSG_PROCESS_ERROR;
+ }
+#ifndef OPENSSL_NO_SRP
+ if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
+ if (SRP_Calc_A_param(s) <= 0) {
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_DONE, SSL_R_SRP_A_CALC);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ ossl_statem_set_error(s);
+ return MSG_PROCESS_ERROR;
+ }
+ }
+#endif
+
+ /*
+ * at this point we check that we have the required stuff from
+ * the server
+ */
+ if (!ssl3_check_cert_and_algorithm(s)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ ossl_statem_set_error(s);
+ return MSG_PROCESS_ERROR;
+ }
+
+ /*
+ * Call the ocsp status callback if needed. The |tlsext_ocsp_resp| and
+ * |tlsext_ocsp_resplen| values will be set if we actually received a status
+ * message, or NULL and -1 otherwise
+ */
+ if (s->tlsext_status_type != -1 && s->ctx->tlsext_status_cb != NULL) {
+ int ret;
+ ret = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
+ if (ret == 0) {
+ ssl3_send_alert(s, SSL3_AL_FATAL,
+ SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_DONE,
+ SSL_R_INVALID_STATUS_RESPONSE);
+ return MSG_PROCESS_ERROR;
+ }
+ if (ret < 0) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_DONE, ERR_R_MALLOC_FAILURE);
+ return MSG_PROCESS_ERROR;
+ }
+ }
+#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)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ return MSG_PROCESS_ERROR;
+ }
+ }
+#endif
+
+ return MSG_PROCESS_FINISHED_READING;
+}
+
+static int tls_construct_cke_psk_preamble(SSL *s, unsigned char **p,
+ size_t *pskhdrlen, int *al)
+{
+#ifndef OPENSSL_NO_PSK
+ int ret = 0;
+ /*
+ * The callback needs PSK_MAX_IDENTITY_LEN + 1 bytes to return a
+ * \0-terminated identity. The last byte is for us for simulating
+ * strnlen.
+ */
+ char identity[PSK_MAX_IDENTITY_LEN + 1];
+ size_t identitylen = 0;
+ unsigned char psk[PSK_MAX_PSK_LEN];
+ unsigned char *tmppsk = NULL;
+ char *tmpidentity = NULL;
+ size_t psklen = 0;
+
+ if (s->psk_client_callback == NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, SSL_R_PSK_NO_CLIENT_CB);
+ *al = SSL_AD_INTERNAL_ERROR;
+ goto err;
+ }
+
+ memset(identity, 0, sizeof(identity));
+
+ psklen = s->psk_client_callback(s, s->session->psk_identity_hint,
+ identity, sizeof(identity) - 1,
+ psk, sizeof(psk));
+
+ if (psklen > PSK_MAX_PSK_LEN) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ goto err;
+ } else if (psklen == 0) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
+ SSL_R_PSK_IDENTITY_NOT_FOUND);
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ goto err;
+ }
+
+ identitylen = strlen(identity);
+ if (identitylen > PSK_MAX_IDENTITY_LEN) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ goto err;
+ }
+
+ tmppsk = OPENSSL_memdup(psk, psklen);
+ tmpidentity = OPENSSL_strdup(identity);
+ if (tmppsk == NULL || tmpidentity == NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_MALLOC_FAILURE);
+ *al = SSL_AD_INTERNAL_ERROR;
+ goto err;
+ }
+
+ OPENSSL_free(s->s3->tmp.psk);
+ s->s3->tmp.psk = tmppsk;
+ s->s3->tmp.psklen = psklen;
+ tmppsk = NULL;
+ OPENSSL_free(s->session->psk_identity);
+ s->session->psk_identity = tmpidentity;
+ tmpidentity = NULL;
+ s2n(identitylen, *p);
+ memcpy(*p, identity, identitylen);
+ *pskhdrlen = 2 + identitylen;
+ *p += identitylen;
+
+ ret = 1;
+
+ err:
+ OPENSSL_cleanse(psk, psklen);
+ OPENSSL_cleanse(identity, sizeof(identity));
+ OPENSSL_clear_free(tmppsk, psklen);
+ OPENSSL_clear_free(tmpidentity, identitylen);
+
+ return ret;
+#else
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+#endif
+}
+
+static int tls_construct_cke_rsa(SSL *s, unsigned char **p, int *len, int *al)
+{
+#ifndef OPENSSL_NO_RSA
+ unsigned char *q;
+ 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.
+ */
+ SSLerr(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) {
+ SSLerr(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) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_MALLOC_FAILURE);
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+
+ pms[0] = s->client_version >> 8;
+ pms[1] = s->client_version & 0xff;
+ if (RAND_bytes(pms + 2, pmslen - 2) <= 0) {
+ goto err;
+ }
+
+ q = *p;
+ /* Fix buf for TLS and beyond */
+ if (s->version > SSL3_VERSION)
+ *p += 2;
+ 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) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_EVP_LIB);
+ goto err;
+ }
+ if (EVP_PKEY_encrypt(pctx, *p, &enclen, pms, pmslen) <= 0) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, SSL_R_BAD_RSA_ENCRYPT);
+ goto err;
+ }
+ *len = enclen;
+ EVP_PKEY_CTX_free(pctx);
+ pctx = NULL;
+# ifdef PKCS1_CHECK
+ if (s->options & SSL_OP_PKCS1_CHECK_1)
+ (*p)[1]++;
+ if (s->options & SSL_OP_PKCS1_CHECK_2)
+ tmp_buf[0] = 0x70;
+# endif
+
+ /* Fix buf for TLS and beyond */
+ if (s->version > SSL3_VERSION) {
+ s2n(*len, q);
+ *len += 2;
+ }
+
+ 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
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR);
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+#endif
+}
+
+static int tls_construct_cke_dhe(SSL *s, unsigned char **p, int *len, int *al)
+{
+#ifndef OPENSSL_NO_DH
+ DH *dh_clnt = NULL;
+ const BIGNUM *pub_key;
+ EVP_PKEY *ckey = NULL, *skey = NULL;
+
+ skey = s->s3->peer_tmp;
+ if (skey == NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_DHE, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ ckey = ssl_generate_pkey(skey);
+ if (ckey == NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_DHE, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ dh_clnt = EVP_PKEY_get0_DH(ckey);
+
+ if (dh_clnt == NULL || ssl_derive(s, ckey, skey) == 0) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_DHE, ERR_R_INTERNAL_ERROR);
+ EVP_PKEY_free(ckey);
+ return 0;
+ }
+
+ /* send off the data */
+ DH_get0_key(dh_clnt, &pub_key, NULL);
+ *len = BN_num_bytes(pub_key);
+ s2n(*len, *p);
+ BN_bn2bin(pub_key, *p);
+ *len += 2;
+ EVP_PKEY_free(ckey);
+
+ return 1;
+#else
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_DHE, ERR_R_INTERNAL_ERROR);
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+#endif
+}
+
+static int tls_construct_cke_ecdhe(SSL *s, unsigned char **p, int *len, int *al)
+{
+#ifndef OPENSSL_NO_EC
+ unsigned char *encodedPoint = NULL;
+ int encoded_pt_len = 0;
+ EVP_PKEY *ckey = NULL, *skey = NULL;
+
+ skey = s->s3->peer_tmp;
+ if (skey == NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ ckey = ssl_generate_pkey(skey);
+ if (ckey == NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (ssl_derive(s, ckey, skey) == 0) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_EVP_LIB);
+ goto err;
+ }
+
+ /* Generate encoding of client key */
+ encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(ckey, &encodedPoint);
+
+ if (encoded_pt_len == 0) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_EC_LIB);
+ goto err;
+ }
+
+ EVP_PKEY_free(ckey);
+ ckey = NULL;
+
+ *len = encoded_pt_len;
+
+ /* length of encoded point */
+ **p = *len;
+ *p += 1;
+ /* copy the point */
+ memcpy(*p, encodedPoint, *len);
+ /* increment len to account for length field */
+ *len += 1;
+
+ OPENSSL_free(encodedPoint);
+
+ return 1;
+ err:
+ EVP_PKEY_free(ckey);
+ return 0;
+#else
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_INTERNAL_ERROR);
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+#endif
+}
+
+static int tls_construct_cke_gost(SSL *s, unsigned char **p, int *len, int *al)
+{
+#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) {
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(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) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(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) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0
+ /* Generate session key */
+ || RAND_bytes(pms, pmslen) <= 0) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(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) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(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) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, SSL_R_LIBRARY_BUG);
+ goto err;
+ }
+ /* Make GOST keytransport blob message */
+ /*
+ * Encapsulate it into sequence
+ */
+ *((*p)++) = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
+ msglen = 255;
+ if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) <= 0) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, SSL_R_LIBRARY_BUG);
+ goto err;
+ }
+ if (msglen >= 0x80) {
+ *((*p)++) = 0x81;
+ *((*p)++) = msglen & 0xff;
+ *len = msglen + 3;
+ } else {
+ *((*p)++) = msglen & 0xff;
+ *len = msglen + 2;
+ }
+ memcpy(*p, tmp, msglen);
+
+ 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
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_INTERNAL_ERROR);
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+#endif
+}
+
+static int tls_construct_cke_srp(SSL *s, unsigned char **p, int *len, int *al)
+{
+#ifndef OPENSSL_NO_SRP
+ if (s->srp_ctx.A != NULL) {
+ /* send off the data */
+ *len = BN_num_bytes(s->srp_ctx.A);
+ s2n(*len, *p);
+ BN_bn2bin(s->srp_ctx.A, *p);
+ *len += 2;
+ } else {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_SRP, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ OPENSSL_free(s->session->srp_username);
+ s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login);
+ if (s->session->srp_username == NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_SRP, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ return 1;
+#else
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_SRP, ERR_R_INTERNAL_ERROR);
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+#endif
+}
+
+int tls_construct_client_key_exchange(SSL *s)
+{
+ unsigned char *p;
+ int len;
+ size_t pskhdrlen = 0;
+ unsigned long alg_k;
+ int al = -1;
+
+ alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+
+ p = ssl_handshake_start(s);
+
+ if ((alg_k & SSL_PSK)
+ && !tls_construct_cke_psk_preamble(s, &p, &pskhdrlen, &al))
+ goto err;
+
+ if (alg_k & SSL_kPSK) {
+ len = 0;
+ } else if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
+ if (!tls_construct_cke_rsa(s, &p, &len, &al))
+ goto err;
+ } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
+ if (!tls_construct_cke_dhe(s, &p, &len, &al))
+ goto err;
+ } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
+ if (!tls_construct_cke_ecdhe(s, &p, &len, &al))
+ goto err;
+ } else if (alg_k & SSL_kGOST) {
+ if (!tls_construct_cke_gost(s, &p, &len, &al))
+ goto err;
+ } else if (alg_k & SSL_kSRP) {
+ if (!tls_construct_cke_srp(s, &p, &len, &al))
+ goto err;
+ } else {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ len += pskhdrlen;
+
+ if (!ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, len)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ return 1;
+ err:
+ if (al != -1)
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen);
+ s->s3->tmp.pms = NULL;
+#ifndef OPENSSL_NO_PSK
+ OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
+ s->s3->tmp.psk = NULL;
+#endif
+ ossl_statem_set_error(s);
+ return 0;
+}
+
+int tls_client_key_exchange_post_work(SSL *s)
+{
+ unsigned char *pms = NULL;
+ size_t pmslen = 0;
+
+ pms = s->s3->tmp.pms;
+ pmslen = s->s3->tmp.pmslen;
+
+#ifndef OPENSSL_NO_SRP
+ /* Check for SRP */
+ if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
+ if (!srp_generate_client_master_secret(s)) {
+ SSLerr(SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ return 1;
+ }
+#endif
+
+ if (pms == NULL && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!ssl_generate_master_secret(s, pms, pmslen, 1)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK, ERR_R_INTERNAL_ERROR);
+ /* ssl_generate_master_secret frees the pms even on error */
+ pms = NULL;
+ pmslen = 0;
+ goto err;
+ }
+ pms = NULL;
+ pmslen = 0;
+
+#ifndef OPENSSL_NO_SCTP
+ if (SSL_IS_DTLS(s)) {
+ unsigned char sctpauthkey[64];
+ char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
+
+ /*
+ * Add new shared key for SCTP-Auth, will be ignored if no SCTP
+ * used.
+ */
+ memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
+ sizeof(DTLS1_SCTP_AUTH_LABEL));
+
+ if (SSL_export_keying_material(s, sctpauthkey,
+ sizeof(sctpauthkey), labelbuffer,
+ sizeof(labelbuffer), NULL, 0, 0) <= 0)
+ goto err;
+
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
+ sizeof(sctpauthkey), sctpauthkey);
+ }
+#endif
+
+ return 1;
+ err:
+ OPENSSL_clear_free(pms, pmslen);
+ s->s3->tmp.pms = NULL;
+ return 0;
+}
+
+int tls_construct_client_verify(SSL *s)
+{
+ unsigned char *p;
+ EVP_PKEY *pkey;
+ const EVP_MD *md = s->s3->tmp.md[s->cert->key - s->cert->pkeys];
+ EVP_MD_CTX *mctx;
+ unsigned u = 0;
+ unsigned long n = 0;
+ long hdatalen = 0;
+ void *hdata;
+
+ mctx = EVP_MD_CTX_new();
+ if (mctx == NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ p = ssl_handshake_start(s);
+ pkey = s->cert->key->privatekey;
+
+ hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
+ if (hdatalen <= 0) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ if (SSL_USE_SIGALGS(s)) {
+ if (!tls12_get_sigandhash(p, pkey, md)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ p += 2;
+ n = 2;
+ }
+#ifdef SSL_DEBUG
+ fprintf(stderr, "Using client alg %s\n", EVP_MD_name(md));
+#endif
+ if (!EVP_SignInit_ex(mctx, md, NULL)
+ || !EVP_SignUpdate(mctx, hdata, hdatalen)
+ || (s->version == SSL3_VERSION
+ && !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
+ s->session->master_key_length,
+ s->session->master_key))
+ || !EVP_SignFinal(mctx, p + 2, &u, pkey)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, 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)
+ BUF_reverse(p + 2, NULL, u);
+ }
+#endif
+
+ s2n(u, p);
+ n += u + 2;
+ /* Digest cached records and discard handshake buffer */
+ if (!ssl3_digest_cached_records(s, 0))
+ goto err;
+ if (!ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ EVP_MD_CTX_free(mctx);
+ return 1;
+ err:
+ EVP_MD_CTX_free(mctx);
+ 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 (!s->cert || !s->cert->key->x509 || !s->cert->key->privatekey)
+ return 0;
+ /* If no suitable signature algorithm can't use certificate */
+ if (SSL_USE_SIGALGS(s) && !s->s3->tmp.md[s->cert->key - s->cert->pkeys])
+ 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(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) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ ossl_statem_set_error(s);
+ return 0;
+ }
+ s->rwstate = SSL_NOTHING;
+ }
+ if (ssl3_check_client_certificate(s))
+ 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(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,
+ SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
+ }
+
+ X509_free(x509);
+ EVP_PKEY_free(pkey);
+ if (i && !ssl3_check_client_certificate(s))
+ i = 0;
+ if (i == 0) {
+ if (s->version == SSL3_VERSION) {
+ s->s3->tmp.cert_req = 0;
+ ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_CERTIFICATE);
+ return WORK_FINISHED_CONTINUE;
+ } else {
+ s->s3->tmp.cert_req = 2;
+ if (!ssl3_digest_cached_records(s, 0)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ ossl_statem_set_error(s);
+ return 0;
+ }
+ }
+ }
+
+ return WORK_FINISHED_CONTINUE;
+ }
+
+ /* Shouldn't ever get here */
+ return WORK_ERROR;
+}
+
+int tls_construct_client_certificate(SSL *s)
+{
+ if (!ssl3_output_cert_chain(s,
+ (s->s3->tmp.cert_req ==
+ 2) ? NULL : s->cert->key)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ ossl_statem_set_error(s);
+ return 0;
+ }
+
+ return 1;
+}
+
+#define has_bits(i,m) (((i)&(m)) == (m))
+
+int ssl3_check_cert_and_algorithm(SSL *s)
+{
+ int i;
+#ifndef OPENSSL_NO_EC
+ int idx;
+#endif
+ long alg_k, alg_a;
+ EVP_PKEY *pkey = NULL;
+ int al = SSL_AD_HANDSHAKE_FAILURE;
+
+ 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_aNULL) || (alg_k & SSL_kPSK))
+ return (1);
+
+ /* This is the passed certificate */
+
+#ifndef OPENSSL_NO_EC
+ idx = s->session->peer_type;
+ if (idx == SSL_PKEY_ECC) {
+ if (ssl_check_srvr_ecc_cert_and_alg(s->session->peer, s) == 0) {
+ /* check failed */
+ SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_BAD_ECC_CERT);
+ goto f_err;
+ } else {
+ return 1;
+ }
+ } else if (alg_a & SSL_aECDSA) {
+ SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+ SSL_R_MISSING_ECDSA_SIGNING_CERT);
+ goto f_err;
+ }
+#endif
+ pkey = X509_get0_pubkey(s->session->peer);
+ i = X509_certificate_type(s->session->peer, pkey);
+
+ /* Check that we have a certificate if we require one */
+ if ((alg_a & SSL_aRSA) && !has_bits(i, EVP_PK_RSA | EVP_PKT_SIGN)) {
+ SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+ SSL_R_MISSING_RSA_SIGNING_CERT);
+ goto f_err;
+ }
+#ifndef OPENSSL_NO_DSA
+ else if ((alg_a & SSL_aDSS) && !has_bits(i, EVP_PK_DSA | EVP_PKT_SIGN)) {
+ SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+ SSL_R_MISSING_DSA_SIGNING_CERT);
+ goto f_err;
+ }
+#endif
+#ifndef OPENSSL_NO_RSA
+ if (alg_k & (SSL_kRSA | SSL_kRSAPSK) &&
+ !has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) {
+ SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+ SSL_R_MISSING_RSA_ENCRYPTING_CERT);
+ goto f_err;
+ }
+#endif
+#ifndef OPENSSL_NO_DH
+ if ((alg_k & SSL_kDHE) && (s->s3->peer_tmp == NULL)) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
+#endif
+
+ return (1);
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ return (0);
+}
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+int tls_construct_next_proto(SSL *s)
+{
+ unsigned int len, padding_len;
+ unsigned char *d;
+
+ len = s->next_proto_negotiated_len;
+ padding_len = 32 - ((len + 2) % 32);
+ d = (unsigned char *)s->init_buf->data;
+ d[4] = len;
+ memcpy(d + 5, s->next_proto_negotiated, len);
+ d[5 + len] = padding_len;
+ memset(d + 6 + len, 0, padding_len);
+ *(d++) = SSL3_MT_NEXT_PROTO;
+ l2n3(2 + len + padding_len, d);
+ s->init_num = 4 + 2 + len + padding_len;
+ s->init_off = 0;
+
+ return 1;
+}
+#endif
+
+int ssl_do_client_cert_cb(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, unsigned char *p)
+{
+ int i, j = 0;
+ const SSL_CIPHER *c;
+ unsigned char *q;
+ int empty_reneg_info_scsv = !s->renegotiate;
+ /* Set disabled masks for this session */
+ ssl_set_client_disabled(s);
+
+ if (sk == NULL)
+ return (0);
+ q = p;
+
+ for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
+ c = sk_SSL_CIPHER_value(sk, i);
+ /* Skip disabled ciphers */
+ if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0))
+ continue;
+ j = s->method->put_cipher_by_char(c, p);
+ p += j;
+ }
+ /*
+ * If p == q, no ciphers; caller indicates an error. Otherwise, add
+ * applicable SCSVs.
+ */
+ if (p != q) {
+ if (empty_reneg_info_scsv) {
+ static SSL_CIPHER scsv = {
+ 0, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ j = s->method->put_cipher_by_char(&scsv, p);
+ p += j;
+ }
+ if (s->mode & SSL_MODE_SEND_FALLBACK_SCSV) {
+ static SSL_CIPHER scsv = {
+ 0, NULL, SSL3_CK_FALLBACK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ j = s->method->put_cipher_by_char(&scsv, p);
+ p += j;
+ }
+ }
+
+ return (p - q);
+}
diff --git a/openssl-1.1.0h/ssl/statem/statem_dtls.c b/openssl-1.1.0h/ssl/statem/statem_dtls.c
new file mode 100644
index 0000000..6b80620
--- /dev/null
+++ b/openssl-1.1.0h/ssl/statem/statem_dtls.c
@@ -0,0 +1,1220 @@
+/*
+ * Copyright 2005-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
+ */
+
+#include <limits.h>
+#include <string.h>
+#include <stdio.h>
+#include "../ssl_locl.h"
+#include "statem_locl.h"
+#include <openssl/buffer.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
+#define RSMBLY_BITMASK_SIZE(msg_len) (((msg_len) + 7) / 8)
+
+#define RSMBLY_BITMASK_MARK(bitmask, start, end) { \
+ if ((end) - (start) <= 8) { \
+ long ii; \
+ for (ii = (start); ii < (end); ii++) bitmask[((ii) >> 3)] |= (1 << ((ii) & 7)); \
+ } else { \
+ long ii; \
+ bitmask[((start) >> 3)] |= bitmask_start_values[((start) & 7)]; \
+ for (ii = (((start) >> 3) + 1); ii < ((((end) - 1)) >> 3); ii++) bitmask[ii] = 0xff; \
+ bitmask[(((end) - 1) >> 3)] |= bitmask_end_values[((end) & 7)]; \
+ } }
+
+#define RSMBLY_BITMASK_IS_COMPLETE(bitmask, msg_len, is_complete) { \
+ long ii; \
+ OPENSSL_assert((msg_len) > 0); \
+ is_complete = 1; \
+ if (bitmask[(((msg_len) - 1) >> 3)] != bitmask_end_values[((msg_len) & 7)]) is_complete = 0; \
+ if (is_complete) for (ii = (((msg_len) - 1) >> 3) - 1; ii >= 0 ; ii--) \
+ if (bitmask[ii] != 0xff) { is_complete = 0; break; } }
+
+static unsigned char bitmask_start_values[] =
+ { 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80 };
+static unsigned char bitmask_end_values[] =
+ { 0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f };
+
+static void dtls1_fix_message_header(SSL *s, unsigned long frag_off,
+ unsigned long frag_len);
+static unsigned char *dtls1_write_message_header(SSL *s, unsigned char *p);
+static void dtls1_set_message_header_int(SSL *s, unsigned char mt,
+ unsigned long len,
+ unsigned short seq_num,
+ unsigned long frag_off,
+ unsigned long frag_len);
+static int dtls_get_reassembled_message(SSL *s, long *len);
+
+static hm_fragment *dtls1_hm_fragment_new(unsigned long frag_len,
+ int reassembly)
+{
+ hm_fragment *frag = NULL;
+ unsigned char *buf = NULL;
+ unsigned char *bitmask = NULL;
+
+ frag = OPENSSL_malloc(sizeof(*frag));
+ if (frag == NULL)
+ return NULL;
+
+ if (frag_len) {
+ buf = OPENSSL_malloc(frag_len);
+ if (buf == NULL) {
+ OPENSSL_free(frag);
+ return NULL;
+ }
+ }
+
+ /* zero length fragment gets zero frag->fragment */
+ frag->fragment = buf;
+
+ /* Initialize reassembly bitmask if necessary */
+ if (reassembly) {
+ bitmask = OPENSSL_zalloc(RSMBLY_BITMASK_SIZE(frag_len));
+ if (bitmask == NULL) {
+ OPENSSL_free(buf);
+ OPENSSL_free(frag);
+ return NULL;
+ }
+ }
+
+ frag->reassembly = bitmask;
+
+ return frag;
+}
+
+void dtls1_hm_fragment_free(hm_fragment *frag)
+{
+ if (!frag)
+ return;
+ if (frag->msg_header.is_ccs) {
+ EVP_CIPHER_CTX_free(frag->msg_header.
+ saved_retransmit_state.enc_write_ctx);
+ EVP_MD_CTX_free(frag->msg_header.saved_retransmit_state.write_hash);
+ }
+ OPENSSL_free(frag->fragment);
+ OPENSSL_free(frag->reassembly);
+ OPENSSL_free(frag);
+}
+
+/*
+ * send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or
+ * SSL3_RT_CHANGE_CIPHER_SPEC)
+ */
+int dtls1_do_write(SSL *s, int type)
+{
+ int ret;
+ unsigned int curr_mtu;
+ int retry = 1;
+ unsigned int len, frag_off, mac_size, blocksize, used_len;
+
+ if (!dtls1_query_mtu(s))
+ return -1;
+
+ if (s->d1->mtu < dtls1_min_mtu(s))
+ /* should have something reasonable now */
+ return -1;
+
+ if (s->init_off == 0 && type == SSL3_RT_HANDSHAKE)
+ OPENSSL_assert(s->init_num ==
+ (int)s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH);
+
+ if (s->write_hash) {
+ if (s->enc_write_ctx
+ && (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx)) &
+ EVP_CIPH_FLAG_AEAD_CIPHER) != 0)
+ mac_size = 0;
+ else
+ mac_size = EVP_MD_CTX_size(s->write_hash);
+ } else
+ mac_size = 0;
+
+ if (s->enc_write_ctx &&
+ (EVP_CIPHER_CTX_mode(s->enc_write_ctx) == EVP_CIPH_CBC_MODE))
+ blocksize = 2 * EVP_CIPHER_CTX_block_size(s->enc_write_ctx);
+ else
+ blocksize = 0;
+
+ frag_off = 0;
+ s->rwstate = SSL_NOTHING;
+
+ /* s->init_num shouldn't ever be < 0...but just in case */
+ while (s->init_num > 0) {
+ if (type == SSL3_RT_HANDSHAKE && s->init_off != 0) {
+ /* We must be writing a fragment other than the first one */
+
+ if (frag_off > 0) {
+ /* This is the first attempt at writing out this fragment */
+
+ if (s->init_off <= DTLS1_HM_HEADER_LENGTH) {
+ /*
+ * Each fragment that was already sent must at least have
+ * contained the message header plus one other byte.
+ * Therefore |init_off| must have progressed by at least
+ * |DTLS1_HM_HEADER_LENGTH + 1| bytes. If not something went
+ * wrong.
+ */
+ return -1;
+ }
+
+ /*
+ * Adjust |init_off| and |init_num| to allow room for a new
+ * message header for this fragment.
+ */
+ s->init_off -= DTLS1_HM_HEADER_LENGTH;
+ s->init_num += DTLS1_HM_HEADER_LENGTH;
+ } else {
+ /*
+ * We must have been called again after a retry so use the
+ * fragment offset from our last attempt. We do not need
+ * to adjust |init_off| and |init_num| as above, because
+ * that should already have been done before the retry.
+ */
+ frag_off = s->d1->w_msg_hdr.frag_off;
+ }
+ }
+
+ used_len = BIO_wpending(s->wbio) + DTLS1_RT_HEADER_LENGTH
+ + mac_size + blocksize;
+ if (s->d1->mtu > used_len)
+ curr_mtu = s->d1->mtu - used_len;
+ else
+ curr_mtu = 0;
+
+ if (curr_mtu <= DTLS1_HM_HEADER_LENGTH) {
+ /*
+ * grr.. we could get an error if MTU picked was wrong
+ */
+ ret = BIO_flush(s->wbio);
+ if (ret <= 0) {
+ s->rwstate = SSL_WRITING;
+ return ret;
+ }
+ used_len = DTLS1_RT_HEADER_LENGTH + mac_size + blocksize;
+ if (s->d1->mtu > used_len + DTLS1_HM_HEADER_LENGTH) {
+ curr_mtu = s->d1->mtu - used_len;
+ } else {
+ /* Shouldn't happen */
+ return -1;
+ }
+ }
+
+ /*
+ * We just checked that s->init_num > 0 so this cast should be safe
+ */
+ if (((unsigned int)s->init_num) > curr_mtu)
+ len = curr_mtu;
+ else
+ len = s->init_num;
+
+ if (len > s->max_send_fragment)
+ len = s->max_send_fragment;
+
+ /*
+ * XDTLS: this function is too long. split out the CCS part
+ */
+ if (type == SSL3_RT_HANDSHAKE) {
+ if (len < DTLS1_HM_HEADER_LENGTH) {
+ /*
+ * len is so small that we really can't do anything sensible
+ * so fail
+ */
+ return -1;
+ }
+ dtls1_fix_message_header(s, frag_off, len - DTLS1_HM_HEADER_LENGTH);
+
+ dtls1_write_message_header(s,
+ (unsigned char *)&s->init_buf->
+ data[s->init_off]);
+ }
+
+ ret = dtls1_write_bytes(s, type, &s->init_buf->data[s->init_off], len);
+ if (ret < 0) {
+ /*
+ * might need to update MTU here, but we don't know which
+ * previous packet caused the failure -- so can't really
+ * retransmit anything. continue as if everything is fine and
+ * wait for an alert to handle the retransmit
+ */
+ if (retry && BIO_ctrl(SSL_get_wbio(s),
+ BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0) {
+ if (!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
+ if (!dtls1_query_mtu(s))
+ return -1;
+ /* Have one more go */
+ retry = 0;
+ } else
+ return -1;
+ } else {
+ return (-1);
+ }
+ } else {
+
+ /*
+ * bad if this assert fails, only part of the handshake message
+ * got sent. but why would this happen?
+ */
+ OPENSSL_assert(len == (unsigned int)ret);
+
+ if (type == SSL3_RT_HANDSHAKE && !s->d1->retransmitting) {
+ /*
+ * should not be done for 'Hello Request's, but in that case
+ * we'll ignore the result anyway
+ */
+ unsigned char *p =
+ (unsigned char *)&s->init_buf->data[s->init_off];
+ const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+ int xlen;
+
+ if (frag_off == 0 && s->version != DTLS1_BAD_VER) {
+ /*
+ * reconstruct message header is if it is being sent in
+ * single fragment
+ */
+ *p++ = msg_hdr->type;
+ l2n3(msg_hdr->msg_len, p);
+ s2n(msg_hdr->seq, p);
+ l2n3(0, p);
+ l2n3(msg_hdr->msg_len, p);
+ p -= DTLS1_HM_HEADER_LENGTH;
+ xlen = ret;
+ } else {
+ p += DTLS1_HM_HEADER_LENGTH;
+ xlen = ret - DTLS1_HM_HEADER_LENGTH;
+ }
+
+ if (!ssl3_finish_mac(s, p, xlen))
+ return -1;
+ }
+
+ if (ret == 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);
+
+ s->init_off = 0; /* done writing this message */
+ s->init_num = 0;
+
+ return (1);
+ }
+ s->init_off += ret;
+ s->init_num -= ret;
+ ret -= DTLS1_HM_HEADER_LENGTH;
+ frag_off += ret;
+
+ /*
+ * We save the fragment offset for the next fragment so we have it
+ * available in case of an IO retry. We don't know the length of the
+ * next fragment yet so just set that to 0 for now. It will be
+ * updated again later.
+ */
+ dtls1_fix_message_header(s, frag_off, 0);
+ }
+ }
+ return (0);
+}
+
+int dtls_get_message(SSL *s, int *mt, unsigned long *len)
+{
+ struct hm_header_st *msg_hdr;
+ unsigned char *p;
+ unsigned long msg_len;
+ int ok;
+ long tmplen;
+
+ msg_hdr = &s->d1->r_msg_hdr;
+ memset(msg_hdr, 0, sizeof(*msg_hdr));
+
+ again:
+ ok = dtls_get_reassembled_message(s, &tmplen);
+ if (tmplen == DTLS1_HM_BAD_FRAGMENT || tmplen == DTLS1_HM_FRAGMENT_RETRY) {
+ /* bad fragment received */
+ goto again;
+ } else if (tmplen <= 0 && !ok) {
+ return 0;
+ }
+
+ *mt = s->s3->tmp.message_type;
+
+ p = (unsigned char *)s->init_buf->data;
+
+ if (*mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ if (s->msg_callback) {
+ s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC,
+ p, 1, s, s->msg_callback_arg);
+ }
+ /*
+ * This isn't a real handshake message so skip the processing below.
+ */
+ *len = (unsigned long)tmplen;
+ return 1;
+ }
+
+ msg_len = msg_hdr->msg_len;
+
+ /* reconstruct message header */
+ *(p++) = msg_hdr->type;
+ l2n3(msg_len, p);
+ s2n(msg_hdr->seq, p);
+ l2n3(0, p);
+ l2n3(msg_len, p);
+ if (s->version != DTLS1_BAD_VER) {
+ p -= DTLS1_HM_HEADER_LENGTH;
+ msg_len += DTLS1_HM_HEADER_LENGTH;
+ }
+
+ /*
+ * If receiving Finished, record MAC of prior handshake messages for
+ * Finished verification.
+ */
+ if (*mt == SSL3_MT_FINISHED && !ssl3_take_mac(s)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ if (!ssl3_finish_mac(s, p, msg_len))
+ return 0;
+ if (s->msg_callback)
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
+ p, msg_len, s, s->msg_callback_arg);
+
+ memset(msg_hdr, 0, sizeof(*msg_hdr));
+
+ s->d1->handshake_read_seq++;
+
+ s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
+ *len = s->init_num;
+
+ return 1;
+}
+
+/*
+ * dtls1_max_handshake_message_len returns the maximum number of bytes
+ * permitted in a DTLS handshake message for |s|. The minimum is 16KB, but
+ * may be greater if the maximum certificate list size requires it.
+ */
+static unsigned long dtls1_max_handshake_message_len(const SSL *s)
+{
+ unsigned long max_len =
+ DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
+ if (max_len < (unsigned long)s->max_cert_list)
+ return s->max_cert_list;
+ return max_len;
+}
+
+static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr)
+{
+ size_t frag_off, frag_len, msg_len;
+
+ msg_len = msg_hdr->msg_len;
+ frag_off = msg_hdr->frag_off;
+ frag_len = msg_hdr->frag_len;
+
+ /* sanity checking */
+ if ((frag_off + frag_len) > msg_len
+ || msg_len > dtls1_max_handshake_message_len(s)) {
+ SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ return SSL_AD_ILLEGAL_PARAMETER;
+ }
+
+ if (s->d1->r_msg_hdr.frag_off == 0) { /* first fragment */
+ /*
+ * msg_len is limited to 2^24, but is effectively checked against
+ * dtls_max_handshake_message_len(s) above
+ */
+ if (!BUF_MEM_grow_clean(s->init_buf, msg_len + DTLS1_HM_HEADER_LENGTH)) {
+ SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, ERR_R_BUF_LIB);
+ return SSL_AD_INTERNAL_ERROR;
+ }
+
+ s->s3->tmp.message_size = msg_len;
+ s->d1->r_msg_hdr.msg_len = msg_len;
+ s->s3->tmp.message_type = msg_hdr->type;
+ s->d1->r_msg_hdr.type = msg_hdr->type;
+ s->d1->r_msg_hdr.seq = msg_hdr->seq;
+ } else if (msg_len != s->d1->r_msg_hdr.msg_len) {
+ /*
+ * They must be playing with us! BTW, failure to enforce upper limit
+ * would open possibility for buffer overrun.
+ */
+ SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ return SSL_AD_ILLEGAL_PARAMETER;
+ }
+
+ return 0; /* no error */
+}
+
+static int dtls1_retrieve_buffered_fragment(SSL *s, int *ok)
+{
+ /*-
+ * (0) check whether the desired fragment is available
+ * if so:
+ * (1) copy over the fragment to s->init_buf->data[]
+ * (2) update s->init_num
+ */
+ pitem *item;
+ hm_fragment *frag;
+ int al;
+
+ *ok = 0;
+
+ do {
+ item = pqueue_peek(s->d1->buffered_messages);
+ if (item == NULL)
+ return 0;
+
+ frag = (hm_fragment *)item->data;
+
+ if (frag->msg_header.seq < s->d1->handshake_read_seq) {
+ /* This is a stale message that has been buffered so clear it */
+ pqueue_pop(s->d1->buffered_messages);
+ dtls1_hm_fragment_free(frag);
+ pitem_free(item);
+ item = NULL;
+ frag = NULL;
+ }
+ } while (item == NULL);
+
+ /* Don't return if reassembly still in progress */
+ if (frag->reassembly != NULL)
+ return 0;
+
+ if (s->d1->handshake_read_seq == frag->msg_header.seq) {
+ unsigned long frag_len = frag->msg_header.frag_len;
+ pqueue_pop(s->d1->buffered_messages);
+
+ al = dtls1_preprocess_fragment(s, &frag->msg_header);
+
+ if (al == 0) { /* no alert */
+ unsigned char *p =
+ (unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
+ memcpy(&p[frag->msg_header.frag_off], frag->fragment,
+ frag->msg_header.frag_len);
+ }
+
+ dtls1_hm_fragment_free(frag);
+ pitem_free(item);
+
+ if (al == 0) {
+ *ok = 1;
+ return frag_len;
+ }
+
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ s->init_num = 0;
+ *ok = 0;
+ return -1;
+ } else
+ return 0;
+}
+
+static int
+dtls1_reassemble_fragment(SSL *s, const struct hm_header_st *msg_hdr, int *ok)
+{
+ hm_fragment *frag = NULL;
+ pitem *item = NULL;
+ int i = -1, is_complete;
+ unsigned char seq64be[8];
+ unsigned long frag_len = msg_hdr->frag_len;
+
+ if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len ||
+ msg_hdr->msg_len > dtls1_max_handshake_message_len(s))
+ goto err;
+
+ if (frag_len == 0)
+ return DTLS1_HM_FRAGMENT_RETRY;
+
+ /* Try to find item in queue */
+ memset(seq64be, 0, sizeof(seq64be));
+ seq64be[6] = (unsigned char)(msg_hdr->seq >> 8);
+ seq64be[7] = (unsigned char)msg_hdr->seq;
+ item = pqueue_find(s->d1->buffered_messages, seq64be);
+
+ if (item == NULL) {
+ frag = dtls1_hm_fragment_new(msg_hdr->msg_len, 1);
+ if (frag == NULL)
+ goto err;
+ memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
+ frag->msg_header.frag_len = frag->msg_header.msg_len;
+ frag->msg_header.frag_off = 0;
+ } else {
+ frag = (hm_fragment *)item->data;
+ if (frag->msg_header.msg_len != msg_hdr->msg_len) {
+ item = NULL;
+ frag = NULL;
+ goto err;
+ }
+ }
+
+ /*
+ * If message is already reassembled, this must be a retransmit and can
+ * be dropped. In this case item != NULL and so frag does not need to be
+ * freed.
+ */
+ if (frag->reassembly == NULL) {
+ unsigned char devnull[256];
+
+ while (frag_len) {
+ i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
+ devnull,
+ frag_len >
+ sizeof(devnull) ? sizeof(devnull) :
+ frag_len, 0);
+ if (i <= 0)
+ goto err;
+ frag_len -= i;
+ }
+ return DTLS1_HM_FRAGMENT_RETRY;
+ }
+
+ /* read the body of the fragment (header has already been read */
+ i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
+ frag->fragment + msg_hdr->frag_off,
+ frag_len, 0);
+ if ((unsigned long)i != frag_len)
+ i = -1;
+ if (i <= 0)
+ goto err;
+
+ RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off,
+ (long)(msg_hdr->frag_off + frag_len));
+
+ RSMBLY_BITMASK_IS_COMPLETE(frag->reassembly, (long)msg_hdr->msg_len,
+ is_complete);
+
+ if (is_complete) {
+ OPENSSL_free(frag->reassembly);
+ frag->reassembly = NULL;
+ }
+
+ if (item == NULL) {
+ item = pitem_new(seq64be, frag);
+ if (item == NULL) {
+ i = -1;
+ goto err;
+ }
+
+ item = pqueue_insert(s->d1->buffered_messages, item);
+ /*
+ * pqueue_insert fails iff a duplicate item is inserted. However,
+ * |item| cannot be a duplicate. If it were, |pqueue_find|, above,
+ * would have returned it and control would never have reached this
+ * branch.
+ */
+ OPENSSL_assert(item != NULL);
+ }
+
+ return DTLS1_HM_FRAGMENT_RETRY;
+
+ err:
+ if (item == NULL)
+ dtls1_hm_fragment_free(frag);
+ *ok = 0;
+ return i;
+}
+
+static int
+dtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st *msg_hdr,
+ int *ok)
+{
+ int i = -1;
+ hm_fragment *frag = NULL;
+ pitem *item = NULL;
+ unsigned char seq64be[8];
+ unsigned long frag_len = msg_hdr->frag_len;
+
+ if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len)
+ goto err;
+
+ /* Try to find item in queue, to prevent duplicate entries */
+ memset(seq64be, 0, sizeof(seq64be));
+ seq64be[6] = (unsigned char)(msg_hdr->seq >> 8);
+ seq64be[7] = (unsigned char)msg_hdr->seq;
+ item = pqueue_find(s->d1->buffered_messages, seq64be);
+
+ /*
+ * If we already have an entry and this one is a fragment, don't discard
+ * it and rather try to reassemble it.
+ */
+ if (item != NULL && frag_len != msg_hdr->msg_len)
+ item = NULL;
+
+ /*
+ * Discard the message if sequence number was already there, is too far
+ * in the future, already in the queue or if we received a FINISHED
+ * before the SERVER_HELLO, which then must be a stale retransmit.
+ */
+ if (msg_hdr->seq <= s->d1->handshake_read_seq ||
+ msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL ||
+ (s->d1->handshake_read_seq == 0 && msg_hdr->type == SSL3_MT_FINISHED)) {
+ unsigned char devnull[256];
+
+ while (frag_len) {
+ i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
+ devnull,
+ frag_len >
+ sizeof(devnull) ? sizeof(devnull) :
+ frag_len, 0);
+ if (i <= 0)
+ goto err;
+ frag_len -= i;
+ }
+ } else {
+ if (frag_len != msg_hdr->msg_len)
+ return dtls1_reassemble_fragment(s, msg_hdr, ok);
+
+ if (frag_len > dtls1_max_handshake_message_len(s))
+ goto err;
+
+ frag = dtls1_hm_fragment_new(frag_len, 0);
+ if (frag == NULL)
+ goto err;
+
+ memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
+
+ if (frag_len) {
+ /*
+ * read the body of the fragment (header has already been read
+ */
+ i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
+ frag->fragment, frag_len, 0);
+ if ((unsigned long)i != frag_len)
+ i = -1;
+ if (i <= 0)
+ goto err;
+ }
+
+ item = pitem_new(seq64be, frag);
+ if (item == NULL)
+ goto err;
+
+ item = pqueue_insert(s->d1->buffered_messages, item);
+ /*
+ * pqueue_insert fails iff a duplicate item is inserted. However,
+ * |item| cannot be a duplicate. If it were, |pqueue_find|, above,
+ * would have returned it. Then, either |frag_len| !=
+ * |msg_hdr->msg_len| in which case |item| is set to NULL and it will
+ * have been processed with |dtls1_reassemble_fragment|, above, or
+ * the record will have been discarded.
+ */
+ OPENSSL_assert(item != NULL);
+ }
+
+ return DTLS1_HM_FRAGMENT_RETRY;
+
+ err:
+ if (item == NULL)
+ dtls1_hm_fragment_free(frag);
+ *ok = 0;
+ return i;
+}
+
+static int dtls_get_reassembled_message(SSL *s, long *len)
+{
+ unsigned char wire[DTLS1_HM_HEADER_LENGTH];
+ unsigned long mlen, frag_off, frag_len;
+ int i, al, recvd_type;
+ struct hm_header_st msg_hdr;
+ int ok;
+
+ redo:
+ /* see if we have the required fragment already */
+ if ((frag_len = dtls1_retrieve_buffered_fragment(s, &ok)) || ok) {
+ if (ok)
+ s->init_num = frag_len;
+ *len = frag_len;
+ return ok;
+ }
+
+ /* read handshake message header */
+ i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type, wire,
+ DTLS1_HM_HEADER_LENGTH, 0);
+ if (i <= 0) { /* nbio, or an error */
+ s->rwstate = SSL_READING;
+ *len = i;
+ return 0;
+ }
+ if (recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC) {
+ if (wire[0] != SSL3_MT_CCS) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE,
+ SSL_R_BAD_CHANGE_CIPHER_SPEC);
+ goto f_err;
+ }
+
+ memcpy(s->init_buf->data, wire, i);
+ s->init_num = i - 1;
+ s->init_msg = s->init_buf->data + 1;
+ s->s3->tmp.message_type = SSL3_MT_CHANGE_CIPHER_SPEC;
+ s->s3->tmp.message_size = i - 1;
+ *len = i - 1;
+ return 1;
+ }
+
+ /* Handshake fails if message header is incomplete */
+ if (i != DTLS1_HM_HEADER_LENGTH) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
+ goto f_err;
+ }
+
+ /* parse the message fragment header */
+ dtls1_get_message_header(wire, &msg_hdr);
+
+ mlen = msg_hdr.msg_len;
+ frag_off = msg_hdr.frag_off;
+ frag_len = msg_hdr.frag_len;
+
+ /*
+ * We must have at least frag_len bytes left in the record to be read.
+ * Fragments must not span records.
+ */
+ if (frag_len > RECORD_LAYER_get_rrec_length(&s->rlayer)) {
+ al = SSL3_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_BAD_LENGTH);
+ goto f_err;
+ }
+
+ /*
+ * if this is a future (or stale) message it gets buffered
+ * (or dropped)--no further processing at this time
+ * While listening, we accept seq 1 (ClientHello with cookie)
+ * although we're still expecting seq 0 (ClientHello)
+ */
+ if (msg_hdr.seq != s->d1->handshake_read_seq) {
+ *len = dtls1_process_out_of_seq_message(s, &msg_hdr, &ok);
+ return ok;
+ }
+
+ if (frag_len && frag_len < mlen) {
+ *len = dtls1_reassemble_fragment(s, &msg_hdr, &ok);
+ return ok;
+ }
+
+ if (!s->server && s->d1->r_msg_hdr.frag_off == 0 &&
+ wire[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 (wire[1] == 0 && wire[2] == 0 && wire[3] == 0) {
+ if (s->msg_callback)
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
+ wire, DTLS1_HM_HEADER_LENGTH, s,
+ s->msg_callback_arg);
+
+ s->init_num = 0;
+ goto redo;
+ } else { /* Incorrectly formatted Hello request */
+
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE,
+ SSL_R_UNEXPECTED_MESSAGE);
+ goto f_err;
+ }
+ }
+
+ if ((al = dtls1_preprocess_fragment(s, &msg_hdr)))
+ goto f_err;
+
+ if (frag_len > 0) {
+ unsigned char *p =
+ (unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
+
+ i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
+ &p[frag_off], frag_len, 0);
+
+ /*
+ * This shouldn't ever fail due to NBIO because we already checked
+ * that we have enough data in the record
+ */
+ if (i <= 0) {
+ s->rwstate = SSL_READING;
+ *len = i;
+ return 0;
+ }
+ } else
+ i = 0;
+
+ /*
+ * XDTLS: an incorrectly formatted fragment should cause the handshake
+ * to fail
+ */
+ if (i != (int)frag_len) {
+ al = SSL3_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL3_AD_ILLEGAL_PARAMETER);
+ goto f_err;
+ }
+
+ /*
+ * Note that s->init_num is *not* used as current offset in
+ * s->init_buf->data, but as a counter summing up fragments' lengths: as
+ * soon as they sum up to handshake packet length, we assume we have got
+ * all the fragments.
+ */
+ *len = s->init_num = frag_len;
+ return 1;
+
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ s->init_num = 0;
+ *len = -1;
+ return 0;
+}
+
+/*-
+ * for these 2 messages, we need to
+ * ssl->enc_read_ctx re-init
+ * ssl->rlayer.read_sequence zero
+ * ssl->s3->read_mac_secret re-init
+ * ssl->session->read_sym_enc assign
+ * ssl->session->read_compression assign
+ * ssl->session->read_hash assign
+ */
+int dtls_construct_change_cipher_spec(SSL *s)
+{
+ unsigned char *p;
+
+ p = (unsigned char *)s->init_buf->data;
+ *p++ = SSL3_MT_CCS;
+ s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
+ s->init_num = DTLS1_CCS_HEADER_LENGTH;
+
+ if (s->version == DTLS1_BAD_VER) {
+ s->d1->next_handshake_write_seq++;
+ s2n(s->d1->handshake_write_seq, p);
+ s->init_num += 2;
+ }
+
+ s->init_off = 0;
+
+ dtls1_set_message_header_int(s, SSL3_MT_CCS, 0,
+ s->d1->handshake_write_seq, 0, 0);
+
+ /* buffer the message to handle re-xmits */
+ if (!dtls1_buffer_message(s, 1)) {
+ SSLerr(SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_SCTP
+/*
+ * Wait for a dry event. Should only be called at a point in the handshake
+ * where we are not expecting any data from the peer (except possibly an alert).
+ */
+WORK_STATE dtls_wait_for_dry(SSL *s)
+{
+ int ret;
+ long len;
+
+ /* read app data until dry event */
+ ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
+ if (ret < 0)
+ return WORK_ERROR;
+
+ if (ret == 0) {
+ /*
+ * We're not expecting any more messages from the peer at this point -
+ * but we could get an alert. If an alert is waiting then we will never
+ * return successfully. Therefore we attempt to read a message. This
+ * should never succeed but will process any waiting alerts.
+ */
+ if (dtls_get_reassembled_message(s, &len)) {
+ /* The call succeeded! This should never happen */
+ SSLerr(SSL_F_DTLS_WAIT_FOR_DRY, SSL_R_UNEXPECTED_MESSAGE);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ ossl_statem_set_error(s);
+ return WORK_ERROR;
+ }
+
+ s->s3->in_read_app_data = 2;
+ s->rwstate = SSL_READING;
+ BIO_clear_retry_flags(SSL_get_rbio(s));
+ BIO_set_retry_read(SSL_get_rbio(s));
+ return WORK_MORE_A;
+ }
+ return WORK_FINISHED_CONTINUE;
+}
+#endif
+
+int dtls1_read_failed(SSL *s, int code)
+{
+ if (code > 0) {
+ SSLerr(SSL_F_DTLS1_READ_FAILED, ERR_R_INTERNAL_ERROR);
+ return 1;
+ }
+
+ if (!dtls1_is_timer_expired(s)) {
+ /*
+ * not a timeout, none of our business, let higher layers handle
+ * this. in fact it's probably an error
+ */
+ return code;
+ }
+#ifndef OPENSSL_NO_HEARTBEATS
+ /* done, no need to send a retransmit */
+ if (!SSL_in_init(s) && !s->tlsext_hb_pending)
+#else
+ /* done, no need to send a retransmit */
+ if (!SSL_in_init(s))
+#endif
+ {
+ BIO_set_flags(SSL_get_rbio(s), BIO_FLAGS_READ);
+ return code;
+ }
+
+ return dtls1_handle_timeout(s);
+}
+
+int dtls1_get_queue_priority(unsigned short seq, int is_ccs)
+{
+ /*
+ * The index of the retransmission queue actually is the message sequence
+ * number, since the queue only contains messages of a single handshake.
+ * However, the ChangeCipherSpec has no message sequence number and so
+ * using only the sequence will result in the CCS and Finished having the
+ * same index. To prevent this, the sequence number is multiplied by 2.
+ * In case of a CCS 1 is subtracted. This does not only differ CSS and
+ * Finished, it also maintains the order of the index (important for
+ * priority queues) and fits in the unsigned short variable.
+ */
+ return seq * 2 - is_ccs;
+}
+
+int dtls1_retransmit_buffered_messages(SSL *s)
+{
+ pqueue *sent = s->d1->sent_messages;
+ piterator iter;
+ pitem *item;
+ hm_fragment *frag;
+ int found = 0;
+
+ iter = pqueue_iterator(sent);
+
+ for (item = pqueue_next(&iter); item != NULL; item = pqueue_next(&iter)) {
+ frag = (hm_fragment *)item->data;
+ if (dtls1_retransmit_message(s, (unsigned short)
+ dtls1_get_queue_priority
+ (frag->msg_header.seq,
+ frag->msg_header.is_ccs), &found) <= 0)
+ return -1;
+ }
+
+ return 1;
+}
+
+int dtls1_buffer_message(SSL *s, int is_ccs)
+{
+ pitem *item;
+ hm_fragment *frag;
+ unsigned char seq64be[8];
+
+ /*
+ * this function is called immediately after a message has been
+ * serialized
+ */
+ OPENSSL_assert(s->init_off == 0);
+
+ frag = dtls1_hm_fragment_new(s->init_num, 0);
+ if (frag == NULL)
+ return 0;
+
+ memcpy(frag->fragment, s->init_buf->data, s->init_num);
+
+ if (is_ccs) {
+ /* For DTLS1_BAD_VER the header length is non-standard */
+ OPENSSL_assert(s->d1->w_msg_hdr.msg_len +
+ ((s->version ==
+ DTLS1_BAD_VER) ? 3 : DTLS1_CCS_HEADER_LENGTH)
+ == (unsigned int)s->init_num);
+ } else {
+ OPENSSL_assert(s->d1->w_msg_hdr.msg_len +
+ DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num);
+ }
+
+ frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len;
+ frag->msg_header.seq = s->d1->w_msg_hdr.seq;
+ frag->msg_header.type = s->d1->w_msg_hdr.type;
+ frag->msg_header.frag_off = 0;
+ frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len;
+ frag->msg_header.is_ccs = is_ccs;
+
+ /* save current state */
+ frag->msg_header.saved_retransmit_state.enc_write_ctx = s->enc_write_ctx;
+ frag->msg_header.saved_retransmit_state.write_hash = s->write_hash;
+ frag->msg_header.saved_retransmit_state.compress = s->compress;
+ frag->msg_header.saved_retransmit_state.session = s->session;
+ frag->msg_header.saved_retransmit_state.epoch =
+ DTLS_RECORD_LAYER_get_w_epoch(&s->rlayer);
+
+ memset(seq64be, 0, sizeof(seq64be));
+ seq64be[6] =
+ (unsigned
+ char)(dtls1_get_queue_priority(frag->msg_header.seq,
+ frag->msg_header.is_ccs) >> 8);
+ seq64be[7] =
+ (unsigned
+ char)(dtls1_get_queue_priority(frag->msg_header.seq,
+ frag->msg_header.is_ccs));
+
+ item = pitem_new(seq64be, frag);
+ if (item == NULL) {
+ dtls1_hm_fragment_free(frag);
+ return 0;
+ }
+
+ pqueue_insert(s->d1->sent_messages, item);
+ return 1;
+}
+
+int dtls1_retransmit_message(SSL *s, unsigned short seq, int *found)
+{
+ int ret;
+ /* XDTLS: for now assuming that read/writes are blocking */
+ pitem *item;
+ hm_fragment *frag;
+ unsigned long header_length;
+ unsigned char seq64be[8];
+ struct dtls1_retransmit_state saved_state;
+
+ /*-
+ OPENSSL_assert(s->init_num == 0);
+ OPENSSL_assert(s->init_off == 0);
+ */
+
+ /* XDTLS: the requested message ought to be found, otherwise error */
+ memset(seq64be, 0, sizeof(seq64be));
+ seq64be[6] = (unsigned char)(seq >> 8);
+ seq64be[7] = (unsigned char)seq;
+
+ item = pqueue_find(s->d1->sent_messages, seq64be);
+ if (item == NULL) {
+ SSLerr(SSL_F_DTLS1_RETRANSMIT_MESSAGE, ERR_R_INTERNAL_ERROR);
+ *found = 0;
+ return 0;
+ }
+
+ *found = 1;
+ frag = (hm_fragment *)item->data;
+
+ if (frag->msg_header.is_ccs)
+ header_length = DTLS1_CCS_HEADER_LENGTH;
+ else
+ header_length = DTLS1_HM_HEADER_LENGTH;
+
+ memcpy(s->init_buf->data, frag->fragment,
+ frag->msg_header.msg_len + header_length);
+ s->init_num = frag->msg_header.msg_len + header_length;
+
+ dtls1_set_message_header_int(s, frag->msg_header.type,
+ frag->msg_header.msg_len,
+ frag->msg_header.seq, 0,
+ frag->msg_header.frag_len);
+
+ /* save current state */
+ saved_state.enc_write_ctx = s->enc_write_ctx;
+ saved_state.write_hash = s->write_hash;
+ saved_state.compress = s->compress;
+ saved_state.session = s->session;
+ saved_state.epoch = DTLS_RECORD_LAYER_get_w_epoch(&s->rlayer);
+
+ s->d1->retransmitting = 1;
+
+ /* restore state in which the message was originally sent */
+ s->enc_write_ctx = frag->msg_header.saved_retransmit_state.enc_write_ctx;
+ s->write_hash = frag->msg_header.saved_retransmit_state.write_hash;
+ s->compress = frag->msg_header.saved_retransmit_state.compress;
+ s->session = frag->msg_header.saved_retransmit_state.session;
+ DTLS_RECORD_LAYER_set_saved_w_epoch(&s->rlayer,
+ frag->msg_header.
+ saved_retransmit_state.epoch);
+
+ ret = dtls1_do_write(s, frag->msg_header.is_ccs ?
+ SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE);
+
+ /* restore current state */
+ s->enc_write_ctx = saved_state.enc_write_ctx;
+ s->write_hash = saved_state.write_hash;
+ s->compress = saved_state.compress;
+ s->session = saved_state.session;
+ DTLS_RECORD_LAYER_set_saved_w_epoch(&s->rlayer, saved_state.epoch);
+
+ s->d1->retransmitting = 0;
+
+ (void)BIO_flush(s->wbio);
+ return ret;
+}
+
+void dtls1_set_message_header(SSL *s,
+ unsigned char mt, unsigned long len,
+ unsigned long frag_off, unsigned long frag_len)
+{
+ if (frag_off == 0) {
+ s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
+ s->d1->next_handshake_write_seq++;
+ }
+
+ dtls1_set_message_header_int(s, mt, len, s->d1->handshake_write_seq,
+ frag_off, frag_len);
+}
+
+/* don't actually do the writing, wait till the MTU has been retrieved */
+static void
+dtls1_set_message_header_int(SSL *s, unsigned char mt,
+ unsigned long len, unsigned short seq_num,
+ unsigned long frag_off, unsigned long frag_len)
+{
+ struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+
+ msg_hdr->type = mt;
+ msg_hdr->msg_len = len;
+ msg_hdr->seq = seq_num;
+ msg_hdr->frag_off = frag_off;
+ msg_hdr->frag_len = frag_len;
+}
+
+static void
+dtls1_fix_message_header(SSL *s, unsigned long frag_off, unsigned long frag_len)
+{
+ struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+
+ msg_hdr->frag_off = frag_off;
+ msg_hdr->frag_len = frag_len;
+}
+
+static unsigned char *dtls1_write_message_header(SSL *s, unsigned char *p)
+{
+ struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+
+ *p++ = msg_hdr->type;
+ l2n3(msg_hdr->msg_len, p);
+
+ s2n(msg_hdr->seq, p);
+ l2n3(msg_hdr->frag_off, p);
+ l2n3(msg_hdr->frag_len, p);
+
+ return p;
+}
+
+void dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr)
+{
+ memset(msg_hdr, 0, sizeof(*msg_hdr));
+ msg_hdr->type = *(data++);
+ n2l3(data, msg_hdr->msg_len);
+
+ n2s(data, msg_hdr->seq);
+ n2l3(data, msg_hdr->frag_off);
+ n2l3(data, msg_hdr->frag_len);
+}
diff --git a/openssl-1.1.0h/ssl/statem/statem_lib.c b/openssl-1.1.0h/ssl/statem/statem_lib.c
new file mode 100644
index 0000000..36d410b
--- /dev/null
+++ b/openssl-1.1.0h/ssl/statem/statem_lib.c
@@ -0,0 +1,1083 @@
+/*
+ * Copyright 1995-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
+ */
+
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#include <limits.h>
+#include <string.h>
+#include <stdio.h>
+#include "../ssl_locl.h"
+#include "statem_locl.h"
+#include <openssl/buffer.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
+/*
+ * send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or
+ * SSL3_RT_CHANGE_CIPHER_SPEC)
+ */
+int ssl3_do_write(SSL *s, int type)
+{
+ int ret;
+
+ ret = ssl3_write_bytes(s, type, &s->init_buf->data[s->init_off],
+ s->init_num);
+ 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
+ */
+ if (!ssl3_finish_mac(s,
+ (unsigned char *)&s->init_buf->data[s->init_off],
+ ret))
+ return -1;
+
+ if (ret == 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 += ret;
+ s->init_num -= ret;
+ return (0);
+}
+
+int tls_construct_finished(SSL *s, const char *sender, int slen)
+{
+ unsigned char *p;
+ int i;
+ unsigned long l;
+
+ p = ssl_handshake_start(s);
+
+ i = s->method->ssl3_enc->final_finish_mac(s,
+ sender, slen,
+ s->s3->tmp.finish_md);
+ if (i <= 0)
+ return 0;
+ s->s3->tmp.finish_md_len = i;
+ memcpy(p, s->s3->tmp.finish_md, i);
+ l = i;
+
+ /*
+ * Copy the finished so we can use it for renegotiation checks
+ */
+ if (!s->server) {
+ OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
+ memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md, i);
+ s->s3->previous_client_finished_len = i;
+ } else {
+ OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
+ memcpy(s->s3->previous_server_finished, s->s3->tmp.finish_md, i);
+ s->s3->previous_server_finished_len = i;
+ }
+
+ if (!ssl_set_handshake_header(s, SSL3_MT_FINISHED, l)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * ssl3_take_mac calculates the Finished MAC for the handshakes messages seen
+ * to far.
+ */
+int ssl3_take_mac(SSL *s)
+{
+ const char *sender;
+ int 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) {
+ SSLerr(SSL_F_SSL3_TAKE_MAC, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt)
+{
+ int al;
+ long 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,
+ * unless we're using DTLS1_BAD_VER, which has an extra 2 bytes
+ */
+ if (SSL_IS_DTLS(s)) {
+ if ((s->version == DTLS1_BAD_VER
+ && remain != DTLS1_CCS_HEADER_LENGTH + 1)
+ || (s->version != DTLS1_BAD_VER
+ && remain != DTLS1_CCS_HEADER_LENGTH - 1)) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
+ SSL_R_BAD_CHANGE_CIPHER_SPEC);
+ goto f_err;
+ }
+ } else {
+ if (remain != 0) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
+ SSL_R_BAD_CHANGE_CIPHER_SPEC);
+ goto f_err;
+ }
+ }
+
+ /* Check we have a cipher to change to */
+ if (s->s3->tmp.new_cipher == NULL) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY);
+ goto f_err;
+ }
+
+ s->s3->change_cipher_spec = 1;
+ if (!ssl3_do_change_cipher_spec(s)) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
+
+ if (SSL_IS_DTLS(s)) {
+ dtls1_reset_seq_numbers(s, SSL3_CC_READ);
+
+ if (s->version == DTLS1_BAD_VER)
+ s->d1->handshake_read_seq++;
+
+#ifndef OPENSSL_NO_SCTP
+ /*
+ * Remember that a CCS has been received, so that an old key of
+ * SCTP-Auth can be deleted when a CCS is sent. Will be ignored if no
+ * SCTP is used
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD, 1, NULL);
+#endif
+ }
+
+ return MSG_PROCESS_CONTINUE_READING;
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ ossl_statem_set_error(s);
+ return MSG_PROCESS_ERROR;
+}
+
+MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt)
+{
+ int al, i;
+
+ /* If this occurs, we have missed a message */
+ if (!s->s3->change_cipher_spec) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_GOT_A_FIN_BEFORE_A_CCS);
+ goto f_err;
+ }
+ s->s3->change_cipher_spec = 0;
+
+ i = s->s3->tmp.peer_finish_md_len;
+
+ if ((unsigned long)i != PACKET_remaining(pkt)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_BAD_DIGEST_LENGTH);
+ goto f_err;
+ }
+
+ if (CRYPTO_memcmp(PACKET_data(pkt), s->s3->tmp.peer_finish_md, i) != 0) {
+ al = SSL_AD_DECRYPT_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_DIGEST_CHECK_FAILED);
+ goto f_err;
+ }
+
+ /*
+ * Copy the finished so we can use it for renegotiation checks
+ */
+ if (s->server) {
+ OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
+ memcpy(s->s3->previous_client_finished, s->s3->tmp.peer_finish_md, i);
+ s->s3->previous_client_finished_len = i;
+ } else {
+ OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
+ memcpy(s->s3->previous_server_finished, s->s3->tmp.peer_finish_md, i);
+ s->s3->previous_server_finished_len = i;
+ }
+
+ return MSG_PROCESS_FINISHED_READING;
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ ossl_statem_set_error(s);
+ return MSG_PROCESS_ERROR;
+}
+
+int tls_construct_change_cipher_spec(SSL *s)
+{
+ unsigned char *p;
+
+ p = (unsigned char *)s->init_buf->data;
+ *p = SSL3_MT_CCS;
+ s->init_num = 1;
+ s->init_off = 0;
+
+ return 1;
+}
+
+unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk)
+{
+ unsigned char *p;
+ unsigned long l = 3 + SSL_HM_HEADER_LENGTH(s);
+
+ if (!ssl_add_cert_chain(s, cpk, &l))
+ return 0;
+
+ l -= 3 + SSL_HM_HEADER_LENGTH(s);
+ p = ssl_handshake_start(s);
+ l2n3(l, p);
+ l += 3;
+
+ if (!ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE, l)) {
+ SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ return l + SSL_HM_HEADER_LENGTH(s);
+}
+
+WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst)
+{
+ void (*cb) (const SSL *ssl, int type, int val) = NULL;
+
+ /* clean a few things up */
+ ssl3_cleanup_key_block(s);
+
+ if (!SSL_IS_DTLS(s)) {
+ /*
+ * We don't do this in DTLS because we may still need the init_buf
+ * in case there are any unexpected retransmits
+ */
+ BUF_MEM_free(s->init_buf);
+ s->init_buf = NULL;
+ }
+
+ ssl_free_wbio_buffer(s);
+
+ s->init_num = 0;
+
+ if (!s->server || s->renegotiate == 2) {
+ /* skipped if we just sent a HelloRequest */
+ s->renegotiate = 0;
+ s->new_session = 0;
+
+ if (s->server) {
+ ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
+
+ s->ctx->stats.sess_accept_good++;
+ s->handshake_func = ossl_statem_accept;
+ } else {
+ ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
+ if (s->hit)
+ s->ctx->stats.sess_hit++;
+
+ s->handshake_func = ossl_statem_connect;
+ s->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;
+
+ if (cb != NULL)
+ cb(s, SSL_CB_HANDSHAKE_DONE, 1);
+
+ if (SSL_IS_DTLS(s)) {
+ /* done with handshaking */
+ s->d1->handshake_read_seq = 0;
+ s->d1->handshake_write_seq = 0;
+ s->d1->next_handshake_write_seq = 0;
+ dtls1_clear_received_buffer(s);
+ }
+ }
+
+ return WORK_FINISHED_STOP;
+}
+
+int tls_get_message_header(SSL *s, int *mt)
+{
+ /* s->init_num < SSL3_HM_HEADER_LENGTH */
+ int skip_message, i, recvd_type, al;
+ unsigned char *p;
+ unsigned long l;
+
+ 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);
+ 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 || i != 1 || p[0] != SSL3_MT_CCS) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER,
+ SSL_R_BAD_CHANGE_CIPHER_SPEC);
+ goto f_err;
+ }
+ s->s3->tmp.message_type = *mt = SSL3_MT_CHANGE_CIPHER_SPEC;
+ s->init_num = i - 1;
+ s->init_msg = s->init_buf->data;
+ s->s3->tmp.message_size = i;
+ return 1;
+ } else if (recvd_type != SSL3_RT_HANDSHAKE) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, SSL_R_CCS_RECEIVED_EARLY);
+ goto f_err;
+ }
+ s->init_num += i;
+ }
+
+ skip_message = 0;
+ if (!s->server)
+ if (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)) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ goto f_err;
+ }
+ s->s3->tmp.message_size = l;
+
+ s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH;
+ s->init_num = 0;
+ }
+
+ return 1;
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ return 0;
+}
+
+int tls_get_message_body(SSL *s, unsigned long *len)
+{
+ long n;
+ 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);
+ if (i <= 0) {
+ s->rwstate = SSL_READING;
+ *len = 0;
+ return 0;
+ }
+ s->init_num += i;
+ n -= i;
+ }
+
+ /*
+ * If receiving Finished, record MAC of prior handshake messages for
+ * Finished verification.
+ */
+ if (*(s->init_buf->data) == SSL3_MT_FINISHED && !ssl3_take_mac(s)) {
+ /* SSLfatal() 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)) {
+ SSLerr(SSL_F_TLS_GET_MESSAGE_BODY, ERR_R_EVP_LIB);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ *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 {
+ if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
+ s->init_num + SSL3_HM_HEADER_LENGTH)) {
+ SSLerr(SSL_F_TLS_GET_MESSAGE_BODY, ERR_R_EVP_LIB);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ *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);
+ }
+
+ /*
+ * init_num should never be negative...should probably be declared
+ * unsigned
+ */
+ if (s->init_num < 0) {
+ SSLerr(SSL_F_TLS_GET_MESSAGE_BODY, ERR_R_INTERNAL_ERROR);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ *len = 0;
+ return 0;
+ }
+ *len = (unsigned long)s->init_num;
+ return 1;
+}
+
+int ssl_cert_type(const X509 *x, const EVP_PKEY *pk)
+{
+ if (pk == NULL && (pk = X509_get0_pubkey(x)) == NULL)
+ return -1;
+
+ switch (EVP_PKEY_id(pk)) {
+ default:
+ return -1;
+ case EVP_PKEY_RSA:
+ return SSL_PKEY_RSA_ENC;
+ case EVP_PKEY_DSA:
+ return SSL_PKEY_DSA_SIGN;
+#ifndef OPENSSL_NO_EC
+ case EVP_PKEY_EC:
+ return SSL_PKEY_ECC;
+#endif
+#ifndef OPENSSL_NO_GOST
+ case NID_id_GostR3410_2001:
+ return SSL_PKEY_GOST01;
+ case NID_id_GostR3410_2012_256:
+ return SSL_PKEY_GOST12_256;
+ case NID_id_GostR3410_2012_512:
+ return SSL_PKEY_GOST12_512;
+#endif
+ }
+}
+
+int ssl_verify_alarm_type(long type)
+{
+ int al;
+
+ switch (type) {
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+ case X509_V_ERR_UNABLE_TO_GET_CRL:
+ case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
+ al = SSL_AD_UNKNOWN_CA;
+ break;
+ case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
+ case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
+ case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
+ case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+ case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+ case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
+ case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
+ case X509_V_ERR_CERT_NOT_YET_VALID:
+ case X509_V_ERR_CRL_NOT_YET_VALID:
+ case X509_V_ERR_CERT_UNTRUSTED:
+ case X509_V_ERR_CERT_REJECTED:
+ case X509_V_ERR_HOSTNAME_MISMATCH:
+ case X509_V_ERR_EMAIL_MISMATCH:
+ case X509_V_ERR_IP_ADDRESS_MISMATCH:
+ case X509_V_ERR_DANE_NO_MATCH:
+ case X509_V_ERR_EE_KEY_TOO_SMALL:
+ case X509_V_ERR_CA_KEY_TOO_SMALL:
+ case X509_V_ERR_CA_MD_TOO_WEAK:
+ al = SSL_AD_BAD_CERTIFICATE;
+ break;
+ case X509_V_ERR_CERT_SIGNATURE_FAILURE:
+ case X509_V_ERR_CRL_SIGNATURE_FAILURE:
+ al = SSL_AD_DECRYPT_ERROR;
+ break;
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ case X509_V_ERR_CRL_HAS_EXPIRED:
+ al = SSL_AD_CERTIFICATE_EXPIRED;
+ break;
+ case X509_V_ERR_CERT_REVOKED:
+ al = SSL_AD_CERTIFICATE_REVOKED;
+ break;
+ case X509_V_ERR_UNSPECIFIED:
+ case X509_V_ERR_OUT_OF_MEM:
+ case X509_V_ERR_INVALID_CALL:
+ case X509_V_ERR_STORE_LOOKUP:
+ al = SSL_AD_INTERNAL_ERROR;
+ break;
+ case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+ case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
+ case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
+ case X509_V_ERR_CERT_CHAIN_TOO_LONG:
+ case X509_V_ERR_PATH_LENGTH_EXCEEDED:
+ case X509_V_ERR_INVALID_CA:
+ al = SSL_AD_UNKNOWN_CA;
+ break;
+ case X509_V_ERR_APPLICATION_VERIFICATION:
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ break;
+ case X509_V_ERR_INVALID_PURPOSE:
+ al = SSL_AD_UNSUPPORTED_CERTIFICATE;
+ break;
+ default:
+ al = SSL_AD_CERTIFICATE_UNKNOWN;
+ break;
+ }
+ return (al);
+}
+
+int ssl_allow_compression(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)
+{
+ int dtls = SSL_IS_DTLS(s);
+
+ if (a == b)
+ return 0;
+ if (!dtls)
+ return a < b ? -1 : 1;
+ return DTLS_VERSION_LT(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_2_VERSION
+# error Code needs update for TLS_method() support beyond TLS1_2_VERSION.
+#endif
+
+static const version_info tls_version_table[] = {
+#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
+#ifndef OPENSSL_NO_SSL3
+ {SSL3_VERSION, sslv3_client_method, sslv3_server_method},
+#else
+ {SSL3_VERSION, NULL, NULL},
+#endif
+ {0, NULL, NULL},
+};
+
+#if DTLS_MAX_VERSION != DTLS1_2_VERSION
+# error Code needs update for DTLS_method() support beyond DTLS1_2_VERSION.
+#endif
+
+static const version_info dtls_version_table[] = {
+#ifndef OPENSSL_NO_DTLS1_2
+ {DTLS1_2_VERSION, dtlsv1_2_client_method, dtlsv1_2_server_method},
+#else
+ {DTLS1_2_VERSION, NULL, NULL},
+#endif
+#ifndef OPENSSL_NO_DTLS1
+ {DTLS1_VERSION, dtlsv1_client_method, dtlsv1_server_method},
+ {DTLS1_BAD_VER, dtls_bad_ver_client_method, NULL},
+#else
+ {DTLS1_VERSION, NULL, NULL},
+ {DTLS1_BAD_VER, 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;
+ else if ((method->flags & SSL_METHOD_NO_FIPS) != 0 && FIPS_mode())
+ return SSL_R_AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE;
+
+ return 0;
+}
+
+/*
+ * ssl_version_supported - 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(const SSL *s, int version)
+{
+ 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;
+ case DTLS_ANY_VERSION:
+ table = dtls_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) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * ssl_check_version_downgrade - 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(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 if (s->ctx->method->version == DTLS_method()->version)
+ table = dtls_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 - 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(int method_version, int version, int *bound)
+{
+ if (version == 0) {
+ *bound = version;
+ return 1;
+ }
+
+ /*-
+ * Restrict TLS methods to TLS protocol versions.
+ * Restrict DTLS methods to DTLS protocol versions.
+ * Note, DTLS version numbers are decreasing, use comparison macros.
+ *
+ * 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.
+ */
+ return 0;
+
+ case TLS_ANY_VERSION:
+ if (version < SSL3_VERSION || version > TLS_MAX_VERSION)
+ return 0;
+ break;
+
+ case DTLS_ANY_VERSION:
+ if (DTLS_VERSION_GT(version, DTLS_MAX_VERSION) ||
+ DTLS_VERSION_LT(version, DTLS1_BAD_VER))
+ return 0;
+ break;
+ }
+
+ *bound = version;
+ return 1;
+}
+
+/*
+ * ssl_choose_server_version - 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(SSL *s)
+{
+ /*-
+ * 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 = s->client_version;
+ const version_info *vent;
+ const version_info *table;
+ int disabled = 0;
+
+ switch (server_version) {
+ default:
+ if (version_cmp(s, client_version, s->version) < 0)
+ return SSL_R_WRONG_SSL_VERSION;
+ /*
+ * 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;
+ case TLS_ANY_VERSION:
+ table = tls_version_table;
+ break;
+ case DTLS_ANY_VERSION:
+ table = dtls_version_table;
+ break;
+ }
+
+ 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) {
+ 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 - 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.
+ *
+ * Returns 0 on success or an SSL error reason number on failure.
+ */
+int ssl_choose_client_version(SSL *s, int version)
+{
+ const version_info *vent;
+ const version_info *table;
+
+ switch (s->method->version) {
+ default:
+ if (version != s->version)
+ return SSL_R_WRONG_SSL_VERSION;
+ /*
+ * 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;
+ case TLS_ANY_VERSION:
+ table = tls_version_table;
+ break;
+ case DTLS_ANY_VERSION:
+ table = dtls_version_table;
+ break;
+ }
+
+ for (vent = table; vent->version != 0; ++vent) {
+ const SSL_METHOD *method;
+ int err;
+
+ if (version != vent->version)
+ continue;
+ if (vent->cmeth == NULL)
+ break;
+ method = vent->cmeth();
+ err = ssl_method_error(s, method);
+ if (err != 0)
+ return err;
+ s->method = method;
+ s->version = version;
+ return 0;
+ }
+
+ return SSL_R_UNSUPPORTED_PROTOCOL;
+}
+
+/*
+ * ssl_get_client_min_max_version - get minimum and maximum client version
+ * @s: The SSL connection
+ * @min_version: The minimum supported version
+ * @max_version: The maximum supported version
+ *
+ * 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
+ * or FIPS_mode() 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_client_min_max_version(const SSL *s, int *min_version,
+ int *max_version)
+{
+ int version;
+ 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;
+ return 0;
+ case TLS_ANY_VERSION:
+ table = tls_version_table;
+ break;
+ case DTLS_ANY_VERSION:
+ table = dtls_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;
+ 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;
+ continue;
+ }
+ method = vent->cmeth();
+ if (ssl_method_error(s, method) != 0) {
+ hole = 1;
+ } else if (!hole) {
+ single = NULL;
+ *min_version = method->version;
+ } else {
+ 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 - Work out what version we should be using for
+ * the initial ClientHello.
+ *
+ * @s: client SSL handle.
+ *
+ * Returns 0 on success or an SSL error reason number on failure.
+ */
+int ssl_set_client_hello_version(SSL *s)
+{
+ int ver_min, ver_max, ret;
+
+ ret = ssl_get_client_min_max_version(s, &ver_min, &ver_max);
+
+ if (ret != 0)
+ return ret;
+
+ s->client_version = s->version = ver_max;
+ return 0;
+}
diff --git a/openssl-1.1.0h/ssl/statem/statem_locl.h b/openssl-1.1.0h/ssl/statem/statem_locl.h
new file mode 100644
index 0000000..5dbc62b
--- /dev/null
+++ b/openssl-1.1.0h/ssl/statem/statem_locl.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2015-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
+ */
+
+/*****************************************************************************
+ * *
+ * 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 SERVER_HELLO_MAX_LENGTH 20000
+#define SERVER_KEY_EXCH_MAX_LENGTH 102400
+#define SERVER_HELLO_DONE_MAX_LENGTH 0
+#define CCS_MAX_LENGTH 1
+/* Max should actually be 36 but we are generous */
+#define FINISHED_MAX_LENGTH 64
+
+/* 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;
+
+/* Flush the write BIO */
+int statem_flush(SSL *s);
+int ssl3_take_mac(SSL *s);
+
+/*
+ * TLS/DTLS client state machine functions
+ */
+int ossl_statem_client_read_transition(SSL *s, int mt);
+WRITE_TRAN ossl_statem_client_write_transition(SSL *s);
+WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst);
+WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst);
+int ossl_statem_client_construct_message(SSL *s);
+unsigned long ossl_statem_client_max_message_size(SSL *s);
+MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt);
+WORK_STATE ossl_statem_client_post_process_message(SSL *s, WORK_STATE wst);
+
+/*
+ * TLS/DTLS server state machine functions
+ */
+int ossl_statem_server_read_transition(SSL *s, int mt);
+WRITE_TRAN ossl_statem_server_write_transition(SSL *s);
+WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst);
+WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst);
+int ossl_statem_server_construct_message(SSL *s);
+unsigned long ossl_statem_server_max_message_size(SSL *s);
+MSG_PROCESS_RETURN ossl_statem_server_process_message(SSL *s, PACKET *pkt);
+WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst);
+
+/* Functions for getting new message data */
+__owur int tls_get_message_header(SSL *s, int *mt);
+__owur int tls_get_message_body(SSL *s, unsigned long *len);
+__owur int dtls_get_message(SSL *s, int *mt, unsigned long *len);
+
+/* Message construction and processing functions */
+__owur MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt);
+__owur MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt);
+__owur int tls_construct_change_cipher_spec(SSL *s);
+__owur int dtls_construct_change_cipher_spec(SSL *s);
+
+__owur int tls_construct_finished(SSL *s, const char *sender, int slen);
+__owur WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst);
+__owur WORK_STATE dtls_wait_for_dry(SSL *s);
+
+/* some client-only functions */
+__owur int tls_construct_client_hello(SSL *s);
+__owur MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt);
+__owur MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt);
+__owur MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt);
+__owur MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt);
+__owur MSG_PROCESS_RETURN tls_process_server_done(SSL *s, PACKET *pkt);
+__owur int tls_construct_client_verify(SSL *s);
+__owur WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst);
+__owur int tls_construct_client_certificate(SSL *s);
+__owur int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey);
+__owur int tls_construct_client_key_exchange(SSL *s);
+__owur int tls_client_key_exchange_post_work(SSL *s);
+__owur int tls_construct_cert_status(SSL *s);
+__owur MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt);
+__owur MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt);
+__owur int ssl3_check_cert_and_algorithm(SSL *s);
+#ifndef OPENSSL_NO_NEXTPROTONEG
+__owur int tls_construct_next_proto(SSL *s);
+#endif
+__owur MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, PACKET *pkt);
+
+/* some server-only functions */
+__owur MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt);
+__owur WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst);
+__owur int tls_construct_server_hello(SSL *s);
+__owur int tls_construct_hello_request(SSL *s);
+__owur int dtls_construct_hello_verify_request(SSL *s);
+__owur int tls_construct_server_certificate(SSL *s);
+__owur int tls_construct_server_key_exchange(SSL *s);
+__owur int tls_construct_certificate_request(SSL *s);
+__owur int tls_construct_server_done(SSL *s);
+__owur MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt);
+__owur MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt);
+__owur WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst);
+__owur MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt);
+#ifndef OPENSSL_NO_NEXTPROTONEG
+__owur MSG_PROCESS_RETURN tls_process_next_proto(SSL *s, PACKET *pkt);
+#endif
+__owur int tls_construct_new_session_ticket(SSL *s);
diff --git a/openssl-1.1.0h/ssl/statem/statem_srvr.c b/openssl-1.1.0h/ssl/statem/statem_srvr.c
new file mode 100644
index 0000000..c7cd9eb
--- /dev/null
+++ b/openssl-1.1.0h/ssl/statem/statem_srvr.c
@@ -0,0 +1,3341 @@
+/*
+ * Copyright 1995-2016 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
+ */
+
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * ECC cipher suite support in OpenSSL originally written by
+ * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
+ *
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <stdio.h>
+#include "../ssl_locl.h"
+#include "statem_locl.h"
+#include "internal/constant_time_locl.h"
+#include <openssl/buffer.h>
+#include <openssl/rand.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/x509.h>
+#include <openssl/dh.h>
+#include <openssl/bn.h>
+#include <openssl/md5.h>
+
+static STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,
+ PACKET *cipher_suites,
+ STACK_OF(SSL_CIPHER)
+ **skp, int sslv2format,
+ int *al);
+
+/*
+ * server_read_transition() 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|.
+ *
+ * Valid return values are:
+ * 1: Success (transition allowed)
+ * 0: Error (transition not allowed)
+ */
+int ossl_statem_server_read_transition(SSL *s, int mt)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ case TLS_ST_BEFORE:
+ case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
+ 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.
+ */
+ ssl3_send_alert(s, SSL3_AL_FATAL,
+ SSL3_AD_HANDSHAKE_FAILURE);
+ SSLerr(SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION,
+ 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->next_proto_neg_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;
+
+ default:
+ break;
+ }
+
+ /* No valid transition found */
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL3_AD_UNEXPECTED_MESSAGE);
+ SSLerr(SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION, 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)
+{
+ unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+
+ /*
+ * only send a ServerKeyExchange if DH or fortezza but we have a
+ * sign only certificate PSK: may send PSK identity hints For
+ * ECC ciphersuites, we send a serverKeyExchange message only if
+ * the cipher suite is either ECDH-anon or ECDHE. In other cases,
+ * the server certificate contains the server's public key for
+ * key exchange.
+ */
+ if (alg_k & (SSL_kDHE | SSL_kECDHE)
+ /*
+ * PSK: send ServerKeyExchange if PSK identity hint if
+ * provided
+ */
+#ifndef OPENSSL_NO_PSK
+ /* Only send SKE if we have identity hint for plain PSK */
+ || ((alg_k & (SSL_kPSK | SSL_kRSAPSK))
+ && s->cert->psk_identity_hint)
+ /* For other PSK always send SKE */
+ || (alg_k & (SSL_PSK & (SSL_kDHEPSK | SSL_kECDHEPSK)))
+#endif
+#ifndef OPENSSL_NO_SRP
+ /* SRP: send ServerKeyExchange */
+ || (alg_k & SSL_kSRP)
+#endif
+ ) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Should we send a CertificateRequest message?
+ *
+ * Valid return values are:
+ * 1: Yes
+ * 0: No
+ */
+static int send_certificate_request(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
+ * during re-negotiation:
+ */
+ && (s->s3->tmp.finish_md_len == 0 ||
+ !(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;
+}
+
+/*
+ * server_write_transition() 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(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ case TLS_ST_BEFORE:
+ /* Just go straight to trying to read from the client */
+ return WRITE_TRAN_FINISHED;
+
+ case TLS_ST_OK:
+ /* We must be trying to renegotiate */
+ st->hand_state = TLS_ST_SW_HELLO_REQ;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SW_HELLO_REQ:
+ st->hand_state = TLS_ST_OK;
+ ossl_statem_set_in_init(s, 0);
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SR_CLNT_HELLO:
+ if (SSL_IS_DTLS(s) && !s->d1->cookie_verified
+ && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE))
+ st->hand_state = DTLS_ST_SW_HELLO_VERIFY_REQUEST;
+ else
+ st->hand_state = TLS_ST_SW_SRVR_HELLO;
+ return WRITE_TRAN_CONTINUE;
+
+ case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
+ return WRITE_TRAN_FINISHED;
+
+ case TLS_ST_SW_SRVR_HELLO:
+ if (s->hit) {
+ if (s->tlsext_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(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->tlsext_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(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;
+ ossl_statem_set_in_init(s, 0);
+ return WRITE_TRAN_CONTINUE;
+ } else if (s->tlsext_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;
+ ossl_statem_set_in_init(s, 0);
+ return WRITE_TRAN_CONTINUE;
+
+ default:
+ /* Shouldn't happen */
+ return WRITE_TRAN_ERROR;
+ }
+}
+
+/*
+ * 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(SSL *s, WORK_STATE wst)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ case TLS_ST_SW_HELLO_REQ:
+ s->shutdown = 0;
+ if (SSL_IS_DTLS(s))
+ dtls1_clear_sent_buffer(s);
+ break;
+
+ case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
+ s->shutdown = 0;
+ if (SSL_IS_DTLS(s)) {
+ dtls1_clear_sent_buffer(s);
+ /* We don't buffer this message so don't use the timer */
+ st->use_timer = 0;
+ }
+ break;
+
+ case TLS_ST_SW_SRVR_HELLO:
+ if (SSL_IS_DTLS(s)) {
+ /*
+ * Messages we write from now on should be buffered and
+ * retransmitted if necessary, so we need to use the timer now
+ */
+ st->use_timer = 1;
+ }
+ break;
+
+ case TLS_ST_SW_SRVR_DONE:
+#ifndef OPENSSL_NO_SCTP
+ if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s)))
+ return dtls_wait_for_dry(s);
+#endif
+ return WORK_FINISHED_CONTINUE;
+
+ case TLS_ST_SW_SESSION_TICKET:
+ if (SSL_IS_DTLS(s)) {
+ /*
+ * We're into the last flight. We don't retransmit the last flight
+ * unless we need to, so we don't use the timer
+ */
+ st->use_timer = 0;
+ }
+ break;
+
+ case TLS_ST_SW_CHANGE:
+ s->session->cipher = s->s3->tmp.new_cipher;
+ if (!s->method->ssl3_enc->setup_key_block(s)) {
+ ossl_statem_set_error(s);
+ return WORK_ERROR;
+ }
+ if (SSL_IS_DTLS(s)) {
+ /*
+ * We're into the last flight. We don't retransmit the last flight
+ * unless we need to, so we don't use the timer. This might have
+ * already been set to 0 if we sent a NewSessionTicket message,
+ * but we'll set it again here in case we didn't.
+ */
+ st->use_timer = 0;
+ }
+ return WORK_FINISHED_CONTINUE;
+
+ case TLS_ST_OK:
+ return tls_finish_handshake(s, wst);
+
+ default:
+ /* No pre work to be done */
+ break;
+ }
+
+ return WORK_FINISHED_CONTINUE;
+}
+
+/*
+ * 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(SSL *s, WORK_STATE wst)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ s->init_num = 0;
+
+ switch (st->hand_state) {
+ case TLS_ST_SW_HELLO_REQ:
+ if (statem_flush(s) != 1)
+ return WORK_MORE_A;
+ if (!ssl3_init_finished_mac(s)) {
+ ossl_statem_set_error(s);
+ return WORK_ERROR;
+ }
+ break;
+
+ case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
+ if (statem_flush(s) != 1)
+ return WORK_MORE_A;
+ /* HelloVerifyRequest resets Finished MAC */
+ if (s->version != DTLS1_BAD_VER && !ssl3_init_finished_mac(s)) {
+ ossl_statem_set_error(s);
+ return WORK_ERROR;
+ }
+ /*
+ * The next message should be another ClientHello which we need to
+ * treat like it was the first packet
+ */
+ s->first_packet = 1;
+ break;
+
+ case TLS_ST_SW_SRVR_HELLO:
+#ifndef OPENSSL_NO_SCTP
+ if (SSL_IS_DTLS(s) && s->hit) {
+ unsigned char sctpauthkey[64];
+ char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
+
+ /*
+ * Add new shared key for SCTP-Auth, will be ignored if no
+ * SCTP used.
+ */
+ memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
+ sizeof(DTLS1_SCTP_AUTH_LABEL));
+
+ if (SSL_export_keying_material(s, sctpauthkey,
+ sizeof(sctpauthkey), labelbuffer,
+ sizeof(labelbuffer), NULL, 0,
+ 0) <= 0) {
+ ossl_statem_set_error(s);
+ return WORK_ERROR;
+ }
+
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
+ sizeof(sctpauthkey), sctpauthkey);
+ }
+#endif
+ break;
+
+ case TLS_ST_SW_CHANGE:
+#ifndef OPENSSL_NO_SCTP
+ if (SSL_IS_DTLS(s) && !s->hit) {
+ /*
+ * Change to new shared key of SCTP-Auth, will be ignored if
+ * no SCTP used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
+ 0, NULL);
+ }
+#endif
+ if (!s->method->ssl3_enc->change_cipher_state(s,
+ SSL3_CHANGE_CIPHER_SERVER_WRITE))
+ {
+ ossl_statem_set_error(s);
+ return WORK_ERROR;
+ }
+
+ if (SSL_IS_DTLS(s))
+ dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
+ break;
+
+ case TLS_ST_SW_SRVR_DONE:
+ if (statem_flush(s) != 1)
+ return WORK_MORE_A;
+ break;
+
+ case TLS_ST_SW_FINISHED:
+ if (statem_flush(s) != 1)
+ return WORK_MORE_A;
+#ifndef OPENSSL_NO_SCTP
+ if (SSL_IS_DTLS(s) && s->hit) {
+ /*
+ * Change to new shared key of SCTP-Auth, will be ignored if
+ * no SCTP used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
+ 0, NULL);
+ }
+#endif
+ break;
+
+ default:
+ /* No post work to be done */
+ break;
+ }
+
+ return WORK_FINISHED_CONTINUE;
+}
+
+/*
+ * Construct a message to be sent from the server to the client.
+ *
+ * Valid return values are:
+ * 1: Success
+ * 0: Error
+ */
+int ossl_statem_server_construct_message(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
+ return dtls_construct_hello_verify_request(s);
+
+ case TLS_ST_SW_HELLO_REQ:
+ return tls_construct_hello_request(s);
+
+ case TLS_ST_SW_SRVR_HELLO:
+ return tls_construct_server_hello(s);
+
+ case TLS_ST_SW_CERT:
+ return tls_construct_server_certificate(s);
+
+ case TLS_ST_SW_KEY_EXCH:
+ return tls_construct_server_key_exchange(s);
+
+ case TLS_ST_SW_CERT_REQ:
+ return tls_construct_certificate_request(s);
+
+ case TLS_ST_SW_SRVR_DONE:
+ return tls_construct_server_done(s);
+
+ case TLS_ST_SW_SESSION_TICKET:
+ return tls_construct_new_session_ticket(s);
+
+ case TLS_ST_SW_CERT_STATUS:
+ return tls_construct_cert_status(s);
+
+ case TLS_ST_SW_CHANGE:
+ if (SSL_IS_DTLS(s))
+ return dtls_construct_change_cipher_spec(s);
+ else
+ return tls_construct_change_cipher_spec(s);
+
+ case TLS_ST_SW_FINISHED:
+ return tls_construct_finished(s,
+ s->method->
+ ssl3_enc->server_finished_label,
+ s->method->
+ ssl3_enc->server_finished_label_len);
+
+ default:
+ /* Shouldn't happen */
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * 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.
+ */
+unsigned long ossl_statem_server_max_message_size(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ case TLS_ST_SR_CLNT_HELLO:
+ return CLIENT_HELLO_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;
+
+ default:
+ /* Shouldn't happen */
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * Process a message that the server has received from the client.
+ */
+MSG_PROCESS_RETURN ossl_statem_server_process_message(SSL *s, PACKET *pkt)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ case TLS_ST_SR_CLNT_HELLO:
+ return tls_process_client_hello(s, pkt);
+
+ case TLS_ST_SR_CERT:
+ return tls_process_client_certificate(s, pkt);
+
+ case TLS_ST_SR_KEY_EXCH:
+ return tls_process_client_key_exchange(s, pkt);
+
+ case TLS_ST_SR_CERT_VRFY:
+ return tls_process_cert_verify(s, pkt);
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ case TLS_ST_SR_NEXT_PROTO:
+ return tls_process_next_proto(s, pkt);
+#endif
+
+ case TLS_ST_SR_CHANGE:
+ return tls_process_change_cipher_spec(s, pkt);
+
+ case TLS_ST_SR_FINISHED:
+ return tls_process_finished(s, pkt);
+
+ default:
+ /* Shouldn't happen */
+ break;
+ }
+
+ return MSG_PROCESS_ERROR;
+}
+
+/*
+ * Perform any further processing required following the receipt of a message
+ * from the client
+ */
+WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ case TLS_ST_SR_CLNT_HELLO:
+ return tls_post_process_client_hello(s, wst);
+
+ case TLS_ST_SR_KEY_EXCH:
+ return tls_post_process_client_key_exchange(s, wst);
+
+ default:
+ break;
+ }
+
+ /* Shouldn't happen */
+ return WORK_ERROR;
+}
+
+#ifndef OPENSSL_NO_SRP
+static int ssl_check_srp_ext_ClientHello(SSL *s, int *al)
+{
+ int ret = SSL_ERROR_NONE;
+
+ *al = SSL_AD_UNRECOGNIZED_NAME;
+
+ if ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) &&
+ (s->srp_ctx.TLS_ext_srp_username_callback != NULL)) {
+ if (s->srp_ctx.login == NULL) {
+ /*
+ * RFC 5054 says SHOULD reject, we do so if There is no srp
+ * login name
+ */
+ ret = SSL3_AL_FATAL;
+ *al = SSL_AD_UNKNOWN_PSK_IDENTITY;
+ } else {
+ ret = SSL_srp_server_param_with_username(s, al);
+ }
+ }
+ return ret;
+}
+#endif
+
+int tls_construct_hello_request(SSL *s)
+{
+ if (!ssl_set_handshake_header(s, SSL3_MT_HELLO_REQUEST, 0)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_HELLO_REQUEST, ERR_R_INTERNAL_ERROR);
+ ossl_statem_set_error(s);
+ return 0;
+ }
+
+ return 1;
+}
+
+unsigned int dtls_raw_hello_verify_request(unsigned char *buf,
+ unsigned char *cookie,
+ unsigned char cookie_len)
+{
+ unsigned int msg_len;
+ unsigned char *p;
+
+ p = buf;
+ /* Always use DTLS 1.0 version: see RFC 6347 */
+ *(p++) = DTLS1_VERSION >> 8;
+ *(p++) = DTLS1_VERSION & 0xFF;
+
+ *(p++) = (unsigned char)cookie_len;
+ memcpy(p, cookie, cookie_len);
+ p += cookie_len;
+ msg_len = p - buf;
+
+ return msg_len;
+}
+
+int dtls_construct_hello_verify_request(SSL *s)
+{
+ unsigned int len;
+ unsigned char *buf;
+
+ buf = (unsigned char *)s->init_buf->data;
+
+ if (s->ctx->app_gen_cookie_cb == NULL ||
+ s->ctx->app_gen_cookie_cb(s, s->d1->cookie,
+ &(s->d1->cookie_len)) == 0 ||
+ s->d1->cookie_len > 255) {
+ SSLerr(SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST,
+ SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
+ ossl_statem_set_error(s);
+ return 0;
+ }
+
+ len = dtls_raw_hello_verify_request(&buf[DTLS1_HM_HEADER_LENGTH],
+ s->d1->cookie, s->d1->cookie_len);
+
+ dtls1_set_message_header(s, DTLS1_MT_HELLO_VERIFY_REQUEST, len, 0, len);
+ len += DTLS1_HM_HEADER_LENGTH;
+
+ /* number of bytes to write */
+ s->init_num = len;
+ s->init_off = 0;
+
+ return 1;
+}
+
+MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
+{
+ int i, al = SSL_AD_INTERNAL_ERROR;
+ unsigned int j, complen = 0;
+ unsigned long id;
+ const SSL_CIPHER *c;
+#ifndef OPENSSL_NO_COMP
+ SSL_COMP *comp = NULL;
+#endif
+ STACK_OF(SSL_CIPHER) *ciphers = NULL;
+ int protverr;
+ /* |cookie| will only be initialized for DTLS. */
+ PACKET session_id, cipher_suites, compression, extensions, cookie;
+ int is_v2_record;
+ static const unsigned char null_compression = 0;
+
+ is_v2_record = RECORD_LAYER_is_sslv2_record(&s->rlayer);
+
+ PACKET_null_init(&cookie);
+ /* First lets get s->client_version set correctly */
+ if (is_v2_record) {
+ unsigned int version;
+ unsigned int mt;
+ /*-
+ * 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
+ */
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (!PACKET_get_net_2(pkt, &version)) {
+ /* No protocol version supplied! */
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
+ goto err;
+ }
+ if (version == 0x0002) {
+ /* This is real SSLv2. We don't support it. */
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
+ goto err;
+ } else if ((version & 0xff00) == (SSL3_VERSION_MAJOR << 8)) {
+ /* SSLv3/TLS */
+ s->client_version = version;
+ } else {
+ /* No idea what protocol this is */
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
+ goto err;
+ }
+ } else {
+ /*
+ * use version from inside client hello, not from record header (may
+ * differ: see RFC 2246, Appendix E, second paragraph)
+ */
+ if (!PACKET_get_net_2(pkt, (unsigned int *)&s->client_version)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+ }
+
+ /*
+ * Do SSL/TLS version negotiation if applicable. For DTLS we just check
+ * versions are potentially compatible. Version negotiation comes later.
+ */
+ if (!SSL_IS_DTLS(s)) {
+ protverr = ssl_choose_server_version(s);
+ } else if (s->method->version != DTLS_ANY_VERSION &&
+ DTLS_VERSION_LT(s->client_version, s->version)) {
+ protverr = SSL_R_VERSION_TOO_LOW;
+ } else {
+ protverr = 0;
+ }
+
+ if (protverr) {
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, protverr);
+ if ((!s->enc_write_ctx && !s->write_hash)) {
+ /*
+ * similar to ssl3_get_record, send alert using remote version
+ * number
+ */
+ s->version = s->client_version;
+ }
+ al = SSL_AD_PROTOCOL_VERSION;
+ goto f_err;
+ }
+
+ /* Parse the message and load client random. */
+ if (is_v2_record) {
+ /*
+ * 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 above.
+ */
+ unsigned int cipher_len, session_id_len, challenge_len;
+ PACKET challenge;
+
+ if (!PACKET_get_net_2(pkt, &cipher_len)
+ || !PACKET_get_net_2(pkt, &session_id_len)
+ || !PACKET_get_net_2(pkt, &challenge_len)) {
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ SSL_R_RECORD_LENGTH_MISMATCH);
+ al = SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
+
+ if (session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+
+ if (!PACKET_get_sub_packet(pkt, &cipher_suites, cipher_len)
+ || !PACKET_get_sub_packet(pkt, &session_id, session_id_len)
+ || !PACKET_get_sub_packet(pkt, &challenge, challenge_len)
+ /* No extensions. */
+ || PACKET_remaining(pkt) != 0) {
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ SSL_R_RECORD_LENGTH_MISMATCH);
+ al = SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
+
+ /* Load the client random and compression list. */
+ challenge_len = challenge_len > SSL3_RANDOM_SIZE ? SSL3_RANDOM_SIZE :
+ challenge_len;
+ memset(s->s3->client_random, 0, SSL3_RANDOM_SIZE);
+ if (!PACKET_copy_bytes(&challenge,
+ s->s3->client_random + SSL3_RANDOM_SIZE -
+ challenge_len, challenge_len)
+ /* Advertise only null compression. */
+ || !PACKET_buf_init(&compression, &null_compression, 1)) {
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+
+ PACKET_null_init(&extensions);
+ } else {
+ /* Regular ClientHello. */
+ if (!PACKET_copy_bytes(pkt, s->s3->client_random, SSL3_RANDOM_SIZE)
+ || !PACKET_get_length_prefixed_1(pkt, &session_id)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+
+ if (PACKET_remaining(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+
+ if (SSL_IS_DTLS(s)) {
+ if (!PACKET_get_length_prefixed_1(pkt, &cookie)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ /*
+ * If we require cookies and this ClientHello doesn't contain one,
+ * just return since we do not want to allocate any memory yet.
+ * So check cookie length...
+ */
+ if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) {
+ if (PACKET_remaining(&cookie) == 0)
+ return 1;
+ }
+ }
+
+ if (!PACKET_get_length_prefixed_2(pkt, &cipher_suites)
+ || !PACKET_get_length_prefixed_1(pkt, &compression)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ /* Could be empty. */
+ extensions = *pkt;
+ }
+
+ if (SSL_IS_DTLS(s)) {
+ /* Empty cookie was already handled above by returning early. */
+ if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) {
+ if (s->ctx->app_verify_cookie_cb != NULL) {
+ if (s->ctx->app_verify_cookie_cb(s, PACKET_data(&cookie),
+ PACKET_remaining(&cookie)) ==
+ 0) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ SSL_R_COOKIE_MISMATCH);
+ goto f_err;
+ /* else cookie verification succeeded */
+ }
+ /* default verification */
+ } else if (!PACKET_equal(&cookie, s->d1->cookie, s->d1->cookie_len)) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH);
+ goto f_err;
+ }
+ s->d1->cookie_verified = 1;
+ }
+ if (s->method->version == DTLS_ANY_VERSION) {
+ protverr = ssl_choose_server_version(s);
+ if (protverr != 0) {
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, protverr);
+ s->version = s->client_version;
+ al = SSL_AD_PROTOCOL_VERSION;
+ goto f_err;
+ }
+ }
+ }
+
+ s->hit = 0;
+
+ /*
+ * 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 (is_v2_record ||
+ (s->new_session &&
+ (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) {
+ if (!ssl_get_new_session(s, 1))
+ goto err;
+ } else {
+ i = ssl_get_prev_session(s, &extensions, &session_id);
+ /*
+ * Only resume if the session's version matches the negotiated
+ * version.
+ * RFC 5246 does not provide much useful advice on resumption
+ * with a different protocol version. It doesn't forbid it but
+ * the sanity of such behaviour would be questionable.
+ * In practice, clients do not accept a version mismatch and
+ * will abort the handshake with an error.
+ */
+ if (i == 1 && s->version == s->session->ssl_version) {
+ /* previous session */
+ s->hit = 1;
+ } else if (i == -1) {
+ goto err;
+ } else {
+ /* i == 0 */
+ if (!ssl_get_new_session(s, 1))
+ goto err;
+ }
+ }
+
+ if (ssl_bytes_to_cipher_list(s, &cipher_suites, &(ciphers),
+ is_v2_record, &al) == NULL) {
+ goto f_err;
+ }
+
+ /* If it is a hit, check that the cipher is in the list */
+ 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
+ */
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ SSL_R_REQUIRED_CIPHER_MISSING);
+ goto f_err;
+ }
+ }
+
+ complen = PACKET_remaining(&compression);
+ for (j = 0; j < complen; j++) {
+ if (PACKET_data(&compression)[j] == 0)
+ break;
+ }
+
+ if (j >= complen) {
+ /* no compress */
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_NO_COMPRESSION_SPECIFIED);
+ goto f_err;
+ }
+
+ /* TLS extensions */
+ if (s->version >= SSL3_VERSION) {
+ if (!ssl_parse_clienthello_tlsext(s, &extensions)) {
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_PARSE_TLSEXT);
+ 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) <= 0) {
+ goto f_err;
+ }
+ }
+
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) {
+ const SSL_CIPHER *pref_cipher = NULL;
+
+ s->session->master_key_length = sizeof(s->session->master_key);
+ if (s->tls_session_secret_cb(s, s->session->master_key,
+ &s->session->master_key_length, ciphers,
+ &pref_cipher,
+ s->tls_session_secret_cb_arg)) {
+ s->hit = 1;
+ s->session->ciphers = ciphers;
+ s->session->verify_result = X509_V_OK;
+
+ ciphers = NULL;
+
+ /* check if some cipher was preferred by call back */
+ pref_cipher =
+ pref_cipher ? pref_cipher : ssl3_choose_cipher(s,
+ s->
+ session->ciphers,
+ SSL_get_ciphers
+ (s));
+ if (pref_cipher == NULL) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_NO_SHARED_CIPHER);
+ goto f_err;
+ }
+
+ s->session->cipher = pref_cipher;
+ sk_SSL_CIPHER_free(s->cipher_list);
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->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;
+#ifndef OPENSSL_NO_COMP
+ /* This only happens if we have a cache hit */
+ if (s->session->compress_meth != 0) {
+ int m, comp_id = s->session->compress_meth;
+ unsigned int k;
+ /* Perform sanity checks on resumed compression algorithm */
+ /* Can't disable compression */
+ if (!ssl_allow_compression(s)) {
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ SSL_R_INCONSISTENT_COMPRESSION);
+ goto f_err;
+ }
+ /* Look for resumed compression method */
+ for (m = 0; m < sk_SSL_COMP_num(s->ctx->comp_methods); m++) {
+ comp = sk_SSL_COMP_value(s->ctx->comp_methods, m);
+ if (comp_id == comp->id) {
+ s->s3->tmp.new_compression = comp;
+ break;
+ }
+ }
+ if (s->s3->tmp.new_compression == NULL) {
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ SSL_R_INVALID_COMPRESSION_ALGORITHM);
+ goto f_err;
+ }
+ /* Look for resumed method in compression list */
+ for (k = 0; k < complen; k++) {
+ if (PACKET_data(&compression)[k] == comp_id)
+ break;
+ }
+ if (k >= complen) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING);
+ goto f_err;
+ }
+ } else if (s->hit)
+ comp = NULL;
+ else if (ssl_allow_compression(s) && s->ctx->comp_methods) {
+ /* See if we have a match */
+ int m, nn, v, done = 0;
+ unsigned int o;
+
+ nn = sk_SSL_COMP_num(s->ctx->comp_methods);
+ for (m = 0; m < nn; m++) {
+ comp = sk_SSL_COMP_value(s->ctx->comp_methods, m);
+ v = comp->id;
+ for (o = 0; o < complen; o++) {
+ if (v == PACKET_data(&compression)[o]) {
+ done = 1;
+ break;
+ }
+ }
+ if (done)
+ break;
+ }
+ if (done)
+ s->s3->tmp.new_compression = comp;
+ else
+ comp = NULL;
+ }
+#else
+ /*
+ * If compression is disabled we'd better not try to resume a session
+ * using compression.
+ */
+ if (s->session->compress_meth != 0) {
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_INCONSISTENT_COMPRESSION);
+ goto f_err;
+ }
+#endif
+
+ /*
+ * Given s->session->ciphers and SSL_get_ciphers, we must pick a cipher
+ */
+
+ if (!s->hit) {
+#ifdef OPENSSL_NO_COMP
+ s->session->compress_meth = 0;
+#else
+ s->session->compress_meth = (comp == NULL) ? 0 : comp->id;
+#endif
+ sk_SSL_CIPHER_free(s->session->ciphers);
+ s->session->ciphers = ciphers;
+ if (ciphers == NULL) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
+ ciphers = NULL;
+ if (!tls1_set_server_sigalgs(s)) {
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
+ goto err;
+ }
+ }
+
+ sk_SSL_CIPHER_free(ciphers);
+ return MSG_PROCESS_CONTINUE_PROCESSING;
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ err:
+ ossl_statem_set_error(s);
+
+ sk_SSL_CIPHER_free(ciphers);
+ return MSG_PROCESS_ERROR;
+
+}
+
+WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
+{
+ int al = SSL_AD_HANDSHAKE_FAILURE;
+ const SSL_CIPHER *cipher;
+
+ if (wst == WORK_MORE_A) {
+ if (!s->hit) {
+ /* Let cert callback update server certificates if required */
+ if (s->cert->cert_cb) {
+ int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg);
+ if (rv == 0) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_CERT_CB_ERROR);
+ goto f_err;
+ }
+ if (rv < 0) {
+ s->rwstate = SSL_X509_LOOKUP;
+ return WORK_MORE_A;
+ }
+ s->rwstate = SSL_NOTHING;
+ }
+ cipher =
+ ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
+
+ if (cipher == NULL) {
+ SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_NO_SHARED_CIPHER);
+ goto f_err;
+ }
+ s->s3->tmp.new_cipher = cipher;
+ /* check whether we should disable session resumption */
+ if (s->not_resumable_session_cb != NULL)
+ s->session->not_resumable = s->not_resumable_session_cb(s,
+ ((cipher->algorithm_mkey & (SSL_kDHE | SSL_kECDHE)) != 0));
+ if (s->session->not_resumable)
+ /* do not send a session ticket */
+ s->tlsext_ticket_expected = 0;
+ } else {
+ /* Session-id reuse */
+ s->s3->tmp.new_cipher = s->session->cipher;
+ }
+
+ if (!(s->verify_mode & SSL_VERIFY_PEER)) {
+ if (!ssl3_digest_cached_records(s, 0)) {
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+ }
+
+ /*-
+ * 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.
+ */
+
+ /* Handles TLS extensions that we couldn't check earlier */
+ if (s->version >= SSL3_VERSION) {
+ if (!ssl_check_clienthello_tlsext_late(s, &al)) {
+ SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_CLIENTHELLO_TLSEXT);
+ goto f_err;
+ }
+ }
+
+ wst = WORK_MORE_B;
+ }
+#ifndef OPENSSL_NO_SRP
+ if (wst == WORK_MORE_B) {
+ int ret;
+ if ((ret = ssl_check_srp_ext_ClientHello(s, &al)) < 0) {
+ /*
+ * callback indicates further work to be done
+ */
+ s->rwstate = SSL_X509_LOOKUP;
+ return WORK_MORE_B;
+ }
+ if (ret != SSL_ERROR_NONE) {
+ /*
+ * This is not really an error but the only means to for
+ * a client to detect whether srp is supported.
+ */
+ if (al != TLS1_AD_UNKNOWN_PSK_IDENTITY)
+ SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_CLIENTHELLO_TLSEXT);
+ else
+ SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_PSK_IDENTITY_NOT_FOUND);
+ goto f_err;
+ }
+ }
+#endif
+ s->renegotiate = 2;
+
+ return WORK_FINISHED_STOP;
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ ossl_statem_set_error(s);
+ return WORK_ERROR;
+}
+
+int tls_construct_server_hello(SSL *s)
+{
+ unsigned char *buf;
+ unsigned char *p, *d;
+ int i, sl;
+ int al = 0;
+ unsigned long l;
+
+ buf = (unsigned char *)s->init_buf->data;
+
+ /* Do the message type and length last */
+ d = p = ssl_handshake_start(s);
+
+ *(p++) = s->version >> 8;
+ *(p++) = s->version & 0xff;
+
+ /*
+ * Random stuff. Filling of the server_random takes place in
+ * tls_process_client_hello()
+ */
+ memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE);
+ p += SSL3_RANDOM_SIZE;
+
+ /*-
+ * 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.
+ * 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;
+
+ sl = s->session->session_id_length;
+ if (sl > (int)sizeof(s->session->session_id)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+ ossl_statem_set_error(s);
+ return 0;
+ }
+ *(p++) = sl;
+ memcpy(p, s->session->session_id, sl);
+ p += sl;
+
+ /* put the cipher */
+ i = ssl3_put_cipher_by_char(s->s3->tmp.new_cipher, p);
+ p += i;
+
+ /* put the compression method */
+#ifdef OPENSSL_NO_COMP
+ *(p++) = 0;
+#else
+ if (s->s3->tmp.new_compression == NULL)
+ *(p++) = 0;
+ else
+ *(p++) = s->s3->tmp.new_compression->id;
+#endif
+
+ if (ssl_prepare_serverhello_tlsext(s) <= 0) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, SSL_R_SERVERHELLO_TLSEXT);
+ ossl_statem_set_error(s);
+ return 0;
+ }
+ if ((p =
+ ssl_add_serverhello_tlsext(s, p, buf + SSL3_RT_MAX_PLAIN_LENGTH,
+ &al)) == NULL) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+ ossl_statem_set_error(s);
+ return 0;
+ }
+
+ /* do the header */
+ l = (p - d);
+ if (!ssl_set_handshake_header(s, SSL3_MT_SERVER_HELLO, l)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+ ossl_statem_set_error(s);
+ return 0;
+ }
+
+ return 1;
+}
+
+int tls_construct_server_done(SSL *s)
+{
+ if (!ssl_set_handshake_header(s, SSL3_MT_SERVER_DONE, 0)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_DONE, ERR_R_INTERNAL_ERROR);
+ ossl_statem_set_error(s);
+ return 0;
+ }
+
+ if (!s->s3->tmp.cert_request) {
+ if (!ssl3_digest_cached_records(s, 0)) {
+ ossl_statem_set_error(s);
+ }
+ }
+
+ return 1;
+}
+
+int tls_construct_server_key_exchange(SSL *s)
+{
+#ifndef OPENSSL_NO_DH
+ EVP_PKEY *pkdh = NULL;
+ int j;
+#endif
+#ifndef OPENSSL_NO_EC
+ unsigned char *encodedPoint = NULL;
+ int encodedlen = 0;
+ int curve_id = 0;
+#endif
+ EVP_PKEY *pkey;
+ const EVP_MD *md = NULL;
+ unsigned char *p, *d;
+ int al, i;
+ unsigned long type;
+ int n;
+ const BIGNUM *r[4];
+ int nr[4], kn;
+ BUF_MEM *buf;
+ EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
+
+ if (md_ctx == NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+
+ type = s->s3->tmp.new_cipher->algorithm_mkey;
+
+ buf = s->init_buf;
+
+ r[0] = r[1] = r[2] = r[3] = NULL;
+ n = 0;
+#ifndef OPENSSL_NO_PSK
+ if (type & SSL_PSK) {
+ /*
+ * reserve size for record length and PSK identity hint
+ */
+ n += 2;
+ if (s->cert->psk_identity_hint)
+ n += strlen(s->cert->psk_identity_hint);
+ }
+ /* Plain PSK or RSAPSK nothing to do */
+ if (type & (SSL_kPSK | SSL_kRSAPSK)) {
+ } else
+#endif /* !OPENSSL_NO_PSK */
+#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);
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto f_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) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
+ pkdhp = pkdh;
+ }
+ if (pkdhp == NULL) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ SSL_R_MISSING_TMP_DH_KEY);
+ goto f_err;
+ }
+ if (!ssl_security(s, SSL_SECOP_TMP_DH,
+ EVP_PKEY_security_bits(pkdhp), 0, pkdhp)) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ SSL_R_DH_KEY_TOO_SMALL);
+ goto f_err;
+ }
+ if (s->s3->tmp.pkey != NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ s->s3->tmp.pkey = ssl_generate_pkey(pkdhp);
+
+ if (s->s3->tmp.pkey == NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EVP_LIB);
+ goto err;
+ }
+
+ dh = EVP_PKEY_get0_DH(s->s3->tmp.pkey);
+
+ 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)) {
+ int nid;
+
+ if (s->s3->tmp.pkey != NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Get NID of appropriate shared curve */
+ nid = tls1_shared_curve(s, -2);
+ curve_id = tls1_ec_nid2curve_id(nid);
+ if (curve_id == 0) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
+ goto err;
+ }
+ s->s3->tmp.pkey = ssl_generate_pkey_curve(curve_id);
+ /* Generate a new key for this curve */
+ if (s->s3->tmp.pkey == NULL) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EVP_LIB);
+ goto f_err;
+ }
+
+ /* Encode the public key. */
+ encodedlen = EVP_PKEY_get1_tls_encodedpoint(s->s3->tmp.pkey,
+ &encodedPoint);
+ if (encodedlen == 0) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EC_LIB);
+ goto err;
+ }
+
+ /*
+ * We only support named (not generic) curves in ECDH ephemeral key
+ * exchanges. In this situation, we need four additional bytes to
+ * encode the entire ServerECDHParams structure.
+ */
+ n += 4 + encodedlen;
+
+ /*
+ * 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 */
+#ifndef OPENSSL_NO_SRP
+ if (type & SSL_kSRP) {
+ if ((s->srp_ctx.N == NULL) ||
+ (s->srp_ctx.g == NULL) ||
+ (s->srp_ctx.s == NULL) || (s->srp_ctx.B == NULL)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ SSL_R_MISSING_SRP_PARAM);
+ goto err;
+ }
+ r[0] = s->srp_ctx.N;
+ r[1] = s->srp_ctx.g;
+ r[2] = s->srp_ctx.s;
+ r[3] = s->srp_ctx.B;
+ } else
+#endif
+ {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
+ goto f_err;
+ }
+ for (i = 0; i < 4 && r[i] != NULL; i++) {
+ nr[i] = BN_num_bytes(r[i]);
+#ifndef OPENSSL_NO_SRP
+ if ((i == 2) && (type & SSL_kSRP))
+ n += 1 + nr[i];
+ else
+#endif
+#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, so use the length of the prime here
+ */
+ if ((i == 2) && (type & (SSL_kDHE | SSL_kDHEPSK)))
+ n += 2 + nr[0];
+ else
+#endif
+ n += 2 + nr[i];
+ }
+
+ if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP))
+ && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)) {
+ if ((pkey = ssl_get_sign_pkey(s, s->s3->tmp.new_cipher, &md))
+ == NULL) {
+ al = SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
+ kn = EVP_PKEY_size(pkey);
+ /* Allow space for signature algorithm */
+ if (SSL_USE_SIGALGS(s))
+ kn += 2;
+ /* Allow space for signature length */
+ kn += 2;
+ } else {
+ pkey = NULL;
+ kn = 0;
+ }
+
+ if (!BUF_MEM_grow_clean(buf, n + SSL_HM_HEADER_LENGTH(s) + kn)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_LIB_BUF);
+ goto err;
+ }
+ d = p = ssl_handshake_start(s);
+
+#ifndef OPENSSL_NO_PSK
+ if (type & SSL_PSK) {
+ /* copy PSK identity hint */
+ if (s->cert->psk_identity_hint) {
+ size_t len = strlen(s->cert->psk_identity_hint);
+ if (len > PSK_MAX_IDENTITY_LEN) {
+ /*
+ * Should not happen - we already checked this when we set
+ * the identity hint
+ */
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ s2n(len, p);
+ memcpy(p, s->cert->psk_identity_hint, len);
+ p += len;
+ } else {
+ s2n(0, p);
+ }
+ }
+#endif
+
+ for (i = 0; i < 4 && r[i] != NULL; i++) {
+#ifndef OPENSSL_NO_SRP
+ if ((i == 2) && (type & SSL_kSRP)) {
+ *p = nr[i];
+ p++;
+ } else
+#endif
+#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))) {
+ s2n(nr[0], p);
+ for (j = 0; j < (nr[0] - nr[2]); ++j) {
+ *p = 0;
+ ++p;
+ }
+ } else
+#endif
+ s2n(nr[i], p);
+ BN_bn2bin(r[i], p);
+ p += nr[i];
+ }
+
+#ifndef OPENSSL_NO_EC
+ if (type & (SSL_kECDHE | SSL_kECDHEPSK)) {
+ /*
+ * XXX: For now, 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
+ */
+ *p = NAMED_CURVE_TYPE;
+ p += 1;
+ *p = 0;
+ p += 1;
+ *p = curve_id;
+ p += 1;
+ *p = encodedlen;
+ p += 1;
+ memcpy(p, encodedPoint, encodedlen);
+ OPENSSL_free(encodedPoint);
+ encodedPoint = NULL;
+ p += encodedlen;
+ }
+#endif
+
+ /* not anonymous */
+ if (pkey != NULL) {
+ /*
+ * n is the length of the params, they start at &(d[4]) and p
+ * points to the space at the end.
+ */
+ if (md) {
+ /* send signature algorithm */
+ if (SSL_USE_SIGALGS(s)) {
+ if (!tls12_get_sigandhash(p, pkey, md)) {
+ /* Should never happen */
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
+ p += 2;
+ }
+#ifdef SSL_DEBUG
+ fprintf(stderr, "Using hash %s\n", EVP_MD_name(md));
+#endif
+ if (EVP_SignInit_ex(md_ctx, md, NULL) <= 0
+ || 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, d, n) <= 0
+ || EVP_SignFinal(md_ctx, &(p[2]),
+ (unsigned int *)&i, pkey) <= 0) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_LIB_EVP);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+ s2n(i, p);
+ n += i + 2;
+ if (SSL_USE_SIGALGS(s))
+ n += 2;
+ } else {
+ /* Is this error check actually needed? */
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ SSL_R_UNKNOWN_PKEY_TYPE);
+ goto f_err;
+ }
+ }
+
+ if (!ssl_set_handshake_header(s, SSL3_MT_SERVER_KEY_EXCHANGE, n)) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
+
+ EVP_MD_CTX_free(md_ctx);
+ return 1;
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ err:
+#ifndef OPENSSL_NO_DH
+ EVP_PKEY_free(pkdh);
+#endif
+#ifndef OPENSSL_NO_EC
+ OPENSSL_free(encodedPoint);
+#endif
+ EVP_MD_CTX_free(md_ctx);
+ ossl_statem_set_error(s);
+ return 0;
+}
+
+int tls_construct_certificate_request(SSL *s)
+{
+ unsigned char *p, *d;
+ int i, j, nl, off, n;
+ STACK_OF(X509_NAME) *sk = NULL;
+ X509_NAME *name;
+ BUF_MEM *buf;
+
+ buf = s->init_buf;
+
+ d = p = ssl_handshake_start(s);
+
+ /* get the list of acceptable cert types */
+ p++;
+ n = ssl3_get_req_cert_type(s, p);
+ d[0] = n;
+ p += n;
+ n++;
+
+ if (SSL_USE_SIGALGS(s)) {
+ const unsigned char *psigs;
+ unsigned char *etmp = p;
+ nl = tls12_get_psigalgs(s, 1, &psigs);
+ /* Skip over length for now */
+ p += 2;
+ nl = tls12_copy_sigalgs(s, p, psigs, nl);
+ /* Now fill in length */
+ s2n(nl, etmp);
+ p += nl;
+ n += nl + 2;
+ }
+
+ off = n;
+ p += 2;
+ n += 2;
+
+ sk = SSL_get_client_CA_list(s);
+ nl = 0;
+ if (sk != NULL) {
+ for (i = 0; i < sk_X509_NAME_num(sk); i++) {
+ name = sk_X509_NAME_value(sk, i);
+ j = i2d_X509_NAME(name, NULL);
+ if (!BUF_MEM_grow_clean(buf, SSL_HM_HEADER_LENGTH(s) + n + j + 2)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, ERR_R_BUF_LIB);
+ goto err;
+ }
+ p = ssl_handshake_start(s) + n;
+ s2n(j, p);
+ i2d_X509_NAME(name, &p);
+ n += 2 + j;
+ nl += 2 + j;
+ }
+ }
+ /* else no CA names */
+ p = ssl_handshake_start(s) + off;
+ s2n(nl, p);
+
+ if (!ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_REQUEST, n)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ s->s3->tmp.cert_request = 1;
+
+ return 1;
+ err:
+ ossl_statem_set_error(s);
+ return 0;
+}
+
+static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt, int *al)
+{
+#ifndef OPENSSL_NO_PSK
+ unsigned char psk[PSK_MAX_PSK_LEN];
+ size_t psklen;
+ PACKET psk_identity;
+
+ if (!PACKET_get_length_prefixed_2(pkt, &psk_identity)) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+ if (PACKET_remaining(&psk_identity) > PSK_MAX_IDENTITY_LEN) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, SSL_R_DATA_LENGTH_TOO_LONG);
+ return 0;
+ }
+ if (s->psk_server_callback == NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, SSL_R_PSK_NO_SERVER_CB);
+ return 0;
+ }
+
+ if (!PACKET_strndup(&psk_identity, &s->session->psk_identity)) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ psklen = s->psk_server_callback(s, s->session->psk_identity,
+ psk, sizeof(psk));
+
+ if (psklen > PSK_MAX_PSK_LEN) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
+ return 0;
+ } else if (psklen == 0) {
+ /*
+ * PSK related to the given identity not found
+ */
+ *al = SSL_AD_UNKNOWN_PSK_IDENTITY;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
+ SSL_R_PSK_IDENTITY_NOT_FOUND);
+ return 0;
+ }
+
+ OPENSSL_free(s->s3->tmp.psk);
+ s->s3->tmp.psk = OPENSSL_memdup(psk, psklen);
+ OPENSSL_cleanse(psk, psklen);
+
+ if (s->s3->tmp.psk == NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ s->s3->tmp.psklen = psklen;
+
+ return 1;
+#else
+ /* Should never happen */
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+static int tls_process_cke_rsa(SSL *s, PACKET *pkt, int *al)
+{
+#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;
+
+ rsa = EVP_PKEY_get0_RSA(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey);
+ if (rsa == NULL) {
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_RSA, SSL_R_MISSING_RSA_CERTIFICATE);
+ return 0;
+ }
+
+ /* SSLv3 and pre-standard DTLS omit the length bytes. */
+ if (s->version == SSL3_VERSION || s->version == DTLS1_BAD_VER) {
+ enc_premaster = *pkt;
+ } else {
+ if (!PACKET_get_length_prefixed_2(pkt, &enc_premaster)
+ || PACKET_remaining(pkt) != 0) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(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) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(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) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(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_bytes(rand_premaster_secret, sizeof(rand_premaster_secret)) <= 0)
+ 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)
+ 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) {
+ *al = SSL_AD_DECRYPT_ERROR;
+ SSLerr(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)) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_RSA, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ ret = 1;
+ err:
+ OPENSSL_free(rsa_decrypt);
+ return ret;
+#else
+ /* Should never happen */
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_RSA, ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+static int tls_process_cke_dhe(SSL *s, PACKET *pkt, int *al)
+{
+#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) {
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_DHE,
+ SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
+ goto err;
+ }
+ skey = s->s3->tmp.pkey;
+ if (skey == NULL) {
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_DHE, SSL_R_MISSING_TMP_DH_KEY);
+ goto err;
+ }
+
+ if (PACKET_remaining(pkt) == 0L) {
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(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 */
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(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) {
+ SSLerr(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 || !DH_set0_key(cdh, pub_key, NULL)) {
+ SSLerr(SSL_F_TLS_PROCESS_CKE_DHE, ERR_R_INTERNAL_ERROR);
+ if (pub_key != NULL)
+ BN_free(pub_key);
+ goto err;
+ }
+
+ if (ssl_derive(s, skey, ckey) == 0) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_DHE, ERR_R_INTERNAL_ERROR);
+ 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 */
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_DHE, ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt, int *al)
+{
+#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 */
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(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) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_ECDHE, SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+ ckey = EVP_PKEY_new();
+ if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) <= 0) {
+ SSLerr(SSL_F_TLS_PROCESS_CKE_ECDHE, ERR_R_EVP_LIB);
+ goto err;
+ }
+ if (EVP_PKEY_set1_tls_encodedpoint(ckey, data, i) == 0) {
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_ECDHE, ERR_R_EC_LIB);
+ goto err;
+ }
+ }
+
+ if (ssl_derive(s, skey, ckey) == 0) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_ECDHE, ERR_R_INTERNAL_ERROR);
+ 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 */
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_ECDHE, ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+static int tls_process_cke_srp(SSL *s, PACKET *pkt, int *al)
+{
+#ifndef OPENSSL_NO_SRP
+ unsigned int i;
+ const unsigned char *data;
+
+ if (!PACKET_get_net_2(pkt, &i)
+ || !PACKET_get_bytes(pkt, &data, i)) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_SRP, SSL_R_BAD_SRP_A_LENGTH);
+ return 0;
+ }
+ if ((s->srp_ctx.A = BN_bin2bn(data, i, NULL)) == NULL) {
+ SSLerr(SSL_F_TLS_PROCESS_CKE_SRP, ERR_R_BN_LIB);
+ return 0;
+ }
+ if (BN_ucmp(s->srp_ctx.A, s->srp_ctx.N) >= 0 || BN_is_zero(s->srp_ctx.A)) {
+ *al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_SRP, SSL_R_BAD_SRP_PARAMETERS);
+ return 0;
+ }
+ OPENSSL_free(s->session->srp_username);
+ s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login);
+ if (s->session->srp_username == NULL) {
+ SSLerr(SSL_F_TLS_PROCESS_CKE_SRP, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (!srp_generate_server_master_secret(s)) {
+ SSLerr(SSL_F_TLS_PROCESS_CKE_SRP, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+#else
+ /* Should never happen */
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_SRP, ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+static int tls_process_cke_gost(SSL *s, PACKET *pkt, int *al)
+{
+#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;
+ int Ttag, Tclass;
+ long Tlen;
+ long sess_key_len;
+ const unsigned char *data;
+ int ret = 0;
+
+ /* 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) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_GOST, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(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 */
+ sess_key_len = PACKET_remaining(pkt);
+ if (!PACKET_get_bytes(pkt, &data, sess_key_len)) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_GOST, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ if (ASN1_get_object((const unsigned char **)&data, &Tlen, &Ttag,
+ &Tclass, sess_key_len) != V_ASN1_CONSTRUCTED
+ || Ttag != V_ASN1_SEQUENCE || Tclass != V_ASN1_UNIVERSAL) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_GOST, SSL_R_DECRYPTION_FAILED);
+ goto err;
+ }
+ start = data;
+ inlen = Tlen;
+ if (EVP_PKEY_decrypt
+ (pkey_ctx, premaster_secret, &outlen, start, inlen) <= 0) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(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)) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_GOST, ERR_R_INTERNAL_ERROR);
+ 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 */
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CKE_GOST, ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
+{
+ int al = -1;
+ 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, &al))
+ goto err;
+
+ if (alg_k & SSL_kPSK) {
+ /* Identity extracted earlier: should be nothing left */
+ if (PACKET_remaining(pkt) != 0) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+ /* PSK handled by ssl_generate_master_secret */
+ if (!ssl_generate_master_secret(s, NULL, 0, 0)) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ } else if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
+ if (!tls_process_cke_rsa(s, pkt, &al))
+ goto err;
+ } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
+ if (!tls_process_cke_dhe(s, pkt, &al))
+ goto err;
+ } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
+ if (!tls_process_cke_ecdhe(s, pkt, &al))
+ goto err;
+ } else if (alg_k & SSL_kSRP) {
+ if (!tls_process_cke_srp(s, pkt, &al))
+ goto err;
+ } else if (alg_k & SSL_kGOST) {
+ if (!tls_process_cke_gost(s, pkt, &al))
+ goto err;
+ } else {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
+ SSL_R_UNKNOWN_CIPHER_TYPE);
+ goto err;
+ }
+
+ return MSG_PROCESS_CONTINUE_PROCESSING;
+ err:
+ if (al != -1)
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+#ifndef OPENSSL_NO_PSK
+ OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
+ s->s3->tmp.psk = NULL;
+#endif
+ ossl_statem_set_error(s);
+ return MSG_PROCESS_ERROR;
+}
+
+WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
+{
+#ifndef OPENSSL_NO_SCTP
+ if (wst == WORK_MORE_A) {
+ if (SSL_IS_DTLS(s)) {
+ unsigned char sctpauthkey[64];
+ char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
+ /*
+ * Add new shared key for SCTP-Auth, will be ignored if no SCTP
+ * used.
+ */
+ memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
+ sizeof(DTLS1_SCTP_AUTH_LABEL));
+
+ if (SSL_export_keying_material(s, sctpauthkey,
+ sizeof(sctpauthkey), labelbuffer,
+ sizeof(labelbuffer), NULL, 0,
+ 0) <= 0) {
+ ossl_statem_set_error(s);
+ return WORK_ERROR;;
+ }
+
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
+ sizeof(sctpauthkey), sctpauthkey);
+ }
+ }
+#endif
+
+ 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)) {
+ ossl_statem_set_error(s);
+ return WORK_ERROR;
+ }
+ return WORK_FINISHED_CONTINUE;
+ } else {
+ if (!s->s3->handshake_buffer) {
+ SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ ossl_statem_set_error(s);
+ 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)) {
+ ossl_statem_set_error(s);
+ return WORK_ERROR;
+ }
+ }
+
+ return WORK_FINISHED_CONTINUE;
+}
+
+MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
+{
+ EVP_PKEY *pkey = NULL;
+ const unsigned char *sig, *data;
+#ifndef OPENSSL_NO_GOST
+ unsigned char *gost_data = NULL;
+#endif
+ int al, ret = MSG_PROCESS_ERROR;
+ int type = 0, j;
+ unsigned int len;
+ X509 *peer;
+ const EVP_MD *md = NULL;
+ long hdatalen = 0;
+ void *hdata;
+
+ EVP_MD_CTX *mctx = EVP_MD_CTX_new();
+
+ if (mctx == NULL) {
+ SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+
+ peer = s->session->peer;
+ pkey = X509_get0_pubkey(peer);
+ if (pkey == NULL) {
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+
+ type = X509_certificate_type(peer, pkey);
+
+ if (!(type & EVP_PKT_SIGN)) {
+ SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY,
+ SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE);
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ goto f_err;
+ }
+
+ if (SSL_USE_SIGALGS(s)) {
+ int rv;
+
+ if (!PACKET_get_bytes(pkt, &sig, 2)) {
+ al = SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
+ rv = tls12_check_peer_sigalg(&md, s, sig, pkey);
+ if (rv == -1) {
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ } else if (rv == 0) {
+ al = SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
+#ifdef SSL_DEBUG
+ fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
+#endif
+ } else {
+ /* Use default digest for this key type */
+ int idx = ssl_cert_type(NULL, pkey);
+ if (idx >= 0)
+ md = s->s3->tmp.md[idx];
+ if (md == NULL) {
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+ }
+
+ /* 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)) {
+ SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_LENGTH_MISMATCH);
+ al = SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
+
+ j = EVP_PKEY_size(pkey);
+ if (((int)len > j) || ((int)PACKET_remaining(pkt) > j)
+ || (PACKET_remaining(pkt) == 0)) {
+ SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_WRONG_SIGNATURE_SIZE);
+ al = SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
+ if (!PACKET_get_bytes(pkt, &data, len)) {
+ SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_LENGTH_MISMATCH);
+ al = SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
+
+ hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
+ if (hdatalen <= 0) {
+ SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+#ifdef SSL_DEBUG
+ fprintf(stderr, "Using client verify alg %s\n", EVP_MD_name(md));
+#endif
+ if (!EVP_VerifyInit_ex(mctx, md, NULL)
+ || !EVP_VerifyUpdate(mctx, hdata, hdatalen)) {
+ SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_EVP_LIB);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_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) {
+ SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+ BUF_reverse(gost_data, data, len);
+ data = gost_data;
+ }
+ }
+#endif
+
+ if (s->version == SSL3_VERSION
+ && !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
+ s->session->master_key_length,
+ s->session->master_key)) {
+ SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_EVP_LIB);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+
+ if (EVP_VerifyFinal(mctx, data, len, pkey) <= 0) {
+ al = SSL_AD_DECRYPT_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_BAD_SIGNATURE);
+ goto f_err;
+ }
+
+ ret = MSG_PROCESS_CONTINUE_READING;
+ if (0) {
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ ossl_statem_set_error(s);
+ }
+ 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
+ return ret;
+}
+
+MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
+{
+ int i, al = SSL_AD_INTERNAL_ERROR, ret = MSG_PROCESS_ERROR;
+ X509 *x = NULL;
+ unsigned long l, llen;
+ const unsigned char *certstart, *certbytes;
+ STACK_OF(X509) *sk = NULL;
+ PACKET spkt;
+
+ if ((sk = sk_X509_new_null()) == NULL) {
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+
+ if (!PACKET_get_net_3(pkt, &llen)
+ || !PACKET_get_sub_packet(pkt, &spkt, llen)
+ || PACKET_remaining(pkt) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+
+ while (PACKET_remaining(&spkt) > 0) {
+ if (!PACKET_get_net_3(&spkt, &l)
+ || !PACKET_get_bytes(&spkt, &certbytes, l)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+ SSL_R_CERT_LENGTH_MISMATCH);
+ goto f_err;
+ }
+
+ certstart = certbytes;
+ x = d2i_X509(NULL, (const unsigned char **)&certbytes, l);
+ if (x == NULL) {
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_ASN1_LIB);
+ goto f_err;
+ }
+ if (certbytes != (certstart + l)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+ SSL_R_CERT_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ if (!sk_X509_push(sk, x)) {
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+ x = NULL;
+ }
+
+ if (sk_X509_num(sk) <= 0) {
+ /* TLS does not mind 0 certs returned */
+ if (s->version == SSL3_VERSION) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+ SSL_R_NO_CERTIFICATES_RETURNED);
+ goto f_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)) {
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+ SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ goto f_err;
+ }
+ /* No client certificate so digest cached records */
+ if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s, 0)) {
+ goto f_err;
+ }
+ } else {
+ EVP_PKEY *pkey;
+ i = ssl_verify_cert_chain(s, sk);
+ if (i <= 0) {
+ al = ssl_verify_alarm_type(s->verify_result);
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+ SSL_R_CERTIFICATE_VERIFY_FAILED);
+ goto f_err;
+ }
+ if (i > 1) {
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, i);
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ goto f_err;
+ }
+ pkey = X509_get0_pubkey(sk_X509_value(sk, 0));
+ if (pkey == NULL) {
+ al = SSL3_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+ SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+ goto f_err;
+ }
+ }
+
+ 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);
+ 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;
+ goto done;
+
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ ossl_statem_set_error(s);
+ done:
+ X509_free(x);
+ sk_X509_pop_free(sk, X509_free);
+ return ret;
+}
+
+int tls_construct_server_certificate(SSL *s)
+{
+ CERT_PKEY *cpk;
+
+ cpk = ssl_get_server_send_pkey(s);
+ if (cpk == NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+ ossl_statem_set_error(s);
+ return 0;
+ }
+
+ if (!ssl3_output_cert_chain(s, cpk)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+ ossl_statem_set_error(s);
+ return 0;
+ }
+
+ return 1;
+}
+
+int tls_construct_new_session_ticket(SSL *s)
+{
+ unsigned char *senc = NULL;
+ EVP_CIPHER_CTX *ctx = NULL;
+ HMAC_CTX *hctx = NULL;
+ unsigned char *p, *macstart;
+ const unsigned char *const_p;
+ int len, slen_full, slen;
+ 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;
+
+ /* 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) {
+ ossl_statem_set_error(s);
+ return 0;
+ }
+ senc = OPENSSL_malloc(slen_full);
+ if (senc == NULL) {
+ ossl_statem_set_error(s);
+ return 0;
+ }
+
+ ctx = EVP_CIPHER_CTX_new();
+ hctx = HMAC_CTX_new();
+ if (ctx == NULL || hctx == NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ p = senc;
+ if (!i2d_SSL_SESSION(s->session, &p))
+ 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)
+ goto err;
+ sess->session_id_length = 0; /* ID is irrelevant for the ticket */
+
+ slen = i2d_SSL_SESSION(sess, NULL);
+ if (slen == 0 || slen > slen_full) { /* shouldn't ever happen */
+ SSL_SESSION_free(sess);
+ goto err;
+ }
+ p = senc;
+ if (!i2d_SSL_SESSION(sess, &p)) {
+ SSL_SESSION_free(sess);
+ goto err;
+ }
+ SSL_SESSION_free(sess);
+
+ /*-
+ * Grow buffer if need be: the length calculation is as
+ * follows handshake_header_length +
+ * 4 (ticket lifetime hint) + 2 (ticket length) +
+ * sizeof(keyname) + max_iv_len (iv length) +
+ * max_enc_block_size (max encrypted session * length) +
+ * max_md_size (HMAC) + session_length.
+ */
+ if (!BUF_MEM_grow(s->init_buf,
+ SSL_HM_HEADER_LENGTH(s) + 6 + sizeof(key_name) +
+ EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH +
+ EVP_MAX_MD_SIZE + slen))
+ goto err;
+
+ p = ssl_handshake_start(s);
+ /*
+ * Initialize HMAC and cipher contexts. If callback present it does
+ * all the work otherwise use generated values from parent ctx.
+ */
+ if (tctx->tlsext_ticket_key_cb) {
+ /* if 0 is returned, write an empty ticket */
+ int ret = tctx->tlsext_ticket_key_cb(s, key_name, iv, ctx,
+ hctx, 1);
+
+ if (ret == 0) {
+ l2n(0, p); /* timeout */
+ s2n(0, p); /* length */
+ if (!ssl_set_handshake_header
+ (s, SSL3_MT_NEWSESSION_TICKET, p - ssl_handshake_start(s)))
+ goto err;
+ OPENSSL_free(senc);
+ EVP_CIPHER_CTX_free(ctx);
+ HMAC_CTX_free(hctx);
+ return 1;
+ }
+ if (ret < 0)
+ 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)
+ goto err;
+ if (!EVP_EncryptInit_ex(ctx, cipher, NULL,
+ tctx->tlsext_tick_aes_key, iv))
+ goto err;
+ if (!HMAC_Init_ex(hctx, tctx->tlsext_tick_hmac_key,
+ sizeof(tctx->tlsext_tick_hmac_key),
+ EVP_sha256(), NULL))
+ goto err;
+ memcpy(key_name, tctx->tlsext_tick_key_name,
+ sizeof(tctx->tlsext_tick_key_name));
+ }
+
+ /*
+ * Ticket lifetime hint (advisory only): We leave this unspecified
+ * for resumed session (for simplicity), and guess that tickets for
+ * new sessions will live as long as their sessions.
+ */
+ l2n(s->hit ? 0 : s->session->timeout, p);
+
+ /* Skip ticket length for now */
+ p += 2;
+ /* Output key name */
+ macstart = p;
+ memcpy(p, key_name, sizeof(key_name));
+ p += sizeof(key_name);
+ /* output IV */
+ memcpy(p, iv, iv_len);
+ p += iv_len;
+ /* Encrypt session data */
+ if (!EVP_EncryptUpdate(ctx, p, &len, senc, slen))
+ goto err;
+ p += len;
+ if (!EVP_EncryptFinal(ctx, p, &len))
+ goto err;
+ p += len;
+
+ if (!HMAC_Update(hctx, macstart, p - macstart))
+ goto err;
+ if (!HMAC_Final(hctx, p, &hlen))
+ goto err;
+
+ EVP_CIPHER_CTX_free(ctx);
+ HMAC_CTX_free(hctx);
+ ctx = NULL;
+ hctx = NULL;
+
+ p += hlen;
+ /* Now write out lengths: p points to end of data written */
+ /* Total length */
+ len = p - ssl_handshake_start(s);
+ /* Skip ticket lifetime hint */
+ p = ssl_handshake_start(s) + 4;
+ s2n(len - 6, p);
+ if (!ssl_set_handshake_header(s, SSL3_MT_NEWSESSION_TICKET, len))
+ goto err;
+ OPENSSL_free(senc);
+
+ return 1;
+ err:
+ OPENSSL_free(senc);
+ EVP_CIPHER_CTX_free(ctx);
+ HMAC_CTX_free(hctx);
+ ossl_statem_set_error(s);
+ return 0;
+}
+
+int tls_construct_cert_status(SSL *s)
+{
+ unsigned char *p;
+ size_t msglen;
+
+ /*-
+ * Grow buffer if need be: the length calculation is as
+ * follows handshake_header_length +
+ * 1 (ocsp response type) + 3 (ocsp response length)
+ * + (ocsp response)
+ */
+ msglen = 4 + s->tlsext_ocsp_resplen;
+ if (!BUF_MEM_grow(s->init_buf, SSL_HM_HEADER_LENGTH(s) + msglen))
+ goto err;
+
+ p = ssl_handshake_start(s);
+
+ /* status type */
+ *(p++) = s->tlsext_status_type;
+ /* length of OCSP response */
+ l2n3(s->tlsext_ocsp_resplen, p);
+ /* actual response */
+ memcpy(p, s->tlsext_ocsp_resp, s->tlsext_ocsp_resplen);
+
+ if (!ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_STATUS, msglen))
+ goto err;
+
+ return 1;
+
+ err:
+ ossl_statem_set_error(s);
+ return 0;
+}
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+/*
+ * tls_process_next_proto reads a Next Protocol Negotiation handshake message.
+ * It sets the next_proto member in s if found
+ */
+MSG_PROCESS_RETURN tls_process_next_proto(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) {
+ SSLerr(SSL_F_TLS_PROCESS_NEXT_PROTO, SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ if (!PACKET_memdup(&next_proto, &s->next_proto_negotiated, &next_proto_len)) {
+ s->next_proto_negotiated_len = 0;
+ goto err;
+ }
+
+ s->next_proto_negotiated_len = (unsigned char)next_proto_len;
+
+ return MSG_PROCESS_CONTINUE_READING;
+ err:
+ ossl_statem_set_error(s);
+ return MSG_PROCESS_ERROR;
+}
+#endif
+
+#define SSLV2_CIPHER_LEN 3
+
+STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,
+ PACKET *cipher_suites,
+ STACK_OF(SSL_CIPHER) **skp,
+ int sslv2format, int *al)
+{
+ const SSL_CIPHER *c;
+ STACK_OF(SSL_CIPHER) *sk;
+ int n;
+ /* 3 = SSLV2_CIPHER_LEN > TLS_CIPHER_LEN = 2. */
+ unsigned char cipher[SSLV2_CIPHER_LEN];
+
+ s->s3->send_connection_binding = 0;
+
+ n = sslv2format ? SSLV2_CIPHER_LEN : TLS_CIPHER_LEN;
+
+ if (PACKET_remaining(cipher_suites) == 0) {
+ SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, SSL_R_NO_CIPHERS_SPECIFIED);
+ *al = SSL_AD_ILLEGAL_PARAMETER;
+ return NULL;
+ }
+
+ if (PACKET_remaining(cipher_suites) % n != 0) {
+ SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,
+ SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
+ *al = SSL_AD_DECODE_ERROR;
+ return NULL;
+ }
+
+ sk = sk_SSL_CIPHER_new_null();
+ if (sk == NULL) {
+ SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
+ *al = SSL_AD_INTERNAL_ERROR;
+ return NULL;
+ }
+
+ if (sslv2format) {
+ size_t numciphers = PACKET_remaining(cipher_suites) / n;
+ PACKET sslv2ciphers = *cipher_suites;
+ unsigned int leadbyte;
+ unsigned char *raw;
+
+ /*
+ * We store the raw ciphers list in SSLv3+ format so we need to do some
+ * preprocessing to convert the list first. If there are any SSLv2 only
+ * ciphersuites with a non-zero leading byte then we are going to
+ * slightly over allocate because we won't store those. But that isn't a
+ * problem.
+ */
+ raw = OPENSSL_malloc(numciphers * TLS_CIPHER_LEN);
+ s->s3->tmp.ciphers_raw = raw;
+ if (raw == NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ goto err;
+ }
+ for (s->s3->tmp.ciphers_rawlen = 0;
+ PACKET_remaining(&sslv2ciphers) > 0;
+ raw += TLS_CIPHER_LEN) {
+ if (!PACKET_get_1(&sslv2ciphers, &leadbyte)
+ || (leadbyte == 0
+ && !PACKET_copy_bytes(&sslv2ciphers, raw,
+ TLS_CIPHER_LEN))
+ || (leadbyte != 0
+ && !PACKET_forward(&sslv2ciphers, TLS_CIPHER_LEN))) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ OPENSSL_free(s->s3->tmp.ciphers_raw);
+ s->s3->tmp.ciphers_raw = NULL;
+ s->s3->tmp.ciphers_rawlen = 0;
+ goto err;
+ }
+ if (leadbyte == 0)
+ s->s3->tmp.ciphers_rawlen += TLS_CIPHER_LEN;
+ }
+ } else if (!PACKET_memdup(cipher_suites, &s->s3->tmp.ciphers_raw,
+ &s->s3->tmp.ciphers_rawlen)) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ goto err;
+ }
+
+ while (PACKET_copy_bytes(cipher_suites, cipher, n)) {
+ /*
+ * SSLv3 ciphers wrapped in an SSLv2-compatible ClientHello have the
+ * first byte set to zero, while true SSLv2 ciphers have a non-zero
+ * first byte. We don't support any true SSLv2 ciphers, so skip them.
+ */
+ if (sslv2format && cipher[0] != '\0')
+ continue;
+
+ /* Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV */
+ if ((cipher[n - 2] == ((SSL3_CK_SCSV >> 8) & 0xff)) &&
+ (cipher[n - 1] == (SSL3_CK_SCSV & 0xff))) {
+ /* SCSV fatal if renegotiating */
+ if (s->renegotiate) {
+ SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,
+ SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING);
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ goto err;
+ }
+ s->s3->send_connection_binding = 1;
+ continue;
+ }
+
+ /* Check for TLS_FALLBACK_SCSV */
+ if ((cipher[n - 2] == ((SSL3_CK_FALLBACK_SCSV >> 8) & 0xff)) &&
+ (cipher[n - 1] == (SSL3_CK_FALLBACK_SCSV & 0xff))) {
+ /*
+ * The SCSV indicates that the client previously tried a higher
+ * version. Fail if the current version is an unexpected
+ * downgrade.
+ */
+ if (!ssl_check_version_downgrade(s)) {
+ SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,
+ SSL_R_INAPPROPRIATE_FALLBACK);
+ *al = SSL_AD_INAPPROPRIATE_FALLBACK;
+ goto err;
+ }
+ continue;
+ }
+
+ /* For SSLv2-compat, ignore leading 0-byte. */
+ c = ssl_get_cipher_by_char(s, sslv2format ? &cipher[1] : cipher);
+ if (c != NULL) {
+ if (!sk_SSL_CIPHER_push(sk, c)) {
+ SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
+ *al = SSL_AD_INTERNAL_ERROR;
+ goto err;
+ }
+ }
+ }
+ if (PACKET_remaining(cipher_suites) > 0) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ *skp = sk;
+ return sk;
+ err:
+ sk_SSL_CIPHER_free(sk);
+ return NULL;
+}
diff --git a/openssl-1.1.0h/ssl/t1_enc.c b/openssl-1.1.0h/ssl/t1_enc.c
new file mode 100644
index 0000000..235c5e4
--- /dev/null
+++ b/openssl-1.1.0h/ssl/t1_enc.c
@@ -0,0 +1,668 @@
+/*
+ * Copyright 1995-2016 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
+ */
+
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <stdio.h>
+#include "ssl_locl.h"
+#include <openssl/comp.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include <openssl/rand.h>
+
+/* seed1 through seed5 are concatenated */
+static int tls1_PRF(SSL *s,
+ const void *seed1, int seed1_len,
+ const void *seed2, int seed2_len,
+ const void *seed3, int seed3_len,
+ const void *seed4, int seed4_len,
+ const void *seed5, int seed5_len,
+ const unsigned char *sec, int slen,
+ unsigned char *out, int olen)
+{
+ const EVP_MD *md = ssl_prf_md(s);
+ EVP_PKEY_CTX *pctx = NULL;
+
+ int ret = 0;
+ size_t outlen = olen;
+
+ if (md == NULL) {
+ /* Should never happen */
+ SSLerr(SSL_F_TLS1_PRF, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL);
+ if (pctx == NULL || EVP_PKEY_derive_init(pctx) <= 0
+ || EVP_PKEY_CTX_set_tls1_prf_md(pctx, md) <= 0
+ || EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, sec, slen) <= 0)
+ goto err;
+
+ if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed1, seed1_len) <= 0)
+ goto err;
+ if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed2, seed2_len) <= 0)
+ goto err;
+ if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed3, seed3_len) <= 0)
+ goto err;
+ if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed4, seed4_len) <= 0)
+ goto err;
+ if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed5, seed5_len) <= 0)
+ goto err;
+
+ if (EVP_PKEY_derive(pctx, out, &outlen) <= 0)
+ goto err;
+ ret = 1;
+
+ err:
+ EVP_PKEY_CTX_free(pctx);
+ return ret;
+}
+
+static int tls1_generate_key_block(SSL *s, unsigned char *km, int num)
+{
+ int ret;
+ ret = tls1_PRF(s,
+ TLS_MD_KEY_EXPANSION_CONST,
+ TLS_MD_KEY_EXPANSION_CONST_SIZE, s->s3->server_random,
+ SSL3_RANDOM_SIZE, s->s3->client_random, SSL3_RANDOM_SIZE,
+ NULL, 0, NULL, 0, s->session->master_key,
+ s->session->master_key_length, km, num);
+
+ return ret;
+}
+
+int tls1_change_cipher_state(SSL *s, int which)
+{
+ unsigned char *p, *mac_secret;
+ unsigned char tmp1[EVP_MAX_KEY_LENGTH];
+ unsigned char tmp2[EVP_MAX_KEY_LENGTH];
+ unsigned char iv1[EVP_MAX_IV_LENGTH * 2];
+ unsigned char iv2[EVP_MAX_IV_LENGTH * 2];
+ unsigned char *ms, *key, *iv;
+ EVP_CIPHER_CTX *dd;
+ const EVP_CIPHER *c;
+#ifndef OPENSSL_NO_COMP
+ const SSL_COMP *comp;
+#endif
+ const EVP_MD *m;
+ int mac_type;
+ int *mac_secret_size;
+ EVP_MD_CTX *mac_ctx;
+ EVP_PKEY *mac_key;
+ int n, i, j, k, cl;
+ int reuse_dd = 0;
+
+ c = s->s3->tmp.new_sym_enc;
+ m = s->s3->tmp.new_hash;
+ mac_type = s->s3->tmp.new_mac_pkey_type;
+#ifndef OPENSSL_NO_COMP
+ comp = s->s3->tmp.new_compression;
+#endif
+
+ if (which & SSL3_CC_READ) {
+ if (s->tlsext_use_etm)
+ s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC_READ;
+ else
+ s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC_READ;
+
+ if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC)
+ s->mac_flags |= SSL_MAC_FLAG_READ_MAC_STREAM;
+ else
+ s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM;
+
+ if (s->enc_read_ctx != NULL)
+ reuse_dd = 1;
+ else if ((s->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL)
+ goto err;
+ else
+ /*
+ * make sure it's initialised in case we exit later with an error
+ */
+ EVP_CIPHER_CTX_reset(s->enc_read_ctx);
+ dd = s->enc_read_ctx;
+ mac_ctx = ssl_replace_hash(&s->read_hash, NULL);
+ if (mac_ctx == NULL)
+ goto err;
+#ifndef OPENSSL_NO_COMP
+ COMP_CTX_free(s->expand);
+ s->expand = NULL;
+ if (comp != NULL) {
+ s->expand = COMP_CTX_new(comp->method);
+ if (s->expand == NULL) {
+ SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,
+ SSL_R_COMPRESSION_LIBRARY_ERROR);
+ goto err2;
+ }
+ }
+#endif
+ /*
+ * this is done by dtls1_reset_seq_numbers for DTLS
+ */
+ if (!SSL_IS_DTLS(s))
+ RECORD_LAYER_reset_read_sequence(&s->rlayer);
+ mac_secret = &(s->s3->read_mac_secret[0]);
+ mac_secret_size = &(s->s3->read_mac_secret_size);
+ } else {
+ if (s->tlsext_use_etm)
+ s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE;
+ else
+ s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE;
+
+ if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC)
+ s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM;
+ else
+ s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_STREAM;
+ if (s->enc_write_ctx != NULL && !SSL_IS_DTLS(s))
+ reuse_dd = 1;
+ else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL)
+ goto err;
+ dd = s->enc_write_ctx;
+ if (SSL_IS_DTLS(s)) {
+ mac_ctx = EVP_MD_CTX_new();
+ if (mac_ctx == NULL)
+ goto err;
+ s->write_hash = mac_ctx;
+ } else {
+ mac_ctx = ssl_replace_hash(&s->write_hash, NULL);
+ if (mac_ctx == NULL)
+ goto err;
+ }
+#ifndef OPENSSL_NO_COMP
+ COMP_CTX_free(s->compress);
+ s->compress = NULL;
+ if (comp != NULL) {
+ s->compress = COMP_CTX_new(comp->method);
+ if (s->compress == NULL) {
+ SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,
+ SSL_R_COMPRESSION_LIBRARY_ERROR);
+ goto err2;
+ }
+ }
+#endif
+ /*
+ * this is done by dtls1_reset_seq_numbers for DTLS
+ */
+ if (!SSL_IS_DTLS(s))
+ RECORD_LAYER_reset_write_sequence(&s->rlayer);
+ mac_secret = &(s->s3->write_mac_secret[0]);
+ mac_secret_size = &(s->s3->write_mac_secret_size);
+ }
+
+ if (reuse_dd)
+ EVP_CIPHER_CTX_reset(dd);
+
+ p = s->s3->tmp.key_block;
+ i = *mac_secret_size = s->s3->tmp.new_mac_secret_size;
+
+ cl = EVP_CIPHER_key_length(c);
+ j = cl;
+ /* Was j=(exp)?5:EVP_CIPHER_key_length(c); */
+ /* If GCM/CCM mode only part of IV comes from PRF */
+ if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE)
+ k = EVP_GCM_TLS_FIXED_IV_LEN;
+ else if (EVP_CIPHER_mode(c) == EVP_CIPH_CCM_MODE)
+ k = EVP_CCM_TLS_FIXED_IV_LEN;
+ else
+ k = EVP_CIPHER_iv_length(c);
+ if ((which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||
+ (which == SSL3_CHANGE_CIPHER_SERVER_READ)) {
+ ms = &(p[0]);
+ n = i + i;
+ key = &(p[n]);
+ n += j + j;
+ iv = &(p[n]);
+ n += k + k;
+ } else {
+ n = i;
+ ms = &(p[n]);
+ n += i + j;
+ key = &(p[n]);
+ n += j + k;
+ iv = &(p[n]);
+ n += k;
+ }
+
+ if (n > s->s3->tmp.key_block_length) {
+ SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+ goto err2;
+ }
+
+ memcpy(mac_secret, ms, i);
+
+ if (!(EVP_CIPHER_flags(c) & EVP_CIPH_FLAG_AEAD_CIPHER)) {
+ mac_key = EVP_PKEY_new_mac_key(mac_type, NULL,
+ mac_secret, *mac_secret_size);
+ if (mac_key == NULL
+ || EVP_DigestSignInit(mac_ctx, NULL, m, NULL, mac_key) <= 0) {
+ EVP_PKEY_free(mac_key);
+ SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+ goto err2;
+ }
+ EVP_PKEY_free(mac_key);
+ }
+#ifdef SSL_DEBUG
+ printf("which = %04X\nmac key=", which);
+ {
+ int z;
+ for (z = 0; z < i; z++)
+ printf("%02X%c", ms[z], ((z + 1) % 16) ? ' ' : '\n');
+ }
+#endif
+
+ if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE) {
+ if (!EVP_CipherInit_ex(dd, c, NULL, key, NULL, (which & SSL3_CC_WRITE))
+ || !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_GCM_SET_IV_FIXED, k, iv)) {
+ SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+ goto err2;
+ }
+ } else if (EVP_CIPHER_mode(c) == EVP_CIPH_CCM_MODE) {
+ int taglen;
+ if (s->s3->tmp.
+ new_cipher->algorithm_enc & (SSL_AES128CCM8 | SSL_AES256CCM8))
+ taglen = 8;
+ else
+ taglen = 16;
+ if (!EVP_CipherInit_ex(dd, c, NULL, NULL, NULL, (which & SSL3_CC_WRITE))
+ || !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_IVLEN, 12, NULL)
+ || !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_TAG, taglen, NULL)
+ || !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_CCM_SET_IV_FIXED, k, iv)
+ || !EVP_CipherInit_ex(dd, NULL, NULL, key, NULL, -1)) {
+ SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+ goto err2;
+ }
+ } else {
+ if (!EVP_CipherInit_ex(dd, c, NULL, key, iv, (which & SSL3_CC_WRITE))) {
+ SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+ goto err2;
+ }
+ }
+ /* Needed for "composite" AEADs, such as RC4-HMAC-MD5 */
+ if ((EVP_CIPHER_flags(c) & EVP_CIPH_FLAG_AEAD_CIPHER) && *mac_secret_size
+ && !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_MAC_KEY,
+ *mac_secret_size, mac_secret)) {
+ SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+ goto err2;
+ }
+
+#ifdef SSL_DEBUG
+ printf("which = %04X\nkey=", which);
+ {
+ int z;
+ for (z = 0; z < EVP_CIPHER_key_length(c); z++)
+ printf("%02X%c", key[z], ((z + 1) % 16) ? ' ' : '\n');
+ }
+ printf("\niv=");
+ {
+ int z;
+ for (z = 0; z < k; z++)
+ printf("%02X%c", iv[z], ((z + 1) % 16) ? ' ' : '\n');
+ }
+ printf("\n");
+#endif
+
+ OPENSSL_cleanse(tmp1, sizeof(tmp1));
+ OPENSSL_cleanse(tmp2, sizeof(tmp1));
+ OPENSSL_cleanse(iv1, sizeof(iv1));
+ OPENSSL_cleanse(iv2, sizeof(iv2));
+ return (1);
+ err:
+ SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
+ err2:
+ OPENSSL_cleanse(tmp1, sizeof(tmp1));
+ OPENSSL_cleanse(tmp2, sizeof(tmp1));
+ OPENSSL_cleanse(iv1, sizeof(iv1));
+ OPENSSL_cleanse(iv2, sizeof(iv2));
+ return (0);
+}
+
+int tls1_setup_key_block(SSL *s)
+{
+ unsigned char *p;
+ const EVP_CIPHER *c;
+ const EVP_MD *hash;
+ int num;
+ SSL_COMP *comp;
+ int mac_type = NID_undef, mac_secret_size = 0;
+ int ret = 0;
+
+ if (s->s3->tmp.key_block_length != 0)
+ return (1);
+
+ if (!ssl_cipher_get_evp(s->session, &c, &hash, &mac_type, &mac_secret_size,
+ &comp, s->tlsext_use_etm)) {
+ SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK, SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
+ return (0);
+ }
+
+ s->s3->tmp.new_sym_enc = c;
+ s->s3->tmp.new_hash = hash;
+ s->s3->tmp.new_mac_pkey_type = mac_type;
+ s->s3->tmp.new_mac_secret_size = mac_secret_size;
+ num = EVP_CIPHER_key_length(c) + mac_secret_size + EVP_CIPHER_iv_length(c);
+ num *= 2;
+
+ ssl3_cleanup_key_block(s);
+
+ if ((p = OPENSSL_malloc(num)) == NULL) {
+ SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ s->s3->tmp.key_block_length = num;
+ s->s3->tmp.key_block = p;
+
+#ifdef SSL_DEBUG
+ printf("client random\n");
+ {
+ int z;
+ for (z = 0; z < SSL3_RANDOM_SIZE; z++)
+ printf("%02X%c", s->s3->client_random[z],
+ ((z + 1) % 16) ? ' ' : '\n');
+ }
+ printf("server random\n");
+ {
+ int z;
+ for (z = 0; z < SSL3_RANDOM_SIZE; z++)
+ printf("%02X%c", s->s3->server_random[z],
+ ((z + 1) % 16) ? ' ' : '\n');
+ }
+ printf("master key\n");
+ {
+ int z;
+ for (z = 0; z < s->session->master_key_length; z++)
+ printf("%02X%c", s->session->master_key[z],
+ ((z + 1) % 16) ? ' ' : '\n');
+ }
+#endif
+ if (!tls1_generate_key_block(s, p, num))
+ goto err;
+#ifdef SSL_DEBUG
+ printf("\nkey block\n");
+ {
+ int z;
+ for (z = 0; z < num; z++)
+ printf("%02X%c", p[z], ((z + 1) % 16) ? ' ' : '\n');
+ }
+#endif
+
+ if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)
+ && s->method->version <= TLS1_VERSION) {
+ /*
+ * enable vulnerability countermeasure for CBC ciphers with known-IV
+ * problem (http://www.openssl.org/~bodo/tls-cbc.txt)
+ */
+ s->s3->need_empty_fragments = 1;
+
+ if (s->session->cipher != NULL) {
+ if (s->session->cipher->algorithm_enc == SSL_eNULL)
+ s->s3->need_empty_fragments = 0;
+
+#ifndef OPENSSL_NO_RC4
+ if (s->session->cipher->algorithm_enc == SSL_RC4)
+ s->s3->need_empty_fragments = 0;
+#endif
+ }
+ }
+
+ ret = 1;
+ err:
+ return (ret);
+}
+
+int tls1_final_finish_mac(SSL *s, const char *str, int slen, unsigned char *out)
+{
+ int hashlen;
+ unsigned char hash[EVP_MAX_MD_SIZE];
+
+ if (!ssl3_digest_cached_records(s, 0))
+ return 0;
+
+ hashlen = ssl_handshake_hash(s, hash, sizeof(hash));
+
+ if (hashlen == 0)
+ return 0;
+
+ if (!tls1_PRF(s, str, slen, hash, hashlen, NULL, 0, NULL, 0, NULL, 0,
+ s->session->master_key, s->session->master_key_length,
+ out, TLS1_FINISH_MAC_LENGTH))
+ return 0;
+ OPENSSL_cleanse(hash, hashlen);
+ return TLS1_FINISH_MAC_LENGTH;
+}
+
+int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
+ int len)
+{
+ if (s->session->flags & SSL_SESS_FLAG_EXTMS) {
+ unsigned char hash[EVP_MAX_MD_SIZE * 2];
+ int hashlen;
+ /*
+ * Digest cached records keeping record buffer (if present): this wont
+ * affect client auth because we're freezing the buffer at the same
+ * point (after client key exchange and before certificate verify)
+ */
+ if (!ssl3_digest_cached_records(s, 1))
+ return -1;
+ hashlen = ssl_handshake_hash(s, hash, sizeof(hash));
+#ifdef SSL_DEBUG
+ fprintf(stderr, "Handshake hashes:\n");
+ BIO_dump_fp(stderr, (char *)hash, hashlen);
+#endif
+ tls1_PRF(s,
+ TLS_MD_EXTENDED_MASTER_SECRET_CONST,
+ TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE,
+ hash, hashlen,
+ NULL, 0,
+ NULL, 0,
+ NULL, 0, p, len, s->session->master_key,
+ SSL3_MASTER_SECRET_SIZE);
+ OPENSSL_cleanse(hash, hashlen);
+ } else {
+ tls1_PRF(s,
+ TLS_MD_MASTER_SECRET_CONST,
+ TLS_MD_MASTER_SECRET_CONST_SIZE,
+ s->s3->client_random, SSL3_RANDOM_SIZE,
+ NULL, 0,
+ s->s3->server_random, SSL3_RANDOM_SIZE,
+ NULL, 0, p, len, s->session->master_key,
+ SSL3_MASTER_SECRET_SIZE);
+ }
+#ifdef SSL_DEBUG
+ fprintf(stderr, "Premaster Secret:\n");
+ BIO_dump_fp(stderr, (char *)p, len);
+ fprintf(stderr, "Client Random:\n");
+ BIO_dump_fp(stderr, (char *)s->s3->client_random, SSL3_RANDOM_SIZE);
+ fprintf(stderr, "Server Random:\n");
+ BIO_dump_fp(stderr, (char *)s->s3->server_random, SSL3_RANDOM_SIZE);
+ fprintf(stderr, "Master Secret:\n");
+ BIO_dump_fp(stderr, (char *)s->session->master_key,
+ SSL3_MASTER_SECRET_SIZE);
+#endif
+
+ return (SSL3_MASTER_SECRET_SIZE);
+}
+
+int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen,
+ const char *label, size_t llen,
+ const unsigned char *context,
+ size_t contextlen, int use_context)
+{
+ unsigned char *val = NULL;
+ size_t vallen = 0, currentvalpos;
+ int rv;
+
+ /*
+ * construct PRF arguments we construct the PRF argument ourself rather
+ * than passing separate values into the TLS PRF to ensure that the
+ * concatenation of values does not create a prohibited label.
+ */
+ vallen = llen + SSL3_RANDOM_SIZE * 2;
+ if (use_context) {
+ vallen += 2 + contextlen;
+ }
+
+ val = OPENSSL_malloc(vallen);
+ if (val == NULL)
+ goto err2;
+ currentvalpos = 0;
+ memcpy(val + currentvalpos, (unsigned char *)label, llen);
+ currentvalpos += llen;
+ memcpy(val + currentvalpos, s->s3->client_random, SSL3_RANDOM_SIZE);
+ currentvalpos += SSL3_RANDOM_SIZE;
+ memcpy(val + currentvalpos, s->s3->server_random, SSL3_RANDOM_SIZE);
+ currentvalpos += SSL3_RANDOM_SIZE;
+
+ if (use_context) {
+ val[currentvalpos] = (contextlen >> 8) & 0xff;
+ currentvalpos++;
+ val[currentvalpos] = contextlen & 0xff;
+ currentvalpos++;
+ if ((contextlen > 0) || (context != NULL)) {
+ memcpy(val + currentvalpos, context, contextlen);
+ }
+ }
+
+ /*
+ * disallow prohibited labels note that SSL3_RANDOM_SIZE > max(prohibited
+ * label len) = 15, so size of val > max(prohibited label len) = 15 and
+ * the comparisons won't have buffer overflow
+ */
+ if (memcmp(val, TLS_MD_CLIENT_FINISH_CONST,
+ TLS_MD_CLIENT_FINISH_CONST_SIZE) == 0)
+ goto err1;
+ if (memcmp(val, TLS_MD_SERVER_FINISH_CONST,
+ TLS_MD_SERVER_FINISH_CONST_SIZE) == 0)
+ goto err1;
+ if (memcmp(val, TLS_MD_MASTER_SECRET_CONST,
+ TLS_MD_MASTER_SECRET_CONST_SIZE) == 0)
+ goto err1;
+ if (memcmp(val, TLS_MD_EXTENDED_MASTER_SECRET_CONST,
+ TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE) == 0)
+ goto err1;
+ if (memcmp(val, TLS_MD_KEY_EXPANSION_CONST,
+ TLS_MD_KEY_EXPANSION_CONST_SIZE) == 0)
+ goto err1;
+
+ rv = tls1_PRF(s,
+ val, vallen,
+ NULL, 0,
+ NULL, 0,
+ NULL, 0,
+ NULL, 0,
+ s->session->master_key, s->session->master_key_length,
+ out, olen);
+
+ goto ret;
+ err1:
+ SSLerr(SSL_F_TLS1_EXPORT_KEYING_MATERIAL, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL);
+ rv = 0;
+ goto ret;
+ err2:
+ SSLerr(SSL_F_TLS1_EXPORT_KEYING_MATERIAL, ERR_R_MALLOC_FAILURE);
+ rv = 0;
+ ret:
+ OPENSSL_clear_free(val, vallen);
+ return (rv);
+}
+
+int tls1_alert_code(int code)
+{
+ switch (code) {
+ case SSL_AD_CLOSE_NOTIFY:
+ return (SSL3_AD_CLOSE_NOTIFY);
+ case SSL_AD_UNEXPECTED_MESSAGE:
+ return (SSL3_AD_UNEXPECTED_MESSAGE);
+ case SSL_AD_BAD_RECORD_MAC:
+ return (SSL3_AD_BAD_RECORD_MAC);
+ case SSL_AD_DECRYPTION_FAILED:
+ return (TLS1_AD_DECRYPTION_FAILED);
+ case SSL_AD_RECORD_OVERFLOW:
+ return (TLS1_AD_RECORD_OVERFLOW);
+ case SSL_AD_DECOMPRESSION_FAILURE:
+ return (SSL3_AD_DECOMPRESSION_FAILURE);
+ case SSL_AD_HANDSHAKE_FAILURE:
+ return (SSL3_AD_HANDSHAKE_FAILURE);
+ case SSL_AD_NO_CERTIFICATE:
+ return (-1);
+ case SSL_AD_BAD_CERTIFICATE:
+ return (SSL3_AD_BAD_CERTIFICATE);
+ case SSL_AD_UNSUPPORTED_CERTIFICATE:
+ return (SSL3_AD_UNSUPPORTED_CERTIFICATE);
+ case SSL_AD_CERTIFICATE_REVOKED:
+ return (SSL3_AD_CERTIFICATE_REVOKED);
+ case SSL_AD_CERTIFICATE_EXPIRED:
+ return (SSL3_AD_CERTIFICATE_EXPIRED);
+ case SSL_AD_CERTIFICATE_UNKNOWN:
+ return (SSL3_AD_CERTIFICATE_UNKNOWN);
+ case SSL_AD_ILLEGAL_PARAMETER:
+ return (SSL3_AD_ILLEGAL_PARAMETER);
+ case SSL_AD_UNKNOWN_CA:
+ return (TLS1_AD_UNKNOWN_CA);
+ case SSL_AD_ACCESS_DENIED:
+ return (TLS1_AD_ACCESS_DENIED);
+ case SSL_AD_DECODE_ERROR:
+ return (TLS1_AD_DECODE_ERROR);
+ case SSL_AD_DECRYPT_ERROR:
+ return (TLS1_AD_DECRYPT_ERROR);
+ case SSL_AD_EXPORT_RESTRICTION:
+ return (TLS1_AD_EXPORT_RESTRICTION);
+ case SSL_AD_PROTOCOL_VERSION:
+ return (TLS1_AD_PROTOCOL_VERSION);
+ case SSL_AD_INSUFFICIENT_SECURITY:
+ return (TLS1_AD_INSUFFICIENT_SECURITY);
+ case SSL_AD_INTERNAL_ERROR:
+ return (TLS1_AD_INTERNAL_ERROR);
+ case SSL_AD_USER_CANCELLED:
+ return (TLS1_AD_USER_CANCELLED);
+ case SSL_AD_NO_RENEGOTIATION:
+ return (TLS1_AD_NO_RENEGOTIATION);
+ case SSL_AD_UNSUPPORTED_EXTENSION:
+ return (TLS1_AD_UNSUPPORTED_EXTENSION);
+ case SSL_AD_CERTIFICATE_UNOBTAINABLE:
+ return (TLS1_AD_CERTIFICATE_UNOBTAINABLE);
+ case SSL_AD_UNRECOGNIZED_NAME:
+ return (TLS1_AD_UNRECOGNIZED_NAME);
+ case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE:
+ return (TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE);
+ case SSL_AD_BAD_CERTIFICATE_HASH_VALUE:
+ return (TLS1_AD_BAD_CERTIFICATE_HASH_VALUE);
+ case SSL_AD_UNKNOWN_PSK_IDENTITY:
+ return (TLS1_AD_UNKNOWN_PSK_IDENTITY);
+ case SSL_AD_INAPPROPRIATE_FALLBACK:
+ return (TLS1_AD_INAPPROPRIATE_FALLBACK);
+ case SSL_AD_NO_APPLICATION_PROTOCOL:
+ return (TLS1_AD_NO_APPLICATION_PROTOCOL);
+ default:
+ return (-1);
+ }
+}
diff --git a/openssl-1.1.0h/ssl/t1_ext.c b/openssl-1.1.0h/ssl/t1_ext.c
new file mode 100644
index 0000000..a996a20
--- /dev/null
+++ b/openssl-1.1.0h/ssl/t1_ext.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2014-2016 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
+ */
+
+/* Custom extension utility functions */
+
+#include <openssl/ct.h>
+#include "ssl_locl.h"
+
+/* Find a custom extension from the list. */
+static custom_ext_method *custom_ext_find(const custom_ext_methods *exts,
+ unsigned int ext_type)
+{
+ size_t i;
+ custom_ext_method *meth = exts->meths;
+ for (i = 0; i < exts->meths_count; i++, meth++) {
+ if (ext_type == meth->ext_type)
+ return meth;
+ }
+ return NULL;
+}
+
+/*
+ * Initialise custom extensions flags to indicate neither sent nor received.
+ */
+void custom_ext_init(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(SSL *s, int server,
+ unsigned int ext_type,
+ const unsigned char *ext_data, size_t ext_size, int *al)
+{
+ custom_ext_methods *exts = server ? &s->cert->srv_ext : &s->cert->cli_ext;
+ custom_ext_method *meth;
+ meth = custom_ext_find(exts, ext_type);
+ /* If not found return success */
+ if (!meth)
+ return 1;
+ if (!server) {
+ /*
+ * If it's ServerHello we can't have any extensions not sent in
+ * ClientHello.
+ */
+ if (!(meth->ext_flags & SSL_EXT_FLAG_SENT)) {
+ *al = TLS1_AD_UNSUPPORTED_EXTENSION;
+ return 0;
+ }
+ }
+ /* If already present it's a duplicate */
+ if (meth->ext_flags & SSL_EXT_FLAG_RECEIVED) {
+ *al = TLS1_AD_DECODE_ERROR;
+ return 0;
+ }
+ meth->ext_flags |= SSL_EXT_FLAG_RECEIVED;
+ /* If no parse function set return success */
+ if (!meth->parse_cb)
+ return 1;
+
+ return meth->parse_cb(s, ext_type, ext_data, ext_size, al, meth->parse_arg);
+}
+
+/*
+ * Request custom extension data from the application and add to the return
+ * buffer.
+ */
+int custom_ext_add(SSL *s, int server,
+ unsigned char **pret, unsigned char *limit, int *al)
+{
+ custom_ext_methods *exts = server ? &s->cert->srv_ext : &s->cert->cli_ext;
+ custom_ext_method *meth;
+ unsigned char *ret = *pret;
+ size_t i;
+
+ for (i = 0; i < exts->meths_count; i++) {
+ const unsigned char *out = NULL;
+ size_t outlen = 0;
+ meth = exts->meths + i;
+
+ if (server) {
+ /*
+ * For ServerHello only send extensions present in ClientHello.
+ */
+ if (!(meth->ext_flags & SSL_EXT_FLAG_RECEIVED))
+ continue;
+ /* If callback absent for server skip it */
+ if (!meth->add_cb)
+ continue;
+ }
+ if (meth->add_cb) {
+ int cb_retval = 0;
+ cb_retval = meth->add_cb(s, meth->ext_type,
+ &out, &outlen, al, meth->add_arg);
+ if (cb_retval < 0)
+ return 0; /* error */
+ if (cb_retval == 0)
+ continue; /* skip this extension */
+ }
+ if (4 > limit - ret || outlen > (size_t)(limit - ret - 4))
+ return 0;
+ s2n(meth->ext_type, ret);
+ s2n(outlen, ret);
+ if (outlen) {
+ memcpy(ret, out, outlen);
+ ret += outlen;
+ }
+ /*
+ * We can't send duplicates: code logic should prevent this.
+ */
+ OPENSSL_assert(!(meth->ext_flags & SSL_EXT_FLAG_SENT));
+ /*
+ * 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)
+ meth->free_cb(s, meth->ext_type, out, meth->add_arg);
+ }
+ *pret = ret;
+ return 1;
+}
+
+/* Copy the flags from src to dst for any extensions that exist in both */
+int custom_exts_copy_flags(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(dst, methsrc->ext_type);
+
+ if (methdst == NULL)
+ continue;
+
+ methdst->ext_flags = methsrc->ext_flags;
+ }
+
+ return 1;
+}
+
+/* Copy table of custom extensions */
+int custom_exts_copy(custom_ext_methods *dst, const custom_ext_methods *src)
+{
+ if (src->meths_count) {
+ dst->meths =
+ OPENSSL_memdup(src->meths,
+ sizeof(custom_ext_method) * src->meths_count);
+ if (dst->meths == NULL)
+ return 0;
+ dst->meths_count = src->meths_count;
+ }
+ return 1;
+}
+
+void custom_exts_free(custom_ext_methods *exts)
+{
+ OPENSSL_free(exts->meths);
+}
+
+/* Set callbacks for a custom extension. */
+static int custom_ext_meth_add(custom_ext_methods *exts,
+ 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)
+{
+ custom_ext_method *meth, *tmp;
+ /*
+ * Check application error: if add_cb is not set free_cb will never be
+ * called.
+ */
+ if (!add_cb && free_cb)
+ return 0;
+ /*
+ * 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(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(exts, ext_type))
+ 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->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;
+}
+
+/* Return true if a client custom extension exists, false otherwise */
+int SSL_CTX_has_client_custom_ext(const SSL_CTX *ctx, unsigned int ext_type)
+{
+ return custom_ext_find(&ctx->cert->cli_ext, ext_type) != NULL;
+}
+
+/* Application level functions to add custom extension callbacks */
+int SSL_CTX_add_client_custom_ext(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)
+{
+#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 &&
+ SSL_CTX_ct_is_enabled(ctx))
+ return 0;
+#endif
+ return custom_ext_meth_add(&ctx->cert->cli_ext, ext_type, add_cb,
+ free_cb, add_arg, parse_cb, parse_arg);
+}
+
+int SSL_CTX_add_server_custom_ext(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 custom_ext_meth_add(&ctx->cert->srv_ext, ext_type,
+ add_cb, free_cb, add_arg, parse_cb, parse_arg);
+}
+
+int SSL_extension_supported(unsigned int ext_type)
+{
+ switch (ext_type) {
+ /* Internally supported extensions. */
+ case TLSEXT_TYPE_application_layer_protocol_negotiation:
+ case TLSEXT_TYPE_ec_point_formats:
+ case TLSEXT_TYPE_elliptic_curves:
+ case TLSEXT_TYPE_heartbeat:
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ case TLSEXT_TYPE_next_proto_neg:
+#endif
+ case TLSEXT_TYPE_padding:
+ case TLSEXT_TYPE_renegotiate:
+ case TLSEXT_TYPE_server_name:
+ case TLSEXT_TYPE_session_ticket:
+ case TLSEXT_TYPE_signature_algorithms:
+ case TLSEXT_TYPE_srp:
+ case TLSEXT_TYPE_status_request:
+ case TLSEXT_TYPE_signed_certificate_timestamp:
+ case TLSEXT_TYPE_use_srtp:
+#ifdef TLSEXT_TYPE_encrypt_then_mac
+ case TLSEXT_TYPE_encrypt_then_mac:
+#endif
+ return 1;
+ default:
+ return 0;
+ }
+}
diff --git a/openssl-1.1.0h/ssl/t1_lib.c b/openssl-1.1.0h/ssl/t1_lib.c
new file mode 100644
index 0000000..7a5721a
--- /dev/null
+++ b/openssl-1.1.0h/ssl/t1_lib.c
@@ -0,0 +1,4228 @@
+/*
+ * Copyright 1995-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
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/ocsp.h>
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+#include <openssl/dh.h>
+#include <openssl/bn.h>
+#include "ssl_locl.h"
+#include <openssl/ct.h>
+
+
+#define CHECKLEN(curr, val, limit) \
+ (((curr) >= (limit)) || (size_t)((limit) - (curr)) < (size_t)(val))
+
+static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, int ticklen,
+ const unsigned char *sess_id, int sesslen,
+ SSL_SESSION **psess);
+static int ssl_check_clienthello_tlsext_early(SSL *s);
+static int ssl_check_serverhello_tlsext(SSL *s);
+
+SSL3_ENC_METHOD const TLSv1_enc_data = {
+ tls1_enc,
+ tls1_mac,
+ tls1_setup_key_block,
+ tls1_generate_master_secret,
+ tls1_change_cipher_state,
+ tls1_final_finish_mac,
+ TLS1_FINISH_MAC_LENGTH,
+ TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
+ TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
+ tls1_alert_code,
+ tls1_export_keying_material,
+ 0,
+ SSL3_HM_HEADER_LENGTH,
+ ssl3_set_handshake_header,
+ ssl3_handshake_write
+};
+
+SSL3_ENC_METHOD const TLSv1_1_enc_data = {
+ tls1_enc,
+ tls1_mac,
+ tls1_setup_key_block,
+ tls1_generate_master_secret,
+ tls1_change_cipher_state,
+ tls1_final_finish_mac,
+ TLS1_FINISH_MAC_LENGTH,
+ TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
+ TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
+ tls1_alert_code,
+ tls1_export_keying_material,
+ SSL_ENC_FLAG_EXPLICIT_IV,
+ SSL3_HM_HEADER_LENGTH,
+ ssl3_set_handshake_header,
+ ssl3_handshake_write
+};
+
+SSL3_ENC_METHOD const TLSv1_2_enc_data = {
+ tls1_enc,
+ tls1_mac,
+ tls1_setup_key_block,
+ tls1_generate_master_secret,
+ tls1_change_cipher_state,
+ tls1_final_finish_mac,
+ TLS1_FINISH_MAC_LENGTH,
+ TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
+ TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
+ tls1_alert_code,
+ tls1_export_keying_material,
+ SSL_ENC_FLAG_EXPLICIT_IV | SSL_ENC_FLAG_SIGALGS | SSL_ENC_FLAG_SHA256_PRF
+ | SSL_ENC_FLAG_TLS1_2_CIPHERS,
+ SSL3_HM_HEADER_LENGTH,
+ ssl3_set_handshake_header,
+ ssl3_handshake_write
+};
+
+long tls1_default_timeout(void)
+{
+ /*
+ * 2 hours, the 24 hours mentioned in the TLSv1 spec is way too long for
+ * http, the cache would over fill
+ */
+ return (60 * 60 * 2);
+}
+
+int tls1_new(SSL *s)
+{
+ if (!ssl3_new(s))
+ return (0);
+ s->method->ssl_clear(s);
+ return (1);
+}
+
+void tls1_free(SSL *s)
+{
+ OPENSSL_free(s->tlsext_session_ticket);
+ ssl3_free(s);
+}
+
+void tls1_clear(SSL *s)
+{
+ ssl3_clear(s);
+ if (s->method->version == TLS_ANY_VERSION)
+ s->version = TLS_MAX_VERSION;
+ else
+ s->version = s->method->version;
+}
+
+#ifndef OPENSSL_NO_EC
+
+typedef struct {
+ int nid; /* Curve NID */
+ int secbits; /* Bits of security (from SP800-57) */
+ unsigned int flags; /* Flags: currently just field type */
+} tls_curve_info;
+
+/*
+ * Table of curve information.
+ * Do not delete entries or reorder this array! It is used as a lookup
+ * table: the index of each entry is one less than the TLS curve id.
+ */
+static const tls_curve_info nid_list[] = {
+ {NID_sect163k1, 80, TLS_CURVE_CHAR2}, /* sect163k1 (1) */
+ {NID_sect163r1, 80, TLS_CURVE_CHAR2}, /* sect163r1 (2) */
+ {NID_sect163r2, 80, TLS_CURVE_CHAR2}, /* sect163r2 (3) */
+ {NID_sect193r1, 80, TLS_CURVE_CHAR2}, /* sect193r1 (4) */
+ {NID_sect193r2, 80, TLS_CURVE_CHAR2}, /* sect193r2 (5) */
+ {NID_sect233k1, 112, TLS_CURVE_CHAR2}, /* sect233k1 (6) */
+ {NID_sect233r1, 112, TLS_CURVE_CHAR2}, /* sect233r1 (7) */
+ {NID_sect239k1, 112, TLS_CURVE_CHAR2}, /* sect239k1 (8) */
+ {NID_sect283k1, 128, TLS_CURVE_CHAR2}, /* sect283k1 (9) */
+ {NID_sect283r1, 128, TLS_CURVE_CHAR2}, /* sect283r1 (10) */
+ {NID_sect409k1, 192, TLS_CURVE_CHAR2}, /* sect409k1 (11) */
+ {NID_sect409r1, 192, TLS_CURVE_CHAR2}, /* sect409r1 (12) */
+ {NID_sect571k1, 256, TLS_CURVE_CHAR2}, /* sect571k1 (13) */
+ {NID_sect571r1, 256, TLS_CURVE_CHAR2}, /* sect571r1 (14) */
+ {NID_secp160k1, 80, TLS_CURVE_PRIME}, /* secp160k1 (15) */
+ {NID_secp160r1, 80, TLS_CURVE_PRIME}, /* secp160r1 (16) */
+ {NID_secp160r2, 80, TLS_CURVE_PRIME}, /* secp160r2 (17) */
+ {NID_secp192k1, 80, TLS_CURVE_PRIME}, /* secp192k1 (18) */
+ {NID_X9_62_prime192v1, 80, TLS_CURVE_PRIME}, /* secp192r1 (19) */
+ {NID_secp224k1, 112, TLS_CURVE_PRIME}, /* secp224k1 (20) */
+ {NID_secp224r1, 112, TLS_CURVE_PRIME}, /* secp224r1 (21) */
+ {NID_secp256k1, 128, TLS_CURVE_PRIME}, /* secp256k1 (22) */
+ {NID_X9_62_prime256v1, 128, TLS_CURVE_PRIME}, /* secp256r1 (23) */
+ {NID_secp384r1, 192, TLS_CURVE_PRIME}, /* secp384r1 (24) */
+ {NID_secp521r1, 256, TLS_CURVE_PRIME}, /* secp521r1 (25) */
+ {NID_brainpoolP256r1, 128, TLS_CURVE_PRIME}, /* brainpoolP256r1 (26) */
+ {NID_brainpoolP384r1, 192, TLS_CURVE_PRIME}, /* brainpoolP384r1 (27) */
+ {NID_brainpoolP512r1, 256, TLS_CURVE_PRIME}, /* brainpool512r1 (28) */
+ {NID_X25519, 128, TLS_CURVE_CUSTOM}, /* X25519 (29) */
+};
+
+static const unsigned char ecformats_default[] = {
+ TLSEXT_ECPOINTFORMAT_uncompressed,
+ TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime,
+ TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2
+};
+
+/* The default curves */
+static const unsigned char eccurves_default[] = {
+ 0, 29, /* X25519 (29) */
+ 0, 23, /* secp256r1 (23) */
+ 0, 25, /* secp521r1 (25) */
+ 0, 24, /* secp384r1 (24) */
+};
+
+static const unsigned char suiteb_curves[] = {
+ 0, TLSEXT_curve_P_256,
+ 0, TLSEXT_curve_P_384
+};
+
+int tls1_ec_curve_id2nid(int curve_id, unsigned int *pflags)
+{
+ const tls_curve_info *cinfo;
+ /* ECC curves from RFC 4492 and RFC 7027 */
+ if ((curve_id < 1) || ((unsigned int)curve_id > OSSL_NELEM(nid_list)))
+ return 0;
+ cinfo = nid_list + curve_id - 1;
+ if (pflags)
+ *pflags = cinfo->flags;
+ return cinfo->nid;
+}
+
+int tls1_ec_nid2curve_id(int nid)
+{
+ size_t i;
+ for (i = 0; i < OSSL_NELEM(nid_list); i++) {
+ if (nid_list[i].nid == nid)
+ return i + 1;
+ }
+ return 0;
+}
+
+/*
+ * Get curves list, if "sess" is set return client curves otherwise
+ * preferred list.
+ * Sets |num_curves| to the number of curves in the list, i.e.,
+ * the length of |pcurves| is 2 * num_curves.
+ * Returns 1 on success and 0 if the client curves list has invalid format.
+ * The latter indicates an internal error: we should not be accepting such
+ * lists in the first place.
+ * TODO(emilia): we should really be storing the curves list in explicitly
+ * parsed form instead. (However, this would affect binary compatibility
+ * so cannot happen in the 1.0.x series.)
+ */
+static int tls1_get_curvelist(SSL *s, int sess,
+ const unsigned char **pcurves, size_t *num_curves)
+{
+ size_t pcurveslen = 0;
+
+ if (sess) {
+ *pcurves = s->session->tlsext_ellipticcurvelist;
+ pcurveslen = s->session->tlsext_ellipticcurvelist_length;
+ } else {
+ /* For Suite B mode only include P-256, P-384 */
+ switch (tls1_suiteb(s)) {
+ case SSL_CERT_FLAG_SUITEB_128_LOS:
+ *pcurves = suiteb_curves;
+ pcurveslen = sizeof(suiteb_curves);
+ break;
+
+ case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY:
+ *pcurves = suiteb_curves;
+ pcurveslen = 2;
+ break;
+
+ case SSL_CERT_FLAG_SUITEB_192_LOS:
+ *pcurves = suiteb_curves + 2;
+ pcurveslen = 2;
+ break;
+ default:
+ *pcurves = s->tlsext_ellipticcurvelist;
+ pcurveslen = s->tlsext_ellipticcurvelist_length;
+ }
+ if (!*pcurves) {
+ *pcurves = eccurves_default;
+ pcurveslen = sizeof(eccurves_default);
+ }
+ }
+
+ /* We do not allow odd length arrays to enter the system. */
+ if (pcurveslen & 1) {
+ SSLerr(SSL_F_TLS1_GET_CURVELIST, ERR_R_INTERNAL_ERROR);
+ *num_curves = 0;
+ return 0;
+ }
+ *num_curves = pcurveslen / 2;
+ return 1;
+}
+
+/* See if curve is allowed by security callback */
+static int tls_curve_allowed(SSL *s, const unsigned char *curve, int op)
+{
+ const tls_curve_info *cinfo;
+ if (curve[0])
+ return 1;
+ if ((curve[1] < 1) || ((size_t)curve[1] > OSSL_NELEM(nid_list)))
+ return 0;
+ cinfo = &nid_list[curve[1] - 1];
+# ifdef OPENSSL_NO_EC2M
+ if (cinfo->flags & TLS_CURVE_CHAR2)
+ return 0;
+# endif
+ return ssl_security(s, op, cinfo->secbits, cinfo->nid, (void *)curve);
+}
+
+/* Check a curve is one of our preferences */
+int tls1_check_curve(SSL *s, const unsigned char *p, size_t len)
+{
+ const unsigned char *curves;
+ size_t num_curves, i;
+ unsigned int suiteb_flags = tls1_suiteb(s);
+ if (len != 3 || p[0] != NAMED_CURVE_TYPE)
+ return 0;
+ /* Check curve matches Suite B preferences */
+ if (suiteb_flags) {
+ unsigned long cid = s->s3->tmp.new_cipher->id;
+ if (p[1])
+ return 0;
+ if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) {
+ if (p[2] != TLSEXT_curve_P_256)
+ return 0;
+ } else if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) {
+ if (p[2] != TLSEXT_curve_P_384)
+ return 0;
+ } else /* Should never happen */
+ return 0;
+ }
+ if (!tls1_get_curvelist(s, 0, &curves, &num_curves))
+ return 0;
+ for (i = 0; i < num_curves; i++, curves += 2) {
+ if (p[1] == curves[0] && p[2] == curves[1])
+ return tls_curve_allowed(s, p + 1, SSL_SECOP_CURVE_CHECK);
+ }
+ return 0;
+}
+
+/*-
+ * For nmatch >= 0, return the NID of the |nmatch|th shared curve or NID_undef
+ * if there is no match.
+ * For nmatch == -1, return number of matches
+ * For nmatch == -2, return the NID of the curve to use for
+ * an EC tmp key, or NID_undef if there is no match.
+ */
+int tls1_shared_curve(SSL *s, int nmatch)
+{
+ const unsigned char *pref, *supp;
+ size_t num_pref, num_supp, i, j;
+ int k;
+
+ /* Can't do anything on client side */
+ if (s->server == 0)
+ return -1;
+ if (nmatch == -2) {
+ if (tls1_suiteb(s)) {
+ /*
+ * For Suite B ciphersuite determines curve: we already know
+ * these are acceptable due to previous checks.
+ */
+ unsigned long cid = s->s3->tmp.new_cipher->id;
+
+ if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
+ return NID_X9_62_prime256v1; /* P-256 */
+ if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
+ return NID_secp384r1; /* P-384 */
+ /* Should never happen */
+ return NID_undef;
+ }
+ /* If not Suite B just return first preference shared curve */
+ nmatch = 0;
+ }
+ /*
+ * Avoid truncation. tls1_get_curvelist takes an int
+ * but s->options is a long...
+ */
+ if (!tls1_get_curvelist(s,
+ (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) != 0,
+ &supp, &num_supp))
+ /* In practice, NID_undef == 0 but let's be precise. */
+ return nmatch == -1 ? 0 : NID_undef;
+ if (!tls1_get_curvelist(s,
+ (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) == 0,
+ &pref, &num_pref))
+ return nmatch == -1 ? 0 : NID_undef;
+
+ for (k = 0, i = 0; i < num_pref; i++, pref += 2) {
+ const unsigned char *tsupp = supp;
+
+ for (j = 0; j < num_supp; j++, tsupp += 2) {
+ if (pref[0] == tsupp[0] && pref[1] == tsupp[1]) {
+ if (!tls_curve_allowed(s, pref, SSL_SECOP_CURVE_SHARED))
+ continue;
+ if (nmatch == k) {
+ int id = (pref[0] << 8) | pref[1];
+
+ return tls1_ec_curve_id2nid(id, NULL);
+ }
+ k++;
+ }
+ }
+ }
+ if (nmatch == -1)
+ return k;
+ /* Out of range (nmatch > k). */
+ return NID_undef;
+}
+
+int tls1_set_curves(unsigned char **pext, size_t *pextlen,
+ int *curves, size_t ncurves)
+{
+ unsigned char *clist, *p;
+ size_t i;
+ /*
+ * Bitmap of curves included to detect duplicates: only works while curve
+ * ids < 32
+ */
+ unsigned long dup_list = 0;
+ clist = OPENSSL_malloc(ncurves * 2);
+ if (clist == NULL)
+ return 0;
+ for (i = 0, p = clist; i < ncurves; i++) {
+ unsigned long idmask;
+ int id;
+ id = tls1_ec_nid2curve_id(curves[i]);
+ idmask = 1L << id;
+ if (!id || (dup_list & idmask)) {
+ OPENSSL_free(clist);
+ return 0;
+ }
+ dup_list |= idmask;
+ s2n(id, p);
+ }
+ OPENSSL_free(*pext);
+ *pext = clist;
+ *pextlen = ncurves * 2;
+ return 1;
+}
+
+# define MAX_CURVELIST 28
+
+typedef struct {
+ size_t nidcnt;
+ int nid_arr[MAX_CURVELIST];
+} nid_cb_st;
+
+static int nid_cb(const char *elem, int len, void *arg)
+{
+ nid_cb_st *narg = arg;
+ size_t i;
+ int nid;
+ char etmp[20];
+ if (elem == NULL)
+ return 0;
+ if (narg->nidcnt == MAX_CURVELIST)
+ return 0;
+ if (len > (int)(sizeof(etmp) - 1))
+ return 0;
+ memcpy(etmp, elem, len);
+ etmp[len] = 0;
+ nid = EC_curve_nist2nid(etmp);
+ if (nid == NID_undef)
+ nid = OBJ_sn2nid(etmp);
+ if (nid == NID_undef)
+ nid = OBJ_ln2nid(etmp);
+ if (nid == NID_undef)
+ return 0;
+ for (i = 0; i < narg->nidcnt; i++)
+ if (narg->nid_arr[i] == nid)
+ return 0;
+ narg->nid_arr[narg->nidcnt++] = nid;
+ return 1;
+}
+
+/* Set curves based on a colon separate list */
+int tls1_set_curves_list(unsigned char **pext, size_t *pextlen, const char *str)
+{
+ nid_cb_st ncb;
+ ncb.nidcnt = 0;
+ if (!CONF_parse_list(str, ':', 1, nid_cb, &ncb))
+ return 0;
+ if (pext == NULL)
+ return 1;
+ return tls1_set_curves(pext, pextlen, ncb.nid_arr, ncb.nidcnt);
+}
+
+/* For an EC key set TLS id and required compression based on parameters */
+static int tls1_set_ec_id(unsigned char *curve_id, unsigned char *comp_id,
+ EC_KEY *ec)
+{
+ int id;
+ const EC_GROUP *grp;
+ if (!ec)
+ return 0;
+ /* Determine if it is a prime field */
+ grp = EC_KEY_get0_group(ec);
+ if (!grp)
+ return 0;
+ /* Determine curve ID */
+ id = EC_GROUP_get_curve_name(grp);
+ id = tls1_ec_nid2curve_id(id);
+ /* If no id return error: we don't support arbitrary explicit curves */
+ if (id == 0)
+ return 0;
+ curve_id[0] = 0;
+ curve_id[1] = (unsigned char)id;
+ if (comp_id) {
+ if (EC_KEY_get0_public_key(ec) == NULL)
+ return 0;
+ if (EC_KEY_get_conv_form(ec) == POINT_CONVERSION_UNCOMPRESSED) {
+ *comp_id = TLSEXT_ECPOINTFORMAT_uncompressed;
+ } else {
+ if ((nid_list[id - 1].flags & TLS_CURVE_TYPE) == TLS_CURVE_PRIME)
+ *comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
+ else
+ *comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
+ }
+ }
+ return 1;
+}
+
+/* Check an EC key is compatible with extensions */
+static int tls1_check_ec_key(SSL *s,
+ unsigned char *curve_id, unsigned char *comp_id)
+{
+ const unsigned char *pformats, *pcurves;
+ size_t num_formats, num_curves, i;
+ int j;
+ /*
+ * If point formats extension present check it, otherwise everything is
+ * supported (see RFC4492).
+ */
+ if (comp_id && s->session->tlsext_ecpointformatlist) {
+ pformats = s->session->tlsext_ecpointformatlist;
+ num_formats = s->session->tlsext_ecpointformatlist_length;
+ for (i = 0; i < num_formats; i++, pformats++) {
+ if (*comp_id == *pformats)
+ break;
+ }
+ if (i == num_formats)
+ return 0;
+ }
+ if (!curve_id)
+ return 1;
+ /* Check curve is consistent with client and server preferences */
+ for (j = 0; j <= 1; j++) {
+ if (!tls1_get_curvelist(s, j, &pcurves, &num_curves))
+ return 0;
+ if (j == 1 && num_curves == 0) {
+ /*
+ * If we've not received any curves then skip this check.
+ * RFC 4492 does not require the supported elliptic curves extension
+ * so if it is not sent we can just choose any curve.
+ * It is invalid to send an empty list in the elliptic curves
+ * extension, so num_curves == 0 always means no extension.
+ */
+ break;
+ }
+ for (i = 0; i < num_curves; i++, pcurves += 2) {
+ if (pcurves[0] == curve_id[0] && pcurves[1] == curve_id[1])
+ break;
+ }
+ if (i == num_curves)
+ return 0;
+ /* For clients can only check sent curve list */
+ if (!s->server)
+ break;
+ }
+ return 1;
+}
+
+static void tls1_get_formatlist(SSL *s, const unsigned char **pformats,
+ size_t *num_formats)
+{
+ /*
+ * If we have a custom point format list use it otherwise use default
+ */
+ if (s->tlsext_ecpointformatlist) {
+ *pformats = s->tlsext_ecpointformatlist;
+ *num_formats = s->tlsext_ecpointformatlist_length;
+ } else {
+ *pformats = ecformats_default;
+ /* For Suite B we don't support char2 fields */
+ if (tls1_suiteb(s))
+ *num_formats = sizeof(ecformats_default) - 1;
+ else
+ *num_formats = sizeof(ecformats_default);
+ }
+}
+
+/*
+ * Check cert parameters compatible with extensions: currently just checks EC
+ * certificates have compatible curves and compression.
+ */
+static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md)
+{
+ unsigned char comp_id, curve_id[2];
+ EVP_PKEY *pkey;
+ int rv;
+ pkey = X509_get0_pubkey(x);
+ if (!pkey)
+ return 0;
+ /* If not EC nothing to do */
+ if (EVP_PKEY_id(pkey) != EVP_PKEY_EC)
+ return 1;
+ rv = tls1_set_ec_id(curve_id, &comp_id, EVP_PKEY_get0_EC_KEY(pkey));
+ if (!rv)
+ return 0;
+ /*
+ * Can't check curve_id for client certs as we don't have a supported
+ * curves extension.
+ */
+ rv = tls1_check_ec_key(s, s->server ? curve_id : NULL, &comp_id);
+ if (!rv)
+ return 0;
+ /*
+ * Special case for suite B. We *MUST* sign using SHA256+P-256 or
+ * SHA384+P-384, adjust digest if necessary.
+ */
+ if (set_ee_md && tls1_suiteb(s)) {
+ int check_md;
+ size_t i;
+ CERT *c = s->cert;
+ if (curve_id[0])
+ return 0;
+ /* Check to see we have necessary signing algorithm */
+ if (curve_id[1] == TLSEXT_curve_P_256)
+ check_md = NID_ecdsa_with_SHA256;
+ else if (curve_id[1] == TLSEXT_curve_P_384)
+ check_md = NID_ecdsa_with_SHA384;
+ else
+ return 0; /* Should never happen */
+ for (i = 0; i < c->shared_sigalgslen; i++)
+ if (check_md == c->shared_sigalgs[i].signandhash_nid)
+ break;
+ if (i == c->shared_sigalgslen)
+ return 0;
+ if (set_ee_md == 2) {
+ if (check_md == NID_ecdsa_with_SHA256)
+ s->s3->tmp.md[SSL_PKEY_ECC] = EVP_sha256();
+ else
+ s->s3->tmp.md[SSL_PKEY_ECC] = EVP_sha384();
+ }
+ }
+ return rv;
+}
+
+# ifndef OPENSSL_NO_EC
+/*
+ * tls1_check_ec_tmp_key - Check EC temporary key compatibility
+ * @s: SSL connection
+ * @cid: Cipher ID we're considering using
+ *
+ * Checks that the kECDHE cipher suite we're considering using
+ * is compatible with the client extensions.
+ *
+ * Returns 0 when the cipher can't be used or 1 when it can.
+ */
+int tls1_check_ec_tmp_key(SSL *s, unsigned long cid)
+{
+ /*
+ * If Suite B, AES128 MUST use P-256 and AES256 MUST use P-384, no other
+ * curves permitted.
+ */
+ if (tls1_suiteb(s)) {
+ unsigned char curve_id[2];
+ /* Curve to check determined by ciphersuite */
+ if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
+ curve_id[1] = TLSEXT_curve_P_256;
+ else if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
+ curve_id[1] = TLSEXT_curve_P_384;
+ else
+ return 0;
+ curve_id[0] = 0;
+ /* Check this curve is acceptable */
+ if (!tls1_check_ec_key(s, curve_id, NULL))
+ return 0;
+ return 1;
+ }
+ /* Need a shared curve */
+ if (tls1_shared_curve(s, 0))
+ return 1;
+ return 0;
+}
+# endif /* OPENSSL_NO_EC */
+
+#else
+
+static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md)
+{
+ return 1;
+}
+
+#endif /* OPENSSL_NO_EC */
+
+/*
+ * List of supported signature algorithms and hashes. Should make this
+ * customisable at some point, for now include everything we support.
+ */
+
+#ifdef OPENSSL_NO_RSA
+# define tlsext_sigalg_rsa(md) /* */
+#else
+# define tlsext_sigalg_rsa(md) md, TLSEXT_signature_rsa,
+#endif
+
+#ifdef OPENSSL_NO_DSA
+# define tlsext_sigalg_dsa(md) /* */
+#else
+# define tlsext_sigalg_dsa(md) md, TLSEXT_signature_dsa,
+#endif
+
+#ifdef OPENSSL_NO_EC
+# define tlsext_sigalg_ecdsa(md)/* */
+#else
+# define tlsext_sigalg_ecdsa(md) md, TLSEXT_signature_ecdsa,
+#endif
+
+#define tlsext_sigalg(md) \
+ tlsext_sigalg_rsa(md) \
+ tlsext_sigalg_dsa(md) \
+ tlsext_sigalg_ecdsa(md)
+
+static const unsigned char tls12_sigalgs[] = {
+ tlsext_sigalg(TLSEXT_hash_sha512)
+ tlsext_sigalg(TLSEXT_hash_sha384)
+ tlsext_sigalg(TLSEXT_hash_sha256)
+ tlsext_sigalg(TLSEXT_hash_sha224)
+ tlsext_sigalg(TLSEXT_hash_sha1)
+#ifndef OPENSSL_NO_GOST
+ TLSEXT_hash_gostr3411, TLSEXT_signature_gostr34102001,
+ TLSEXT_hash_gostr34112012_256, TLSEXT_signature_gostr34102012_256,
+ TLSEXT_hash_gostr34112012_512, TLSEXT_signature_gostr34102012_512
+#endif
+};
+
+#ifndef OPENSSL_NO_EC
+static const unsigned char suiteb_sigalgs[] = {
+ tlsext_sigalg_ecdsa(TLSEXT_hash_sha256)
+ tlsext_sigalg_ecdsa(TLSEXT_hash_sha384)
+};
+#endif
+size_t tls12_get_psigalgs(SSL *s, int sent, const unsigned char **psigs)
+{
+ /*
+ * If Suite B mode use Suite B sigalgs only, ignore any other
+ * preferences.
+ */
+#ifndef OPENSSL_NO_EC
+ switch (tls1_suiteb(s)) {
+ case SSL_CERT_FLAG_SUITEB_128_LOS:
+ *psigs = suiteb_sigalgs;
+ return sizeof(suiteb_sigalgs);
+
+ case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY:
+ *psigs = suiteb_sigalgs;
+ return 2;
+
+ case SSL_CERT_FLAG_SUITEB_192_LOS:
+ *psigs = suiteb_sigalgs + 2;
+ return 2;
+ }
+#endif
+ /* If server use client authentication sigalgs if not NULL */
+ if (s->server == sent && s->cert->client_sigalgs) {
+ *psigs = s->cert->client_sigalgs;
+ return s->cert->client_sigalgslen;
+ } else if (s->cert->conf_sigalgs) {
+ *psigs = s->cert->conf_sigalgs;
+ return s->cert->conf_sigalgslen;
+ } else {
+ *psigs = tls12_sigalgs;
+ return sizeof(tls12_sigalgs);
+ }
+}
+
+/*
+ * Check signature algorithm is consistent with sent supported signature
+ * algorithms and if so return relevant digest.
+ */
+int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
+ const unsigned char *sig, EVP_PKEY *pkey)
+{
+ const unsigned char *sent_sigs;
+ size_t sent_sigslen, i;
+ int sigalg = tls12_get_sigid(pkey);
+ /* Should never happen */
+ if (sigalg == -1)
+ return -1;
+ /* Check key type is consistent with signature */
+ if (sigalg != (int)sig[1]) {
+ SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
+ return 0;
+ }
+#ifndef OPENSSL_NO_EC
+ if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) {
+ unsigned char curve_id[2], comp_id;
+ /* Check compression and curve matches extensions */
+ if (!tls1_set_ec_id(curve_id, &comp_id, EVP_PKEY_get0_EC_KEY(pkey)))
+ return 0;
+ if (!s->server && !tls1_check_ec_key(s, curve_id, &comp_id)) {
+ SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE);
+ return 0;
+ }
+ /* If Suite B only P-384+SHA384 or P-256+SHA-256 allowed */
+ if (tls1_suiteb(s)) {
+ if (curve_id[0])
+ return 0;
+ if (curve_id[1] == TLSEXT_curve_P_256) {
+ if (sig[0] != TLSEXT_hash_sha256) {
+ SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,
+ SSL_R_ILLEGAL_SUITEB_DIGEST);
+ return 0;
+ }
+ } else if (curve_id[1] == TLSEXT_curve_P_384) {
+ if (sig[0] != TLSEXT_hash_sha384) {
+ SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,
+ SSL_R_ILLEGAL_SUITEB_DIGEST);
+ return 0;
+ }
+ } else
+ return 0;
+ }
+ } else if (tls1_suiteb(s))
+ return 0;
+#endif
+
+ /* Check signature matches a type we sent */
+ sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs);
+ for (i = 0; i < sent_sigslen; i += 2, sent_sigs += 2) {
+ if (sig[0] == sent_sigs[0] && sig[1] == sent_sigs[1])
+ break;
+ }
+ /* Allow fallback to SHA1 if not strict mode */
+ if (i == sent_sigslen
+ && (sig[0] != TLSEXT_hash_sha1
+ || s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)) {
+ SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
+ return 0;
+ }
+ *pmd = tls12_get_hash(sig[0]);
+ if (*pmd == NULL) {
+ SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_UNKNOWN_DIGEST);
+ return 0;
+ }
+ /* Make sure security callback allows algorithm */
+ if (!ssl_security(s, SSL_SECOP_SIGALG_CHECK,
+ EVP_MD_size(*pmd) * 4, EVP_MD_type(*pmd), (void *)sig)) {
+ SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
+ return 0;
+ }
+ /*
+ * Store the digest used so applications can retrieve it if they wish.
+ */
+ s->s3->tmp.peer_md = *pmd;
+ return 1;
+}
+
+/*
+ * Set a mask of disabled algorithms: an algorithm is disabled if it isn't
+ * supported, doesn't appear in supported signature algorithms, isn't supported
+ * by the enabled protocol versions or by the security level.
+ *
+ * This function should only be used for checking which ciphers are supported
+ * by the client.
+ *
+ * Call ssl_cipher_disabled() to check that it's enabled or not.
+ */
+void ssl_set_client_disabled(SSL *s)
+{
+ s->s3->tmp.mask_a = 0;
+ s->s3->tmp.mask_k = 0;
+ ssl_set_sig_mask(&s->s3->tmp.mask_a, s, SSL_SECOP_SIGALG_MASK);
+ ssl_get_client_min_max_version(s, &s->s3->tmp.min_ver, &s->s3->tmp.max_ver);
+#ifndef OPENSSL_NO_PSK
+ /* with PSK there must be client callback set */
+ if (!s->psk_client_callback) {
+ s->s3->tmp.mask_a |= SSL_aPSK;
+ s->s3->tmp.mask_k |= SSL_PSK;
+ }
+#endif /* OPENSSL_NO_PSK */
+#ifndef OPENSSL_NO_SRP
+ if (!(s->srp_ctx.srp_Mask & SSL_kSRP)) {
+ s->s3->tmp.mask_a |= SSL_aSRP;
+ s->s3->tmp.mask_k |= SSL_kSRP;
+ }
+#endif
+}
+
+/*
+ * ssl_cipher_disabled - check that a cipher is disabled or not
+ * @s: SSL connection that you want to use the cipher on
+ * @c: cipher to check
+ * @op: Security check that you want to do
+ * @ecdhe: If set to 1 then TLSv1 ECDHE ciphers are also allowed in SSLv3
+ *
+ * Returns 1 when it's disabled, 0 when enabled.
+ */
+int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op, int ecdhe)
+{
+ if (c->algorithm_mkey & s->s3->tmp.mask_k
+ || c->algorithm_auth & s->s3->tmp.mask_a)
+ return 1;
+ if (s->s3->tmp.max_ver == 0)
+ return 1;
+ if (!SSL_IS_DTLS(s)) {
+ int min_tls = c->min_tls;
+
+ /*
+ * For historical reasons we will allow ECHDE to be selected by a server
+ * in SSLv3 if we are a client
+ */
+ if (min_tls == TLS1_VERSION && ecdhe
+ && (c->algorithm_mkey & (SSL_kECDHE | SSL_kECDHEPSK)) != 0)
+ min_tls = SSL3_VERSION;
+
+ if ((min_tls > s->s3->tmp.max_ver) || (c->max_tls < s->s3->tmp.min_ver))
+ return 1;
+ }
+ if (SSL_IS_DTLS(s) && (DTLS_VERSION_GT(c->min_dtls, s->s3->tmp.max_ver)
+ || DTLS_VERSION_LT(c->max_dtls, s->s3->tmp.min_ver)))
+ return 1;
+
+ return !ssl_security(s, op, c->strength_bits, 0, (void *)c);
+}
+
+static int tls_use_ticket(SSL *s)
+{
+ if (s->options & SSL_OP_NO_TICKET)
+ return 0;
+ return ssl_security(s, SSL_SECOP_TICKET, 0, 0, NULL);
+}
+
+static int compare_uint(const void *p1, const void *p2)
+{
+ unsigned int u1 = *((const unsigned int *)p1);
+ unsigned int u2 = *((const unsigned int *)p2);
+ if (u1 < u2)
+ return -1;
+ else if (u1 > u2)
+ return 1;
+ else
+ return 0;
+}
+
+/*
+ * 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 does an initial scan over the extensions block to filter those
+ * out. It returns 1 if all extensions are unique, and 0 if the extensions
+ * contain duplicates, could not be successfully parsed, or an internal error
+ * occurred.
+ */
+static int tls1_check_duplicate_extensions(const PACKET *packet)
+{
+ PACKET extensions = *packet;
+ size_t num_extensions = 0, i = 0;
+ unsigned int *extension_types = NULL;
+ int ret = 0;
+
+ /* First pass: count the extensions. */
+ while (PACKET_remaining(&extensions) > 0) {
+ unsigned int type;
+ PACKET extension;
+ if (!PACKET_get_net_2(&extensions, &type) ||
+ !PACKET_get_length_prefixed_2(&extensions, &extension)) {
+ goto done;
+ }
+ num_extensions++;
+ }
+
+ if (num_extensions <= 1)
+ return 1;
+
+ extension_types = OPENSSL_malloc(sizeof(unsigned int) * num_extensions);
+ if (extension_types == NULL) {
+ SSLerr(SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS, ERR_R_MALLOC_FAILURE);
+ goto done;
+ }
+
+ /* Second pass: gather the extension types. */
+ extensions = *packet;
+ for (i = 0; i < num_extensions; i++) {
+ PACKET extension;
+ if (!PACKET_get_net_2(&extensions, &extension_types[i]) ||
+ !PACKET_get_length_prefixed_2(&extensions, &extension)) {
+ /* This should not happen. */
+ SSLerr(SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS, ERR_R_INTERNAL_ERROR);
+ goto done;
+ }
+ }
+
+ if (PACKET_remaining(&extensions) != 0) {
+ SSLerr(SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS, ERR_R_INTERNAL_ERROR);
+ goto done;
+ }
+ /* Sort the extensions and make sure there are no duplicates. */
+ qsort(extension_types, num_extensions, sizeof(unsigned int), compare_uint);
+ for (i = 1; i < num_extensions; i++) {
+ if (extension_types[i - 1] == extension_types[i])
+ goto done;
+ }
+ ret = 1;
+ done:
+ OPENSSL_free(extension_types);
+ return ret;
+}
+
+unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf,
+ unsigned char *limit, int *al)
+{
+ int extdatalen = 0;
+ unsigned char *orig = buf;
+ unsigned char *ret = buf;
+#ifndef OPENSSL_NO_EC
+ /* See if we support any ECC ciphersuites */
+ int using_ecc = 0;
+ if (s->version >= TLS1_VERSION || SSL_IS_DTLS(s)) {
+ int i;
+ unsigned long alg_k, alg_a;
+ STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(s);
+
+ for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); 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)) {
+ using_ecc = 1;
+ break;
+ }
+ }
+ }
+#endif
+
+ ret += 2;
+
+ if (ret >= limit)
+ return NULL; /* this really never occurs, but ... */
+
+ /* Add RI if renegotiating */
+ if (s->renegotiate) {
+ int el;
+
+ if (!ssl_add_clienthello_renegotiate_ext(s, 0, &el, 0)) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ if (CHECKLEN(ret, 4 + el, limit))
+ return NULL;
+
+ s2n(TLSEXT_TYPE_renegotiate, ret);
+ s2n(el, ret);
+
+ if (!ssl_add_clienthello_renegotiate_ext(s, ret, &el, el)) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ ret += el;
+ }
+ /* Only add RI for SSLv3 */
+ if (s->client_version == SSL3_VERSION)
+ goto done;
+
+ if (s->tlsext_hostname != NULL) {
+ /* Add TLS extension servername to the Client Hello message */
+ size_t size_str;
+
+ /*-
+ * check for enough space.
+ * 4 for the servername type and extension length
+ * 2 for servernamelist length
+ * 1 for the hostname type
+ * 2 for hostname length
+ * + hostname length
+ */
+ size_str = strlen(s->tlsext_hostname);
+ if (CHECKLEN(ret, 9 + size_str, limit))
+ return NULL;
+
+ /* extension type and length */
+ s2n(TLSEXT_TYPE_server_name, ret);
+ s2n(size_str + 5, ret);
+
+ /* length of servername list */
+ s2n(size_str + 3, ret);
+
+ /* hostname type, length and hostname */
+ *(ret++) = (unsigned char)TLSEXT_NAMETYPE_host_name;
+ s2n(size_str, ret);
+ memcpy(ret, s->tlsext_hostname, size_str);
+ ret += size_str;
+ }
+#ifndef OPENSSL_NO_SRP
+ /* Add SRP username if there is one */
+ if (s->srp_ctx.login != NULL) { /* Add TLS extension SRP username to the
+ * Client Hello message */
+
+ size_t login_len = strlen(s->srp_ctx.login);
+ if (login_len > 255 || login_len == 0) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ /*-
+ * check for enough space.
+ * 4 for the srp type type and extension length
+ * 1 for the srp user identity
+ * + srp user identity length
+ */
+ if (CHECKLEN(ret, 5 + login_len, limit))
+ return NULL;
+
+ /* fill in the extension */
+ s2n(TLSEXT_TYPE_srp, ret);
+ s2n(login_len + 1, ret);
+ (*ret++) = (unsigned char)login_len;
+ memcpy(ret, s->srp_ctx.login, login_len);
+ ret += login_len;
+ }
+#endif
+
+#ifndef OPENSSL_NO_EC
+ if (using_ecc) {
+ /*
+ * Add TLS extension ECPointFormats to the ClientHello message
+ */
+ const unsigned char *pcurves, *pformats;
+ size_t num_curves, num_formats, curves_list_len;
+ size_t i;
+ unsigned char *etmp;
+
+ tls1_get_formatlist(s, &pformats, &num_formats);
+
+ if (num_formats > 255) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+ /*-
+ * check for enough space.
+ * 4 bytes for the ec point formats type and extension length
+ * 1 byte for the length of the formats
+ * + formats length
+ */
+ if (CHECKLEN(ret, 5 + num_formats, limit))
+ return NULL;
+
+ s2n(TLSEXT_TYPE_ec_point_formats, ret);
+ /* The point format list has 1-byte length. */
+ s2n(num_formats + 1, ret);
+ *(ret++) = (unsigned char)num_formats;
+ memcpy(ret, pformats, num_formats);
+ ret += num_formats;
+
+ /*
+ * Add TLS extension EllipticCurves to the ClientHello message
+ */
+ pcurves = s->tlsext_ellipticcurvelist;
+ if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves))
+ return NULL;
+
+ if (num_curves > 65532 / 2) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+ /*-
+ * check for enough space.
+ * 4 bytes for the ec curves type and extension length
+ * 2 bytes for the curve list length
+ * + curve list length
+ */
+ if (CHECKLEN(ret, 6 + (num_curves * 2), limit))
+ return NULL;
+
+ s2n(TLSEXT_TYPE_elliptic_curves, ret);
+ etmp = ret + 4;
+ /* Copy curve ID if supported */
+ for (i = 0; i < num_curves; i++, pcurves += 2) {
+ if (tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED)) {
+ *etmp++ = pcurves[0];
+ *etmp++ = pcurves[1];
+ }
+ }
+
+ curves_list_len = etmp - ret - 4;
+
+ s2n(curves_list_len + 2, ret);
+ s2n(curves_list_len, ret);
+ ret += curves_list_len;
+ }
+#endif /* OPENSSL_NO_EC */
+
+ if (tls_use_ticket(s)) {
+ size_t ticklen;
+ if (!s->new_session && s->session && s->session->tlsext_tick)
+ ticklen = s->session->tlsext_ticklen;
+ else if (s->session && s->tlsext_session_ticket &&
+ s->tlsext_session_ticket->data) {
+ ticklen = s->tlsext_session_ticket->length;
+ s->session->tlsext_tick = OPENSSL_malloc(ticklen);
+ if (s->session->tlsext_tick == NULL)
+ return NULL;
+ memcpy(s->session->tlsext_tick,
+ s->tlsext_session_ticket->data, ticklen);
+ s->session->tlsext_ticklen = ticklen;
+ } else
+ ticklen = 0;
+ if (ticklen == 0 && s->tlsext_session_ticket &&
+ s->tlsext_session_ticket->data == NULL)
+ goto skip_ext;
+ /*
+ * Check for enough room 2 for extension type, 2 for len rest for
+ * ticket
+ */
+ if (CHECKLEN(ret, 4 + ticklen, limit))
+ return NULL;
+ s2n(TLSEXT_TYPE_session_ticket, ret);
+ s2n(ticklen, ret);
+ if (ticklen > 0) {
+ memcpy(ret, s->session->tlsext_tick, ticklen);
+ ret += ticklen;
+ }
+ }
+ skip_ext:
+
+#ifndef OPENSSL_NO_OCSP
+ if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) {
+ int i;
+ size_t extlen, idlen;
+ int lentmp;
+ OCSP_RESPID *id;
+
+ idlen = 0;
+ for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++) {
+ id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i);
+ lentmp = i2d_OCSP_RESPID(id, NULL);
+ if (lentmp <= 0)
+ return NULL;
+ idlen += (size_t)lentmp + 2;
+ }
+
+ if (s->tlsext_ocsp_exts) {
+ lentmp = i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, NULL);
+ if (lentmp < 0)
+ return NULL;
+ extlen = (size_t)lentmp;
+ } else
+ extlen = 0;
+
+ if (extlen + idlen > 0xFFF0)
+ return NULL;
+ /*
+ * 2 bytes for status request type
+ * 2 bytes for status request len
+ * 1 byte for OCSP request type
+ * 2 bytes for length of ids
+ * 2 bytes for length of extensions
+ * + length of ids
+ * + length of extensions
+ */
+ if (CHECKLEN(ret, 9 + idlen + extlen, limit))
+ return NULL;
+
+ s2n(TLSEXT_TYPE_status_request, ret);
+ s2n(extlen + idlen + 5, ret);
+ *(ret++) = TLSEXT_STATUSTYPE_ocsp;
+ s2n(idlen, ret);
+ for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++) {
+ /* save position of id len */
+ unsigned char *q = ret;
+ id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i);
+ /* skip over id len */
+ ret += 2;
+ lentmp = i2d_OCSP_RESPID(id, &ret);
+ /* write id len */
+ s2n(lentmp, q);
+ }
+ s2n(extlen, ret);
+ if (extlen > 0)
+ i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &ret);
+ }
+#endif
+#ifndef OPENSSL_NO_HEARTBEATS
+ if (SSL_IS_DTLS(s)) {
+ /* Add Heartbeat extension */
+
+ /*-
+ * check for enough space.
+ * 4 bytes for the heartbeat ext type and extension length
+ * 1 byte for the mode
+ */
+ if (CHECKLEN(ret, 5, limit))
+ return NULL;
+
+ s2n(TLSEXT_TYPE_heartbeat, ret);
+ s2n(1, ret);
+ /*-
+ * Set mode:
+ * 1: peer may send requests
+ * 2: peer not allowed to send requests
+ */
+ if (s->tlsext_heartbeat & SSL_DTLSEXT_HB_DONT_RECV_REQUESTS)
+ *(ret++) = SSL_DTLSEXT_HB_DONT_SEND_REQUESTS;
+ else
+ *(ret++) = SSL_DTLSEXT_HB_ENABLED;
+ }
+#endif
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ if (s->ctx->next_proto_select_cb && !s->s3->tmp.finish_md_len) {
+ /*
+ * The client advertises an empty extension to indicate its support
+ * for Next Protocol Negotiation
+ */
+
+ /*-
+ * check for enough space.
+ * 4 bytes for the NPN ext type and extension length
+ */
+ if (CHECKLEN(ret, 4, limit))
+ return NULL;
+ s2n(TLSEXT_TYPE_next_proto_neg, ret);
+ s2n(0, ret);
+ }
+#endif
+
+ /*
+ * finish_md_len is non-zero during a renegotiation, so
+ * this avoids sending ALPN during the renegotiation
+ * (see longer comment below)
+ */
+ if (s->alpn_client_proto_list && !s->s3->tmp.finish_md_len) {
+ /*-
+ * check for enough space.
+ * 4 bytes for the ALPN type and extension length
+ * 2 bytes for the ALPN protocol list length
+ * + ALPN protocol list length
+ */
+ if (CHECKLEN(ret, 6 + s->alpn_client_proto_list_len, limit))
+ return NULL;
+ s2n(TLSEXT_TYPE_application_layer_protocol_negotiation, ret);
+ s2n(2 + s->alpn_client_proto_list_len, ret);
+ s2n(s->alpn_client_proto_list_len, ret);
+ memcpy(ret, s->alpn_client_proto_list, s->alpn_client_proto_list_len);
+ ret += s->alpn_client_proto_list_len;
+ s->s3->alpn_sent = 1;
+ }
+#ifndef OPENSSL_NO_SRTP
+ if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)) {
+ int el;
+
+ /* Returns 0 on success!! */
+ if (ssl_add_clienthello_use_srtp_ext(s, 0, &el, 0)) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ /*-
+ * check for enough space.
+ * 4 bytes for the SRTP type and extension length
+ * + SRTP profiles length
+ */
+ if (CHECKLEN(ret, 4 + el, limit))
+ return NULL;
+
+ s2n(TLSEXT_TYPE_use_srtp, ret);
+ s2n(el, ret);
+
+ if (ssl_add_clienthello_use_srtp_ext(s, ret, &el, el)) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+ ret += el;
+ }
+#endif
+ custom_ext_init(&s->cert->cli_ext);
+ /* Add custom TLS Extensions to ClientHello */
+ if (!custom_ext_add(s, 0, &ret, limit, al))
+ return NULL;
+ /*
+ * In 1.1.0 before 1.1.0c we negotiated EtM with DTLS, then just
+ * silently failed to actually do it. It is fixed in 1.1.1 but to
+ * ease the transition especially from 1.1.0b to 1.1.0c, we just
+ * disable it in 1.1.0.
+ * Also skip if SSL_OP_NO_ENCRYPT_THEN_MAC is set.
+ */
+ if (!SSL_IS_DTLS(s) && !(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)) {
+ /*-
+ * check for enough space.
+ * 4 bytes for the ETM type and extension length
+ */
+ if (CHECKLEN(ret, 4, limit))
+ return NULL;
+ s2n(TLSEXT_TYPE_encrypt_then_mac, ret);
+ s2n(0, ret);
+ }
+
+#ifndef OPENSSL_NO_CT
+ if (s->ct_validation_callback != NULL) {
+ /*-
+ * check for enough space.
+ * 4 bytes for the SCT type and extension length
+ */
+ if (CHECKLEN(ret, 4, limit))
+ return NULL;
+
+ s2n(TLSEXT_TYPE_signed_certificate_timestamp, ret);
+ s2n(0, ret);
+ }
+#endif
+
+ /*-
+ * check for enough space.
+ * 4 bytes for the EMS type and extension length
+ */
+ if (CHECKLEN(ret, 4, limit))
+ return NULL;
+ s2n(TLSEXT_TYPE_extended_master_secret, ret);
+ s2n(0, ret);
+
+ /*
+ * WebSphere application server can not handle having the
+ * last extension be 0-length (e.g. EMS, EtM), so keep those
+ * before SigAlgs
+ */
+ if (SSL_CLIENT_USE_SIGALGS(s)) {
+ size_t salglen;
+ const unsigned char *salg;
+ unsigned char *etmp;
+ salglen = tls12_get_psigalgs(s, 1, &salg);
+
+ /*-
+ * check for enough space.
+ * 4 bytes for the sigalgs type and extension length
+ * 2 bytes for the sigalg list length
+ * + sigalg list length
+ */
+ if (CHECKLEN(ret, salglen + 6, limit))
+ return NULL;
+ s2n(TLSEXT_TYPE_signature_algorithms, ret);
+ etmp = ret;
+ /* Skip over lengths for now */
+ ret += 4;
+ salglen = tls12_copy_sigalgs(s, ret, salg, salglen);
+ /* Fill in lengths */
+ s2n(salglen + 2, etmp);
+ s2n(salglen, etmp);
+ ret += salglen;
+ }
+
+ /*
+ * Add padding to workaround bugs in F5 terminators. See
+ * https://tools.ietf.org/html/draft-agl-tls-padding-03 NB: because this
+ * code works out the length of all existing extensions it MUST always
+ * appear last. WebSphere 7.x/8.x is intolerant of empty extensions
+ * being last, so minimum length of 1.
+ */
+ if (s->options & SSL_OP_TLSEXT_PADDING) {
+ int hlen = ret - (unsigned char *)s->init_buf->data;
+
+ if (hlen > 0xff && hlen < 0x200) {
+ hlen = 0x200 - hlen;
+ if (hlen >= 4)
+ hlen -= 4;
+ else
+ hlen = 1;
+
+ /*-
+ * check for enough space. Strictly speaking we know we've already
+ * got enough space because to get here the message size is < 0x200,
+ * but we know that we've allocated far more than that in the buffer
+ * - but for consistency and robustness we're going to check anyway.
+ *
+ * 4 bytes for the padding type and extension length
+ * + padding length
+ */
+ if (CHECKLEN(ret, 4 + hlen, limit))
+ return NULL;
+ s2n(TLSEXT_TYPE_padding, ret);
+ s2n(hlen, ret);
+ memset(ret, 0, hlen);
+ ret += hlen;
+ }
+ }
+
+ done:
+
+ if ((extdatalen = ret - orig - 2) == 0)
+ return orig;
+
+ s2n(extdatalen, orig);
+ return ret;
+}
+
+unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
+ unsigned char *limit, int *al)
+{
+ int extdatalen = 0;
+ unsigned char *orig = buf;
+ unsigned char *ret = buf;
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ int next_proto_neg_seen;
+#endif
+#ifndef OPENSSL_NO_EC
+ 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);
+ using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL);
+#endif
+
+ ret += 2;
+ if (ret >= limit)
+ return NULL; /* this really never occurs, but ... */
+
+ if (s->s3->send_connection_binding) {
+ int el;
+
+ /* Still add this even if SSL_OP_NO_RENEGOTIATION is set */
+ if (!ssl_add_serverhello_renegotiate_ext(s, 0, &el, 0)) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ /*-
+ * check for enough space.
+ * 4 bytes for the reneg type and extension length
+ * + reneg data length
+ */
+ if (CHECKLEN(ret, 4 + el, limit))
+ return NULL;
+
+ s2n(TLSEXT_TYPE_renegotiate, ret);
+ s2n(el, ret);
+
+ if (!ssl_add_serverhello_renegotiate_ext(s, ret, &el, el)) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ ret += el;
+ }
+
+ /* Only add RI for SSLv3 */
+ if (s->version == SSL3_VERSION)
+ goto done;
+
+ if (!s->hit && s->servername_done == 1
+ && s->session->tlsext_hostname != NULL) {
+ /*-
+ * check for enough space.
+ * 4 bytes for the server name type and extension length
+ */
+ if (CHECKLEN(ret, 4, limit))
+ return NULL;
+
+ s2n(TLSEXT_TYPE_server_name, ret);
+ s2n(0, ret);
+ }
+#ifndef OPENSSL_NO_EC
+ if (using_ecc) {
+ const unsigned char *plist;
+ size_t plistlen;
+ /*
+ * Add TLS extension ECPointFormats to the ServerHello message
+ */
+
+ tls1_get_formatlist(s, &plist, &plistlen);
+
+ if (plistlen > 255) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ /*-
+ * check for enough space.
+ * 4 bytes for the ec points format type and extension length
+ * 1 byte for the points format list length
+ * + length of points format list
+ */
+ if (CHECKLEN(ret, 5 + plistlen, limit))
+ return NULL;
+
+ s2n(TLSEXT_TYPE_ec_point_formats, ret);
+ s2n(plistlen + 1, ret);
+ *(ret++) = (unsigned char)plistlen;
+ memcpy(ret, plist, plistlen);
+ ret += plistlen;
+
+ }
+ /*
+ * Currently the server should not respond with a SupportedCurves
+ * extension
+ */
+#endif /* OPENSSL_NO_EC */
+
+ if (s->tlsext_ticket_expected && tls_use_ticket(s)) {
+ /*-
+ * check for enough space.
+ * 4 bytes for the Ticket type and extension length
+ */
+ if (CHECKLEN(ret, 4, limit))
+ return NULL;
+ s2n(TLSEXT_TYPE_session_ticket, ret);
+ s2n(0, ret);
+ } else {
+ /*
+ * if we don't add the above TLSEXT, we can't add a session ticket
+ * later
+ */
+ s->tlsext_ticket_expected = 0;
+ }
+
+ if (s->tlsext_status_expected) {
+ /*-
+ * check for enough space.
+ * 4 bytes for the Status request type and extension length
+ */
+ if (CHECKLEN(ret, 4, limit))
+ return NULL;
+ s2n(TLSEXT_TYPE_status_request, ret);
+ s2n(0, ret);
+ }
+#ifndef OPENSSL_NO_SRTP
+ if (SSL_IS_DTLS(s) && s->srtp_profile) {
+ int el;
+
+ /* Returns 0 on success!! */
+ if (ssl_add_serverhello_use_srtp_ext(s, 0, &el, 0)) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+ /*-
+ * check for enough space.
+ * 4 bytes for the SRTP profiles type and extension length
+ * + length of the SRTP profiles list
+ */
+ if (CHECKLEN(ret, 4 + el, limit))
+ return NULL;
+
+ s2n(TLSEXT_TYPE_use_srtp, ret);
+ s2n(el, ret);
+
+ if (ssl_add_serverhello_use_srtp_ext(s, ret, &el, el)) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+ ret += el;
+ }
+#endif
+
+ 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)) {
+ 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
+ };
+
+ /* check for enough space. */
+ if (CHECKLEN(ret, sizeof(cryptopro_ext), limit))
+ return NULL;
+ memcpy(ret, cryptopro_ext, sizeof(cryptopro_ext));
+ ret += sizeof(cryptopro_ext);
+
+ }
+#ifndef OPENSSL_NO_HEARTBEATS
+ /* Add Heartbeat extension if we've received one */
+ if (SSL_IS_DTLS(s) && (s->tlsext_heartbeat & SSL_DTLSEXT_HB_ENABLED)) {
+ /*-
+ * check for enough space.
+ * 4 bytes for the Heartbeat type and extension length
+ * 1 byte for the mode
+ */
+ if (CHECKLEN(ret, 5, limit))
+ return NULL;
+ s2n(TLSEXT_TYPE_heartbeat, ret);
+ s2n(1, ret);
+ /*-
+ * Set mode:
+ * 1: peer may send requests
+ * 2: peer not allowed to send requests
+ */
+ if (s->tlsext_heartbeat & SSL_DTLSEXT_HB_DONT_RECV_REQUESTS)
+ *(ret++) = SSL_DTLSEXT_HB_DONT_SEND_REQUESTS;
+ else
+ *(ret++) = SSL_DTLSEXT_HB_ENABLED;
+
+ }
+#endif
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ next_proto_neg_seen = s->s3->next_proto_neg_seen;
+ s->s3->next_proto_neg_seen = 0;
+ if (next_proto_neg_seen && s->ctx->next_protos_advertised_cb) {
+ const unsigned char *npa;
+ unsigned int npalen;
+ int r;
+
+ r = s->ctx->next_protos_advertised_cb(s, &npa, &npalen,
+ s->
+ ctx->next_protos_advertised_cb_arg);
+ if (r == SSL_TLSEXT_ERR_OK) {
+ /*-
+ * check for enough space.
+ * 4 bytes for the NPN type and extension length
+ * + length of protocols list
+ */
+ if (CHECKLEN(ret, 4 + npalen, limit))
+ return NULL;
+ s2n(TLSEXT_TYPE_next_proto_neg, ret);
+ s2n(npalen, ret);
+ memcpy(ret, npa, npalen);
+ ret += npalen;
+ s->s3->next_proto_neg_seen = 1;
+ }
+ }
+#endif
+ if (!custom_ext_add(s, 1, &ret, limit, al))
+ return NULL;
+ if (s->tlsext_use_etm) {
+ /*
+ * Don't use encrypt_then_mac if AEAD or RC4 might want to disable
+ * for other cases too.
+ */
+ if (SSL_IS_DTLS(s) || 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->tlsext_use_etm = 0;
+ else {
+ /*-
+ * check for enough space.
+ * 4 bytes for the ETM type and extension length
+ */
+ if (CHECKLEN(ret, 4, limit))
+ return NULL;
+ s2n(TLSEXT_TYPE_encrypt_then_mac, ret);
+ s2n(0, ret);
+ }
+ }
+ if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) {
+ /*-
+ * check for enough space.
+ * 4 bytes for the EMS type and extension length
+ */
+ if (CHECKLEN(ret, 4, limit))
+ return NULL;
+ s2n(TLSEXT_TYPE_extended_master_secret, ret);
+ s2n(0, ret);
+ }
+
+ if (s->s3->alpn_selected != NULL) {
+ const unsigned char *selected = s->s3->alpn_selected;
+ size_t len = s->s3->alpn_selected_len;
+
+ /*-
+ * check for enough space.
+ * 4 bytes for the ALPN type and extension length
+ * 2 bytes for ALPN data length
+ * 1 byte for selected protocol length
+ * + length of the selected protocol
+ */
+ if (CHECKLEN(ret, 7 + len, limit))
+ return NULL;
+ s2n(TLSEXT_TYPE_application_layer_protocol_negotiation, ret);
+ s2n(3 + len, ret);
+ s2n(1 + len, ret);
+ *ret++ = len;
+ memcpy(ret, selected, len);
+ ret += len;
+ }
+
+ done:
+
+ if ((extdatalen = ret - orig - 2) == 0)
+ return orig;
+
+ s2n(extdatalen, orig);
+ return ret;
+}
+
+/*
+ * Save the ALPN extension in a ClientHello.
+ * pkt: the contents of the ALPN extension, not including type and length.
+ * al: a pointer to the alert value to send in the event of a failure.
+ * returns: 1 on success, 0 on error.
+ */
+static int tls1_alpn_handle_client_hello(SSL *s, PACKET *pkt, int *al)
+{
+ PACKET protocol_list, save_protocol_list, protocol;
+
+ *al = SSL_AD_DECODE_ERROR;
+
+ if (!PACKET_as_length_prefixed_2(pkt, &protocol_list)
+ || PACKET_remaining(&protocol_list) < 2) {
+ 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) {
+ return 0;
+ }
+ } while (PACKET_remaining(&protocol_list) != 0);
+
+ if (!PACKET_memdup(&save_protocol_list,
+ &s->s3->alpn_proposed, &s->s3->alpn_proposed_len)) {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Process the ALPN extension in a ClientHello.
+ * al: a pointer to the alert value to send in the event of a failure.
+ * returns 1 on success, 0 on error.
+ */
+static int tls1_alpn_handle_client_hello_late(SSL *s, int *al)
+{
+ const unsigned char *selected = NULL;
+ unsigned char selected_len = 0;
+
+ if (s->ctx->alpn_select_cb != NULL && s->s3->alpn_proposed != NULL) {
+ int r = s->ctx->alpn_select_cb(s, &selected, &selected_len,
+ s->s3->alpn_proposed,
+ s->s3->alpn_proposed_len,
+ s->ctx->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) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ s->s3->alpn_selected_len = selected_len;
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ /* ALPN takes precedence over NPN. */
+ s->s3->next_proto_neg_seen = 0;
+#endif
+ } else if (r == SSL_TLSEXT_ERR_NOACK) {
+ /* Behave as if no callback was present. */
+ return 1;
+ } else {
+ *al = SSL_AD_NO_APPLICATION_PROTOCOL;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_EC
+/*-
+ * ssl_check_for_safari attempts to fingerprint Safari using OS X
+ * SecureTransport using the TLS extension block in |pkt|.
+ * Safari, since 10.6, sends exactly these extensions, in this order:
+ * SNI,
+ * elliptic_curves
+ * ec_point_formats
+ *
+ * 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 PACKET *pkt)
+{
+ unsigned int type;
+ PACKET sni, tmppkt;
+ size_t ext_len;
+
+ 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;
+
+ tmppkt = *pkt;
+
+ 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 */
+
+/*
+ * Parse ClientHello extensions and stash extension info in various parts of
+ * the SSL object. Verify that there are no duplicate extensions.
+ *
+ * Behaviour upon resumption is extension-specific. If the extension has no
+ * effect during resumption, it is parsed (to verify its format) but otherwise
+ * ignored.
+ *
+ * Consumes the entire packet in |pkt|. Returns 1 on success and 0 on failure.
+ * Upon failure, sets |al| to the appropriate alert.
+ */
+static int ssl_scan_clienthello_tlsext(SSL *s, PACKET *pkt, int *al)
+{
+ unsigned int type;
+ int renegotiate_seen = 0;
+ PACKET extensions;
+
+ *al = SSL_AD_DECODE_ERROR;
+ s->servername_done = 0;
+ s->tlsext_status_type = -1;
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ s->s3->next_proto_neg_seen = 0;
+#endif
+
+ OPENSSL_free(s->s3->alpn_selected);
+ s->s3->alpn_selected = NULL;
+ s->s3->alpn_selected_len = 0;
+ OPENSSL_free(s->s3->alpn_proposed);
+ s->s3->alpn_proposed = NULL;
+ s->s3->alpn_proposed_len = 0;
+#ifndef OPENSSL_NO_HEARTBEATS
+ s->tlsext_heartbeat &= ~(SSL_DTLSEXT_HB_ENABLED |
+ SSL_DTLSEXT_HB_DONT_SEND_REQUESTS);
+#endif
+
+#ifndef OPENSSL_NO_EC
+ if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
+ ssl_check_for_safari(s, pkt);
+#endif /* !OPENSSL_NO_EC */
+
+ /* Clear any signature algorithms extension received */
+ OPENSSL_free(s->s3->tmp.peer_sigalgs);
+ s->s3->tmp.peer_sigalgs = NULL;
+ s->tlsext_use_etm = 0;
+
+#ifndef OPENSSL_NO_SRP
+ OPENSSL_free(s->srp_ctx.login);
+ s->srp_ctx.login = NULL;
+#endif
+
+ s->srtp_profile = NULL;
+
+ if (PACKET_remaining(pkt) == 0)
+ goto ri_check;
+
+ if (!PACKET_as_length_prefixed_2(pkt, &extensions))
+ return 0;
+
+ if (!tls1_check_duplicate_extensions(&extensions))
+ return 0;
+
+ /*
+ * We parse all extensions to ensure the ClientHello is well-formed but,
+ * unless an extension specifies otherwise, we ignore extensions upon
+ * resumption.
+ */
+ while (PACKET_get_net_2(&extensions, &type)) {
+ PACKET extension;
+ if (!PACKET_get_length_prefixed_2(&extensions, &extension))
+ return 0;
+
+ if (s->tlsext_debug_cb)
+ s->tlsext_debug_cb(s, 0, type, PACKET_data(&extension),
+ PACKET_remaining(&extension),
+ s->tlsext_debug_arg);
+
+ if (type == TLSEXT_TYPE_renegotiate) {
+ if (!ssl_parse_clienthello_renegotiate_ext(s, &extension, al))
+ return 0;
+ renegotiate_seen = 1;
+ } else if (s->version == SSL3_VERSION) {
+ }
+/*-
+ * 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.
+ *
+ */
+
+ else if (type == TLSEXT_TYPE_server_name) {
+ unsigned int servname_type;
+ PACKET sni, hostname;
+
+ if (!PACKET_as_length_prefixed_2(&extension, &sni)
+ /* ServerNameList must be at least 1 byte long. */
+ || PACKET_remaining(&sni) == 0) {
+ return 0;
+ }
+
+ /*
+ * Although the server_name extension was intended to be
+ * extensible to new name types, RFC 4366 defined the
+ * syntax inextensibility and OpenSSL 1.0.x parses it as
+ * such.
+ * 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)) {
+ return 0;
+ }
+
+ if (!s->hit) {
+ if (PACKET_remaining(&hostname) > TLSEXT_MAXLEN_host_name) {
+ *al = TLS1_AD_UNRECOGNIZED_NAME;
+ return 0;
+ }
+
+ if (PACKET_contains_zero_byte(&hostname)) {
+ *al = TLS1_AD_UNRECOGNIZED_NAME;
+ return 0;
+ }
+
+ if (!PACKET_strndup(&hostname, &s->session->tlsext_hostname)) {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+
+ s->servername_done = 1;
+ } else {
+ /*
+ * TODO(openssl-team): if the SNI doesn't match, we MUST
+ * fall back to a full handshake.
+ */
+ s->servername_done = s->session->tlsext_hostname
+ && PACKET_equal(&hostname, s->session->tlsext_hostname,
+ strlen(s->session->tlsext_hostname));
+ }
+ }
+#ifndef OPENSSL_NO_SRP
+ else if (type == TLSEXT_TYPE_srp) {
+ PACKET srp_I;
+
+ if (!PACKET_as_length_prefixed_1(&extension, &srp_I))
+ return 0;
+
+ if (PACKET_contains_zero_byte(&srp_I))
+ return 0;
+
+ /*
+ * TODO(openssl-team): currently, we re-authenticate the user
+ * upon resumption. Instead, we MUST ignore the login.
+ */
+ if (!PACKET_strndup(&srp_I, &s->srp_ctx.login)) {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ }
+#endif
+
+#ifndef OPENSSL_NO_EC
+ else if (type == TLSEXT_TYPE_ec_point_formats) {
+ PACKET ec_point_format_list;
+
+ if (!PACKET_as_length_prefixed_1(&extension, &ec_point_format_list)
+ || PACKET_remaining(&ec_point_format_list) == 0) {
+ return 0;
+ }
+
+ if (!s->hit) {
+ if (!PACKET_memdup(&ec_point_format_list,
+ &s->session->tlsext_ecpointformatlist,
+ &s->
+ session->tlsext_ecpointformatlist_length)) {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ }
+ } else if (type == TLSEXT_TYPE_elliptic_curves) {
+ PACKET elliptic_curve_list;
+
+ /* Each NamedCurve is 2 bytes and we must have at least 1. */
+ if (!PACKET_as_length_prefixed_2(&extension, &elliptic_curve_list)
+ || PACKET_remaining(&elliptic_curve_list) == 0
+ || (PACKET_remaining(&elliptic_curve_list) % 2) != 0) {
+ return 0;
+ }
+
+ if (!s->hit) {
+ if (!PACKET_memdup(&elliptic_curve_list,
+ &s->session->tlsext_ellipticcurvelist,
+ &s->
+ session->tlsext_ellipticcurvelist_length)) {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ }
+ }
+#endif /* OPENSSL_NO_EC */
+ else if (type == TLSEXT_TYPE_session_ticket) {
+ if (s->tls_session_ticket_ext_cb &&
+ !s->tls_session_ticket_ext_cb(s, PACKET_data(&extension),
+ PACKET_remaining(&extension),
+ s->tls_session_ticket_ext_cb_arg))
+ {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ } else if (type == TLSEXT_TYPE_signature_algorithms) {
+ PACKET supported_sig_algs;
+
+ if (!PACKET_as_length_prefixed_2(&extension, &supported_sig_algs)
+ || (PACKET_remaining(&supported_sig_algs) % 2) != 0
+ || PACKET_remaining(&supported_sig_algs) == 0) {
+ return 0;
+ }
+
+ if (!s->hit) {
+ if (!tls1_save_sigalgs(s, PACKET_data(&supported_sig_algs),
+ PACKET_remaining(&supported_sig_algs))) {
+ return 0;
+ }
+ }
+ } else if (type == TLSEXT_TYPE_status_request) {
+ if (!PACKET_get_1(&extension,
+ (unsigned int *)&s->tlsext_status_type)) {
+ return 0;
+ }
+#ifndef OPENSSL_NO_OCSP
+ if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) {
+ const unsigned char *ext_data;
+ PACKET responder_id_list, exts;
+ if (!PACKET_get_length_prefixed_2
+ (&extension, &responder_id_list))
+ 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->tlsext_ocsp_ids,
+ OCSP_RESPID_free);
+ if (PACKET_remaining(&responder_id_list) > 0) {
+ s->tlsext_ocsp_ids = sk_OCSP_RESPID_new_null();
+ if (s->tlsext_ocsp_ids == NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ } else {
+ s->tlsext_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) {
+ return 0;
+ }
+
+ id_data = PACKET_data(&responder_id);
+ id = d2i_OCSP_RESPID(NULL, &id_data,
+ PACKET_remaining(&responder_id));
+ if (id == NULL)
+ return 0;
+
+ if (id_data != PACKET_end(&responder_id)) {
+ OCSP_RESPID_free(id);
+ return 0;
+ }
+
+ if (!sk_OCSP_RESPID_push(s->tlsext_ocsp_ids, id)) {
+ OCSP_RESPID_free(id);
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ }
+
+ /* Read in request_extensions */
+ if (!PACKET_as_length_prefixed_2(&extension, &exts))
+ return 0;
+
+ if (PACKET_remaining(&exts) > 0) {
+ ext_data = PACKET_data(&exts);
+ sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts,
+ X509_EXTENSION_free);
+ s->tlsext_ocsp_exts =
+ d2i_X509_EXTENSIONS(NULL, &ext_data,
+ PACKET_remaining(&exts));
+ if (s->tlsext_ocsp_exts == NULL
+ || ext_data != PACKET_end(&exts)) {
+ return 0;
+ }
+ }
+ } else
+#endif
+ {
+ /*
+ * We don't know what to do with any other type so ignore it.
+ */
+ s->tlsext_status_type = -1;
+ }
+ }
+#ifndef OPENSSL_NO_HEARTBEATS
+ else if (SSL_IS_DTLS(s) && type == TLSEXT_TYPE_heartbeat) {
+ unsigned int hbtype;
+
+ if (!PACKET_get_1(&extension, &hbtype)
+ || PACKET_remaining(&extension)) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+ switch (hbtype) {
+ case 0x01: /* Client allows us to send HB requests */
+ s->tlsext_heartbeat |= SSL_DTLSEXT_HB_ENABLED;
+ break;
+ case 0x02: /* Client doesn't accept HB requests */
+ s->tlsext_heartbeat |= SSL_DTLSEXT_HB_ENABLED;
+ s->tlsext_heartbeat |= SSL_DTLSEXT_HB_DONT_SEND_REQUESTS;
+ break;
+ default:
+ *al = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+ }
+#endif
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ else if (type == TLSEXT_TYPE_next_proto_neg &&
+ s->s3->tmp.finish_md_len == 0) {
+ /*-
+ * We shouldn't accept this extension on a
+ * renegotiation.
+ *
+ * s->new_session will be set on renegotiation, but we
+ * probably shouldn't rely that it couldn't be set on
+ * the initial renegotiation too in certain cases (when
+ * there's some other reason to disallow resuming an
+ * earlier session -- the current code won't be doing
+ * anything like that, but this might change).
+ *
+ * A valid sign that there's been a previous handshake
+ * in this connection is if s->s3->tmp.finish_md_len >
+ * 0. (We are talking about a check that will happen
+ * in the Hello protocol round, well before a new
+ * Finished message could have been computed.)
+ */
+ s->s3->next_proto_neg_seen = 1;
+ }
+#endif
+
+ else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation &&
+ s->s3->tmp.finish_md_len == 0) {
+ if (!tls1_alpn_handle_client_hello(s, &extension, al))
+ return 0;
+ }
+
+ /* session ticket processed earlier */
+#ifndef OPENSSL_NO_SRTP
+ else if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)
+ && type == TLSEXT_TYPE_use_srtp) {
+ if (ssl_parse_clienthello_use_srtp_ext(s, &extension, al))
+ return 0;
+ }
+#endif
+ else if (type == TLSEXT_TYPE_encrypt_then_mac &&
+ !(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC))
+ s->tlsext_use_etm = 1;
+ /*
+ * Note: extended master secret extension handled in
+ * tls_check_serverhello_tlsext_early()
+ */
+
+ /*
+ * If this ClientHello extension was unhandled and this is a
+ * nonresumed connection, check whether the extension is a custom
+ * TLS Extension (has a custom_srv_ext_record), and if so call the
+ * callback and record the extension number so that an appropriate
+ * ServerHello may be later returned.
+ */
+ else if (!s->hit) {
+ if (custom_ext_parse(s, 1, type, PACKET_data(&extension),
+ PACKET_remaining(&extension), al) <= 0)
+ return 0;
+ }
+ }
+
+ if (PACKET_remaining(pkt) != 0) {
+ /*
+ * tls1_check_duplicate_extensions should ensure this never happens.
+ */
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+
+ ri_check:
+
+ /* Need RI if renegotiating */
+
+ if (!renegotiate_seen && s->renegotiate &&
+ !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) {
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT,
+ SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
+ return 0;
+ }
+
+ /*
+ * This function currently has no state to clean up, so it returns directly.
+ * If parsing fails at any point, the function returns early.
+ * The SSL object may be left with partial data from extensions, but it must
+ * then no longer be used, and clearing it up will free the leftovers.
+ */
+ return 1;
+}
+
+int ssl_parse_clienthello_tlsext(SSL *s, PACKET *pkt)
+{
+ int al = -1;
+ custom_ext_init(&s->cert->srv_ext);
+ if (ssl_scan_clienthello_tlsext(s, pkt, &al) <= 0) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ return 0;
+ }
+ if (ssl_check_clienthello_tlsext_early(s) <= 0) {
+ SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT, SSL_R_CLIENTHELLO_TLSEXT);
+ return 0;
+ }
+ return 1;
+}
+
+#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.
+ */
+static char ssl_next_proto_validate(PACKET *pkt)
+{
+ PACKET tmp_protocol;
+
+ while (PACKET_remaining(pkt)) {
+ if (!PACKET_get_length_prefixed_1(pkt, &tmp_protocol)
+ || PACKET_remaining(&tmp_protocol) == 0)
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+
+static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al)
+{
+ unsigned int length, type, size;
+ int tlsext_servername = 0;
+ int renegotiate_seen = 0;
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ s->s3->next_proto_neg_seen = 0;
+#endif
+ s->tlsext_ticket_expected = 0;
+
+ OPENSSL_free(s->s3->alpn_selected);
+ s->s3->alpn_selected = NULL;
+#ifndef OPENSSL_NO_HEARTBEATS
+ s->tlsext_heartbeat &= ~(SSL_DTLSEXT_HB_ENABLED |
+ SSL_DTLSEXT_HB_DONT_SEND_REQUESTS);
+#endif
+
+ s->tlsext_use_etm = 0;
+
+ s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
+
+ if (!PACKET_get_net_2(pkt, &length))
+ goto ri_check;
+
+ if (PACKET_remaining(pkt) != length) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ if (!tls1_check_duplicate_extensions(pkt)) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ while (PACKET_get_net_2(pkt, &type) && PACKET_get_net_2(pkt, &size)) {
+ const unsigned char *data;
+ PACKET spkt;
+
+ if (!PACKET_get_sub_packet(pkt, &spkt, size)
+ || !PACKET_peek_bytes(&spkt, &data, size))
+ goto ri_check;
+
+ if (s->tlsext_debug_cb)
+ s->tlsext_debug_cb(s, 1, type, data, size, s->tlsext_debug_arg);
+
+ if (type == TLSEXT_TYPE_renegotiate) {
+ if (!ssl_parse_serverhello_renegotiate_ext(s, &spkt, al))
+ return 0;
+ renegotiate_seen = 1;
+ } else if (s->version == SSL3_VERSION) {
+ } else if (type == TLSEXT_TYPE_server_name) {
+ if (s->tlsext_hostname == NULL || size > 0) {
+ *al = TLS1_AD_UNRECOGNIZED_NAME;
+ return 0;
+ }
+ tlsext_servername = 1;
+ }
+#ifndef OPENSSL_NO_EC
+ else if (type == TLSEXT_TYPE_ec_point_formats) {
+ unsigned int ecpointformatlist_length;
+ if (!PACKET_get_1(&spkt, &ecpointformatlist_length)
+ || ecpointformatlist_length != size - 1) {
+ *al = TLS1_AD_DECODE_ERROR;
+ return 0;
+ }
+ if (!s->hit) {
+ s->session->tlsext_ecpointformatlist_length = 0;
+ OPENSSL_free(s->session->tlsext_ecpointformatlist);
+ if ((s->session->tlsext_ecpointformatlist =
+ OPENSSL_malloc(ecpointformatlist_length)) == NULL) {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ s->session->tlsext_ecpointformatlist_length =
+ ecpointformatlist_length;
+ if (!PACKET_copy_bytes(&spkt,
+ s->session->tlsext_ecpointformatlist,
+ ecpointformatlist_length)) {
+ *al = TLS1_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ }
+ }
+#endif /* OPENSSL_NO_EC */
+
+ else if (type == TLSEXT_TYPE_session_ticket) {
+ if (s->tls_session_ticket_ext_cb &&
+ !s->tls_session_ticket_ext_cb(s, data, size,
+ s->tls_session_ticket_ext_cb_arg))
+ {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ if (!tls_use_ticket(s) || (size > 0)) {
+ *al = TLS1_AD_UNSUPPORTED_EXTENSION;
+ return 0;
+ }
+ s->tlsext_ticket_expected = 1;
+ } else if (type == TLSEXT_TYPE_status_request) {
+ /*
+ * MUST be empty and only sent if we've requested a status
+ * request message.
+ */
+ if ((s->tlsext_status_type == -1) || (size > 0)) {
+ *al = TLS1_AD_UNSUPPORTED_EXTENSION;
+ return 0;
+ }
+ /* Set flag to expect CertificateStatus message */
+ s->tlsext_status_expected = 1;
+ }
+#ifndef OPENSSL_NO_CT
+ /*
+ * 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.
+ */
+ else if (type == TLSEXT_TYPE_signed_certificate_timestamp &&
+ s->ct_validation_callback != NULL) {
+ /* Simply copy it off for later processing */
+ if (s->tlsext_scts != NULL) {
+ OPENSSL_free(s->tlsext_scts);
+ s->tlsext_scts = NULL;
+ }
+ s->tlsext_scts_len = size;
+ if (size > 0) {
+ s->tlsext_scts = OPENSSL_malloc(size);
+ if (s->tlsext_scts == NULL) {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ memcpy(s->tlsext_scts, data, size);
+ }
+ }
+#endif
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ else if (type == TLSEXT_TYPE_next_proto_neg &&
+ s->s3->tmp.finish_md_len == 0) {
+ unsigned char *selected;
+ unsigned char selected_len;
+ /* We must have requested it. */
+ if (s->ctx->next_proto_select_cb == NULL) {
+ *al = TLS1_AD_UNSUPPORTED_EXTENSION;
+ return 0;
+ }
+ /* The data must be valid */
+ if (!ssl_next_proto_validate(&spkt)) {
+ *al = TLS1_AD_DECODE_ERROR;
+ return 0;
+ }
+ if (s->ctx->next_proto_select_cb(s, &selected, &selected_len, data,
+ size,
+ s->
+ ctx->next_proto_select_cb_arg) !=
+ SSL_TLSEXT_ERR_OK) {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ /*
+ * Could be non-NULL if server has sent multiple NPN extensions in
+ * a single Serverhello
+ */
+ OPENSSL_free(s->next_proto_negotiated);
+ s->next_proto_negotiated = OPENSSL_malloc(selected_len);
+ if (s->next_proto_negotiated == NULL) {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ memcpy(s->next_proto_negotiated, selected, selected_len);
+ s->next_proto_negotiated_len = selected_len;
+ s->s3->next_proto_neg_seen = 1;
+ }
+#endif
+
+ else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation) {
+ unsigned len;
+ /* We must have requested it. */
+ if (!s->s3->alpn_sent) {
+ *al = TLS1_AD_UNSUPPORTED_EXTENSION;
+ return 0;
+ }
+ /*-
+ * The extension data consists of:
+ * uint16 list_length
+ * uint8 proto_length;
+ * uint8 proto[proto_length];
+ */
+ if (!PACKET_get_net_2(&spkt, &len)
+ || PACKET_remaining(&spkt) != len || !PACKET_get_1(&spkt, &len)
+ || PACKET_remaining(&spkt) != len) {
+ *al = TLS1_AD_DECODE_ERROR;
+ return 0;
+ }
+ OPENSSL_free(s->s3->alpn_selected);
+ s->s3->alpn_selected = OPENSSL_malloc(len);
+ if (s->s3->alpn_selected == NULL) {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ if (!PACKET_copy_bytes(&spkt, s->s3->alpn_selected, len)) {
+ *al = TLS1_AD_DECODE_ERROR;
+ return 0;
+ }
+ s->s3->alpn_selected_len = len;
+ }
+#ifndef OPENSSL_NO_HEARTBEATS
+ else if (SSL_IS_DTLS(s) && type == TLSEXT_TYPE_heartbeat) {
+ unsigned int hbtype;
+ if (!PACKET_get_1(&spkt, &hbtype)) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+ switch (hbtype) {
+ case 0x01: /* Server allows us to send HB requests */
+ s->tlsext_heartbeat |= SSL_DTLSEXT_HB_ENABLED;
+ break;
+ case 0x02: /* Server doesn't accept HB requests */
+ s->tlsext_heartbeat |= SSL_DTLSEXT_HB_ENABLED;
+ s->tlsext_heartbeat |= SSL_DTLSEXT_HB_DONT_SEND_REQUESTS;
+ break;
+ default:
+ *al = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+ }
+#endif
+#ifndef OPENSSL_NO_SRTP
+ else if (SSL_IS_DTLS(s) && type == TLSEXT_TYPE_use_srtp) {
+ if (ssl_parse_serverhello_use_srtp_ext(s, &spkt, al))
+ return 0;
+ }
+#endif
+ else if (type == TLSEXT_TYPE_encrypt_then_mac) {
+ /* 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->tlsext_use_etm = 1;
+ } else if (type == TLSEXT_TYPE_extended_master_secret) {
+ s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
+ if (!s->hit)
+ s->session->flags |= SSL_SESS_FLAG_EXTMS;
+ }
+ /*
+ * If this extension type was not otherwise handled, but matches a
+ * custom_cli_ext_record, then send it to the c callback
+ */
+ else if (custom_ext_parse(s, 0, type, data, size, al) <= 0)
+ return 0;
+ }
+
+ if (PACKET_remaining(pkt) != 0) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ if (!s->hit && tlsext_servername == 1) {
+ if (s->tlsext_hostname) {
+ if (s->session->tlsext_hostname == NULL) {
+ s->session->tlsext_hostname =
+ OPENSSL_strdup(s->tlsext_hostname);
+ if (!s->session->tlsext_hostname) {
+ *al = SSL_AD_UNRECOGNIZED_NAME;
+ return 0;
+ }
+ } else {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+ }
+ }
+
+ ri_check:
+
+ /*
+ * Determine if we need to see RI. Strictly speaking if we want to avoid
+ * an attack we should *always* see RI even on initial server hello
+ * because the client doesn't see any renegotiation during an attack.
+ * However this would mean we could not connect to any server which
+ * doesn't support RI so for the immediate future tolerate RI absence
+ */
+ if (!renegotiate_seen && !(s->options & SSL_OP_LEGACY_SERVER_CONNECT)
+ && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) {
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT,
+ SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
+ return 0;
+ }
+
+ if (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)) {
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT, SSL_R_INCONSISTENT_EXTMS);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int ssl_prepare_clienthello_tlsext(SSL *s)
+{
+ s->s3->alpn_sent = 0;
+ return 1;
+}
+
+int ssl_prepare_serverhello_tlsext(SSL *s)
+{
+ return 1;
+}
+
+static int ssl_check_clienthello_tlsext_early(SSL *s)
+{
+ int ret = SSL_TLSEXT_ERR_NOACK;
+ int al = SSL_AD_UNRECOGNIZED_NAME;
+
+#ifndef OPENSSL_NO_EC
+ /*
+ * The handling of the ECPointFormats extension is done elsewhere, namely
+ * in ssl3_choose_cipher in s3_lib.c.
+ */
+ /*
+ * The handling of the EllipticCurves extension is done elsewhere, namely
+ * in ssl3_choose_cipher in s3_lib.c.
+ */
+#endif
+
+ if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0)
+ ret =
+ s->ctx->tlsext_servername_callback(s, &al,
+ s->ctx->tlsext_servername_arg);
+ else if (s->session_ctx != NULL
+ && s->session_ctx->tlsext_servername_callback != 0)
+ ret =
+ s->session_ctx->tlsext_servername_callback(s, &al,
+ s->
+ session_ctx->tlsext_servername_arg);
+
+ switch (ret) {
+ case SSL_TLSEXT_ERR_ALERT_FATAL:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ return -1;
+
+ case SSL_TLSEXT_ERR_ALERT_WARNING:
+ ssl3_send_alert(s, SSL3_AL_WARNING, al);
+ return 1;
+
+ case SSL_TLSEXT_ERR_NOACK:
+ s->servername_done = 0;
+ /* fall thru */
+ default:
+ return 1;
+ }
+}
+
+/* Initialise digests to default values */
+void ssl_set_default_md(SSL *s)
+{
+ const EVP_MD **pmd = s->s3->tmp.md;
+#ifndef OPENSSL_NO_DSA
+ pmd[SSL_PKEY_DSA_SIGN] = ssl_md(SSL_MD_SHA1_IDX);
+#endif
+#ifndef OPENSSL_NO_RSA
+ if (SSL_USE_SIGALGS(s))
+ pmd[SSL_PKEY_RSA_SIGN] = ssl_md(SSL_MD_SHA1_IDX);
+ else
+ pmd[SSL_PKEY_RSA_SIGN] = ssl_md(SSL_MD_MD5_SHA1_IDX);
+ pmd[SSL_PKEY_RSA_ENC] = pmd[SSL_PKEY_RSA_SIGN];
+#endif
+#ifndef OPENSSL_NO_EC
+ pmd[SSL_PKEY_ECC] = ssl_md(SSL_MD_SHA1_IDX);
+#endif
+#ifndef OPENSSL_NO_GOST
+ pmd[SSL_PKEY_GOST01] = ssl_md(SSL_MD_GOST94_IDX);
+ pmd[SSL_PKEY_GOST12_256] = ssl_md(SSL_MD_GOST12_256_IDX);
+ pmd[SSL_PKEY_GOST12_512] = ssl_md(SSL_MD_GOST12_512_IDX);
+#endif
+}
+
+int tls1_set_server_sigalgs(SSL *s)
+{
+ int al;
+ size_t i;
+
+ /* Clear any shared signature algorithms */
+ OPENSSL_free(s->cert->shared_sigalgs);
+ s->cert->shared_sigalgs = NULL;
+ s->cert->shared_sigalgslen = 0;
+ /* Clear certificate digests and validity flags */
+ for (i = 0; i < SSL_PKEY_NUM; i++) {
+ s->s3->tmp.md[i] = NULL;
+ s->s3->tmp.valid_flags[i] = 0;
+ }
+
+ /* If sigalgs received process it. */
+ if (s->s3->tmp.peer_sigalgs) {
+ if (!tls1_process_sigalgs(s)) {
+ SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS, ERR_R_MALLOC_FAILURE);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto err;
+ }
+ /* Fatal error is no shared signature algorithms */
+ if (!s->cert->shared_sigalgs) {
+ SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS,
+ SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS);
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ goto err;
+ }
+ } else {
+ ssl_set_default_md(s);
+ }
+ return 1;
+ err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ return 0;
+}
+
+/*
+ * Upon success, returns 1.
+ * Upon failure, returns 0 and sets |al| to the appropriate fatal alert.
+ */
+int ssl_check_clienthello_tlsext_late(SSL *s, int *al)
+{
+ s->tlsext_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->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb) {
+ int ret;
+ CERT_PKEY *certpkey;
+ certpkey = ssl_get_server_send_pkey(s);
+ /* If no certificate can't return certificate status */
+ if (certpkey != NULL) {
+ /*
+ * Set current certificate to one we will use so SSL_get_certificate
+ * et al can pick it up.
+ */
+ s->cert->key = certpkey;
+ ret = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
+ switch (ret) {
+ /* We don't want to send a status request response */
+ case SSL_TLSEXT_ERR_NOACK:
+ s->tlsext_status_expected = 0;
+ break;
+ /* status request response should be sent */
+ case SSL_TLSEXT_ERR_OK:
+ if (s->tlsext_ocsp_resp)
+ s->tlsext_status_expected = 1;
+ break;
+ /* something bad happened */
+ case SSL_TLSEXT_ERR_ALERT_FATAL:
+ default:
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ }
+ }
+
+ if (!tls1_alpn_handle_client_hello_late(s, al)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+int ssl_check_serverhello_tlsext(SSL *s)
+{
+ int ret = SSL_TLSEXT_ERR_NOACK;
+ int al = SSL_AD_UNRECOGNIZED_NAME;
+
+#ifndef OPENSSL_NO_EC
+ /*
+ * 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.
+ */
+ unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+ if ((s->tlsext_ecpointformatlist != NULL)
+ && (s->tlsext_ecpointformatlist_length > 0)
+ && (s->session->tlsext_ecpointformatlist != NULL)
+ && (s->session->tlsext_ecpointformatlist_length > 0)
+ && ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA))) {
+ /* we are using an ECC cipher */
+ size_t i;
+ unsigned char *list;
+ int found_uncompressed = 0;
+ list = s->session->tlsext_ecpointformatlist;
+ for (i = 0; i < s->session->tlsext_ecpointformatlist_length; i++) {
+ if (*(list++) == TLSEXT_ECPOINTFORMAT_uncompressed) {
+ found_uncompressed = 1;
+ break;
+ }
+ }
+ if (!found_uncompressed) {
+ SSLerr(SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT,
+ SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
+ return -1;
+ }
+ }
+ ret = SSL_TLSEXT_ERR_OK;
+#endif /* OPENSSL_NO_EC */
+
+ if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0)
+ ret =
+ s->ctx->tlsext_servername_callback(s, &al,
+ s->ctx->tlsext_servername_arg);
+ else if (s->session_ctx != NULL
+ && s->session_ctx->tlsext_servername_callback != 0)
+ ret =
+ s->session_ctx->tlsext_servername_callback(s, &al,
+ s->
+ session_ctx->tlsext_servername_arg);
+
+ /*
+ * Ensure we get sensible values passed to tlsext_status_cb in the event
+ * that we don't receive a status message
+ */
+ OPENSSL_free(s->tlsext_ocsp_resp);
+ s->tlsext_ocsp_resp = NULL;
+ s->tlsext_ocsp_resplen = -1;
+
+ switch (ret) {
+ case SSL_TLSEXT_ERR_ALERT_FATAL:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ return -1;
+
+ case SSL_TLSEXT_ERR_ALERT_WARNING:
+ ssl3_send_alert(s, SSL3_AL_WARNING, al);
+ return 1;
+
+ case SSL_TLSEXT_ERR_NOACK:
+ s->servername_done = 0;
+ /* fall thru */
+ default:
+ return 1;
+ }
+}
+
+int ssl_parse_serverhello_tlsext(SSL *s, PACKET *pkt)
+{
+ int al = -1;
+ if (s->version < SSL3_VERSION)
+ return 1;
+ if (ssl_scan_serverhello_tlsext(s, pkt, &al) <= 0) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ return 0;
+ }
+
+ if (ssl_check_serverhello_tlsext(s) <= 0) {
+ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT, SSL_R_SERVERHELLO_TLSEXT);
+ return 0;
+ }
+ return 1;
+}
+
+/*-
+ * Since the server cache lookup is done early on in the processing of the
+ * ClientHello and other operations depend on the result some extensions
+ * need to be handled at the same time.
+ *
+ * Two extensions are currently handled, session ticket and extended master
+ * secret.
+ *
+ * session_id: ClientHello session ID.
+ * ext: ClientHello extensions (including length prefix)
+ * ret: (output) on return, if a ticket was decrypted, then this is set to
+ * point to the resulting session.
+ *
+ * If s->tls_session_secret_cb is set then we are expecting a pre-shared key
+ * ciphersuite, in which case we have no use for session tickets and one will
+ * never be decrypted, nor will s->tlsext_ticket_expected be set to 1.
+ *
+ * Returns:
+ * -1: fatal error, either from parsing or decrypting the ticket.
+ * 0: no ticket was found (or was ignored, based on settings).
+ * 1: a zero length extension was found, indicating that the client supports
+ * session tickets but doesn't currently have one to offer.
+ * 2: either s->tls_session_secret_cb was set, or a ticket was offered but
+ * couldn't be decrypted because of a non-fatal error.
+ * 3: a ticket was successfully decrypted and *ret was set.
+ *
+ * Side effects:
+ * Sets s->tlsext_ticket_expected to 1 if the server will have to issue
+ * a new session ticket to the client because the client indicated support
+ * (and s->tls_session_secret_cb is NULL) but the client either doesn't have
+ * a session ticket or we couldn't use the one it gave us, or if
+ * s->ctx->tlsext_ticket_key_cb asked to renew the client's ticket.
+ * Otherwise, s->tlsext_ticket_expected is set to 0.
+ *
+ * For extended master secret flag is set if the extension is present.
+ *
+ */
+int tls_check_serverhello_tlsext_early(SSL *s, const PACKET *ext,
+ const PACKET *session_id,
+ SSL_SESSION **ret)
+{
+ unsigned int i;
+ PACKET local_ext = *ext;
+ int retv = -1;
+
+ int have_ticket = 0;
+ int use_ticket = tls_use_ticket(s);
+
+ *ret = NULL;
+ s->tlsext_ticket_expected = 0;
+ s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
+
+ /*
+ * If tickets disabled behave as if no ticket present to permit stateful
+ * resumption.
+ */
+ if ((s->version <= SSL3_VERSION))
+ return 0;
+
+ if (!PACKET_get_net_2(&local_ext, &i)) {
+ retv = 0;
+ goto end;
+ }
+ while (PACKET_remaining(&local_ext) >= 4) {
+ unsigned int type, size;
+
+ if (!PACKET_get_net_2(&local_ext, &type)
+ || !PACKET_get_net_2(&local_ext, &size)) {
+ /* Shouldn't ever happen */
+ retv = -1;
+ goto end;
+ }
+ if (PACKET_remaining(&local_ext) < size) {
+ retv = 0;
+ goto end;
+ }
+ if (type == TLSEXT_TYPE_session_ticket && use_ticket) {
+ int r;
+ const unsigned char *etick;
+
+ /* Duplicate extension */
+ if (have_ticket != 0) {
+ retv = -1;
+ goto end;
+ }
+ have_ticket = 1;
+
+ if (size == 0) {
+ /*
+ * The client will accept a ticket but doesn't currently have
+ * one.
+ */
+ s->tlsext_ticket_expected = 1;
+ retv = 1;
+ continue;
+ }
+ if (s->tls_session_secret_cb) {
+ /*
+ * Indicate that the ticket couldn't be decrypted rather than
+ * generating the session from ticket now, trigger
+ * abbreviated handshake based on external mechanism to
+ * calculate the master secret later.
+ */
+ retv = 2;
+ continue;
+ }
+ if (!PACKET_get_bytes(&local_ext, &etick, size)) {
+ /* Shouldn't ever happen */
+ retv = -1;
+ goto end;
+ }
+ r = tls_decrypt_ticket(s, etick, size, PACKET_data(session_id),
+ PACKET_remaining(session_id), ret);
+ switch (r) {
+ case 2: /* ticket couldn't be decrypted */
+ s->tlsext_ticket_expected = 1;
+ retv = 2;
+ break;
+ case 3: /* ticket was decrypted */
+ retv = r;
+ break;
+ case 4: /* ticket decrypted but need to renew */
+ s->tlsext_ticket_expected = 1;
+ retv = 3;
+ break;
+ default: /* fatal error */
+ retv = -1;
+ break;
+ }
+ continue;
+ } else {
+ if (type == TLSEXT_TYPE_extended_master_secret)
+ s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
+ if (!PACKET_forward(&local_ext, size)) {
+ retv = -1;
+ goto end;
+ }
+ }
+ }
+ if (have_ticket == 0)
+ retv = 0;
+ end:
+ return retv;
+}
+
+/*-
+ * tls_decrypt_ticket attempts to decrypt a session ticket.
+ *
+ * etick: points to the body of the session ticket extension.
+ * eticklen: the length of the session tickets extension.
+ * sess_id: points at the session ID.
+ * sesslen: the length of the session ID.
+ * psess: (output) on return, if a ticket was decrypted, then this is set to
+ * point to the resulting session.
+ *
+ * Returns:
+ * -2: fatal error, malloc failure.
+ * -1: fatal error, either from parsing or decrypting the ticket.
+ * 2: the ticket couldn't be decrypted.
+ * 3: a ticket was successfully decrypted and *psess was set.
+ * 4: same as 3, but the ticket needs to be renewed.
+ */
+static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
+ int eticklen, const unsigned char *sess_id,
+ int sesslen, SSL_SESSION **psess)
+{
+ SSL_SESSION *sess;
+ unsigned char *sdec;
+ const unsigned char *p;
+ int slen, mlen, renew_ticket = 0, ret = -1;
+ unsigned char tick_hmac[EVP_MAX_MD_SIZE];
+ HMAC_CTX *hctx = NULL;
+ EVP_CIPHER_CTX *ctx = NULL;
+ SSL_CTX *tctx = s->session_ctx;
+
+ /* Need at least keyname + iv */
+ if (eticklen < TLSEXT_KEYNAME_LENGTH + EVP_MAX_IV_LENGTH) {
+ ret = 2;
+ goto err;
+ }
+
+ /* Initialize session ticket encryption and HMAC contexts */
+ hctx = HMAC_CTX_new();
+ if (hctx == NULL)
+ return -2;
+ ctx = EVP_CIPHER_CTX_new();
+ if (ctx == NULL) {
+ ret = -2;
+ goto err;
+ }
+ if (tctx->tlsext_ticket_key_cb) {
+ unsigned char *nctick = (unsigned char *)etick;
+ int rv = tctx->tlsext_ticket_key_cb(s, nctick,
+ nctick + TLSEXT_KEYNAME_LENGTH,
+ ctx, hctx, 0);
+ if (rv < 0)
+ goto err;
+ if (rv == 0) {
+ ret = 2;
+ goto err;
+ }
+ if (rv == 2)
+ renew_ticket = 1;
+ } else {
+ /* Check key name matches */
+ if (memcmp(etick, tctx->tlsext_tick_key_name,
+ TLSEXT_KEYNAME_LENGTH) != 0) {
+ ret = 2;
+ goto err;
+ }
+ if (HMAC_Init_ex(hctx, tctx->tlsext_tick_hmac_key,
+ sizeof(tctx->tlsext_tick_hmac_key),
+ EVP_sha256(), NULL) <= 0
+ || EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL,
+ tctx->tlsext_tick_aes_key,
+ etick + TLSEXT_KEYNAME_LENGTH) <= 0) {
+ goto err;
+ }
+ }
+ /*
+ * Attempt to process session ticket, first conduct sanity and integrity
+ * checks on ticket.
+ */
+ mlen = HMAC_size(hctx);
+ if (mlen < 0) {
+ goto err;
+ }
+ /* Sanity check ticket length: must exceed keyname + IV + HMAC */
+ if (eticklen <=
+ TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_iv_length(ctx) + mlen) {
+ ret = 2;
+ goto err;
+ }
+ eticklen -= mlen;
+ /* Check HMAC of encrypted ticket */
+ if (HMAC_Update(hctx, etick, eticklen) <= 0
+ || HMAC_Final(hctx, tick_hmac, NULL) <= 0) {
+ goto err;
+ }
+ HMAC_CTX_free(hctx);
+ if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen)) {
+ EVP_CIPHER_CTX_free(ctx);
+ return 2;
+ }
+ /* Attempt to decrypt session data */
+ /* Move p after IV to start of encrypted ticket, update length */
+ p = etick + TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_iv_length(ctx);
+ eticklen -= TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_iv_length(ctx);
+ sdec = OPENSSL_malloc(eticklen);
+ if (sdec == NULL || EVP_DecryptUpdate(ctx, sdec, &slen, p, eticklen) <= 0) {
+ EVP_CIPHER_CTX_free(ctx);
+ OPENSSL_free(sdec);
+ return -1;
+ }
+ if (EVP_DecryptFinal(ctx, sdec + slen, &mlen) <= 0) {
+ EVP_CIPHER_CTX_free(ctx);
+ OPENSSL_free(sdec);
+ return 2;
+ }
+ slen += mlen;
+ EVP_CIPHER_CTX_free(ctx);
+ ctx = NULL;
+ p = sdec;
+
+ sess = d2i_SSL_SESSION(NULL, &p, slen);
+ slen -= p - sdec;
+ OPENSSL_free(sdec);
+ if (sess) {
+ /* Some additional consistency checks */
+ if (slen != 0 || sess->session_id_length != 0) {
+ SSL_SESSION_free(sess);
+ return 2;
+ }
+ /*
+ * The session ID, if non-empty, is used by some clients to detect
+ * that the ticket has been accepted. So we copy it to the session
+ * structure. If it is empty set length to zero as required by
+ * standard.
+ */
+ if (sesslen)
+ memcpy(sess->session_id, sess_id, sesslen);
+ sess->session_id_length = sesslen;
+ *psess = sess;
+ if (renew_ticket)
+ return 4;
+ else
+ return 3;
+ }
+ ERR_clear_error();
+ /*
+ * For session parse failure, indicate that we need to send a new ticket.
+ */
+ return 2;
+ err:
+ EVP_CIPHER_CTX_free(ctx);
+ HMAC_CTX_free(hctx);
+ return ret;
+}
+
+/* Tables to translate from NIDs to TLS v1.2 ids */
+
+typedef struct {
+ int nid;
+ int id;
+} tls12_lookup;
+
+static const tls12_lookup tls12_md[] = {
+ {NID_md5, TLSEXT_hash_md5},
+ {NID_sha1, TLSEXT_hash_sha1},
+ {NID_sha224, TLSEXT_hash_sha224},
+ {NID_sha256, TLSEXT_hash_sha256},
+ {NID_sha384, TLSEXT_hash_sha384},
+ {NID_sha512, TLSEXT_hash_sha512},
+ {NID_id_GostR3411_94, TLSEXT_hash_gostr3411},
+ {NID_id_GostR3411_2012_256, TLSEXT_hash_gostr34112012_256},
+ {NID_id_GostR3411_2012_512, TLSEXT_hash_gostr34112012_512},
+};
+
+static const tls12_lookup tls12_sig[] = {
+ {EVP_PKEY_RSA, TLSEXT_signature_rsa},
+ {EVP_PKEY_DSA, TLSEXT_signature_dsa},
+ {EVP_PKEY_EC, TLSEXT_signature_ecdsa},
+ {NID_id_GostR3410_2001, TLSEXT_signature_gostr34102001},
+ {NID_id_GostR3410_2012_256, TLSEXT_signature_gostr34102012_256},
+ {NID_id_GostR3410_2012_512, TLSEXT_signature_gostr34102012_512}
+};
+
+static int tls12_find_id(int nid, const tls12_lookup *table, size_t tlen)
+{
+ size_t i;
+ for (i = 0; i < tlen; i++) {
+ if (table[i].nid == nid)
+ return table[i].id;
+ }
+ return -1;
+}
+
+static int tls12_find_nid(int id, const tls12_lookup *table, size_t tlen)
+{
+ size_t i;
+ for (i = 0; i < tlen; i++) {
+ if ((table[i].id) == id)
+ return table[i].nid;
+ }
+ return NID_undef;
+}
+
+int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, const EVP_MD *md)
+{
+ int sig_id, md_id;
+ if (!md)
+ return 0;
+ md_id = tls12_find_id(EVP_MD_type(md), tls12_md, OSSL_NELEM(tls12_md));
+ if (md_id == -1)
+ return 0;
+ sig_id = tls12_get_sigid(pk);
+ if (sig_id == -1)
+ return 0;
+ p[0] = (unsigned char)md_id;
+ p[1] = (unsigned char)sig_id;
+ return 1;
+}
+
+int tls12_get_sigid(const EVP_PKEY *pk)
+{
+ return tls12_find_id(EVP_PKEY_id(pk), tls12_sig, OSSL_NELEM(tls12_sig));
+}
+
+typedef struct {
+ int nid;
+ int secbits;
+ int md_idx;
+ unsigned char tlsext_hash;
+} tls12_hash_info;
+
+static const tls12_hash_info tls12_md_info[] = {
+ {NID_md5, 64, SSL_MD_MD5_IDX, TLSEXT_hash_md5},
+ {NID_sha1, 80, SSL_MD_SHA1_IDX, TLSEXT_hash_sha1},
+ {NID_sha224, 112, SSL_MD_SHA224_IDX, TLSEXT_hash_sha224},
+ {NID_sha256, 128, SSL_MD_SHA256_IDX, TLSEXT_hash_sha256},
+ {NID_sha384, 192, SSL_MD_SHA384_IDX, TLSEXT_hash_sha384},
+ {NID_sha512, 256, SSL_MD_SHA512_IDX, TLSEXT_hash_sha512},
+ {NID_id_GostR3411_94, 128, SSL_MD_GOST94_IDX, TLSEXT_hash_gostr3411},
+ {NID_id_GostR3411_2012_256, 128, SSL_MD_GOST12_256_IDX,
+ TLSEXT_hash_gostr34112012_256},
+ {NID_id_GostR3411_2012_512, 256, SSL_MD_GOST12_512_IDX,
+ TLSEXT_hash_gostr34112012_512},
+};
+
+static const tls12_hash_info *tls12_get_hash_info(unsigned char hash_alg)
+{
+ unsigned int i;
+ if (hash_alg == 0)
+ return NULL;
+
+ for (i = 0; i < OSSL_NELEM(tls12_md_info); i++) {
+ if (tls12_md_info[i].tlsext_hash == hash_alg)
+ return tls12_md_info + i;
+ }
+
+ return NULL;
+}
+
+const EVP_MD *tls12_get_hash(unsigned char hash_alg)
+{
+ const tls12_hash_info *inf;
+ if (hash_alg == TLSEXT_hash_md5 && FIPS_mode())
+ return NULL;
+ inf = tls12_get_hash_info(hash_alg);
+ if (!inf)
+ return NULL;
+ return ssl_md(inf->md_idx);
+}
+
+static int tls12_get_pkey_idx(unsigned char sig_alg)
+{
+ switch (sig_alg) {
+#ifndef OPENSSL_NO_RSA
+ case TLSEXT_signature_rsa:
+ return SSL_PKEY_RSA_SIGN;
+#endif
+#ifndef OPENSSL_NO_DSA
+ case TLSEXT_signature_dsa:
+ return SSL_PKEY_DSA_SIGN;
+#endif
+#ifndef OPENSSL_NO_EC
+ case TLSEXT_signature_ecdsa:
+ return SSL_PKEY_ECC;
+#endif
+#ifndef OPENSSL_NO_GOST
+ case TLSEXT_signature_gostr34102001:
+ return SSL_PKEY_GOST01;
+
+ case TLSEXT_signature_gostr34102012_256:
+ return SSL_PKEY_GOST12_256;
+
+ case TLSEXT_signature_gostr34102012_512:
+ return SSL_PKEY_GOST12_512;
+#endif
+ }
+ return -1;
+}
+
+/* Convert TLS 1.2 signature algorithm extension values into NIDs */
+static void tls1_lookup_sigalg(int *phash_nid, int *psign_nid,
+ int *psignhash_nid, const unsigned char *data)
+{
+ int sign_nid = NID_undef, hash_nid = NID_undef;
+ if (!phash_nid && !psign_nid && !psignhash_nid)
+ return;
+ if (phash_nid || psignhash_nid) {
+ hash_nid = tls12_find_nid(data[0], tls12_md, OSSL_NELEM(tls12_md));
+ if (phash_nid)
+ *phash_nid = hash_nid;
+ }
+ if (psign_nid || psignhash_nid) {
+ sign_nid = tls12_find_nid(data[1], tls12_sig, OSSL_NELEM(tls12_sig));
+ if (psign_nid)
+ *psign_nid = sign_nid;
+ }
+ if (psignhash_nid) {
+ if (sign_nid == NID_undef || hash_nid == NID_undef
+ || OBJ_find_sigid_by_algs(psignhash_nid, hash_nid, sign_nid) <= 0)
+ *psignhash_nid = NID_undef;
+ }
+}
+
+/* Check to see if a signature algorithm is allowed */
+static int tls12_sigalg_allowed(SSL *s, int op, const unsigned char *ptmp)
+{
+ /* See if we have an entry in the hash table and it is enabled */
+ const tls12_hash_info *hinf = tls12_get_hash_info(ptmp[0]);
+ if (hinf == NULL || ssl_md(hinf->md_idx) == NULL)
+ return 0;
+ /* See if public key algorithm allowed */
+ if (tls12_get_pkey_idx(ptmp[1]) == -1)
+ return 0;
+ /* Finally see if security callback allows it */
+ return ssl_security(s, op, hinf->secbits, hinf->nid, (void *)ptmp);
+}
+
+/*
+ * Get a mask of disabled public key algorithms based on supported signature
+ * algorithms. For example if no signature algorithm supports RSA then RSA is
+ * disabled.
+ */
+
+void ssl_set_sig_mask(uint32_t *pmask_a, SSL *s, int op)
+{
+ const unsigned char *sigalgs;
+ size_t i, sigalgslen;
+ int have_rsa = 0, have_dsa = 0, have_ecdsa = 0;
+ /*
+ * Now go through all signature algorithms seeing if we support any for
+ * RSA, DSA, ECDSA. Do this for all versions not just TLS 1.2. To keep
+ * down calls to security callback only check if we have to.
+ */
+ sigalgslen = tls12_get_psigalgs(s, 1, &sigalgs);
+ for (i = 0; i < sigalgslen; i += 2, sigalgs += 2) {
+ switch (sigalgs[1]) {
+#ifndef OPENSSL_NO_RSA
+ case TLSEXT_signature_rsa:
+ if (!have_rsa && tls12_sigalg_allowed(s, op, sigalgs))
+ have_rsa = 1;
+ break;
+#endif
+#ifndef OPENSSL_NO_DSA
+ case TLSEXT_signature_dsa:
+ if (!have_dsa && tls12_sigalg_allowed(s, op, sigalgs))
+ have_dsa = 1;
+ break;
+#endif
+#ifndef OPENSSL_NO_EC
+ case TLSEXT_signature_ecdsa:
+ if (!have_ecdsa && tls12_sigalg_allowed(s, op, sigalgs))
+ have_ecdsa = 1;
+ break;
+#endif
+ }
+ }
+ if (!have_rsa)
+ *pmask_a |= SSL_aRSA;
+ if (!have_dsa)
+ *pmask_a |= SSL_aDSS;
+ if (!have_ecdsa)
+ *pmask_a |= SSL_aECDSA;
+}
+
+size_t tls12_copy_sigalgs(SSL *s, unsigned char *out,
+ const unsigned char *psig, size_t psiglen)
+{
+ unsigned char *tmpout = out;
+ size_t i;
+ for (i = 0; i < psiglen; i += 2, psig += 2) {
+ if (tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, psig)) {
+ *tmpout++ = psig[0];
+ *tmpout++ = psig[1];
+ }
+ }
+ return tmpout - out;
+}
+
+/* Given preference and allowed sigalgs set shared sigalgs */
+static int tls12_shared_sigalgs(SSL *s, TLS_SIGALGS *shsig,
+ const unsigned char *pref, size_t preflen,
+ const unsigned char *allow, size_t allowlen)
+{
+ const unsigned char *ptmp, *atmp;
+ size_t i, j, nmatch = 0;
+ for (i = 0, ptmp = pref; i < preflen; i += 2, ptmp += 2) {
+ /* Skip disabled hashes or signature algorithms */
+ if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SHARED, ptmp))
+ continue;
+ for (j = 0, atmp = allow; j < allowlen; j += 2, atmp += 2) {
+ if (ptmp[0] == atmp[0] && ptmp[1] == atmp[1]) {
+ nmatch++;
+ if (shsig) {
+ shsig->rhash = ptmp[0];
+ shsig->rsign = ptmp[1];
+ tls1_lookup_sigalg(&shsig->hash_nid,
+ &shsig->sign_nid,
+ &shsig->signandhash_nid, ptmp);
+ shsig++;
+ }
+ break;
+ }
+ }
+ }
+ return nmatch;
+}
+
+/* Set shared signature algorithms for SSL structures */
+static int tls1_set_shared_sigalgs(SSL *s)
+{
+ const unsigned char *pref, *allow, *conf;
+ size_t preflen, allowlen, conflen;
+ size_t nmatch;
+ TLS_SIGALGS *salgs = NULL;
+ CERT *c = s->cert;
+ unsigned int is_suiteb = tls1_suiteb(s);
+
+ OPENSSL_free(c->shared_sigalgs);
+ c->shared_sigalgs = NULL;
+ c->shared_sigalgslen = 0;
+ /* If client use client signature algorithms if not NULL */
+ if (!s->server && c->client_sigalgs && !is_suiteb) {
+ conf = c->client_sigalgs;
+ conflen = c->client_sigalgslen;
+ } else if (c->conf_sigalgs && !is_suiteb) {
+ conf = c->conf_sigalgs;
+ conflen = c->conf_sigalgslen;
+ } else
+ 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_sigalgs;
+ allowlen = s->s3->tmp.peer_sigalgslen;
+ } else {
+ allow = conf;
+ allowlen = conflen;
+ pref = s->s3->tmp.peer_sigalgs;
+ preflen = s->s3->tmp.peer_sigalgslen;
+ }
+ nmatch = tls12_shared_sigalgs(s, NULL, pref, preflen, allow, allowlen);
+ if (nmatch) {
+ salgs = OPENSSL_malloc(nmatch * sizeof(TLS_SIGALGS));
+ if (salgs == NULL)
+ return 0;
+ nmatch = tls12_shared_sigalgs(s, salgs, pref, preflen, allow, allowlen);
+ } else {
+ salgs = NULL;
+ }
+ c->shared_sigalgs = salgs;
+ c->shared_sigalgslen = nmatch;
+ return 1;
+}
+
+/* Set preferred digest for each key type */
+
+int tls1_save_sigalgs(SSL *s, const unsigned char *data, int dsize)
+{
+ CERT *c = s->cert;
+ /* Extension ignored for inappropriate versions */
+ if (!SSL_USE_SIGALGS(s))
+ return 1;
+ /* Should never happen */
+ if (!c)
+ return 0;
+
+ OPENSSL_free(s->s3->tmp.peer_sigalgs);
+ s->s3->tmp.peer_sigalgs = OPENSSL_malloc(dsize);
+ if (s->s3->tmp.peer_sigalgs == NULL)
+ return 0;
+ s->s3->tmp.peer_sigalgslen = dsize;
+ memcpy(s->s3->tmp.peer_sigalgs, data, dsize);
+ return 1;
+}
+
+int tls1_process_sigalgs(SSL *s)
+{
+ int idx;
+ size_t i;
+ const EVP_MD *md;
+ const EVP_MD **pmd = s->s3->tmp.md;
+ uint32_t *pvalid = s->s3->tmp.valid_flags;
+ CERT *c = s->cert;
+ TLS_SIGALGS *sigptr;
+ if (!tls1_set_shared_sigalgs(s))
+ return 0;
+
+ for (i = 0, sigptr = c->shared_sigalgs;
+ i < c->shared_sigalgslen; i++, sigptr++) {
+ idx = tls12_get_pkey_idx(sigptr->rsign);
+ if (idx > 0 && pmd[idx] == NULL) {
+ md = tls12_get_hash(sigptr->rhash);
+ pmd[idx] = md;
+ pvalid[idx] = CERT_PKEY_EXPLICIT_SIGN;
+ if (idx == SSL_PKEY_RSA_SIGN) {
+ pvalid[SSL_PKEY_RSA_ENC] = CERT_PKEY_EXPLICIT_SIGN;
+ pmd[SSL_PKEY_RSA_ENC] = md;
+ }
+ }
+
+ }
+ /*
+ * In strict mode leave unset digests as NULL to indicate we can't use
+ * the certificate for signing.
+ */
+ if (!(s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)) {
+ /*
+ * Set any remaining keys to default values. NOTE: if alg is not
+ * supported it stays as NULL.
+ */
+#ifndef OPENSSL_NO_DSA
+ if (pmd[SSL_PKEY_DSA_SIGN] == NULL)
+ pmd[SSL_PKEY_DSA_SIGN] = EVP_sha1();
+#endif
+#ifndef OPENSSL_NO_RSA
+ if (pmd[SSL_PKEY_RSA_SIGN] == NULL) {
+ pmd[SSL_PKEY_RSA_SIGN] = EVP_sha1();
+ pmd[SSL_PKEY_RSA_ENC] = EVP_sha1();
+ }
+#endif
+#ifndef OPENSSL_NO_EC
+ if (pmd[SSL_PKEY_ECC] == NULL)
+ pmd[SSL_PKEY_ECC] = EVP_sha1();
+#endif
+#ifndef OPENSSL_NO_GOST
+ if (pmd[SSL_PKEY_GOST01] == NULL)
+ pmd[SSL_PKEY_GOST01] = EVP_get_digestbynid(NID_id_GostR3411_94);
+ if (pmd[SSL_PKEY_GOST12_256] == NULL)
+ pmd[SSL_PKEY_GOST12_256] =
+ EVP_get_digestbynid(NID_id_GostR3411_2012_256);
+ if (pmd[SSL_PKEY_GOST12_512] == NULL)
+ pmd[SSL_PKEY_GOST12_512] =
+ EVP_get_digestbynid(NID_id_GostR3411_2012_512);
+#endif
+ }
+ return 1;
+}
+
+int SSL_get_sigalgs(SSL *s, int idx,
+ int *psign, int *phash, int *psignhash,
+ unsigned char *rsig, unsigned char *rhash)
+{
+ const unsigned char *psig = s->s3->tmp.peer_sigalgs;
+ if (psig == NULL)
+ return 0;
+ if (idx >= 0) {
+ idx <<= 1;
+ if (idx >= (int)s->s3->tmp.peer_sigalgslen)
+ return 0;
+ psig += idx;
+ if (rhash)
+ *rhash = psig[0];
+ if (rsig)
+ *rsig = psig[1];
+ tls1_lookup_sigalg(phash, psign, psignhash, psig);
+ }
+ return s->s3->tmp.peer_sigalgslen / 2;
+}
+
+int SSL_get_shared_sigalgs(SSL *s, int idx,
+ int *psign, int *phash, int *psignhash,
+ unsigned char *rsig, unsigned char *rhash)
+{
+ TLS_SIGALGS *shsigalgs = s->cert->shared_sigalgs;
+ if (!shsigalgs || idx >= (int)s->cert->shared_sigalgslen)
+ return 0;
+ shsigalgs += idx;
+ if (phash)
+ *phash = shsigalgs->hash_nid;
+ if (psign)
+ *psign = shsigalgs->sign_nid;
+ if (psignhash)
+ *psignhash = shsigalgs->signandhash_nid;
+ if (rsig)
+ *rsig = shsigalgs->rsign;
+ if (rhash)
+ *rhash = shsigalgs->rhash;
+ return s->cert->shared_sigalgslen;
+}
+
+#define MAX_SIGALGLEN (TLSEXT_hash_num * TLSEXT_signature_num * 2)
+
+typedef struct {
+ size_t sigalgcnt;
+ int sigalgs[MAX_SIGALGLEN];
+} sig_cb_st;
+
+static void get_sigorhash(int *psig, int *phash, const char *str)
+{
+ if (strcmp(str, "RSA") == 0) {
+ *psig = EVP_PKEY_RSA;
+ } else if (strcmp(str, "DSA") == 0) {
+ *psig = EVP_PKEY_DSA;
+ } else if (strcmp(str, "ECDSA") == 0) {
+ *psig = EVP_PKEY_EC;
+ } else {
+ *phash = OBJ_sn2nid(str);
+ if (*phash == NID_undef)
+ *phash = OBJ_ln2nid(str);
+ }
+}
+
+static int sig_cb(const char *elem, int len, void *arg)
+{
+ sig_cb_st *sarg = arg;
+ size_t i;
+ char etmp[20], *p;
+ int sig_alg = NID_undef, hash_alg = NID_undef;
+ if (elem == NULL)
+ return 0;
+ if (sarg->sigalgcnt == MAX_SIGALGLEN)
+ return 0;
+ if (len > (int)(sizeof(etmp) - 1))
+ return 0;
+ memcpy(etmp, elem, len);
+ etmp[len] = 0;
+ p = strchr(etmp, '+');
+ if (!p)
+ return 0;
+ *p = 0;
+ p++;
+ if (!*p)
+ return 0;
+
+ get_sigorhash(&sig_alg, &hash_alg, etmp);
+ get_sigorhash(&sig_alg, &hash_alg, p);
+
+ if (sig_alg == NID_undef || hash_alg == NID_undef)
+ return 0;
+
+ for (i = 0; i < sarg->sigalgcnt; i += 2) {
+ if (sarg->sigalgs[i] == sig_alg && sarg->sigalgs[i + 1] == hash_alg)
+ return 0;
+ }
+ sarg->sigalgs[sarg->sigalgcnt++] = hash_alg;
+ sarg->sigalgs[sarg->sigalgcnt++] = sig_alg;
+ return 1;
+}
+
+/*
+ * Set supported signature algorithms based on a colon separated list of the
+ * form sig+hash e.g. RSA+SHA512:DSA+SHA512
+ */
+int tls1_set_sigalgs_list(CERT *c, const char *str, int client)
+{
+ sig_cb_st sig;
+ sig.sigalgcnt = 0;
+ if (!CONF_parse_list(str, ':', 1, sig_cb, &sig))
+ return 0;
+ if (c == NULL)
+ return 1;
+ return tls1_set_sigalgs(c, sig.sigalgs, sig.sigalgcnt, client);
+}
+
+int tls1_set_sigalgs(CERT *c, const int *psig_nids, size_t salglen, int client)
+{
+ unsigned char *sigalgs, *sptr;
+ int rhash, rsign;
+ size_t i;
+ if (salglen & 1)
+ return 0;
+ sigalgs = OPENSSL_malloc(salglen);
+ if (sigalgs == NULL)
+ return 0;
+ for (i = 0, sptr = sigalgs; i < salglen; i += 2) {
+ rhash = tls12_find_id(*psig_nids++, tls12_md, OSSL_NELEM(tls12_md));
+ rsign = tls12_find_id(*psig_nids++, tls12_sig, OSSL_NELEM(tls12_sig));
+
+ if (rhash == -1 || rsign == -1)
+ goto err;
+ *sptr++ = rhash;
+ *sptr++ = rsign;
+ }
+
+ if (client) {
+ OPENSSL_free(c->client_sigalgs);
+ c->client_sigalgs = sigalgs;
+ c->client_sigalgslen = salglen;
+ } else {
+ OPENSSL_free(c->conf_sigalgs);
+ c->conf_sigalgs = sigalgs;
+ c->conf_sigalgslen = salglen;
+ }
+
+ return 1;
+
+ err:
+ OPENSSL_free(sigalgs);
+ return 0;
+}
+
+static int tls1_check_sig_alg(CERT *c, X509 *x, int default_nid)
+{
+ int sig_nid;
+ size_t i;
+ if (default_nid == -1)
+ return 1;
+ sig_nid = X509_get_signature_nid(x);
+ if (default_nid)
+ return sig_nid == default_nid ? 1 : 0;
+ for (i = 0; i < c->shared_sigalgslen; i++)
+ if (sig_nid == c->shared_sigalgs[i].signandhash_nid)
+ return 1;
+ return 0;
+}
+
+/* Check to see if a certificate issuer name matches list of CA names */
+static int ssl_check_ca_name(STACK_OF(X509_NAME) *names, X509 *x)
+{
+ X509_NAME *nm;
+ int i;
+ nm = X509_get_issuer_name(x);
+ for (i = 0; i < sk_X509_NAME_num(names); i++) {
+ if (!X509_NAME_cmp(nm, sk_X509_NAME_value(names, i)))
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Check certificate chain is consistent with TLS extensions and is usable by
+ * server. This servers two purposes: it allows users to check chains before
+ * passing them to the server and it allows the server to check chains before
+ * attempting to use them.
+ */
+
+/* Flags which need to be set for a certificate when strict mode not set */
+
+#define CERT_PKEY_VALID_FLAGS \
+ (CERT_PKEY_EE_SIGNATURE|CERT_PKEY_EE_PARAM)
+/* Strict mode flags */
+#define CERT_PKEY_STRICT_FLAGS \
+ (CERT_PKEY_VALID_FLAGS|CERT_PKEY_CA_SIGNATURE|CERT_PKEY_CA_PARAM \
+ | CERT_PKEY_ISSUER_NAME|CERT_PKEY_CERT_TYPE)
+
+int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
+ int idx)
+{
+ int i;
+ int rv = 0;
+ int check_flags = 0, strict_mode;
+ CERT_PKEY *cpk = NULL;
+ CERT *c = s->cert;
+ uint32_t *pvalid;
+ unsigned int suiteb_flags = tls1_suiteb(s);
+ /* idx == -1 means checking server chains */
+ if (idx != -1) {
+ /* idx == -2 means checking client certificate chains */
+ if (idx == -2) {
+ cpk = c->key;
+ idx = cpk - c->pkeys;
+ } else
+ cpk = c->pkeys + idx;
+ pvalid = s->s3->tmp.valid_flags + idx;
+ x = cpk->x509;
+ pk = cpk->privatekey;
+ chain = cpk->chain;
+ strict_mode = c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT;
+ /* If no cert or key, forget it */
+ if (!x || !pk)
+ goto end;
+ } else {
+ if (!x || !pk)
+ return 0;
+ idx = ssl_cert_type(x, pk);
+ if (idx == -1)
+ return 0;
+ pvalid = s->s3->tmp.valid_flags + idx;
+
+ if (c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)
+ check_flags = CERT_PKEY_STRICT_FLAGS;
+ else
+ check_flags = CERT_PKEY_VALID_FLAGS;
+ strict_mode = 1;
+ }
+
+ if (suiteb_flags) {
+ int ok;
+ if (check_flags)
+ check_flags |= CERT_PKEY_SUITEB;
+ ok = X509_chain_check_suiteb(NULL, x, chain, suiteb_flags);
+ if (ok == X509_V_OK)
+ rv |= CERT_PKEY_SUITEB;
+ else if (!check_flags)
+ goto end;
+ }
+
+ /*
+ * Check all signature algorithms are consistent with signature
+ * algorithms extension if TLS 1.2 or later and strict mode.
+ */
+ if (TLS1_get_version(s) >= TLS1_2_VERSION && strict_mode) {
+ int default_nid;
+ unsigned char rsign = 0;
+ if (s->s3->tmp.peer_sigalgs)
+ default_nid = 0;
+ /* If no sigalgs extension use defaults from RFC5246 */
+ else {
+ switch (idx) {
+ case SSL_PKEY_RSA_ENC:
+ case SSL_PKEY_RSA_SIGN:
+ rsign = TLSEXT_signature_rsa;
+ default_nid = NID_sha1WithRSAEncryption;
+ break;
+
+ case SSL_PKEY_DSA_SIGN:
+ rsign = TLSEXT_signature_dsa;
+ default_nid = NID_dsaWithSHA1;
+ break;
+
+ case SSL_PKEY_ECC:
+ rsign = TLSEXT_signature_ecdsa;
+ default_nid = NID_ecdsa_with_SHA1;
+ break;
+
+ case SSL_PKEY_GOST01:
+ rsign = TLSEXT_signature_gostr34102001;
+ default_nid = NID_id_GostR3411_94_with_GostR3410_2001;
+ break;
+
+ case SSL_PKEY_GOST12_256:
+ rsign = TLSEXT_signature_gostr34102012_256;
+ default_nid = NID_id_tc26_signwithdigest_gost3410_2012_256;
+ break;
+
+ case SSL_PKEY_GOST12_512:
+ rsign = TLSEXT_signature_gostr34102012_512;
+ default_nid = NID_id_tc26_signwithdigest_gost3410_2012_512;
+ break;
+
+ default:
+ default_nid = -1;
+ break;
+ }
+ }
+ /*
+ * If peer sent no signature algorithms extension and we have set
+ * preferred signature algorithms check we support sha1.
+ */
+ if (default_nid > 0 && c->conf_sigalgs) {
+ size_t j;
+ const unsigned char *p = c->conf_sigalgs;
+ for (j = 0; j < c->conf_sigalgslen; j += 2, p += 2) {
+ if (p[0] == TLSEXT_hash_sha1 && p[1] == rsign)
+ break;
+ }
+ if (j == c->conf_sigalgslen) {
+ if (check_flags)
+ goto skip_sigs;
+ else
+ goto end;
+ }
+ }
+ /* Check signature algorithm of each cert in chain */
+ if (!tls1_check_sig_alg(c, x, default_nid)) {
+ if (!check_flags)
+ goto end;
+ } else
+ rv |= CERT_PKEY_EE_SIGNATURE;
+ rv |= CERT_PKEY_CA_SIGNATURE;
+ for (i = 0; i < sk_X509_num(chain); i++) {
+ if (!tls1_check_sig_alg(c, sk_X509_value(chain, i), default_nid)) {
+ if (check_flags) {
+ rv &= ~CERT_PKEY_CA_SIGNATURE;
+ break;
+ } else
+ goto end;
+ }
+ }
+ }
+ /* Else not TLS 1.2, so mark EE and CA signing algorithms OK */
+ else if (check_flags)
+ rv |= CERT_PKEY_EE_SIGNATURE | CERT_PKEY_CA_SIGNATURE;
+ skip_sigs:
+ /* Check cert parameters are consistent */
+ if (tls1_check_cert_param(s, x, check_flags ? 1 : 2))
+ rv |= CERT_PKEY_EE_PARAM;
+ else if (!check_flags)
+ goto end;
+ if (!s->server)
+ rv |= CERT_PKEY_CA_PARAM;
+ /* In strict mode check rest of chain too */
+ else if (strict_mode) {
+ rv |= CERT_PKEY_CA_PARAM;
+ for (i = 0; i < sk_X509_num(chain); i++) {
+ X509 *ca = sk_X509_value(chain, i);
+ if (!tls1_check_cert_param(s, ca, 0)) {
+ if (check_flags) {
+ rv &= ~CERT_PKEY_CA_PARAM;
+ break;
+ } else
+ goto end;
+ }
+ }
+ }
+ if (!s->server && strict_mode) {
+ STACK_OF(X509_NAME) *ca_dn;
+ int check_type = 0;
+ switch (EVP_PKEY_id(pk)) {
+ case EVP_PKEY_RSA:
+ check_type = TLS_CT_RSA_SIGN;
+ break;
+ case EVP_PKEY_DSA:
+ check_type = TLS_CT_DSS_SIGN;
+ break;
+ case EVP_PKEY_EC:
+ check_type = TLS_CT_ECDSA_SIGN;
+ break;
+ }
+ if (check_type) {
+ const unsigned char *ctypes;
+ int ctypelen;
+ if (c->ctypes) {
+ ctypes = c->ctypes;
+ ctypelen = (int)c->ctype_num;
+ } else {
+ ctypes = (unsigned char *)s->s3->tmp.ctype;
+ ctypelen = s->s3->tmp.ctype_num;
+ }
+ for (i = 0; i < ctypelen; i++) {
+ if (ctypes[i] == check_type) {
+ rv |= CERT_PKEY_CERT_TYPE;
+ break;
+ }
+ }
+ if (!(rv & CERT_PKEY_CERT_TYPE) && !check_flags)
+ goto end;
+ } else
+ rv |= CERT_PKEY_CERT_TYPE;
+
+ ca_dn = s->s3->tmp.ca_names;
+
+ if (!sk_X509_NAME_num(ca_dn))
+ rv |= CERT_PKEY_ISSUER_NAME;
+
+ if (!(rv & CERT_PKEY_ISSUER_NAME)) {
+ if (ssl_check_ca_name(ca_dn, x))
+ rv |= CERT_PKEY_ISSUER_NAME;
+ }
+ if (!(rv & CERT_PKEY_ISSUER_NAME)) {
+ for (i = 0; i < sk_X509_num(chain); i++) {
+ X509 *xtmp = sk_X509_value(chain, i);
+ if (ssl_check_ca_name(ca_dn, xtmp)) {
+ rv |= CERT_PKEY_ISSUER_NAME;
+ break;
+ }
+ }
+ }
+ if (!check_flags && !(rv & CERT_PKEY_ISSUER_NAME))
+ goto end;
+ } else
+ rv |= CERT_PKEY_ISSUER_NAME | CERT_PKEY_CERT_TYPE;
+
+ if (!check_flags || (rv & check_flags) == check_flags)
+ rv |= CERT_PKEY_VALID;
+
+ end:
+
+ if (TLS1_get_version(s) >= TLS1_2_VERSION) {
+ if (*pvalid & CERT_PKEY_EXPLICIT_SIGN)
+ rv |= CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN;
+ else if (s->s3->tmp.md[idx] != NULL)
+ rv |= CERT_PKEY_SIGN;
+ } else
+ rv |= CERT_PKEY_SIGN | CERT_PKEY_EXPLICIT_SIGN;
+
+ /*
+ * When checking a CERT_PKEY structure all flags are irrelevant if the
+ * chain is invalid.
+ */
+ if (!check_flags) {
+ if (rv & CERT_PKEY_VALID)
+ *pvalid = rv;
+ else {
+ /* Preserve explicit sign flag, clear rest */
+ *pvalid &= CERT_PKEY_EXPLICIT_SIGN;
+ return 0;
+ }
+ }
+ return rv;
+}
+
+/* Set validity of certificates in an SSL structure */
+void tls1_set_cert_validity(SSL *s)
+{
+ tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA_ENC);
+ tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA_SIGN);
+ tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_DSA_SIGN);
+ tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_ECC);
+ tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST01);
+ tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST12_256);
+ tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST12_512);
+}
+
+/* User level utility function to check a chain is suitable */
+int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain)
+{
+ return tls1_check_chain(s, x, pk, chain, -1);
+}
+
+#ifndef OPENSSL_NO_DH
+DH *ssl_get_auto_dh(SSL *s)
+{
+ int dh_secbits = 80;
+ if (s->cert->dh_tmp_auto == 2)
+ return DH_get_1024_160();
+ if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aPSK)) {
+ if (s->s3->tmp.new_cipher->strength_bits == 256)
+ dh_secbits = 128;
+ else
+ dh_secbits = 80;
+ } else {
+ CERT_PKEY *cpk = ssl_get_server_send_pkey(s);
+ dh_secbits = EVP_PKEY_security_bits(cpk->privatekey);
+ }
+
+ if (dh_secbits >= 128) {
+ DH *dhp = DH_new();
+ BIGNUM *p, *g;
+ if (dhp == NULL)
+ return NULL;
+ g = BN_new();
+ if (g != NULL)
+ BN_set_word(g, 2);
+ if (dh_secbits >= 192)
+ p = BN_get_rfc3526_prime_8192(NULL);
+ else
+ p = BN_get_rfc3526_prime_3072(NULL);
+ if (p == NULL || g == NULL || !DH_set0_pqg(dhp, p, NULL, g)) {
+ DH_free(dhp);
+ BN_free(p);
+ BN_free(g);
+ return NULL;
+ }
+ return dhp;
+ }
+ if (dh_secbits >= 112)
+ return DH_get_2048_224();
+ return DH_get_1024_160();
+}
+#endif
+
+static int ssl_security_cert_key(SSL *s, SSL_CTX *ctx, X509 *x, int op)
+{
+ int secbits = -1;
+ EVP_PKEY *pkey = X509_get0_pubkey(x);
+ if (pkey) {
+ /*
+ * If no parameters this will return -1 and fail using the default
+ * security callback for any non-zero security level. This will
+ * reject keys which omit parameters but this only affects DSA and
+ * omission of parameters is never (?) done in practice.
+ */
+ secbits = EVP_PKEY_security_bits(pkey);
+ }
+ if (s)
+ return ssl_security(s, op, secbits, 0, x);
+ else
+ return ssl_ctx_security(ctx, op, secbits, 0, x);
+}
+
+static int ssl_security_cert_sig(SSL *s, SSL_CTX *ctx, X509 *x, int op)
+{
+ /* Lookup signature algorithm digest */
+ int secbits = -1, md_nid = NID_undef, sig_nid;
+ /* Don't check signature if self signed */
+ if ((X509_get_extension_flags(x) & EXFLAG_SS) != 0)
+ return 1;
+ sig_nid = X509_get_signature_nid(x);
+ if (sig_nid && OBJ_find_sigid_algs(sig_nid, &md_nid, NULL)) {
+ const EVP_MD *md;
+ if (md_nid && (md = EVP_get_digestbynid(md_nid)))
+ secbits = EVP_MD_size(md) * 4;
+ }
+ if (s)
+ return ssl_security(s, op, secbits, md_nid, x);
+ else
+ return ssl_ctx_security(ctx, op, secbits, md_nid, x);
+}
+
+int ssl_security_cert(SSL *s, SSL_CTX *ctx, X509 *x, int vfy, int is_ee)
+{
+ if (vfy)
+ vfy = SSL_SECOP_PEER;
+ if (is_ee) {
+ if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_EE_KEY | vfy))
+ return SSL_R_EE_KEY_TOO_SMALL;
+ } else {
+ if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_CA_KEY | vfy))
+ return SSL_R_CA_KEY_TOO_SMALL;
+ }
+ if (!ssl_security_cert_sig(s, ctx, x, SSL_SECOP_CA_MD | vfy))
+ return SSL_R_CA_MD_TOO_WEAK;
+ return 1;
+}
+
+/*
+ * Check security of a chain, if |sk| includes the end entity certificate then
+ * |x| is NULL. If |vfy| is 1 then we are verifying a peer chain and not sending
+ * one to the peer. Return values: 1 if ok otherwise error code to use
+ */
+
+int ssl_security_cert_chain(SSL *s, STACK_OF(X509) *sk, X509 *x, int vfy)
+{
+ int rv, start_idx, i;
+ if (x == NULL) {
+ x = sk_X509_value(sk, 0);
+ start_idx = 1;
+ } else
+ start_idx = 0;
+
+ rv = ssl_security_cert(s, NULL, x, vfy, 1);
+ if (rv != 1)
+ return rv;
+
+ for (i = start_idx; i < sk_X509_num(sk); i++) {
+ x = sk_X509_value(sk, i);
+ rv = ssl_security_cert(s, NULL, x, vfy, 0);
+ if (rv != 1)
+ return rv;
+ }
+ return 1;
+}
diff --git a/openssl-1.1.0h/ssl/t1_reneg.c b/openssl-1.1.0h/ssl/t1_reneg.c
new file mode 100644
index 0000000..01dc403
--- /dev/null
+++ b/openssl-1.1.0h/ssl/t1_reneg.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright 1995-2016 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
+ */
+
+#include <stdio.h>
+#include <openssl/objects.h>
+#include "ssl_locl.h"
+
+/* Add the client's renegotiation binding */
+int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
+ int maxlen)
+{
+ if (p) {
+ if ((s->s3->previous_client_finished_len + 1) > maxlen) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT,
+ SSL_R_RENEGOTIATE_EXT_TOO_LONG);
+ return 0;
+ }
+
+ /* Length byte */
+ *p = s->s3->previous_client_finished_len;
+ p++;
+
+ memcpy(p, s->s3->previous_client_finished,
+ s->s3->previous_client_finished_len);
+ }
+
+ *len = s->s3->previous_client_finished_len + 1;
+
+ return 1;
+}
+
+/*
+ * Parse the client's renegotiation binding and abort if it's not right
+ */
+int ssl_parse_clienthello_renegotiate_ext(SSL *s, PACKET *pkt, int *al)
+{
+ unsigned int ilen;
+ const unsigned char *d;
+
+ /* Parse the length byte */
+ if (!PACKET_get_1(pkt, &ilen)
+ || !PACKET_get_bytes(pkt, &d, ilen)) {
+ SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,
+ SSL_R_RENEGOTIATION_ENCODING_ERR);
+ *al = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+
+ /* Check that the extension matches */
+ if (ilen != s->s3->previous_client_finished_len) {
+ SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,
+ SSL_R_RENEGOTIATION_MISMATCH);
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ return 0;
+ }
+
+ if (memcmp(d, s->s3->previous_client_finished,
+ s->s3->previous_client_finished_len)) {
+ SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,
+ SSL_R_RENEGOTIATION_MISMATCH);
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ return 0;
+ }
+
+ s->s3->send_connection_binding = 1;
+
+ return 1;
+}
+
+/* Add the server's renegotiation binding */
+int ssl_add_serverhello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
+ int maxlen)
+{
+ if (p) {
+ if ((s->s3->previous_client_finished_len +
+ s->s3->previous_server_finished_len + 1) > maxlen) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT,
+ SSL_R_RENEGOTIATE_EXT_TOO_LONG);
+ return 0;
+ }
+
+ /* Length byte */
+ *p = s->s3->previous_client_finished_len +
+ s->s3->previous_server_finished_len;
+ p++;
+
+ memcpy(p, s->s3->previous_client_finished,
+ s->s3->previous_client_finished_len);
+ p += s->s3->previous_client_finished_len;
+
+ memcpy(p, s->s3->previous_server_finished,
+ s->s3->previous_server_finished_len);
+ }
+
+ *len = s->s3->previous_client_finished_len
+ + s->s3->previous_server_finished_len + 1;
+
+ return 1;
+}
+
+/*
+ * Parse the server's renegotiation binding and abort if it's not right
+ */
+int ssl_parse_serverhello_renegotiate_ext(SSL *s, PACKET *pkt, int *al)
+{
+ unsigned int expected_len = s->s3->previous_client_finished_len
+ + s->s3->previous_server_finished_len;
+ unsigned int ilen;
+ const unsigned char *data;
+
+ /* Check for logic errors */
+ OPENSSL_assert(!expected_len || s->s3->previous_client_finished_len);
+ OPENSSL_assert(!expected_len || s->s3->previous_server_finished_len);
+
+ /* Parse the length byte */
+ if (!PACKET_get_1(pkt, &ilen)) {
+ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,
+ SSL_R_RENEGOTIATION_ENCODING_ERR);
+ *al = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+
+ /* Consistency check */
+ if (PACKET_remaining(pkt) != ilen) {
+ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,
+ SSL_R_RENEGOTIATION_ENCODING_ERR);
+ *al = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+
+ /* Check that the extension matches */
+ if (ilen != expected_len) {
+ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,
+ SSL_R_RENEGOTIATION_MISMATCH);
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ 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) {
+ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,
+ SSL_R_RENEGOTIATION_MISMATCH);
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ 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) {
+ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,
+ SSL_R_RENEGOTIATION_MISMATCH);
+ *al = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+ s->s3->send_connection_binding = 1;
+
+ return 1;
+}
diff --git a/openssl-1.1.0h/ssl/t1_trce.c b/openssl-1.1.0h/ssl/t1_trce.c
new file mode 100644
index 0000000..76bdf79
--- /dev/null
+++ b/openssl-1.1.0h/ssl/t1_trce.c
@@ -0,0 +1,1322 @@
+/*
+ * Copyright 2012-2016 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
+ */
+
+#include "ssl_locl.h"
+
+#ifndef OPENSSL_NO_SSL_TRACE
+
+/* Packet trace support for OpenSSL */
+
+typedef struct {
+ int num;
+ const char *name;
+} ssl_trace_tbl;
+
+# define ssl_trace_str(val, tbl) \
+ do_ssl_trace_str(val, tbl, OSSL_NELEM(tbl))
+
+# define ssl_trace_list(bio, indent, msg, msglen, value, table) \
+ do_ssl_trace_list(bio, indent, msg, msglen, value, \
+ table, OSSL_NELEM(table))
+
+static const char *do_ssl_trace_str(int val, ssl_trace_tbl *tbl, size_t ntbl)
+{
+ size_t i;
+ for (i = 0; i < ntbl; i++, tbl++) {
+ if (tbl->num == val)
+ return tbl->name;
+ }
+ return "UNKNOWN";
+}
+
+static int do_ssl_trace_list(BIO *bio, int indent,
+ const unsigned char *msg, size_t msglen,
+ size_t vlen, ssl_trace_tbl *tbl, size_t ntbl)
+{
+ int val;
+ if (msglen % vlen)
+ return 0;
+ while (msglen) {
+ val = msg[0];
+ if (vlen == 2)
+ val = (val << 8) | msg[1];
+ BIO_indent(bio, indent, 80);
+ BIO_printf(bio, "%s (%d)\n", do_ssl_trace_str(val, tbl, ntbl), val);
+ msg += vlen;
+ msglen -= vlen;
+ }
+ return 1;
+}
+
+/* Version number */
+
+static ssl_trace_tbl ssl_version_tbl[] = {
+ {SSL3_VERSION, "SSL 3.0"},
+ {TLS1_VERSION, "TLS 1.0"},
+ {TLS1_1_VERSION, "TLS 1.1"},
+ {TLS1_2_VERSION, "TLS 1.2"},
+ {DTLS1_VERSION, "DTLS 1.0"},
+ {DTLS1_2_VERSION, "DTLS 1.2"},
+ {DTLS1_BAD_VER, "DTLS 1.0 (bad)"}
+};
+
+static ssl_trace_tbl ssl_content_tbl[] = {
+ {SSL3_RT_CHANGE_CIPHER_SPEC, "ChangeCipherSpec"},
+ {SSL3_RT_ALERT, "Alert"},
+ {SSL3_RT_HANDSHAKE, "Handshake"},
+ {SSL3_RT_APPLICATION_DATA, "ApplicationData"},
+ {DTLS1_RT_HEARTBEAT, "HeartBeat"}
+};
+
+/* Handshake types */
+static ssl_trace_tbl ssl_handshake_tbl[] = {
+ {SSL3_MT_HELLO_REQUEST, "HelloRequest"},
+ {SSL3_MT_CLIENT_HELLO, "ClientHello"},
+ {SSL3_MT_SERVER_HELLO, "ServerHello"},
+ {DTLS1_MT_HELLO_VERIFY_REQUEST, "HelloVerifyRequest"},
+ {SSL3_MT_NEWSESSION_TICKET, "NewSessionTicket"},
+ {SSL3_MT_CERTIFICATE, "Certificate"},
+ {SSL3_MT_SERVER_KEY_EXCHANGE, "ServerKeyExchange"},
+ {SSL3_MT_CERTIFICATE_REQUEST, "CertificateRequest"},
+ {SSL3_MT_CLIENT_KEY_EXCHANGE, "ClientKeyExchange"},
+ {SSL3_MT_CERTIFICATE_STATUS, "CertificateStatus"},
+ {SSL3_MT_SERVER_DONE, "ServerHelloDone"},
+ {SSL3_MT_CERTIFICATE_VERIFY, "CertificateVerify"},
+ {SSL3_MT_CLIENT_KEY_EXCHANGE, "ClientKeyExchange"},
+ {SSL3_MT_FINISHED, "Finished"},
+ {SSL3_MT_CERTIFICATE_STATUS, "CertificateStatus"}
+};
+
+/* Cipher suites */
+static ssl_trace_tbl ssl_ciphers_tbl[] = {
+ {0x0000, "SSL_NULL_WITH_NULL_NULL"},
+ {0x0001, "SSL_RSA_WITH_NULL_MD5"},
+ {0x0002, "SSL_RSA_WITH_NULL_SHA"},
+ {0x0003, "SSL_RSA_EXPORT_WITH_RC4_40_MD5"},
+ {0x0004, "SSL_RSA_WITH_RC4_128_MD5"},
+ {0x0005, "SSL_RSA_WITH_RC4_128_SHA"},
+ {0x0006, "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5"},
+ {0x0007, "SSL_RSA_WITH_IDEA_CBC_SHA"},
+ {0x0008, "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"},
+ {0x0009, "SSL_RSA_WITH_DES_CBC_SHA"},
+ {0x000A, "SSL_RSA_WITH_3DES_EDE_CBC_SHA"},
+ {0x000B, "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"},
+ {0x000C, "SSL_DH_DSS_WITH_DES_CBC_SHA"},
+ {0x000D, "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA"},
+ {0x000E, "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"},
+ {0x000F, "SSL_DH_RSA_WITH_DES_CBC_SHA"},
+ {0x0010, "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA"},
+ {0x0011, "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"},
+ {0x0012, "SSL_DHE_DSS_WITH_DES_CBC_SHA"},
+ {0x0013, "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"},
+ {0x0014, "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"},
+ {0x0015, "SSL_DHE_RSA_WITH_DES_CBC_SHA"},
+ {0x0016, "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA"},
+ {0x0017, "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5"},
+ {0x0018, "SSL_DH_anon_WITH_RC4_128_MD5"},
+ {0x0019, "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA"},
+ {0x001A, "SSL_DH_anon_WITH_DES_CBC_SHA"},
+ {0x001B, "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA"},
+ {0x001D, "SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA"},
+ {0x001E, "SSL_FORTEZZA_KEA_WITH_RC4_128_SHA"},
+ {0x001F, "TLS_KRB5_WITH_3DES_EDE_CBC_SHA"},
+ {0x0020, "TLS_KRB5_WITH_RC4_128_SHA"},
+ {0x0021, "TLS_KRB5_WITH_IDEA_CBC_SHA"},
+ {0x0022, "TLS_KRB5_WITH_DES_CBC_MD5"},
+ {0x0023, "TLS_KRB5_WITH_3DES_EDE_CBC_MD5"},
+ {0x0024, "TLS_KRB5_WITH_RC4_128_MD5"},
+ {0x0025, "TLS_KRB5_WITH_IDEA_CBC_MD5"},
+ {0x0026, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA"},
+ {0x0027, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA"},
+ {0x0028, "TLS_KRB5_EXPORT_WITH_RC4_40_SHA"},
+ {0x0029, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5"},
+ {0x002A, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5"},
+ {0x002B, "TLS_KRB5_EXPORT_WITH_RC4_40_MD5"},
+ {0x002C, "TLS_PSK_WITH_NULL_SHA"},
+ {0x002D, "TLS_DHE_PSK_WITH_NULL_SHA"},
+ {0x002E, "TLS_RSA_PSK_WITH_NULL_SHA"},
+ {0x002F, "TLS_RSA_WITH_AES_128_CBC_SHA"},
+ {0x0030, "TLS_DH_DSS_WITH_AES_128_CBC_SHA"},
+ {0x0031, "TLS_DH_RSA_WITH_AES_128_CBC_SHA"},
+ {0x0032, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"},
+ {0x0033, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"},
+ {0x0034, "TLS_DH_anon_WITH_AES_128_CBC_SHA"},
+ {0x0035, "TLS_RSA_WITH_AES_256_CBC_SHA"},
+ {0x0036, "TLS_DH_DSS_WITH_AES_256_CBC_SHA"},
+ {0x0037, "TLS_DH_RSA_WITH_AES_256_CBC_SHA"},
+ {0x0038, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"},
+ {0x0039, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"},
+ {0x003A, "TLS_DH_anon_WITH_AES_256_CBC_SHA"},
+ {0x003B, "TLS_RSA_WITH_NULL_SHA256"},
+ {0x003C, "TLS_RSA_WITH_AES_128_CBC_SHA256"},
+ {0x003D, "TLS_RSA_WITH_AES_256_CBC_SHA256"},
+ {0x003E, "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"},
+ {0x003F, "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"},
+ {0x0040, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"},
+ {0x0041, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA"},
+ {0x0042, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA"},
+ {0x0043, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA"},
+ {0x0044, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA"},
+ {0x0045, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA"},
+ {0x0046, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA"},
+ {0x0067, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"},
+ {0x0068, "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"},
+ {0x0069, "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"},
+ {0x006A, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"},
+ {0x006B, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"},
+ {0x006C, "TLS_DH_anon_WITH_AES_128_CBC_SHA256"},
+ {0x006D, "TLS_DH_anon_WITH_AES_256_CBC_SHA256"},
+ {0x0084, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA"},
+ {0x0085, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA"},
+ {0x0086, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA"},
+ {0x0087, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA"},
+ {0x0088, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA"},
+ {0x0089, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA"},
+ {0x008A, "TLS_PSK_WITH_RC4_128_SHA"},
+ {0x008B, "TLS_PSK_WITH_3DES_EDE_CBC_SHA"},
+ {0x008C, "TLS_PSK_WITH_AES_128_CBC_SHA"},
+ {0x008D, "TLS_PSK_WITH_AES_256_CBC_SHA"},
+ {0x008E, "TLS_DHE_PSK_WITH_RC4_128_SHA"},
+ {0x008F, "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA"},
+ {0x0090, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA"},
+ {0x0091, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA"},
+ {0x0092, "TLS_RSA_PSK_WITH_RC4_128_SHA"},
+ {0x0093, "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"},
+ {0x0094, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA"},
+ {0x0095, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA"},
+ {0x0096, "TLS_RSA_WITH_SEED_CBC_SHA"},
+ {0x0097, "TLS_DH_DSS_WITH_SEED_CBC_SHA"},
+ {0x0098, "TLS_DH_RSA_WITH_SEED_CBC_SHA"},
+ {0x0099, "TLS_DHE_DSS_WITH_SEED_CBC_SHA"},
+ {0x009A, "TLS_DHE_RSA_WITH_SEED_CBC_SHA"},
+ {0x009B, "TLS_DH_anon_WITH_SEED_CBC_SHA"},
+ {0x009C, "TLS_RSA_WITH_AES_128_GCM_SHA256"},
+ {0x009D, "TLS_RSA_WITH_AES_256_GCM_SHA384"},
+ {0x009E, "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"},
+ {0x009F, "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"},
+ {0x00A0, "TLS_DH_RSA_WITH_AES_128_GCM_SHA256"},
+ {0x00A1, "TLS_DH_RSA_WITH_AES_256_GCM_SHA384"},
+ {0x00A2, "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"},
+ {0x00A3, "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"},
+ {0x00A4, "TLS_DH_DSS_WITH_AES_128_GCM_SHA256"},
+ {0x00A5, "TLS_DH_DSS_WITH_AES_256_GCM_SHA384"},
+ {0x00A6, "TLS_DH_anon_WITH_AES_128_GCM_SHA256"},
+ {0x00A7, "TLS_DH_anon_WITH_AES_256_GCM_SHA384"},
+ {0x00A8, "TLS_PSK_WITH_AES_128_GCM_SHA256"},
+ {0x00A9, "TLS_PSK_WITH_AES_256_GCM_SHA384"},
+ {0x00AA, "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"},
+ {0x00AB, "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"},
+ {0x00AC, "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"},
+ {0x00AD, "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384"},
+ {0x00AE, "TLS_PSK_WITH_AES_128_CBC_SHA256"},
+ {0x00AF, "TLS_PSK_WITH_AES_256_CBC_SHA384"},
+ {0x00B0, "TLS_PSK_WITH_NULL_SHA256"},
+ {0x00B1, "TLS_PSK_WITH_NULL_SHA384"},
+ {0x00B2, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"},
+ {0x00B3, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"},
+ {0x00B4, "TLS_DHE_PSK_WITH_NULL_SHA256"},
+ {0x00B5, "TLS_DHE_PSK_WITH_NULL_SHA384"},
+ {0x00B6, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"},
+ {0x00B7, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"},
+ {0x00B8, "TLS_RSA_PSK_WITH_NULL_SHA256"},
+ {0x00B9, "TLS_RSA_PSK_WITH_NULL_SHA384"},
+ {0x00BA, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256"},
+ {0x00BB, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256"},
+ {0x00BC, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256"},
+ {0x00BD, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256"},
+ {0x00BE, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256"},
+ {0x00BF, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256"},
+ {0x00C0, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256"},
+ {0x00C1, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256"},
+ {0x00C2, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256"},
+ {0x00C3, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256"},
+ {0x00C4, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256"},
+ {0x00C5, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256"},
+ {0x00FF, "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"},
+ {0x5600, "TLS_FALLBACK_SCSV"},
+ {0xC001, "TLS_ECDH_ECDSA_WITH_NULL_SHA"},
+ {0xC002, "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"},
+ {0xC003, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"},
+ {0xC004, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"},
+ {0xC005, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"},
+ {0xC006, "TLS_ECDHE_ECDSA_WITH_NULL_SHA"},
+ {0xC007, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"},
+ {0xC008, "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"},
+ {0xC009, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"},
+ {0xC00A, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"},
+ {0xC00B, "TLS_ECDH_RSA_WITH_NULL_SHA"},
+ {0xC00C, "TLS_ECDH_RSA_WITH_RC4_128_SHA"},
+ {0xC00D, "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"},
+ {0xC00E, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"},
+ {0xC00F, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"},
+ {0xC010, "TLS_ECDHE_RSA_WITH_NULL_SHA"},
+ {0xC011, "TLS_ECDHE_RSA_WITH_RC4_128_SHA"},
+ {0xC012, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"},
+ {0xC013, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"},
+ {0xC014, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"},
+ {0xC015, "TLS_ECDH_anon_WITH_NULL_SHA"},
+ {0xC016, "TLS_ECDH_anon_WITH_RC4_128_SHA"},
+ {0xC017, "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"},
+ {0xC018, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"},
+ {0xC019, "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"},
+ {0xC01A, "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA"},
+ {0xC01B, "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA"},
+ {0xC01C, "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA"},
+ {0xC01D, "TLS_SRP_SHA_WITH_AES_128_CBC_SHA"},
+ {0xC01E, "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA"},
+ {0xC01F, "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA"},
+ {0xC020, "TLS_SRP_SHA_WITH_AES_256_CBC_SHA"},
+ {0xC021, "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA"},
+ {0xC022, "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA"},
+ {0xC023, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"},
+ {0xC024, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"},
+ {0xC025, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"},
+ {0xC026, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"},
+ {0xC027, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"},
+ {0xC028, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"},
+ {0xC029, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"},
+ {0xC02A, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"},
+ {0xC02B, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"},
+ {0xC02C, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"},
+ {0xC02D, "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"},
+ {0xC02E, "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"},
+ {0xC02F, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"},
+ {0xC030, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"},
+ {0xC031, "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"},
+ {0xC032, "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"},
+ {0xC033, "TLS_ECDHE_PSK_WITH_RC4_128_SHA"},
+ {0xC034, "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA"},
+ {0xC035, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA"},
+ {0xC036, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA"},
+ {0xC037, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256"},
+ {0xC038, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384"},
+ {0xC039, "TLS_ECDHE_PSK_WITH_NULL_SHA"},
+ {0xC03A, "TLS_ECDHE_PSK_WITH_NULL_SHA256"},
+ {0xC03B, "TLS_ECDHE_PSK_WITH_NULL_SHA384"},
+ {0xC03C, "TLS_RSA_WITH_ARIA_128_CBC_SHA256"},
+ {0xC03D, "TLS_RSA_WITH_ARIA_256_CBC_SHA384"},
+ {0xC03E, "TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256"},
+ {0xC03F, "TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384"},
+ {0xC040, "TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256"},
+ {0xC041, "TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384"},
+ {0xC042, "TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256"},
+ {0xC043, "TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384"},
+ {0xC044, "TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256"},
+ {0xC045, "TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384"},
+ {0xC046, "TLS_DH_anon_WITH_ARIA_128_CBC_SHA256"},
+ {0xC047, "TLS_DH_anon_WITH_ARIA_256_CBC_SHA384"},
+ {0xC048, "TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256"},
+ {0xC049, "TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384"},
+ {0xC04A, "TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256"},
+ {0xC04B, "TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384"},
+ {0xC04C, "TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256"},
+ {0xC04D, "TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384"},
+ {0xC04E, "TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256"},
+ {0xC04F, "TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384"},
+ {0xC050, "TLS_RSA_WITH_ARIA_128_GCM_SHA256"},
+ {0xC051, "TLS_RSA_WITH_ARIA_256_GCM_SHA384"},
+ {0xC052, "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256"},
+ {0xC053, "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384"},
+ {0xC054, "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256"},
+ {0xC055, "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384"},
+ {0xC056, "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256"},
+ {0xC057, "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384"},
+ {0xC058, "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256"},
+ {0xC059, "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384"},
+ {0xC05A, "TLS_DH_anon_WITH_ARIA_128_GCM_SHA256"},
+ {0xC05B, "TLS_DH_anon_WITH_ARIA_256_GCM_SHA384"},
+ {0xC05C, "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256"},
+ {0xC05D, "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384"},
+ {0xC05E, "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256"},
+ {0xC05F, "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384"},
+ {0xC060, "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256"},
+ {0xC061, "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384"},
+ {0xC062, "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256"},
+ {0xC063, "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384"},
+ {0xC064, "TLS_PSK_WITH_ARIA_128_CBC_SHA256"},
+ {0xC065, "TLS_PSK_WITH_ARIA_256_CBC_SHA384"},
+ {0xC066, "TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256"},
+ {0xC067, "TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384"},
+ {0xC068, "TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256"},
+ {0xC069, "TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384"},
+ {0xC06A, "TLS_PSK_WITH_ARIA_128_GCM_SHA256"},
+ {0xC06B, "TLS_PSK_WITH_ARIA_256_GCM_SHA384"},
+ {0xC06C, "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256"},
+ {0xC06D, "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384"},
+ {0xC06E, "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256"},
+ {0xC06F, "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384"},
+ {0xC070, "TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256"},
+ {0xC071, "TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384"},
+ {0xC072, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256"},
+ {0xC073, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384"},
+ {0xC074, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256"},
+ {0xC075, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384"},
+ {0xC076, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256"},
+ {0xC077, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384"},
+ {0xC078, "TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256"},
+ {0xC079, "TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384"},
+ {0xC07A, "TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256"},
+ {0xC07B, "TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384"},
+ {0xC07C, "TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256"},
+ {0xC07D, "TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384"},
+ {0xC07E, "TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256"},
+ {0xC07F, "TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384"},
+ {0xC080, "TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256"},
+ {0xC081, "TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384"},
+ {0xC082, "TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256"},
+ {0xC083, "TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384"},
+ {0xC084, "TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256"},
+ {0xC085, "TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384"},
+ {0xC086, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256"},
+ {0xC087, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384"},
+ {0xC088, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256"},
+ {0xC089, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384"},
+ {0xC08A, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256"},
+ {0xC08B, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384"},
+ {0xC08C, "TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256"},
+ {0xC08D, "TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384"},
+ {0xC08E, "TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256"},
+ {0xC08F, "TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384"},
+ {0xC090, "TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256"},
+ {0xC091, "TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384"},
+ {0xC092, "TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256"},
+ {0xC093, "TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384"},
+ {0xC094, "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256"},
+ {0xC095, "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384"},
+ {0xC096, "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256"},
+ {0xC097, "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384"},
+ {0xC098, "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256"},
+ {0xC099, "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384"},
+ {0xC09A, "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256"},
+ {0xC09B, "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384"},
+ {0xC09C, "TLS_RSA_WITH_AES_128_CCM"},
+ {0xC09D, "TLS_RSA_WITH_AES_256_CCM"},
+ {0xC09E, "TLS_DHE_RSA_WITH_AES_128_CCM"},
+ {0xC09F, "TLS_DHE_RSA_WITH_AES_256_CCM"},
+ {0xC0A0, "TLS_RSA_WITH_AES_128_CCM_8"},
+ {0xC0A1, "TLS_RSA_WITH_AES_256_CCM_8"},
+ {0xC0A2, "TLS_DHE_RSA_WITH_AES_128_CCM_8"},
+ {0xC0A3, "TLS_DHE_RSA_WITH_AES_256_CCM_8"},
+ {0xC0A4, "TLS_PSK_WITH_AES_128_CCM"},
+ {0xC0A5, "TLS_PSK_WITH_AES_256_CCM"},
+ {0xC0A6, "TLS_DHE_PSK_WITH_AES_128_CCM"},
+ {0xC0A7, "TLS_DHE_PSK_WITH_AES_256_CCM"},
+ {0xC0A8, "TLS_PSK_WITH_AES_128_CCM_8"},
+ {0xC0A9, "TLS_PSK_WITH_AES_256_CCM_8"},
+ {0xC0AA, "TLS_PSK_DHE_WITH_AES_128_CCM_8"},
+ {0xC0AB, "TLS_PSK_DHE_WITH_AES_256_CCM_8"},
+ {0xC0AC, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM"},
+ {0xC0AD, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM"},
+ {0xC0AE, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8"},
+ {0xC0AF, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8"},
+ {0xCCA8, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"},
+ {0xCCA9, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"},
+ {0xCCAA, "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256"},
+ {0xCCAB, "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256"},
+ {0xCCAC, "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256"},
+ {0xCCAD, "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256"},
+ {0xCCAE, "TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256"},
+ {0xFEFE, "SSL_RSA_FIPS_WITH_DES_CBC_SHA"},
+ {0xFEFF, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA"},
+};
+
+/* Compression methods */
+static ssl_trace_tbl ssl_comp_tbl[] = {
+ {0x0000, "No Compression"},
+ {0x0001, "Zlib Compression"}
+};
+
+/* Extensions */
+static ssl_trace_tbl ssl_exts_tbl[] = {
+ {TLSEXT_TYPE_server_name, "server_name"},
+ {TLSEXT_TYPE_max_fragment_length, "max_fragment_length"},
+ {TLSEXT_TYPE_client_certificate_url, "client_certificate_url"},
+ {TLSEXT_TYPE_trusted_ca_keys, "trusted_ca_keys"},
+ {TLSEXT_TYPE_truncated_hmac, "truncated_hmac"},
+ {TLSEXT_TYPE_status_request, "status_request"},
+ {TLSEXT_TYPE_user_mapping, "user_mapping"},
+ {TLSEXT_TYPE_client_authz, "client_authz"},
+ {TLSEXT_TYPE_server_authz, "server_authz"},
+ {TLSEXT_TYPE_cert_type, "cert_type"},
+ {TLSEXT_TYPE_elliptic_curves, "elliptic_curves"},
+ {TLSEXT_TYPE_ec_point_formats, "ec_point_formats"},
+ {TLSEXT_TYPE_srp, "srp"},
+ {TLSEXT_TYPE_signature_algorithms, "signature_algorithms"},
+ {TLSEXT_TYPE_use_srtp, "use_srtp"},
+ {TLSEXT_TYPE_heartbeat, "heartbeat"},
+ {TLSEXT_TYPE_session_ticket, "session_ticket"},
+ {TLSEXT_TYPE_renegotiate, "renegotiate"},
+# ifndef OPENSSL_NO_NEXTPROTONEG
+ {TLSEXT_TYPE_next_proto_neg, "next_proto_neg"},
+# endif
+ {TLSEXT_TYPE_signed_certificate_timestamp, "signed_certificate_timestamps"},
+ {TLSEXT_TYPE_padding, "padding"},
+ {TLSEXT_TYPE_encrypt_then_mac, "encrypt_then_mac"},
+ {TLSEXT_TYPE_extended_master_secret, "extended_master_secret"}
+};
+
+static ssl_trace_tbl ssl_curve_tbl[] = {
+ {1, "sect163k1 (K-163)"},
+ {2, "sect163r1"},
+ {3, "sect163r2 (B-163)"},
+ {4, "sect193r1"},
+ {5, "sect193r2"},
+ {6, "sect233k1 (K-233)"},
+ {7, "sect233r1 (B-233)"},
+ {8, "sect239k1"},
+ {9, "sect283k1 (K-283)"},
+ {10, "sect283r1 (B-283)"},
+ {11, "sect409k1 (K-409)"},
+ {12, "sect409r1 (B-409)"},
+ {13, "sect571k1 (K-571)"},
+ {14, "sect571r1 (B-571)"},
+ {15, "secp160k1"},
+ {16, "secp160r1"},
+ {17, "secp160r2"},
+ {18, "secp192k1"},
+ {19, "secp192r1 (P-192)"},
+ {20, "secp224k1"},
+ {21, "secp224r1 (P-224)"},
+ {22, "secp256k1"},
+ {23, "secp256r1 (P-256)"},
+ {24, "secp384r1 (P-384)"},
+ {25, "secp521r1 (P-521)"},
+ {26, "brainpoolP256r1"},
+ {27, "brainpoolP384r1"},
+ {28, "brainpoolP512r1"},
+ {29, "ecdh_x25519"},
+ {0xFF01, "arbitrary_explicit_prime_curves"},
+ {0xFF02, "arbitrary_explicit_char2_curves"}
+};
+
+static ssl_trace_tbl ssl_point_tbl[] = {
+ {0, "uncompressed"},
+ {1, "ansiX962_compressed_prime"},
+ {2, "ansiX962_compressed_char2"}
+};
+
+static ssl_trace_tbl ssl_md_tbl[] = {
+ {TLSEXT_hash_none, "none"},
+ {TLSEXT_hash_md5, "md5"},
+ {TLSEXT_hash_sha1, "sha1"},
+ {TLSEXT_hash_sha224, "sha224"},
+ {TLSEXT_hash_sha256, "sha256"},
+ {TLSEXT_hash_sha384, "sha384"},
+ {TLSEXT_hash_sha512, "sha512"},
+ {TLSEXT_hash_gostr3411, "md_gost94"},
+ {TLSEXT_hash_gostr34112012_256, "md_gost2012_256"},
+ {TLSEXT_hash_gostr34112012_512, "md_gost2012_512"}
+};
+
+static ssl_trace_tbl ssl_sig_tbl[] = {
+ {TLSEXT_signature_anonymous, "anonymous"},
+ {TLSEXT_signature_rsa, "rsa"},
+ {TLSEXT_signature_dsa, "dsa"},
+ {TLSEXT_signature_ecdsa, "ecdsa"},
+ {TLSEXT_signature_gostr34102001, "gost2001"},
+ {TLSEXT_signature_gostr34102012_256, "gost2012_256"},
+ {TLSEXT_signature_gostr34102012_512, "gost2012_512"}
+};
+
+static ssl_trace_tbl ssl_hb_tbl[] = {
+ {1, "peer_allowed_to_send"},
+ {2, "peer_not_allowed_to_send"}
+};
+
+static ssl_trace_tbl ssl_hb_type_tbl[] = {
+ {1, "heartbeat_request"},
+ {2, "heartbeat_response"}
+};
+
+static ssl_trace_tbl ssl_ctype_tbl[] = {
+ {1, "rsa_sign"},
+ {2, "dss_sign"},
+ {3, "rsa_fixed_dh"},
+ {4, "dss_fixed_dh"},
+ {5, "rsa_ephemeral_dh"},
+ {6, "dss_ephemeral_dh"},
+ {20, "fortezza_dms"},
+ {64, "ecdsa_sign"},
+ {65, "rsa_fixed_ecdh"},
+ {66, "ecdsa_fixed_ecdh"}
+};
+
+static void ssl_print_hex(BIO *bio, int indent, const char *name,
+ const unsigned char *msg, size_t msglen)
+{
+ size_t i;
+ BIO_indent(bio, indent, 80);
+ BIO_printf(bio, "%s (len=%d): ", name, (int)msglen);
+ for (i = 0; i < msglen; i++)
+ BIO_printf(bio, "%02X", msg[i]);
+ BIO_puts(bio, "\n");
+}
+
+static int ssl_print_hexbuf(BIO *bio, int indent,
+ const char *name, size_t nlen,
+ const unsigned char **pmsg, size_t *pmsglen)
+{
+ size_t blen;
+ const unsigned char *p = *pmsg;
+ if (*pmsglen < nlen)
+ return 0;
+ blen = p[0];
+ if (nlen > 1)
+ blen = (blen << 8) | p[1];
+ if (*pmsglen < nlen + blen)
+ return 0;
+ p += nlen;
+ ssl_print_hex(bio, indent, name, p, blen);
+ *pmsg += blen + nlen;
+ *pmsglen -= blen + nlen;
+ return 1;
+}
+
+static int ssl_print_version(BIO *bio, int indent, const char *name,
+ const unsigned char **pmsg, size_t *pmsglen)
+{
+ int vers;
+ if (*pmsglen < 2)
+ return 0;
+ vers = ((*pmsg)[0] << 8) | (*pmsg)[1];
+ BIO_indent(bio, indent, 80);
+ BIO_printf(bio, "%s=0x%x (%s)\n",
+ name, vers, ssl_trace_str(vers, ssl_version_tbl));
+ *pmsg += 2;
+ *pmsglen -= 2;
+ return 1;
+}
+
+static int ssl_print_random(BIO *bio, int indent,
+ const unsigned char **pmsg, size_t *pmsglen)
+{
+ unsigned int tm;
+ const unsigned char *p = *pmsg;
+ if (*pmsglen < 32)
+ return 0;
+ tm = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+ p += 4;
+ BIO_indent(bio, indent, 80);
+ BIO_puts(bio, "Random:\n");
+ BIO_indent(bio, indent + 2, 80);
+ BIO_printf(bio, "gmt_unix_time=0x%08X\n", tm);
+ ssl_print_hex(bio, indent + 2, "random_bytes", p, 28);
+ *pmsg += 32;
+ *pmsglen -= 32;
+ return 1;
+}
+
+static int ssl_print_signature(BIO *bio, int indent, SSL *s,
+ const unsigned char **pmsg, size_t *pmsglen)
+{
+ if (*pmsglen < 2)
+ return 0;
+ if (SSL_USE_SIGALGS(s)) {
+ const unsigned char *p = *pmsg;
+ BIO_indent(bio, indent, 80);
+ BIO_printf(bio, "Signature Algorithm %s+%s (%d+%d)\n",
+ ssl_trace_str(p[0], ssl_md_tbl),
+ ssl_trace_str(p[1], ssl_sig_tbl), p[0], p[1]);
+ *pmsg += 2;
+ *pmsglen -= 2;
+ }
+ return ssl_print_hexbuf(bio, indent, "Signature", 2, pmsg, pmsglen);
+}
+
+static int ssl_print_extension(BIO *bio, int indent, int server, int extype,
+ const unsigned char *ext, size_t extlen)
+{
+ size_t xlen;
+ BIO_indent(bio, indent, 80);
+ BIO_printf(bio, "extension_type=%s(%d), length=%d\n",
+ ssl_trace_str(extype, ssl_exts_tbl), extype, (int)extlen);
+ switch (extype) {
+ case TLSEXT_TYPE_ec_point_formats:
+ if (extlen < 1)
+ return 0;
+ xlen = ext[0];
+ if (extlen != xlen + 1)
+ return 0;
+ return ssl_trace_list(bio, indent + 2, ext + 1, xlen, 1, ssl_point_tbl);
+
+ case TLSEXT_TYPE_elliptic_curves:
+ if (extlen < 2)
+ return 0;
+ xlen = (ext[0] << 8) | ext[1];
+ if (extlen != xlen + 2)
+ return 0;
+ return ssl_trace_list(bio, indent + 2, ext + 2, xlen, 2, ssl_curve_tbl);
+
+ case TLSEXT_TYPE_signature_algorithms:
+
+ if (extlen < 2)
+ return 0;
+ xlen = (ext[0] << 8) | ext[1];
+ if (extlen != xlen + 2)
+ return 0;
+ if (xlen & 1)
+ return 0;
+ ext += 2;
+ while (xlen > 0) {
+ BIO_indent(bio, indent + 2, 80);
+ BIO_printf(bio, "%s+%s (%d+%d)\n",
+ ssl_trace_str(ext[0], ssl_md_tbl),
+ ssl_trace_str(ext[1], ssl_sig_tbl), ext[0], ext[1]);
+ xlen -= 2;
+ ext += 2;
+ }
+ break;
+
+ case TLSEXT_TYPE_renegotiate:
+ if (extlen < 1)
+ return 0;
+ xlen = ext[0];
+ if (xlen + 1 != extlen)
+ return 0;
+ ext++;
+ if (xlen) {
+ if (server) {
+ if (xlen & 1)
+ return 0;
+ xlen >>= 1;
+ }
+ ssl_print_hex(bio, indent + 4, "client_verify_data", ext, xlen);
+ if (server) {
+ ext += xlen;
+ ssl_print_hex(bio, indent + 4, "server_verify_data", ext, xlen);
+ }
+ } else {
+ BIO_indent(bio, indent + 4, 80);
+ BIO_puts(bio, "<EMPTY>\n");
+ }
+ break;
+
+ case TLSEXT_TYPE_heartbeat:
+ if (extlen != 1)
+ return 0;
+ BIO_indent(bio, indent + 2, 80);
+ BIO_printf(bio, "HeartbeatMode: %s\n",
+ ssl_trace_str(ext[0], ssl_hb_tbl));
+ break;
+
+ case TLSEXT_TYPE_session_ticket:
+ if (extlen != 0)
+ ssl_print_hex(bio, indent + 4, "ticket", ext, extlen);
+ break;
+
+ default:
+ BIO_dump_indent(bio, (const char *)ext, extlen, indent + 2);
+ }
+ return 1;
+}
+
+static int ssl_print_extensions(BIO *bio, int indent, int server,
+ const unsigned char *msg, size_t msglen)
+{
+ size_t extslen;
+ BIO_indent(bio, indent, 80);
+ if (msglen == 0) {
+ BIO_puts(bio, "No Extensions\n");
+ return 1;
+ }
+ extslen = (msg[0] << 8) | msg[1];
+ if (extslen != msglen - 2)
+ return 0;
+ msg += 2;
+ msglen = extslen;
+ BIO_printf(bio, "extensions, length = %d\n", (int)msglen);
+ while (msglen > 0) {
+ int extype;
+ size_t extlen;
+ if (msglen < 4)
+ return 0;
+ extype = (msg[0] << 8) | msg[1];
+ extlen = (msg[2] << 8) | msg[3];
+ if (msglen < extlen + 4)
+ return 0;
+ msg += 4;
+ if (!ssl_print_extension(bio, indent + 2, server, extype, msg, extlen))
+ return 0;
+ msg += extlen;
+ msglen -= extlen + 4;
+ }
+ return 1;
+}
+
+static int ssl_print_client_hello(BIO *bio, SSL *ssl, int indent,
+ const unsigned char *msg, size_t msglen)
+{
+ size_t len;
+ unsigned int cs;
+ if (!ssl_print_version(bio, indent, "client_version", &msg, &msglen))
+ return 0;
+ if (!ssl_print_random(bio, indent, &msg, &msglen))
+ return 0;
+ if (!ssl_print_hexbuf(bio, indent, "session_id", 1, &msg, &msglen))
+ return 0;
+ if (SSL_IS_DTLS(ssl)) {
+ if (!ssl_print_hexbuf(bio, indent, "cookie", 1, &msg, &msglen))
+ return 0;
+ }
+ if (msglen < 2)
+ return 0;
+ len = (msg[0] << 8) | msg[1];
+ msg += 2;
+ msglen -= 2;
+ BIO_indent(bio, indent, 80);
+ BIO_printf(bio, "cipher_suites (len=%d)\n", (int)len);
+ if (msglen < len || len & 1)
+ return 0;
+ while (len > 0) {
+ cs = (msg[0] << 8) | msg[1];
+ BIO_indent(bio, indent + 2, 80);
+ BIO_printf(bio, "{0x%02X, 0x%02X} %s\n",
+ msg[0], msg[1], ssl_trace_str(cs, ssl_ciphers_tbl));
+ msg += 2;
+ msglen -= 2;
+ len -= 2;
+ }
+ if (msglen < 1)
+ return 0;
+ len = msg[0];
+ msg++;
+ msglen--;
+ if (msglen < len)
+ return 0;
+ BIO_indent(bio, indent, 80);
+ BIO_printf(bio, "compression_methods (len=%d)\n", (int)len);
+ while (len > 0) {
+ BIO_indent(bio, indent + 2, 80);
+ BIO_printf(bio, "%s (0x%02X)\n",
+ ssl_trace_str(msg[0], ssl_comp_tbl), msg[0]);
+ msg++;
+ msglen--;
+ len--;
+ }
+ if (!ssl_print_extensions(bio, indent, 0, msg, msglen))
+ return 0;
+ return 1;
+}
+
+static int dtls_print_hello_vfyrequest(BIO *bio, int indent,
+ const unsigned char *msg, size_t msglen)
+{
+ if (!ssl_print_version(bio, indent, "server_version", &msg, &msglen))
+ return 0;
+ if (!ssl_print_hexbuf(bio, indent, "cookie", 1, &msg, &msglen))
+ return 0;
+ return 1;
+}
+
+static int ssl_print_server_hello(BIO *bio, int indent,
+ const unsigned char *msg, size_t msglen)
+{
+ unsigned int cs;
+ if (!ssl_print_version(bio, indent, "server_version", &msg, &msglen))
+ return 0;
+ if (!ssl_print_random(bio, indent, &msg, &msglen))
+ return 0;
+ if (!ssl_print_hexbuf(bio, indent, "session_id", 1, &msg, &msglen))
+ return 0;
+ if (msglen < 2)
+ return 0;
+ cs = (msg[0] << 8) | msg[1];
+ BIO_indent(bio, indent, 80);
+ BIO_printf(bio, "cipher_suite {0x%02X, 0x%02X} %s\n",
+ msg[0], msg[1], ssl_trace_str(cs, ssl_ciphers_tbl));
+ msg += 2;
+ msglen -= 2;
+ if (msglen < 1)
+ return 0;
+ BIO_indent(bio, indent, 80);
+ BIO_printf(bio, "compression_method: %s (0x%02X)\n",
+ ssl_trace_str(msg[0], ssl_comp_tbl), msg[0]);
+ msg++;
+ msglen--;
+ if (!ssl_print_extensions(bio, indent, 1, msg, msglen))
+ return 0;
+ return 1;
+}
+
+static int ssl_get_keyex(const char **pname, SSL *ssl)
+{
+ unsigned long alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
+ if (alg_k & SSL_kRSA) {
+ *pname = "rsa";
+ return SSL_kRSA;
+ }
+ if (alg_k & SSL_kDHE) {
+ *pname = "DHE";
+ return SSL_kDHE;
+ }
+ if (alg_k & SSL_kECDHE) {
+ *pname = "ECDHE";
+ return SSL_kECDHE;
+ }
+ if (alg_k & SSL_kPSK) {
+ *pname = "PSK";
+ return SSL_kPSK;
+ }
+ if (alg_k & SSL_kRSAPSK) {
+ *pname = "RSAPSK";
+ return SSL_kRSAPSK;
+ }
+ if (alg_k & SSL_kDHEPSK) {
+ *pname = "DHEPSK";
+ return SSL_kDHEPSK;
+ }
+ if (alg_k & SSL_kECDHEPSK) {
+ *pname = "ECDHEPSK";
+ return SSL_kECDHEPSK;
+ }
+ if (alg_k & SSL_kSRP) {
+ *pname = "SRP";
+ return SSL_kSRP;
+ }
+ if (alg_k & SSL_kGOST) {
+ *pname = "GOST";
+ return SSL_kGOST;
+ }
+ *pname = "UNKNOWN";
+ return 0;
+}
+
+static int ssl_print_client_keyex(BIO *bio, int indent, SSL *ssl,
+ const unsigned char *msg, size_t msglen)
+{
+ const char *algname;
+ int id;
+ id = ssl_get_keyex(&algname, ssl);
+ BIO_indent(bio, indent, 80);
+ BIO_printf(bio, "KeyExchangeAlgorithm=%s\n", algname);
+ if (id & SSL_PSK) {
+ if (!ssl_print_hexbuf(bio, indent + 2,
+ "psk_identity", 2, &msg, &msglen))
+ return 0;
+ }
+ switch (id) {
+
+ case SSL_kRSA:
+ case SSL_kRSAPSK:
+ if (TLS1_get_version(ssl) == SSL3_VERSION) {
+ ssl_print_hex(bio, indent + 2,
+ "EncyptedPreMasterSecret", msg, msglen);
+ } else {
+ if (!ssl_print_hexbuf(bio, indent + 2,
+ "EncyptedPreMasterSecret", 2, &msg, &msglen))
+ return 0;
+ }
+ break;
+
+ case SSL_kDHE:
+ case SSL_kDHEPSK:
+ if (!ssl_print_hexbuf(bio, indent + 2, "dh_Yc", 2, &msg, &msglen))
+ return 0;
+ break;
+
+ case SSL_kECDHE:
+ case SSL_kECDHEPSK:
+ if (!ssl_print_hexbuf(bio, indent + 2, "ecdh_Yc", 1, &msg, &msglen))
+ return 0;
+ break;
+
+ }
+
+ return !msglen;
+}
+
+static int ssl_print_server_keyex(BIO *bio, int indent, SSL *ssl,
+ const unsigned char *msg, size_t msglen)
+{
+ const char *algname;
+ int id;
+ id = ssl_get_keyex(&algname, ssl);
+ BIO_indent(bio, indent, 80);
+ BIO_printf(bio, "KeyExchangeAlgorithm=%s\n", algname);
+ if (id & SSL_PSK) {
+ if (!ssl_print_hexbuf(bio, indent + 2,
+ "psk_identity_hint", 2, &msg, &msglen))
+ return 0;
+ }
+ switch (id) {
+ case SSL_kRSA:
+
+ if (!ssl_print_hexbuf(bio, indent + 2, "rsa_modulus", 2, &msg, &msglen))
+ return 0;
+ if (!ssl_print_hexbuf(bio, indent + 2, "rsa_exponent", 2,
+ &msg, &msglen))
+ return 0;
+ break;
+
+ case SSL_kDHE:
+ case SSL_kDHEPSK:
+ if (!ssl_print_hexbuf(bio, indent + 2, "dh_p", 2, &msg, &msglen))
+ return 0;
+ if (!ssl_print_hexbuf(bio, indent + 2, "dh_g", 2, &msg, &msglen))
+ return 0;
+ if (!ssl_print_hexbuf(bio, indent + 2, "dh_Ys", 2, &msg, &msglen))
+ return 0;
+ break;
+
+# ifndef OPENSSL_NO_EC
+ case SSL_kECDHE:
+ case SSL_kECDHEPSK:
+ if (msglen < 1)
+ return 0;
+ BIO_indent(bio, indent + 2, 80);
+ if (msg[0] == EXPLICIT_PRIME_CURVE_TYPE)
+ BIO_puts(bio, "explicit_prime\n");
+ else if (msg[0] == EXPLICIT_CHAR2_CURVE_TYPE)
+ BIO_puts(bio, "explicit_char2\n");
+ else if (msg[0] == NAMED_CURVE_TYPE) {
+ int curve;
+ if (msglen < 3)
+ return 0;
+ curve = (msg[1] << 8) | msg[2];
+ BIO_printf(bio, "named_curve: %s (%d)\n",
+ ssl_trace_str(curve, ssl_curve_tbl), curve);
+ msg += 3;
+ msglen -= 3;
+ if (!ssl_print_hexbuf(bio, indent + 2, "point", 1, &msg, &msglen))
+ return 0;
+ } else {
+ BIO_printf(bio, "UNKNOWN CURVE PARAMETER TYPE %d\n", msg[0]);
+ return 0;
+ }
+ break;
+# endif
+
+ case SSL_kPSK:
+ case SSL_kRSAPSK:
+ break;
+ }
+ if (!(id & SSL_PSK))
+ ssl_print_signature(bio, indent, ssl, &msg, &msglen);
+ return !msglen;
+}
+
+static int ssl_print_certificate(BIO *bio, int indent,
+ const unsigned char **pmsg, size_t *pmsglen)
+{
+ size_t msglen = *pmsglen;
+ size_t clen;
+ X509 *x;
+ const unsigned char *p = *pmsg, *q;
+ if (msglen < 3)
+ return 0;
+ clen = (p[0] << 16) | (p[1] << 8) | p[2];
+ if (msglen < clen + 3)
+ return 0;
+ q = p + 3;
+ BIO_indent(bio, indent, 80);
+ BIO_printf(bio, "ASN.1Cert, length=%d", (int)clen);
+ x = d2i_X509(NULL, &q, clen);
+ if (!x)
+ BIO_puts(bio, "<UNPARSEABLE CERTIFICATE>\n");
+ else {
+ BIO_puts(bio, "\n------details-----\n");
+ X509_print_ex(bio, x, XN_FLAG_ONELINE, 0);
+ PEM_write_bio_X509(bio, x);
+ /* Print certificate stuff */
+ BIO_puts(bio, "------------------\n");
+ X509_free(x);
+ }
+ if (q != p + 3 + clen) {
+ BIO_puts(bio, "<TRAILING GARBAGE AFTER CERTIFICATE>\n");
+ }
+ *pmsg += clen + 3;
+ *pmsglen -= clen + 3;
+ return 1;
+}
+
+static int ssl_print_certificates(BIO *bio, int indent,
+ const unsigned char *msg, size_t msglen)
+{
+ size_t clen;
+ if (msglen < 3)
+ return 0;
+ clen = (msg[0] << 16) | (msg[1] << 8) | msg[2];
+ if (msglen != clen + 3)
+ return 0;
+ msg += 3;
+ BIO_indent(bio, indent, 80);
+ BIO_printf(bio, "certificate_list, length=%d\n", (int)clen);
+ while (clen > 0) {
+ if (!ssl_print_certificate(bio, indent + 2, &msg, &clen))
+ return 0;
+ }
+ return 1;
+}
+
+static int ssl_print_cert_request(BIO *bio, int indent, SSL *s,
+ const unsigned char *msg, size_t msglen)
+{
+ size_t xlen;
+ if (msglen < 1)
+ return 0;
+ xlen = msg[0];
+ if (msglen < xlen + 1)
+ return 0;
+ msg++;
+ BIO_indent(bio, indent, 80);
+ BIO_printf(bio, "certificate_types (len=%d)\n", (int)xlen);
+ if (!ssl_trace_list(bio, indent + 2, msg, xlen, 1, ssl_ctype_tbl))
+ return 0;
+ msg += xlen;
+ msglen -= xlen + 1;
+ if (!SSL_USE_SIGALGS(s))
+ goto skip_sig;
+ if (msglen < 2)
+ return 0;
+ xlen = (msg[0] << 8) | msg[1];
+ if (msglen < xlen + 2 || (xlen & 1))
+ return 0;
+ msg += 2;
+ BIO_indent(bio, indent, 80);
+ BIO_printf(bio, "signature_algorithms (len=%d)\n", (int)xlen);
+ while (xlen > 0) {
+ BIO_indent(bio, indent + 2, 80);
+ BIO_printf(bio, "%s+%s (%d+%d)\n",
+ ssl_trace_str(msg[0], ssl_md_tbl),
+ ssl_trace_str(msg[1], ssl_sig_tbl), msg[0], msg[1]);
+ xlen -= 2;
+ msg += 2;
+ }
+ msg += xlen;
+ msglen -= xlen + 2;
+
+ skip_sig:
+ xlen = (msg[0] << 8) | msg[1];
+ BIO_indent(bio, indent, 80);
+ if (msglen < xlen + 2)
+ return 0;
+ msg += 2;
+ msglen -= 2;
+ BIO_printf(bio, "certificate_authorities (len=%d)\n", (int)xlen);
+ while (xlen > 0) {
+ size_t dlen;
+ X509_NAME *nm;
+ const unsigned char *p;
+ if (xlen < 2)
+ return 0;
+ dlen = (msg[0] << 8) | msg[1];
+ if (xlen < dlen + 2)
+ return 0;
+ msg += 2;
+ BIO_indent(bio, indent + 2, 80);
+ BIO_printf(bio, "DistinguishedName (len=%d): ", (int)dlen);
+ p = msg;
+ nm = d2i_X509_NAME(NULL, &p, dlen);
+ if (!nm) {
+ BIO_puts(bio, "<UNPARSEABLE DN>\n");
+ } else {
+ X509_NAME_print_ex(bio, nm, 0, XN_FLAG_ONELINE);
+ BIO_puts(bio, "\n");
+ X509_NAME_free(nm);
+ }
+ xlen -= dlen + 2;
+ msg += dlen;
+ }
+ return 1;
+}
+
+static int ssl_print_ticket(BIO *bio, int indent,
+ const unsigned char *msg, size_t msglen)
+{
+ unsigned int tick_life;
+ if (msglen == 0) {
+ BIO_indent(bio, indent + 2, 80);
+ BIO_puts(bio, "No Ticket\n");
+ return 1;
+ }
+ if (msglen < 4)
+ return 0;
+ tick_life = (msg[0] << 24) | (msg[1] << 16) | (msg[2] << 8) | msg[3];
+ msglen -= 4;
+ msg += 4;
+ BIO_indent(bio, indent + 2, 80);
+ BIO_printf(bio, "ticket_lifetime_hint=%u\n", tick_life);
+ if (!ssl_print_hexbuf(bio, indent + 2, "ticket", 2, &msg, &msglen))
+ return 0;
+ if (msglen)
+ return 0;
+ return 1;
+}
+
+static int ssl_print_handshake(BIO *bio, SSL *ssl,
+ const unsigned char *msg, size_t msglen,
+ int indent)
+{
+ size_t hlen;
+ unsigned char htype;
+ if (msglen < 4)
+ return 0;
+ htype = msg[0];
+ hlen = (msg[1] << 16) | (msg[2] << 8) | msg[3];
+ BIO_indent(bio, indent, 80);
+ BIO_printf(bio, "%s, Length=%d\n",
+ ssl_trace_str(htype, ssl_handshake_tbl), (int)hlen);
+ msg += 4;
+ msglen -= 4;
+ if (SSL_IS_DTLS(ssl)) {
+ if (msglen < 8)
+ return 0;
+ BIO_indent(bio, indent, 80);
+ BIO_printf(bio, "message_seq=%d, fragment_offset=%d, "
+ "fragment_length=%d\n",
+ (msg[0] << 8) | msg[1],
+ (msg[2] << 16) | (msg[3] << 8) | msg[4],
+ (msg[5] << 16) | (msg[6] << 8) | msg[7]);
+ msg += 8;
+ msglen -= 8;
+ }
+ if (msglen < hlen)
+ return 0;
+ switch (htype) {
+ case SSL3_MT_CLIENT_HELLO:
+ if (!ssl_print_client_hello(bio, ssl, indent + 2, msg, msglen))
+ return 0;
+ break;
+
+ case DTLS1_MT_HELLO_VERIFY_REQUEST:
+ if (!dtls_print_hello_vfyrequest(bio, indent + 2, msg, msglen))
+ return 0;
+ break;
+
+ case SSL3_MT_SERVER_HELLO:
+ if (!ssl_print_server_hello(bio, indent + 2, msg, msglen))
+ return 0;
+ break;
+
+ case SSL3_MT_SERVER_KEY_EXCHANGE:
+ if (!ssl_print_server_keyex(bio, indent + 2, ssl, msg, msglen))
+ return 0;
+ break;
+
+ case SSL3_MT_CLIENT_KEY_EXCHANGE:
+ if (!ssl_print_client_keyex(bio, indent + 2, ssl, msg, msglen))
+ return 0;
+ break;
+
+ case SSL3_MT_CERTIFICATE:
+ if (!ssl_print_certificates(bio, indent + 2, msg, msglen))
+ return 0;
+ break;
+
+ case SSL3_MT_CERTIFICATE_VERIFY:
+ if (!ssl_print_signature(bio, indent + 2, ssl, &msg, &msglen))
+ return 0;
+ break;
+
+ case SSL3_MT_CERTIFICATE_REQUEST:
+ if (!ssl_print_cert_request(bio, indent + 2, ssl, msg, msglen))
+ return 0;
+ break;
+
+ case SSL3_MT_FINISHED:
+ ssl_print_hex(bio, indent + 2, "verify_data", msg, msglen);
+ break;
+
+ case SSL3_MT_SERVER_DONE:
+ if (msglen != 0)
+ ssl_print_hex(bio, indent + 2, "unexpected value", msg, msglen);
+ break;
+
+ case SSL3_MT_NEWSESSION_TICKET:
+ if (!ssl_print_ticket(bio, indent + 2, msg, msglen))
+ return 0;
+ break;
+
+ default:
+ BIO_indent(bio, indent + 2, 80);
+ BIO_puts(bio, "Unsupported, hex dump follows:\n");
+ BIO_dump_indent(bio, (const char *)msg, msglen, indent + 4);
+ }
+ return 1;
+}
+
+static int ssl_print_heartbeat(BIO *bio, int indent,
+ const unsigned char *msg, size_t msglen)
+{
+ if (msglen < 3)
+ return 0;
+ BIO_indent(bio, indent, 80);
+ BIO_printf(bio, "HeartBeatMessageType: %s\n",
+ ssl_trace_str(msg[0], ssl_hb_type_tbl));
+ msg++;
+ msglen--;
+ if (!ssl_print_hexbuf(bio, indent, "payload", 2, &msg, &msglen))
+ return 0;
+ ssl_print_hex(bio, indent, "padding", msg, msglen);
+ return 1;
+}
+
+const char *SSL_CIPHER_standard_name(const SSL_CIPHER *c)
+{
+ return ssl_trace_str(c->id & 0xFFFF, ssl_ciphers_tbl);
+}
+
+void SSL_trace(int write_p, int version, int content_type,
+ const void *buf, size_t msglen, SSL *ssl, void *arg)
+{
+ const unsigned char *msg = buf;
+ BIO *bio = arg;
+
+ switch (content_type) {
+ case SSL3_RT_HEADER:
+ {
+ int hvers = msg[1] << 8 | msg[2];
+ BIO_puts(bio, write_p ? "Sent" : "Received");
+ BIO_printf(bio, " Record\nHeader:\n Version = %s (0x%x)\n",
+ ssl_trace_str(hvers, ssl_version_tbl), hvers);
+ if (SSL_IS_DTLS(ssl)) {
+ BIO_printf(bio,
+ " epoch=%d, sequence_number=%04x%04x%04x\n",
+ (msg[3] << 8 | msg[4]),
+ (msg[5] << 8 | msg[6]),
+ (msg[7] << 8 | msg[8]), (msg[9] << 8 | msg[10]));
+ }
+
+ BIO_printf(bio, " Content Type = %s (%d)\n Length = %d",
+ ssl_trace_str(msg[0], ssl_content_tbl), msg[0],
+ msg[msglen - 2] << 8 | msg[msglen - 1]);
+ }
+ break;
+ case SSL3_RT_HANDSHAKE:
+ if (!ssl_print_handshake(bio, ssl, msg, msglen, 4))
+ BIO_printf(bio, "Message length parse error!\n");
+ break;
+
+ case SSL3_RT_CHANGE_CIPHER_SPEC:
+ if (msglen == 1 && msg[0] == 1)
+ BIO_puts(bio, " change_cipher_spec (1)\n");
+ else
+ ssl_print_hex(bio, 4, "unknown value", msg, msglen);
+ break;
+
+ case SSL3_RT_ALERT:
+ if (msglen != 2) {
+ BIO_puts(bio, " Illegal Alert Length\n");
+ } else {
+ BIO_printf(bio, " Level=%s(%d), description=%s(%d)\n",
+ SSL_alert_type_string_long(msg[0] << 8),
+ msg[0], SSL_alert_desc_string_long(msg[1]), msg[1]);
+ }
+ break;
+
+ case DTLS1_RT_HEARTBEAT:
+ ssl_print_heartbeat(bio, 4, msg, msglen);
+ break;
+
+ }
+
+ BIO_puts(bio, "\n");
+}
+
+#endif
diff --git a/openssl-1.1.0h/ssl/tls_srp.c b/openssl-1.1.0h/ssl/tls_srp.c
new file mode 100644
index 0000000..bfdbdf5
--- /dev/null
+++ b/openssl-1.1.0h/ssl/tls_srp.c
@@ -0,0 +1,430 @@
+/*
+ * Copyright 2004-2016 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
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include "ssl_locl.h"
+
+#ifndef OPENSSL_NO_SRP
+# include <openssl/srp.h>
+
+int SSL_CTX_SRP_CTX_free(struct ssl_ctx_st *ctx)
+{
+ if (ctx == NULL)
+ return 0;
+ OPENSSL_free(ctx->srp_ctx.login);
+ OPENSSL_free(ctx->srp_ctx.info);
+ BN_free(ctx->srp_ctx.N);
+ BN_free(ctx->srp_ctx.g);
+ BN_free(ctx->srp_ctx.s);
+ BN_free(ctx->srp_ctx.B);
+ BN_free(ctx->srp_ctx.A);
+ BN_free(ctx->srp_ctx.a);
+ BN_free(ctx->srp_ctx.b);
+ BN_free(ctx->srp_ctx.v);
+ memset(&ctx->srp_ctx, 0, sizeof(ctx->srp_ctx));
+ ctx->srp_ctx.strength = SRP_MINIMAL_N;
+ return (1);
+}
+
+int SSL_SRP_CTX_free(struct ssl_st *s)
+{
+ if (s == NULL)
+ return 0;
+ OPENSSL_free(s->srp_ctx.login);
+ OPENSSL_free(s->srp_ctx.info);
+ BN_free(s->srp_ctx.N);
+ BN_free(s->srp_ctx.g);
+ BN_free(s->srp_ctx.s);
+ BN_free(s->srp_ctx.B);
+ BN_free(s->srp_ctx.A);
+ BN_free(s->srp_ctx.a);
+ BN_free(s->srp_ctx.b);
+ BN_free(s->srp_ctx.v);
+ memset(&s->srp_ctx, 0, sizeof(s->srp_ctx));
+ s->srp_ctx.strength = SRP_MINIMAL_N;
+ return (1);
+}
+
+int SSL_SRP_CTX_init(struct ssl_st *s)
+{
+ SSL_CTX *ctx;
+
+ if ((s == NULL) || ((ctx = s->ctx) == NULL))
+ return 0;
+
+ memset(&s->srp_ctx, 0, sizeof(s->srp_ctx));
+
+ s->srp_ctx.SRP_cb_arg = ctx->srp_ctx.SRP_cb_arg;
+ /* set client Hello login callback */
+ s->srp_ctx.TLS_ext_srp_username_callback =
+ ctx->srp_ctx.TLS_ext_srp_username_callback;
+ /* set SRP N/g param callback for verification */
+ s->srp_ctx.SRP_verify_param_callback =
+ ctx->srp_ctx.SRP_verify_param_callback;
+ /* set SRP client passwd callback */
+ s->srp_ctx.SRP_give_srp_client_pwd_callback =
+ ctx->srp_ctx.SRP_give_srp_client_pwd_callback;
+
+ s->srp_ctx.strength = ctx->srp_ctx.strength;
+
+ if (((ctx->srp_ctx.N != NULL) &&
+ ((s->srp_ctx.N = BN_dup(ctx->srp_ctx.N)) == NULL)) ||
+ ((ctx->srp_ctx.g != NULL) &&
+ ((s->srp_ctx.g = BN_dup(ctx->srp_ctx.g)) == NULL)) ||
+ ((ctx->srp_ctx.s != NULL) &&
+ ((s->srp_ctx.s = BN_dup(ctx->srp_ctx.s)) == NULL)) ||
+ ((ctx->srp_ctx.B != NULL) &&
+ ((s->srp_ctx.B = BN_dup(ctx->srp_ctx.B)) == NULL)) ||
+ ((ctx->srp_ctx.A != NULL) &&
+ ((s->srp_ctx.A = BN_dup(ctx->srp_ctx.A)) == NULL)) ||
+ ((ctx->srp_ctx.a != NULL) &&
+ ((s->srp_ctx.a = BN_dup(ctx->srp_ctx.a)) == NULL)) ||
+ ((ctx->srp_ctx.v != NULL) &&
+ ((s->srp_ctx.v = BN_dup(ctx->srp_ctx.v)) == NULL)) ||
+ ((ctx->srp_ctx.b != NULL) &&
+ ((s->srp_ctx.b = BN_dup(ctx->srp_ctx.b)) == NULL))) {
+ SSLerr(SSL_F_SSL_SRP_CTX_INIT, ERR_R_BN_LIB);
+ goto err;
+ }
+ if ((ctx->srp_ctx.login != NULL) &&
+ ((s->srp_ctx.login = OPENSSL_strdup(ctx->srp_ctx.login)) == NULL)) {
+ SSLerr(SSL_F_SSL_SRP_CTX_INIT, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ if ((ctx->srp_ctx.info != NULL) &&
+ ((s->srp_ctx.info = BUF_strdup(ctx->srp_ctx.info)) == NULL)) {
+ SSLerr(SSL_F_SSL_SRP_CTX_INIT, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ s->srp_ctx.srp_Mask = ctx->srp_ctx.srp_Mask;
+
+ return (1);
+ err:
+ OPENSSL_free(s->srp_ctx.login);
+ OPENSSL_free(s->srp_ctx.info);
+ BN_free(s->srp_ctx.N);
+ BN_free(s->srp_ctx.g);
+ BN_free(s->srp_ctx.s);
+ BN_free(s->srp_ctx.B);
+ BN_free(s->srp_ctx.A);
+ BN_free(s->srp_ctx.a);
+ BN_free(s->srp_ctx.b);
+ BN_free(s->srp_ctx.v);
+ memset(&s->srp_ctx, 0, sizeof(s->srp_ctx));
+ return (0);
+}
+
+int SSL_CTX_SRP_CTX_init(struct ssl_ctx_st *ctx)
+{
+ if (ctx == NULL)
+ return 0;
+
+ memset(&ctx->srp_ctx, 0, sizeof(ctx->srp_ctx));
+ ctx->srp_ctx.strength = SRP_MINIMAL_N;
+
+ return (1);
+}
+
+/* server side */
+int SSL_srp_server_param_with_username(SSL *s, int *ad)
+{
+ unsigned char b[SSL_MAX_MASTER_KEY_LENGTH];
+ int al;
+
+ *ad = SSL_AD_UNKNOWN_PSK_IDENTITY;
+ if ((s->srp_ctx.TLS_ext_srp_username_callback != NULL) &&
+ ((al =
+ s->srp_ctx.TLS_ext_srp_username_callback(s, ad,
+ s->srp_ctx.SRP_cb_arg)) !=
+ SSL_ERROR_NONE))
+ return al;
+
+ *ad = SSL_AD_INTERNAL_ERROR;
+ if ((s->srp_ctx.N == NULL) ||
+ (s->srp_ctx.g == NULL) ||
+ (s->srp_ctx.s == NULL) || (s->srp_ctx.v == NULL))
+ return SSL3_AL_FATAL;
+
+ if (RAND_bytes(b, sizeof(b)) <= 0)
+ return SSL3_AL_FATAL;
+ s->srp_ctx.b = BN_bin2bn(b, sizeof(b), NULL);
+ OPENSSL_cleanse(b, sizeof(b));
+
+ /* Calculate: B = (kv + g^b) % N */
+
+ return ((s->srp_ctx.B =
+ SRP_Calc_B(s->srp_ctx.b, s->srp_ctx.N, s->srp_ctx.g,
+ s->srp_ctx.v)) !=
+ NULL) ? SSL_ERROR_NONE : SSL3_AL_FATAL;
+}
+
+/*
+ * If the server just has the raw password, make up a verifier entry on the
+ * fly
+ */
+int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass,
+ const char *grp)
+{
+ SRP_gN *GN = SRP_get_default_gN(grp);
+ if (GN == NULL)
+ return -1;
+ s->srp_ctx.N = BN_dup(GN->N);
+ s->srp_ctx.g = BN_dup(GN->g);
+ BN_clear_free(s->srp_ctx.v);
+ s->srp_ctx.v = NULL;
+ BN_clear_free(s->srp_ctx.s);
+ s->srp_ctx.s = NULL;
+ if (!SRP_create_verifier_BN
+ (user, pass, &s->srp_ctx.s, &s->srp_ctx.v, GN->N, GN->g))
+ return -1;
+
+ return 1;
+}
+
+int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g,
+ BIGNUM *sa, BIGNUM *v, char *info)
+{
+ if (N != NULL) {
+ if (s->srp_ctx.N != NULL) {
+ if (!BN_copy(s->srp_ctx.N, N)) {
+ BN_free(s->srp_ctx.N);
+ s->srp_ctx.N = NULL;
+ }
+ } else
+ s->srp_ctx.N = BN_dup(N);
+ }
+ if (g != NULL) {
+ if (s->srp_ctx.g != NULL) {
+ if (!BN_copy(s->srp_ctx.g, g)) {
+ BN_free(s->srp_ctx.g);
+ s->srp_ctx.g = NULL;
+ }
+ } else
+ s->srp_ctx.g = BN_dup(g);
+ }
+ if (sa != NULL) {
+ if (s->srp_ctx.s != NULL) {
+ if (!BN_copy(s->srp_ctx.s, sa)) {
+ BN_free(s->srp_ctx.s);
+ s->srp_ctx.s = NULL;
+ }
+ } else
+ s->srp_ctx.s = BN_dup(sa);
+ }
+ if (v != NULL) {
+ if (s->srp_ctx.v != NULL) {
+ if (!BN_copy(s->srp_ctx.v, v)) {
+ BN_free(s->srp_ctx.v);
+ s->srp_ctx.v = NULL;
+ }
+ } else
+ s->srp_ctx.v = BN_dup(v);
+ }
+ if (info != NULL) {
+ if (s->srp_ctx.info)
+ OPENSSL_free(s->srp_ctx.info);
+ if ((s->srp_ctx.info = BUF_strdup(info)) == NULL)
+ return -1;
+ }
+
+ if (!(s->srp_ctx.N) ||
+ !(s->srp_ctx.g) || !(s->srp_ctx.s) || !(s->srp_ctx.v))
+ return -1;
+
+ return 1;
+}
+
+int srp_generate_server_master_secret(SSL *s)
+{
+ BIGNUM *K = NULL, *u = NULL;
+ int ret = -1, tmp_len = 0;
+ unsigned char *tmp = NULL;
+
+ if (!SRP_Verify_A_mod_N(s->srp_ctx.A, s->srp_ctx.N))
+ goto err;
+ if ((u = SRP_Calc_u(s->srp_ctx.A, s->srp_ctx.B, s->srp_ctx.N)) == NULL)
+ goto err;
+ if ((K = SRP_Calc_server_key(s->srp_ctx.A, s->srp_ctx.v, u, s->srp_ctx.b,
+ s->srp_ctx.N)) == NULL)
+ goto err;
+
+ tmp_len = BN_num_bytes(K);
+ if ((tmp = OPENSSL_malloc(tmp_len)) == NULL)
+ goto err;
+ BN_bn2bin(K, tmp);
+ ret = ssl_generate_master_secret(s, tmp, tmp_len, 1);
+ err:
+ BN_clear_free(K);
+ BN_clear_free(u);
+ return ret;
+}
+
+/* client side */
+int srp_generate_client_master_secret(SSL *s)
+{
+ BIGNUM *x = NULL, *u = NULL, *K = NULL;
+ int ret = -1, tmp_len = 0;
+ char *passwd = NULL;
+ unsigned char *tmp = NULL;
+
+ /*
+ * Checks if b % n == 0
+ */
+ if (SRP_Verify_B_mod_N(s->srp_ctx.B, s->srp_ctx.N) == 0)
+ goto err;
+ if ((u = SRP_Calc_u(s->srp_ctx.A, s->srp_ctx.B, s->srp_ctx.N)) == NULL)
+ goto err;
+ if (s->srp_ctx.SRP_give_srp_client_pwd_callback == NULL)
+ goto err;
+ if (!
+ (passwd =
+ s->srp_ctx.SRP_give_srp_client_pwd_callback(s, s->srp_ctx.SRP_cb_arg)))
+ goto err;
+ if ((x = SRP_Calc_x(s->srp_ctx.s, s->srp_ctx.login, passwd)) == NULL)
+ goto err;
+ if ((K = SRP_Calc_client_key(s->srp_ctx.N, s->srp_ctx.B, s->srp_ctx.g, x,
+ s->srp_ctx.a, u)) == NULL)
+ goto err;
+
+ tmp_len = BN_num_bytes(K);
+ if ((tmp = OPENSSL_malloc(tmp_len)) == NULL)
+ goto err;
+ BN_bn2bin(K, tmp);
+ ret = ssl_generate_master_secret(s, tmp, tmp_len, 1);
+ err:
+ BN_clear_free(K);
+ BN_clear_free(x);
+ if (passwd != NULL)
+ OPENSSL_clear_free(passwd, strlen(passwd));
+ BN_clear_free(u);
+ return ret;
+}
+
+int srp_verify_server_param(SSL *s, int *al)
+{
+ SRP_CTX *srp = &s->srp_ctx;
+ /*
+ * Sanity check parameters: we can quickly check B % N == 0 by checking B
+ * != 0 since B < N
+ */
+ if (BN_ucmp(srp->g, srp->N) >= 0 || BN_ucmp(srp->B, srp->N) >= 0
+ || BN_is_zero(srp->B)) {
+ *al = SSL3_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+
+ if (BN_num_bits(srp->N) < srp->strength) {
+ *al = TLS1_AD_INSUFFICIENT_SECURITY;
+ return 0;
+ }
+
+ if (srp->SRP_verify_param_callback) {
+ if (srp->SRP_verify_param_callback(s, srp->SRP_cb_arg) <= 0) {
+ *al = TLS1_AD_INSUFFICIENT_SECURITY;
+ return 0;
+ }
+ } else if (!SRP_check_known_gN_param(srp->g, srp->N)) {
+ *al = TLS1_AD_INSUFFICIENT_SECURITY;
+ return 0;
+ }
+
+ return 1;
+}
+
+int SRP_Calc_A_param(SSL *s)
+{
+ unsigned char rnd[SSL_MAX_MASTER_KEY_LENGTH];
+
+ if (RAND_bytes(rnd, sizeof(rnd)) <= 0)
+ return 0;
+ s->srp_ctx.a = BN_bin2bn(rnd, sizeof(rnd), s->srp_ctx.a);
+ OPENSSL_cleanse(rnd, sizeof(rnd));
+
+ if (!(s->srp_ctx.A = SRP_Calc_A(s->srp_ctx.a, s->srp_ctx.N, s->srp_ctx.g)))
+ return 0;
+
+ return 1;
+}
+
+BIGNUM *SSL_get_srp_g(SSL *s)
+{
+ if (s->srp_ctx.g != NULL)
+ return s->srp_ctx.g;
+ return s->ctx->srp_ctx.g;
+}
+
+BIGNUM *SSL_get_srp_N(SSL *s)
+{
+ if (s->srp_ctx.N != NULL)
+ return s->srp_ctx.N;
+ return s->ctx->srp_ctx.N;
+}
+
+char *SSL_get_srp_username(SSL *s)
+{
+ if (s->srp_ctx.login != NULL)
+ return s->srp_ctx.login;
+ return s->ctx->srp_ctx.login;
+}
+
+char *SSL_get_srp_userinfo(SSL *s)
+{
+ if (s->srp_ctx.info != NULL)
+ return s->srp_ctx.info;
+ return s->ctx->srp_ctx.info;
+}
+
+# define tls1_ctx_ctrl ssl3_ctx_ctrl
+# define tls1_ctx_callback_ctrl ssl3_ctx_callback_ctrl
+
+int SSL_CTX_set_srp_username(SSL_CTX *ctx, char *name)
+{
+ return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_USERNAME, 0, name);
+}
+
+int SSL_CTX_set_srp_password(SSL_CTX *ctx, char *password)
+{
+ return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD, 0, password);
+}
+
+int SSL_CTX_set_srp_strength(SSL_CTX *ctx, int strength)
+{
+ return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH, strength,
+ NULL);
+}
+
+int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx,
+ int (*cb) (SSL *, void *))
+{
+ return tls1_ctx_callback_ctrl(ctx, SSL_CTRL_SET_SRP_VERIFY_PARAM_CB,
+ (void (*)(void))cb);
+}
+
+int SSL_CTX_set_srp_cb_arg(SSL_CTX *ctx, void *arg)
+{
+ return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_SRP_ARG, 0, arg);
+}
+
+int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx,
+ int (*cb) (SSL *, int *, void *))
+{
+ return tls1_ctx_callback_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB,
+ (void (*)(void))cb);
+}
+
+int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx,
+ char *(*cb) (SSL *, void *))
+{
+ return tls1_ctx_callback_ctrl(ctx, SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB,
+ (void (*)(void))cb);
+}
+
+#endif