#include <linux/debugfs.h>
#include <linux/scatterlist.h>
+#include <crypto/aes-cbc-macs.h>
#include <crypto/aes.h>
-#include <crypto/hash.h>
#include <crypto/kpp.h>
#include <crypto/utils.h>
0x3f : 0x07)
#define KEY_DIST_MASK 0x07
-/* Maximum message length that can be passed to aes_cmac */
+/* Maximum message length that can be passed to smp_aes_cmac */
#define CMAC_MSG_MAX 80
enum {
u8 local_rand[16];
bool debug_key;
- struct crypto_shash *tfm_cmac;
struct crypto_kpp *tfm_ecdh;
};
u8 dhkey[32];
u8 mackey[16];
- struct crypto_shash *tfm_cmac;
struct crypto_kpp *tfm_ecdh;
};
* AES-CMAC, f4, f5, f6, g2 and h6.
*/
-static int aes_cmac(struct crypto_shash *tfm, const u8 k[16], const u8 *m,
- size_t len, u8 mac[16])
+static int smp_aes_cmac(const u8 k[16], const u8 *m, size_t len, u8 mac[16])
{
uint8_t tmp[16], mac_msb[16], msg_msb[CMAC_MSG_MAX];
+ struct aes_cmac_key key;
int err;
if (len > CMAC_MSG_MAX)
return -EFBIG;
- if (!tfm) {
- BT_ERR("tfm %p", tfm);
- return -EINVAL;
- }
-
/* Swap key and message from LSB to MSB */
swap_buf(k, tmp, 16);
swap_buf(m, msg_msb, len);
SMP_DBG("msg (len %zu) %*phN", len, (int) len, m);
SMP_DBG("key %16phN", k);
- err = crypto_shash_setkey(tfm, tmp, 16);
- if (err) {
- BT_ERR("cipher setkey failed: %d", err);
+ err = aes_cmac_preparekey(&key, tmp, 16);
+ if (WARN_ON_ONCE(err)) /* Should never happen, as 16 is valid keylen */
return err;
- }
-
- err = crypto_shash_tfm_digest(tfm, msg_msb, len, mac_msb);
- if (err) {
- BT_ERR("Hash computation error %d", err);
- return err;
- }
+ aes_cmac(&key, msg_msb, len, mac_msb);
swap_buf(mac_msb, mac, 16);
return 0;
}
-static int smp_f4(struct crypto_shash *tfm_cmac, const u8 u[32],
- const u8 v[32], const u8 x[16], u8 z, u8 res[16])
+static int smp_f4(const u8 u[32], const u8 v[32], const u8 x[16], u8 z,
+ u8 res[16])
{
u8 m[65];
int err;
memcpy(m + 1, v, 32);
memcpy(m + 33, u, 32);
- err = aes_cmac(tfm_cmac, x, m, sizeof(m), res);
+ err = smp_aes_cmac(x, m, sizeof(m), res);
if (err)
return err;
return err;
}
-static int smp_f5(struct crypto_shash *tfm_cmac, const u8 w[32],
- const u8 n1[16], const u8 n2[16], const u8 a1[7],
- const u8 a2[7], u8 mackey[16], u8 ltk[16])
+static int smp_f5(const u8 w[32], const u8 n1[16], const u8 n2[16],
+ const u8 a1[7], const u8 a2[7], u8 mackey[16], u8 ltk[16])
{
/* The btle, salt and length "magic" values are as defined in
* the SMP section of the Bluetooth core specification. In ASCII
SMP_DBG("n1 %16phN n2 %16phN", n1, n2);
SMP_DBG("a1 %7phN a2 %7phN", a1, a2);
- err = aes_cmac(tfm_cmac, salt, w, 32, t);
+ err = smp_aes_cmac(salt, w, 32, t);
if (err)
return err;
m[52] = 0; /* Counter */
- err = aes_cmac(tfm_cmac, t, m, sizeof(m), mackey);
+ err = smp_aes_cmac(t, m, sizeof(m), mackey);
if (err)
return err;
m[52] = 1; /* Counter */
- err = aes_cmac(tfm_cmac, t, m, sizeof(m), ltk);
+ err = smp_aes_cmac(t, m, sizeof(m), ltk);
if (err)
return err;
return 0;
}
-static int smp_f6(struct crypto_shash *tfm_cmac, const u8 w[16],
- const u8 n1[16], const u8 n2[16], const u8 r[16],
- const u8 io_cap[3], const u8 a1[7], const u8 a2[7],
- u8 res[16])
+static int smp_f6(const u8 w[16], const u8 n1[16], const u8 n2[16],
+ const u8 r[16], const u8 io_cap[3], const u8 a1[7],
+ const u8 a2[7], u8 res[16])
{
u8 m[65];
int err;
memcpy(m + 33, n2, 16);
memcpy(m + 49, n1, 16);
- err = aes_cmac(tfm_cmac, w, m, sizeof(m), res);
+ err = smp_aes_cmac(w, m, sizeof(m), res);
if (err)
return err;
return err;
}
-static int smp_g2(struct crypto_shash *tfm_cmac, const u8 u[32], const u8 v[32],
- const u8 x[16], const u8 y[16], u32 *val)
+static int smp_g2(const u8 u[32], const u8 v[32], const u8 x[16],
+ const u8 y[16], u32 *val)
{
u8 m[80], tmp[16];
int err;
memcpy(m + 16, v, 32);
memcpy(m + 48, u, 32);
- err = aes_cmac(tfm_cmac, x, m, sizeof(m), tmp);
+ err = smp_aes_cmac(x, m, sizeof(m), tmp);
if (err)
return err;
return 0;
}
-static int smp_h6(struct crypto_shash *tfm_cmac, const u8 w[16],
- const u8 key_id[4], u8 res[16])
+static int smp_h6(const u8 w[16], const u8 key_id[4], u8 res[16])
{
int err;
SMP_DBG("w %16phN key_id %4phN", w, key_id);
- err = aes_cmac(tfm_cmac, w, key_id, 4, res);
+ err = smp_aes_cmac(w, key_id, 4, res);
if (err)
return err;
return err;
}
-static int smp_h7(struct crypto_shash *tfm_cmac, const u8 w[16],
- const u8 salt[16], u8 res[16])
+static int smp_h7(const u8 w[16], const u8 salt[16], u8 res[16])
{
int err;
SMP_DBG("w %16phN salt %16phN", w, salt);
- err = aes_cmac(tfm_cmac, salt, w, 16, res);
+ err = smp_aes_cmac(salt, w, 16, res);
if (err)
return err;
get_random_bytes(smp->local_rand, 16);
- err = smp_f4(smp->tfm_cmac, smp->local_pk, smp->local_pk,
- smp->local_rand, 0, hash);
+ err = smp_f4(smp->local_pk, smp->local_pk, smp->local_rand, 0, hash);
if (err < 0)
return err;
kfree_sensitive(smp->responder_csrk);
kfree_sensitive(smp->link_key);
- crypto_free_shash(smp->tfm_cmac);
crypto_free_kpp(smp->tfm_ecdh);
/* Ensure that we don't leave any debug key around if debug key
/* SALT = 0x000000000000000000000000746D7031 */
const u8 salt[16] = { 0x31, 0x70, 0x6d, 0x74 };
- if (smp_h7(smp->tfm_cmac, smp->tk, salt, smp->link_key)) {
+ if (smp_h7(smp->tk, salt, smp->link_key)) {
kfree_sensitive(smp->link_key);
smp->link_key = NULL;
return;
/* From core spec. Spells out in ASCII as 'tmp1'. */
const u8 tmp1[4] = { 0x31, 0x70, 0x6d, 0x74 };
- if (smp_h6(smp->tfm_cmac, smp->tk, tmp1, smp->link_key)) {
+ if (smp_h6(smp->tk, tmp1, smp->link_key)) {
kfree_sensitive(smp->link_key);
smp->link_key = NULL;
return;
}
}
- if (smp_h6(smp->tfm_cmac, smp->link_key, lebr, smp->link_key)) {
+ if (smp_h6(smp->link_key, lebr, smp->link_key)) {
kfree_sensitive(smp->link_key);
smp->link_key = NULL;
return;
/* SALT = 0x000000000000000000000000746D7032 */
const u8 salt[16] = { 0x32, 0x70, 0x6d, 0x74 };
- if (smp_h7(smp->tfm_cmac, key->val, salt, smp->tk))
+ if (smp_h7(key->val, salt, smp->tk))
return;
} else {
/* From core spec. Spells out in ASCII as 'tmp2'. */
const u8 tmp2[4] = { 0x32, 0x70, 0x6d, 0x74 };
- if (smp_h6(smp->tfm_cmac, key->val, tmp2, smp->tk))
+ if (smp_h6(key->val, tmp2, smp->tk))
return;
}
- if (smp_h6(smp->tfm_cmac, smp->tk, brle, smp->tk))
+ if (smp_h6(smp->tk, brle, smp->tk))
return;
sc_add_ltk(smp);
if (!smp)
return NULL;
- smp->tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, 0);
- if (IS_ERR(smp->tfm_cmac)) {
- bt_dev_err(hcon->hdev, "Unable to create CMAC crypto context");
- goto zfree_smp;
- }
-
smp->tfm_ecdh = crypto_alloc_kpp("ecdh-nist-p256", 0, 0);
if (IS_ERR(smp->tfm_ecdh)) {
bt_dev_err(hcon->hdev, "Unable to create ECDH crypto context");
- goto free_shash;
+ goto zfree_smp;
}
smp->conn = conn;
return smp;
-free_shash:
- crypto_free_shash(smp->tfm_cmac);
zfree_smp:
kfree_sensitive(smp);
return NULL;
a[6] = hcon->init_addr_type;
b[6] = hcon->resp_addr_type;
- return smp_f5(smp->tfm_cmac, smp->dhkey, na, nb, a, b, mackey, ltk);
+ return smp_f5(smp->dhkey, na, nb, a, b, mackey, ltk);
}
static void sc_dhkey_check(struct smp_chan *smp)
if (smp->method == REQ_OOB)
memcpy(r, smp->rr, 16);
- smp_f6(smp->tfm_cmac, smp->mackey, smp->prnd, smp->rrnd, r, io_cap,
- local_addr, remote_addr, check.e);
+ smp_f6(smp->mackey, smp->prnd, smp->rrnd, r, io_cap, local_addr,
+ remote_addr, check.e);
smp_send_cmd(smp->conn, SMP_CMD_DHKEY_CHECK, sizeof(check), &check);
}
get_random_bytes(smp->prnd, sizeof(smp->prnd));
- if (smp_f4(smp->tfm_cmac, smp->local_pk, smp->remote_pk, smp->prnd, r,
+ if (smp_f4(smp->local_pk, smp->remote_pk, smp->prnd, r,
cfm.confirm_val))
return SMP_UNSPECIFIED;
r = ((hcon->passkey_notify >> smp->passkey_round) & 0x01);
r |= 0x80;
- if (smp_f4(smp->tfm_cmac, smp->remote_pk, smp->local_pk,
- smp->rrnd, r, cfm))
+ if (smp_f4(smp->remote_pk, smp->local_pk, smp->rrnd, r, cfm))
return SMP_UNSPECIFIED;
if (crypto_memneq(smp->pcnf, cfm, 16))
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
u8 cfm[16];
- err = smp_f4(smp->tfm_cmac, smp->remote_pk, smp->local_pk,
- smp->rrnd, 0, cfm);
+ err = smp_f4(smp->remote_pk, smp->local_pk, smp->rrnd, 0, cfm);
if (err)
return SMP_UNSPECIFIED;
return 0;
}
- err = smp_g2(smp->tfm_cmac, pkax, pkbx, na, nb, &passkey);
+ err = smp_g2(pkax, pkbx, na, nb, &passkey);
if (err)
return SMP_UNSPECIFIED;
memcpy(smp->remote_pk, key, 64);
if (test_bit(SMP_FLAG_REMOTE_OOB, &smp->flags)) {
- err = smp_f4(smp->tfm_cmac, smp->remote_pk, smp->remote_pk,
- smp->rr, 0, cfm.confirm_val);
+ err = smp_f4(smp->remote_pk, smp->remote_pk, smp->rr, 0,
+ cfm.confirm_val);
if (err)
return SMP_UNSPECIFIED;
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags))
return 0;
- err = smp_f4(smp->tfm_cmac, smp->local_pk, smp->remote_pk, smp->prnd,
- 0, cfm.confirm_val);
+ err = smp_f4(smp->local_pk, smp->remote_pk, smp->prnd, 0,
+ cfm.confirm_val);
if (err)
return SMP_UNSPECIFIED;
else if (smp->method == REQ_OOB)
memcpy(r, smp->lr, 16);
- err = smp_f6(smp->tfm_cmac, smp->mackey, smp->rrnd, smp->prnd, r,
- io_cap, remote_addr, local_addr, e);
+ err = smp_f6(smp->mackey, smp->rrnd, smp->prnd, r, io_cap, remote_addr,
+ local_addr, e);
if (err)
return SMP_UNSPECIFIED;
{
struct l2cap_chan *chan;
struct smp_dev *smp;
- struct crypto_shash *tfm_cmac;
struct crypto_kpp *tfm_ecdh;
if (cid == L2CAP_CID_SMP_BREDR) {
if (!smp)
return ERR_PTR(-ENOMEM);
- tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, 0);
- if (IS_ERR(tfm_cmac)) {
- bt_dev_err(hdev, "Unable to create CMAC crypto context");
- kfree_sensitive(smp);
- return ERR_CAST(tfm_cmac);
- }
-
tfm_ecdh = crypto_alloc_kpp("ecdh-nist-p256", 0, 0);
if (IS_ERR(tfm_ecdh)) {
bt_dev_err(hdev, "Unable to create ECDH crypto context");
- crypto_free_shash(tfm_cmac);
kfree_sensitive(smp);
return ERR_CAST(tfm_ecdh);
}
smp->local_oob = false;
- smp->tfm_cmac = tfm_cmac;
smp->tfm_ecdh = tfm_ecdh;
create_chan:
chan = l2cap_chan_create();
if (!chan) {
if (smp) {
- crypto_free_shash(smp->tfm_cmac);
crypto_free_kpp(smp->tfm_ecdh);
kfree_sensitive(smp);
}
smp = chan->data;
if (smp) {
chan->data = NULL;
- crypto_free_shash(smp->tfm_cmac);
crypto_free_kpp(smp->tfm_ecdh);
kfree_sensitive(smp);
}
return 0;
}
-static int __init test_f4(struct crypto_shash *tfm_cmac)
+static int __init test_f4(void)
{
const u8 u[32] = {
0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc,
u8 res[16];
int err;
- err = smp_f4(tfm_cmac, u, v, x, z, res);
+ err = smp_f4(u, v, x, z, res);
if (err)
return err;
return 0;
}
-static int __init test_f5(struct crypto_shash *tfm_cmac)
+static int __init test_f5(void)
{
const u8 w[32] = {
0x98, 0xa6, 0xbf, 0x73, 0xf3, 0x34, 0x8d, 0x86,
u8 mackey[16], ltk[16];
int err;
- err = smp_f5(tfm_cmac, w, n1, n2, a1, a2, mackey, ltk);
+ err = smp_f5(w, n1, n2, a1, a2, mackey, ltk);
if (err)
return err;
return 0;
}
-static int __init test_f6(struct crypto_shash *tfm_cmac)
+static int __init test_f6(void)
{
const u8 w[16] = {
0x20, 0x6e, 0x63, 0xce, 0x20, 0x6a, 0x3f, 0xfd,
u8 res[16];
int err;
- err = smp_f6(tfm_cmac, w, n1, n2, r, io_cap, a1, a2, res);
+ err = smp_f6(w, n1, n2, r, io_cap, a1, a2, res);
if (err)
return err;
return 0;
}
-static int __init test_g2(struct crypto_shash *tfm_cmac)
+static int __init test_g2(void)
{
const u8 u[32] = {
0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc,
u32 val;
int err;
- err = smp_g2(tfm_cmac, u, v, x, y, &val);
+ err = smp_g2(u, v, x, y, &val);
if (err)
return err;
return 0;
}
-static int __init test_h6(struct crypto_shash *tfm_cmac)
+static int __init test_h6(void)
{
const u8 w[16] = {
0x9b, 0x7d, 0x39, 0x0a, 0xa6, 0x10, 0x10, 0x34,
u8 res[16];
int err;
- err = smp_h6(tfm_cmac, w, key_id, res);
+ err = smp_h6(w, key_id, res);
if (err)
return err;
.llseek = default_llseek,
};
-static int __init run_selftests(struct crypto_shash *tfm_cmac,
- struct crypto_kpp *tfm_ecdh)
+static int __init run_selftests(struct crypto_kpp *tfm_ecdh)
{
ktime_t calltime, delta, rettime;
unsigned long long duration;
goto done;
}
- err = test_f4(tfm_cmac);
+ err = test_f4();
if (err) {
BT_ERR("smp_f4 test failed");
goto done;
}
- err = test_f5(tfm_cmac);
+ err = test_f5();
if (err) {
BT_ERR("smp_f5 test failed");
goto done;
}
- err = test_f6(tfm_cmac);
+ err = test_f6();
if (err) {
BT_ERR("smp_f6 test failed");
goto done;
}
- err = test_g2(tfm_cmac);
+ err = test_g2();
if (err) {
BT_ERR("smp_g2 test failed");
goto done;
}
- err = test_h6(tfm_cmac);
+ err = test_h6();
if (err) {
BT_ERR("smp_h6 test failed");
goto done;
int __init bt_selftest_smp(void)
{
- struct crypto_shash *tfm_cmac;
struct crypto_kpp *tfm_ecdh;
int err;
- tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, 0);
- if (IS_ERR(tfm_cmac)) {
- BT_ERR("Unable to create CMAC crypto context");
- return PTR_ERR(tfm_cmac);
- }
-
tfm_ecdh = crypto_alloc_kpp("ecdh-nist-p256", 0, 0);
if (IS_ERR(tfm_ecdh)) {
BT_ERR("Unable to create ECDH crypto context");
- crypto_free_shash(tfm_cmac);
return PTR_ERR(tfm_ecdh);
}
- err = run_selftests(tfm_cmac, tfm_ecdh);
+ err = run_selftests(tfm_ecdh);
- crypto_free_shash(tfm_cmac);
crypto_free_kpp(tfm_ecdh);
return err;