Parcourir la source

TLS: Validate RSA ClientKeyExchange length field

Instead of using implicit length based on the received buffer, validate
RSA ClientKeyExchange based on the explicit length field.
Jouni Malinen il y a 13 ans
Parent
commit
3803bd331d
1 fichiers modifiés avec 13 ajouts et 5 suppressions
  1. 13 5
      src/tls/tlsv1_server_read.c

+ 13 - 5
src/tls/tlsv1_server_read.c

@@ -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");