Add new functions to extract {client,server}_random, master_key
[openssl.git] / ssl / ssl_lib.c
index 9a29d9c60a6c0c5659651044e4b30c037f79b9db..081f27a73e92ee81f1ae3ad9af477b2ad683547b 100644 (file)
 #endif
 #include <stdio.h>
 #include "ssl_locl.h"
-#include "kssl_lcl.h"
 #include <openssl/objects.h>
 #include <openssl/lhash.h>
 #include <openssl/x509v3.h>
@@ -215,17 +214,12 @@ int SSL_clear(SSL *s)
     s->version = s->method->version;
     s->client_version = s->version;
     s->rwstate = SSL_NOTHING;
-    s->rstate = SSL_ST_READ_HEADER;
-
-    if (s->init_buf != NULL) {
-        BUF_MEM_free(s->init_buf);
-        s->init_buf = NULL;
-    }
 
+    BUF_MEM_free(s->init_buf);
+    s->init_buf = NULL;
     ssl_clear_cipher_ctx(s);
     ssl_clear_hash_ctx(&s->read_hash);
     ssl_clear_hash_ctx(&s->write_hash);
-
     s->first_packet = 0;
 
     /*
@@ -277,18 +271,12 @@ SSL *SSL_new(SSL_CTX *ctx)
         return (NULL);
     }
 
-    s = (SSL *)OPENSSL_malloc(sizeof(SSL));
+    s = OPENSSL_malloc(sizeof(*s));
     if (s == NULL)
         goto err;
-    memset(s, 0, sizeof(SSL));
-
-    RECORD_LAYER_set_ssl(&s->rlayer, s);
-    SSL3_RECORD_clear(RECORD_LAYER_get_rrec(&s->rlayer));
-    SSL3_RECORD_clear(RECORD_LAYER_get_wrec(&s->rlayer));
+    memset(s, 0, sizeof(*s));
 
-#ifndef OPENSSL_NO_KRB5
-    s->kssl_ctx = kssl_ctx_new();
-#endif                          /* OPENSSL_NO_KRB5 */
+    RECORD_LAYER_init(&s->rlayer, s);
 
     s->options = ctx->options;
     s->mode = ctx->mode;
@@ -327,7 +315,6 @@ SSL *SSL_new(SSL_CTX *ctx)
 
     CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX);
     s->ctx = ctx;
-#ifndef OPENSSL_NO_TLSEXT
     s->tlsext_debug_cb = 0;
     s->tlsext_debug_arg = NULL;
     s->tlsext_ticket_expected = 0;
@@ -372,7 +359,6 @@ SSL *SSL_new(SSL_CTX *ctx)
                s->ctx->alpn_client_proto_list_len);
         s->alpn_client_proto_list_len = s->ctx->alpn_client_proto_list_len;
     }
-#endif
 
     s->verify_result = X509_V_OK;
 
@@ -384,7 +370,7 @@ SSL *SSL_new(SSL_CTX *ctx)
     s->references = 1;
     s->server = (ctx->method->ssl_accept == ssl_undefined_function) ? 0 : 1;
 
-    if(!SSL_clear(s))
+    if (!SSL_clear(s))
         goto err;
 
     CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data);
@@ -396,8 +382,7 @@ SSL *SSL_new(SSL_CTX *ctx)
 
     return (s);
  err:
-    if (s != NULL)
-        SSL_free(s);
+    SSL_free(s);
     SSLerr(SSL_F_SSL_NEW, ERR_R_MALLOC_FAILURE);
     return (NULL);
 }
@@ -536,9 +521,7 @@ void SSL_free(SSL *s)
     }
 #endif
 
-    if (s->param)
-        X509_VERIFY_PARAM_free(s->param);
-
+    X509_VERIFY_PARAM_free(s->param);
     CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data);
 
     if (s->bbio != NULL) {
@@ -553,14 +536,11 @@ void SSL_free(SSL *s)
     if (s->wbio != s->rbio)
         BIO_free_all(s->wbio);
 
-    if (s->init_buf != NULL)
-        BUF_MEM_free(s->init_buf);
+    BUF_MEM_free(s->init_buf);
 
     /* add extra stuff */
-    if (s->cipher_list != NULL)
-        sk_SSL_CIPHER_free(s->cipher_list);
-    if (s->cipher_list_by_id != NULL)
-        sk_SSL_CIPHER_free(s->cipher_list_by_id);
+    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) {
@@ -572,55 +552,35 @@ void SSL_free(SSL *s)
     ssl_clear_hash_ctx(&s->read_hash);
     ssl_clear_hash_ctx(&s->write_hash);
 
-    if (s->cert != NULL)
-        ssl_cert_free(s->cert);
+    ssl_cert_free(s->cert);
     /* Free up if allocated */
 
-#ifndef OPENSSL_NO_TLSEXT
-    if (s->tlsext_hostname)
-        OPENSSL_free(s->tlsext_hostname);
-    if (s->initial_ctx)
-        SSL_CTX_free(s->initial_ctx);
-# ifndef OPENSSL_NO_EC
-    if (s->tlsext_ecpointformatlist)
-        OPENSSL_free(s->tlsext_ecpointformatlist);
-    if (s->tlsext_ellipticcurvelist)
-        OPENSSL_free(s->tlsext_ellipticcurvelist);
-# endif                         /* OPENSSL_NO_EC */
-    if (s->tlsext_ocsp_exts)
-        sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts, X509_EXTENSION_free);
-    if (s->tlsext_ocsp_ids)
-        sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids, OCSP_RESPID_free);
-    if (s->tlsext_ocsp_resp)
-        OPENSSL_free(s->tlsext_ocsp_resp);
-    if (s->alpn_client_proto_list)
-        OPENSSL_free(s->alpn_client_proto_list);
-#endif
+    OPENSSL_free(s->tlsext_hostname);
+    SSL_CTX_free(s->initial_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);
+    sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids, OCSP_RESPID_free);
+    OPENSSL_free(s->tlsext_ocsp_resp);
+    OPENSSL_free(s->alpn_client_proto_list);
 
-    if (s->client_CA != NULL)
-        sk_X509_NAME_pop_free(s->client_CA, X509_NAME_free);
+    sk_X509_NAME_pop_free(s->client_CA, X509_NAME_free);
 
     if (s->method != NULL)
         s->method->ssl_free(s);
 
     RECORD_LAYER_release(&s->rlayer);
 
-    if (s->ctx)
-        SSL_CTX_free(s->ctx);
-
-#ifndef OPENSSL_NO_KRB5
-    if (s->kssl_ctx != NULL)
-        kssl_ctx_free(s->kssl_ctx);
-#endif                          /* OPENSSL_NO_KRB5 */
+    SSL_CTX_free(s->ctx);
 
-#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
-    if (s->next_proto_negotiated)
-        OPENSSL_free(s->next_proto_negotiated);
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
+    OPENSSL_free(s->next_proto_negotiated);
 #endif
 
 #ifndef OPENSSL_NO_SRTP
-    if (s->srtp_profiles)
-        sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles);
+    sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles);
 #endif
 
     OPENSSL_free(s);
@@ -891,7 +851,7 @@ STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s)
 int SSL_copy_session_id(SSL *t, const SSL *f)
 {
     /* Do we need to to SSL locking? */
-    if(!SSL_set_session(t, SSL_get_session(f))) {
+    if (!SSL_set_session(t, SSL_get_session(f))) {
         return 0;
     }
 
@@ -907,7 +867,7 @@ int SSL_copy_session_id(SSL *t, const SSL *f)
     CRYPTO_add(&f->cert->references, 1, CRYPTO_LOCK_SSL_CERT);
     ssl_cert_free(t->cert);
     t->cert = f->cert;
-    if(!SSL_set_session_id_context(t, f->sid_ctx, f->sid_ctx_length)) {
+    if (!SSL_set_session_id_context(t, f->sid_ctx, f->sid_ctx_length)) {
         return 0;
     }
 
@@ -1112,10 +1072,10 @@ long SSL_ctrl(SSL *s, int cmd, long larg, void *parg)
 
     case SSL_CTRL_GET_RAW_CIPHERLIST:
         if (parg) {
-            if (s->cert->ciphers_raw == NULL)
+            if (s->s3->tmp.ciphers_raw == NULL)
                 return 0;
-            *(unsigned char **)parg = s->cert->ciphers_raw;
-            return (int)s->cert->ciphers_rawlen;
+            *(unsigned char **)parg = s->s3->tmp.ciphers_raw;
+            return (int)s->s3->tmp.ciphers_rawlen;
         } else
             return ssl_put_cipher_by_char(s, NULL, NULL);
     case SSL_CTRL_GET_EXTMS_SUPPORT:
@@ -1298,6 +1258,13 @@ STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s)
     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;
@@ -1430,162 +1397,6 @@ char *SSL_get_shared_ciphers(const SSL *s, char *buf, int len)
     return (buf);
 }
 
-int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk,
-                             unsigned char *p,
-                             int (*put_cb) (const SSL_CIPHER *,
-                                            unsigned char *))
-{
-    int i, j = 0;
-    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;
-    if (put_cb == NULL)
-        put_cb = s->method->put_cipher_by_char;
-
-    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))
-            continue;
-#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
-        if (c->id == SSL3_CK_SCSV) {
-            if (!empty_reneg_info_scsv)
-                continue;
-            else
-                empty_reneg_info_scsv = 0;
-        }
-#endif
-        j = put_cb(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 = put_cb(&scsv, p);
-            p += j;
-#ifdef OPENSSL_RI_DEBUG
-            fprintf(stderr,
-                    "TLS_EMPTY_RENEGOTIATION_INFO_SCSV sent by client\n");
-#endif
-        }
-        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 = put_cb(&scsv, p);
-            p += j;
-        }
-    }
-
-    return (p - q);
-}
-
-STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, unsigned char *p,
-                                               int num,
-                                               STACK_OF(SSL_CIPHER) **skp)
-{
-    const SSL_CIPHER *c;
-    STACK_OF(SSL_CIPHER) *sk;
-    int i, n;
-
-    if (s->s3)
-        s->s3->send_connection_binding = 0;
-
-    n = ssl_put_cipher_by_char(s, NULL, NULL);
-    if (n == 0 || (num % n) != 0) {
-        SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,
-               SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
-        return (NULL);
-    }
-    if ((skp == NULL) || (*skp == NULL))
-        sk = sk_SSL_CIPHER_new_null(); /* change perhaps later */
-    else {
-        sk = *skp;
-        sk_SSL_CIPHER_zero(sk);
-    }
-
-    if (s->cert->ciphers_raw)
-        OPENSSL_free(s->cert->ciphers_raw);
-    s->cert->ciphers_raw = BUF_memdup(p, num);
-    if (s->cert->ciphers_raw == NULL) {
-        SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
-        goto err;
-    }
-    s->cert->ciphers_rawlen = (size_t)num;
-
-    for (i = 0; i < num; i += n) {
-        /* Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV */
-        if (s->s3 && (n != 3 || !p[0]) &&
-            (p[n - 2] == ((SSL3_CK_SCSV >> 8) & 0xff)) &&
-            (p[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);
-                ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
-                goto err;
-            }
-            s->s3->send_connection_binding = 1;
-            p += n;
-#ifdef OPENSSL_RI_DEBUG
-            fprintf(stderr, "SCSV received by server\n");
-#endif
-            continue;
-        }
-
-        /* Check for TLS_FALLBACK_SCSV */
-        if ((n != 3 || !p[0]) &&
-            (p[n - 2] == ((SSL3_CK_FALLBACK_SCSV >> 8) & 0xff)) &&
-            (p[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_ctrl(s, SSL_CTRL_CHECK_PROTO_VERSION, 0, NULL)) {
-                SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,
-                       SSL_R_INAPPROPRIATE_FALLBACK);
-                if (s->s3)
-                    ssl3_send_alert(s, SSL3_AL_FATAL,
-                                    SSL_AD_INAPPROPRIATE_FALLBACK);
-                goto err;
-            }
-            p += n;
-            continue;
-        }
-
-        c = ssl_get_cipher_by_char(s, p);
-        p += n;
-        if (c != NULL) {
-            if (!sk_SSL_CIPHER_push(sk, c)) {
-                SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
-                goto err;
-            }
-        }
-    }
-
-    if (skp != NULL)
-        *skp = sk;
-    return (sk);
- err:
-    if ((skp == NULL) || (*skp == NULL))
-        sk_SSL_CIPHER_free(sk);
-    return (NULL);
-}
-
-#ifndef OPENSSL_NO_TLSEXT
 /** return a servername extension value if provided in Client Hello, or NULL.
  * So far, only host_name types are defined (RFC 3546).
  */
@@ -1667,7 +1478,7 @@ int SSL_select_next_proto(unsigned char **out, unsigned char *outlen,
     return status;
 }
 
-# ifndef OPENSSL_NO_NEXTPROTONEG
+#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
@@ -1728,7 +1539,7 @@ void SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx,
     ctx->next_proto_select_cb = cb;
     ctx->next_proto_select_cb_arg = arg;
 }
-# endif
+#endif
 
 /*
  * SSL_CTX_set_alpn_protos sets the ALPN protocol list on |ctx| to |protos|.
@@ -1738,9 +1549,7 @@ void SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx,
 int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos,
                             unsigned protos_len)
 {
-    if (ctx->alpn_client_proto_list)
-        OPENSSL_free(ctx->alpn_client_proto_list);
-
+    OPENSSL_free(ctx->alpn_client_proto_list);
     ctx->alpn_client_proto_list = OPENSSL_malloc(protos_len);
     if (!ctx->alpn_client_proto_list)
         return 1;
@@ -1758,9 +1567,7 @@ int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos,
 int SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos,
                         unsigned protos_len)
 {
-    if (ssl->alpn_client_proto_list)
-        OPENSSL_free(ssl->alpn_client_proto_list);
-
+    OPENSSL_free(ssl->alpn_client_proto_list);
     ssl->alpn_client_proto_list = OPENSSL_malloc(protos_len);
     if (!ssl->alpn_client_proto_list)
         return 1;
@@ -1805,7 +1612,6 @@ void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data,
         *len = ssl->s3->alpn_selected_len;
 }
 
-#endif                          /* !OPENSSL_NO_TLSEXT */
 
 int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen,
                                const char *label, size_t llen,
@@ -1875,11 +1681,11 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
         SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_X509_VERIFICATION_SETUP_PROBLEMS);
         goto err;
     }
-    ret = (SSL_CTX *)OPENSSL_malloc(sizeof(SSL_CTX));
+    ret = OPENSSL_malloc(sizeof(*ret));
     if (ret == NULL)
         goto err;
 
-    memset(ret, 0, sizeof(SSL_CTX));
+    memset(ret, 0, sizeof(*ret));
 
     ret->method = meth;
 
@@ -1897,7 +1703,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
     ret->get_session_cb = 0;
     ret->generate_session_id = 0;
 
-    memset((char *)&ret->stats, 0, sizeof(ret->stats));
+    memset(&ret->stats, 0, sizeof(ret->stats));
 
     ret->references = 1;
     ret->quiet_shutdown = 0;
@@ -1927,7 +1733,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
     if (ret->cert_store == NULL)
         goto err;
 
-    if(!ssl_create_cipher_list(ret->method,
+    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) {
@@ -1960,7 +1766,6 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
 
     ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH;
 
-#ifndef OPENSSL_NO_TLSEXT
     ret->tlsext_servername_callback = 0;
     ret->tlsext_servername_arg = NULL;
     /* Setup RFC4507 ticket keys */
@@ -1972,10 +1777,9 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
     ret->tlsext_status_cb = 0;
     ret->tlsext_status_arg = NULL;
 
-# ifndef OPENSSL_NO_NEXTPROTONEG
+#ifndef OPENSSL_NO_NEXTPROTONEG
     ret->next_protos_advertised_cb = 0;
     ret->next_proto_select_cb = 0;
-# endif
 #endif
 #ifndef OPENSSL_NO_PSK
     ret->psk_identity_hint = NULL;
@@ -1983,7 +1787,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
     ret->psk_server_callback = NULL;
 #endif
 #ifndef OPENSSL_NO_SRP
-    if(!SSL_CTX_SRP_CTX_init(ret))
+    if (!SSL_CTX_SRP_CTX_init(ret))
         goto err;
 #endif
 #ifndef OPENSSL_NO_ENGINE
@@ -2015,8 +1819,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
  err:
     SSLerr(SSL_F_SSL_CTX_NEW, ERR_R_MALLOC_FAILURE);
  err2:
-    if (ret != NULL)
-        SSL_CTX_free(ret);
+    SSL_CTX_free(ret);
     return (NULL);
 }
 
@@ -2040,8 +1843,7 @@ void SSL_CTX_free(SSL_CTX *a)
     }
 #endif
 
-    if (a->param)
-        X509_VERIFY_PARAM_free(a->param);
+    X509_VERIFY_PARAM_free(a->param);
 
     /*
      * Free internal session cache. However: the remove_cb() may reference
@@ -2056,32 +1858,19 @@ void SSL_CTX_free(SSL_CTX *a)
         SSL_CTX_flush_sessions(a, 0);
 
     CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data);
-
-    if (a->sessions != NULL)
-        lh_SSL_SESSION_free(a->sessions);
-
-    if (a->cert_store != NULL)
-        X509_STORE_free(a->cert_store);
-    if (a->cipher_list != NULL)
-        sk_SSL_CIPHER_free(a->cipher_list);
-    if (a->cipher_list_by_id != NULL)
-        sk_SSL_CIPHER_free(a->cipher_list_by_id);
-    if (a->cert != NULL)
-        ssl_cert_free(a->cert);
-    if (a->client_CA != NULL)
-        sk_X509_NAME_pop_free(a->client_CA, X509_NAME_free);
-    if (a->extra_certs != NULL)
-        sk_X509_pop_free(a->extra_certs, X509_free);
+    lh_SSL_SESSION_free(a->sessions);
+    X509_STORE_free(a->cert_store);
+    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
-    if (a->srtp_profiles)
-        sk_SRTP_PROTECTION_PROFILE_free(a->srtp_profiles);
+    sk_SRTP_PROTECTION_PROFILE_free(a->srtp_profiles);
 #endif
-
 #ifndef OPENSSL_NO_PSK
-    if (a->psk_identity_hint)
-        OPENSSL_free(a->psk_identity_hint);
+    OPENSSL_free(a->psk_identity_hint);
 #endif
 #ifndef OPENSSL_NO_SRP
     SSL_CTX_SRP_CTX_free(a);
@@ -2091,16 +1880,11 @@ void SSL_CTX_free(SSL_CTX *a)
         ENGINE_finish(a->client_cert_engine);
 #endif
 
-#ifndef OPENSSL_NO_TLSEXT
-# ifndef OPENSSL_NO_EC
-    if (a->tlsext_ecpointformatlist)
-        OPENSSL_free(a->tlsext_ecpointformatlist);
-    if (a->tlsext_ellipticcurvelist)
-        OPENSSL_free(a->tlsext_ellipticcurvelist);
-# endif                         /* OPENSSL_NO_EC */
-    if (a->alpn_client_proto_list != NULL)
-        OPENSSL_free(a->alpn_client_proto_list);
+#ifndef OPENSSL_NO_EC
+    OPENSSL_free(a->tlsext_ecpointformatlist);
+    OPENSSL_free(a->tlsext_ellipticcurvelist);
 #endif
+    OPENSSL_free(a->alpn_client_proto_list);
 
     OPENSSL_free(a);
 }
@@ -2146,9 +1930,11 @@ 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_cert_masks(CERT *c, const SSL_CIPHER *cipher)
+void ssl_set_masks(SSL *s, const SSL_CIPHER *cipher)
 {
     CERT_PKEY *cpk;
+    CERT *c = s->cert;
+    int *pvalid = s->s3->tmp.valid_flags;
     int rsa_enc, rsa_tmp, rsa_sign, dh_tmp, dh_rsa, dh_dsa, dsa_sign;
     int rsa_enc_export, dh_rsa_export, dh_dsa_export;
     int rsa_tmp_export, dh_tmp_export, kl;
@@ -2185,22 +1971,21 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
     have_ecdh_tmp = (c->ecdh_tmp || c->ecdh_tmp_cb || c->ecdh_tmp_auto);
 #endif
     cpk = &(c->pkeys[SSL_PKEY_RSA_ENC]);
-    rsa_enc = cpk->valid_flags & CERT_PKEY_VALID;
+    rsa_enc = pvalid[SSL_PKEY_RSA_ENC] & CERT_PKEY_VALID;
     rsa_enc_export = (rsa_enc && EVP_PKEY_size(cpk->privatekey) * 8 <= kl);
     cpk = &(c->pkeys[SSL_PKEY_RSA_SIGN]);
-    rsa_sign = cpk->valid_flags & CERT_PKEY_SIGN;
+    rsa_sign = pvalid[SSL_PKEY_RSA_SIGN] & CERT_PKEY_SIGN;
     cpk = &(c->pkeys[SSL_PKEY_DSA_SIGN]);
-    dsa_sign = cpk->valid_flags & CERT_PKEY_SIGN;
+    dsa_sign = pvalid[SSL_PKEY_DSA_SIGN] & CERT_PKEY_SIGN;
     cpk = &(c->pkeys[SSL_PKEY_DH_RSA]);
-    dh_rsa = cpk->valid_flags & CERT_PKEY_VALID;
+    dh_rsa = pvalid[SSL_PKEY_DH_RSA] & CERT_PKEY_VALID;
     dh_rsa_export = (dh_rsa && EVP_PKEY_size(cpk->privatekey) * 8 <= kl);
     cpk = &(c->pkeys[SSL_PKEY_DH_DSA]);
-/* FIX THIS EAY EAY EAY */
-    dh_dsa = cpk->valid_flags & CERT_PKEY_VALID;
+    dh_dsa = pvalid[SSL_PKEY_DH_DSA] & CERT_PKEY_VALID;
     dh_dsa_export = (dh_dsa && EVP_PKEY_size(cpk->privatekey) * 8 <= kl);
     cpk = &(c->pkeys[SSL_PKEY_ECC]);
 #ifndef OPENSSL_NO_EC
-    have_ecc_cert = cpk->valid_flags & CERT_PKEY_VALID;
+    have_ecc_cert = pvalid[SSL_PKEY_ECC] & CERT_PKEY_VALID;
 #endif
     mask_k = 0;
     mask_a = 0;
@@ -2246,7 +2031,7 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
     if (dh_dsa_export)
         emask_k |= SSL_kDHd;
 
-    if (emask_k & (SSL_kDHr | SSL_kDHd))
+    if (mask_k & (SSL_kDHr | SSL_kDHd))
         mask_a |= SSL_aDH;
 
     if (rsa_enc || rsa_sign) {
@@ -2262,13 +2047,6 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
     mask_a |= SSL_aNULL;
     emask_a |= SSL_aNULL;
 
-#ifndef OPENSSL_NO_KRB5
-    mask_k |= SSL_kKRB5;
-    mask_a |= SSL_aKRB5;
-    emask_k |= SSL_kKRB5;
-    emask_a |= SSL_aKRB5;
-#endif
-
     /*
      * An ECC certificate may be usable for ECDH and/or ECDSA cipher suites
      * depending on the key usage extension.
@@ -2283,7 +2061,7 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
             (x->ex_kusage & X509v3_KU_KEY_AGREEMENT) : 1;
         ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE) ?
             (x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE) : 1;
-        if (!(cpk->valid_flags & CERT_PKEY_SIGN))
+        if (!(pvalid[SSL_PKEY_ECC] & CERT_PKEY_SIGN))
             ecdsa_ok = 0;
         ecc_pkey = X509_get_pubkey(x);
         ecc_pkey_size = (ecc_pkey != NULL) ? EVP_PKEY_bits(ecc_pkey) : 0;
@@ -2333,11 +2111,10 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
     emask_a |= SSL_aPSK;
 #endif
 
-    c->mask_k = mask_k;
-    c->mask_a = mask_a;
-    c->export_mask_k = emask_k;
-    c->export_mask_a = emask_a;
-    c->valid = 1;
+    s->s3->tmp.mask_k = mask_k;
+    s->s3->tmp.mask_a = mask_a;
+    s->s3->tmp.export_mask_k = emask_k;
+    s->s3->tmp.export_mask_a = emask_a;
 }
 
 /* This handy macro borrowed from crypto/x509v3/v3_purp.c */
@@ -2424,7 +2201,7 @@ static int ssl_get_server_cert_index(const SSL *s)
     return idx;
 }
 
-CERT_PKEY *ssl_get_server_send_pkey(const SSL *s)
+CERT_PKEY *ssl_get_server_send_pkey(SSL *s)
 {
     CERT *c;
     int i;
@@ -2432,7 +2209,7 @@ CERT_PKEY *ssl_get_server_send_pkey(const SSL *s)
     c = s->cert;
     if (!s->s3 || !s->s3->tmp.new_cipher)
         return NULL;
-    ssl_set_cert_masks(c, s->s3->tmp.new_cipher);
+    ssl_set_masks(s, s->s3->tmp.new_cipher);
 
 #ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
     /*
@@ -2489,11 +2266,10 @@ EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *cipher,
         return (NULL);
     }
     if (pmd)
-        *pmd = c->pkeys[idx].digest;
+        *pmd = s->s3->tmp.md[idx];
     return c->pkeys[idx].privatekey;
 }
 
-#ifndef OPENSSL_NO_TLSEXT
 int ssl_get_server_cert_serverinfo(SSL *s, const unsigned char **serverinfo,
                                    size_t *serverinfo_length)
 {
@@ -2513,7 +2289,6 @@ int ssl_get_server_cert_serverinfo(SSL *s, const unsigned char **serverinfo,
     *serverinfo_length = c->pkeys[i].serverinfo_length;
     return 1;
 }
-#endif
 
 void ssl_update_cache(SSL *s, int mode)
 {
@@ -2765,7 +2540,7 @@ SSL *SSL_dup(SSL *s)
 
     if (s->session != NULL) {
         /* This copies session-id, SSL_METHOD, sid_ctx, and 'cert' */
-        if(!SSL_copy_session_id(ret, s))
+        if (!SSL_copy_session_id(ret, s))
             goto err;
     } else {
         /*
@@ -2780,15 +2555,13 @@ SSL *SSL_dup(SSL *s)
         ret->method->ssl_new(ret);
 
         if (s->cert != NULL) {
-            if (ret->cert != NULL) {
-                ssl_cert_free(ret->cert);
-            }
+            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))
+        if (!SSL_set_session_id_context(ret, s->sid_ctx, s->sid_ctx_length))
             goto err;
     }
 
@@ -2832,7 +2605,7 @@ SSL *SSL_dup(SSL *s)
     ret->shutdown = s->shutdown;
     ret->state = s->state;      /* SSL_dup does not really work at any state,
                                  * though */
-    ret->rstate = s->rstate;
+    RECORD_LAYER_dup(&ret->rlayer, &s->rlayer);
     ret->init_num = 0;          /* would have to copy ret->init_buf,
                                  * ret->init_msg, ret->init_num,
                                  * ret->init_off */
@@ -2863,14 +2636,11 @@ SSL *SSL_dup(SSL *s)
             }
         }
     }
+    return ret;
 
-    if (0) {
  err:
-        if (ret != NULL)
-            SSL_free(ret);
-        ret = NULL;
-    }
-    return (ret);
+    SSL_free(ret);
+    return NULL;
 }
 
 void ssl_clear_cipher_ctx(SSL *s)
@@ -2886,14 +2656,10 @@ void ssl_clear_cipher_ctx(SSL *s)
         s->enc_write_ctx = NULL;
     }
 #ifndef OPENSSL_NO_COMP
-    if (s->expand != NULL) {
-        COMP_CTX_free(s->expand);
-        s->expand = NULL;
-    }
-    if (s->compress != NULL) {
-        COMP_CTX_free(s->compress);
-        s->compress = NULL;
-    }
+    COMP_CTX_free(s->expand);
+    s->expand = NULL;
+    COMP_CTX_free(s->compress);
+    s->compress = NULL;
 #endif
 }
 
@@ -2936,32 +2702,23 @@ const SSL_CIPHER *SSL_get_current_cipher(const SSL *s)
     return (NULL);
 }
 
-#ifdef OPENSSL_NO_COMP
-const void *SSL_get_current_compression(SSL *s)
-{
-    return NULL;
-}
-
-const void *SSL_get_current_expansion(SSL *s)
-{
-    return NULL;
-}
-#else
-
 const COMP_METHOD *SSL_get_current_compression(SSL *s)
 {
-    if (s->compress != NULL)
-        return (s->compress->meth);
-    return (NULL);
+#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)
 {
-    if (s->expand != NULL)
-        return (s->expand->meth);
-    return (NULL);
-}
+#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, int push)
 {
@@ -2995,6 +2752,7 @@ int ssl_init_wbio_buffer(SSL *s, int push)
 
 void ssl_free_wbio_buffer(SSL *s)
 {
+    /* callers ensure s is never null */
     if (s->bbio == NULL)
         return;
 
@@ -3055,23 +2813,12 @@ SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx)
     CERT *new_cert;
     if (ssl->ctx == ctx)
         return ssl->ctx;
-#ifndef OPENSSL_NO_TLSEXT
     if (ctx == NULL)
         ctx = ssl->initial_ctx;
-#endif
     new_cert = ssl_cert_dup(ctx->cert);
     if (new_cert == NULL) {
         return NULL;
     }
-    /* Preserve any already negotiated parameters */
-    if (ssl->server) {
-        new_cert->peer_sigalgs = ssl->cert->peer_sigalgs;
-        new_cert->peer_sigalgslen = ssl->cert->peer_sigalgslen;
-        ssl->cert->peer_sigalgs = NULL;
-        new_cert->ciphers_raw = ssl->cert->ciphers_raw;
-        new_cert->ciphers_rawlen = ssl->cert->ciphers_rawlen;
-        ssl->cert->ciphers_raw = NULL;
-    }
     ssl_cert_free(ssl->cert);
     ssl->cert = new_cert;
 
@@ -3095,8 +2842,7 @@ SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx)
     }
 
     CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX);
-    if (ssl->ctx != NULL)
-        SSL_CTX_free(ssl->ctx); /* decrement reference count */
+    SSL_CTX_free(ssl->ctx); /* decrement reference count */
     ssl->ctx = ctx;
 
     return (ssl->ctx);
@@ -3151,6 +2897,37 @@ long SSL_get_verify_result(const SSL *ssl)
     return (ssl->verify_result);
 }
 
+int SSL_get_client_random(const SSL *ssl, unsigned char *out, int 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);
+}
+
+int SSL_get_server_random(const SSL *ssl, unsigned char *out, int 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);
+}
+
+int SSL_SESSION_get_master_key(const SSL_SESSION *session,
+                               unsigned char *out, int outlen)
+{
+    if (outlen < 0)
+        return session->master_key_length;
+    if (outlen > session->master_key_length)
+        outlen = session->master_key_length;
+    memcpy(out, session->master_key, outlen);
+    return (outlen);
+}
+
 int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
                          CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
 {
@@ -3198,8 +2975,7 @@ X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx)
 
 void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *store)
 {
-    if (ctx->cert_store != NULL)
-        X509_STORE_free(ctx->cert_store);
+    X509_STORE_free(ctx->cert_store);
     ctx->cert_store = store;
 }
 
@@ -3292,8 +3068,7 @@ int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint)
                SSL_R_DATA_LENGTH_TOO_LONG);
         return 0;
     }
-    if (ctx->psk_identity_hint != NULL)
-        OPENSSL_free(ctx->psk_identity_hint);
+    OPENSSL_free(ctx->psk_identity_hint);
     if (identity_hint != NULL) {
         ctx->psk_identity_hint = BUF_strdup(identity_hint);
         if (ctx->psk_identity_hint == NULL)
@@ -3315,8 +3090,7 @@ int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint)
         SSLerr(SSL_F_SSL_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG);
         return 0;
     }
-    if (s->session->psk_identity_hint != NULL)
-        OPENSSL_free(s->session->psk_identity_hint);
+    OPENSSL_free(s->session->psk_identity_hint);
     if (identity_hint != NULL) {
         s->session->psk_identity_hint = BUF_strdup(identity_hint);
         if (s->session->psk_identity_hint == NULL)