Remove useless code
[openssl.git] / ssl / s3_clnt.c
index 0195d099586815e52eac586c18778342eda5c989..8a89b4268cecd3cfad0d14a90b68b21b5f6394f7 100644 (file)
@@ -167,9 +167,7 @@ static int ssl_set_version(SSL *s);
 static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b);
 static int ssl3_check_change(SSL *s);
 static int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk,
-                                    unsigned char *p,
-                                    int (*put_cb) (const SSL_CIPHER *,
-                                                 unsigned char *));
+                                    unsigned char *p);
 
 
 int ssl3_connect(SSL *s)
@@ -862,7 +860,7 @@ int ssl3_client_hello(SSL *s)
         }
 
         /* Ciphers supported */
-        i = ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &(p[2]), 0);
+        i = ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &(p[2]));
         if (i == 0) {
             SSLerr(SSL_F_SSL3_CLIENT_HELLO, SSL_R_NO_CIPHERS_AVAILABLE);
             goto err;
@@ -930,10 +928,11 @@ int ssl3_get_server_hello(SSL *s)
 {
     STACK_OF(SSL_CIPHER) *sk;
     const SSL_CIPHER *c;
-    PACKET pkt;
-    unsigned char *session_id, *cipherchars;
+    PACKET pkt, session_id;
+    size_t session_id_len;
+    unsigned char *cipherchars;
     int i, al = SSL_AD_INTERNAL_ERROR, ok;
-    unsigned int j, ciphercharlen;
+    unsigned int compression;
     long n;
 #ifndef OPENSSL_NO_COMP
     SSL_COMP *comp;
@@ -1077,16 +1076,26 @@ int ssl3_get_server_hello(SSL *s)
 
     s->hit = 0;
 
-    /* get the session-id length */
-    if (!PACKET_get_1(&pkt, &j)
-            || (j > sizeof s->session->session_id)
-            || (j > SSL3_SESSION_ID_SIZE)) {
+    /* Get the session-id. */
+    if (!PACKET_get_length_prefixed_1(&pkt, &session_id)) {
+        al = SSL_AD_DECODE_ERROR;
+        SSLerr(SSL_F_SSL3_GET_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_SSL3_GET_SERVER_HELLO, SSL_R_SSL3_SESSION_ID_TOO_LONG);
         goto f_err;
     }
 
-    ciphercharlen = ssl_put_cipher_by_char(s, NULL, NULL);
+    if (!PACKET_get_bytes(&pkt, &cipherchars, TLS_CIPHER_LEN)) {
+        SSLerr(SSL_F_SSL3_GET_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.
@@ -1102,14 +1111,6 @@ int ssl3_get_server_hello(SSL *s)
     if (s->version >= TLS1_VERSION && s->tls_session_secret_cb &&
         s->session->tlsext_tick) {
         SSL_CIPHER *pref_cipher = NULL;
-        size_t bookm;
-        if (!PACKET_get_bookmark(&pkt, &bookm)
-                || !PACKET_forward(&pkt, j)
-                || !PACKET_get_bytes(&pkt, &cipherchars, ciphercharlen)) {
-            SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
-            al = SSL_AD_DECODE_ERROR;
-            goto f_err;
-        }
         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,
@@ -1122,22 +1123,11 @@ int ssl3_get_server_hello(SSL *s)
             al = SSL_AD_INTERNAL_ERROR;
             goto f_err;
         }
-        if (!PACKET_goto_bookmark(&pkt, bookm)) {
-            SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
-            al = SSL_AD_INTERNAL_ERROR;
-            goto f_err;
-        }
-    }
-
-    /* Get the session id */
-    if (!PACKET_get_bytes(&pkt, &session_id, j)) {
-        SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
-        al = SSL_AD_DECODE_ERROR;
-        goto f_err;
     }
 
-    if (j != 0 && j == s->session->session_id_length
-        && memcmp(session_id, s->session->session_id, j) == 0) {
+    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 */
@@ -1160,15 +1150,13 @@ int ssl3_get_server_hello(SSL *s)
                 goto f_err;
             }
         }
-        s->session->session_id_length = j;
-        memcpy(s->session->session_id, session_id, j); /* j could be 0 */
-    }
 
-    if (!PACKET_get_bytes(&pkt, &cipherchars, ciphercharlen)) {
-        SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
-        al = SSL_AD_DECODE_ERROR;
-        goto f_err;
+        s->session->session_id_length = session_id_len;
+        /* session_id_len could be 0 */
+        memcpy(s->session->session_id, PACKET_data(&session_id),
+               session_id_len);
     }
+
     c = ssl_get_cipher_by_char(s, cipherchars);
     if (c == NULL) {
         /* unknown cipher */
@@ -1222,13 +1210,13 @@ int ssl3_get_server_hello(SSL *s)
         goto f_err;
     /* lets get the compression algorithm */
     /* COMPRESSION */
-    if (!PACKET_get_1(&pkt, &j)) {
+    if (!PACKET_get_1(&pkt, &compression)) {
         SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
         al = SSL_AD_DECODE_ERROR;
         goto f_err;
     }
 #ifdef OPENSSL_NO_COMP
-    if (j != 0) {
+    if (compression != 0) {
         al = SSL_AD_ILLEGAL_PARAMETER;
         SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,
                SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
@@ -1243,22 +1231,23 @@ int ssl3_get_server_hello(SSL *s)
         goto f_err;
     }
 #else
-    if (s->hit && j != s->session->compress_meth) {
+    if (s->hit && compression != s->session->compress_meth) {
         al = SSL_AD_ILLEGAL_PARAMETER;
         SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,
                SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED);
         goto f_err;
     }
-    if (j == 0)
+    if (compression == 0)
         comp = NULL;
     else if (!ssl_allow_compression(s)) {
         al = SSL_AD_ILLEGAL_PARAMETER;
         SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_COMPRESSION_DISABLED);
         goto f_err;
-    } else
-        comp = ssl3_comp_find(s->ctx->comp_methods, j);
+    } else {
+        comp = ssl3_comp_find(s->ctx->comp_methods, compression);
+    }
 
-    if ((j != 0) && (comp == NULL)) {
+    if (compression != 0 && comp == NULL) {
         al = SSL_AD_ILLEGAL_PARAMETER;
         SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,
                SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
@@ -1445,7 +1434,6 @@ int ssl3_get_key_exchange(SSL *s)
 #endif
     EVP_MD_CTX md_ctx;
     int al, j, verify_ret, ok;
-    unsigned int i;
     long n, alg_k, alg_a;
     EVP_PKEY *pkey = NULL;
     const EVP_MD *md = NULL;
@@ -1460,11 +1448,8 @@ int ssl3_get_key_exchange(SSL *s)
     BN_CTX *bn_ctx = NULL;
     EC_POINT *srvr_ecpoint = NULL;
     int curve_nid = 0;
-    unsigned int encoded_pt_len = 0;
 #endif
-    PACKET pkt;
-    unsigned char *data, *param;
-    size_t startparam, endparam;
+    PACKET pkt, save_param_start, signature;
 
     EVP_MD_CTX_init(&md_ctx);
 
@@ -1496,12 +1481,12 @@ int ssl3_get_key_exchange(SSL *s)
         return (1);
     }
 
-    if (!PACKET_buf_init(&pkt, s->init_msg, n)
-            || !PACKET_get_bookmark(&pkt, &startparam)) {
+    if (!PACKET_buf_init(&pkt, s->init_msg, n)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
             al = SSL_AD_INTERNAL_ERROR;
             goto f_err;
     }
+    save_param_start = pkt;
 
 #ifndef OPENSSL_NO_RSA
     RSA_free(s->s3->peer_rsa_tmp);
@@ -1523,9 +1508,9 @@ int ssl3_get_key_exchange(SSL *s)
 #ifndef OPENSSL_NO_PSK
     /* PSK ciphersuites are preceded by an identity hint */
     if (alg_k & SSL_PSK) {
-
-        if (!PACKET_get_net_2(&pkt, &i)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
+        PACKET psk_identity_hint;
+        if (!PACKET_get_length_prefixed_2(&pkt, &psk_identity_hint)) {
+            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
             goto f_err;
         }
 
@@ -1535,33 +1520,16 @@ int ssl3_get_key_exchange(SSL *s)
          * a PSK identity hint can be as long as the maximum length of a PSK
          * identity.
          */
-        if (i > PSK_MAX_IDENTITY_LEN) {
+        if (PACKET_remaining(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN) {
             al = SSL_AD_HANDSHAKE_FAILURE;
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG);
             goto f_err;
         }
-        if (PACKET_remaining(&pkt) < i) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
-                   SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH);
-            goto f_err;
-        }
 
-        OPENSSL_free(s->session->psk_identity_hint);
-        if (i != 0) {
-            unsigned char *hint = NULL;
-
-            if (!PACKET_get_bytes(&pkt, &hint, i)) {
-                SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
-                goto f_err;
-            }
-            s->session->psk_identity_hint = BUF_strndup((char *)hint, i);
-            if (s->session->psk_identity_hint == NULL) {
-                al = SSL_AD_HANDSHAKE_FAILURE;
-                SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
-                goto f_err;
-            }
-        } else {
-            s->session->psk_identity_hint = NULL;
+        if (!PACKET_strndup(&psk_identity_hint,
+                            &s->session->psk_identity_hint)) {
+            al = SSL_AD_INTERNAL_ERROR;
+            goto f_err;
         }
     }
 
@@ -1571,62 +1539,27 @@ int ssl3_get_key_exchange(SSL *s)
 #endif                          /* !OPENSSL_NO_PSK */
 #ifndef OPENSSL_NO_SRP
     if (alg_k & SSL_kSRP) {
-        if (!PACKET_get_net_2(&pkt, &i)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
-            goto f_err;
-        }
-
-        if (!PACKET_get_bytes(&pkt, &data, i)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SRP_N_LENGTH);
-            goto f_err;
-        }
-
-        if ((s->srp_ctx.N = BN_bin2bn(data, i, NULL)) == NULL) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
-            goto err;
-        }
-
-        if (!PACKET_get_net_2(&pkt, &i)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
-            goto f_err;
-        }
-
-        if (!PACKET_get_bytes(&pkt, &data, i)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SRP_G_LENGTH);
-            goto f_err;
-        }
-
-        if ((s->srp_ctx.g = BN_bin2bn(data, i, NULL)) == NULL) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
-            goto err;
-        }
-
-        if (!PACKET_get_1(&pkt, &i)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
-            goto f_err;
-        }
-
-        if (!PACKET_get_bytes(&pkt, &data, i)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SRP_S_LENGTH);
-            goto f_err;
-        }
-
-        if ((s->srp_ctx.s = BN_bin2bn(data, i, NULL)) == NULL) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
-            goto err;
-        }
-
-        if (!PACKET_get_net_2(&pkt, &i)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
+        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)) {
+            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
             goto f_err;
         }
 
-        if (!PACKET_get_bytes(&pkt, &data, i)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SRP_B_LENGTH);
-            goto f_err;
-        }
-
-        if ((s->srp_ctx.B = BN_bin2bn(data, i, NULL)) == NULL) {
+        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) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
             goto err;
         }
@@ -1643,43 +1576,29 @@ int ssl3_get_key_exchange(SSL *s)
 #endif                          /* !OPENSSL_NO_SRP */
 #ifndef OPENSSL_NO_RSA
     if (alg_k & SSL_kRSA) {
+        PACKET mod, exp;
         /* Temporary RSA keys only allowed in export ciphersuites */
         if (!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)) {
             al = SSL_AD_UNEXPECTED_MESSAGE;
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE);
             goto f_err;
         }
-        if ((rsa = RSA_new()) == NULL) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
-            goto err;
-        }
-
-        if (!PACKET_get_net_2(&pkt, &i)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
-            goto f_err;
-        }
 
-        if (!PACKET_get_bytes(&pkt, &data, i)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_RSA_MODULUS_LENGTH);
+        if (!PACKET_get_length_prefixed_2(&pkt, &mod)
+            || !PACKET_get_length_prefixed_2(&pkt, &exp)) {
+            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
             goto f_err;
         }
 
-        if ((rsa->n = BN_bin2bn(data, i, rsa->n)) == NULL) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
+        if ((rsa = RSA_new()) == NULL) {
+            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
             goto err;
         }
 
-        if (!PACKET_get_net_2(&pkt, &i)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
-            goto f_err;
-        }
-
-        if (!PACKET_get_bytes(&pkt, &data, i)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_RSA_E_LENGTH);
-            goto f_err;
-        }
-
-        if ((rsa->e = BN_bin2bn(data, i, rsa->e)) == NULL) {
+        if ((rsa->n = BN_bin2bn(PACKET_data(&mod), PACKET_remaining(&mod),
+                                rsa->n)) == NULL
+            || (rsa->e = BN_bin2bn(PACKET_data(&exp), PACKET_remaining(&exp),
+                                   rsa->e)) == NULL) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
             goto err;
         }
@@ -1706,68 +1625,33 @@ int ssl3_get_key_exchange(SSL *s)
 #endif
 #ifndef OPENSSL_NO_DH
     else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
-        if ((dh = DH_new()) == NULL) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_DH_LIB);
-            goto err;
-        }
-
-        if (!PACKET_get_net_2(&pkt, &i)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
-            goto f_err;
-        }
+        PACKET prime, generator, pub_key;
 
-        if (!PACKET_get_bytes(&pkt, &data, i)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_P_LENGTH);
+        if (!PACKET_get_length_prefixed_2(&pkt, &prime)
+            || !PACKET_get_length_prefixed_2(&pkt, &generator)
+            || !PACKET_get_length_prefixed_2(&pkt, &pub_key)) {
+            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
             goto f_err;
         }
 
-        if ((dh->p = BN_bin2bn(data, i, NULL)) == NULL) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
-            goto err;
-        }
-
-        if (BN_is_zero(dh->p)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_P_VALUE);
-            goto f_err;
-        }
-
-        if (!PACKET_get_net_2(&pkt, &i)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
-            goto f_err;
-        }
-
-        if (!PACKET_get_bytes(&pkt, &data, i)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_G_LENGTH);
-            goto f_err;
-        }
-
-        if ((dh->g = BN_bin2bn(data, i, NULL)) == NULL) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
+        if ((dh = DH_new()) == NULL) {
+            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_DH_LIB);
             goto err;
         }
 
-        if (BN_is_zero(dh->g)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_G_VALUE);
-            goto f_err;
-        }
-
-        if (!PACKET_get_net_2(&pkt, &i)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
-            goto f_err;
-        }
-
-        if (!PACKET_get_bytes(&pkt, &data, i)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_PUB_KEY_LENGTH);
-            goto f_err;
-        }
-
-        if ((dh->pub_key = BN_bin2bn(data, i, NULL)) == NULL) {
+        if ((dh->p = BN_bin2bn(PACKET_data(&prime),
+                               PACKET_remaining(&prime), NULL)) == NULL
+            || (dh->g = BN_bin2bn(PACKET_data(&generator),
+                                  PACKET_remaining(&generator), NULL)) == NULL
+            || (dh->pub_key =
+                BN_bin2bn(PACKET_data(&pub_key),
+                          PACKET_remaining(&pub_key), NULL)) == NULL) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
             goto err;
         }
 
-        if (BN_is_zero(dh->pub_key)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_PUB_KEY_VALUE);
+        if (BN_is_zero(dh->p) || BN_is_zero(dh->g) || BN_is_zero(dh->pub_key)) {
+            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_VALUE);
             goto f_err;
         }
 
@@ -1789,6 +1673,8 @@ int ssl3_get_key_exchange(SSL *s)
     else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
         EC_GROUP *ngroup;
         const EC_GROUP *group;
+        PACKET encoded_pt;
+        unsigned char *ecparams;
 
         if ((ecdh = EC_KEY_new()) == NULL) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
@@ -1797,15 +1683,10 @@ int ssl3_get_key_exchange(SSL *s)
 
         /*
          * Extract elliptic curve parameters and the server's ephemeral ECDH
-         * public key. Keep accumulating lengths of various components in
-         * param_len and make sure it never exceeds n.
-         */
-
-        /*
-         * XXX: For now we only support named (not generic) curves and the
+         * 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, &data, 3)) {
+        if (!PACKET_get_bytes(&pkt, &ecparams, 3)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
             goto f_err;
         }
@@ -1813,12 +1694,12 @@ int ssl3_get_key_exchange(SSL *s)
          * Check curve is one of our preferences, if not server has sent an
          * invalid curve. ECParameters is 3 bytes.
          */
-        if (!tls1_check_curve(s, data, 3)) {
+        if (!tls1_check_curve(s, ecparams, 3)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_WRONG_CURVE);
             goto f_err;
         }
 
-        if ((curve_nid = tls1_ec_curve_id2nid(*(data + 2))) == 0) {
+        if ((curve_nid = tls1_ec_curve_id2nid(*(ecparams + 2))) == 0) {
             al = SSL_AD_INTERNAL_ERROR;
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
                    SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
@@ -1853,14 +1734,13 @@ int ssl3_get_key_exchange(SSL *s)
             goto err;
         }
 
-        if (!PACKET_get_1(&pkt, &encoded_pt_len)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
+        if (!PACKET_get_length_prefixed_1(&pkt, &encoded_pt)) {
+            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
             goto f_err;
         }
 
-        if (!PACKET_get_bytes(&pkt, &data, encoded_pt_len) ||
-            (EC_POINT_oct2point(group, srvr_ecpoint,
-                                data, encoded_pt_len, bn_ctx) == 0)) {
+        if (EC_POINT_oct2point(group, srvr_ecpoint, PACKET_data(&encoded_pt),
+                               PACKET_remaining(&encoded_pt), bn_ctx) == 0) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_ECPOINT);
             goto f_err;
         }
@@ -1894,20 +1774,29 @@ int ssl3_get_key_exchange(SSL *s)
     }
 #endif                          /* !OPENSSL_NO_EC */
 
-    if (!PACKET_get_bookmark(&pkt, &endparam)) {
-        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
-        goto f_err;
-    }
-
     /* if it was signed, check the signature */
     if (pkey != NULL) {
+        PACKET params;
+        /*
+         * |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_SSL3_GET_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+            goto f_err;
+        }
+
         if (SSL_USE_SIGALGS(s)) {
+            unsigned char *sigalgs;
             int rv;
-            if (!PACKET_get_bytes(&pkt, &data, 2)) {
+            if (!PACKET_get_bytes(&pkt, &sigalgs, 2)) {
                 SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
                 goto f_err;
             }
-            rv = tls12_check_peer_sigalg(&md, s, data, pkey);
+            rv = tls12_check_peer_sigalg(&md, s, sigalgs, pkey);
             if (rv == -1)
                 goto err;
             else if (rv == 0) {
@@ -1916,11 +1805,13 @@ int ssl3_get_key_exchange(SSL *s)
 #ifdef SSL_DEBUG
             fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
 #endif
-        } else
+        } else {
             md = EVP_sha1();
+        }
 
-        if (!PACKET_get_net_2(&pkt, &i)) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
+        if (!PACKET_get_length_prefixed_2(&pkt, &signature)
+            || PACKET_remaining(&pkt) != 0) {
+            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
             goto f_err;
         }
         j = EVP_PKEY_size(pkey);
@@ -1932,19 +1823,11 @@ int ssl3_get_key_exchange(SSL *s)
         /*
          * Check signature length
          */
-        if (i > (unsigned int)j
-                || !PACKET_get_bytes(&pkt, &data, i)
-                || PACKET_remaining(&pkt) != 0) {
+        if (PACKET_remaining(&signature) > (size_t)j) {
             /* wrong packet length */
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_WRONG_SIGNATURE_LENGTH);
             goto f_err;
         }
-        if (!PACKET_goto_bookmark(&pkt, startparam)
-                || !PACKET_get_bytes(&pkt, &param, endparam - startparam)) {
-            al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
-            goto f_err;
-        }
 #ifndef OPENSSL_NO_RSA
         if (pkey->type == EVP_PKEY_RSA && !SSL_USE_SIGALGS(s)) {
             int num;
@@ -1960,13 +1843,15 @@ int ssl3_get_key_exchange(SSL *s)
                                  SSL3_RANDOM_SIZE);
                 EVP_DigestUpdate(&md_ctx, &(s->s3->server_random[0]),
                                  SSL3_RANDOM_SIZE);
-                EVP_DigestUpdate(&md_ctx, param, endparam - startparam);
+                EVP_DigestUpdate(&md_ctx, PACKET_data(&params),
+                                 PACKET_remaining(&params));
                 EVP_DigestFinal_ex(&md_ctx, q, &size);
                 q += size;
                 j += size;
             }
             verify_ret =
-                RSA_verify(NID_md5_sha1, md_buf, j, data, i, pkey->pkey.rsa);
+                RSA_verify(NID_md5_sha1, md_buf, j, PACKET_data(&signature),
+                           PACKET_remaining(&signature), pkey->pkey.rsa);
             if (verify_ret < 0) {
                 al = SSL_AD_DECRYPT_ERROR;
                 SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_RSA_DECRYPT);
@@ -1986,8 +1871,10 @@ int ssl3_get_key_exchange(SSL *s)
                              SSL3_RANDOM_SIZE);
             EVP_VerifyUpdate(&md_ctx, &(s->s3->server_random[0]),
                              SSL3_RANDOM_SIZE);
-            EVP_VerifyUpdate(&md_ctx, param, endparam - startparam);
-            if (EVP_VerifyFinal(&md_ctx, data, (int)i, pkey) <= 0) {
+            EVP_VerifyUpdate(&md_ctx, PACKET_data(&params),
+                             PACKET_remaining(&params));
+            if (EVP_VerifyFinal(&md_ctx, PACKET_data(&signature),
+                                PACKET_remaining(&signature), pkey) <= 0) {
                 /* bad signature */
                 al = SSL_AD_DECRYPT_ERROR;
                 SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SIGNATURE);
@@ -2202,6 +2089,7 @@ int ssl3_get_new_session_ticket(SSL *s)
 {
     int ok, al, ret = 0;
     unsigned int ticklen;
+    unsigned long ticket_lifetime_hint;
     long n;
     PACKET pkt;
 
@@ -2219,6 +2107,18 @@ int ssl3_get_new_session_ticket(SSL *s)
         goto f_err;
     }
 
+    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_SSL3_GET_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 1;
+
     if (s->session->session_id_length > 0) {
         int i = s->session_ctx->session_cache_mode;
         SSL_SESSION *new_sess;
@@ -2250,15 +2150,9 @@ int ssl3_get_new_session_ticket(SSL *s)
         s->session = new_sess;
     }
 
-    if (!PACKET_get_net_4(&pkt, &s->session->tlsext_tick_lifetime_hint)
-            || !PACKET_get_net_2(&pkt, &ticklen)
-            || PACKET_remaining(&pkt) != ticklen) {
-        al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, SSL_R_LENGTH_MISMATCH);
-        goto f_err;
-    }
     OPENSSL_free(s->session->tlsext_tick);
     s->session->tlsext_ticklen = 0;
+
     s->session->tlsext_tick = OPENSSL_malloc(ticklen);
     if (!s->session->tlsext_tick) {
         SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
@@ -2269,6 +2163,8 @@ int ssl3_get_new_session_ticket(SSL *s)
         SSLerr(SSL_F_SSL3_GET_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
@@ -2515,6 +2411,7 @@ int ssl3_send_client_key_exchange(SSL *s)
                     || (pkey->pkey.rsa == NULL)) {
                     SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
                            ERR_R_INTERNAL_ERROR);
+                    EVP_PKEY_free(pkey);
                     goto err;
                 }
                 rsa = pkey->pkey.rsa;
@@ -3205,7 +3102,6 @@ int ssl3_send_client_certificate(SSL *s)
          * If we get an error, we need to ssl->rwstate=SSL_X509_LOOKUP;
          * return(-1); We then get retied later
          */
-        i = 0;
         i = ssl_do_client_cert_cb(s, &x509, &pkey);
         if (i < 0) {
             s->rwstate = SSL_X509_LOOKUP;
@@ -3503,9 +3399,7 @@ int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)
 }
 
 int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk,
-                             unsigned char *p,
-                             int (*put_cb) (const SSL_CIPHER *,
-                                            unsigned char *))
+                             unsigned char *p)
 {
     int i, j = 0;
     SSL_CIPHER *c;
@@ -3517,8 +3411,6 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk,
     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);
@@ -3533,7 +3425,7 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk,
                 empty_reneg_info_scsv = 0;
         }
 #endif
-        j = put_cb(c, p);
+        j = s->method->put_cipher_by_char(c, p);
         p += j;
     }
     /*
@@ -3545,7 +3437,7 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk,
             static SSL_CIPHER scsv = {
                 0, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
             };
-            j = put_cb(&scsv, p);
+            j = s->method->put_cipher_by_char(&scsv, p);
             p += j;
 #ifdef OPENSSL_RI_DEBUG
             fprintf(stderr,
@@ -3556,7 +3448,7 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk,
             static SSL_CIPHER scsv = {
                 0, NULL, SSL3_CK_FALLBACK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
             };
-            j = put_cb(&scsv, p);
+            j = s->method->put_cipher_by_char(&scsv, p);
             p += j;
         }
     }