bare version of security manager unit test

This commit is contained in:
matthias.ringwald@gmail.com 2014-04-11 15:14:38 +00:00
parent 4762dcfac9
commit fdcd1130d4
7 changed files with 1604 additions and 0 deletions

View File

@ -0,0 +1,38 @@
CC = g++
# Requirements: http://www.cpputest.org/ should be placed in btstack/test
BTSTACK_ROOT = ../..
CPPUTEST_HOME = ${BTSTACK_ROOT}/test/cpputest
CFLAGS = -DUNIT_TEST -g -Wall -I. -I${BTSTACK_ROOT}/src -I${BTSTACK_ROOT}/ble -I${BTSTACK_ROOT}/include -I$(CPPUTEST_HOME)/include
LDFLAGS += -L$(CPPUTEST_HOME) -lCppUTest -lCppUTestExt
COMMON = \
${BTSTACK_ROOT}/src/utils.c \
${BTSTACK_ROOT}/src/btstack_memory.c \
${BTSTACK_ROOT}/src/memory_pool.c \
${BTSTACK_ROOT}/src/linked_list.c \
${BTSTACK_ROOT}/src/sdp_util.c \
${BTSTACK_ROOT}/src/remote_device_db_memory.c \
${BTSTACK_ROOT}/src/run_loop.c \
${BTSTACK_ROOT}/src/run_loop_posix.c \
${BTSTACK_ROOT}/src/hci_cmds.c \
${BTSTACK_ROOT}/src/hci_dump.c \
${BTSTACK_ROOT}/ble/sm.c \
${BTSTACK_ROOT}/ble/central_device_db_memory.c \
rijndael.c \
mock.c
COMMON_OBJ = $(COMMON:.c=.o)
all: security_manager
security_manager: ${CORE_OBJ} ${COMMON_OBJ} security_manager.c
${CC} ${CORE_OBJ} ${COMMON_OBJ} security_manager.c ${CFLAGS} ${LDFLAGS} -o $@
clean:
rm -f security_manager
rm -f *.o ${BTSTACK_ROOT}/src/*.o
rm -rf *.dSYM

View File

@ -0,0 +1,17 @@
// config.h created by configure for BTstack Tue Jun 4 23:10:20 CEST 2013
#define HAVE_TRANSPORT_USB
#define HAVE_BLE
#define USE_POSIX_RUN_LOOP
#define HAVE_SDP
#define HAVE_RFCOMM
#define REMOTE_DEVICE_DB remote_device_db_iphone
#define HAVE_SO_NOSIGPIPE
#define HAVE_TIME
#define HAVE_MALLOC
#define HAVE_BZERO
#define SDP_DES_DUMP
#define ENABLE_LOG_INFO
#define ENABLE_LOG_ERROR
#define HCI_ACL_PAYLOAD_SIZE 1021
#define HAVE_HCI_DUMP
#define SDP_DES_DUMP

View File

@ -0,0 +1,182 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <btstack/btstack.h>
#include "att.h"
#include "hci.h"
#include "hci_dump.h"
#include "l2cap.h"
#include "rijndael.h"
static btstack_packet_handler_t le_data_handler;
static void (*event_packet_handler) (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) = NULL;
static const uint16_t max_mtu = 23;
static uint8_t l2cap_stack_buffer[max_mtu];
static uint8_t aes128_cyphertext[16];
void aes128_calc_cyphertext(uint8_t key[16], uint8_t plaintext[16], uint8_t cyphertext[16]){
uint32_t rk[RKLENGTH(KEYBITS)];
int nrounds = rijndaelSetupEncrypt(rk, &key[0], KEYBITS);
rijndaelEncrypt(rk, nrounds, plaintext, cyphertext);
}
void mock_simulate_hci_event(uint8_t * packet, uint16_t size){
hci_dump_packet(HCI_EVENT_PACKET, 1, packet, size);
event_packet_handler(NULL, HCI_EVENT_PACKET, NULL, packet, size);
}
void aes128_report_result(){
uint8_t le_enc_result[22];
uint8_t enc1_data[] = { 0x0e, 0x14, 0x01, 0x17, 0x20, 0x00 };
memcpy (le_enc_result, enc1_data, 6);
swap128(aes128_cyphertext, &le_enc_result[6]);
mock_simulate_hci_event(&le_enc_result[0], sizeof(le_enc_result));
}
void mock_simulate_sm_data_packet(uint8_t * packet, uint16_t len){
uint16_t handle = 0x40;
uint16_t cid = 0x06;
uint8_t acl_buffer[len + 8];
// 0 - Connection handle : PB=10 : BC=00
bt_store_16(acl_buffer, 0, handle | (2 << 12) | (0 << 14));
// 2 - ACL length
bt_store_16(acl_buffer, 2, len + 4);
// 4 - L2CAP packet length
bt_store_16(acl_buffer, 4, len + 0);
// 6 - L2CAP channel DEST
bt_store_16(acl_buffer, 6, cid);
memcpy(&acl_buffer[8], packet, len);
hci_dump_packet(HCI_ACL_DATA_PACKET, 1, &acl_buffer[0], len + 8);
le_data_handler(SM_DATA_PACKET, handle, packet, len);
}
void mock_simulate_command_complete(const hci_cmd_t *cmd){
uint8_t packet[] = {HCI_EVENT_COMMAND_COMPLETE, 4, 1, cmd->opcode & 0xff, cmd->opcode >> 8, 0};
mock_simulate_hci_event((uint8_t *)&packet, sizeof(packet));
}
void mock_simulate_hci_state_working(){
uint8_t packet[] = {BTSTACK_EVENT_STATE, 0, HCI_STATE_WORKING};
mock_simulate_hci_event((uint8_t *)&packet, sizeof(packet));
}
void mock_simulate_connected(){
uint8_t packet[] = { 0x3e, 0x13, 0x01, 0x00, 0x40, 0x00, 0x01, 0x01, 0x18, 0x12, 0x5e, 0x68, 0xc9, 0x73, 0x18, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05};
mock_simulate_hci_event((uint8_t *)&packet, sizeof(packet));
}
void att_init_connection(att_connection_t * att_connection){
att_connection->mtu = 23;
att_connection->encryption_key_size = 0;
att_connection->authenticated = 0;
att_connection->authorized = 0;
}
int hci_can_send_packet_now_using_packet_buffer(uint8_t packet_type){
return 1;
}
// get addr type and address used in advertisement packets
void hci_le_advertisement_address(uint8_t * addr_type, bd_addr_t * addr){
*addr_type = 0;
uint8_t dummy[] = { 0x00, 0x1b, 0xdc, 0x07, 0x32, 0xef };
memcpy(addr, dummy, 6);
}
int l2cap_can_send_connectionless_packet_now(void){
return 1;
}
int hci_send_cmd(const hci_cmd_t *cmd, ...){
uint8_t cmd_buffer[256];
va_list argptr;
va_start(argptr, cmd);
uint16_t len = hci_create_cmd_internal(cmd_buffer, cmd, argptr);
va_end(argptr);
hci_dump_packet(HCI_COMMAND_DATA_PACKET, 0, cmd_buffer, len);
// track le encrypt and le rand
if (cmd->opcode == hci_le_encrypt.opcode){
uint8_t * key_flipped = &cmd_buffer[3];
uint8_t * plaintext_flipped = &cmd_buffer[19];
uint8_t key[16];
uint8_t plaintext[16];
swap128(key_flipped, key);
swap128(plaintext_flipped, plaintext);
printf("le_encrypt key ");
hexdump(key_flipped, 16);
printf("le_encrypt txt ");
hexdump(plaintext_flipped, 16);
aes128_calc_cyphertext(key, plaintext, aes128_cyphertext);
printf("le_encrypt res ");
hexdump(aes128_cyphertext, 16);
}
return 0;
}
uint8_t *l2cap_get_outgoing_buffer(void){
printf("l2cap_get_outgoing_buffer\n");
return (uint8_t *)&l2cap_stack_buffer; // 8 bytes
}
uint16_t l2cap_max_mtu(void){
printf("l2cap_max_mtu\n");
return max_mtu;
}
void l2cap_register_fixed_channel(btstack_packet_handler_t packet_handler, uint16_t channel_id) {
le_data_handler = packet_handler;
}
void l2cap_register_packet_handler(void (*handler)(void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)){
event_packet_handler = handler;
}
int l2cap_reserve_packet_buffer(void){
printf("l2cap_reserve_packet_buffer\n");
return 1;
}
int l2cap_send_prepared_connectionless(uint16_t handle, uint16_t cid, uint16_t len){
printf("l2cap_send_prepared_connectionless\n");
return 0;
}
int l2cap_send_connectionless(uint16_t handle, uint16_t cid, uint8_t * buffer, uint16_t len){
printf("l2cap_send_connectionless\n");
uint8_t acl_buffer[len + 8];
// 0 - Connection handle : PB=10 : BC=00
bt_store_16(acl_buffer, 0, handle | (2 << 12) | (0 << 14));
// 2 - ACL length
bt_store_16(acl_buffer, 2, len + 4);
// 4 - L2CAP packet length
bt_store_16(acl_buffer, 4, len + 0);
// 6 - L2CAP channel DEST
bt_store_16(acl_buffer, 6, cid);
memcpy(&acl_buffer[8], buffer, len);
hci_dump_packet(HCI_ACL_DATA_PACKET, 0, &acl_buffer[0], len + 8);
return 0;
}
void hci_disconnect_security_block(hci_con_handle_t con_handle){
printf("hci_disconnect_security_block \n");
}
void l2cap_run(void){
}

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,31 @@
// =============================== RIJNDAEL.H ===============================
// from http://www.efgh.com/software/rijndael.htm,
// License: Public Domain,
// Author: Philip J. Erdelsky
#ifndef H__RIJNDAEL
#define H__RIJNDAEL
#if defined __cplusplus
extern "C" {
#endif
#include <stdint.h>
int rijndaelSetupEncrypt(uint32_t *rk, const unsigned char *key, int keybits);
int rijndaelSetupDecrypt(uint32_t *rk, const unsigned char *key, int keybits);
void rijndaelEncrypt(const uint32_t *rk, int nrounds, const unsigned char plaintext[16], unsigned char ciphertext[16]);
void rijndaelDecrypt(const uint32_t *rk, int nrounds, const unsigned char ciphertext[16], unsigned char plaintext[16]);
#define KEYBITS 128
#define KEYLENGTH(keybits) ((keybits)/8)
#define RKLENGTH(keybits) ((keybits)/8+28)
#define NROUNDS(keybits) ((keybits)/32+6)
#if defined __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,119 @@
//*****************************************************************************
//
// test rfcomm query tests
//
//*****************************************************************************
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "CppUTest/TestHarness.h"
#include "CppUTest/CommandLineTestRunner.h"
#include <btstack/hci_cmds.h>
#include "btstack_memory.h"
#include "hci.h"
#include "hci_dump.h"
#include "l2cap.h"
#include "sm.h"
/*
SM: sending security request
SMP: generation method 0
p1 07 07 10 01 00 03 02 07 07 10 01 00 04 01 00 01
r 2F 04 82 84 72 46 9C 93 48 3F 27 0E EB D5 05 7A
t1 28 03 92 85 72 45 9E 94 4F 2F 26 0E EF D4 05 7B
p2 00 00 00 00 73 C9 68 5E 12 18 00 1B DC 07 32 EF
t3 CD FE D3 58 79 85 2C 84 A6 47 4D AD 7F 7B D0 87
c1! DA 42 76 BE B2 C0 17 A1 52 E3 96 C3 9A 8D E9 A9
p1 07 07 10 01 00 03 02 07 07 10 01 00 04 01 00 01
r 29 36 C0 5E F7 AC 43 D5 84 DC 1E 0F 45 06 D4 FD
t1 2E 31 D0 5F F7 AF 41 D2 83 CC 1F 0F 41 07 D4 FC
p2 00 00 00 00 73 C9 68 5E 12 18 00 1B DC 07 32 EF
t3 55 C2 AF B9 F9 95 5E 80 35 4D 48 B5 E4 BE D8 71
c1! C8 A9 70 70 A0 79 C5 48 BA 42 A9 0F 9A 87 5A 84
r1 2F 04 82 84 72 46 9C 93 48 3F 27 0E EB D5 05 7A
r2 29 36 C0 5E F7 AC 43 D5 84 DC 1E 0F 45 06 D4 FD
stk 30 95 98 99 12 1C 56 70 D1 D4 5F 8D 5F A2 36 D1
div 0xf1e2
y 0x45b9
ediv 0xb45b
ltk 73 30 38 B7 83 A3 C3 CF A1 E9 7A 04 0B D9 2F EF
Central Device DB adding type 1 - 73:C9:68:5E:12:18
irk 95 78 40 80 59 66 48 90 94 7F BB 92 53 91 7B C6
csrk 02 91 78 72 29 23 C5 F5 5F B1 99 94 42 5F 02 8D
*/
bd_addr_t test_device_addr = {0x34, 0xb1, 0xf7, 0xd1, 0x77, 0x9b};
void mock_simulate_hci_state_working();
void mock_simulate_hci_event(uint8_t * packet, uint16_t size);
void aes128_report_result();
void mock_simulate_sm_data_packet(uint8_t * packet, uint16_t size);
void mock_simulate_command_complete(const hci_cmd_t *cmd);
void mock_simulate_connected();
void hexdump2(void const *data, int size){
int i;
for (i=0; i<size;i++){
printf("%02X ", ((uint8_t *)data)[i]);
}
printf("\n");
}
void CHECK_EQUAL_ARRAY(uint8_t * expected, uint8_t * actual, int size){
int i;
for (i=0; i<size; i++){
BYTES_EQUAL(expected[i], actual[i]);
}
}
TEST_GROUP(GATTClient){
void setup(){
btstack_memory_init();
run_loop_init(RUN_LOOP_POSIX);
sm_init();
sm_set_io_capabilities(IO_CAPABILITY_NO_INPUT_NO_OUTPUT);
sm_set_authentication_requirements( SM_AUTHREQ_BONDING | SM_AUTHREQ_MITM_PROTECTION);
mock_simulate_hci_state_working();
aes128_report_result();
aes128_report_result();
mock_simulate_connected();
uint8_t test_pairing_request_command[] = { 0x01, 0x04, 0x00, 0x01, 0x10, 0x07, 0x07 };
mock_simulate_sm_data_packet(&test_pairing_request_command[0], sizeof(test_pairing_request_command));
uint8_t test_pairing_confirm_command[] = { 0x03, 0x84, 0x5a, 0x87, 0x9a, 0x0f, 0xa9, 0x42, 0xba, 0x48, 0xc5, 0x79, 0xa0, 0x70, 0x70, 0xa9, 0xc8 };
mock_simulate_sm_data_packet(&test_pairing_confirm_command[0], sizeof(test_pairing_confirm_command));
uint8_t rand1_data_event[] = { 0x0e, 0x0c, 0x01, 0x18, 0x20, 0x00, 0x2f, 0x04, 0x82, 0x84, 0x72, 0x46, 0x9c, 0x93 };
mock_simulate_hci_event(&rand1_data_event[0], sizeof(rand1_data_event));
uint8_t rand2_data_event[] = { 0x0e, 0x0c,0x01, 0x18,0x20, 0x00,0x48, 0x3f,0x27, 0x0e,0xeb, 0xd5,0x05, 0x7a };
mock_simulate_hci_event(&rand2_data_event[0], sizeof(rand2_data_event));
aes128_report_result();
aes128_report_result();
uint8_t test_pairing_random_command[] ={0x04, 0xfd, 0xd4, 0x06, 0x45, 0x0f, 0x1e, 0xdc, 0x84, 0xd5, 0x43, 0xac, 0xf7, 0x5e, 0xc0, 0x36, 0x29};
mock_simulate_sm_data_packet(&test_pairing_random_command[0], sizeof(test_pairing_random_command));
aes128_report_result();
aes128_report_result();
}
};
TEST(GATTClient, TestScanning){
}
int main (int argc, const char * argv[]){
hci_dump_open("hci_dump.pklg", HCI_DUMP_PACKETLOGGER);
return CommandLineTestRunner::RunAllTests(argc, argv);
}