2014-11-06 06:42:46

by Gu, Chao Jie

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

*This patch set give user dedicated command to set CSRK option and seperate from
signed write command implementation in previous patchset.
*Remove the valid_csrk flag, use struct signed_write_info make implementaion more
clear and simple.
*signed_counter will initialize automatically when CSRK setup, remove initialization
in bt_att_new procedure.

Gu Chaojie (3):
shared/att.c:Add signed command outgoing and CSRK function
shared/gatt-client:Add CSRK part to support signed write
tools/btgatt-client:Add signed write with CSRK option

src/shared/att-types.h | 3 +
src/shared/att.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++-
src/shared/att.h | 12 ++++
src/shared/gatt-client.c | 21 +++++--
src/shared/gatt-client.h | 4 ++
tools/btgatt-client.c | 69 +++++++++++++++++++++-
6 files changed, 245 insertions(+), 10 deletions(-)

--
1.9.1



2014-11-06 06:42:49

by Gu, Chao Jie

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

---
tools/btgatt-client.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 67 insertions(+), 2 deletions(-)

diff --git a/tools/btgatt-client.c b/tools/btgatt-client.c
index 7a1204f..f175cf2 100644
--- a/tools/btgatt-client.c
+++ b/tools/btgatt-client.c
@@ -505,12 +505,14 @@ 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-s, --signed-write\tsigned write command\n"
"e.g.:\n"
"\twrite-value 0x0001 00 01 00\n");
}

static struct option write_value_options[] = {
{ "without-response", 0, 0, 'w' },
+ { "signed-write", 0, 0, 's' },
{ }
};

@@ -534,6 +536,7 @@ 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;

if (!bt_gatt_client_is_ready(cli->gatt)) {
printf("GATT client not initialized\n");
@@ -548,12 +551,15 @@ 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, "+ws", write_value_options,
NULL)) != -1) {
switch (opt) {
case 'w':
without_response = true;
break;
+ case 's':
+ signed_write = true;
+ break;
default:
write_value_usage();
return;
@@ -607,7 +613,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;
@@ -858,6 +864,63 @@ static void cmd_unregister_notify(struct client *cli, char *cmd_str)
printf("Unregistered notify handler with id: %u\n", id);
}

+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 set_csrk_usage(void)
+{
+ printf("Usage: set-csrk [options]\nOptions:\n"
+ "\t -c, --csrk <csrk>\tCSRK\n"
+ "e.g.:\n"
+ "\tset-csrk -c D8515948451FEA320DC05A2E88308188\n");
+}
+
+static void cmd_set_csrk(struct client *cli, char *cmd_str)
+{
+ char *argv[3];
+ int argc = 0;
+ uint8_t csrk[16];
+
+ memset(csrk, 0, 16);
+
+ if (!bt_gatt_client_is_ready(cli->gatt)) {
+ printf("GATT client not initialized\n");
+ return;
+ }
+
+ if (!parse_args(cmd_str, 2, argv, &argc)) {
+ set_csrk_usage();
+ return;
+ }
+
+ if (argc != 2) {
+ set_csrk_usage();
+ return;
+ }
+
+ if (!strcmp(argv[0], "-c") || !strcmp(argv[0], "--csrk")) {
+ if (convert_csrk_key(argv[1], csrk))
+ bt_gatt_client_set_local_csrk(cli->gatt, 0, csrk);
+
+ } else
+ set_csrk_usage();
+}
+
static void cmd_help(struct client *cli, char *cmd_str);

typedef void (*command_func_t)(struct client *cli, char *cmd_str);
@@ -881,6 +944,8 @@ static struct {
"\tSubscribe to not/ind from a characteristic" },
{ "unregister-notify", cmd_unregister_notify,
"Unregister a not/ind session"},
+ { "set-csrk", cmd_set_csrk,
+ "\tSet CSRK for signed write command"},
{ }
};

--
1.9.1


2014-11-06 06:42:47

by Gu, Chao Jie

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

---
src/shared/att-types.h | 3 +
src/shared/att.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++-
src/shared/att.h | 12 ++++
3 files changed, 158 insertions(+), 3 deletions(-)

diff --git a/src/shared/att-types.h b/src/shared/att-types.h
index a6b23e4..1bea1ef 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 6adde22..988eaff 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
@@ -44,6 +45,8 @@

struct att_send_op;

+struct sign_write_info;
+
struct bt_att {
int ref_count;
int fd;
@@ -79,6 +82,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;
+
+ struct sign_write_info *local_info;
+ struct sign_write_info *remote_info;
+};
+
+struct sign_write_info {
+ uint8_t csrk[16];
+ uint32_t sign_cnt;
};

enum att_op_type {
@@ -178,6 +191,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)
@@ -289,6 +304,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;
@@ -305,17 +324,36 @@ 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))
+ return true;
+
+ if (!att->local_info)
+ return false;
+
+ if (!(bt_crypto_sign_att(att->crypto,
+ att->local_info->csrk,
+ op->pdu,
+ 1 + length,
+ att->local_info->sign_cnt,
+ &((uint8_t *) op->pdu)[1 + length])))
+ return false;
+
+ att->local_info->sign_cnt++;
+
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;
@@ -346,6 +384,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);
@@ -756,6 +795,8 @@ struct bt_att *bt_att_new(int fd)

att->fd = fd;

+ att->local_info = NULL;
+ att->remote_info = NULL;
att->mtu = BT_ATT_DEFAULT_LE_MTU;
att->buf = malloc(att->mtu);
if (!att->buf)
@@ -765,6 +806,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;
@@ -799,6 +844,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);
@@ -852,6 +898,16 @@ void bt_att_unref(struct bt_att *att)
if (att->debug_destroy)
att->debug_destroy(att->debug_data);

+ if (att->local_info) {
+ free(att->local_info);
+ att->local_info = NULL;
+ }
+
+ if (att->remote_info) {
+ free(att->remote_info);
+ att->remote_info = NULL;
+ }
+
free(att->buf);
att->buf = NULL;

@@ -995,7 +1051,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;
@@ -1178,3 +1234,87 @@ bool bt_att_unregister_all(struct bt_att *att)

return true;
}
+
+bool bt_att_set_local_csrk(struct bt_att *att, uint32_t local_sign_cnt,
+ uint8_t local_key[16])
+{
+ struct sign_write_info *local_sign_info;
+
+ if (!att)
+ return false;
+
+ local_sign_info = att->local_info;
+
+ if (!local_sign_info) {
+ local_sign_info = new0(struct sign_write_info, 1);
+ if (!local_sign_info)
+ return false;
+ att->local_info = local_sign_info;
+ }
+
+ local_sign_info->sign_cnt = local_sign_cnt;
+ memcpy(local_sign_info->csrk, local_key, 16);
+
+ return true;
+}
+
+bool bt_att_set_remote_csrk(struct bt_att *att, uint32_t remote_sign_cnt,
+ uint8_t remote_key[16])
+{
+ struct sign_write_info *remote_sign_info;
+
+ if (!att)
+ return false;
+
+ remote_sign_info = att->remote_info;
+
+ if (!remote_sign_info) {
+ remote_sign_info = new0(struct sign_write_info, 1);
+ if (!remote_sign_info)
+ return false;
+ att->remote_info = remote_sign_info;
+ }
+
+ remote_sign_info->sign_cnt = remote_sign_cnt;
+ memcpy(remote_sign_info->csrk, remote_key, 16);
+
+ return true;
+}
+
+bool bt_att_get_local_csrk(struct bt_att *att, uint8_t local_key[16],
+ uint32_t *local_sign_cnt)
+{
+ struct sign_write_info *local_sign_info;
+
+ if (!att)
+ return false;
+
+ if (!att->local_info)
+ return false;
+
+ local_sign_info = att->local_info;
+
+ memcpy(local_key, local_sign_info->csrk, 16);
+ *local_sign_cnt = local_sign_info->sign_cnt;
+
+ return true;
+}
+
+bool bt_att_get_remote_csrk(struct bt_att *att, uint8_t remote_key[16],
+ uint32_t *remote_sign_cnt)
+{
+ struct sign_write_info *remote_sign_info;
+
+ if (!att)
+ return false;
+
+ if (!att->remote_info)
+ return false;
+
+ remote_sign_info = att->remote_info;
+
+ memcpy(remote_key, remote_sign_info->csrk, 16);
+ *remote_sign_cnt = remote_sign_info->sign_cnt;
+
+ return true;
+}
diff --git a/src/shared/att.h b/src/shared/att.h
index 1063021..d232d22 100644
--- a/src/shared/att.h
+++ b/src/shared/att.h
@@ -76,3 +76,15 @@ 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_local_csrk(struct bt_att *att, uint32_t local_sign_cnt,
+ uint8_t local_key[16]);
+
+bool bt_att_set_remote_csrk(struct bt_att *att, uint32_t remote_sign_cnt,
+ uint8_t remote_key[16]);
+
+bool bt_att_get_local_csrk(struct bt_att *att, uint8_t local_key[16],
+ uint32_t *local_sign_cnt);
+
+bool bt_att_get_remote_csrk(struct bt_att *att, uint8_t remote_key[16],
+ uint32_t *remote_sign_cnt);
--
1.9.1


2014-11-06 06:42:48

by Gu, Chao Jie

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

---
src/shared/gatt-client.c | 21 ++++++++++++++++-----
src/shared/gatt-client.h | 4 ++++
2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index 8689368..0d406f5 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -1987,19 +1987,20 @@ 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)
+ return bt_att_send(client->att, BT_ATT_OP_SIGNED_WRITE_CMD,
+ pdu, sizeof(pdu), NULL, NULL, NULL);
+
return bt_att_send(client->att, BT_ATT_OP_WRITE_CMD, pdu, sizeof(pdu),
NULL, NULL, NULL);
}
@@ -2480,3 +2481,13 @@ bool bt_gatt_client_unregister_notify(struct bt_gatt_client *client,
client->need_notify_cleanup = true;
return true;
}
+
+bool bt_gatt_client_set_local_csrk(struct bt_gatt_client *client,
+ uint32_t local_sign_cnt,
+ uint8_t local_key[16])
+{
+ if (!client)
+ return false;
+
+ return bt_att_set_local_csrk(client->att, local_sign_cnt, local_key);
+}
diff --git a/src/shared/gatt-client.h b/src/shared/gatt-client.h
index adccfc5..5429576 100644
--- a/src/shared/gatt-client.h
+++ b/src/shared/gatt-client.h
@@ -171,3 +171,7 @@ 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_local_csrk(struct bt_gatt_client *client,
+ uint32_t local_sign_cnt,
+ uint8_t local_key[16]);
--
1.9.1