[PATCH BlueZ v2 1/3] src: add HMAC-SHA256 to bt_crypto using kernel AF_ALG

Pakrohk <[email protected]>
Newsgroups org.kernel.vger.linux-bluetooth
Message-ID <[email protected]>
From: Pakrohk <[email protected]>

Add HMAC-SHA256 computation to the bt_crypto library using the Linux
kernel AF_ALG interface. This follows the exact same pattern as the
existing cmac(aes) implementation.

The HMAC-SHA256 function is needed for verifying external quirk profile
signatures. The previous implementation used popen("openssl dgst ...")
which had command injection risks and an openssl CLI dependency.

Using kernel AF_ALG:
  - No external library dependencies
  - Matches existing BlueZ crypto patterns
  - No shell invocation or temp files
  - Works in bluetoothd's process context

The hmac(sha256) algorithm is available in all modern Linux kernels
via the crypto API (/proc/crypto).

Signed-off-by: Pakrohk <[email protected]>
diff --git a/src/shared/crypto.c b/src/shared/crypto.c
index cb99116..f5883bd 100644
--- a/src/shared/crypto.c
+++ b/src/shared/crypto.c
@@ -69,6 +69,7 @@ struct bt_crypto {
 	int ecb_aes;
 	int urandom;
 	int cmac_aes;
+	int hmac_sha256;
 };
 
 static int urandom_setup(void)
@@ -126,6 +127,28 @@ static int cmac_aes_setup(void)
 	return fd;
 }
 
+static int hmac_sha256_setup(void)
+{
+	struct sockaddr_alg salg;
+	int fd;
+
+	fd = socket(PF_ALG, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
+	if (fd < 0)
+		return -1;
+
+	memset(&salg, 0, sizeof(salg));
+	salg.salg_family = AF_ALG;
+	strcpy((char *) salg.salg_type, "hash");
+	strcpy((char *) salg.salg_name, "hmac(sha256)");
+
+	if (bind(fd, (struct sockaddr *) &salg, sizeof(salg)) < 0) {
+		close(fd);
+		return -1;
+	}
+
+	return fd;
+}
+
 static struct bt_crypto *singleton;
 
 struct bt_crypto *bt_crypto_new(void)
@@ -159,6 +182,16 @@ struct bt_crypto *bt_crypto_new(void)
 		return NULL;
 	}
 
+	singleton->hmac_sha256 = hmac_sha256_setup();
+	if (singleton->hmac_sha256 < 0) {
+		close(singleton->cmac_aes);
+		close(singleton->urandom);
+		close(singleton->ecb_aes);
+		free(singleton);
+		singleton = NULL;
+		return NULL;
+	}
+
 	return bt_crypto_ref(singleton);
 }
 
@@ -183,6 +216,7 @@ void bt_crypto_unref(struct bt_crypto *crypto)
 	close(crypto->urandom);
 	close(crypto->ecb_aes);
 	close(crypto->cmac_aes);
+	close(crypto->hmac_sha256);
 
 	free(crypto);
 	singleton = NULL;
@@ -1005,3 +1039,35 @@ bool bt_crypto_sirk(struct bt_crypto *crypto, const char *str, uint16_t vendor,
 	/* Encrypt sirk using k as LTK with sef function */
 	return bt_crypto_sef(crypto, k, sirk_plaintext, sirk);
 }
+
+bool bt_crypto_hmac_sha256(struct bt_crypto *crypto,
+				const uint8_t *key, size_t key_len,
+				const uint8_t *msg, size_t msg_len,
+				uint8_t res[32])
+{
+	ssize_t len;
+	int fd;
+
+	if (!crypto)
+		return false;
+
+	fd = alg_new(crypto->hmac_sha256, key, key_len);
+	if (fd < 0)
+		return false;
+
+	len = send(fd, msg, msg_len, 0);
+	if (len < 0) {
+		close(fd);
+		return false;
+	}
+
+	len = read(fd, res, 32);
+	if (len < 0) {
+		close(fd);
+		return false;
+	}
+
+	close(fd);
+
+	return true;
+}
diff --git a/src/shared/crypto.h b/src/shared/crypto.h
index d85f807..6b234bc 100644
--- a/src/shared/crypto.h
+++ b/src/shared/crypto.h
@@ -62,3 +62,8 @@ bool bt_crypto_sirk(struct bt_crypto *crypto, const char *str, uint16_t vendor,
 			uint8_t sirk[16]);
 bool bt_crypto_rsi(struct bt_crypto *crypto, const uint8_t sirk[16],
 					uint8_t rsi[6]);
+
+bool bt_crypto_hmac_sha256(struct bt_crypto *crypto,
+				const uint8_t *key, size_t key_len,
+				const uint8_t *msg, size_t msg_len,
+				uint8_t res[32]);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.