This patch set adds signed write command outgoing.
Patch set v1 cannot apply on latest source code
because it conflict with Arman's newest patch.
Gu Chaojie (3):
shared/att.c: Add signed command outgoing and related CSRK function
shared/gatt-client: Add CSRK part to support signed write
tools/btgatt-client: Add signed write CSRK option
src/shared/att-types.h | 3 ++
src/shared/att.c | 101 ++++++++++++++++++++++++++++++++++++++++++++--
src/shared/att.h | 13 ++++++
src/shared/gatt-client.c | 28 ++++++++++---
src/shared/gatt-client.h | 5 +++
tools/btgatt-client.c | 35 +++++++++++++++-
6 files changed, 175 insertions(+), 10 deletions(-)
--
1.7.10.4
SGksIFN6eW1vbiwNCiANCj4gT24gVGh1cnNkYXkgMjUgb2YgU2VwdGVtYmVyIDIwMTQgMTY6Mjg6
NTUgR3UgQ2hhb2ppZSB3cm90ZToNCj4gPiBUaGlzIHBhdGNoIHNldCBhZGRzIHNpZ25lZCB3cml0
ZSBjb21tYW5kIG91dGdvaW5nLg0KPiA+IFBhdGNoIHNldCB2MSBjYW5ub3QgYXBwbHkgb24gbGF0
ZXN0IHNvdXJjZSBjb2RlIGJlY2F1c2UgaXQgY29uZmxpY3QNCj4gPiB3aXRoIEFybWFuJ3MgbmV3
ZXN0IHBhdGNoLg0KPiA+DQo+ID4gR3UgQ2hhb2ppZSAoMyk6DQo+ID4gICBzaGFyZWQvYXR0LmM6
IEFkZCBzaWduZWQgY29tbWFuZCBvdXRnb2luZyBhbmQgcmVsYXRlZCBDU1JLIGZ1bmN0aW9uDQo+
ID4gICBzaGFyZWQvZ2F0dC1jbGllbnQ6IEFkZCBDU1JLIHBhcnQgdG8gc3VwcG9ydCBzaWduZWQg
d3JpdGUNCj4gPiAgIHRvb2xzL2J0Z2F0dC1jbGllbnQ6IEFkZCBzaWduZWQgd3JpdGUgQ1NSSyBv
cHRpb24NCj4gPg0KPiA+ICBzcmMvc2hhcmVkL2F0dC10eXBlcy5oICAgfCAgICAzICsrDQo+ID4g
IHNyYy9zaGFyZWQvYXR0LmMgICAgICAgICB8ICAxMDENCj4gKysrKysrKysrKysrKysrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKystLQ0KPiA+ICBzcmMvc2hhcmVkL2F0dC5oICAgICAgICAg
fCAgIDEzICsrKysrKw0KPiA+ICBzcmMvc2hhcmVkL2dhdHQtY2xpZW50LmMgfCAgIDI4ICsrKysr
KysrKystLS0NCj4gPiAgc3JjL3NoYXJlZC9nYXR0LWNsaWVudC5oIHwgICAgNSArKysNCj4gPiAg
dG9vbHMvYnRnYXR0LWNsaWVudC5jICAgIHwgICAzNSArKysrKysrKysrKysrKystDQo+ID4gIDYg
ZmlsZXMgY2hhbmdlZCwgMTc1IGluc2VydGlvbnMoKyksIDEwIGRlbGV0aW9ucygtKQ0KPiA+DQo+
IA0KPiBUaGlzIGRvZXNuJ3QgbGluazoNCj4gDQo+ICAgQ0NMRCAgICAgdG9vbHMvYnRnYXR0LWNs
aWVudA0KPiBzcmMvc2hhcmVkL2F0dC5vOiBJbiBmdW5jdGlvbiBgYnRfYXR0X25ldyc6DQo+IGJs
dWV6L3NyYy9zaGFyZWQvYXR0LmM6NzQ1OiB1bmRlZmluZWQgcmVmZXJlbmNlIHRvIGBidF9jcnlw
dG9fbmV3Jw0KPiBibHVlei9zcmMvc2hhcmVkL2F0dC5jOjc4MzogdW5kZWZpbmVkIHJlZmVyZW5j
ZSB0byBgYnRfY3J5cHRvX3VucmVmJw0KPiBzcmMvc2hhcmVkL2F0dC5vOiBJbiBmdW5jdGlvbiBg
ZW5jb2RlX3BkdSc6DQo+IGJsdWV6L3NyYy9zaGFyZWQvYXR0LmM6MzE0OiB1bmRlZmluZWQgcmVm
ZXJlbmNlIHRvIGBidF9jcnlwdG9fc2lnbl9hdHQnDQo+IA0KDQpZb3UgaGF2ZSB0byBtb2RpZnkg
TWFrZUZpbGUgdG8gYWRkIHNoYXJlZC9jcnlwdG8gbW9kdWxlICwgaG93ZXZlciwgTWFrZWZpbGUg
aW4NCnRoZSAuZ2l0aWdub3JlIGZpbGUgLCBzbyB0aGlzIHBhdGNoIHNldCBkb2VzIG5vdCBpbmNs
dWRlIHRoaXMgY2hhbmdlLg0KDQpUaGFua3MNCkNoYW9qaWUgR3UNCg==
Hi Gu Chaojie,
On Thursday 25 of September 2014 16:28:55 Gu Chaojie wrote:
> This patch set adds signed write command outgoing.
> Patch set v1 cannot apply on latest source code
> because it conflict with Arman's newest patch.
>
> Gu Chaojie (3):
> shared/att.c: Add signed command outgoing and related CSRK function
> shared/gatt-client: Add CSRK part to support signed write
> tools/btgatt-client: Add signed write CSRK option
>
> src/shared/att-types.h | 3 ++
> src/shared/att.c | 101 ++++++++++++++++++++++++++++++++++++++++++++--
> src/shared/att.h | 13 ++++++
> src/shared/gatt-client.c | 28 ++++++++++---
> src/shared/gatt-client.h | 5 +++
> tools/btgatt-client.c | 35 +++++++++++++++-
> 6 files changed, 175 insertions(+), 10 deletions(-)
>
This doesn't link:
CCLD tools/btgatt-client
src/shared/att.o: In function `bt_att_new':
bluez/src/shared/att.c:745: undefined reference to `bt_crypto_new'
bluez/src/shared/att.c:783: undefined reference to `bt_crypto_unref'
src/shared/att.o: In function `encode_pdu':
bluez/src/shared/att.c:314: undefined reference to `bt_crypto_sign_att'
--
Best regards,
Szymon Janc
This patch add CSRK option, use -c <key> to set CSRK for signed
write command. This key from pairing to store 32 byte key string
under group "LocalSignatureKey" in the info file.
---
tools/btgatt-client.c | 35 +++++++++++++++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/tools/btgatt-client.c b/tools/btgatt-client.c
index d900e08..585997e 100644
--- a/tools/btgatt-client.c
+++ b/tools/btgatt-client.c
@@ -486,11 +486,13 @@ static void write_value_usage(void)
printf("Usage: write-value [options] <value_handle> <value>\n"
"Options:\n"
"\t-w, --without-response\tWrite without response\n"
+ "\t-c, --csrk <key>\tCSRK for signed write command\n"
"e.g.:\n"
"\twrite-value 0x0001 00 01 00\n");
}
static struct option write_value_options[] = {
+ { "csrk", 1, 0, 'c' },
{ "without-response", 0, 0, 'w' },
{ }
};
@@ -504,6 +506,24 @@ static void write_cb(bool success, uint8_t att_ecode, void *user_data)
}
}
+static bool convert_csrk_key(char *optarg, uint8_t csrk[16])
+{
+ int i;
+ char value[2];
+
+ if (strlen(optarg) != 32) {
+ printf("csrk length is invalid\n");
+ return false;
+ } else {
+ for (i = 0; i < 16; i++) {
+ strncpy(value, optarg + (i * 2), 2);
+ csrk[i] = strtol(value, NULL, 16);
+ }
+ }
+
+ return true;
+}
+
static void cmd_write_value(struct client *cli, char *cmd_str)
{
int opt, i;
@@ -515,6 +535,11 @@ static void cmd_write_value(struct client *cli, char *cmd_str)
int length;
uint8_t *value = NULL;
bool without_response = false;
+ bool signed_write = false;
+ bool valid_csrk = false;
+ uint8_t csrk[16];
+
+ memset(csrk, 0, 16);
if (!bt_gatt_client_is_ready(cli->gatt)) {
printf("GATT client not initialized\n");
@@ -529,12 +554,18 @@ static void cmd_write_value(struct client *cli, char *cmd_str)
optind = 0;
argv[0] = "write-value";
- while ((opt = getopt_long(argc, argv, "+w", write_value_options,
+ while ((opt = getopt_long(argc, argv, "+wc:", write_value_options,
NULL)) != -1) {
switch (opt) {
case 'w':
without_response = true;
break;
+ case 'c':
+ signed_write = true;
+ valid_csrk = convert_csrk_key(optarg, csrk);
+ bt_gatt_client_set_csrk(cli->gatt, LOCAL_CSRK,
+ valid_csrk, csrk);
+ break;
default:
write_value_usage();
return;
@@ -588,7 +619,7 @@ static void cmd_write_value(struct client *cli, char *cmd_str)
if (without_response) {
if (!bt_gatt_client_write_without_response(cli->gatt, handle,
- false, value, length)) {
+ signed_write, value, length)) {
printf("Failed to initiate write without response "
"procedure\n");
goto done;
--
1.7.10.4
This patch focus on handling signed write in ATT stack.
extend struct bt_att to store CSRK related information
and struct att_send_op to replace mtu by struct bt_att
for signature PDU need.
And add three CSRK related function for upper layer
Set CSRK into bt_att structure
Get CSRK into bt_att structure
Decide if CSRK is valid or not
---
src/shared/att-types.h | 3 ++
src/shared/att.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++--
src/shared/att.h | 13 +++++++
3 files changed, 114 insertions(+), 3 deletions(-)
diff --git a/src/shared/att-types.h b/src/shared/att-types.h
index b85c969..da8b6ae 100644
--- a/src/shared/att-types.h
+++ b/src/shared/att-types.h
@@ -25,6 +25,9 @@
#define BT_ATT_DEFAULT_LE_MTU 23
+/* Length of signature in write signed packet */
+#define BT_ATT_SIGNATURE_LEN 12
+
/* ATT protocol opcodes */
#define BT_ATT_OP_ERROR_RSP 0x01
#define BT_ATT_OP_MTU_REQ 0x02
diff --git a/src/shared/att.c b/src/shared/att.c
index a5cab45..b31eb9e 100644
--- a/src/shared/att.c
+++ b/src/shared/att.c
@@ -36,6 +36,7 @@
#include "lib/uuid.h"
#include "src/shared/att.h"
#include "src/shared/att-types.h"
+#include "src/shared/crypto.h"
#define ATT_MIN_PDU_LEN 1 /* At least 1 byte for the opcode. */
#define ATT_OP_CMD_MASK 0x40
@@ -77,6 +78,16 @@ struct bt_att {
bt_att_debug_func_t debug_callback;
bt_att_destroy_func_t debug_destroy;
void *debug_data;
+
+ struct bt_crypto *crypto;
+
+ bool valid_local_csrk;
+ uint8_t local_csrk[16];
+ uint32_t local_sign_cnt;
+
+ bool valid_remote_csrk;
+ uint8_t remote_csrk[16];
+ uint32_t remote_sign_cnt;
};
enum att_op_type {
@@ -176,6 +187,8 @@ struct att_send_op {
bt_att_response_func_t callback;
bt_att_destroy_func_t destroy;
void *user_data;
+
+ struct bt_att *att;
};
static void destroy_att_send_op(void *data)
@@ -277,6 +290,10 @@ static bool encode_pdu(struct att_send_op *op, const void *pdu,
uint16_t length, uint16_t mtu)
{
uint16_t pdu_len = 1;
+ struct bt_att *att = op->att;
+
+ if (op->opcode & ATT_OP_SIGNED_MASK)
+ pdu_len += BT_ATT_SIGNATURE_LEN;
if (length && pdu)
pdu_len += length;
@@ -293,17 +310,32 @@ static bool encode_pdu(struct att_send_op *op, const void *pdu,
if (pdu_len > 1)
memcpy(op->pdu + 1, pdu, length);
+ if (op->opcode & ATT_OP_SIGNED_MASK) {
+ if (bt_crypto_sign_att(att->crypto,
+ att->local_csrk,
+ op->pdu,
+ 1 + length,
+ att->local_sign_cnt,
+ &((uint8_t *) op->pdu)[1 + length]))
+ att->local_sign_cnt++;
+ else
+ return false;
+ }
+
return true;
}
-static struct att_send_op *create_att_send_op(uint8_t opcode, const void *pdu,
- uint16_t length, uint16_t mtu,
+static struct att_send_op *create_att_send_op(uint8_t opcode,
+ const void *pdu,
+ uint16_t length,
+ struct bt_att *att,
bt_att_response_func_t callback,
void *user_data,
bt_att_destroy_func_t destroy)
{
struct att_send_op *op;
enum att_op_type op_type;
+ uint16_t mtu = att->mtu;
if (length && !pdu)
return NULL;
@@ -334,6 +366,7 @@ static struct att_send_op *create_att_send_op(uint8_t opcode, const void *pdu,
op->callback = callback;
op->destroy = destroy;
op->user_data = user_data;
+ op->att = att;
if (!encode_pdu(op, pdu, length, mtu)) {
free(op);
@@ -698,6 +731,8 @@ struct bt_att *bt_att_new(int fd)
att->fd = fd;
+ att->local_sign_cnt = 0;
+ att->remote_sign_cnt = 0;
att->mtu = BT_ATT_DEFAULT_LE_MTU;
att->buf = malloc(att->mtu);
if (!att->buf)
@@ -707,6 +742,10 @@ struct bt_att *bt_att_new(int fd)
if (!att->io)
goto fail;
+ att->crypto = bt_crypto_new();
+ if (!att->crypto)
+ goto fail;
+
att->req_queue = queue_new();
if (!att->req_queue)
goto fail;
@@ -741,6 +780,7 @@ fail:
queue_destroy(att->write_queue, NULL);
queue_destroy(att->notify_list, NULL);
queue_destroy(att->disconn_list, NULL);
+ bt_crypto_unref(att->crypto);
io_destroy(att->io);
free(att->buf);
free(att);
@@ -931,7 +971,7 @@ unsigned int bt_att_send(struct bt_att *att, uint8_t opcode,
if (!att || !att->io)
return 0;
- op = create_att_send_op(opcode, pdu, length, att->mtu, callback,
+ op = create_att_send_op(opcode, pdu, length, att, callback,
user_data, destroy);
if (!op)
return 0;
@@ -1116,3 +1156,58 @@ bool bt_att_unregister_all(struct bt_att *att)
return true;
}
+
+bool bt_att_set_csrk(struct bt_att *att, enum bt_csrk_type type,
+ bool valid_csrk, uint8_t key[16])
+{
+
+ bool local = (type == LOCAL_CSRK);
+
+ if (!att)
+ return false;
+
+ if (local) {
+ att->valid_local_csrk = valid_csrk;
+ memcpy(att->local_csrk, key, 16);
+ } else {
+ att->valid_remote_csrk = valid_csrk;
+ memcpy(att->remote_csrk, key, 16);
+ }
+
+ return true;
+}
+
+bool bt_att_get_csrk(struct bt_att *att, enum bt_csrk_type type,
+ uint8_t key[16], uint32_t *sign_cnt)
+{
+ bool local = (type == LOCAL_CSRK);
+
+ if (!att)
+ return false;
+
+ if (local && att->valid_local_csrk) {
+ memcpy(key, att->local_csrk, 16);
+ *sign_cnt = att->local_sign_cnt;
+ } else if (!local && att->valid_remote_csrk) {
+ memcpy(key, att->remote_csrk, 16);
+ *sign_cnt = att->remote_sign_cnt;
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+bool bt_att_csrk_is_valid(struct bt_att *att, enum bt_csrk_type type)
+{
+ bool local = (type == LOCAL_CSRK);
+
+ if (!att)
+ return false;
+
+ if (local)
+ return att->valid_local_csrk;
+ else
+ return att->valid_remote_csrk;
+
+}
diff --git a/src/shared/att.h b/src/shared/att.h
index 1063021..9a54f64 100644
--- a/src/shared/att.h
+++ b/src/shared/att.h
@@ -26,6 +26,11 @@
#include "src/shared/att-types.h"
+enum bt_csrk_type {
+ LOCAL_CSRK,
+ REMOTE_CSRK,
+};
+
struct bt_att;
struct bt_att *bt_att_new(int fd);
@@ -76,3 +81,11 @@ unsigned int bt_att_register_disconnect(struct bt_att *att,
bool bt_att_unregister_disconnect(struct bt_att *att, unsigned int id);
bool bt_att_unregister_all(struct bt_att *att);
+
+bool bt_att_set_csrk(struct bt_att *att, enum bt_csrk_type type,
+ bool valid_csrk, uint8_t key[16]);
+
+bool bt_att_get_csrk(struct bt_att *att, enum bt_csrk_type type,
+ uint8_t key[16], uint32_t *sign_cnt);
+
+bool bt_att_csrk_is_valid(struct bt_att *att, enum bt_csrk_type type);
--
1.7.10.4
This patch Add set CSRK function for btgatt-client tool and
check CSRK valid before bt_att_send signed write command to
remote side.
---
src/shared/gatt-client.c | 28 +++++++++++++++++++++++-----
src/shared/gatt-client.h | 5 +++++
2 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index 6dc8e95..d5ff994 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -1753,19 +1753,26 @@ bool bt_gatt_client_read_long_value(struct bt_gatt_client *client,
bool bt_gatt_client_write_without_response(struct bt_gatt_client *client,
uint16_t value_handle,
bool signed_write,
- uint8_t *value, uint16_t length) {
+ uint8_t *value, uint16_t length)
+{
uint8_t pdu[2 + length];
if (!client)
return 0;
- /* TODO: Support this once bt_att_send supports signed writes. */
- if (signed_write)
- return 0;
-
put_le16(value_handle, pdu);
memcpy(pdu + 2, value, length);
+ if (signed_write) {
+ if (bt_att_csrk_is_valid(client->att, LOCAL_CSRK))
+ return bt_att_send(client->att,
+ BT_ATT_OP_SIGNED_WRITE_CMD,
+ pdu, sizeof(pdu), NULL, NULL, NULL);
+ else
+ return 0;
+
+ }
+
return bt_att_send(client->att, BT_ATT_OP_WRITE_CMD, pdu, sizeof(pdu),
NULL, NULL, NULL);
}
@@ -2246,3 +2253,14 @@ bool bt_gatt_client_unregister_notify(struct bt_gatt_client *client,
client->need_notify_cleanup = true;
return true;
}
+
+bool bt_gatt_client_set_csrk(struct bt_gatt_client *client,
+ enum bt_csrk_type type,
+ bool valid_csrk,
+ uint8_t key[16])
+{
+ if (!client)
+ return false;
+
+ return bt_att_set_csrk(client->att, type, valid_csrk, key);
+}
diff --git a/src/shared/gatt-client.h b/src/shared/gatt-client.h
index 6807f6b..f05ecd9 100644
--- a/src/shared/gatt-client.h
+++ b/src/shared/gatt-client.h
@@ -162,3 +162,8 @@ bool bt_gatt_client_register_notify(struct bt_gatt_client *client,
bt_gatt_client_destroy_func_t destroy);
bool bt_gatt_client_unregister_notify(struct bt_gatt_client *client,
unsigned int id);
+
+bool bt_gatt_client_set_csrk(struct bt_gatt_client *client,
+ enum bt_csrk_type type,
+ bool valid_csrk,
+ uint8_t key[16]);
--
1.7.10.4