PACKETise CertificateRequest
[openssl.git] / ssl / s3_clnt.c
index cd6918aa6b5dde1b14c443633be1dc5a1af2b510..e7bbfc90ed100b2cf4a09e281d3d35a8216e27b9 100644 (file)
@@ -1232,12 +1232,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,
@@ -1257,36 +1257,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);
@@ -1297,8 +1302,6 @@ int ssl3_get_server_certificate(SSL *s)
             goto err;
         }
         x = NULL;
-        nc += l + 3;
-        p = q;
     }
 
     i = ssl_verify_cert_chain(s, sk);
@@ -1693,6 +1696,12 @@ int ssl3_get_key_exchange(SSL *s)
         }
         p += i;
 
+        if (BN_is_zero(dh->p)) {
+            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_P_VALUE);
+            goto f_err;
+        }
+
+
         if (2 > n - param_len) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
             goto f_err;
@@ -1713,6 +1722,11 @@ int ssl3_get_key_exchange(SSL *s)
         }
         p += i;
 
+        if (BN_is_zero(dh->g)) {
+            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_G_VALUE);
+            goto f_err;
+        }
+
         if (2 > n - param_len) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
             goto f_err;
@@ -1734,6 +1748,11 @@ int ssl3_get_key_exchange(SSL *s)
         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;
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_DH_KEY_TOO_SMALL);
@@ -1992,12 +2011,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,
@@ -2036,7 +2056,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);
@@ -2044,7 +2068,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) {
@@ -2054,31 +2083,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);
@@ -2089,35 +2114,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);
@@ -2127,9 +2151,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.... */
@@ -2155,10 +2176,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,
@@ -2168,15 +2189,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;
@@ -2208,10 +2226,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;
@@ -2223,7 +2240,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
@@ -2236,7 +2257,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;
@@ -2252,7 +2273,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,
@@ -2261,31 +2283,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;
@@ -3043,8 +3070,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;