PACKETise ServerKeyExchange
[openssl.git] / ssl / s3_clnt.c
index 080dbf0f183dadb6cd730ddf19020593405d82bd..0195d099586815e52eac586c18778342eda5c989 100644 (file)
 
 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_finished(SSL *s);
+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 *,
@@ -276,7 +276,6 @@ int ssl3_connect(SSL *s)
             s->state = SSL3_ST_CW_CLNT_HELLO_A;
             s->ctx->stats.sess_connect++;
             s->init_num = 0;
-            s->s3->flags &= ~SSL3_FLAGS_CCS_OK;
             /*
              * Should have been reset by ssl3_get_finished, too.
              */
@@ -306,7 +305,7 @@ int ssl3_connect(SSL *s)
                 goto end;
 
             if (s->hit) {
-                s->state = SSL3_ST_CR_FINISHED_A;
+                s->state = SSL3_ST_CR_CHANGE_A;
                 if (s->tlsext_ticket_expected) {
                     /* receive renewed session ticket */
                     s->state = SSL3_ST_CR_SESSION_TICKET_A;
@@ -319,12 +318,12 @@ int ssl3_connect(SSL *s)
         case SSL3_ST_CR_CERT_A:
         case SSL3_ST_CR_CERT_B:
             /* Noop (ret = 0) for everything but EAP-FAST. */
-            ret = ssl3_check_finished(s);
+            ret = ssl3_check_change(s);
             if (ret < 0)
                 goto end;
             if (ret == 1) {
                 s->hit = 1;
-                s->state = SSL3_ST_CR_FINISHED_A;
+                s->state = SSL3_ST_CR_CHANGE_A;
                 s->init_num = 0;
                 break;
             }
@@ -525,7 +524,7 @@ int ssl3_connect(SSL *s)
                 if (s->tlsext_ticket_expected)
                     s->s3->tmp.next_state = SSL3_ST_CR_SESSION_TICKET_A;
                 else
-                    s->s3->tmp.next_state = SSL3_ST_CR_FINISHED_A;
+                    s->s3->tmp.next_state = SSL3_ST_CR_CHANGE_A;
             }
             s->init_num = 0;
             break;
@@ -535,7 +534,7 @@ int ssl3_connect(SSL *s)
             ret = ssl3_get_new_session_ticket(s);
             if (ret <= 0)
                 goto end;
-            s->state = SSL3_ST_CR_FINISHED_A;
+            s->state = SSL3_ST_CR_CHANGE_A;
             s->init_num = 0;
             break;
 
@@ -548,10 +547,19 @@ int ssl3_connect(SSL *s)
             s->init_num = 0;
             break;
 
+        case SSL3_ST_CR_CHANGE_A:
+        case SSL3_ST_CR_CHANGE_B:
+            ret = ssl3_get_change_cipher_spec(s, SSL3_ST_CR_CHANGE_A,
+                                              SSL3_ST_CR_CHANGE_B);
+            if (ret <= 0)
+                goto end;
+
+            s->state = SSL3_ST_CR_FINISHED_A;
+            s->init_num = 0;
+            break;
+
         case SSL3_ST_CR_FINISHED_A:
         case SSL3_ST_CR_FINISHED_B:
-            if (!s->s3->change_cipher_spec)
-                s->s3->flags |= SSL3_FLAGS_CCS_OK;
             ret = ssl3_get_finished(s, SSL3_ST_CR_FINISHED_A,
                                     SSL3_ST_CR_FINISHED_B);
             if (ret <= 0)
@@ -922,9 +930,10 @@ int ssl3_get_server_hello(SSL *s)
 {
     STACK_OF(SSL_CIPHER) *sk;
     const SSL_CIPHER *c;
-    unsigned char *p, *d;
+    PACKET pkt;
+    unsigned char *session_id, *cipherchars;
     int i, al = SSL_AD_INTERNAL_ERROR, ok;
-    unsigned int j;
+    unsigned int j, ciphercharlen;
     long n;
 #ifndef OPENSSL_NO_COMP
     SSL_COMP *comp;
@@ -963,10 +972,20 @@ int ssl3_get_server_hello(SSL *s)
         goto f_err;
     }
 
-    d = p = (unsigned char *)s->init_msg;
+    if (!PACKET_buf_init(&pkt, s->init_msg, n)) {
+        al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+        goto f_err;
+    }
 
     if (s->method->version == TLS_ANY_VERSION) {
-        int sversion = (p[0] << 8) | p[1];
+        unsigned int sversion;
+
+        if (!PACKET_get_net_2(&pkt, &sversion)) {
+            al = SSL_AD_DECODE_ERROR;
+            SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+            goto f_err;
+        }
 
 #if TLS_MAX_VERSION != TLS1_2_VERSION
 #error Code needs updating for new TLS version
@@ -1004,8 +1023,16 @@ int ssl3_get_server_hello(SSL *s)
         }
     } else if (s->method->version == DTLS_ANY_VERSION) {
         /* Work out correct protocol version to use */
-        int hversion = (p[0] << 8) | p[1];
-        int options = s->options;
+        unsigned int hversion;
+        int options;
+
+        if (!PACKET_get_net_2(&pkt, &hversion)) {
+            al = SSL_AD_DECODE_ERROR;
+            SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+            goto f_err;
+        }
+
+        options = s->options;
         if (hversion == DTLS1_2_VERSION && !(options & SSL_OP_NO_DTLSv1_2))
             s->method = DTLSv1_2_client_method();
         else if (tls1_suiteb(s)) {
@@ -1023,30 +1050,43 @@ int ssl3_get_server_hello(SSL *s)
             goto f_err;
         }
         s->session->ssl_version = s->version = s->method->version;
-    } else if ((p[0] != (s->version >> 8)) || (p[1] != (s->version & 0xff))) {
-        SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_WRONG_SSL_VERSION);
-        s->version = (s->version & 0xff00) | p[1];
-        al = SSL_AD_PROTOCOL_VERSION;
-        goto f_err;
+    } else {
+        unsigned char *vers;
+
+        if (!PACKET_get_bytes(&pkt, &vers, 2)) {
+            al = SSL_AD_DECODE_ERROR;
+            SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+            goto f_err;
+        }
+        if ((vers[0] != (s->version >> 8))
+                || (vers[1] != (s->version & 0xff))) {
+            SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_WRONG_SSL_VERSION);
+            s->version = (s->version & 0xff00) | vers[1];
+            al = SSL_AD_PROTOCOL_VERSION;
+            goto f_err;
+        }
     }
-    p += 2;
 
     /* load the server hello data */
     /* load the server random */
-    memcpy(s->s3->server_random, p, SSL3_RANDOM_SIZE);
-    p += SSL3_RANDOM_SIZE;
+    if (!PACKET_copy_bytes(&pkt, s->s3->server_random, SSL3_RANDOM_SIZE)) {
+        al = SSL_AD_DECODE_ERROR;
+        SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+        goto f_err;
+    }
 
     s->hit = 0;
 
-    /* get the session-id */
-    j = *(p++);
-
-    if ((j > sizeof s->session->session_id) || (j > SSL3_SESSION_ID_SIZE)) {
+    /* get the session-id length */
+    if (!PACKET_get_1(&pkt, &j)
+            || (j > sizeof s->session->session_id)
+            || (j > 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);
     /*
      * Check if we can resume the session based on external pre-shared secret.
      * EAP-FAST (RFC 4851) supports two types of session resumption.
@@ -1062,22 +1102,42 @@ 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,
                                      NULL, &pref_cipher,
                                      s->tls_session_secret_cb_arg)) {
             s->session->cipher = pref_cipher ?
-                pref_cipher : ssl_get_cipher_by_char(s, p + j);
+                pref_cipher : ssl_get_cipher_by_char(s, cipherchars);
         } else {
             SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
             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(p, s->session->session_id, j) == 0) {
+        && memcmp(session_id, s->session->session_id, j) == 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 */
@@ -1101,10 +1161,15 @@ int ssl3_get_server_hello(SSL *s)
             }
         }
         s->session->session_id_length = j;
-        memcpy(s->session->session_id, p, j); /* j could be 0 */
+        memcpy(s->session->session_id, session_id, j); /* j could be 0 */
     }
-    p += j;
-    c = ssl_get_cipher_by_char(s, p);
+
+    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;
+    }
+    c = ssl_get_cipher_by_char(s, cipherchars);
     if (c == NULL) {
         /* unknown cipher */
         al = SSL_AD_ILLEGAL_PARAMETER;
@@ -1125,7 +1190,6 @@ int ssl3_get_server_hello(SSL *s)
         SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_WRONG_CIPHER_RETURNED);
         goto f_err;
     }
-    p += ssl_put_cipher_by_char(s, NULL, NULL);
 
     sk = ssl_get_ciphers_by_id(s);
     i = sk_SSL_CIPHER_find(sk, c);
@@ -1158,8 +1222,13 @@ int ssl3_get_server_hello(SSL *s)
         goto f_err;
     /* lets get the compression algorithm */
     /* COMPRESSION */
+    if (!PACKET_get_1(&pkt, &j)) {
+        SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+        al = SSL_AD_DECODE_ERROR;
+        goto f_err;
+    }
 #ifdef OPENSSL_NO_COMP
-    if (*(p++) != 0) {
+    if (j != 0) {
         al = SSL_AD_ILLEGAL_PARAMETER;
         SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,
                SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
@@ -1174,7 +1243,6 @@ int ssl3_get_server_hello(SSL *s)
         goto f_err;
     }
 #else
-    j = *(p++);
     if (s->hit && j != s->session->compress_meth) {
         al = SSL_AD_ILLEGAL_PARAMETER;
         SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,
@@ -1201,12 +1269,12 @@ int ssl3_get_server_hello(SSL *s)
 #endif
 
     /* TLS extensions */
-    if (!ssl_parse_serverhello_tlsext(s, &p, d, n)) {
+    if (!ssl_parse_serverhello_tlsext(s, &pkt)) {
         SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_PARSE_TLSEXT);
         goto err;
     }
 
-    if (p != (d + n)) {
+    if (PACKET_remaining(&pkt) != 0) {
         /* wrong packet length */
         al = SSL_AD_DECODE_ERROR;
         SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_BAD_PACKET_LENGTH);
@@ -1224,12 +1292,12 @@ int ssl3_get_server_hello(SSL *s)
 int ssl3_get_server_certificate(SSL *s)
 {
     int al, i, ok, ret = -1, exp_idx;
-    unsigned long n, nc, llen, l;
+    unsigned long n, cert_list_len, cert_len;
     X509 *x = NULL;
-    const unsigned char *q, *p;
-    unsigned char *d;
+    unsigned char *certstart, *certbytes;
     STACK_OF(X509) *sk = NULL;
     EVP_PKEY *pkey = NULL;
+    PACKET pkt;
 
     n = s->method->ssl_get_message(s,
                                    SSL3_ST_CR_CERT_A,
@@ -1249,36 +1317,41 @@ int ssl3_get_server_certificate(SSL *s)
         SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, SSL_R_BAD_MESSAGE_TYPE);
         goto f_err;
     }
-    p = d = (unsigned char *)s->init_msg;
+
+    if (!PACKET_buf_init(&pkt, s->init_msg, n)) {
+        al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+        goto f_err;
+    }
 
     if ((sk = sk_X509_new_null()) == NULL) {
         SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
-    n2l3(p, llen);
-    if (llen + 3 != n) {
+    if (!PACKET_get_net_3(&pkt, &cert_list_len)
+            || PACKET_remaining(&pkt) != cert_list_len) {
         al = SSL_AD_DECODE_ERROR;
         SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, SSL_R_LENGTH_MISMATCH);
         goto f_err;
     }
-    for (nc = 0; nc < llen;) {
-        n2l3(p, l);
-        if ((l + nc + 3) > llen) {
+    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_SSL3_GET_SERVER_CERTIFICATE,
                    SSL_R_CERT_LENGTH_MISMATCH);
             goto f_err;
         }
 
-        q = p;
-        x = d2i_X509(NULL, &q, l);
+        certstart = certbytes;
+        x = d2i_X509(NULL, (const unsigned char **)&certbytes, cert_len);
         if (x == NULL) {
             al = SSL_AD_BAD_CERTIFICATE;
             SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, ERR_R_ASN1_LIB);
             goto f_err;
         }
-        if (q != (p + l)) {
+        if (certbytes != (certstart + cert_len)) {
             al = SSL_AD_DECODE_ERROR;
             SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,
                    SSL_R_CERT_LENGTH_MISMATCH);
@@ -1289,8 +1362,6 @@ int ssl3_get_server_certificate(SSL *s)
             goto err;
         }
         x = NULL;
-        nc += l + 3;
-        p = q;
     }
 
     i = ssl_verify_cert_chain(s, sk);
@@ -1348,7 +1419,7 @@ int ssl3_get_server_certificate(SSL *s)
     s->session->peer_type = i;
 
     X509_free(s->session->peer);
-    CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
+    X509_up_ref(x);
     s->session->peer = x;
     s->session->verify_result = s->verify_result;
 
@@ -1373,9 +1444,9 @@ int ssl3_get_key_exchange(SSL *s)
     unsigned char *q, md_buf[EVP_MAX_MD_SIZE * 2];
 #endif
     EVP_MD_CTX md_ctx;
-    unsigned char *param, *p;
-    int al, j, ok;
-    long i, param_len, n, alg_k, alg_a;
+    int al, j, verify_ret, ok;
+    unsigned int i;
+    long n, alg_k, alg_a;
     EVP_PKEY *pkey = NULL;
     const EVP_MD *md = NULL;
 #ifndef OPENSSL_NO_RSA
@@ -1389,8 +1460,11 @@ int ssl3_get_key_exchange(SSL *s)
     BN_CTX *bn_ctx = NULL;
     EC_POINT *srvr_ecpoint = NULL;
     int curve_nid = 0;
-    int encoded_pt_len = 0;
+    unsigned int encoded_pt_len = 0;
 #endif
+    PACKET pkt;
+    unsigned char *data, *param;
+    size_t startparam, endparam;
 
     EVP_MD_CTX_init(&md_ctx);
 
@@ -1422,7 +1496,12 @@ int ssl3_get_key_exchange(SSL *s)
         return (1);
     }
 
-    param = p = (unsigned char *)s->init_msg;
+    if (!PACKET_buf_init(&pkt, s->init_msg, n)
+            || !PACKET_get_bookmark(&pkt, &startparam)) {
+            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+            al = SSL_AD_INTERNAL_ERROR;
+            goto f_err;
+    }
 
 #ifndef OPENSSL_NO_RSA
     RSA_free(s->s3->peer_rsa_tmp);
@@ -1437,9 +1516,6 @@ int ssl3_get_key_exchange(SSL *s)
     s->s3->peer_ecdh_tmp = NULL;
 #endif
 
-    /* Total length of the parameters including the length prefix */
-    param_len = 0;
-
     alg_a = s->s3->tmp.new_cipher->algorithm_auth;
 
     al = SSL_AD_DECODE_ERROR;
@@ -1448,12 +1524,10 @@ int ssl3_get_key_exchange(SSL *s)
     /* PSK ciphersuites are preceded by an identity hint */
     if (alg_k & SSL_PSK) {
 
-        param_len = 2;
-        if (param_len > n) {
+        if (!PACKET_get_net_2(&pkt, &i)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
             goto f_err;
         }
-        n2s(p, i);
 
         /*
          * Store PSK identity hint for later use, hint is used in
@@ -1466,16 +1540,21 @@ int ssl3_get_key_exchange(SSL *s)
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG);
             goto f_err;
         }
-        if (i > n - param_len) {
+        if (PACKET_remaining(&pkt) < i) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
                    SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH);
             goto f_err;
         }
-        param_len += i;
 
         OPENSSL_free(s->session->psk_identity_hint);
         if (i != 0) {
-            s->session->psk_identity_hint = BUF_strndup((char *)p, i);
+            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);
@@ -1484,9 +1563,6 @@ int ssl3_get_key_exchange(SSL *s)
         } else {
             s->session->psk_identity_hint = NULL;
         }
-
-        p += i;
-        n -= param_len;
     }
 
     /* Nothing else to do for plain PSK or RSAPSK */
@@ -1495,86 +1571,65 @@ int ssl3_get_key_exchange(SSL *s)
 #endif                          /* !OPENSSL_NO_PSK */
 #ifndef OPENSSL_NO_SRP
     if (alg_k & SSL_kSRP) {
-        param_len = 2;
-        if (param_len > n) {
+        if (!PACKET_get_net_2(&pkt, &i)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
             goto f_err;
         }
-        n2s(p, i);
 
-        if (i > n - param_len) {
+        if (!PACKET_get_bytes(&pkt, &data, i)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SRP_N_LENGTH);
             goto f_err;
         }
-        param_len += i;
 
-        if ((s->srp_ctx.N = BN_bin2bn(p, i, NULL)) == NULL) {
+        if ((s->srp_ctx.N = BN_bin2bn(data, i, NULL)) == NULL) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
             goto err;
         }
-        p += i;
 
-        if (2 > n - param_len) {
+        if (!PACKET_get_net_2(&pkt, &i)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
             goto f_err;
         }
-        param_len += 2;
-
-        n2s(p, i);
 
-        if (i > n - param_len) {
+        if (!PACKET_get_bytes(&pkt, &data, i)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SRP_G_LENGTH);
             goto f_err;
         }
-        param_len += i;
 
-        if ((s->srp_ctx.g = BN_bin2bn(p, i, NULL)) == NULL) {
+        if ((s->srp_ctx.g = BN_bin2bn(data, i, NULL)) == NULL) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
             goto err;
         }
-        p += i;
 
-        if (1 > n - param_len) {
+        if (!PACKET_get_1(&pkt, &i)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
             goto f_err;
         }
-        param_len += 1;
-
-        i = (unsigned int)(p[0]);
-        p++;
 
-        if (i > n - param_len) {
+        if (!PACKET_get_bytes(&pkt, &data, i)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SRP_S_LENGTH);
             goto f_err;
         }
-        param_len += i;
 
-        if ((s->srp_ctx.s = BN_bin2bn(p, i, NULL)) == NULL) {
+        if ((s->srp_ctx.s = BN_bin2bn(data, i, NULL)) == NULL) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
             goto err;
         }
-        p += i;
 
-        if (2 > n - param_len) {
+        if (!PACKET_get_net_2(&pkt, &i)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
             goto f_err;
         }
-        param_len += 2;
-
-        n2s(p, i);
 
-        if (i > n - param_len) {
+        if (!PACKET_get_bytes(&pkt, &data, i)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SRP_B_LENGTH);
             goto f_err;
         }
-        param_len += i;
 
-        if ((s->srp_ctx.B = BN_bin2bn(p, i, NULL)) == NULL) {
+        if ((s->srp_ctx.B = BN_bin2bn(data, i, NULL)) == NULL) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
             goto err;
         }
-        p += i;
-        n -= param_len;
 
         if (!srp_verify_server_param(s, &al)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SRP_PARAMETERS);
@@ -1599,45 +1654,35 @@ int ssl3_get_key_exchange(SSL *s)
             goto err;
         }
 
-        param_len = 2;
-        if (param_len > n) {
+        if (!PACKET_get_net_2(&pkt, &i)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
             goto f_err;
         }
-        n2s(p, i);
 
-        if (i > n - param_len) {
+        if (!PACKET_get_bytes(&pkt, &data, i)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_RSA_MODULUS_LENGTH);
             goto f_err;
         }
-        param_len += i;
 
-        if ((rsa->n = BN_bin2bn(p, i, rsa->n)) == NULL) {
+        if ((rsa->n = BN_bin2bn(data, i, rsa->n)) == NULL) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
             goto err;
         }
-        p += i;
 
-        if (2 > n - param_len) {
+        if (!PACKET_get_net_2(&pkt, &i)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
             goto f_err;
         }
-        param_len += 2;
-
-        n2s(p, i);
 
-        if (i > n - param_len) {
+        if (!PACKET_get_bytes(&pkt, &data, i)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_RSA_E_LENGTH);
             goto f_err;
         }
-        param_len += i;
 
-        if ((rsa->e = BN_bin2bn(p, i, rsa->e)) == NULL) {
+        if ((rsa->e = BN_bin2bn(data, i, rsa->e)) == NULL) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
             goto err;
         }
-        p += i;
-        n -= param_len;
 
         /* this should be because we are using an export cipher */
         if (alg_a & SSL_aRSA)
@@ -1666,65 +1711,65 @@ int ssl3_get_key_exchange(SSL *s)
             goto err;
         }
 
-        param_len = 2;
-        if (param_len > n) {
+        if (!PACKET_get_net_2(&pkt, &i)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
             goto f_err;
         }
-        n2s(p, i);
 
-        if (i > n - param_len) {
+        if (!PACKET_get_bytes(&pkt, &data, i)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_P_LENGTH);
             goto f_err;
         }
-        param_len += i;
 
-        if ((dh->p = BN_bin2bn(p, i, NULL)) == NULL) {
+        if ((dh->p = BN_bin2bn(data, i, NULL)) == NULL) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
             goto err;
         }
-        p += i;
 
-        if (2 > n - param_len) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
+        if (BN_is_zero(dh->p)) {
+            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_P_VALUE);
             goto f_err;
         }
-        param_len += 2;
 
-        n2s(p, i);
+        if (!PACKET_get_net_2(&pkt, &i)) {
+            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
+            goto f_err;
+        }
 
-        if (i > n - param_len) {
+        if (!PACKET_get_bytes(&pkt, &data, i)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_G_LENGTH);
             goto f_err;
         }
-        param_len += i;
 
-        if ((dh->g = BN_bin2bn(p, i, NULL)) == NULL) {
+        if ((dh->g = BN_bin2bn(data, i, NULL)) == NULL) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
             goto err;
         }
-        p += i;
 
-        if (2 > n - param_len) {
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
+        if (BN_is_zero(dh->g)) {
+            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_G_VALUE);
             goto f_err;
         }
-        param_len += 2;
 
-        n2s(p, i);
+        if (!PACKET_get_net_2(&pkt, &i)) {
+            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
+            goto f_err;
+        }
 
-        if (i > n - param_len) {
+        if (!PACKET_get_bytes(&pkt, &data, i)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_PUB_KEY_LENGTH);
             goto f_err;
         }
-        param_len += i;
 
-        if ((dh->pub_key = BN_bin2bn(p, i, NULL)) == NULL) {
+        if ((dh->pub_key = BN_bin2bn(data, i, NULL)) == NULL) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
             goto err;
         }
-        p += i;
-        n -= param_len;
+
+        if (BN_is_zero(dh->pub_key)) {
+            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_PUB_KEY_VALUE);
+            goto f_err;
+        }
 
         if (!ssl_security(s, SSL_SECOP_TMP_DH, DH_security_bits(dh), 0, dh)) {
             al = SSL_AD_HANDSHAKE_FAILURE;
@@ -1758,11 +1803,9 @@ int ssl3_get_key_exchange(SSL *s)
 
         /*
          * XXX: For now we only support named (not generic) curves and the
-         * ECParameters in this case is just three bytes. We also need one
-         * byte for the length of the encoded point
+         * ECParameters in this case is just three bytes.
          */
-        param_len = 4;
-        if (param_len > n) {
+        if (!PACKET_get_bytes(&pkt, &data, 3)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
             goto f_err;
         }
@@ -1770,12 +1813,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, p, 3)) {
+        if (!tls1_check_curve(s, data, 3)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_WRONG_CURVE);
             goto f_err;
         }
 
-        if ((curve_nid = tls1_ec_curve_id2nid(*(p + 2))) == 0) {
+        if ((curve_nid = tls1_ec_curve_id2nid(*(data + 2))) == 0) {
             al = SSL_AD_INTERNAL_ERROR;
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
                    SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
@@ -1803,8 +1846,6 @@ int ssl3_get_key_exchange(SSL *s)
             goto f_err;
         }
 
-        p += 3;
-
         /* Next, get the encoded ECPoint */
         if (((srvr_ecpoint = EC_POINT_new(group)) == NULL) ||
             ((bn_ctx = BN_CTX_new()) == NULL)) {
@@ -1812,19 +1853,17 @@ int ssl3_get_key_exchange(SSL *s)
             goto err;
         }
 
-        encoded_pt_len = *p;    /* length of encoded point */
-        p += 1;
+        if (!PACKET_get_1(&pkt, &encoded_pt_len)) {
+            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
+            goto f_err;
+        }
 
-        if ((encoded_pt_len > n - param_len) ||
+        if (!PACKET_get_bytes(&pkt, &data, encoded_pt_len) ||
             (EC_POINT_oct2point(group, srvr_ecpoint,
-                                p, encoded_pt_len, bn_ctx) == 0)) {
+                                data, encoded_pt_len, bn_ctx) == 0)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_ECPOINT);
             goto f_err;
         }
-        param_len += encoded_pt_len;
-
-        n -= param_len;
-        p += encoded_pt_len;
 
         /*
          * The ECC/TLS specification does not mention the use of DSA to sign
@@ -1855,17 +1894,20 @@ int ssl3_get_key_exchange(SSL *s)
     }
 #endif                          /* !OPENSSL_NO_EC */
 
-    /* p points to the next byte, there are 'n' bytes left */
+    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) {
         if (SSL_USE_SIGALGS(s)) {
             int rv;
-            if (2 > n) {
+            if (!PACKET_get_bytes(&pkt, &data, 2)) {
                 SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
                 goto f_err;
             }
-            rv = tls12_check_peer_sigalg(&md, s, p, pkey);
+            rv = tls12_check_peer_sigalg(&md, s, data, pkey);
             if (rv == -1)
                 goto err;
             else if (rv == 0) {
@@ -1874,27 +1916,35 @@ int ssl3_get_key_exchange(SSL *s)
 #ifdef SSL_DEBUG
             fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
 #endif
-            p += 2;
-            n -= 2;
         } else
             md = EVP_sha1();
 
-        if (2 > n) {
+        if (!PACKET_get_net_2(&pkt, &i)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
             goto f_err;
         }
-        n2s(p, i);
-        n -= 2;
         j = EVP_PKEY_size(pkey);
+        if (j < 0) {
+            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+            goto f_err;
+        }
 
         /*
-         * Check signature length. If n is 0 then signature is empty
+         * Check signature length
          */
-        if ((i != n) || (n > j) || (n <= 0)) {
+        if (i > (unsigned int)j
+                || !PACKET_get_bytes(&pkt, &data, i)
+                || PACKET_remaining(&pkt) != 0) {
             /* 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;
@@ -1910,18 +1960,19 @@ 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, param_len);
+                EVP_DigestUpdate(&md_ctx, param, endparam - startparam);
                 EVP_DigestFinal_ex(&md_ctx, q, &size);
                 q += size;
                 j += size;
             }
-            i = RSA_verify(NID_md5_sha1, md_buf, j, p, n, pkey->pkey.rsa);
-            if (i < 0) {
+            verify_ret =
+                RSA_verify(NID_md5_sha1, md_buf, j, data, i, pkey->pkey.rsa);
+            if (verify_ret < 0) {
                 al = SSL_AD_DECRYPT_ERROR;
                 SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_RSA_DECRYPT);
                 goto f_err;
             }
-            if (i == 0) {
+            if (verify_ret == 0) {
                 /* bad signature */
                 al = SSL_AD_DECRYPT_ERROR;
                 SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SIGNATURE);
@@ -1935,8 +1986,8 @@ 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, param_len);
-            if (EVP_VerifyFinal(&md_ctx, p, (int)n, pkey) <= 0) {
+            EVP_VerifyUpdate(&md_ctx, param, endparam - startparam);
+            if (EVP_VerifyFinal(&md_ctx, data, (int)i, pkey) <= 0) {
                 /* bad signature */
                 al = SSL_AD_DECRYPT_ERROR;
                 SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SIGNATURE);
@@ -1953,7 +2004,7 @@ int ssl3_get_key_exchange(SSL *s)
             goto err;
         }
         /* still data left over */
-        if (n != 0) {
+        if (PACKET_remaining(&pkt) != 0) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_EXTRA_DATA_IN_MESSAGE);
             goto f_err;
         }
@@ -1984,12 +2035,13 @@ int ssl3_get_key_exchange(SSL *s)
 int ssl3_get_certificate_request(SSL *s)
 {
     int ok, ret = 0;
-    unsigned long n, nc, l;
-    unsigned int llen, ctype_num, i;
+    unsigned long n;
+    unsigned int list_len, ctype_num, i, name_len;
     X509_NAME *xn = NULL;
-    const unsigned char *p, *q;
-    unsigned char *d;
+    unsigned char *data;
+    unsigned char *namestart, *namebytes;
     STACK_OF(X509_NAME) *ca_sk = NULL;
+    PACKET pkt;
 
     n = s->method->ssl_get_message(s,
                                    SSL3_ST_CR_CERT_REQ_A,
@@ -2028,7 +2080,11 @@ int ssl3_get_certificate_request(SSL *s)
         }
     }
 
-    p = d = (unsigned char *)s->init_msg;
+    if (!PACKET_buf_init(&pkt, s->init_msg, n)) {
+        ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+        SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
 
     if ((ca_sk = sk_X509_NAME_new(ca_dn_cmp)) == NULL) {
         SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
@@ -2036,7 +2092,12 @@ int ssl3_get_certificate_request(SSL *s)
     }
 
     /* get the certificate types */
-    ctype_num = *(p++);
+    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_SSL3_GET_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH);
+        goto err;
+    }
     OPENSSL_free(s->cert->ctypes);
     s->cert->ctypes = NULL;
     if (ctype_num > SSL3_CT_NUMBER) {
@@ -2046,31 +2107,27 @@ int ssl3_get_certificate_request(SSL *s)
             SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
             goto err;
         }
-        memcpy(s->cert->ctypes, p, ctype_num);
+        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] = p[i];
-    p += p[-1];
+        s->s3->tmp.ctype[i] = data[i];
+
     if (SSL_USE_SIGALGS(s)) {
-        n2s(p, llen);
-        /*
-         * Check we have enough room for signature algorithms and following
-         * length value.
-         */
-        if ((unsigned long)(p - d + llen + 2) > n) {
+        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_SSL3_GET_CERTIFICATE_REQUEST,
-                   SSL_R_DATA_LENGTH_TOO_LONG);
+            SSLerr(SSL_F_SSL3_GET_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 ((llen & 1) || !tls1_save_sigalgs(s, p, llen)) {
+        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_SSL3_GET_CERTIFICATE_REQUEST,
                    SSL_R_SIGNATURE_ALGORITHMS_ERROR);
@@ -2081,35 +2138,34 @@ int ssl3_get_certificate_request(SSL *s)
             SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
             goto err;
         }
-        p += llen;
     }
 
     /* get the CA RDNs */
-    n2s(p, llen);
-
-    if ((unsigned long)(p - d + llen) != n) {
+    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_SSL3_GET_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH);
         goto err;
     }
 
-    for (nc = 0; nc < llen;) {
-        n2s(p, l);
-        if ((l + nc + 2) > llen) {
+    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_SSL3_GET_CERTIFICATE_REQUEST, SSL_R_CA_DN_TOO_LONG);
+            SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH);
             goto err;
         }
 
-        q = p;
+        namestart = namebytes;
 
-        if ((xn = d2i_X509_NAME(NULL, &q, l)) == NULL) {
+        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_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_ASN1_LIB);
             goto err;
         }
 
-        if (q != (p + l)) {
+        if (namebytes != (namestart + name_len)) {
             ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
             SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,
                    SSL_R_CA_DN_LENGTH_MISMATCH);
@@ -2119,9 +2175,6 @@ int ssl3_get_certificate_request(SSL *s)
             SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
             goto err;
         }
-
-        p += l;
-        nc += l + 2;
     }
 
     /* we should setup a certificate to return.... */
@@ -2147,10 +2200,10 @@ static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
 
 int ssl3_get_new_session_ticket(SSL *s)
 {
-    int ok, al, ret = 0, ticklen;
+    int ok, al, ret = 0;
+    unsigned int ticklen;
     long n;
-    const unsigned char *p;
-    unsigned char *d;
+    PACKET pkt;
 
     n = s->method->ssl_get_message(s,
                                    SSL3_ST_CR_SESSION_TICKET_A,
@@ -2160,15 +2213,12 @@ int ssl3_get_new_session_ticket(SSL *s)
     if (!ok)
         return ((int)n);
 
-    if (n < 6) {
-        /* need at least ticket_lifetime_hint + ticket length */
-        al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, SSL_R_LENGTH_MISMATCH);
+    if (!PACKET_buf_init(&pkt, s->init_msg, n)) {
+        al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
         goto f_err;
     }
 
-    p = d = (unsigned char *)s->init_msg;
-
     if (s->session->session_id_length > 0) {
         int i = s->session_ctx->session_cache_mode;
         SSL_SESSION *new_sess;
@@ -2200,10 +2250,9 @@ int ssl3_get_new_session_ticket(SSL *s)
         s->session = new_sess;
     }
 
-    n2l(p, s->session->tlsext_tick_lifetime_hint);
-    n2s(p, ticklen);
-    /* ticket_lifetime_hint + ticket_length + ticket */
-    if (ticklen + 6 != n) {
+    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;
@@ -2215,7 +2264,11 @@ int ssl3_get_new_session_ticket(SSL *s)
         SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
         goto err;
     }
-    memcpy(s->session->tlsext_tick, p, ticklen);
+    if (!PACKET_copy_bytes(&pkt, s->session->tlsext_tick, ticklen)) {
+        al = SSL_AD_DECODE_ERROR;
+        SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, SSL_R_LENGTH_MISMATCH);
+        goto f_err;
+    }
     s->session->tlsext_ticklen = ticklen;
     /*
      * There are two ways to detect a resumed ticket session. One is to set
@@ -2228,7 +2281,7 @@ int ssl3_get_new_session_ticket(SSL *s)
      * elsewhere in OpenSSL. The session ID is set to the SHA256 (or SHA1 is
      * SHA256 is disabled) hash of the ticket.
      */
-    EVP_Digest(p, ticklen,
+    EVP_Digest(s->session->tlsext_tick, ticklen,
                s->session->session_id, &s->session->session_id_length,
                EVP_sha256(), NULL);
     ret = 1;
@@ -2244,7 +2297,8 @@ int ssl3_get_cert_status(SSL *s)
 {
     int ok, al;
     unsigned long resplen, n;
-    const unsigned char *p;
+    unsigned int type;
+    PACKET pkt;
 
     n = s->method->ssl_get_message(s,
                                    SSL3_ST_CR_CERT_STATUS_A,
@@ -2253,31 +2307,36 @@ int ssl3_get_cert_status(SSL *s)
 
     if (!ok)
         return ((int)n);
-    if (n < 4) {
-        /* need at least status type + length */
-        al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_LENGTH_MISMATCH);
+
+    if (!PACKET_buf_init(&pkt, s->init_msg, n)) {
+        al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_SSL3_GET_CERT_STATUS, ERR_R_INTERNAL_ERROR);
         goto f_err;
     }
-    p = (unsigned char *)s->init_msg;
-    if (*p++ != TLSEXT_STATUSTYPE_ocsp) {
+    if (!PACKET_get_1(&pkt, &type)
+            || type != TLSEXT_STATUSTYPE_ocsp) {
         al = SSL_AD_DECODE_ERROR;
         SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_UNSUPPORTED_STATUS_TYPE);
         goto f_err;
     }
-    n2l3(p, resplen);
-    if (resplen + 4 != n) {
+    if (!PACKET_get_net_3(&pkt, &resplen)
+            || PACKET_remaining(&pkt) != resplen) {
         al = SSL_AD_DECODE_ERROR;
         SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_LENGTH_MISMATCH);
         goto f_err;
     }
     OPENSSL_free(s->tlsext_ocsp_resp);
-    s->tlsext_ocsp_resp = BUF_memdup(p, resplen);
+    s->tlsext_ocsp_resp = OPENSSL_malloc(resplen);
     if (!s->tlsext_ocsp_resp) {
         al = SSL_AD_INTERNAL_ERROR;
         SSLerr(SSL_F_SSL3_GET_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_SSL3_GET_CERT_STATUS, SSL_R_LENGTH_MISMATCH);
+        goto f_err;
+    }
     s->tlsext_ocsp_resplen = resplen;
     if (s->ctx->tlsext_status_cb) {
         int ret;
@@ -3035,8 +3094,7 @@ int ssl3_send_client_verify(SSL *s)
             n = j + 2;
         } else
 #endif
-        if (pkey->type == NID_id_GostR3410_94
-                || pkey->type == NID_id_GostR3410_2001) {
+        if (pkey->type == NID_id_GostR3410_2001) {
             unsigned char signbuf[64];
             int i;
             size_t sigsize = 64;
@@ -3368,11 +3426,11 @@ int ssl3_check_cert_and_algorithm(SSL *s)
  * the session ID. EAP-FAST (RFC 4851), however, relies on the next server
  * message after the ServerHello to determine if the server is resuming.
  * Therefore, we allow EAP-FAST to peek ahead.
- * ssl3_check_finished returns 1 if we are resuming from an external
- * pre-shared secret, we have a "ticket" and the next server handshake message
- * is Finished; and 0 otherwise. It returns -1 upon an error.
+ * ssl3_check_change returns 1 if we are resuming from an external
+ * pre-shared secret, we have a "ticket" and the next server message
+ * is CCS; and 0 otherwise. It returns -1 upon an error.
  */
-static int ssl3_check_finished(SSL *s)
+static int ssl3_check_change(SSL *s)
 {
     int ok = 0;
 
@@ -3380,8 +3438,6 @@ static int ssl3_check_finished(SSL *s)
         !s->session->tlsext_tick)
         return 0;
 
-    /* Need to permit this temporarily, in case the next message is Finished. */
-    s->s3->flags |= SSL3_FLAGS_CCS_OK;
     /*
      * This function is called when we might get a Certificate message instead,
      * so permit appropriate message length.
@@ -3392,23 +3448,15 @@ static int ssl3_check_finished(SSL *s)
                                SSL3_ST_CR_CERT_A,
                                SSL3_ST_CR_CERT_B,
                                -1, s->max_cert_list, &ok);
-    s->s3->flags &= ~SSL3_FLAGS_CCS_OK;
 
     if (!ok)
         return -1;
 
     s->s3->tmp.reuse_message = 1;
 
-    if (s->s3->tmp.message_type == SSL3_MT_FINISHED)
+    if (s->s3->tmp.message_type == SSL3_MT_CHANGE_CIPHER_SPEC)
         return 1;
 
-    /* If we're not done, then the CCS arrived early and we should bail. */
-    if (s->s3->change_cipher_spec) {
-        SSLerr(SSL_F_SSL3_CHECK_FINISHED, SSL_R_CCS_RECEIVED_EARLY);
-        ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
-        return -1;
-    }
-
     return 0;
 }