diff options
author | Sebastian Chlad <sebastian.chlad@tieto.com> | 2014-05-27 11:21:58 +0200 |
---|---|---|
committer | Sebastian Chlad <sebastian.chlad@tieto.com> | 2014-05-27 11:21:58 +0200 |
commit | 9b7805a3ebc7ab3c4500290df889abedbfd377fc (patch) | |
tree | 12d87aca23319078a4cd6a2aa9aba8d82967e11e /tools/smp-tester.c | |
parent | 5d363eb448eacca7c3939fd6e8d6ee3c284db7e2 (diff) | |
download | bluez-9b7805a3ebc7ab3c4500290df889abedbfd377fc.tar.gz bluez-9b7805a3ebc7ab3c4500290df889abedbfd377fc.tar.bz2 bluez-9b7805a3ebc7ab3c4500290df889abedbfd377fc.zip |
Imported Upstream version 5.19upstream/5.19upstream
Diffstat (limited to 'tools/smp-tester.c')
-rw-r--r-- | tools/smp-tester.c | 313 |
1 files changed, 64 insertions, 249 deletions
diff --git a/tools/smp-tester.c b/tools/smp-tester.c index 05d620a6..e09c8028 100644 --- a/tools/smp-tester.c +++ b/tools/smp-tester.c @@ -40,44 +40,11 @@ #include "monitor/bt.h" #include "emulator/bthost.h" +#include "src/shared/crypto.h" #include "src/shared/tester.h" #include "src/shared/mgmt.h" #include "src/shared/hciemu.h" -#ifndef SOL_ALG -#define SOL_ALG 279 -#endif - -#ifndef AF_ALG -#define AF_ALG 38 -#define PF_ALG AF_ALG - -#include <linux/types.h> - -struct sockaddr_alg { - __u16 salg_family; - __u8 salg_type[14]; - __u32 salg_feat; - __u32 salg_mask; - __u8 salg_name[64]; -}; - -struct af_alg_iv { - __u32 ivlen; - __u8 iv[0]; -}; - -#define ALG_SET_KEY 1 -#define ALG_SET_IV 2 -#define ALG_SET_OP 3 - -#define ALG_OP_DECRYPT 0 -#define ALG_OP_ENCRYPT 1 - -#else -#include <linux/if_alg.h> -#endif - #define SMP_CID 0x0006 struct test_data { @@ -94,14 +61,14 @@ struct test_data { bool out; uint16_t handle; size_t counter; - int alg_sk; - uint8_t smp_tk[16]; - uint8_t smp_prnd[16]; - uint8_t smp_rrnd[16]; - uint8_t smp_pcnf[16]; - uint8_t smp_preq[7]; - uint8_t smp_prsp[7]; - uint8_t smp_ltk[16]; + struct bt_crypto *crypto; + uint8_t tk[16]; + uint8_t prnd[16]; + uint8_t rrnd[16]; + uint8_t pcnf[16]; + uint8_t preq[7]; + uint8_t prsp[7]; + uint8_t ltk[16]; }; struct smp_req_rsp { @@ -116,174 +83,6 @@ struct smp_data { size_t req_count; }; -static int alg_setup(void) -{ - struct sockaddr_alg salg; - int sk; - - sk = socket(PF_ALG, SOCK_SEQPACKET | SOCK_CLOEXEC, 0); - if (sk < 0) { - fprintf(stderr, "socket(AF_ALG): %s\n", strerror(errno)); - return -1; - } - - memset(&salg, 0, sizeof(salg)); - salg.salg_family = AF_ALG; - strcpy((char *) salg.salg_type, "skcipher"); - strcpy((char *) salg.salg_name, "ecb(aes)"); - - if (bind(sk, (struct sockaddr *) &salg, sizeof(salg)) < 0) { - fprintf(stderr, "bind(AF_ALG): %s\n", strerror(errno)); - close(sk); - return -1; - } - - return sk; -} - -static int alg_new(int alg_sk, const uint8_t *key) -{ - int sk; - - if (setsockopt(alg_sk, SOL_ALG, ALG_SET_KEY, key, 16) < 0) { - tester_warn("setsockopt(ALG_SET_KEY): %s", strerror(errno)); - return -1; - } - - sk = accept4(alg_sk, NULL, 0, SOCK_CLOEXEC); - if (sk < 0) { - tester_warn("accept4(AF_ALG): %s", strerror(errno)); - return -1; - } - - return sk; -} - -static int alg_encrypt(int sk, uint8_t in[16], uint8_t out[16]) -{ - __u32 alg_op = ALG_OP_ENCRYPT; - char cbuf[CMSG_SPACE(sizeof(alg_op))]; - struct cmsghdr *cmsg; - struct msghdr msg; - struct iovec iov; - int ret; - - memset(cbuf, 0, sizeof(cbuf)); - memset(&msg, 0, sizeof(msg)); - - msg.msg_control = cbuf; - msg.msg_controllen = sizeof(cbuf); - - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_ALG; - cmsg->cmsg_type = ALG_SET_OP; - cmsg->cmsg_len = CMSG_LEN(sizeof(alg_op)); - memcpy(CMSG_DATA(cmsg), &alg_op, sizeof(alg_op)); - - iov.iov_base = in; - iov.iov_len = 16; - - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - ret = sendmsg(sk, &msg, 0); - if (ret < 0) { - tester_warn("sendmsg(AF_ALG): %s", strerror(errno)); - return ret; - } - - ret = read(sk, out, 16); - if (ret < 0) - tester_warn("read(AF_ALG): %s", strerror(errno)); - - return 0; -} - -static int smp_e(uint8_t key[16], uint8_t in[16], uint8_t out[16]) -{ - struct test_data *data = tester_get_data(); - int sk, err; - - sk = alg_new(data->alg_sk, key); - if (sk < 0) - return sk; - - err = alg_encrypt(sk, in, out); - - close(sk); - - return err; -} - -static inline void swap128(const uint8_t src[16], uint8_t dst[16]) -{ - int i; - for (i = 0; i < 16; i++) - dst[15 - i] = src[i]; -} - -static inline void swap56(const uint8_t src[7], uint8_t dst[7]) -{ - int i; - for (i = 0; i < 7; i++) - dst[6 - i] = src[i]; -} - -typedef struct { - uint64_t a, b; -} u128; - -static inline void u128_xor(u128 *r, const u128 *p, const u128 *q) -{ - r->a = p->a ^ q->a; - r->b = p->b ^ q->b; -} - -static int smp_c1(uint8_t r[16], uint8_t res[16]) -{ - struct test_data *data = tester_get_data(); - uint8_t p1[16], p2[16]; - int err; - - memset(p1, 0, 16); - - /* p1 = pres || preq || _rat || _iat */ - swap56(data->smp_prsp, p1); - swap56(data->smp_preq, p1 + 7); - p1[14] = data->ra_type; - p1[15] = data->ia_type; - - memset(p2, 0, 16); - - /* p2 = padding || ia || ra */ - baswap((bdaddr_t *) (p2 + 4), (bdaddr_t *) data->ia); - baswap((bdaddr_t *) (p2 + 10), (bdaddr_t *) data->ra); - - /* res = r XOR p1 */ - u128_xor((u128 *) res, (u128 *) r, (u128 *) p1); - - /* res = e(k, res) */ - err = smp_e(data->smp_tk, res, res); - if (err) - return err; - - /* res = res XOR p2 */ - u128_xor((u128 *) res, (u128 *) res, (u128 *) p2); - - /* res = e(k, res) */ - return smp_e(data->smp_tk, res, res); -} - -static int smp_s1(uint8_t r1[16], uint8_t r2[16], uint8_t res[16]) -{ - struct test_data *data = tester_get_data(); - - memcpy(res, r1 + 8, 8); - memcpy(res + 8, r2 + 8, 8); - - return smp_e(data->smp_tk, res, res); -} - static void mgmt_debug(const char *str, void *user_data) { const char *prefix = user_data; @@ -396,9 +195,9 @@ static void test_pre_setup(const void *test_data) { struct test_data *data = tester_get_data(); - data->alg_sk = alg_setup(); - if (data->alg_sk < 0) { - tester_warn("Failed to setup AF_ALG socket"); + data->crypto = bt_crypto_new(); + if (!data->crypto) { + tester_warn("Failed to setup crypto"); tester_pre_setup_failed(); return; } @@ -406,6 +205,7 @@ static void test_pre_setup(const void *test_data) data->mgmt = mgmt_new_default(); if (!data->mgmt) { tester_warn("Failed to setup management interface"); + bt_crypto_unref(data->crypto); tester_pre_setup_failed(); return; } @@ -426,9 +226,9 @@ static void test_post_teardown(const void *test_data) data->io_id = 0; } - if (data->alg_sk >= 0) { - close(data->alg_sk); - data->alg_sk = -1; + if (data->crypto) { + bt_crypto_unref(data->crypto); + data->crypto = NULL; } hciemu_unref(data->hciemu); @@ -449,7 +249,6 @@ static void test_data_free(void *test_data) if (!user) \ break; \ user->hciemu_type = HCIEMU_TYPE_LE; \ - user->alg_sk = -1; \ user->test_data = data; \ tester_add_full(name, data, \ test_pre_setup, setup, func, NULL, \ @@ -482,21 +281,34 @@ static const struct smp_data smp_server_nval_req_2_test = { .req_count = G_N_ELEMENTS(srv_nval_req_1), }; +static const uint8_t smp_nval_req_3[] = { 0x01, 0xff }; +static const uint8_t smp_nval_req_3_rsp[] = { 0x05, 0x08 }; + +static const struct smp_req_rsp srv_nval_req_2[] = { + { smp_nval_req_2, sizeof(smp_nval_req_3), + smp_nval_req_3_rsp, sizeof(smp_nval_req_3_rsp) }, +}; + +static const struct smp_data smp_server_nval_req_3_test = { + .req = srv_nval_req_2, + .req_count = G_N_ELEMENTS(srv_nval_req_2), +}; + static const uint8_t smp_basic_req_1[] = { 0x01, /* Pairing Request */ 0x03, /* NoInputNoOutput */ 0x00, /* OOB Flag */ 0x01, /* Bonding - no MITM */ 0x10, /* Max key size */ - 0x00, /* Init. key dist. */ - 0x01, /* Rsp. key dist. */ + 0x05, /* Init. key dist. */ + 0x05, /* Rsp. key dist. */ }; static const uint8_t smp_basic_req_1_rsp[] = { 0x02, /* Pairing Response */ 0x03, /* NoInputNoOutput */ 0x00, /* OOB Flag */ 0x01, /* Bonding - no MITM */ 0x10, /* Max key size */ - 0x00, /* Init. key dist. */ - 0x01, /* Rsp. key dist. */ + 0x05, /* Init. key dist. */ + 0x05, /* Rsp. key dist. */ }; static const uint8_t smp_confirm_req_1[17] = { 0x03 }; @@ -592,61 +404,59 @@ static void pair_device_complete(uint8_t status, uint16_t length, tester_test_passed(); } -static const void *get_pdu(const uint8_t *data) +static const void *get_pdu(const uint8_t *pdu) { - struct test_data *test_data = tester_get_data(); - uint8_t opcode = data[0]; + struct test_data *data = tester_get_data(); + uint8_t opcode = pdu[0]; static uint8_t buf[17]; - uint8_t res[16]; switch (opcode) { case 0x01: /* Pairing Request */ - memcpy(test_data->smp_preq, data, sizeof(test_data->smp_preq)); + memcpy(data->preq, pdu, sizeof(data->preq)); break; case 0x02: /* Pairing Response */ - memcpy(test_data->smp_prsp, data, sizeof(test_data->smp_prsp)); + memcpy(data->prsp, pdu, sizeof(data->prsp)); break; case 0x03: /* Pairing Confirm */ - buf[0] = data[0]; - smp_c1(test_data->smp_prnd, res); - swap128(res, &buf[1]); + buf[0] = pdu[0]; + bt_crypto_c1(data->crypto, data->tk, data->prnd, data->prsp, + data->preq, data->ia_type, data->ia, + data->ra_type, data->ra, &buf[1]); return buf; case 0x04: /* Pairing Random */ - buf[0] = data[0]; - swap128(test_data->smp_prnd, &buf[1]); + buf[0] = pdu[0]; + memcpy(&buf[1], data->prnd, 16); return buf; default: break; } - return data; + return pdu; } static bool verify_random(const uint8_t rnd[16]) { struct test_data *data = tester_get_data(); - uint8_t confirm[16], res[16], key[16]; - int err; + uint8_t confirm[16]; - err = smp_c1(data->smp_rrnd, res); - if (err < 0) + if (!bt_crypto_c1(data->crypto, data->tk, data->rrnd, data->prsp, + data->preq, data->ia_type, data->ia, + data->ra_type, data->ra, confirm)) return false; - swap128(res, confirm); - - if (memcmp(data->smp_pcnf, confirm, sizeof(data->smp_pcnf) != 0)) { + if (memcmp(data->pcnf, confirm, sizeof(data->pcnf) != 0)) { tester_warn("Confirmation values don't match"); return false; } if (data->out) { struct bthost *bthost = hciemu_client_get_host(data->hciemu); - smp_s1(data->smp_rrnd, data->smp_prnd, key); - swap128(key, data->smp_ltk); - bthost_le_start_encrypt(bthost, data->handle, data->smp_ltk); + bt_crypto_s1(data->crypto, data->tk, data->rrnd, data->prnd, + data->ltk); + bthost_le_start_encrypt(bthost, data->handle, data->ltk); } else { - smp_s1(data->smp_prnd, data->smp_rrnd, key); - swap128(key, data->smp_ltk); + bt_crypto_s1(data->crypto, data->tk, data->prnd, data->rrnd, + data->ltk); } return true; @@ -687,16 +497,16 @@ static void smp_server(const void *data, uint16_t len, void *user_data) switch (opcode) { case 0x01: /* Pairing Request */ - memcpy(test_data->smp_preq, data, sizeof(test_data->smp_preq)); + memcpy(test_data->preq, data, sizeof(test_data->preq)); break; case 0x02: /* Pairing Response */ - memcpy(test_data->smp_prsp, data, sizeof(test_data->smp_prsp)); + memcpy(test_data->prsp, data, sizeof(test_data->prsp)); break; case 0x03: /* Pairing Confirm */ - memcpy(test_data->smp_pcnf, data + 1, 16); + memcpy(test_data->pcnf, data + 1, 16); goto next; case 0x04: /* Pairing Random */ - swap128(data + 1, test_data->smp_rrnd); + memcpy(test_data->rrnd, data + 1, 16); if (!verify_random(data + 1)) goto failed; goto next; @@ -833,6 +643,8 @@ static void setup_powered_server(const void *test_data) sizeof(param), param, NULL, NULL, NULL); mgmt_send(data->mgmt, MGMT_OP_SET_PAIRABLE, data->mgmt_index, sizeof(param), param, NULL, NULL, NULL); + mgmt_send(data->mgmt, MGMT_OP_SET_CONNECTABLE, data->mgmt_index, + sizeof(param), param, NULL, NULL, NULL); mgmt_send(data->mgmt, MGMT_OP_SET_ADVERTISING, data->mgmt_index, sizeof(param), param, NULL, NULL, NULL); mgmt_send(data->mgmt, MGMT_OP_SET_POWERED, data->mgmt_index, @@ -868,6 +680,9 @@ int main(int argc, char *argv[]) test_smp("SMP Server - Invalid Request 2", &smp_server_nval_req_2_test, setup_powered_server, test_server); + test_smp("SMP Server - Invalid Request 3", + &smp_server_nval_req_3_test, + setup_powered_server, test_server); test_smp("SMP Client - Basic Request 1", &smp_client_basic_req_1_test, |