|
Packit |
34410b |
/*
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* BlueZ - Bluetooth protocol stack for Linux
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* Copyright (C) 2012-2014 Intel Corporation. All rights reserved.
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* This library is free software; you can redistribute it and/or
|
|
Packit |
34410b |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
34410b |
* License as published by the Free Software Foundation; either
|
|
Packit |
34410b |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
34410b |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
34410b |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
34410b |
* Lesser General Public License for more details.
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
34410b |
* License along with this library; if not, write to the Free Software
|
|
Packit |
34410b |
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
*/
|
|
Packit |
34410b |
|
|
Packit |
34410b |
#ifdef HAVE_CONFIG_H
|
|
Packit |
34410b |
#include <config.h>
|
|
Packit |
34410b |
#endif
|
|
Packit |
34410b |
|
|
Packit |
34410b |
#include <fcntl.h>
|
|
Packit |
34410b |
#include <unistd.h>
|
|
Packit |
34410b |
#include <string.h>
|
|
Packit |
34410b |
#include <sys/socket.h>
|
|
Packit |
34410b |
|
|
Packit |
34410b |
#include "src/shared/util.h"
|
|
Packit |
34410b |
#include "src/shared/crypto.h"
|
|
Packit |
34410b |
|
|
Packit |
34410b |
#ifndef HAVE_LINUX_IF_ALG_H
|
|
Packit |
34410b |
#ifndef HAVE_LINUX_TYPES_H
|
|
Packit |
34410b |
typedef uint8_t __u8;
|
|
Packit |
34410b |
typedef uint16_t __u16;
|
|
Packit |
34410b |
typedef uint32_t __u32;
|
|
Packit |
34410b |
#else
|
|
Packit |
34410b |
#include <linux/types.h>
|
|
Packit |
34410b |
#endif
|
|
Packit |
34410b |
|
|
Packit |
34410b |
struct sockaddr_alg {
|
|
Packit |
34410b |
__u16 salg_family;
|
|
Packit |
34410b |
__u8 salg_type[14];
|
|
Packit |
34410b |
__u32 salg_feat;
|
|
Packit |
34410b |
__u32 salg_mask;
|
|
Packit |
34410b |
__u8 salg_name[64];
|
|
Packit |
34410b |
};
|
|
Packit |
34410b |
|
|
Packit |
34410b |
struct af_alg_iv {
|
|
Packit |
34410b |
__u32 ivlen;
|
|
Packit |
34410b |
__u8 iv[0];
|
|
Packit |
34410b |
};
|
|
Packit |
34410b |
|
|
Packit |
34410b |
#define ALG_SET_KEY 1
|
|
Packit |
34410b |
#define ALG_SET_IV 2
|
|
Packit |
34410b |
#define ALG_SET_OP 3
|
|
Packit |
34410b |
|
|
Packit |
34410b |
#define ALG_OP_DECRYPT 0
|
|
Packit |
34410b |
#define ALG_OP_ENCRYPT 1
|
|
Packit |
34410b |
|
|
Packit |
34410b |
#define PF_ALG 38 /* Algorithm sockets. */
|
|
Packit |
34410b |
#define AF_ALG PF_ALG
|
|
Packit |
34410b |
#else
|
|
Packit |
34410b |
#include <linux/if_alg.h>
|
|
Packit |
34410b |
#endif
|
|
Packit |
34410b |
|
|
Packit |
34410b |
#ifndef SOL_ALG
|
|
Packit |
34410b |
#define SOL_ALG 279
|
|
Packit |
34410b |
#endif
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/* Maximum message length that can be passed to aes_cmac */
|
|
Packit |
34410b |
#define CMAC_MSG_MAX 80
|
|
Packit |
34410b |
|
|
Packit |
34410b |
struct bt_crypto {
|
|
Packit |
34410b |
int ref_count;
|
|
Packit |
34410b |
int ecb_aes;
|
|
Packit |
34410b |
int urandom;
|
|
Packit |
34410b |
int cmac_aes;
|
|
Packit |
34410b |
};
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static int urandom_setup(void)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
int fd;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
fd = open("/dev/urandom", O_RDONLY);
|
|
Packit |
34410b |
if (fd < 0)
|
|
Packit |
34410b |
return -1;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return fd;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static int ecb_aes_setup(void)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
struct sockaddr_alg salg;
|
|
Packit |
34410b |
int fd;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
fd = socket(PF_ALG, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
|
|
Packit |
34410b |
if (fd < 0)
|
|
Packit |
34410b |
return -1;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
memset(&salg, 0, sizeof(salg));
|
|
Packit |
34410b |
salg.salg_family = AF_ALG;
|
|
Packit |
34410b |
strcpy((char *) salg.salg_type, "skcipher");
|
|
Packit |
34410b |
strcpy((char *) salg.salg_name, "ecb(aes)");
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (bind(fd, (struct sockaddr *) &salg, sizeof(salg)) < 0) {
|
|
Packit |
34410b |
close(fd);
|
|
Packit |
34410b |
return -1;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return fd;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static int cmac_aes_setup(void)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
struct sockaddr_alg salg;
|
|
Packit |
34410b |
int fd;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
fd = socket(PF_ALG, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
|
|
Packit |
34410b |
if (fd < 0)
|
|
Packit |
34410b |
return -1;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
memset(&salg, 0, sizeof(salg));
|
|
Packit |
34410b |
salg.salg_family = AF_ALG;
|
|
Packit |
34410b |
strcpy((char *) salg.salg_type, "hash");
|
|
Packit |
34410b |
strcpy((char *) salg.salg_name, "cmac(aes)");
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (bind(fd, (struct sockaddr *) &salg, sizeof(salg)) < 0) {
|
|
Packit |
34410b |
close(fd);
|
|
Packit |
34410b |
return -1;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return fd;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
struct bt_crypto *bt_crypto_new(void)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
struct bt_crypto *crypto;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
crypto = new0(struct bt_crypto, 1);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
crypto->ecb_aes = ecb_aes_setup();
|
|
Packit |
34410b |
if (crypto->ecb_aes < 0) {
|
|
Packit |
34410b |
free(crypto);
|
|
Packit |
34410b |
return NULL;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
crypto->urandom = urandom_setup();
|
|
Packit |
34410b |
if (crypto->urandom < 0) {
|
|
Packit |
34410b |
close(crypto->ecb_aes);
|
|
Packit |
34410b |
free(crypto);
|
|
Packit |
34410b |
return NULL;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
crypto->cmac_aes = cmac_aes_setup();
|
|
Packit |
34410b |
if (crypto->cmac_aes < 0) {
|
|
Packit |
34410b |
close(crypto->urandom);
|
|
Packit |
34410b |
close(crypto->ecb_aes);
|
|
Packit |
34410b |
free(crypto);
|
|
Packit |
34410b |
return NULL;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return bt_crypto_ref(crypto);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
struct bt_crypto *bt_crypto_ref(struct bt_crypto *crypto)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
if (!crypto)
|
|
Packit |
34410b |
return NULL;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
__sync_fetch_and_add(&crypto->ref_count, 1);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return crypto;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
void bt_crypto_unref(struct bt_crypto *crypto)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
if (!crypto)
|
|
Packit |
34410b |
return;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (__sync_sub_and_fetch(&crypto->ref_count, 1))
|
|
Packit |
34410b |
return;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
close(crypto->urandom);
|
|
Packit |
34410b |
close(crypto->ecb_aes);
|
|
Packit |
34410b |
close(crypto->cmac_aes);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
free(crypto);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
bool bt_crypto_random_bytes(struct bt_crypto *crypto,
|
|
Packit |
34410b |
void *buf, uint8_t num_bytes)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
ssize_t len;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (!crypto)
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
len = read(crypto->urandom, buf, num_bytes);
|
|
Packit |
34410b |
if (len < num_bytes)
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return true;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static int alg_new(int fd, const void *keyval, socklen_t keylen)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
if (setsockopt(fd, SOL_ALG, ALG_SET_KEY, keyval, keylen) < 0)
|
|
Packit |
34410b |
return -1;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/* FIXME: This should use accept4() with SOCK_CLOEXEC */
|
|
Packit |
34410b |
return accept(fd, NULL, 0);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static bool alg_encrypt(int fd, const void *inbuf, size_t inlen,
|
|
Packit |
34410b |
void *outbuf, size_t outlen)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
__u32 alg_op = ALG_OP_ENCRYPT;
|
|
Packit |
34410b |
char cbuf[CMSG_SPACE(sizeof(alg_op))];
|
|
Packit |
34410b |
struct cmsghdr *cmsg;
|
|
Packit |
34410b |
struct msghdr msg;
|
|
Packit |
34410b |
struct iovec iov;
|
|
Packit |
34410b |
ssize_t len;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
memset(cbuf, 0, sizeof(cbuf));
|
|
Packit |
34410b |
memset(&msg, 0, sizeof(msg));
|
|
Packit |
34410b |
|
|
Packit |
34410b |
msg.msg_control = cbuf;
|
|
Packit |
34410b |
msg.msg_controllen = sizeof(cbuf);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
cmsg = CMSG_FIRSTHDR(&msg;;
|
|
Packit |
34410b |
cmsg->cmsg_level = SOL_ALG;
|
|
Packit |
34410b |
cmsg->cmsg_type = ALG_SET_OP;
|
|
Packit |
34410b |
cmsg->cmsg_len = CMSG_LEN(sizeof(alg_op));
|
|
Packit |
34410b |
memcpy(CMSG_DATA(cmsg), &alg_op, sizeof(alg_op));
|
|
Packit |
34410b |
|
|
Packit |
34410b |
iov.iov_base = (void *) inbuf;
|
|
Packit |
34410b |
iov.iov_len = inlen;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
msg.msg_iov = &iov;
|
|
Packit |
34410b |
msg.msg_iovlen = 1;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
len = sendmsg(fd, &msg, 0);
|
|
Packit |
34410b |
if (len < 0)
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
len = read(fd, outbuf, outlen);
|
|
Packit |
34410b |
if (len < 0)
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return true;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static inline void swap_buf(const uint8_t *src, uint8_t *dst, uint16_t len)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
int i;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
for (i = 0; i < len; i++)
|
|
Packit |
34410b |
dst[len - 1 - i] = src[i];
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
bool bt_crypto_sign_att(struct bt_crypto *crypto, const uint8_t key[16],
|
|
Packit |
34410b |
const uint8_t *m, uint16_t m_len,
|
|
Packit |
34410b |
uint32_t sign_cnt, uint8_t signature[12])
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
int fd;
|
|
Packit |
34410b |
int len;
|
|
Packit |
34410b |
uint8_t tmp[16], out[16];
|
|
Packit |
34410b |
uint16_t msg_len = m_len + sizeof(uint32_t);
|
|
Packit |
34410b |
uint8_t msg[msg_len];
|
|
Packit |
34410b |
uint8_t msg_s[msg_len];
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (!crypto)
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
memset(msg, 0, msg_len);
|
|
Packit |
34410b |
memcpy(msg, m, m_len);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/* Add sign_counter to the message */
|
|
Packit |
34410b |
put_le32(sign_cnt, msg + m_len);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/* The most significant octet of key corresponds to key[0] */
|
|
Packit |
34410b |
swap_buf(key, tmp, 16);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
fd = alg_new(crypto->cmac_aes, tmp, 16);
|
|
Packit |
34410b |
if (fd < 0)
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/* Swap msg before signing */
|
|
Packit |
34410b |
swap_buf(msg, msg_s, msg_len);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
len = send(fd, msg_s, msg_len, 0);
|
|
Packit |
34410b |
if (len < 0) {
|
|
Packit |
34410b |
close(fd);
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
len = read(fd, out, 16);
|
|
Packit |
34410b |
if (len < 0) {
|
|
Packit |
34410b |
close(fd);
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
close(fd);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/*
|
|
Packit |
34410b |
* As to BT spec. 4.1 Vol[3], Part C, chapter 10.4.1 sign counter should
|
|
Packit |
34410b |
* be placed in the signature
|
|
Packit |
34410b |
*/
|
|
Packit |
34410b |
put_be32(sign_cnt, out + 8);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/*
|
|
Packit |
34410b |
* The most significant octet of hash corresponds to out[0] - swap it.
|
|
Packit |
34410b |
* Then truncate in most significant bit first order to a length of
|
|
Packit |
34410b |
* 12 octets
|
|
Packit |
34410b |
*/
|
|
Packit |
34410b |
swap_buf(out, tmp, 16);
|
|
Packit |
34410b |
memcpy(signature, tmp + 4, 12);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return true;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
/*
|
|
Packit |
34410b |
* Security function e
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* Security function e generates 128-bit encryptedData from a 128-bit key
|
|
Packit |
34410b |
* and 128-bit plaintextData using the AES-128-bit block cypher:
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* encryptedData = e(key, plaintextData)
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* The most significant octet of key corresponds to key[0], the most
|
|
Packit |
34410b |
* significant octet of plaintextData corresponds to in[0] and the
|
|
Packit |
34410b |
* most significant octet of encryptedData corresponds to out[0].
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
*/
|
|
Packit |
34410b |
bool bt_crypto_e(struct bt_crypto *crypto, const uint8_t key[16],
|
|
Packit |
34410b |
const uint8_t plaintext[16], uint8_t encrypted[16])
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
uint8_t tmp[16], in[16], out[16];
|
|
Packit |
34410b |
int fd;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (!crypto)
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/* The most significant octet of key corresponds to key[0] */
|
|
Packit |
34410b |
swap_buf(key, tmp, 16);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
fd = alg_new(crypto->ecb_aes, tmp, 16);
|
|
Packit |
34410b |
if (fd < 0)
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/* Most significant octet of plaintextData corresponds to in[0] */
|
|
Packit |
34410b |
swap_buf(plaintext, in, 16);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (!alg_encrypt(fd, in, 16, out, 16)) {
|
|
Packit |
34410b |
close(fd);
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/* Most significant octet of encryptedData corresponds to out[0] */
|
|
Packit |
34410b |
swap_buf(out, encrypted, 16);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
close(fd);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return true;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/*
|
|
Packit |
34410b |
* Random Address Hash function ah
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* The random address hash function ah is used to generate a hash value
|
|
Packit |
34410b |
* that is used in resolvable private addresses.
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* The following are inputs to the random address hash function ah:
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* k is 128 bits
|
|
Packit |
34410b |
* r is 24 bits
|
|
Packit |
34410b |
* padding is 104 bits
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* r is concatenated with padding to generate r' which is used as the
|
|
Packit |
34410b |
* 128-bit input parameter plaintextData to security function e:
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* r' = padding || r
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* The least significant octet of r becomes the least significant octet
|
|
Packit |
34410b |
* of r’ and the most significant octet of padding becomes the most
|
|
Packit |
34410b |
* significant octet of r'.
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* For example, if the 24-bit value r is 0x423456 then r' is
|
|
Packit |
34410b |
* 0x00000000000000000000000000423456.
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* The output of the random address function ah is:
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* ah(k, r) = e(k, r') mod 2^24
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* The output of the security function e is then truncated to 24 bits by
|
|
Packit |
34410b |
* taking the least significant 24 bits of the output of e as the result
|
|
Packit |
34410b |
* of ah.
|
|
Packit |
34410b |
*/
|
|
Packit |
34410b |
bool bt_crypto_ah(struct bt_crypto *crypto, const uint8_t k[16],
|
|
Packit |
34410b |
const uint8_t r[3], uint8_t hash[3])
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
uint8_t rp[16];
|
|
Packit |
34410b |
uint8_t encrypted[16];
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (!crypto)
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/* r' = padding || r */
|
|
Packit |
34410b |
memcpy(rp, r, 3);
|
|
Packit |
34410b |
memset(rp + 3, 0, 13);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/* e(k, r') */
|
|
Packit |
34410b |
if (!bt_crypto_e(crypto, k, rp, encrypted))
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/* ah(k, r) = e(k, r') mod 2^24 */
|
|
Packit |
34410b |
memcpy(hash, encrypted, 3);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return true;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
typedef struct {
|
|
Packit |
34410b |
uint64_t a, b;
|
|
Packit |
34410b |
} u128;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static inline void u128_xor(const uint8_t p[16], const uint8_t q[16],
|
|
Packit |
34410b |
uint8_t r[16])
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
u128 pp, qq, rr;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
memcpy(&pp, p, 16);
|
|
Packit |
34410b |
memcpy(&qq, q, 16);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
rr.a = pp.a ^ qq.a;
|
|
Packit |
34410b |
rr.b = pp.b ^ qq.b;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
memcpy(r, &rr, 16);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/*
|
|
Packit |
34410b |
* Confirm value generation function c1
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* During the pairing process confirm values are exchanged. This confirm
|
|
Packit |
34410b |
* value generation function c1 is used to generate the confirm values.
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* The following are inputs to the confirm value generation function c1:
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* k is 128 bits
|
|
Packit |
34410b |
* r is 128 bits
|
|
Packit |
34410b |
* pres is 56 bits
|
|
Packit |
34410b |
* preq is 56 bits
|
|
Packit |
34410b |
* iat is 1 bit
|
|
Packit |
34410b |
* ia is 48 bits
|
|
Packit |
34410b |
* rat is 1 bit
|
|
Packit |
34410b |
* ra is 48 bits
|
|
Packit |
34410b |
* padding is 32 bits of 0
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* iat is concatenated with 7-bits of 0 to create iat' which is 8 bits
|
|
Packit |
34410b |
* in length. iat is the least significant bit of iat'
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* rat is concatenated with 7-bits of 0 to create rat' which is 8 bits
|
|
Packit |
34410b |
* in length. rat is the least significant bit of rat'
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* pres, preq, rat' and iat' are concatenated to generate p1 which is
|
|
Packit |
34410b |
* XORed with r and used as 128-bit input parameter plaintextData to
|
|
Packit |
34410b |
* security function e:
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* p1 = pres || preq || rat' || iat'
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* The octet of iat' becomes the least significant octet of p1 and the
|
|
Packit |
34410b |
* most significant octet of pres becomes the most significant octet of
|
|
Packit |
34410b |
* p1.
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* ra is concatenated with ia and padding to generate p2 which is XORed
|
|
Packit |
34410b |
* with the result of the security function e using p1 as the input
|
|
Packit |
34410b |
* paremter plaintextData and is then used as the 128-bit input
|
|
Packit |
34410b |
* parameter plaintextData to security function e:
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* p2 = padding || ia || ra
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* The least significant octet of ra becomes the least significant octet
|
|
Packit |
34410b |
* of p2 and the most significant octet of padding becomes the most
|
|
Packit |
34410b |
* significant octet of p2.
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* The output of the confirm value generation function c1 is:
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* c1(k, r, preq, pres, iat, rat, ia, ra) = e(k, e(k, r XOR p1) XOR p2)
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* The 128-bit output of the security function e is used as the result
|
|
Packit |
34410b |
* of confirm value generation function c1.
|
|
Packit |
34410b |
*/
|
|
Packit |
34410b |
bool bt_crypto_c1(struct bt_crypto *crypto, const uint8_t k[16],
|
|
Packit |
34410b |
const uint8_t r[16], const uint8_t pres[7],
|
|
Packit |
34410b |
const uint8_t preq[7], uint8_t iat,
|
|
Packit |
34410b |
const uint8_t ia[6], uint8_t rat,
|
|
Packit |
34410b |
const uint8_t ra[6], uint8_t res[16])
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
uint8_t p1[16], p2[16];
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/* p1 = pres || preq || _rat || _iat */
|
|
Packit |
34410b |
p1[0] = iat;
|
|
Packit |
34410b |
p1[1] = rat;
|
|
Packit |
34410b |
memcpy(p1 + 2, preq, 7);
|
|
Packit |
34410b |
memcpy(p1 + 9, pres, 7);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/* p2 = padding || ia || ra */
|
|
Packit |
34410b |
memcpy(p2, ra, 6);
|
|
Packit |
34410b |
memcpy(p2 + 6, ia, 6);
|
|
Packit |
34410b |
memset(p2 + 12, 0, 4);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/* res = r XOR p1 */
|
|
Packit |
34410b |
u128_xor(r, p1, res);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/* res = e(k, res) */
|
|
Packit |
34410b |
if (!bt_crypto_e(crypto, k, res, res))
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/* res = res XOR p2 */
|
|
Packit |
34410b |
u128_xor(res, p2, res);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/* res = e(k, res) */
|
|
Packit |
34410b |
return bt_crypto_e(crypto, k, res, res);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/*
|
|
Packit |
34410b |
* Key generation function s1
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* The key generation function s1 is used to generate the STK during the
|
|
Packit |
34410b |
* pairing process.
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* The following are inputs to the key generation function s1:
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* k is 128 bits
|
|
Packit |
34410b |
* r1 is 128 bits
|
|
Packit |
34410b |
* r2 is 128 bits
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* The most significant 64-bits of r1 are discarded to generate r1' and
|
|
Packit |
34410b |
* the most significant 64-bits of r2 are discarded to generate r2'.
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* r1' is concatenated with r2' to generate r' which is used as the
|
|
Packit |
34410b |
* 128-bit input parameter plaintextData to security function e:
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* r' = r1' || r2'
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* The least significant octet of r2' becomes the least significant
|
|
Packit |
34410b |
* octet of r' and the most significant octet of r1' becomes the most
|
|
Packit |
34410b |
* significant octet of r'.
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* The output of the key generation function s1 is:
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* s1(k, r1, r2) = e(k, r')
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* The 128-bit output of the security function e is used as the result
|
|
Packit |
34410b |
* of key generation function s1.
|
|
Packit |
34410b |
*/
|
|
Packit |
34410b |
bool bt_crypto_s1(struct bt_crypto *crypto, const uint8_t k[16],
|
|
Packit |
34410b |
const uint8_t r1[16], const uint8_t r2[16],
|
|
Packit |
34410b |
uint8_t res[16])
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
memcpy(res, r2, 8);
|
|
Packit |
34410b |
memcpy(res + 8, r1, 8);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return bt_crypto_e(crypto, k, res, res);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static bool aes_cmac(struct bt_crypto *crypto, const uint8_t key[16],
|
|
Packit |
34410b |
const uint8_t *msg, size_t msg_len, uint8_t res[16])
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
uint8_t key_msb[16], out[16], msg_msb[CMAC_MSG_MAX];
|
|
Packit |
34410b |
ssize_t len;
|
|
Packit |
34410b |
int fd;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (msg_len > CMAC_MSG_MAX)
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
swap_buf(key, key_msb, 16);
|
|
Packit |
34410b |
fd = alg_new(crypto->cmac_aes, key_msb, 16);
|
|
Packit |
34410b |
if (fd < 0)
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
swap_buf(msg, msg_msb, msg_len);
|
|
Packit |
34410b |
len = send(fd, msg_msb, msg_len, 0);
|
|
Packit |
34410b |
if (len < 0) {
|
|
Packit |
34410b |
close(fd);
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
len = read(fd, out, 16);
|
|
Packit |
34410b |
if (len < 0) {
|
|
Packit |
34410b |
close(fd);
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
swap_buf(out, res, 16);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
close(fd);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return true;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
bool bt_crypto_f4(struct bt_crypto *crypto, uint8_t u[32], uint8_t v[32],
|
|
Packit |
34410b |
uint8_t x[16], uint8_t z, uint8_t res[16])
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
uint8_t m[65];
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (!crypto)
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
m[0] = z;
|
|
Packit |
34410b |
memcpy(&m[1], v, 32);
|
|
Packit |
34410b |
memcpy(&m[33], u, 32);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return aes_cmac(crypto, x, m, sizeof(m), res);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
bool bt_crypto_f5(struct bt_crypto *crypto, uint8_t w[32], uint8_t n1[16],
|
|
Packit |
34410b |
uint8_t n2[16], uint8_t a1[7], uint8_t a2[7],
|
|
Packit |
34410b |
uint8_t mackey[16], uint8_t ltk[16])
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
uint8_t btle[4] = { 0x65, 0x6c, 0x74, 0x62 };
|
|
Packit |
34410b |
uint8_t salt[16] = { 0xbe, 0x83, 0x60, 0x5a, 0xdb, 0x0b, 0x37, 0x60,
|
|
Packit |
34410b |
0x38, 0xa5, 0xf5, 0xaa, 0x91, 0x83, 0x88, 0x6c };
|
|
Packit |
34410b |
uint8_t length[2] = { 0x00, 0x01 };
|
|
Packit |
34410b |
uint8_t m[53], t[16];
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (!aes_cmac(crypto, salt, w, 32, t))
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
memcpy(&m[0], length, 2);
|
|
Packit |
34410b |
memcpy(&m[2], a2, 7);
|
|
Packit |
34410b |
memcpy(&m[9], a1, 7);
|
|
Packit |
34410b |
memcpy(&m[16], n2, 16);
|
|
Packit |
34410b |
memcpy(&m[32], n1, 16);
|
|
Packit |
34410b |
memcpy(&m[48], btle, 4);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
m[52] = 0; /* Counter */
|
|
Packit |
34410b |
if (!aes_cmac(crypto, t, m, sizeof(m), mackey))
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
m[52] = 1; /* Counter */
|
|
Packit |
34410b |
return aes_cmac(crypto, t, m, sizeof(m), ltk);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
bool bt_crypto_f6(struct bt_crypto *crypto, uint8_t w[16], uint8_t n1[16],
|
|
Packit |
34410b |
uint8_t n2[16], uint8_t r[16], uint8_t io_cap[3],
|
|
Packit |
34410b |
uint8_t a1[7], uint8_t a2[7], uint8_t res[16])
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
uint8_t m[65];
|
|
Packit |
34410b |
|
|
Packit |
34410b |
memcpy(&m[0], a2, 7);
|
|
Packit |
34410b |
memcpy(&m[7], a1, 7);
|
|
Packit |
34410b |
memcpy(&m[14], io_cap, 3);
|
|
Packit |
34410b |
memcpy(&m[17], r, 16);
|
|
Packit |
34410b |
memcpy(&m[33], n2, 16);
|
|
Packit |
34410b |
memcpy(&m[49], n1, 16);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return aes_cmac(crypto, w, m, sizeof(m), res);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
bool bt_crypto_g2(struct bt_crypto *crypto, uint8_t u[32], uint8_t v[32],
|
|
Packit |
34410b |
uint8_t x[16], uint8_t y[16], uint32_t *val)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
uint8_t m[80], tmp[16];
|
|
Packit |
34410b |
|
|
Packit |
34410b |
memcpy(&m[0], y, 16);
|
|
Packit |
34410b |
memcpy(&m[16], v, 32);
|
|
Packit |
34410b |
memcpy(&m[48], u, 32);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (!aes_cmac(crypto, x, m, sizeof(m), tmp))
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
*val = get_le32(tmp);
|
|
Packit |
34410b |
*val %= 1000000;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return true;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
bool bt_crypto_h6(struct bt_crypto *crypto, const uint8_t w[16],
|
|
Packit |
34410b |
const uint8_t keyid[4], uint8_t res[16])
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
if (!aes_cmac(crypto, w, keyid, 4, res))
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return true;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
bool bt_crypto_gatt_hash(struct bt_crypto *crypto, struct iovec *iov,
|
|
Packit |
34410b |
size_t iov_len, uint8_t res[16])
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
const uint8_t key[16] = {};
|
|
Packit |
34410b |
ssize_t len;
|
|
Packit |
34410b |
int fd;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (!crypto)
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
fd = alg_new(crypto->cmac_aes, key, 16);
|
|
Packit |
34410b |
if (fd < 0)
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
len = writev(fd, iov, iov_len);
|
|
Packit |
34410b |
if (len < 0) {
|
|
Packit |
34410b |
close(fd);
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
len = read(fd, res, 16);
|
|
Packit |
34410b |
if (len < 0) {
|
|
Packit |
34410b |
close(fd);
|
|
Packit |
34410b |
return false;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
close(fd);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return true;
|
|
Packit |
34410b |
}
|