2014-09-25 08:28:55

by Gu, Chao Jie

[permalink] [raw]
Subject: [PATCH v2 0/3] support signed write command

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



2014-09-25 13:03:22

by Gu, Chao Jie

[permalink] [raw]
Subject: RE: [PATCH v2 0/3] support signed write command

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==

2014-09-25 08:54:57

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH v2 0/3] support signed write command

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

2014-09-25 08:28:58

by Gu, Chao Jie

[permalink] [raw]
Subject: [PATCH v2 3/3] tools/btgatt-client: Add signed write CSRK option

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


2014-09-25 08:28:56

by Gu, Chao Jie

[permalink] [raw]
Subject: [PATCH v2 1/3] shared/att.c: Add signed command outgoing and related CSRK function

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


2014-09-25 08:28:57

by Gu, Chao Jie

[permalink] [raw]
Subject: [PATCH v2 2/3] shared/gatt-client: Add CSRK part to support signed write

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