Add the ability for a server to receive a KeyUpdate message
[oweals/openssl.git] / ssl / ssl_lib.c
index 5bc4c404ce7971f6725a74298e0ce04d1a67ddec..927d70a6a6011c6928f27e883b907b0963d03aca 100644 (file)
@@ -471,6 +471,8 @@ int SSL_clear(SSL *s)
     clear_ciphers(s);
     s->first_packet = 0;
 
+    s->key_update = SSL_KEY_UPDATE_NONE;
+
     /* Reset DANE verification result state */
     s->dane.mdpth = -1;
     s->dane.pdpth = -1;
@@ -639,6 +641,8 @@ SSL *SSL_new(SSL_CTX *ctx)
 
     s->method = ctx->method;
 
+    s->key_update = SSL_KEY_UPDATE_NONE;
+
     if (!s->method->ssl_new(s))
         goto err;
 
@@ -1714,14 +1718,42 @@ int SSL_shutdown(SSL *s)
     }
 }
 
+int SSL_key_update(SSL *s, SSL_KEY_UPDATE updatetype)
+{
+    if (!SSL_IS_TLS13(s)) {
+        SSLerr(SSL_F_SSL_KEY_UPDATE, SSL_R_WRONG_SSL_VERSION);
+        return 0;
+    }
+
+    if (updatetype != SSL_KEY_UPDATE_NOT_REQUESTED
+            && updatetype != SSL_KEY_UPDATE_REQUESTED) {
+        SSLerr(SSL_F_SSL_KEY_UPDATE, SSL_R_INVALID_KEY_UPDATE_TYPE);
+        return 0;
+    }
+
+    if (!SSL_is_init_finished(s)) {
+        SSLerr(SSL_F_SSL_KEY_UPDATE, SSL_R_STILL_IN_INIT);
+        return 0;
+    }
+
+    ossl_statem_set_in_init(s, 1);
+
+    s->key_update = updatetype;
+
+    return 1;
+}
+
+SSL_KEY_UPDATE SSL_get_key_update_type(SSL *s)
+{
+    return s->key_update;
+}
+
 int SSL_renegotiate(SSL *s)
 {
-    /*
-     * TODO(TLS1.3): Return an error for now. Perhaps we should do a KeyUpdate
-     * instead when we support that?
-     */
-    if (SSL_IS_TLS13(s))
+    if (SSL_IS_TLS13(s)) {
+        SSLerr(SSL_F_SSL_RENEGOTIATE, SSL_R_WRONG_SSL_VERSION);
         return 0;
+    }
 
     if (s->renegotiate == 0)
         s->renegotiate = 1;
@@ -1733,10 +1765,6 @@ int SSL_renegotiate(SSL *s)
 
 int SSL_renegotiate_abbreviated(SSL *s)
 {
-    /*
-     * TODO(TLS1.3): Return an error for now. Perhaps we should do a KeyUpdate
-     * instead when we support that?
-     */
     if (SSL_IS_TLS13(s))
         return 0;
 
@@ -2836,20 +2864,14 @@ int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s)
 int ssl_get_server_cert_serverinfo(SSL *s, const unsigned char **serverinfo,
                                    size_t *serverinfo_length)
 {
-    CERT *c = NULL;
-    int i = 0;
+    CERT_PKEY *cpk = s->s3->tmp.cert;
     *serverinfo_length = 0;
 
-    c = s->cert;
-    i = s->s3->tmp.cert_idx;
-
-    if (i == -1)
-        return 0;
-    if (c->pkeys[i].serverinfo == NULL)
+    if (cpk == NULL || cpk->serverinfo == NULL)
         return 0;
 
-    *serverinfo = c->pkeys[i].serverinfo;
-    *serverinfo_length = c->pkeys[i].serverinfo_length;
+    *serverinfo = cpk->serverinfo;
+    *serverinfo_length = cpk->serverinfo_length;
     return 1;
 }