Skip to content

Commit

Permalink
shared/crypto: Adds bt_crypto_sef
Browse files Browse the repository at this point in the history
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/
  • Loading branch information
Vudentz committed Dec 22, 2022
1 parent 09293fd commit a38b6ca
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 9 deletions.
171 changes: 162 additions & 9 deletions src/shared/crypto.c
Expand Up @@ -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])
{
Expand Down Expand Up @@ -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;
}
2 changes: 2 additions & 0 deletions src/shared/crypto.h
Expand Up @@ -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]);

0 comments on commit a38b6ca

Please sign in to comment.