[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]);