Remove ssl_put_cipher_by_char
[openssl.git] / ssl / s3_srvr.c
index 2d15c63b6b7f5bc9ba6a66d58615c3e520233af7..f771bd9eee4acc8985dbaa8e949cc289ef67e3bd 100644 (file)
@@ -444,7 +444,7 @@ int ssl3_accept(SSL *s)
                  */
 #ifndef OPENSSL_NO_PSK
                 /* Only send SKE if we have identity hint for plain PSK */
-                || ((alg_k & (SSL_kPSK | SSL_kRSAPSK)) && s->ctx->psk_identity_hint)
+                || ((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
@@ -838,19 +838,16 @@ int ssl3_send_hello_request(SSL *s)
 int ssl3_get_client_hello(SSL *s)
 {
     int i, ok, al = SSL_AD_INTERNAL_ERROR, ret = -1;
-    unsigned int j, cipherlen, complen;
-    unsigned int cookie_len = 0;
+    unsigned int j, complen = 0;
     long n;
     unsigned long id;
     SSL_CIPHER *c;
 #ifndef OPENSSL_NO_COMP
-    unsigned char *q = NULL;
     SSL_COMP *comp = NULL;
 #endif
     STACK_OF(SSL_CIPHER) *ciphers = NULL;
     int protverr = 1;
-    PACKET pkt;
-    unsigned char *sess, *cdata;
+    PACKET pkt, cipher_suite, compression;
 
     if (s->state == SSL3_ST_SR_CLNT_HELLO_C && !s->first_packet)
         goto retry_cert;
@@ -1013,30 +1010,31 @@ int ssl3_get_client_hello(SSL *s)
          * Note, this is only for SSLv3+ using the backward compatible format.
          * Real SSLv2 is not supported, and is rejected above.
          */
-        unsigned int csl, sil, cl;
+        unsigned int cipher_len, session_id_len, challenge_len;
 
-        if (!PACKET_get_net_2(&pkt, &csl)
-                || !PACKET_get_net_2(&pkt, &sil)
-                || !PACKET_get_net_2(&pkt, &cl)) {
+        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_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH);
             al = SSL_AD_DECODE_ERROR;
             goto f_err;
         }
 
-        if (csl == 0) {
+        if (cipher_len == 0) {
             /* we need at least one cipher */
             al = SSL_AD_ILLEGAL_PARAMETER;
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_CIPHERS_SPECIFIED);
             goto f_err;
         }
 
-        if (!PACKET_get_bytes(&pkt, &cdata, csl)) {
+        if (!PACKET_get_sub_packet(&pkt, &cipher_suite, cipher_len)) {
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH);
             al = SSL_AD_DECODE_ERROR;
             goto f_err;
         }
 
-        if (ssl_bytes_to_cipher_list(s, cdata, csl, &(ciphers), 1) == NULL) {
+        if (ssl_bytes_to_cipher_list(s, PACKET_data(&cipher_suite),
+                                     cipher_len, &(ciphers), 1) == NULL) {
             goto err;
         }
 
@@ -1044,7 +1042,7 @@ int ssl3_get_client_hello(SSL *s)
          * Ignore any session id. We don't allow resumption in a backwards
          * compatible ClientHello
          */
-        if (!PACKET_forward(&pkt, sil)) {
+        if (!PACKET_forward(&pkt, session_id_len)) {
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH);
             al = SSL_AD_DECODE_ERROR;
             goto f_err;
@@ -1055,27 +1053,24 @@ int ssl3_get_client_hello(SSL *s)
             goto err;
 
         /* Load the client random */
-        i = (cl > SSL3_RANDOM_SIZE) ? SSL3_RANDOM_SIZE : cl;
+        i = challenge_len > SSL3_RANDOM_SIZE ? SSL3_RANDOM_SIZE : challenge_len;
         memset(s->s3->client_random, 0, SSL3_RANDOM_SIZE);
         if (!PACKET_peek_copy_bytes(&pkt,
                                     s->s3->client_random + SSL3_RANDOM_SIZE - i,
                                     i)
-                || !PACKET_forward(&pkt, cl)
+                || !PACKET_forward(&pkt, challenge_len)
                 || PACKET_remaining(&pkt) != 0) {
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH);
             al = SSL_AD_DECODE_ERROR;
             goto f_err;
         }
-
-        /* No compression, so set complen to 0 */
-        complen = 0;
     } else {
         /* If we get here we've got SSLv3+ in an SSLv3+ record */
-
+        PACKET session_id;
+        unsigned int cookie_len;
         /* load the client random and get the session-id */
         if (!PACKET_copy_bytes(&pkt, s->s3->client_random, SSL3_RANDOM_SIZE)
-                || !PACKET_get_1(&pkt, &j)
-                || !PACKET_get_bytes(&pkt, &sess, j)) {
+               || !PACKET_get_length_prefixed_1(&pkt, &session_id)) {
             al = SSL_AD_DECODE_ERROR;
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
             goto f_err;
@@ -1117,7 +1112,13 @@ int ssl3_get_client_hello(SSL *s)
             if (!ssl_get_new_session(s, 1))
                 goto err;
         } else {
-            i = ssl_get_prev_session(s, &pkt, sess, j);
+            /*
+             * TODO(openssl-team): ssl_get_prev_session passes a non-const
+             * 'unsigned char*' session id to a user callback. Grab a copy of
+             * the data?
+             */
+           i = ssl_get_prev_session(s, &pkt, PACKET_data(&session_id),
+                                    PACKET_remaining(&session_id));
             /*
              * Only resume if the session's version matches the negotiated
              * version.
@@ -1140,11 +1141,13 @@ int ssl3_get_client_hello(SSL *s)
         }
 
         if (SSL_IS_DTLS(s)) {
-            if (!PACKET_get_1(&pkt, &cookie_len)) {
+            PACKET cookie;
+            if (!PACKET_get_length_prefixed_1(&pkt, &cookie)) {
                 al = SSL_AD_DECODE_ERROR;
                 SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
                 goto f_err;
             }
+           cookie_len = PACKET_remaining(&cookie);
             /*
              * The ClientHello may contain a cookie even if the
              * HelloVerify message has not been sent--make sure that it
@@ -1161,10 +1164,13 @@ int ssl3_get_client_hello(SSL *s)
             if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)
                     && cookie_len > 0) {
                 /* Get cookie */
-                if (!PACKET_copy_bytes(&pkt, s->d1->rcvd_cookie,
-                                              cookie_len)) {
-                    al = SSL_AD_DECODE_ERROR;
-                    SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+                /*
+                 * TODO(openssl-team): rcvd_cookie appears unused outside this
+                 * function. Remove the field?
+                 */
+                if (!PACKET_copy_bytes(&cookie, s->d1->rcvd_cookie, cookie_len)) {
+                    al = SSL_AD_INTERNAL_ERROR;
+                    SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
                     goto f_err;
                 }
 
@@ -1187,15 +1193,7 @@ int ssl3_get_client_hello(SSL *s)
                 }
                 /* Set to -2 so if successful we return 2 */
                 ret = -2;
-            } else {
-                /* Skip over cookie */
-                if (!PACKET_forward(&pkt, cookie_len)) {
-                    al = SSL_AD_DECODE_ERROR;
-                    SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
-                    goto f_err;
-                }
             }
-
             if (s->method->version == DTLS_ANY_VERSION) {
                 /* Select version to use */
                 if (s->client_version <= DTLS1_2_VERSION &&
@@ -1223,26 +1221,21 @@ int ssl3_get_client_hello(SSL *s)
             }
         }
 
-        if (!PACKET_get_net_2(&pkt, &cipherlen)) {
+        if (!PACKET_get_length_prefixed_2(&pkt, &cipher_suite)) {
             al = SSL_AD_DECODE_ERROR;
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
             goto f_err;
         }
 
-        if (cipherlen == 0) {
+        if (PACKET_remaining(&cipher_suite) == 0) {
             al = SSL_AD_ILLEGAL_PARAMETER;
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_CIPHERS_SPECIFIED);
             goto f_err;
         }
 
-        if (!PACKET_get_bytes(&pkt, &cdata, cipherlen)) {
-            /* not enough data */
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
-            goto f_err;
-        }
-
-        if (ssl_bytes_to_cipher_list(s, cdata, cipherlen, &(ciphers), 0) == NULL) {
+        if (ssl_bytes_to_cipher_list(s, PACKET_data(&cipher_suite),
+                                     PACKET_remaining(&cipher_suite),
+                                     &(ciphers), 0) == NULL) {
             goto err;
         }
 
@@ -1301,19 +1294,21 @@ int ssl3_get_client_hello(SSL *s)
         }
 
         /* compression */
-        if (!PACKET_get_1(&pkt, &complen)
-            || !PACKET_get_bytes(&pkt, &cdata, complen)) {
+        if (!PACKET_get_length_prefixed_1(&pkt, &compression)) {
             /* not enough data */
             al = SSL_AD_DECODE_ERROR;
+            /*
+             * TODO(openssl-team):
+             * SSL_R_LENGTH_TOO_SHORT and SSL_R_LENGTH_MISMATCH are used
+             * interchangeably. Pick one.
+             */
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
             goto f_err;
         }
 
-#ifndef OPENSSL_NO_COMP
-        q = cdata;
-#endif
+        complen = PACKET_remaining(&compression);
         for (j = 0; j < complen; j++) {
-            if (cdata[j] == 0)
+            if (PACKET_data(&compression)[j] == 0)
                 break;
         }
 
@@ -1415,7 +1410,7 @@ int ssl3_get_client_hello(SSL *s)
         }
         /* Look for resumed method in compression list */
         for (k = 0; k < complen; k++) {
-            if (q[k] == comp_id)
+            if (PACKET_data(&compression)[k] == comp_id)
                 break;
         }
         if (k >= complen) {
@@ -1436,7 +1431,7 @@ int ssl3_get_client_hello(SSL *s)
             comp = sk_SSL_COMP_value(s->ctx->comp_methods, m);
             v = comp->id;
             for (o = 0; o < complen; o++) {
-                if (v == q[o]) {
+                if (v == PACKET_data(&compression)[o]) {
                     done = 1;
                     break;
                 }
@@ -1713,8 +1708,8 @@ int ssl3_send_server_key_exchange(SSL *s)
              * reserve size for record length and PSK identity hint
              */
             n += 2;
-            if (s->ctx->psk_identity_hint)
-                n += strlen(s->ctx->psk_identity_hint);
+            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)) {
@@ -1996,11 +1991,11 @@ int ssl3_send_server_key_exchange(SSL *s)
 #ifndef OPENSSL_NO_PSK
         if (type & SSL_PSK) {
             /* copy PSK identity hint */
-            if (s->ctx->psk_identity_hint) {
-                s2n(strlen(s->ctx->psk_identity_hint), p);
-                strncpy((char *)p, s->ctx->psk_identity_hint,
-                        strlen(s->ctx->psk_identity_hint));
-                p += strlen(s->ctx->psk_identity_hint);
+            if (s->cert->psk_identity_hint) {
+                s2n(strlen(s->cert->psk_identity_hint), p);
+                strncpy((char *)p, s->cert->psk_identity_hint,
+                        strlen(s->cert->psk_identity_hint));
+                p += strlen(s->cert->psk_identity_hint);
             } else {
                 s2n(0, p);
             }
@@ -2231,9 +2226,8 @@ int ssl3_get_client_key_exchange(SSL *s)
     EC_POINT *clnt_ecpoint = NULL;
     BN_CTX *bn_ctx = NULL;
 #endif
-    PACKET pkt;
-    unsigned char *data;
-    size_t remain;
+    PACKET pkt, enc_premaster;
+    unsigned char *data, *rsa_decrypt = NULL;
 
     n = s->method->ssl_get_message(s,
                                    SSL3_ST_SR_KEY_EXCH_A,
@@ -2255,13 +2249,14 @@ int ssl3_get_client_key_exchange(SSL *s)
     if (alg_k & SSL_PSK) {
         unsigned char psk[PSK_MAX_PSK_LEN];
         size_t psklen;
+       PACKET psk_identity;
 
-        if (!PACKET_get_net_2(&pkt, &i)) {
+        if (!PACKET_get_length_prefixed_2(&pkt, &psk_identity)) {
             al = SSL_AD_DECODE_ERROR;
             SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
             goto f_err;
         }
-        if (i > PSK_MAX_IDENTITY_LEN) {
+        if (PACKET_remaining(&psk_identity) > PSK_MAX_IDENTITY_LEN) {
             al = SSL_AD_DECODE_ERROR;
             SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
                    SSL_R_DATA_LENGTH_TOO_LONG);
@@ -2274,21 +2269,11 @@ int ssl3_get_client_key_exchange(SSL *s)
             goto f_err;
         }
 
-        OPENSSL_free(s->session->psk_identity);
-        s->session->psk_identity = OPENSSL_malloc(i + 1);
-        if (s->session->psk_identity == NULL) {
+        if (!PACKET_strndup(&psk_identity, &s->session->psk_identity)) {
+            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
             al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-                   ERR_R_MALLOC_FAILURE);
-            goto f_err;
-        }
-        if (!PACKET_copy_bytes(&pkt, (unsigned char *)s->session->psk_identity,
-                               i)) {
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
             goto f_err;
         }
-        s->session->psk_identity[i] = '\0';
 
         psklen = s->psk_server_callback(s, s->session->psk_identity,
                                          psk, sizeof(psk));
@@ -2367,59 +2352,44 @@ int ssl3_get_client_key_exchange(SSL *s)
             rsa = pkey->pkey.rsa;
         }
 
-        /* TLS and [incidentally] DTLS{0xFEFF} */
-        if (s->version > SSL3_VERSION && s->version != DTLS1_BAD_VER) {
-            if (!PACKET_get_net_2(&pkt, &i)) {
-                al = SSL_AD_DECODE_ERROR;
-                SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
-                goto f_err;
-            }
-            remain = PACKET_remaining(&pkt);
-            if (remain != i) {
-                if (!(s->options & SSL_OP_TLS_D5_BUG)) {
+        /* SSLv3 and pre-standard DTLS omit the length bytes. */
+        if (s->version == SSL3_VERSION || s->version == DTLS1_BAD_VER) {
+            enc_premaster = pkt;
+        } else {
+            PACKET orig = pkt;
+            if (!PACKET_get_length_prefixed_2(&pkt, &enc_premaster)
+                || PACKET_remaining(&pkt) != 0) {
+                /* Try SSLv3 behaviour for TLS. */
+                if (s->options & SSL_OP_TLS_D5_BUG) {
+                    enc_premaster = orig;
+                } else {
                     al = SSL_AD_DECODE_ERROR;
-                    SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-                           SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG);
+                    SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
                     goto f_err;
-                } else {
-                    remain += 2;
-                    if (!PACKET_back(&pkt, 2)) {
-                        /*
-                         * We already read these 2 bytes so this should never
-                         * fail
-                         */
-                        al = SSL_AD_INTERNAL_ERROR;
-                        SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-                               ERR_R_INTERNAL_ERROR);
-                        goto f_err;
-                    }
                 }
             }
-        } else {
-            remain = PACKET_remaining(&pkt);
         }
 
         /*
-         * Reject overly short RSA ciphertext because we want to be sure
-         * that the buffer size makes it safe to iterate over the entire
-         * size of a premaster secret (SSL_MAX_MASTER_KEY_LENGTH). The
-         * actual expected size is larger due to RSA padding, but the
-         * bound is sufficient to be safe.
+         * 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 (remain < SSL_MAX_MASTER_KEY_LENGTH) {
-            al = SSL_AD_DECRYPT_ERROR;
+        if (RSA_size(rsa) < SSL_MAX_MASTER_KEY_LENGTH) {
+            al = SSL_AD_INTERNAL_ERROR;
             SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-                   SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG);
+                   RSA_R_KEY_SIZE_TOO_SMALL);
             goto f_err;
         }
 
-        if (!PACKET_get_bytes(&pkt, &data, remain)) {
-            /* We already checked we had enough data so this shouldn't happen */
+        rsa_decrypt = OPENSSL_malloc(RSA_size(rsa));
+        if (rsa_decrypt == NULL) {
             al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
             goto f_err;
         }
+
         /*
          * We must not leak whether a decryption failure occurs because of
          * Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see RFC 2246,
@@ -2429,10 +2399,13 @@ int ssl3_get_client_key_exchange(SSL *s)
          */
 
         if (RAND_bytes(rand_premaster_secret,
-                              sizeof(rand_premaster_secret)) <= 0)
+                       sizeof(rand_premaster_secret)) <= 0) {
             goto err;
-        decrypt_len =
-            RSA_private_decrypt(remain, data, data, rsa, RSA_PKCS1_PADDING);
+        }
+
+        decrypt_len = RSA_private_decrypt(PACKET_remaining(&enc_premaster),
+                                          PACKET_data(&enc_premaster),
+                                          rsa_decrypt, rsa, RSA_PKCS1_PADDING);
         ERR_clear_error();
 
         /*
@@ -2451,9 +2424,11 @@ int ssl3_get_client_key_exchange(SSL *s)
          * constant time and are treated like any other decryption error.
          */
         version_good =
-            constant_time_eq_8(data[0], (unsigned)(s->client_version >> 8));
+            constant_time_eq_8(rsa_decrypt[0],
+                               (unsigned)(s->client_version >> 8));
         version_good &=
-            constant_time_eq_8(data[1], (unsigned)(s->client_version & 0xff));
+            constant_time_eq_8(rsa_decrypt[1],
+                               (unsigned)(s->client_version & 0xff));
 
         /*
          * The premaster secret must contain the same version number as the
@@ -2467,9 +2442,10 @@ int ssl3_get_client_key_exchange(SSL *s)
         if (s->options & SSL_OP_TLS_ROLLBACK_BUG) {
             unsigned char workaround_good;
             workaround_good =
-                constant_time_eq_8(data[0], (unsigned)(s->version >> 8));
+                constant_time_eq_8(rsa_decrypt[0], (unsigned)(s->version >> 8));
             workaround_good &=
-                constant_time_eq_8(data[1], (unsigned)(s->version & 0xff));
+                constant_time_eq_8(rsa_decrypt[1],
+                                   (unsigned)(s->version & 0xff));
             version_good |= workaround_good;
         }
 
@@ -2486,30 +2462,28 @@ int ssl3_get_client_key_exchange(SSL *s)
          * it is still sufficiently large to read from.
          */
         for (j = 0; j < sizeof(rand_premaster_secret); j++) {
-            data[j] = constant_time_select_8(decrypt_good, data[j],
-                                          rand_premaster_secret[j]);
+            rsa_decrypt[j] =
+                constant_time_select_8(decrypt_good, rsa_decrypt[j],
+                                       rand_premaster_secret[j]);
         }
 
-        if (!ssl_generate_master_secret(s, data, sizeof(rand_premaster_secret),
-                                        0)) {
+        if (!ssl_generate_master_secret(s, rsa_decrypt,
+                                        sizeof(rand_premaster_secret), 0)) {
             al = SSL_AD_INTERNAL_ERROR;
             SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
             goto f_err;
         }
+        OPENSSL_free(rsa_decrypt);
+        rsa_decrypt = NULL;
     } else
 #endif
 #ifndef OPENSSL_NO_DH
     if (alg_k & (SSL_kDHE | SSL_kDHr | SSL_kDHd | SSL_kDHEPSK)) {
         int idx = -1;
         EVP_PKEY *skey = NULL;
-        size_t bookm;
+        PACKET bookmark = pkt;
         unsigned char shared[(OPENSSL_DH_MAX_MODULUS_BITS + 7) / 8];
 
-        if (!PACKET_get_bookmark(&pkt, &bookm)) {
-            al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
-            goto f_err;
-        }
         if (!PACKET_get_net_2(&pkt, &i)) {
             if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
                 al = SSL_AD_HANDSHAKE_FAILURE;
@@ -2525,12 +2499,7 @@ int ssl3_get_client_key_exchange(SSL *s)
                        SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
                 goto err;
             } else {
-                if (!PACKET_goto_bookmark(&pkt, bookm)) {
-                    al = SSL_AD_INTERNAL_ERROR;
-                    SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-                           ERR_R_INTERNAL_ERROR);
-                    goto f_err;
-                }
+                pkt = bookmark;
                 i = PACKET_remaining(&pkt);
             }
         }
@@ -2866,6 +2835,7 @@ int ssl3_get_client_key_exchange(SSL *s)
     EC_POINT_free(clnt_ecpoint);
     EC_KEY_free(srvr_ecdh);
     BN_CTX_free(bn_ctx);
+    OPENSSL_free(rsa_decrypt);
 #endif
 #ifndef OPENSSL_NO_PSK
     OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
@@ -3460,9 +3430,9 @@ int ssl3_send_cert_status(SSL *s)
 int ssl3_get_next_proto(SSL *s)
 {
     int ok;
-    unsigned int proto_len, padding_len;
     long n;
-    PACKET pkt;
+    PACKET pkt, next_proto, padding;
+    size_t next_proto_len;
 
     /*
      * Clients cannot send a NextProtocol message if we didn't see the
@@ -3511,25 +3481,20 @@ int ssl3_get_next_proto(SSL *s)
      *   uint8 padding_len;
      *   uint8 padding[padding_len];
      */
-    if (!PACKET_get_1(&pkt, &proto_len)){
+    if (!PACKET_get_length_prefixed_1(&pkt, &next_proto)
+        || !PACKET_get_length_prefixed_1(&pkt, &padding)
+        || PACKET_remaining(&pkt) > 0) {
         SSLerr(SSL_F_SSL3_GET_NEXT_PROTO, SSL_R_LENGTH_MISMATCH);
         goto err;
     }
 
-    s->next_proto_negotiated = OPENSSL_malloc(proto_len);
-    if (s->next_proto_negotiated == NULL) {
-        SSLerr(SSL_F_SSL3_GET_NEXT_PROTO, ERR_R_MALLOC_FAILURE);
+    if (!PACKET_memdup(&next_proto, &s->next_proto_negotiated,
+                       &next_proto_len)) {
+        s->next_proto_negotiated_len = 0;
         goto err;
     }
 
-    if (!PACKET_copy_bytes(&pkt, s->next_proto_negotiated, proto_len)
-            || !PACKET_get_1(&pkt, &padding_len)
-            || PACKET_remaining(&pkt) != padding_len) {
-        OPENSSL_free(s->next_proto_negotiated);
-        s->next_proto_negotiated = NULL;
-        SSLerr(SSL_F_SSL3_GET_NEXT_PROTO, SSL_R_LENGTH_MISMATCH);
-        goto err;
-    }
+    s->next_proto_negotiated_len = (unsigned char)next_proto_len;
 
     return 1;
 err:
@@ -3555,7 +3520,7 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, unsigned char *p,
     if(sslv2format) {
         n = SSLV2_CIPHER_LEN;
     } else {
-        n = ssl_put_cipher_by_char(s, NULL, NULL);
+        n = TLS_CIPHER_LEN;
     }
     if (n == 0 || (num % n) != 0) {
         SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,