[PATCH BlueZ v2 9/9] mesh: fix corrupted relay packets

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Currently, all relayed packets are broken!

At the point when net_key_encrypt() is called from net_rx() for
encrypting a relay packet, the packet size must include the NetMIC
field. But the length of this field has already been removed during
decryption of the incoming packet (by decrypt_net_pkt()), although
mesh_crypto_packet_decrypt() has correctly reset the NetMIC field to
zeroes.

Move stripping of the NetMIC field length from decrypt_net_pkt() to
mesh_crypto_packet_parse(), so that the field length is only stripped
from the payload message (but keeping the field length for the network
PDU). Additionally add extra length checks during parsing.
---
 mesh/crypto.c   | 21 +++++++++++++++++++++
 mesh/net-keys.c |  5 +----
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/mesh/crypto.c b/mesh/crypto.c
index 3dcf226ad8d3..a03dc9483862 100644
--- a/mesh/crypto.c
+++ b/mesh/crypto.c
@@ -637,6 +637,9 @@ bool mesh_crypto_packet_parse(const uint8_t *packet, uint8_t packet_len,
 	if (dst)
 		*dst = this_dst;
 
+	if (packet_len < 9 + 4)
+		return false;
+
 	hdr = l_get_be32(packet + 9);
 
 	is_segmented = !!((hdr >> SEG_HDR_SHIFT) & 0x1);
@@ -646,6 +649,9 @@ bool mesh_crypto_packet_parse(const uint8_t *packet, uint8_t packet_len,
 	if (*ctl) {
 		uint8_t this_opcode = packet[9] & OPCODE_MASK;
 
+		/* NetMIC */
+		packet_len -= 8;
+
 		if (cookie)
 			*cookie = l_get_be32(packet + 2) ^ packet[6];
 
@@ -660,13 +666,22 @@ bool mesh_crypto_packet_parse(const uint8_t *packet, uint8_t packet_len,
 				*seqZero = (hdr >> SEQ_ZERO_HDR_SHIFT) &
 								SEQ_ZERO_MASK;
 
+			if (packet_len < 9)
+				return false;
+
 			*payload = packet + 9;
 			*payload_len = packet_len - 9;
 		} else {
+			if (packet_len < 10)
+				return false;
+
 			*payload = packet + 10;
 			*payload_len = packet_len - 10;
 		}
 	} else {
+		/* NetMIC */
+		packet_len -= 4;
+
 		if (cookie)
 			*cookie = l_get_be32(packet + packet_len - 8);
 
@@ -687,9 +702,15 @@ bool mesh_crypto_packet_parse(const uint8_t *packet, uint8_t packet_len,
 			if (segN)
 				*segN = (hdr >> SEGN_HDR_SHIFT) & SEG_MASK;
 
+			if (packet_len < 13)
+				return false;
+
 			*payload = packet + 13;
 			*payload_len = packet_len - 13;
 		} else {
+			if (packet_len < 10)
+				return false;
+
 			*payload = packet + 10;
 			*payload_len = packet_len - 10;
 		}
diff --git a/mesh/net-keys.c b/mesh/net-keys.c
index 0daeb9209b86..98e6d23d3f87 100644
--- a/mesh/net-keys.c
+++ b/mesh/net-keys.c
@@ -238,10 +238,7 @@ static void decrypt_net_pkt(void *a, void *b)
 
 	if (result) {
 		cache_id = key->id;
-		if (cache_plain[1] & 0x80)
-			cache_plainlen = cache_len - 8;
-		else
-			cache_plainlen = cache_len - 4;
+		cache_plainlen = cache_len;
 	}
 }
 
-- 
2.43.0





[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux