Harmonize return values in dtls1_buffer_record
[oweals/openssl.git] / ssl / s3_srvr.c
index 0191790880bb10cf01d10c27266664779a635c69..39c1574eb49a363bbfdf5f8da10a26d888b6dd61 100644 (file)
  * OTHERWISE.
  */
 
-#define REUSE_CIPHER_BUG
-#define NETSCAPE_HANG_BUG
 
 #include <stdio.h>
 #include "ssl_locl.h"
@@ -542,12 +540,7 @@ int ssl3_accept(SSL *s)
                 ret = ssl3_send_certificate_request(s);
                 if (ret <= 0)
                     goto end;
-#ifndef NETSCAPE_HANG_BUG
                 s->state = SSL3_ST_SW_SRVR_DONE_A;
-#else
-                s->state = SSL3_ST_SW_FLUSH;
-                s->s3->tmp.next_state = SSL3_ST_SR_CERT_A;
-#endif
                 s->init_num = 0;
             }
             break;
@@ -620,17 +613,19 @@ int ssl3_accept(SSL *s)
                 s->init_num = 0;
                 if (!s->session->peer)
                     break;
-                /*
-                 * For sigalgs freeze the handshake buffer at this point and
-                 * digest cached records.
-                 */
                 if (!s->s3->handshake_buffer) {
                     SSLerr(SSL_F_SSL3_ACCEPT, ERR_R_INTERNAL_ERROR);
                     return -1;
                 }
-                s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE;
-                if (!ssl3_digest_cached_records(s))
-                    return -1;
+                /*
+                 * For sigalgs freeze the handshake buffer. If we support
+                 * extms we've done this already.
+                 */
+                if (!(s->s3->flags & SSL_SESS_FLAG_EXTMS)) {
+                    s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE;
+                    if (!ssl3_digest_cached_records(s))
+                        return -1;
+                }
             } else {
                 int offset = 0;
                 int dgst_num;
@@ -1382,29 +1377,7 @@ int ssl3_get_client_hello(SSL *s)
             s->tlsext_ticket_expected = 0;
     } else {
         /* Session-id reuse */
-#ifdef REUSE_CIPHER_BUG
-        STACK_OF(SSL_CIPHER) *sk;
-        SSL_CIPHER *nc = NULL;
-        SSL_CIPHER *ec = NULL;
-
-        if (s->options & SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG) {
-            sk = s->session->ciphers;
-            for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
-                c = sk_SSL_CIPHER_value(sk, i);
-                if (c->algorithm_enc & SSL_eNULL)
-                    nc = c;
-                if (SSL_C_IS_EXPORT(c))
-                    ec = c;
-            }
-            if (nc != NULL)
-                s->s3->tmp.new_cipher = nc;
-            else if (ec != NULL)
-                s->s3->tmp.new_cipher = ec;
-            else
-                s->s3->tmp.new_cipher = s->session->cipher;
-        } else
-#endif
-            s->s3->tmp.new_cipher = s->session->cipher;
+        s->s3->tmp.new_cipher = s->session->cipher;
     }
 
     if (!SSL_USE_SIGALGS(s) || !(s->verify_mode & SSL_VERIFY_PEER)) {
@@ -1412,17 +1385,17 @@ int ssl3_get_client_hello(SSL *s)
             goto f_err;
     }
 
-        /*-
-         * we now have the following setup.
-         * client_random
-         * cipher_list          - our prefered list of ciphers
-         * ciphers              - the clients prefered list of ciphers
-         * compression          - basically ignored right now
-         * ssl version is set   - sslv3
-         * s->session           - The ssl session has been setup.
-         * s->hit               - session reuse flag
-         * s->s3->tmp.new_cipher- the new cipher to use.
-         */
+    /*-
+     * we now have the following setup.
+     * client_random
+     * cipher_list          - our prefered list of ciphers
+     * ciphers              - the clients prefered list of ciphers
+     * compression          - basically ignored right now
+     * ssl version is set   - sslv3
+     * s->session           - The ssl session has been setup.
+     * s->hit               - session reuse flag
+     * s->s3->tmp.new_cipher- the new cipher to use.
+     */
 
     /* Handles TLS extensions that we couldn't check earlier */
     if (s->version >= SSL3_VERSION) {
@@ -1469,22 +1442,22 @@ int ssl3_send_server_hello(SSL *s)
         memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE);
         p += SSL3_RANDOM_SIZE;
 
-                /*-
-                 * There are several cases for the session ID to send
-                 * back in the server hello:
-                 * - For session reuse from the session cache,
-                 *   we send back the old session ID.
-                 * - If stateless session reuse (using a session ticket)
-                 *   is successful, we send back the client's "session ID"
-                 *   (which doesn't actually identify the session).
-                 * - If it is a new session, we send back the new
-                 *   session ID.
-                 * - However, if we want the new session to be single-use,
-                 *   we send back a 0-length session ID.
-                 * s->hit is non-zero in either case of session reuse,
-                 * so the following won't overwrite an ID that we're supposed
-                 * to send back.
-                 */
+        /*-
+         * There are several cases for the session ID to send
+         * back in the server hello:
+         * - For session reuse from the session cache,
+         *   we send back the old session ID.
+         * - If stateless session reuse (using a session ticket)
+         *   is successful, we send back the client's "session ID"
+         *   (which doesn't actually identify the session).
+         * - If it is a new session, we send back the new
+         *   session ID.
+         * - However, if we want the new session to be single-use,
+         *   we send back a 0-length session ID.
+         * s->hit is non-zero in either case of session reuse,
+         * so the following won't overwrite an ID that we're supposed
+         * to send back.
+         */
         if (s->session->not_resumable ||
             (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)
              && !s->hit))
@@ -2054,20 +2027,10 @@ int ssl3_send_certificate_request(SSL *s)
                     goto err;
                 }
                 p = ssl_handshake_start(s) + n;
-                if (!(s->options & SSL_OP_NETSCAPE_CA_DN_BUG)) {
-                    s2n(j, p);
-                    i2d_X509_NAME(name, &p);
-                    n += 2 + j;
-                    nl += 2 + j;
-                } else {
-                    d = p;
-                    i2d_X509_NAME(name, &p);
-                    j -= 2;
-                    s2n(j, d);
-                    j += 2;
-                    n += j;
-                    nl += j;
-                }
+                s2n(j, p);
+                i2d_X509_NAME(name, &p);
+                n += 2 + j;
+                nl += 2 + j;
             }
         }
         /* else no CA names */
@@ -2076,22 +2039,6 @@ int ssl3_send_certificate_request(SSL *s)
 
         ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_REQUEST, n);
 
-#ifdef NETSCAPE_HANG_BUG
-        if (!SSL_IS_DTLS(s)) {
-            if (!BUF_MEM_grow_clean(buf, s->init_num + 4)) {
-                SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST, ERR_R_BUF_LIB);
-                goto err;
-            }
-            p = (unsigned char *)s->init_buf->data + s->init_num;
-            /* do the header */
-            *(p++) = SSL3_MT_SERVER_DONE;
-            *(p++) = 0;
-            *(p++) = 0;
-            *(p++) = 0;
-            s->init_num += 4;
-        }
-#endif
-
         s->state = SSL3_ST_SW_CERT_REQ_B;
     }
 
@@ -2540,11 +2487,11 @@ int ssl3_get_client_key_exchange(SSL *s)
             }
         }
 
-                /*- Was doing kssl_ctx_free() here,
-                 *  but it caused problems for apache.
-                 *  kssl_ctx = kssl_ctx_free(kssl_ctx);
-                 *  if (s->kssl_ctx)  s->kssl_ctx = NULL;
-                 */
+        /*- Was doing kssl_ctx_free() here,
+         *  but it caused problems for apache.
+         *  kssl_ctx = kssl_ctx_free(kssl_ctx);
+         *  if (s->kssl_ctx)  s->kssl_ctx = NULL;
+         */
     } else
 #endif                          /* OPENSSL_NO_KRB5 */
 
@@ -3309,14 +3256,16 @@ int ssl3_send_server_certificate(SSL *s)
 /* send a new session ticket (not necessarily for a new session) */
 int ssl3_send_newsession_ticket(SSL *s)
 {
+    unsigned char *senc = NULL;
+    EVP_CIPHER_CTX ctx;
+    HMAC_CTX hctx;
+
     if (s->state == SSL3_ST_SW_SESSION_TICKET_A) {
-        unsigned char *p, *senc, *macstart;
+        unsigned char *p, *macstart;
         const unsigned char *const_p;
         int len, slen_full, slen;
         SSL_SESSION *sess;
         unsigned int hlen;
-        EVP_CIPHER_CTX ctx;
-        HMAC_CTX hctx;
         SSL_CTX *tctx = s->initial_ctx;
         unsigned char iv[EVP_MAX_IV_LENGTH];
         unsigned char key_name[16];
@@ -3327,65 +3276,71 @@ int ssl3_send_newsession_ticket(SSL *s)
          * Some length values are 16 bits, so forget it if session is too
          * long
          */
-        if (slen_full > 0xFF00)
+        if (slen_full == 0 || slen_full > 0xFF00)
             return -1;
         senc = OPENSSL_malloc(slen_full);
         if (!senc)
             return -1;
+
+        EVP_CIPHER_CTX_init(&ctx);
+        HMAC_CTX_init(&hctx);
+
         p = senc;
-        i2d_SSL_SESSION(s->session, &p);
+        if (!i2d_SSL_SESSION(s->session, &p))
+            goto err;
 
         /*
          * create a fresh copy (not shared with other threads) to clean up
          */
         const_p = senc;
         sess = d2i_SSL_SESSION(NULL, &const_p, slen_full);
-        if (sess == NULL) {
-            OPENSSL_free(senc);
-            return -1;
-        }
+        if (sess == NULL)
+            goto err;
         sess->session_id_length = 0; /* ID is irrelevant for the ticket */
 
         slen = i2d_SSL_SESSION(sess, NULL);
-        if (slen > slen_full) { /* shouldn't ever happen */
-            OPENSSL_free(senc);
-            return -1;
+        if (slen == 0 || slen > slen_full) { /* shouldn't ever happen */
+            SSL_SESSION_free(sess);
+            goto err;
         }
         p = senc;
-        i2d_SSL_SESSION(sess, &p);
+        if (!i2d_SSL_SESSION(sess, &p)) {
+            SSL_SESSION_free(sess);
+            goto err;
+        }
         SSL_SESSION_free(sess);
 
-                /*-
-                 * Grow buffer if need be: the length calculation is as
-                 * follows handshake_header_length +
-                 * 4 (ticket lifetime hint) + 2 (ticket length) +
-                 * 16 (key name) + max_iv_len (iv length) +
-                 * session_length + max_enc_block_size (max encrypted session
-                 * length) + max_md_size (HMAC).
-                 */
+        /*-
+         * Grow buffer if need be: the length calculation is as
+         * follows handshake_header_length +
+         * 4 (ticket lifetime hint) + 2 (ticket length) +
+         * 16 (key name) + max_iv_len (iv length) +
+         * session_length + max_enc_block_size (max encrypted session
+         * length) + max_md_size (HMAC).
+         */
         if (!BUF_MEM_grow(s->init_buf,
                           SSL_HM_HEADER_LENGTH(s) + 22 + EVP_MAX_IV_LENGTH +
                           EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE + slen))
-            return -1;
+            goto err;
+
         p = ssl_handshake_start(s);
-        EVP_CIPHER_CTX_init(&ctx);
-        HMAC_CTX_init(&hctx);
         /*
          * Initialize HMAC and cipher contexts. If callback present it does
          * all the work otherwise use generated values from parent ctx.
          */
         if (tctx->tlsext_ticket_key_cb) {
             if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx,
-                                           &hctx, 1) < 0) {
-                OPENSSL_free(senc);
-                return -1;
-            }
+                                           &hctx, 1) < 0)
+                goto err;
         } else {
-            RAND_pseudo_bytes(iv, 16);
-            EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
-                               tctx->tlsext_tick_aes_key, iv);
-            HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
-                         tlsext_tick_md(), NULL);
+            if (RAND_bytes(iv, 16) <= 0)
+                goto err;
+            if (!EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
+                                    tctx->tlsext_tick_aes_key, iv))
+                goto err;
+            if (!HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
+                              EVP_sha256(), NULL))
+                goto err;
             memcpy(key_name, tctx->tlsext_tick_key_name, 16);
         }
 
@@ -3406,14 +3361,19 @@ int ssl3_send_newsession_ticket(SSL *s)
         memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx));
         p += EVP_CIPHER_CTX_iv_length(&ctx);
         /* Encrypt session data */
-        EVP_EncryptUpdate(&ctx, p, &len, senc, slen);
+        if (!EVP_EncryptUpdate(&ctx, p, &len, senc, slen))
+            goto err;
         p += len;
-        EVP_EncryptFinal(&ctx, p, &len);
+        if (!EVP_EncryptFinal(&ctx, p, &len))
+            goto err;
         p += len;
-        EVP_CIPHER_CTX_cleanup(&ctx);
 
-        HMAC_Update(&hctx, macstart, p - macstart);
-        HMAC_Final(&hctx, p, &hlen);
+        if (!HMAC_Update(&hctx, macstart, p - macstart))
+            goto err;
+        if (!HMAC_Final(&hctx, p, &hlen))
+            goto err;
+
+        EVP_CIPHER_CTX_cleanup(&ctx);
         HMAC_CTX_cleanup(&hctx);
 
         p += hlen;
@@ -3430,18 +3390,24 @@ int ssl3_send_newsession_ticket(SSL *s)
 
     /* SSL3_ST_SW_SESSION_TICKET_B */
     return ssl_do_write(s);
+ err:
+    if (senc)
+        OPENSSL_free(senc);
+    EVP_CIPHER_CTX_cleanup(&ctx);
+    HMAC_CTX_cleanup(&hctx);
+    return -1;
 }
 
 int ssl3_send_cert_status(SSL *s)
 {
     if (s->state == SSL3_ST_SW_CERT_STATUS_A) {
         unsigned char *p;
-                /*-
-                 * Grow buffer if need be: the length calculation is as
-                 * follows 1 (message type) + 3 (message length) +
-                 * 1 (ocsp response type) + 3 (ocsp response length)
-                 * + (ocsp response)
-                 */
+        /*-
+         * Grow buffer if need be: the length calculation is as
+         * follows 1 (message type) + 3 (message length) +
+         * 1 (ocsp response type) + 3 (ocsp response length)
+         * + (ocsp response)
+         */
         if (!BUF_MEM_grow(s->init_buf, 8 + s->tlsext_ocsp_resplen))
             return -1;
 
@@ -3513,13 +3479,13 @@ int ssl3_get_next_proto(SSL *s)
 
     p = (unsigned char *)s->init_msg;
 
-        /*-
-         * The payload looks like:
-         *   uint8 proto_len;
-         *   uint8 proto[proto_len];
-         *   uint8 padding_len;
-         *   uint8 padding[padding_len];
-         */
+    /*-
+     * The payload looks like:
+     *   uint8 proto_len;
+     *   uint8 proto[proto_len];
+     *   uint8 padding_len;
+     *   uint8 padding[padding_len];
+     */
     proto_len = p[0];
     if (proto_len + 2 > s->init_num)
         return 0;