PSK premaster secret derivation.
[openssl.git] / ssl / s3_lib.c
index efd96830b1c6cc65cfd9fb2c412f4c3f747c3a7a..e4c0f58c338763116271b4d45b52a7dd6ae503c1 100644 (file)
@@ -1612,6 +1612,40 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[] = {
      256,
      256,
      },
+#ifndef OPENSSL_NO_PSK
+    /* Cipher A8 */
+    {
+     1,
+     TLS1_TXT_PSK_WITH_AES_128_GCM_SHA256,
+     TLS1_CK_PSK_WITH_AES_128_GCM_SHA256,
+     SSL_kPSK,
+     SSL_aPSK,
+     SSL_AES128GCM,
+     SSL_AEAD,
+     SSL_TLSV1_2,
+     SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+     128,
+     128,
+     },
+
+    /* Cipher A9 */
+    {
+     1,
+     TLS1_TXT_PSK_WITH_AES_256_GCM_SHA384,
+     TLS1_CK_PSK_WITH_AES_256_GCM_SHA384,
+     SSL_kPSK,
+     SSL_aPSK,
+     SSL_AES256GCM,
+     SSL_AEAD,
+     SSL_TLSV1_2,
+     SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+     256,
+     256,
+     },
+
+#endif
 
 #ifndef OPENSSL_NO_CAMELLIA
     /* TLS 1.2 Camellia SHA-256 ciphersuites from RFC5932 */
@@ -2894,20 +2928,24 @@ void ssl3_free(SSL *s)
         return;
 
     ssl3_cleanup_key_block(s);
+
+#ifndef OPENSSL_NO_RSA
+    RSA_free(s->s3->peer_rsa_tmp);
+#endif
 #ifndef OPENSSL_NO_DH
     DH_free(s->s3->tmp.dh);
+    DH_free(s->s3->peer_dh_tmp);
 #endif
 #ifndef OPENSSL_NO_EC
     EC_KEY_free(s->s3->tmp.ecdh);
+    EC_KEY_free(s->s3->peer_ecdh_tmp);
 #endif
 
     sk_X509_NAME_pop_free(s->s3->tmp.ca_names, X509_NAME_free);
     OPENSSL_free(s->s3->tmp.ciphers_raw);
     OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen);
     OPENSSL_free(s->s3->tmp.peer_sigalgs);
-    BIO_free(s->s3->handshake_buffer);
-    if (s->s3->handshake_dgst)
-        ssl3_free_digest_list(s);
+    ssl3_free_digest_list(s);
     OPENSSL_free(s->s3->alpn_selected);
 
 #ifndef OPENSSL_NO_SRP
@@ -2930,25 +2968,30 @@ void ssl3_clear(SSL *s)
     OPENSSL_free(s->s3->tmp.peer_sigalgs);
     s->s3->tmp.peer_sigalgs = NULL;
 
+#ifndef OPENSSL_NO_RSA
+    RSA_free(s->s3->peer_rsa_tmp);
+    s->s3->peer_rsa_tmp = NULL;
+#endif
+
 #ifndef OPENSSL_NO_DH
     DH_free(s->s3->tmp.dh);
     s->s3->tmp.dh = NULL;
+    DH_free(s->s3->peer_dh_tmp);
+    s->s3->peer_dh_tmp = NULL;
 #endif
 #ifndef OPENSSL_NO_EC
     EC_KEY_free(s->s3->tmp.ecdh);
     s->s3->tmp.ecdh = NULL;
+    EC_KEY_free(s->s3->peer_ecdh_tmp);
+    s->s3->peer_ecdh_tmp = NULL;
     s->s3->is_probably_safari = 0;
 #endif                         /* !OPENSSL_NO_EC */
 
     init_extra = s->s3->init_extra;
-    BIO_free(s->s3->handshake_buffer);
-    s->s3->handshake_buffer = NULL;
-    if (s->s3->handshake_dgst) {
-        ssl3_free_digest_list(s);
-    }
+    ssl3_free_digest_list(s);
 
     if (s->s3->alpn_selected) {
-        free(s->s3->alpn_selected);
+        OPENSSL_free(s->s3->alpn_selected);
         s->s3->alpn_selected = NULL;
     }
 
@@ -3315,7 +3358,7 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
 
     case SSL_CTRL_GET_PEER_SIGNATURE_NID:
         if (SSL_USE_SIGALGS(s)) {
-            if (s->session && s->session->sess_cert) {
+            if (s->session) {
                 const EVP_MD *sig;
                 sig = s->s3->tmp.peer_md;
                 if (sig) {
@@ -3330,31 +3373,29 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
             return 0;
 
     case SSL_CTRL_GET_SERVER_TMP_KEY:
-        if (s->server || !s->session || !s->session->sess_cert)
+        if (s->server || !s->session)
             return 0;
         else {
-            SESS_CERT *sc;
             EVP_PKEY *ptmp;
             int rv = 0;
-            sc = s->session->sess_cert;
 #if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_EC)
-            if (!sc->peer_rsa_tmp && !sc->peer_dh_tmp && !sc->peer_ecdh_tmp)
+            if (!s->s3->peer_rsa_tmp && !s->s3->peer_dh_tmp && !s->s3->peer_ecdh_tmp)
                 return 0;
 #endif
             ptmp = EVP_PKEY_new();
             if (!ptmp)
                 return 0;
 #ifndef OPENSSL_NO_RSA
-            else if (sc->peer_rsa_tmp)
-                rv = EVP_PKEY_set1_RSA(ptmp, sc->peer_rsa_tmp);
+            else if (s->s3->peer_rsa_tmp)
+                rv = EVP_PKEY_set1_RSA(ptmp, s->s3->peer_rsa_tmp);
 #endif
 #ifndef OPENSSL_NO_DH
-            else if (sc->peer_dh_tmp)
-                rv = EVP_PKEY_set1_DH(ptmp, sc->peer_dh_tmp);
+            else if (s->s3->peer_dh_tmp)
+                rv = EVP_PKEY_set1_DH(ptmp, s->s3->peer_dh_tmp);
 #endif
 #ifndef OPENSSL_NO_EC
-            else if (sc->peer_ecdh_tmp)
-                rv = EVP_PKEY_set1_EC_KEY(ptmp, sc->peer_ecdh_tmp);
+            else if (s->s3->peer_ecdh_tmp)
+                rv = EVP_PKEY_set1_EC_KEY(ptmp, s->s3->peer_ecdh_tmp);
 #endif
             if (rv) {
                 *(EVP_PKEY **)parg = ptmp;
@@ -3892,7 +3933,7 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
 
 #ifndef OPENSSL_NO_PSK
         /* with PSK there must be server callback set */
-        if ((alg_k & SSL_kPSK) && s->psk_server_callback == NULL)
+        if ((alg_k & SSL_PSK) && s->psk_server_callback == NULL)
             continue;
 #endif                          /* OPENSSL_NO_PSK */
 
@@ -4090,54 +4131,12 @@ int ssl3_shutdown(SSL *s)
 
 int ssl3_write(SSL *s, const void *buf, int len)
 {
-    int ret, n;
-
-#if 0
-    if (s->shutdown & SSL_SEND_SHUTDOWN) {
-        s->rwstate = SSL_NOTHING;
-        return (0);
-    }
-#endif
     clear_sys_error();
     if (s->s3->renegotiate)
         ssl3_renegotiate_check(s);
 
-    /*
-     * This is an experimental flag that sends the last handshake message in
-     * the same packet as the first use data - used to see if it helps the
-     * TCP protocol during session-id reuse
-     */
-    /* The second test is because the buffer may have been removed */
-    if ((s->s3->flags & SSL3_FLAGS_POP_BUFFER) && (s->wbio == s->bbio)) {
-        /* First time through, we write into the buffer */
-        if (s->s3->delay_buf_pop_ret == 0) {
-            ret = ssl3_write_bytes(s, SSL3_RT_APPLICATION_DATA, buf, len);
-            if (ret <= 0)
-                return (ret);
-
-            s->s3->delay_buf_pop_ret = ret;
-        }
-
-        s->rwstate = SSL_WRITING;
-        n = BIO_flush(s->wbio);
-        if (n <= 0)
-            return (n);
-        s->rwstate = SSL_NOTHING;
-
-        /* We have flushed the buffer, so remove it */
-        ssl_free_wbio_buffer(s);
-        s->s3->flags &= ~SSL3_FLAGS_POP_BUFFER;
-
-        ret = s->s3->delay_buf_pop_ret;
-        s->s3->delay_buf_pop_ret = 0;
-    } else {
-        ret = s->method->ssl_write_bytes(s, SSL3_RT_APPLICATION_DATA,
+    return s->method->ssl_write_bytes(s, SSL3_RT_APPLICATION_DATA,
                                          buf, len);
-        if (ret <= 0)
-            return (ret);
-    }
-
-    return (ret);
 }
 
 static int ssl3_read_internal(SSL *s, void *buf, int len, int peek)
@@ -4218,13 +4217,19 @@ int ssl3_renegotiate_check(SSL *s)
 /*
  * If we are using default SHA1+MD5 algorithms switch to new SHA256 PRF and
  * handshake macs if required.
+ *
+ * If PSK and using SHA384 for TLS < 1.2 switch to default.
  */
 long ssl_get_algorithm2(SSL *s)
 {
     long alg2 = s->s3->tmp.new_cipher->algorithm2;
-    if (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_SHA256_PRF
-        && alg2 == (SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF))
-        return SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256;
+    if (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_SHA256_PRF) {
+        if (alg2 == (SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF))
+            return SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256;
+    } else if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK) {
+        if (alg2 == (SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384))
+            return SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF;
+    }
     return alg2;
 }
 
@@ -4250,3 +4255,57 @@ int ssl_fill_hello_random(SSL *s, int server, unsigned char *result, int len)
     } else
         return RAND_bytes(result, len);
 }
+
+int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen,
+                               int free_pms)
+{
+#ifndef OPENSSL_NO_PSK
+    unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+    if (alg_k & SSL_PSK) {
+        unsigned char *pskpms, *t;
+        size_t psklen = s->s3->tmp.psklen;
+        size_t pskpmslen;
+
+        /* create PSK premaster_secret */
+
+        /* For plain PSK "other_secret" is psklen zeroes */
+        if (alg_k & SSL_kPSK)
+            pmslen = psklen;
+
+        pskpmslen = 4 + pmslen + psklen;
+        pskpms = OPENSSL_malloc(pskpmslen);
+        if (pskpms == NULL)
+            return 0;
+        t = pskpms;
+        s2n(pmslen, t);
+        if (alg_k & SSL_kPSK)
+            memset(t, 0, pmslen);
+        else
+            memcpy(t, pms, pmslen);
+        t += pmslen;
+        s2n(psklen, t);
+        memcpy(t, s->s3->tmp.psk, psklen);
+
+        OPENSSL_clear_free(s->s3->tmp.psk, psklen);
+        s->s3->tmp.psk = NULL;
+        s->session->master_key_length =
+            s->method->ssl3_enc->generate_master_secret(s,
+                                                        s->session->master_key,
+                                                        pskpms, pskpmslen);
+        OPENSSL_clear_free(pskpms, pskpmslen);
+    } else
+#endif
+        s->session->master_key_length =
+            s->method->ssl3_enc->generate_master_secret(s,
+                                                        s->session->master_key,
+                                                        pms, pmslen);
+    if (pms) {
+        if (free_pms)
+            OPENSSL_clear_free(pms, pmslen);
+        else
+            OPENSSL_cleanse(pms, pmslen);
+    }
+    if (s->server == 0)
+        s->s3->tmp.pms = NULL;
+    return s->session->master_key_length >= 0;
+}