Add the ability for a server to receive a KeyUpdate message
[openssl.git] / ssl / statem / statem_srvr.c
index a251a6ff8cc41b8105aebfd64996a738a458ffbe..2a210010862e6a188a383c43c1d119d437ecd0f3 100644 (file)
@@ -132,6 +132,13 @@ static int ossl_statem_server13_read_transition(SSL *s, int mt)
             return 1;
         }
         break;
+
+    case TLS_ST_OK:
+        if (mt == SSL3_MT_KEY_UPDATE) {
+            st->hand_state = TLS_ST_SR_KEY_UPDATE;
+            return 1;
+        }
+        break;
     }
 
     /* No valid transition found */
@@ -393,11 +400,6 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s)
 {
     OSSL_STATEM *st = &s->statem;
 
-    /*
-     * TODO(TLS1.3): This is still based on the TLSv1.2 state machine. Over time
-     * we will update this to look more like real TLSv1.3
-     */
-
     /*
      * No case for TLS_ST_BEFORE, because at that stage we have not negotiated
      * TLSv1.3 yet, so that is handled by ossl_statem_server_write_transition()
@@ -408,6 +410,14 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s)
         /* Shouldn't happen */
         return WRITE_TRAN_ERROR;
 
+    case TLS_ST_OK:
+        if (s->key_update != SSL_KEY_UPDATE_NONE) {
+            st->hand_state = TLS_ST_SW_KEY_UPDATE;
+            return WRITE_TRAN_CONTINUE;
+        }
+        /* Try to read from the client instead */
+        return WRITE_TRAN_FINISHED;
+
     case TLS_ST_SR_CLNT_HELLO:
         if (s->hello_retry_request)
             st->hand_state = TLS_ST_SW_HELLO_RETRY_REQUEST;
@@ -459,6 +469,8 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s)
         st->hand_state = TLS_ST_SW_SESSION_TICKET;
         return WRITE_TRAN_CONTINUE;
 
+    case TLS_ST_SR_KEY_UPDATE:
+    case TLS_ST_SW_KEY_UPDATE:
     case TLS_ST_SW_SESSION_TICKET:
         st->hand_state = TLS_ST_OK;
         ossl_statem_set_in_init(s, 0);
@@ -822,6 +834,7 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
         }
         break;
 
+    case TLS_ST_SW_KEY_UPDATE:
     case TLS_ST_SW_SESSION_TICKET:
         if (SSL_IS_TLS13(s) && statem_flush(s) != 1)
             return WORK_MORE_A;
@@ -923,6 +936,11 @@ int ossl_statem_server_construct_message(SSL *s, WPACKET *pkt,
         *confunc = tls_construct_hello_retry_request;
         *mt = SSL3_MT_HELLO_RETRY_REQUEST;
         break;
+
+    case TLS_ST_SW_KEY_UPDATE:
+        *confunc = tls_construct_key_update;
+        *mt = SSL3_MT_KEY_UPDATE;
+        break;
     }
 
     return 1;
@@ -983,6 +1001,9 @@ size_t ossl_statem_server_max_message_size(SSL *s)
 
     case TLS_ST_SR_FINISHED:
         return FINISHED_MAX_LENGTH;
+
+    case TLS_ST_SR_KEY_UPDATE:
+        return KEY_UPDATE_MAX_LENGTH;
     }
 }
 
@@ -1020,6 +1041,10 @@ MSG_PROCESS_RETURN ossl_statem_server_process_message(SSL *s, PACKET *pkt)
 
     case TLS_ST_SR_FINISHED:
         return tls_process_finished(s, pkt);
+
+    case TLS_ST_SR_KEY_UPDATE:
+        return tls_process_key_update(s, pkt);
+
     }
 }
 
@@ -1761,12 +1786,12 @@ static int tls_handle_status_request(SSL *s, int *al)
         int ret;
 
         /* If no certificate can't return certificate status */
-        if (s->s3->tmp.cert_idx != -1) {
+        if (s->s3->tmp.cert != NULL) {
             /*
              * Set current certificate to one we will use so SSL_get_certificate
              * et al can pick it up.
              */
-            s->cert->key = &s->cert->pkeys[s->s3->tmp.cert_idx];
+            s->cert->key = s->s3->tmp.cert;
             ret = s->ctx->ext.status_cb(s, s->ctx->ext.status_arg);
             switch (ret) {
                 /* We don't want to send a status request response */
@@ -2249,7 +2274,7 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
 
     /* not anonymous */
     if (lu != NULL) {
-        EVP_PKEY *pkey = s->cert->pkeys[s->s3->tmp.cert_idx].privatekey;
+        EVP_PKEY *pkey = s->s3->tmp.cert->privatekey;
         const EVP_MD *md = ssl_md(lu->hash_idx);
         unsigned char *sigbytes1, *sigbytes2;
         size_t siglen;
@@ -3197,14 +3222,13 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
 
 int tls_construct_server_certificate(SSL *s, WPACKET *pkt)
 {
-    CERT_PKEY *cpk;
+    CERT_PKEY *cpk = s->s3->tmp.cert;
     int al = SSL_AD_INTERNAL_ERROR;
 
-    if (s->s3->tmp.cert_idx == -1) {
+    if (cpk == NULL) {
         SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
         return 0;
     }
-    cpk = &s->cert->pkeys[s->s3->tmp.cert_idx];
 
     /*
      * In TLSv1.3 the certificate chain is always preceded by a 0 length context