uint16_t enc_signed_write_cmd(uint16_t handle, const uint8_t *value, size_t vlen, struct bt_crypto *crypto, const uint8_t csrk[16], uint32_t sign_cnt, uint8_t *pdu, size_t len) { const uint16_t hdr_len = sizeof(pdu[0]) + sizeof(handle); const uint16_t min_len = hdr_len + ATT_SIGNATURE_LEN; if (pdu == NULL) return 0; if (vlen > len - min_len) vlen = len - min_len; pdu[0] = ATT_OP_SIGNED_WRITE_CMD; put_le16(handle, &pdu[1]); if (vlen > 0) memcpy(&pdu[hdr_len], value, vlen); if (!bt_crypto_sign_att(crypto, csrk, pdu, hdr_len + vlen, sign_cnt, &pdu[hdr_len + vlen])) return 0; return min_len + vlen; }
static bool encode_pdu(struct bt_att *att, struct att_send_op *op, const void *pdu, uint16_t length) { uint16_t pdu_len = 1; struct sign_info *sign = att->local_sign; uint32_t sign_cnt; if (sign && (op->opcode & ATT_OP_SIGNED_MASK)) pdu_len += BT_ATT_SIGNATURE_LEN; if (length && pdu) pdu_len += length; if (pdu_len > att->mtu) return false; op->len = pdu_len; op->pdu = malloc(op->len); if (!op->pdu) return false; ((uint8_t *) op->pdu)[0] = op->opcode; if (pdu_len > 1) memcpy(op->pdu + 1, pdu, length); if (!sign || !(op->opcode & ATT_OP_SIGNED_MASK) || !att->crypto) return true; if (!sign->counter(&sign_cnt, sign->user_data)) goto fail; if ((bt_crypto_sign_att(att->crypto, sign->key, op->pdu, 1 + length, sign_cnt, &((uint8_t *) op->pdu)[1 + length]))) return true; util_debug(att->debug_callback, att->debug_data, "ATT unable to generate signature"); fail: free(op->pdu); return false; }
static bool handle_signed(struct bt_att *att, uint8_t opcode, uint8_t *pdu, ssize_t pdu_len) { uint8_t *signature; uint32_t sign_cnt; struct sign_info *sign; /* Check if there is enough data for a signature */ if (pdu_len < 2 + BT_ATT_SIGNATURE_LEN) goto fail; sign = att->remote_sign; if (!sign) goto fail; signature = pdu + (pdu_len - BT_ATT_SIGNATURE_LEN); sign_cnt = get_le32(signature); /* Validate counter */ if (!sign->counter(&sign_cnt, sign->user_data)) goto fail; /* Generate signature and verify it */ if (!bt_crypto_sign_att(att->crypto, sign->key, pdu, pdu_len - BT_ATT_SIGNATURE_LEN, sign_cnt, signature)) goto fail; return true; fail: util_debug(att->debug_callback, att->debug_data, "ATT failed to verify signature: 0x%02x", opcode); return false; }