summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2022-12-21 14:15:26 -0800
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2022-12-22 13:10:49 -0800
commita38b6ca525b392c7ad7e04368abd48ddc64b2142 (patch)
tree86798d6f5e705603575f02585e31d3747ae65e24 /src/shared
parent09293fd22b3edb825a268fbf28480f4e3a53a1e9 (diff)
downloadbluez-a38b6ca525b392c7ad7e04368abd48ddc64b2142.tar.gz
shared/crypto: Adds bt_crypto_sef
This adds bt_crypto_sef is is used to create a hash as stated on CSIS spec: '4.5. SIRK encryption function sef' https://www.bluetooth.com/specifications/csis-1-0-1/
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/crypto.c171
-rw-r--r--src/shared/crypto.h2
2 files changed, 164 insertions, 9 deletions
diff --git a/src/shared/crypto.c b/src/shared/crypto.c
index f164ba69d..4cb2ea857 100644
--- a/src/shared/crypto.c
+++ b/src/shared/crypto.c
@@ -586,41 +586,55 @@ bool bt_crypto_s1(struct bt_crypto *crypto, const uint8_t k[16],
return bt_crypto_e(crypto, k, res, res);
}
-static bool aes_cmac(struct bt_crypto *crypto, const uint8_t key[16],
+static bool aes_cmac_be(struct bt_crypto *crypto, const uint8_t key[16],
const uint8_t *msg, size_t msg_len, uint8_t res[16])
{
- uint8_t key_msb[16], out[16], msg_msb[CMAC_MSG_MAX];
ssize_t len;
int fd;
if (msg_len > CMAC_MSG_MAX)
return false;
- swap_buf(key, key_msb, 16);
- fd = alg_new(crypto->cmac_aes, key_msb, 16);
+ fd = alg_new(crypto->cmac_aes, key, 16);
if (fd < 0)
return false;
- swap_buf(msg, msg_msb, msg_len);
- len = send(fd, msg_msb, msg_len, 0);
+ len = send(fd, msg, msg_len, 0);
if (len < 0) {
close(fd);
return false;
}
- len = read(fd, out, 16);
+ len = read(fd, res, 16);
if (len < 0) {
close(fd);
return false;
}
- swap_buf(out, res, 16);
-
close(fd);
return true;
}
+static bool aes_cmac(struct bt_crypto *crypto, const uint8_t key[16],
+ const uint8_t *msg, size_t msg_len, uint8_t res[16])
+{
+ uint8_t key_msb[16], out[16], msg_msb[CMAC_MSG_MAX];
+
+ if (msg_len > CMAC_MSG_MAX)
+ return false;
+
+ swap_buf(key, key_msb, 16);
+ swap_buf(msg, msg_msb, msg_len);
+
+ if (!aes_cmac_be(crypto, key_msb, msg_msb, msg_len, out))
+ return false;
+
+ swap_buf(out, res, 16);
+
+ return true;
+}
+
bool bt_crypto_f4(struct bt_crypto *crypto, uint8_t u[32], uint8_t v[32],
uint8_t x[16], uint8_t z, uint8_t res[16])
{
@@ -773,3 +787,142 @@ bool bt_crypto_sih(struct bt_crypto *crypto, const uint8_t k[16],
{
return bt_crypto_ah(crypto, k, r, hash);
}
+
+static bool aes_cmac_zero(struct bt_crypto *crypto, const uint8_t *msg,
+ size_t msg_len, uint8_t res[16])
+{
+ const uint8_t zero[16] = {};
+
+ return aes_cmac_be(crypto, zero, msg, msg_len, res);
+}
+
+/* The inputs to function s1 are:
+ *
+ * M is a non-zero length octet array or ASCII encoded string
+ *
+ * If M is an ASCII encoded string, M shall be converted into an integer number
+ * by replacing each string character with its ASCII code preserving the order.
+ * For example, if M is the string “CSIS”, M is converted into the integer
+ * number: 0x4353 4953.
+ *
+ * ZERO is the 128-bit value:
+ *
+ * 0x0000 0000 0000 0000 0000 0000 0000 0000
+ *
+ * The output of the salt generation function s1 shall be calculated as follows:
+ *
+ * s1(M)=AES‐CMACZERO(M)
+ *
+ * Where AES-CMACZERO is the CMAC function defined in Section 4.2.
+ */
+static bool sef_s1(struct bt_crypto *crypto, const uint8_t *m,
+ size_t m_len, uint8_t res[16])
+{
+ /* s1(M)=AES‐CMACZERO(M) */
+ return aes_cmac_zero(crypto, m, m_len, res);
+}
+
+/* The key derivation function k1 is used to derive a key. The derived key is
+ * used to encrypt and decrypt the value of the Set Identity Resolving Key
+ * characteristic (see Section 5.1).
+ *
+ * The definition of this key generation function uses the MAC function
+ * AES-CMACT with a 128-bit key T.
+ *
+ * The inputs to function k1 are:
+ *
+ * N is 0 or more octets
+ *
+ * SALT is 128 bits
+ *
+ * P is 0 or more octets
+ *
+ * The key (T) shall be computed as follows:
+ *
+ * T=AES‐CMACSALT(N)
+ *
+ * Where AES-CMACSALT is the CMAC function defined in Section 4.2.
+ *
+ * The output of the key generation function k1 shall be calculated as follows:
+ *
+ * k1(N, SALT, P)=AES‐CMACT(P)
+ *
+ * Where AES-CMACT is the CMAC function defined in Section 4.2.
+ */
+static bool sef_k1(struct bt_crypto *crypto, const uint8_t n[16],
+ uint8_t salt[16], const uint8_t *p,
+ size_t p_len, uint8_t res[16])
+{
+ uint8_t res1[16];
+
+ /* T=AES‐CMACSALT(N) */
+ if (!aes_cmac_be(crypto, salt, n, 16, res1))
+ return false;
+
+ /* k1(N, SALT, P)=AES‐CMACT(P) */
+ return aes_cmac_be(crypto, res1, p, p_len, res);
+}
+
+/*
+ * SIRK encryption function sef
+ *
+ * The SIRK encryption function sef shall be used by the server to encrypt the
+ * SIRK with a key K. The value of K depends on the transport on which the Set
+ * Identity Resolving Key characteristic is read or notified.
+ *
+ * If the Set Identity Resolving Key characteristic is read or notified on the
+ * Basic Rate/Enhanced Data Rate (BR/EDR) transport, K shall be equal to the
+ * Link Key shared by the server and the client.
+ *
+ * K=LinkKey
+ *
+ * If the Set Identity Resolving Key characteristic is read or notified on the
+ * Bluetooth Low Energy (LE) transport, K shall be equal to the LTK shared by
+ * the server and client. That is,
+ *
+ * K=LTK
+ *
+ * The inputs to the function sef are:
+ *
+ * K is the key defined above in this section
+ *
+ * SIRK is the value of the SIRK to be encrypted
+ *
+ * The output of the SIRK encryption function sef is as follows:
+ *
+ * sef(K, SIRK)=k1(K, s1(“SIRKenc”), “csis”)^SIRK
+ *
+ * Where ^ is the bitwise exclusive or operation.
+ */
+bool bt_crypto_sef(struct bt_crypto *crypto, const uint8_t k[16],
+ const uint8_t sirk[16], uint8_t out[16])
+{
+ const uint8_t m[] = {'S', 'I', 'R', 'K', 'e', 'n', 'c'};
+ const uint8_t p[] = {'c', 's', 'i', 's'};
+ uint8_t k_msb[16];
+ uint8_t salt[16];
+ uint8_t res_msb[16];
+ uint8_t res[16];
+
+ if (!crypto)
+ return false;
+
+ /* salt = s1(“SIRKenc”) */
+ if (!sef_s1(crypto, m, sizeof(m), salt))
+ return false;
+
+ /* Convert K to MSB/BE format */
+ swap_buf(k, k_msb, 16);
+
+ /* res_msb = k1(K, salt, “csis”) */
+ if (!sef_k1(crypto, k_msb, salt, p, sizeof(p), res_msb))
+ return false;
+
+ /* Convert back to LSB/LE format */
+ swap_buf(res_msb, res, 16);
+
+ /* res^SIRK */
+ u128_xor(res, sirk, out);
+
+ return true;
+}
diff --git a/src/shared/crypto.h b/src/shared/crypto.h
index fca52e38e..fc1ba0c4f 100644
--- a/src/shared/crypto.h
+++ b/src/shared/crypto.h
@@ -53,5 +53,7 @@ bool bt_crypto_verify_att_sign(struct bt_crypto *crypto, const uint8_t key[16],
const uint8_t *pdu, uint16_t pdu_len);
bool bt_crypto_gatt_hash(struct bt_crypto *crypto, struct iovec *iov,
size_t iov_len, uint8_t res[16]);
+bool bt_crypto_sef(struct bt_crypto *crypto, const uint8_t k[16],
+ const uint8_t sirk[16], uint8_t out[16]);
bool bt_crypto_sih(struct bt_crypto *crypto, const uint8_t k[16],
const uint8_t r[3], uint8_t hash[3]);