[PATCH BlueZ 2/5] shared/att.c: Add server signing key support

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

 



From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx>

This adds support for setting remote signing keys along with a callback
for validating the counter.
---
 src/shared/att.c | 92 +++++++++++++++++++++++++++++++++++++++++---------------
 src/shared/att.h |  2 ++
 2 files changed, 70 insertions(+), 24 deletions(-)

diff --git a/src/shared/att.c b/src/shared/att.c
index 4bfae5f..aa06dc6 100644
--- a/src/shared/att.c
+++ b/src/shared/att.c
@@ -93,6 +93,7 @@ struct bt_att {
 	struct bt_crypto *crypto;
 
 	struct sign_info *local_sign;
+	struct sign_info *remote_sign;
 };
 
 struct sign_info {
@@ -686,21 +687,6 @@ static bool opcode_match(uint8_t opcode, uint8_t test_opcode)
 	return opcode == test_opcode;
 }
 
-static void notify_handler(void *data, void *user_data)
-{
-	struct att_notify *notify = data;
-	struct notify_data *not_data = user_data;
-
-	if (!opcode_match(notify->opcode, not_data->opcode))
-		return;
-
-	not_data->handler_found = true;
-
-	if (notify->callback)
-		notify->callback(not_data->opcode, not_data->pdu,
-					not_data->pdu_len, notify->user_data);
-}
-
 static void respond_not_supported(struct bt_att *att, uint8_t opcode)
 {
 	uint8_t pdu[4];
@@ -714,28 +700,76 @@ static void respond_not_supported(struct bt_att *att, uint8_t opcode)
 									NULL);
 }
 
+static bool handle_signed(struct bt_att *att, uint8_t opcode, uint8_t *pdu,
+								ssize_t pdu_len)
+{
+	uint8_t *signature;
+	uint32_t sign_cnt;
+	struct sign_info *sign;
+
+	/* Check if there is enough data for a signature */
+	if (pdu_len < 2 + BT_ATT_SIGNATURE_LEN)
+		goto fail;
+
+	sign = att->remote_sign;
+	if (!sign)
+		goto fail;
+
+	signature = pdu + (pdu_len - BT_ATT_SIGNATURE_LEN);
+	sign_cnt = get_le32(signature);
+
+	/* Validate counter */
+	if (!sign->counter(&sign_cnt, sign->user_data))
+		goto fail;
+
+	/* Generate signature and verify it */
+	if (!bt_crypto_sign_att(att->crypto, sign->key, pdu,
+				pdu_len - BT_ATT_SIGNATURE_LEN, sign_cnt,
+				signature))
+		goto fail;
+
+	return true;
+
+fail:
+	util_debug(att->debug_callback, att->debug_data,
+			"ATT failed to verify signature: 0x%02x", opcode);
+
+	return false;
+}
+
 static void handle_notify(struct bt_att *att, uint8_t opcode, uint8_t *pdu,
 								ssize_t pdu_len)
 {
-	struct notify_data data;
+	const struct queue_entry *entry;
+	bool found;
+
+	if (opcode & ATT_OP_SIGNED_MASK) {
+		if (!handle_signed(att, opcode, pdu, pdu_len))
+			return;
+		pdu_len -= BT_ATT_SIGNATURE_LEN;
+	}
 
 	bt_att_ref(att);
 
-	memset(&data, 0, sizeof(data));
-	data.opcode = opcode;
+	for (found = false, entry = queue_get_entries(att->notify_list); entry;
+							entry = entry->next) {
+		struct att_notify *notify = entry->data;
 
-	if (pdu_len > 0) {
-		data.pdu = pdu;
-		data.pdu_len = pdu_len;
-	}
+		if (!opcode_match(notify->opcode, opcode))
+			continue;
+
+		found = true;
 
-	queue_foreach(att->notify_list, notify_handler, &data);
+		if (notify->callback)
+			notify->callback(opcode, pdu, pdu_len,
+							notify->user_data);
+	}
 
 	/*
 	 * If this was a request and no handler was registered for it, respond
 	 * with "Not Supported"
 	 */
-	if (!data.handler_found && get_op_type(opcode) == ATT_OP_TYPE_REQ)
+	if (!found && get_op_type(opcode) == ATT_OP_TYPE_REQ)
 		respond_not_supported(att, opcode);
 
 	bt_att_unref(att);
@@ -862,6 +896,7 @@ static void bt_att_free(struct bt_att *att)
 		att->debug_destroy(att->debug_data);
 
 	free(att->local_sign);
+	free(att->remote_sign);
 
 	free(att->buf);
 
@@ -1376,3 +1411,12 @@ bool bt_att_set_local_key(struct bt_att *att, uint8_t sign_key[16],
 
 	return sign_set_key(&att->local_sign, sign_key, func, user_data);
 }
+
+bool bt_att_set_remote_key(struct bt_att *att, uint8_t sign_key[16],
+				bt_att_counter_func_t func, void *user_data)
+{
+	if (!att)
+		return false;
+
+	return sign_set_key(&att->remote_sign, sign_key, func, user_data);
+}
diff --git a/src/shared/att.h b/src/shared/att.h
index 0cd1a4c..a440aaf 100644
--- a/src/shared/att.h
+++ b/src/shared/att.h
@@ -88,3 +88,5 @@ bool bt_att_set_sec_level(struct bt_att *att, int level);
 
 bool bt_att_set_local_key(struct bt_att *att, uint8_t sign_key[16],
 			bt_att_counter_func_t func, void *user_data);
+bool bt_att_set_remote_key(struct bt_att *att, uint8_t sign_key[16],
+			bt_att_counter_func_t func, void *user_data);
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[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