Bluetooth: BAP: Broadcast source: Add LTV validation for LC3 data

When using the LC3 codec, all codec configuration are LTV encoded.
The broadcast source did not properly validate this, and it also
uncovered a bug in the bsim test for broadcast sources.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
diff --git a/subsys/bluetooth/audio/bap_broadcast_source.c b/subsys/bluetooth/audio/bap_broadcast_source.c
index 4b7ca89..1b4993c 100644
--- a/subsys/bluetooth/audio/bap_broadcast_source.c
+++ b/subsys/bluetooth/audio/bap_broadcast_source.c
@@ -578,6 +578,7 @@
 				return false;
 			}
 
+#if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0
 			CHECKIF(stream_param->data == NULL && stream_param->data_len != 0) {
 				LOG_DBG("subgroup_params[%zu].stream_params[%zu]->data is "
 					"NULL with len %zu",
@@ -585,7 +586,6 @@
 				return false;
 			}
 
-#if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0
 			CHECKIF(stream_param->data_len > CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE) {
 				LOG_DBG("subgroup_params[%zu].stream_params[%zu]->data_len too "
 					"large: %zu > %d",
@@ -593,6 +593,14 @@
 					CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE);
 				return false;
 			}
+
+			CHECKIF(subgroup_param->codec_cfg->id == BT_HCI_CODING_FORMAT_LC3 &&
+				!bt_audio_valid_ltv(stream_param->data, stream_param->data_len)) {
+				LOG_DBG("subgroup_params[%zu].stream_params[%zu]->data not valid "
+					"LTV",
+					i, j);
+				return false;
+			}
 		}
 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 */
 	}
diff --git a/subsys/bluetooth/audio/bap_stream.c b/subsys/bluetooth/audio/bap_stream.c
index 2f1cf71..1e132c5 100644
--- a/subsys/bluetooth/audio/bap_stream.c
+++ b/subsys/bluetooth/audio/bap_stream.c
@@ -180,6 +180,17 @@
 	return BT_BAP_ASCS_REASON_NONE;
 }
 
+static bool valid_ltv_cb(struct bt_data *data, void *user_data)
+{
+	/* just return true to continue parsing as bt_data_parse will validate for us */
+	return true;
+}
+
+bool bt_audio_valid_ltv(const uint8_t *data, uint8_t data_len)
+{
+	return bt_audio_data_parse(data, data_len, valid_ltv_cb, NULL) == 0;
+}
+
 bool bt_audio_valid_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg)
 {
 	if (codec_cfg == NULL) {
@@ -212,6 +223,12 @@
 		LOG_DBG("codec_cfg->data_len (%zu) is invalid", codec_cfg->data_len);
 		return false;
 	}
+
+	if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3 &&
+	    !bt_audio_valid_ltv(codec_cfg->data, codec_cfg->data_len)) {
+		LOG_DBG("codec_cfg->data not valid LTV");
+		return false;
+	}
 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 */
 
 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0
@@ -219,6 +236,12 @@
 		LOG_DBG("codec_cfg->meta_len (%zu) is invalid", codec_cfg->meta_len);
 		return false;
 	}
+
+	if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3 &&
+	    !bt_audio_valid_ltv(codec_cfg->data, codec_cfg->data_len)) {
+		LOG_DBG("codec_cfg->meta not valid LTV");
+		return false;
+	}
 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0 */
 
 	return true;
diff --git a/subsys/bluetooth/audio/bap_stream.h b/subsys/bluetooth/audio/bap_stream.h
index d16cf2c..3d02c2c 100644
--- a/subsys/bluetooth/audio/bap_stream.h
+++ b/subsys/bluetooth/audio/bap_stream.h
@@ -23,6 +23,7 @@
 void bt_bap_stream_detach(struct bt_bap_stream *stream);
 
 enum bt_bap_ascs_reason bt_audio_verify_qos(const struct bt_audio_codec_qos *qos);
+bool bt_audio_valid_ltv(const uint8_t *data, uint8_t data_len);
 bool bt_audio_valid_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg);
 bool bt_bap_stream_can_disconnect(const struct bt_bap_stream *stream);
 
diff --git a/tests/bluetooth/audio/bap_broadcast_source/uut/CMakeLists.txt b/tests/bluetooth/audio/bap_broadcast_source/uut/CMakeLists.txt
index 85f68a6..aea487e 100644
--- a/tests/bluetooth/audio/bap_broadcast_source/uut/CMakeLists.txt
+++ b/tests/bluetooth/audio/bap_broadcast_source/uut/CMakeLists.txt
@@ -7,6 +7,7 @@
 #
 
 add_library(uut STATIC
+  ${ZEPHYR_BASE}/subsys/bluetooth/audio/audio.c
   ${ZEPHYR_BASE}/subsys/bluetooth/audio/bap_iso.c
   ${ZEPHYR_BASE}/subsys/bluetooth/audio/bap_stream.c
   ${ZEPHYR_BASE}/subsys/bluetooth/audio/bap_broadcast_source.c
diff --git a/tests/bsim/bluetooth/audio/src/bap_broadcast_source_test.c b/tests/bsim/bluetooth/audio/src/bap_broadcast_source_test.c
index cd5800c..ccd26af 100644
--- a/tests/bsim/bluetooth/audio/src/bap_broadcast_source_test.c
+++ b/tests/bsim/bluetooth/audio/src/bap_broadcast_source_test.c
@@ -97,8 +97,8 @@
 static int setup_broadcast_source(struct bt_bap_broadcast_source **source)
 {
 	uint8_t bis_codec_data[] = {
-		BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CFG_FREQ,
-				    BT_BYTES_LIST_LE16(BT_AUDIO_CODEC_CFG_FREQ_16KHZ)),
+		BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CFG_CHAN_ALLOC,
+				    BT_BYTES_LIST_LE32(BT_AUDIO_LOCATION_FRONT_LEFT)),
 	};
 	struct bt_bap_broadcast_source_stream_param
 		stream_params[ARRAY_SIZE(broadcast_source_streams)];