]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
TLS: Validate RSA ClientKeyExchange length field
authorJouni Malinen <j@w1.fi>
Sun, 23 Oct 2011 10:04:32 +0000 (13:04 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 23 Oct 2011 10:04:32 +0000 (13:04 +0300)
Instead of using implicit length based on the received buffer, validate
RSA ClientKeyExchange based on the explicit length field.

src/tls/tlsv1_server_read.c

index 5b7ccc39b0f5738bba85e9bd8d443c63dc3f2b29..9ffe05c5065518200d34355117c1d97f845b2a57 100644 (file)
@@ -494,6 +494,14 @@ static int tls_process_client_key_exchange_rsa(
 
        encr_len = WPA_GET_BE16(pos);
        pos += 2;
+       if (pos + encr_len > end) {
+               wpa_printf(MSG_DEBUG, "TLSv1: Invalid ClientKeyExchange "
+                          "format: encr_len=%u left=%u",
+                          encr_len, (unsigned int) (end - pos));
+               tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
+                                  TLS_ALERT_DECODE_ERROR);
+               return -1;
+       }
 
        outbuflen = outlen = end - pos;
        out = os_malloc(outlen >= TLS_PRE_MASTER_SECRET_LEN ?
@@ -523,21 +531,21 @@ static int tls_process_client_key_exchange_rsa(
         */
 
        if (crypto_private_key_decrypt_pkcs1_v15(conn->cred->key,
-                                                pos, end - pos,
+                                                pos, encr_len,
                                                 out, &outlen) < 0) {
                wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt "
-                          "PreMasterSecret (encr_len=%d outlen=%lu)",
-                          (int) (end - pos), (unsigned long) outlen);
+                          "PreMasterSecret (encr_len=%u outlen=%lu)",
+                          encr_len, (unsigned long) outlen);
                use_random = 1;
        }
 
-       if (outlen != TLS_PRE_MASTER_SECRET_LEN) {
+       if (!use_random && outlen != TLS_PRE_MASTER_SECRET_LEN) {
                wpa_printf(MSG_DEBUG, "TLSv1: Unexpected PreMasterSecret "
                           "length %lu", (unsigned long) outlen);
                use_random = 1;
        }
 
-       if (WPA_GET_BE16(out) != conn->client_version) {
+       if (!use_random && WPA_GET_BE16(out) != conn->client_version) {
                wpa_printf(MSG_DEBUG, "TLSv1: Client version in "
                           "ClientKeyExchange does not match with version in "
                           "ClientHello");