Fork ESP-IDF's bluetooth component
i want better sbc encoding, and no cla will stop me
This commit is contained in:
@@ -0,0 +1,938 @@
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
|
||||
|
||||
LICENSE TERMS
|
||||
|
||||
The redistribution and use of this software (with or without changes)
|
||||
is allowed without the payment of fees or royalties provided that:
|
||||
|
||||
1. source code distributions include the above copyright notice, this
|
||||
list of conditions and the following disclaimer;
|
||||
|
||||
2. binary distributions include the above copyright notice, this list
|
||||
of conditions and the following disclaimer in their documentation;
|
||||
|
||||
3. the name of the copyright holder is not used to endorse products
|
||||
built using this software without specific written permission.
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its properties, including, but not limited to, correctness
|
||||
and/or fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue 09/09/2006
|
||||
|
||||
This is an AES implementation that uses only 8-bit byte operations on the
|
||||
cipher state (there are options to use 32-bit types if available).
|
||||
|
||||
The combination of mix columns and byte substitution used here is based on
|
||||
that developed by Karl Malbrain. His contribution is acknowledged.
|
||||
*/
|
||||
|
||||
/* define if you have a fast memcpy function on your system */
|
||||
#if 1
|
||||
# define HAVE_MEMCPY
|
||||
# include <string.h>
|
||||
#if 0
|
||||
# if defined( _MSC_VER )
|
||||
# include <intrin.h>
|
||||
# pragma intrinsic( memcpy )
|
||||
# endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* add the target configuration to allow using internal data types and compilation options */
|
||||
#include "common/bt_target.h"
|
||||
|
||||
/* define if you have fast 32-bit types on your system */
|
||||
#if 1
|
||||
# define HAVE_UINT_32T
|
||||
#endif
|
||||
|
||||
/* define if you don't want any tables */
|
||||
#if 1
|
||||
# define USE_TABLES
|
||||
#endif
|
||||
|
||||
/* On Intel Core 2 duo VERSION_1 is faster */
|
||||
|
||||
/* alternative versions (test for performance on your system) */
|
||||
#if 1
|
||||
# define VERSION_1
|
||||
#endif
|
||||
|
||||
#include "aes.h"
|
||||
|
||||
#if defined( HAVE_UINT_32T )
|
||||
typedef UINT32 uint_32t;
|
||||
#endif
|
||||
|
||||
/* functions for finite field multiplication in the AES Galois field */
|
||||
|
||||
#define WPOLY 0x011b
|
||||
#define BPOLY 0x1b
|
||||
#define DPOLY 0x008d
|
||||
|
||||
#define f1(x) (x)
|
||||
#define f2(x) ((x << 1) ^ (((x >> 7) & 1) * WPOLY))
|
||||
#define f4(x) ((x << 2) ^ (((x >> 6) & 1) * WPOLY) ^ (((x >> 6) & 2) * WPOLY))
|
||||
#define f8(x) ((x << 3) ^ (((x >> 5) & 1) * WPOLY) ^ (((x >> 5) & 2) * WPOLY) \
|
||||
^ (((x >> 5) & 4) * WPOLY))
|
||||
#define d2(x) (((x) >> 1) ^ ((x) & 1 ? DPOLY : 0))
|
||||
|
||||
#define f3(x) (f2(x) ^ x)
|
||||
#define f9(x) (f8(x) ^ x)
|
||||
#define fb(x) (f8(x) ^ f2(x) ^ x)
|
||||
#define fd(x) (f8(x) ^ f4(x) ^ x)
|
||||
#define fe(x) (f8(x) ^ f4(x) ^ f2(x))
|
||||
|
||||
#if defined( USE_TABLES )
|
||||
|
||||
#define sb_data(w) { /* S Box data values */ \
|
||||
w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\
|
||||
w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\
|
||||
w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\
|
||||
w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\
|
||||
w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\
|
||||
w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\
|
||||
w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\
|
||||
w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\
|
||||
w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\
|
||||
w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\
|
||||
w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\
|
||||
w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\
|
||||
w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\
|
||||
w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\
|
||||
w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\
|
||||
w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\
|
||||
w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\
|
||||
w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\
|
||||
w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\
|
||||
w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\
|
||||
w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\
|
||||
w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\
|
||||
w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\
|
||||
w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\
|
||||
w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\
|
||||
w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\
|
||||
w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\
|
||||
w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\
|
||||
w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\
|
||||
w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\
|
||||
w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\
|
||||
w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) }
|
||||
|
||||
#define isb_data(w) { /* inverse S Box data values */ \
|
||||
w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\
|
||||
w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\
|
||||
w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\
|
||||
w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\
|
||||
w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\
|
||||
w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\
|
||||
w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\
|
||||
w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\
|
||||
w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\
|
||||
w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\
|
||||
w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\
|
||||
w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\
|
||||
w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\
|
||||
w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\
|
||||
w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\
|
||||
w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\
|
||||
w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\
|
||||
w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\
|
||||
w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\
|
||||
w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\
|
||||
w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\
|
||||
w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\
|
||||
w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\
|
||||
w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\
|
||||
w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\
|
||||
w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\
|
||||
w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\
|
||||
w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\
|
||||
w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\
|
||||
w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\
|
||||
w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\
|
||||
w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) }
|
||||
|
||||
#define mm_data(w) { /* basic data for forming finite field tables */ \
|
||||
w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\
|
||||
w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\
|
||||
w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\
|
||||
w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\
|
||||
w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\
|
||||
w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\
|
||||
w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\
|
||||
w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\
|
||||
w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\
|
||||
w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\
|
||||
w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\
|
||||
w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\
|
||||
w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\
|
||||
w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\
|
||||
w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\
|
||||
w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\
|
||||
w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\
|
||||
w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\
|
||||
w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\
|
||||
w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\
|
||||
w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\
|
||||
w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\
|
||||
w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\
|
||||
w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\
|
||||
w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\
|
||||
w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\
|
||||
w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\
|
||||
w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\
|
||||
w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\
|
||||
w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\
|
||||
w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\
|
||||
w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) }
|
||||
|
||||
static const uint_8t sbox[256] = sb_data(f1);
|
||||
static const uint_8t isbox[256] = isb_data(f1);
|
||||
|
||||
static const uint_8t gfm2_sbox[256] = sb_data(f2);
|
||||
static const uint_8t gfm3_sbox[256] = sb_data(f3);
|
||||
|
||||
static const uint_8t gfmul_9[256] = mm_data(f9);
|
||||
static const uint_8t gfmul_b[256] = mm_data(fb);
|
||||
static const uint_8t gfmul_d[256] = mm_data(fd);
|
||||
static const uint_8t gfmul_e[256] = mm_data(fe);
|
||||
|
||||
#define s_box(x) sbox[(x)]
|
||||
#define is_box(x) isbox[(x)]
|
||||
#define gfm2_sb(x) gfm2_sbox[(x)]
|
||||
#define gfm3_sb(x) gfm3_sbox[(x)]
|
||||
#define gfm_9(x) gfmul_9[(x)]
|
||||
#define gfm_b(x) gfmul_b[(x)]
|
||||
#define gfm_d(x) gfmul_d[(x)]
|
||||
#define gfm_e(x) gfmul_e[(x)]
|
||||
|
||||
#else
|
||||
|
||||
/* this is the high bit of x right shifted by 1 */
|
||||
/* position. Since the starting polynomial has */
|
||||
/* 9 bits (0x11b), this right shift keeps the */
|
||||
/* values of all top bits within a byte */
|
||||
|
||||
static uint_8t hibit(const uint_8t x)
|
||||
{
|
||||
uint_8t r = (uint_8t)((x >> 1) | (x >> 2));
|
||||
|
||||
r |= (r >> 2);
|
||||
r |= (r >> 4);
|
||||
return (r + 1) >> 1;
|
||||
}
|
||||
|
||||
/* return the inverse of the finite field element x */
|
||||
|
||||
static uint_8t gf_inv(const uint_8t x)
|
||||
{
|
||||
uint_8t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0;
|
||||
|
||||
if (x < 2) {
|
||||
return x;
|
||||
}
|
||||
|
||||
for ( ; ; ) {
|
||||
if (n1) {
|
||||
while (n2 >= n1) { /* divide polynomial p2 by p1 */
|
||||
n2 /= n1; /* shift smaller polynomial left */
|
||||
p2 ^= (p1 * n2) & 0xff; /* and remove from larger one */
|
||||
v2 ^= (v1 * n2); /* shift accumulated value and */
|
||||
n2 = hibit(p2); /* add into result */
|
||||
}
|
||||
} else {
|
||||
return v1;
|
||||
}
|
||||
|
||||
if (n2) { /* repeat with values swapped */
|
||||
while (n1 >= n2) {
|
||||
n1 /= n2;
|
||||
p1 ^= p2 * n1;
|
||||
v1 ^= v2 * n1;
|
||||
n1 = hibit(p1);
|
||||
}
|
||||
} else {
|
||||
return v2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* The forward and inverse affine transformations used in the S-box */
|
||||
uint_8t fwd_affine(const uint_8t x)
|
||||
{
|
||||
#if defined( HAVE_UINT_32T )
|
||||
uint_32t w = x;
|
||||
w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4);
|
||||
return 0x63 ^ ((w ^ (w >> 8)) & 0xff);
|
||||
#else
|
||||
return 0x63 ^ x ^ (x << 1) ^ (x << 2) ^ (x << 3) ^ (x << 4)
|
||||
^ (x >> 7) ^ (x >> 6) ^ (x >> 5) ^ (x >> 4);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint_8t inv_affine(const uint_8t x)
|
||||
{
|
||||
#if defined( HAVE_UINT_32T )
|
||||
uint_32t w = x;
|
||||
w = (w << 1) ^ (w << 3) ^ (w << 6);
|
||||
return 0x05 ^ ((w ^ (w >> 8)) & 0xff);
|
||||
#else
|
||||
return 0x05 ^ (x << 1) ^ (x << 3) ^ (x << 6)
|
||||
^ (x >> 7) ^ (x >> 5) ^ (x >> 2);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define s_box(x) fwd_affine(gf_inv(x))
|
||||
#define is_box(x) gf_inv(inv_affine(x))
|
||||
#define gfm2_sb(x) f2(s_box(x))
|
||||
#define gfm3_sb(x) f3(s_box(x))
|
||||
#define gfm_9(x) f9(x)
|
||||
#define gfm_b(x) fb(x)
|
||||
#define gfm_d(x) fd(x)
|
||||
#define gfm_e(x) fe(x)
|
||||
|
||||
#endif
|
||||
|
||||
#if defined( HAVE_MEMCPY )
|
||||
# define block_copy_nn(d, s, l) memcpy(d, s, l)
|
||||
# define block_copy(d, s) memcpy(d, s, N_BLOCK)
|
||||
#else
|
||||
# define block_copy_nn(d, s, l) copy_block_nn(d, s, l)
|
||||
# define block_copy(d, s) copy_block(d, s)
|
||||
#endif
|
||||
|
||||
#if !defined( HAVE_MEMCPY )
|
||||
static void copy_block( void *d, const void *s )
|
||||
{
|
||||
#if defined( HAVE_UINT_32T )
|
||||
((uint_32t *)d)[ 0] = ((uint_32t *)s)[ 0];
|
||||
((uint_32t *)d)[ 1] = ((uint_32t *)s)[ 1];
|
||||
((uint_32t *)d)[ 2] = ((uint_32t *)s)[ 2];
|
||||
((uint_32t *)d)[ 3] = ((uint_32t *)s)[ 3];
|
||||
#else
|
||||
((uint_8t *)d)[ 0] = ((uint_8t *)s)[ 0];
|
||||
((uint_8t *)d)[ 1] = ((uint_8t *)s)[ 1];
|
||||
((uint_8t *)d)[ 2] = ((uint_8t *)s)[ 2];
|
||||
((uint_8t *)d)[ 3] = ((uint_8t *)s)[ 3];
|
||||
((uint_8t *)d)[ 4] = ((uint_8t *)s)[ 4];
|
||||
((uint_8t *)d)[ 5] = ((uint_8t *)s)[ 5];
|
||||
((uint_8t *)d)[ 6] = ((uint_8t *)s)[ 6];
|
||||
((uint_8t *)d)[ 7] = ((uint_8t *)s)[ 7];
|
||||
((uint_8t *)d)[ 8] = ((uint_8t *)s)[ 8];
|
||||
((uint_8t *)d)[ 9] = ((uint_8t *)s)[ 9];
|
||||
((uint_8t *)d)[10] = ((uint_8t *)s)[10];
|
||||
((uint_8t *)d)[11] = ((uint_8t *)s)[11];
|
||||
((uint_8t *)d)[12] = ((uint_8t *)s)[12];
|
||||
((uint_8t *)d)[13] = ((uint_8t *)s)[13];
|
||||
((uint_8t *)d)[14] = ((uint_8t *)s)[14];
|
||||
((uint_8t *)d)[15] = ((uint_8t *)s)[15];
|
||||
#endif
|
||||
}
|
||||
|
||||
static void copy_block_nn( void *d, const void *s, uint_8t nn )
|
||||
{
|
||||
while ( nn-- ) {
|
||||
*((uint_8t *)d)++ = *((uint_8t *)s)++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void xor_block( void *d, const void *s )
|
||||
{
|
||||
#if defined( HAVE_UINT_32T )
|
||||
((uint_32t *)d)[ 0] ^= ((uint_32t *)s)[ 0];
|
||||
((uint_32t *)d)[ 1] ^= ((uint_32t *)s)[ 1];
|
||||
((uint_32t *)d)[ 2] ^= ((uint_32t *)s)[ 2];
|
||||
((uint_32t *)d)[ 3] ^= ((uint_32t *)s)[ 3];
|
||||
#else
|
||||
((uint_8t *)d)[ 0] ^= ((uint_8t *)s)[ 0];
|
||||
((uint_8t *)d)[ 1] ^= ((uint_8t *)s)[ 1];
|
||||
((uint_8t *)d)[ 2] ^= ((uint_8t *)s)[ 2];
|
||||
((uint_8t *)d)[ 3] ^= ((uint_8t *)s)[ 3];
|
||||
((uint_8t *)d)[ 4] ^= ((uint_8t *)s)[ 4];
|
||||
((uint_8t *)d)[ 5] ^= ((uint_8t *)s)[ 5];
|
||||
((uint_8t *)d)[ 6] ^= ((uint_8t *)s)[ 6];
|
||||
((uint_8t *)d)[ 7] ^= ((uint_8t *)s)[ 7];
|
||||
((uint_8t *)d)[ 8] ^= ((uint_8t *)s)[ 8];
|
||||
((uint_8t *)d)[ 9] ^= ((uint_8t *)s)[ 9];
|
||||
((uint_8t *)d)[10] ^= ((uint_8t *)s)[10];
|
||||
((uint_8t *)d)[11] ^= ((uint_8t *)s)[11];
|
||||
((uint_8t *)d)[12] ^= ((uint_8t *)s)[12];
|
||||
((uint_8t *)d)[13] ^= ((uint_8t *)s)[13];
|
||||
((uint_8t *)d)[14] ^= ((uint_8t *)s)[14];
|
||||
((uint_8t *)d)[15] ^= ((uint_8t *)s)[15];
|
||||
#endif
|
||||
}
|
||||
|
||||
static void copy_and_key( void *d, const void *s, const void *k )
|
||||
{
|
||||
#if defined( HAVE_UINT_32T )
|
||||
((uint_32t *)d)[ 0] = ((uint_32t *)s)[ 0] ^ ((uint_32t *)k)[ 0];
|
||||
((uint_32t *)d)[ 1] = ((uint_32t *)s)[ 1] ^ ((uint_32t *)k)[ 1];
|
||||
((uint_32t *)d)[ 2] = ((uint_32t *)s)[ 2] ^ ((uint_32t *)k)[ 2];
|
||||
((uint_32t *)d)[ 3] = ((uint_32t *)s)[ 3] ^ ((uint_32t *)k)[ 3];
|
||||
#elif 1
|
||||
((uint_8t *)d)[ 0] = ((uint_8t *)s)[ 0] ^ ((uint_8t *)k)[ 0];
|
||||
((uint_8t *)d)[ 1] = ((uint_8t *)s)[ 1] ^ ((uint_8t *)k)[ 1];
|
||||
((uint_8t *)d)[ 2] = ((uint_8t *)s)[ 2] ^ ((uint_8t *)k)[ 2];
|
||||
((uint_8t *)d)[ 3] = ((uint_8t *)s)[ 3] ^ ((uint_8t *)k)[ 3];
|
||||
((uint_8t *)d)[ 4] = ((uint_8t *)s)[ 4] ^ ((uint_8t *)k)[ 4];
|
||||
((uint_8t *)d)[ 5] = ((uint_8t *)s)[ 5] ^ ((uint_8t *)k)[ 5];
|
||||
((uint_8t *)d)[ 6] = ((uint_8t *)s)[ 6] ^ ((uint_8t *)k)[ 6];
|
||||
((uint_8t *)d)[ 7] = ((uint_8t *)s)[ 7] ^ ((uint_8t *)k)[ 7];
|
||||
((uint_8t *)d)[ 8] = ((uint_8t *)s)[ 8] ^ ((uint_8t *)k)[ 8];
|
||||
((uint_8t *)d)[ 9] = ((uint_8t *)s)[ 9] ^ ((uint_8t *)k)[ 9];
|
||||
((uint_8t *)d)[10] = ((uint_8t *)s)[10] ^ ((uint_8t *)k)[10];
|
||||
((uint_8t *)d)[11] = ((uint_8t *)s)[11] ^ ((uint_8t *)k)[11];
|
||||
((uint_8t *)d)[12] = ((uint_8t *)s)[12] ^ ((uint_8t *)k)[12];
|
||||
((uint_8t *)d)[13] = ((uint_8t *)s)[13] ^ ((uint_8t *)k)[13];
|
||||
((uint_8t *)d)[14] = ((uint_8t *)s)[14] ^ ((uint_8t *)k)[14];
|
||||
((uint_8t *)d)[15] = ((uint_8t *)s)[15] ^ ((uint_8t *)k)[15];
|
||||
#else
|
||||
block_copy(d, s);
|
||||
xor_block(d, k);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void add_round_key( uint_8t d[N_BLOCK], const uint_8t k[N_BLOCK] )
|
||||
{
|
||||
xor_block(d, k);
|
||||
}
|
||||
|
||||
static void shift_sub_rows( uint_8t st[N_BLOCK] )
|
||||
{
|
||||
uint_8t tt;
|
||||
|
||||
st[ 0] = s_box(st[ 0]); st[ 4] = s_box(st[ 4]);
|
||||
st[ 8] = s_box(st[ 8]); st[12] = s_box(st[12]);
|
||||
|
||||
tt = st[1]; st[ 1] = s_box(st[ 5]); st[ 5] = s_box(st[ 9]);
|
||||
st[ 9] = s_box(st[13]); st[13] = s_box( tt );
|
||||
|
||||
tt = st[2]; st[ 2] = s_box(st[10]); st[10] = s_box( tt );
|
||||
tt = st[6]; st[ 6] = s_box(st[14]); st[14] = s_box( tt );
|
||||
|
||||
tt = st[15]; st[15] = s_box(st[11]); st[11] = s_box(st[ 7]);
|
||||
st[ 7] = s_box(st[ 3]); st[ 3] = s_box( tt );
|
||||
}
|
||||
|
||||
static void inv_shift_sub_rows( uint_8t st[N_BLOCK] )
|
||||
{
|
||||
uint_8t tt;
|
||||
|
||||
st[ 0] = is_box(st[ 0]); st[ 4] = is_box(st[ 4]);
|
||||
st[ 8] = is_box(st[ 8]); st[12] = is_box(st[12]);
|
||||
|
||||
tt = st[13]; st[13] = is_box(st[9]); st[ 9] = is_box(st[5]);
|
||||
st[ 5] = is_box(st[1]); st[ 1] = is_box( tt );
|
||||
|
||||
tt = st[2]; st[ 2] = is_box(st[10]); st[10] = is_box( tt );
|
||||
tt = st[6]; st[ 6] = is_box(st[14]); st[14] = is_box( tt );
|
||||
|
||||
tt = st[3]; st[ 3] = is_box(st[ 7]); st[ 7] = is_box(st[11]);
|
||||
st[11] = is_box(st[15]); st[15] = is_box( tt );
|
||||
}
|
||||
|
||||
#if defined( VERSION_1 )
|
||||
static void mix_sub_columns( uint_8t dt[N_BLOCK] )
|
||||
{
|
||||
uint_8t st[N_BLOCK];
|
||||
block_copy(st, dt);
|
||||
#else
|
||||
static void mix_sub_columns( uint_8t dt[N_BLOCK], uint_8t st[N_BLOCK] )
|
||||
{
|
||||
#endif
|
||||
dt[ 0] = gfm2_sb(st[0]) ^ gfm3_sb(st[5]) ^ s_box(st[10]) ^ s_box(st[15]);
|
||||
dt[ 1] = s_box(st[0]) ^ gfm2_sb(st[5]) ^ gfm3_sb(st[10]) ^ s_box(st[15]);
|
||||
dt[ 2] = s_box(st[0]) ^ s_box(st[5]) ^ gfm2_sb(st[10]) ^ gfm3_sb(st[15]);
|
||||
dt[ 3] = gfm3_sb(st[0]) ^ s_box(st[5]) ^ s_box(st[10]) ^ gfm2_sb(st[15]);
|
||||
|
||||
dt[ 4] = gfm2_sb(st[4]) ^ gfm3_sb(st[9]) ^ s_box(st[14]) ^ s_box(st[3]);
|
||||
dt[ 5] = s_box(st[4]) ^ gfm2_sb(st[9]) ^ gfm3_sb(st[14]) ^ s_box(st[3]);
|
||||
dt[ 6] = s_box(st[4]) ^ s_box(st[9]) ^ gfm2_sb(st[14]) ^ gfm3_sb(st[3]);
|
||||
dt[ 7] = gfm3_sb(st[4]) ^ s_box(st[9]) ^ s_box(st[14]) ^ gfm2_sb(st[3]);
|
||||
|
||||
dt[ 8] = gfm2_sb(st[8]) ^ gfm3_sb(st[13]) ^ s_box(st[2]) ^ s_box(st[7]);
|
||||
dt[ 9] = s_box(st[8]) ^ gfm2_sb(st[13]) ^ gfm3_sb(st[2]) ^ s_box(st[7]);
|
||||
dt[10] = s_box(st[8]) ^ s_box(st[13]) ^ gfm2_sb(st[2]) ^ gfm3_sb(st[7]);
|
||||
dt[11] = gfm3_sb(st[8]) ^ s_box(st[13]) ^ s_box(st[2]) ^ gfm2_sb(st[7]);
|
||||
|
||||
dt[12] = gfm2_sb(st[12]) ^ gfm3_sb(st[1]) ^ s_box(st[6]) ^ s_box(st[11]);
|
||||
dt[13] = s_box(st[12]) ^ gfm2_sb(st[1]) ^ gfm3_sb(st[6]) ^ s_box(st[11]);
|
||||
dt[14] = s_box(st[12]) ^ s_box(st[1]) ^ gfm2_sb(st[6]) ^ gfm3_sb(st[11]);
|
||||
dt[15] = gfm3_sb(st[12]) ^ s_box(st[1]) ^ s_box(st[6]) ^ gfm2_sb(st[11]);
|
||||
}
|
||||
|
||||
#if defined( VERSION_1 )
|
||||
static void inv_mix_sub_columns( uint_8t dt[N_BLOCK] )
|
||||
{
|
||||
uint_8t st[N_BLOCK];
|
||||
block_copy(st, dt);
|
||||
#else
|
||||
static void inv_mix_sub_columns( uint_8t dt[N_BLOCK], uint_8t st[N_BLOCK] )
|
||||
{
|
||||
#endif
|
||||
dt[ 0] = is_box(gfm_e(st[ 0]) ^ gfm_b(st[ 1]) ^ gfm_d(st[ 2]) ^ gfm_9(st[ 3]));
|
||||
dt[ 5] = is_box(gfm_9(st[ 0]) ^ gfm_e(st[ 1]) ^ gfm_b(st[ 2]) ^ gfm_d(st[ 3]));
|
||||
dt[10] = is_box(gfm_d(st[ 0]) ^ gfm_9(st[ 1]) ^ gfm_e(st[ 2]) ^ gfm_b(st[ 3]));
|
||||
dt[15] = is_box(gfm_b(st[ 0]) ^ gfm_d(st[ 1]) ^ gfm_9(st[ 2]) ^ gfm_e(st[ 3]));
|
||||
|
||||
dt[ 4] = is_box(gfm_e(st[ 4]) ^ gfm_b(st[ 5]) ^ gfm_d(st[ 6]) ^ gfm_9(st[ 7]));
|
||||
dt[ 9] = is_box(gfm_9(st[ 4]) ^ gfm_e(st[ 5]) ^ gfm_b(st[ 6]) ^ gfm_d(st[ 7]));
|
||||
dt[14] = is_box(gfm_d(st[ 4]) ^ gfm_9(st[ 5]) ^ gfm_e(st[ 6]) ^ gfm_b(st[ 7]));
|
||||
dt[ 3] = is_box(gfm_b(st[ 4]) ^ gfm_d(st[ 5]) ^ gfm_9(st[ 6]) ^ gfm_e(st[ 7]));
|
||||
|
||||
dt[ 8] = is_box(gfm_e(st[ 8]) ^ gfm_b(st[ 9]) ^ gfm_d(st[10]) ^ gfm_9(st[11]));
|
||||
dt[13] = is_box(gfm_9(st[ 8]) ^ gfm_e(st[ 9]) ^ gfm_b(st[10]) ^ gfm_d(st[11]));
|
||||
dt[ 2] = is_box(gfm_d(st[ 8]) ^ gfm_9(st[ 9]) ^ gfm_e(st[10]) ^ gfm_b(st[11]));
|
||||
dt[ 7] = is_box(gfm_b(st[ 8]) ^ gfm_d(st[ 9]) ^ gfm_9(st[10]) ^ gfm_e(st[11]));
|
||||
|
||||
dt[12] = is_box(gfm_e(st[12]) ^ gfm_b(st[13]) ^ gfm_d(st[14]) ^ gfm_9(st[15]));
|
||||
dt[ 1] = is_box(gfm_9(st[12]) ^ gfm_e(st[13]) ^ gfm_b(st[14]) ^ gfm_d(st[15]));
|
||||
dt[ 6] = is_box(gfm_d(st[12]) ^ gfm_9(st[13]) ^ gfm_e(st[14]) ^ gfm_b(st[15]));
|
||||
dt[11] = is_box(gfm_b(st[12]) ^ gfm_d(st[13]) ^ gfm_9(st[14]) ^ gfm_e(st[15]));
|
||||
}
|
||||
|
||||
#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED )
|
||||
|
||||
/* Set the cipher key for the pre-keyed version */
|
||||
/* NOTE: If the length_type used for the key length is an
|
||||
unsigned 8-bit character, a key length of 256 bits must
|
||||
be entered as a length in bytes (valid inputs are hence
|
||||
128, 192, 16, 24 and 32).
|
||||
*/
|
||||
|
||||
return_type aes_set_key( const unsigned char key[], length_type keylen, aes_context ctx[1] )
|
||||
{
|
||||
uint_8t cc, rc, hi;
|
||||
|
||||
switch ( keylen ) {
|
||||
case 16:
|
||||
case 128: /* length in bits (128 = 8*16) */
|
||||
keylen = 16;
|
||||
break;
|
||||
case 24:
|
||||
case 192: /* length in bits (192 = 8*24) */
|
||||
keylen = 24;
|
||||
break;
|
||||
case 32:
|
||||
/* case 256: length in bits (256 = 8*32) */
|
||||
keylen = 32;
|
||||
break;
|
||||
default:
|
||||
ctx->rnd = 0;
|
||||
return (return_type) - 1;
|
||||
}
|
||||
block_copy_nn(ctx->ksch, key, keylen);
|
||||
hi = (keylen + 28) << 2;
|
||||
ctx->rnd = (hi >> 4) - 1;
|
||||
for ( cc = keylen, rc = 1; cc < hi; cc += 4 ) {
|
||||
uint_8t tt, t0, t1, t2, t3;
|
||||
|
||||
t0 = ctx->ksch[cc - 4];
|
||||
t1 = ctx->ksch[cc - 3];
|
||||
t2 = ctx->ksch[cc - 2];
|
||||
t3 = ctx->ksch[cc - 1];
|
||||
if ( cc % keylen == 0 ) {
|
||||
tt = t0;
|
||||
t0 = s_box(t1) ^ rc;
|
||||
t1 = s_box(t2);
|
||||
t2 = s_box(t3);
|
||||
t3 = s_box(tt);
|
||||
rc = f2(rc);
|
||||
} else if ( keylen > 24 && cc % keylen == 16 ) {
|
||||
t0 = s_box(t0);
|
||||
t1 = s_box(t1);
|
||||
t2 = s_box(t2);
|
||||
t3 = s_box(t3);
|
||||
}
|
||||
tt = cc - keylen;
|
||||
ctx->ksch[cc + 0] = ctx->ksch[tt + 0] ^ t0;
|
||||
ctx->ksch[cc + 1] = ctx->ksch[tt + 1] ^ t1;
|
||||
ctx->ksch[cc + 2] = ctx->ksch[tt + 2] ^ t2;
|
||||
ctx->ksch[cc + 3] = ctx->ksch[tt + 3] ^ t3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined( AES_ENC_PREKEYED )
|
||||
|
||||
/* Encrypt a single block of 16 bytes */
|
||||
|
||||
/* @breif change the name by snake for avoid the conflict with libcrypto */
|
||||
return_type bluedroid_aes_encrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const aes_context ctx[1] )
|
||||
{
|
||||
if ( ctx->rnd ) {
|
||||
uint_8t s1[N_BLOCK], r;
|
||||
copy_and_key( s1, in, ctx->ksch );
|
||||
|
||||
for ( r = 1 ; r < ctx->rnd ; ++r )
|
||||
#if defined( VERSION_1 )
|
||||
{
|
||||
mix_sub_columns( s1 );
|
||||
add_round_key( s1, ctx->ksch + r * N_BLOCK);
|
||||
}
|
||||
#else
|
||||
{
|
||||
uint_8t s2[N_BLOCK];
|
||||
mix_sub_columns( s2, s1 );
|
||||
copy_and_key( s1, s2, ctx->ksch + r * N_BLOCK);
|
||||
}
|
||||
#endif
|
||||
shift_sub_rows( s1 );
|
||||
copy_and_key( out, s1, ctx->ksch + r * N_BLOCK );
|
||||
} else {
|
||||
return (return_type) - 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* CBC encrypt a number of blocks (input and return an IV) */
|
||||
|
||||
return_type aes_cbc_encrypt( const unsigned char *in, unsigned char *out,
|
||||
int n_block, unsigned char iv[N_BLOCK], const aes_context ctx[1] )
|
||||
{
|
||||
|
||||
while (n_block--) {
|
||||
xor_block(iv, in);
|
||||
if (bluedroid_aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
memcpy(out, iv, N_BLOCK);
|
||||
in += N_BLOCK;
|
||||
out += N_BLOCK;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined( AES_DEC_PREKEYED )
|
||||
|
||||
/* Decrypt a single block of 16 bytes */
|
||||
|
||||
return_type bluedroid_aes_decrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const aes_context ctx[1] )
|
||||
{
|
||||
if ( ctx->rnd ) {
|
||||
uint_8t s1[N_BLOCK], r;
|
||||
copy_and_key( s1, in, ctx->ksch + ctx->rnd * N_BLOCK );
|
||||
inv_shift_sub_rows( s1 );
|
||||
|
||||
for ( r = ctx->rnd ; --r ; )
|
||||
#if defined( VERSION_1 )
|
||||
{
|
||||
add_round_key( s1, ctx->ksch + r * N_BLOCK );
|
||||
inv_mix_sub_columns( s1 );
|
||||
}
|
||||
#else
|
||||
{
|
||||
uint_8t s2[N_BLOCK];
|
||||
copy_and_key( s2, s1, ctx->ksch + r * N_BLOCK );
|
||||
inv_mix_sub_columns( s1, s2 );
|
||||
}
|
||||
#endif
|
||||
copy_and_key( out, s1, ctx->ksch );
|
||||
} else {
|
||||
return (return_type) - 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* CBC decrypt a number of blocks (input and return an IV) */
|
||||
|
||||
return_type aes_cbc_decrypt( const unsigned char *in, unsigned char *out,
|
||||
int n_block, unsigned char iv[N_BLOCK], const aes_context ctx[1] )
|
||||
{
|
||||
while (n_block--) {
|
||||
uint_8t tmp[N_BLOCK];
|
||||
|
||||
memcpy(tmp, in, N_BLOCK);
|
||||
if (bluedroid_aes_decrypt(in, out, ctx) != EXIT_SUCCESS) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
xor_block(out, iv);
|
||||
memcpy(iv, tmp, N_BLOCK);
|
||||
in += N_BLOCK;
|
||||
out += N_BLOCK;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined( AES_ENC_128_OTFK )
|
||||
|
||||
/* The 'on the fly' encryption key update for for 128 bit keys */
|
||||
|
||||
static void update_encrypt_key_128( uint_8t k[N_BLOCK], uint_8t *rc )
|
||||
{
|
||||
uint_8t cc;
|
||||
|
||||
k[0] ^= s_box(k[13]) ^ *rc;
|
||||
k[1] ^= s_box(k[14]);
|
||||
k[2] ^= s_box(k[15]);
|
||||
k[3] ^= s_box(k[12]);
|
||||
*rc = f2( *rc );
|
||||
|
||||
for (cc = 4; cc < 16; cc += 4 ) {
|
||||
k[cc + 0] ^= k[cc - 4];
|
||||
k[cc + 1] ^= k[cc - 3];
|
||||
k[cc + 2] ^= k[cc - 2];
|
||||
k[cc + 3] ^= k[cc - 1];
|
||||
}
|
||||
}
|
||||
|
||||
/* Encrypt a single block of 16 bytes with 'on the fly' 128 bit keying */
|
||||
|
||||
void bluedroid_aes_encrypt_128( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK],
|
||||
const unsigned char key[N_BLOCK], unsigned char o_key[N_BLOCK] )
|
||||
{
|
||||
uint_8t s1[N_BLOCK], r, rc = 1;
|
||||
|
||||
if (o_key != key) {
|
||||
block_copy( o_key, key );
|
||||
}
|
||||
copy_and_key( s1, in, o_key );
|
||||
|
||||
for ( r = 1 ; r < 10 ; ++r )
|
||||
#if defined( VERSION_1 )
|
||||
{
|
||||
mix_sub_columns( s1 );
|
||||
update_encrypt_key_128( o_key, &rc );
|
||||
add_round_key( s1, o_key );
|
||||
}
|
||||
#else
|
||||
{
|
||||
uint_8t s2[N_BLOCK];
|
||||
mix_sub_columns( s2, s1 );
|
||||
update_encrypt_key_128( o_key, &rc );
|
||||
copy_and_key( s1, s2, o_key );
|
||||
}
|
||||
#endif
|
||||
|
||||
shift_sub_rows( s1 );
|
||||
update_encrypt_key_128( o_key, &rc );
|
||||
copy_and_key( out, s1, o_key );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined( AES_DEC_128_OTFK )
|
||||
|
||||
/* The 'on the fly' decryption key update for for 128 bit keys */
|
||||
|
||||
static void update_decrypt_key_128( uint_8t k[N_BLOCK], uint_8t *rc )
|
||||
{
|
||||
uint_8t cc;
|
||||
|
||||
for ( cc = 12; cc > 0; cc -= 4 ) {
|
||||
k[cc + 0] ^= k[cc - 4];
|
||||
k[cc + 1] ^= k[cc - 3];
|
||||
k[cc + 2] ^= k[cc - 2];
|
||||
k[cc + 3] ^= k[cc - 1];
|
||||
}
|
||||
*rc = d2(*rc);
|
||||
k[0] ^= s_box(k[13]) ^ *rc;
|
||||
k[1] ^= s_box(k[14]);
|
||||
k[2] ^= s_box(k[15]);
|
||||
k[3] ^= s_box(k[12]);
|
||||
}
|
||||
|
||||
/* Decrypt a single block of 16 bytes with 'on the fly' 128 bit keying */
|
||||
|
||||
void bluedroid_aes_decrypt_128( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK],
|
||||
const unsigned char key[N_BLOCK], unsigned char o_key[N_BLOCK] )
|
||||
{
|
||||
uint_8t s1[N_BLOCK], r, rc = 0x6c;
|
||||
if (o_key != key) {
|
||||
block_copy( o_key, key );
|
||||
}
|
||||
|
||||
copy_and_key( s1, in, o_key );
|
||||
inv_shift_sub_rows( s1 );
|
||||
|
||||
for ( r = 10 ; --r ; )
|
||||
#if defined( VERSION_1 )
|
||||
{
|
||||
update_decrypt_key_128( o_key, &rc );
|
||||
add_round_key( s1, o_key );
|
||||
inv_mix_sub_columns( s1 );
|
||||
}
|
||||
#else
|
||||
{
|
||||
uint_8t s2[N_BLOCK];
|
||||
update_decrypt_key_128( o_key, &rc );
|
||||
copy_and_key( s2, s1, o_key );
|
||||
inv_mix_sub_columns( s1, s2 );
|
||||
}
|
||||
#endif
|
||||
update_decrypt_key_128( o_key, &rc );
|
||||
copy_and_key( out, s1, o_key );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined( AES_ENC_256_OTFK )
|
||||
|
||||
/* The 'on the fly' encryption key update for for 256 bit keys */
|
||||
|
||||
static void update_encrypt_key_256( uint_8t k[2 * N_BLOCK], uint_8t *rc )
|
||||
{
|
||||
uint_8t cc;
|
||||
|
||||
k[0] ^= s_box(k[29]) ^ *rc;
|
||||
k[1] ^= s_box(k[30]);
|
||||
k[2] ^= s_box(k[31]);
|
||||
k[3] ^= s_box(k[28]);
|
||||
*rc = f2( *rc );
|
||||
|
||||
for (cc = 4; cc < 16; cc += 4) {
|
||||
k[cc + 0] ^= k[cc - 4];
|
||||
k[cc + 1] ^= k[cc - 3];
|
||||
k[cc + 2] ^= k[cc - 2];
|
||||
k[cc + 3] ^= k[cc - 1];
|
||||
}
|
||||
|
||||
k[16] ^= s_box(k[12]);
|
||||
k[17] ^= s_box(k[13]);
|
||||
k[18] ^= s_box(k[14]);
|
||||
k[19] ^= s_box(k[15]);
|
||||
|
||||
for ( cc = 20; cc < 32; cc += 4 ) {
|
||||
k[cc + 0] ^= k[cc - 4];
|
||||
k[cc + 1] ^= k[cc - 3];
|
||||
k[cc + 2] ^= k[cc - 2];
|
||||
k[cc + 3] ^= k[cc - 1];
|
||||
}
|
||||
}
|
||||
|
||||
/* Encrypt a single block of 16 bytes with 'on the fly' 256 bit keying */
|
||||
|
||||
void bluedroid_aes_encrypt_256( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK],
|
||||
const unsigned char key[2 * N_BLOCK], unsigned char o_key[2 * N_BLOCK] )
|
||||
{
|
||||
uint_8t s1[N_BLOCK], r, rc = 1;
|
||||
if (o_key != key) {
|
||||
block_copy( o_key, key );
|
||||
block_copy( o_key + 16, key + 16 );
|
||||
}
|
||||
copy_and_key( s1, in, o_key );
|
||||
|
||||
for ( r = 1 ; r < 14 ; ++r )
|
||||
#if defined( VERSION_1 )
|
||||
{
|
||||
mix_sub_columns(s1);
|
||||
if ( r & 1 ) {
|
||||
add_round_key( s1, o_key + 16 );
|
||||
} else {
|
||||
update_encrypt_key_256( o_key, &rc );
|
||||
add_round_key( s1, o_key );
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
uint_8t s2[N_BLOCK];
|
||||
mix_sub_columns( s2, s1 );
|
||||
if ( r & 1 ) {
|
||||
copy_and_key( s1, s2, o_key + 16 );
|
||||
} else {
|
||||
update_encrypt_key_256( o_key, &rc );
|
||||
copy_and_key( s1, s2, o_key );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
shift_sub_rows( s1 );
|
||||
update_encrypt_key_256( o_key, &rc );
|
||||
copy_and_key( out, s1, o_key );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined( AES_DEC_256_OTFK )
|
||||
|
||||
/* The 'on the fly' encryption key update for for 256 bit keys */
|
||||
|
||||
static void update_decrypt_key_256( uint_8t k[2 * N_BLOCK], uint_8t *rc )
|
||||
{
|
||||
uint_8t cc;
|
||||
|
||||
for (cc = 28; cc > 16; cc -= 4) {
|
||||
k[cc + 0] ^= k[cc - 4];
|
||||
k[cc + 1] ^= k[cc - 3];
|
||||
k[cc + 2] ^= k[cc - 2];
|
||||
k[cc + 3] ^= k[cc - 1];
|
||||
}
|
||||
|
||||
k[16] ^= s_box(k[12]);
|
||||
k[17] ^= s_box(k[13]);
|
||||
k[18] ^= s_box(k[14]);
|
||||
k[19] ^= s_box(k[15]);
|
||||
|
||||
for (cc = 12; cc > 0; cc -= 4) {
|
||||
k[cc + 0] ^= k[cc - 4];
|
||||
k[cc + 1] ^= k[cc - 3];
|
||||
k[cc + 2] ^= k[cc - 2];
|
||||
k[cc + 3] ^= k[cc - 1];
|
||||
}
|
||||
|
||||
*rc = d2(*rc);
|
||||
k[0] ^= s_box(k[29]) ^ *rc;
|
||||
k[1] ^= s_box(k[30]);
|
||||
k[2] ^= s_box(k[31]);
|
||||
k[3] ^= s_box(k[28]);
|
||||
}
|
||||
|
||||
/* Decrypt a single block of 16 bytes with 'on the fly'
|
||||
256 bit keying
|
||||
*/
|
||||
void bluedroid_aes_decrypt_256( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK],
|
||||
const unsigned char key[2 * N_BLOCK], unsigned char o_key[2 * N_BLOCK] )
|
||||
{
|
||||
uint_8t s1[N_BLOCK], r, rc = 0x80;
|
||||
|
||||
if (o_key != key) {
|
||||
block_copy( o_key, key );
|
||||
block_copy( o_key + 16, key + 16 );
|
||||
}
|
||||
|
||||
copy_and_key( s1, in, o_key );
|
||||
inv_shift_sub_rows( s1 );
|
||||
|
||||
for ( r = 14 ; --r ; )
|
||||
#if defined( VERSION_1 )
|
||||
{
|
||||
if ( ( r & 1 ) ) {
|
||||
update_decrypt_key_256( o_key, &rc );
|
||||
add_round_key( s1, o_key + 16 );
|
||||
} else {
|
||||
add_round_key( s1, o_key );
|
||||
}
|
||||
inv_mix_sub_columns( s1 );
|
||||
}
|
||||
#else
|
||||
{
|
||||
uint_8t s2[N_BLOCK];
|
||||
if ( ( r & 1 ) ) {
|
||||
update_decrypt_key_256( o_key, &rc );
|
||||
copy_and_key( s2, s1, o_key + 16 );
|
||||
} else {
|
||||
copy_and_key( s2, s1, o_key );
|
||||
}
|
||||
inv_mix_sub_columns( s1, s2 );
|
||||
}
|
||||
#endif
|
||||
copy_and_key( out, s1, o_key );
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
|
||||
|
||||
LICENSE TERMS
|
||||
|
||||
The redistribution and use of this software (with or without changes)
|
||||
is allowed without the payment of fees or royalties provided that:
|
||||
|
||||
1. source code distributions include the above copyright notice, this
|
||||
list of conditions and the following disclaimer;
|
||||
|
||||
2. binary distributions include the above copyright notice, this list
|
||||
of conditions and the following disclaimer in their documentation;
|
||||
|
||||
3. the name of the copyright holder is not used to endorse products
|
||||
built using this software without specific written permission.
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its properties, including, but not limited to, correctness
|
||||
and/or fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue 09/09/2006
|
||||
|
||||
This is an AES implementation that uses only 8-bit byte operations on the
|
||||
cipher state.
|
||||
*/
|
||||
|
||||
#ifndef AES_H
|
||||
#define AES_H
|
||||
|
||||
#if 1
|
||||
# define AES_ENC_PREKEYED /* AES encryption with a precomputed key schedule */
|
||||
#endif
|
||||
#if 1
|
||||
# define AES_DEC_PREKEYED /* AES decryption with a precomputed key schedule */
|
||||
#endif
|
||||
#if 1
|
||||
# define AES_ENC_128_OTFK /* AES encryption with 'on the fly' 128 bit keying */
|
||||
#endif
|
||||
#if 1
|
||||
# define AES_DEC_128_OTFK /* AES decryption with 'on the fly' 128 bit keying */
|
||||
#endif
|
||||
#if 1
|
||||
# define AES_ENC_256_OTFK /* AES encryption with 'on the fly' 256 bit keying */
|
||||
#endif
|
||||
#if 1
|
||||
# define AES_DEC_256_OTFK /* AES decryption with 'on the fly' 256 bit keying */
|
||||
#endif
|
||||
|
||||
#define N_ROW 4
|
||||
#define N_COL 4
|
||||
#define N_BLOCK (N_ROW * N_COL)
|
||||
#define N_MAX_ROUNDS 14
|
||||
|
||||
typedef unsigned char uint_8t;
|
||||
|
||||
typedef uint_8t return_type;
|
||||
|
||||
/* Warning: The key length for 256 bit keys overflows a byte
|
||||
(see comment below)
|
||||
*/
|
||||
|
||||
typedef uint_8t length_type;
|
||||
|
||||
typedef struct {
|
||||
uint_8t ksch[(N_MAX_ROUNDS + 1) * N_BLOCK];
|
||||
uint_8t rnd;
|
||||
} aes_context;
|
||||
|
||||
/* The following calls are for a precomputed key schedule
|
||||
|
||||
NOTE: If the length_type used for the key length is an
|
||||
unsigned 8-bit character, a key length of 256 bits must
|
||||
be entered as a length in bytes (valid inputs are hence
|
||||
128, 192, 16, 24 and 32).
|
||||
*/
|
||||
|
||||
#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED )
|
||||
|
||||
return_type aes_set_key( const unsigned char key[],
|
||||
length_type keylen,
|
||||
aes_context ctx[1] );
|
||||
#endif
|
||||
|
||||
#if defined( AES_ENC_PREKEYED )
|
||||
|
||||
return_type bluedroid_aes_encrypt( const unsigned char in[N_BLOCK],
|
||||
unsigned char out[N_BLOCK],
|
||||
const aes_context ctx[1] );
|
||||
|
||||
return_type aes_cbc_encrypt( const unsigned char *in,
|
||||
unsigned char *out,
|
||||
int n_block,
|
||||
unsigned char iv[N_BLOCK],
|
||||
const aes_context ctx[1] );
|
||||
#endif
|
||||
|
||||
#if defined( AES_DEC_PREKEYED )
|
||||
|
||||
return_type bluedroid_aes_decrypt( const unsigned char in[N_BLOCK],
|
||||
unsigned char out[N_BLOCK],
|
||||
const aes_context ctx[1] );
|
||||
|
||||
return_type aes_cbc_decrypt( const unsigned char *in,
|
||||
unsigned char *out,
|
||||
int n_block,
|
||||
unsigned char iv[N_BLOCK],
|
||||
const aes_context ctx[1] );
|
||||
#endif
|
||||
|
||||
/* The following calls are for 'on the fly' keying. In this case the
|
||||
encryption and decryption keys are different.
|
||||
|
||||
The encryption subroutines take a key in an array of bytes in
|
||||
key[L] where L is 16, 24 or 32 bytes for key lengths of 128,
|
||||
192, and 256 bits respectively. They then encrypts the input
|
||||
data, in[] with this key and put the reult in the output array
|
||||
out[]. In addition, the second key array, o_key[L], is used
|
||||
to output the key that is needed by the decryption subroutine
|
||||
to reverse the encryption operation. The two key arrays can
|
||||
be the same array but in this case the original key will be
|
||||
overwritten.
|
||||
|
||||
In the same way, the decryption subroutines output keys that
|
||||
can be used to reverse their effect when used for encryption.
|
||||
|
||||
Only 128 and 256 bit keys are supported in these 'on the fly'
|
||||
modes.
|
||||
*/
|
||||
|
||||
#if defined( AES_ENC_128_OTFK )
|
||||
void bluedroid_aes_encrypt_128( const unsigned char in[N_BLOCK],
|
||||
unsigned char out[N_BLOCK],
|
||||
const unsigned char key[N_BLOCK],
|
||||
uint_8t o_key[N_BLOCK] );
|
||||
#endif
|
||||
|
||||
#if defined( AES_DEC_128_OTFK )
|
||||
void bluedroid_aes_decrypt_128( const unsigned char in[N_BLOCK],
|
||||
unsigned char out[N_BLOCK],
|
||||
const unsigned char key[N_BLOCK],
|
||||
unsigned char o_key[N_BLOCK] );
|
||||
#endif
|
||||
|
||||
#if defined( AES_ENC_256_OTFK )
|
||||
void bluedroid_aes_encrypt_256( const unsigned char in[N_BLOCK],
|
||||
unsigned char out[N_BLOCK],
|
||||
const unsigned char key[2 * N_BLOCK],
|
||||
unsigned char o_key[2 * N_BLOCK] );
|
||||
#endif
|
||||
|
||||
#if defined( AES_DEC_256_OTFK )
|
||||
void bluedroid_aes_decrypt_256( const unsigned char in[N_BLOCK],
|
||||
unsigned char out[N_BLOCK],
|
||||
const unsigned char key[2 * N_BLOCK],
|
||||
unsigned char o_key[2 * N_BLOCK] );
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,74 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2006-2015 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file contains simple pairing algorithms using Elliptic Curve Cryptography for private public key
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "p_256_multprecision.h"
|
||||
#include "common/bt_target.h"
|
||||
|
||||
typedef unsigned long DWORD;
|
||||
|
||||
typedef struct {
|
||||
DWORD x[KEY_LENGTH_DWORDS_P256];
|
||||
DWORD y[KEY_LENGTH_DWORDS_P256];
|
||||
DWORD z[KEY_LENGTH_DWORDS_P256];
|
||||
} Point;
|
||||
|
||||
typedef struct {
|
||||
// curve's coefficients
|
||||
DWORD a[KEY_LENGTH_DWORDS_P256];
|
||||
DWORD b[KEY_LENGTH_DWORDS_P256];
|
||||
|
||||
//whether a is -3
|
||||
int a_minus3;
|
||||
|
||||
// prime modulus
|
||||
DWORD p[KEY_LENGTH_DWORDS_P256];
|
||||
|
||||
// Omega, p = 2^m -omega
|
||||
DWORD omega[KEY_LENGTH_DWORDS_P256];
|
||||
|
||||
// base point, a point on E of order r
|
||||
Point G;
|
||||
|
||||
} elliptic_curve_t;
|
||||
|
||||
#if SMP_DYNAMIC_MEMORY == FALSE
|
||||
extern elliptic_curve_t curve;
|
||||
extern elliptic_curve_t curve_p256;
|
||||
#else
|
||||
extern elliptic_curve_t *curve_ptr;
|
||||
extern elliptic_curve_t *curve_p256_ptr;
|
||||
#define curve (*curve_ptr)
|
||||
#define curve_p256 (*curve_p256_ptr)
|
||||
#endif
|
||||
|
||||
|
||||
void ECC_PointMult_Bin_NAF(Point *q, Point *p, DWORD *n, uint32_t keyLength);
|
||||
|
||||
bool ECC_CheckPointIsInElliCur_P256(Point *p);
|
||||
|
||||
#define ECC_PointMult(q, p, n, keyLength) ECC_PointMult_Bin_NAF(q, p, n, keyLength)
|
||||
|
||||
void p_256_init_curve(UINT32 keyLength);
|
||||
@@ -0,0 +1,60 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2006-2015 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file contains simple pairing algorithms
|
||||
*
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "stack/bt_types.h"
|
||||
|
||||
/* Type definitions */
|
||||
typedef unsigned long DWORD;
|
||||
|
||||
#define DWORD_BITS 32
|
||||
#define DWORD_BYTES 4
|
||||
#define DWORD_BITS_SHIFT 5
|
||||
|
||||
#define KEY_LENGTH_DWORDS_P192 6
|
||||
#define KEY_LENGTH_DWORDS_P256 8
|
||||
/* Arithmetic Operations */
|
||||
|
||||
int multiprecision_compare(DWORD *a, DWORD *b, uint32_t keyLength);
|
||||
int multiprecision_iszero(DWORD *a, uint32_t keyLength);
|
||||
void multiprecision_init(DWORD *c, uint32_t keyLength);
|
||||
void multiprecision_copy(DWORD *c, DWORD *a, uint32_t keyLength);
|
||||
UINT32 multiprecision_dword_bits (DWORD a);
|
||||
UINT32 multiprecision_most_signdwords(DWORD *a, uint32_t keyLength);
|
||||
UINT32 multiprecision_most_signbits(DWORD *a, uint32_t keyLength);
|
||||
void multiprecision_inv_mod(DWORD *aminus, DWORD *a, uint32_t keyLength);
|
||||
DWORD multiprecision_add(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength); // c=a+b
|
||||
void multiprecision_add_mod(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength);
|
||||
DWORD multiprecision_sub(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength); // c=a-b
|
||||
void multiprecision_sub_mod(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength);
|
||||
void multiprecision_rshift(DWORD *c, DWORD *a, uint32_t keyLength); // c=a>>1, return carrier
|
||||
void multiprecision_lshift_mod(DWORD *c, DWORD *a, uint32_t keyLength); // c=a<<b, return carrier
|
||||
DWORD multiprecision_lshift(DWORD *c, DWORD *a, uint32_t keyLength); // c=a<<b, return carrier
|
||||
void multiprecision_mult(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength); // c=a*b
|
||||
void multiprecision_mersenns_mult_mod(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength);
|
||||
void multiprecision_mersenns_squa_mod(DWORD *c, DWORD *a, uint32_t keyLength);
|
||||
DWORD multiprecision_lshift(DWORD *c, DWORD *a, uint32_t keyLength);
|
||||
void multiprecision_mult(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength);
|
||||
void multiprecision_fast_mod(DWORD *c, DWORD *a);
|
||||
void multiprecision_fast_mod_P256(DWORD *c, DWORD *a);
|
||||
@@ -0,0 +1,545 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2012 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file contains internally used SMP definitions
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef SMP_INT_H
|
||||
#define SMP_INT_H
|
||||
|
||||
// #if (SMP_INCLUDED == TRUE)
|
||||
|
||||
#include "stack/btu.h"
|
||||
#include "stack/btm_ble_api.h"
|
||||
#include "stack/btm_api.h"
|
||||
#include "stack/smp_api.h"
|
||||
|
||||
#define SMP_MODEL_ENCRYPTION_ONLY 0 /* Legacy mode, Just Works model */
|
||||
#define SMP_MODEL_PASSKEY 1 /* Legacy mode, Passkey Entry model, this side inputs the key */
|
||||
#define SMP_MODEL_OOB 2 /* Legacy mode, OOB model */
|
||||
#define SMP_MODEL_KEY_NOTIF 3 /* Legacy mode, Passkey Entry model, this side displays the key */
|
||||
#define SMP_MODEL_SEC_CONN_JUSTWORKS 4 /* Secure Connections mode, Just Works model */
|
||||
#define SMP_MODEL_SEC_CONN_NUM_COMP 5 /* Secure Connections mode, Numeric Comparison model */
|
||||
#define SMP_MODEL_SEC_CONN_PASSKEY_ENT 6 /* Secure Connections mode, Passkey Entry model, */
|
||||
/* this side inputs the key */
|
||||
#define SMP_MODEL_SEC_CONN_PASSKEY_DISP 7 /* Secure Connections mode, Passkey Entry model, */
|
||||
/* this side displays the key */
|
||||
#define SMP_MODEL_SEC_CONN_OOB 8 /* Secure Connections mode, OOB model */
|
||||
#define SMP_MODEL_OUT_OF_RANGE 9
|
||||
typedef UINT8 tSMP_ASSO_MODEL;
|
||||
|
||||
|
||||
#ifndef SMP_MAX_CONN
|
||||
#define SMP_MAX_CONN 2
|
||||
#endif
|
||||
|
||||
#define SMP_WAIT_FOR_RSP_TOUT 30
|
||||
|
||||
#define SMP_OPCODE_INIT 0x04
|
||||
|
||||
/* SMP events */
|
||||
#define SMP_PAIRING_REQ_EVT SMP_OPCODE_PAIRING_REQ
|
||||
#define SMP_PAIRING_RSP_EVT SMP_OPCODE_PAIRING_RSP
|
||||
#define SMP_CONFIRM_EVT SMP_OPCODE_CONFIRM
|
||||
#define SMP_RAND_EVT SMP_OPCODE_RAND
|
||||
#define SMP_PAIRING_FAILED_EVT SMP_OPCODE_PAIRING_FAILED
|
||||
#define SMP_ENCRPTION_INFO_EVT SMP_OPCODE_ENCRYPT_INFO
|
||||
#define SMP_MASTER_ID_EVT SMP_OPCODE_MASTER_ID
|
||||
#define SMP_ID_INFO_EVT SMP_OPCODE_IDENTITY_INFO
|
||||
#define SMP_ID_ADDR_EVT SMP_OPCODE_ID_ADDR
|
||||
#define SMP_SIGN_INFO_EVT SMP_OPCODE_SIGN_INFO
|
||||
#define SMP_SECURITY_REQ_EVT SMP_OPCODE_SEC_REQ
|
||||
|
||||
#define SMP_PAIR_PUBLIC_KEY_EVT SMP_OPCODE_PAIR_PUBLIC_KEY
|
||||
#define SMP_PAIR_KEYPRESS_NOTIFICATION_EVT SMP_OPCODE_PAIR_KEYPR_NOTIF
|
||||
|
||||
#define SMP_PAIR_COMMITM_EVT SMP_OPCODE_PAIR_COMMITM
|
||||
|
||||
#define SMP_SELF_DEF_EVT (SMP_PAIR_COMMITM_EVT + 1)
|
||||
#define SMP_KEY_READY_EVT (SMP_SELF_DEF_EVT)
|
||||
#define SMP_ENCRYPTED_EVT (SMP_SELF_DEF_EVT + 1)
|
||||
#define SMP_L2CAP_CONN_EVT (SMP_SELF_DEF_EVT + 2)
|
||||
#define SMP_L2CAP_DISCONN_EVT (SMP_SELF_DEF_EVT + 3)
|
||||
#define SMP_IO_RSP_EVT (SMP_SELF_DEF_EVT + 4)
|
||||
#define SMP_API_SEC_GRANT_EVT (SMP_SELF_DEF_EVT + 5)
|
||||
#define SMP_TK_REQ_EVT (SMP_SELF_DEF_EVT + 6)
|
||||
#define SMP_AUTH_CMPL_EVT (SMP_SELF_DEF_EVT + 7)
|
||||
#define SMP_ENC_REQ_EVT (SMP_SELF_DEF_EVT + 8)
|
||||
#define SMP_BOND_REQ_EVT (SMP_SELF_DEF_EVT + 9)
|
||||
#define SMP_DISCARD_SEC_REQ_EVT (SMP_SELF_DEF_EVT + 10)
|
||||
|
||||
#define SMP_PAIR_DHKEY_CHCK_EVT SMP_OPCODE_PAIR_DHKEY_CHECK
|
||||
|
||||
#define SMP_PUBL_KEY_EXCH_REQ_EVT (SMP_SELF_DEF_EVT + 11) /* request to start public */
|
||||
/* key exchange */
|
||||
|
||||
#define SMP_LOC_PUBL_KEY_CRTD_EVT (SMP_SELF_DEF_EVT + 12) /* local public key created */
|
||||
|
||||
#define SMP_BOTH_PUBL_KEYS_RCVD_EVT (SMP_SELF_DEF_EVT + 13) /* both local and peer public */
|
||||
/* keys are saved in cb */
|
||||
|
||||
#define SMP_SC_DHKEY_CMPLT_EVT (SMP_SELF_DEF_EVT + 14) /* DHKey computation is completed,*/
|
||||
/* time to start SC phase1 */
|
||||
|
||||
#define SMP_HAVE_LOC_NONCE_EVT (SMP_SELF_DEF_EVT + 15) /* new local nonce is generated */
|
||||
/*and saved in p_cb->rand */
|
||||
|
||||
#define SMP_SC_PHASE1_CMPLT_EVT (SMP_SELF_DEF_EVT + 16) /* time to start SC phase2 */
|
||||
|
||||
#define SMP_SC_CALC_NC_EVT (SMP_SELF_DEF_EVT + 17) /* request to calculate number */
|
||||
/* for user check. Used only in the */
|
||||
/* numeric compare protocol */
|
||||
|
||||
/* Request to display the number for user check to the user.*/
|
||||
/* Used only in the numeric compare protocol */
|
||||
#define SMP_SC_DSPL_NC_EVT (SMP_SELF_DEF_EVT + 18)
|
||||
|
||||
#define SMP_SC_NC_OK_EVT (SMP_SELF_DEF_EVT + 19) /* user confirms 'OK' numeric */
|
||||
/*comparison request */
|
||||
|
||||
/* both local and peer DHKey Checks are already present - it is used on slave to prevent race condition */
|
||||
#define SMP_SC_2_DHCK_CHKS_PRES_EVT (SMP_SELF_DEF_EVT + 20)
|
||||
|
||||
/* same meaning as SMP_KEY_READY_EVT to separate between SC and legacy actions */
|
||||
#define SMP_SC_KEY_READY_EVT (SMP_SELF_DEF_EVT + 21)
|
||||
#define SMP_KEYPRESS_NOTIFICATION_EVENT (SMP_SELF_DEF_EVT + 22)
|
||||
|
||||
#define SMP_SC_OOB_DATA_EVT (SMP_SELF_DEF_EVT + 23) /* SC OOB data from some */
|
||||
/* repository is provided */
|
||||
|
||||
#define SMP_CR_LOC_SC_OOB_DATA_EVT (SMP_SELF_DEF_EVT + 24)
|
||||
#define SMP_MAX_EVT SMP_CR_LOC_SC_OOB_DATA_EVT
|
||||
|
||||
typedef UINT8 tSMP_EVENT;
|
||||
|
||||
/* Assumption it's only using the low 8 bits, if bigger than that, need to expand it to 16 bits */
|
||||
#define SMP_SEC_KEY_MASK 0x00ff
|
||||
|
||||
#define SMP_PASSKEY_MASK 0xfff00000
|
||||
|
||||
/* SMP pairing state */
|
||||
enum {
|
||||
SMP_STATE_IDLE,
|
||||
SMP_STATE_WAIT_APP_RSP,
|
||||
SMP_STATE_SEC_REQ_PENDING,
|
||||
SMP_STATE_PAIR_REQ_RSP,
|
||||
SMP_STATE_WAIT_CONFIRM,
|
||||
SMP_STATE_CONFIRM,
|
||||
SMP_STATE_RAND,
|
||||
SMP_STATE_PUBLIC_KEY_EXCH,
|
||||
SMP_STATE_SEC_CONN_PHS1_START,
|
||||
SMP_STATE_WAIT_COMMITMENT,
|
||||
SMP_STATE_WAIT_NONCE,
|
||||
SMP_STATE_SEC_CONN_PHS2_START,
|
||||
SMP_STATE_WAIT_DHK_CHECK,
|
||||
SMP_STATE_DHK_CHECK,
|
||||
SMP_STATE_ENCRYPTION_PENDING,
|
||||
SMP_STATE_BOND_PENDING,
|
||||
SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA,
|
||||
SMP_STATE_MAX
|
||||
};
|
||||
typedef UINT8 tSMP_STATE;
|
||||
|
||||
/* SMP over BR/EDR events */
|
||||
#define SMP_BR_PAIRING_REQ_EVT SMP_OPCODE_PAIRING_REQ
|
||||
#define SMP_BR_PAIRING_RSP_EVT SMP_OPCODE_PAIRING_RSP
|
||||
#define SMP_BR_CONFIRM_EVT SMP_OPCODE_CONFIRM /* not expected over BR/EDR */
|
||||
#define SMP_BR_RAND_EVT SMP_OPCODE_RAND /* not expected over BR/EDR */
|
||||
#define SMP_BR_PAIRING_FAILED_EVT SMP_OPCODE_PAIRING_FAILED
|
||||
#define SMP_BR_ENCRPTION_INFO_EVT SMP_OPCODE_ENCRYPT_INFO /* not expected over BR/EDR */
|
||||
#define SMP_BR_MASTER_ID_EVT SMP_OPCODE_MASTER_ID /* not expected over BR/EDR */
|
||||
#define SMP_BR_ID_INFO_EVT SMP_OPCODE_IDENTITY_INFO
|
||||
#define SMP_BR_ID_ADDR_EVT SMP_OPCODE_ID_ADDR
|
||||
#define SMP_BR_SIGN_INFO_EVT SMP_OPCODE_SIGN_INFO
|
||||
#define SMP_BR_SECURITY_REQ_EVT SMP_OPCODE_SEC_REQ /* not expected over BR/EDR */
|
||||
#define SMP_BR_PAIR_PUBLIC_KEY_EVT SMP_OPCODE_PAIR_PUBLIC_KEY /* not expected over BR/EDR */
|
||||
#define SMP_BR_PAIR_DHKEY_CHCK_EVT SMP_OPCODE_PAIR_DHKEY_CHECK /* not expected over BR/EDR */
|
||||
#define SMP_BR_PAIR_KEYPR_NOTIF_EVT SMP_OPCODE_PAIR_KEYPR_NOTIF /* not expected over BR/EDR */
|
||||
#define SMP_BR_SELF_DEF_EVT SMP_BR_PAIR_KEYPR_NOTIF_EVT
|
||||
#define SMP_BR_KEY_READY_EVT (SMP_BR_SELF_DEF_EVT + 1)
|
||||
#define SMP_BR_ENCRYPTED_EVT (SMP_BR_SELF_DEF_EVT + 2)
|
||||
#define SMP_BR_L2CAP_CONN_EVT (SMP_BR_SELF_DEF_EVT + 3)
|
||||
#define SMP_BR_L2CAP_DISCONN_EVT (SMP_BR_SELF_DEF_EVT + 4)
|
||||
#define SMP_BR_KEYS_RSP_EVT (SMP_BR_SELF_DEF_EVT + 5)
|
||||
#define SMP_BR_API_SEC_GRANT_EVT (SMP_BR_SELF_DEF_EVT + 6)
|
||||
#define SMP_BR_TK_REQ_EVT (SMP_BR_SELF_DEF_EVT + 7)
|
||||
#define SMP_BR_AUTH_CMPL_EVT (SMP_BR_SELF_DEF_EVT + 8)
|
||||
#define SMP_BR_ENC_REQ_EVT (SMP_BR_SELF_DEF_EVT + 9)
|
||||
#define SMP_BR_BOND_REQ_EVT (SMP_BR_SELF_DEF_EVT + 10)
|
||||
#define SMP_BR_DISCARD_SEC_REQ_EVT (SMP_BR_SELF_DEF_EVT + 11)
|
||||
#define SMP_BR_MAX_EVT (SMP_BR_SELF_DEF_EVT + 12)
|
||||
typedef UINT8 tSMP_BR_EVENT;
|
||||
|
||||
/* SMP over BR/EDR pairing states */
|
||||
enum {
|
||||
SMP_BR_STATE_IDLE = SMP_STATE_IDLE,
|
||||
SMP_BR_STATE_WAIT_APP_RSP,
|
||||
SMP_BR_STATE_PAIR_REQ_RSP,
|
||||
SMP_BR_STATE_BOND_PENDING,
|
||||
SMP_BR_STATE_MAX
|
||||
};
|
||||
typedef UINT8 tSMP_BR_STATE;
|
||||
|
||||
/* random and encrption activity state */
|
||||
enum {
|
||||
SMP_GEN_COMPARE = 1,
|
||||
SMP_GEN_CONFIRM,
|
||||
|
||||
SMP_GEN_DIV_LTK,
|
||||
SMP_GEN_DIV_CSRK,
|
||||
SMP_GEN_RAND_V,
|
||||
SMP_GEN_TK,
|
||||
SMP_GEN_SRAND_MRAND,
|
||||
SMP_GEN_SRAND_MRAND_CONT,
|
||||
SMP_GENERATE_PRIVATE_KEY_0_7,
|
||||
SMP_GENERATE_PRIVATE_KEY_8_15,
|
||||
SMP_GENERATE_PRIVATE_KEY_16_23,
|
||||
SMP_GENERATE_PRIVATE_KEY_24_31,
|
||||
SMP_GEN_NONCE_0_7,
|
||||
SMP_GEN_NONCE_8_15
|
||||
};
|
||||
|
||||
enum {
|
||||
SMP_KEY_TYPE_TK,
|
||||
SMP_KEY_TYPE_CFM,
|
||||
SMP_KEY_TYPE_CMP,
|
||||
SMP_KEY_TYPE_PEER_DHK_CHCK,
|
||||
SMP_KEY_TYPE_STK,
|
||||
SMP_KEY_TYPE_LTK
|
||||
};
|
||||
typedef struct {
|
||||
UINT8 key_type;
|
||||
UINT8 *p_data;
|
||||
} tSMP_KEY;
|
||||
|
||||
typedef union {
|
||||
UINT8 *p_data; /* UINT8 type data pointer */
|
||||
tSMP_KEY key;
|
||||
UINT16 reason;
|
||||
UINT32 passkey;
|
||||
tSMP_OOB_DATA_TYPE req_oob_type;
|
||||
} tSMP_INT_DATA;
|
||||
|
||||
/* internal status mask */
|
||||
#define SMP_PAIR_FLAGS_WE_STARTED_DD (1)
|
||||
#define SMP_PAIR_FLAGS_PEER_STARTED_DD (1 << 1)
|
||||
#define SMP_PAIR_FLAGS_CMD_CONFIRM (1 << SMP_OPCODE_CONFIRM) /* 1 << 3 */
|
||||
#define SMP_PAIR_FLAG_ENC_AFTER_PAIR (1 << 4)
|
||||
#define SMP_PAIR_FLAG_HAVE_PEER_DHK_CHK (1 << 5) /* used on slave to resolve race condition */
|
||||
#define SMP_PAIR_FLAG_HAVE_PEER_PUBL_KEY (1 << 6) /* used on slave to resolve race condition */
|
||||
#define SMP_PAIR_FLAG_HAVE_PEER_COMM (1 << 7) /* used to resolve race condition */
|
||||
#define SMP_PAIR_FLAG_HAVE_LOCAL_PUBL_KEY (1 << 8) /* used on slave to resolve race condition */
|
||||
|
||||
/* check if authentication requirement need MITM protection */
|
||||
#define SMP_NO_MITM_REQUIRED(x) (((x) & SMP_AUTH_YN_BIT) == 0)
|
||||
|
||||
#define SMP_ENCRYT_KEY_SIZE 16
|
||||
#define SMP_ENCRYT_DATA_SIZE 16
|
||||
#define SMP_ECNCRPYT_STATUS HCI_SUCCESS
|
||||
|
||||
typedef struct {
|
||||
BD_ADDR bd_addr;
|
||||
BT_HDR *p_copy;
|
||||
} tSMP_REQ_Q_ENTRY;
|
||||
|
||||
/* SMP control block */
|
||||
typedef struct {
|
||||
tSMP_CALLBACK *p_callback;
|
||||
TIMER_LIST_ENT rsp_timer_ent;
|
||||
UINT8 trace_level;
|
||||
BD_ADDR pairing_bda;
|
||||
tSMP_STATE state;
|
||||
BOOLEAN derive_lk;
|
||||
BOOLEAN id_addr_rcvd;
|
||||
tBLE_ADDR_TYPE id_addr_type;
|
||||
BD_ADDR id_addr;
|
||||
BOOLEAN smp_over_br;
|
||||
tSMP_BR_STATE br_state; /* if SMP over BR/ERD has priority over SMP */
|
||||
UINT8 failure;
|
||||
UINT8 status;
|
||||
UINT8 role;
|
||||
UINT16 flags;
|
||||
UINT8 cb_evt;
|
||||
tSMP_SEC_LEVEL sec_level;
|
||||
BOOLEAN connect_initialized;
|
||||
BT_OCTET16 confirm;
|
||||
BT_OCTET16 rconfirm;
|
||||
BT_OCTET16 rrand; /* for SC this is peer nonce */
|
||||
BT_OCTET16 rand; /* for SC this is local nonce */
|
||||
BT_OCTET32 private_key;
|
||||
BT_OCTET32 dhkey;
|
||||
BT_OCTET16 commitment;
|
||||
BT_OCTET16 remote_commitment;
|
||||
BT_OCTET16 local_random; /* local randomizer - passkey or OOB randomizer */
|
||||
BT_OCTET16 peer_random; /* peer randomizer - passkey or OOB randomizer */
|
||||
BT_OCTET16 dhkey_check;
|
||||
BT_OCTET16 remote_dhkey_check;
|
||||
tSMP_PUBLIC_KEY loc_publ_key;
|
||||
tSMP_PUBLIC_KEY peer_publ_key;
|
||||
tSMP_OOB_DATA_TYPE req_oob_type;
|
||||
tSMP_SC_OOB_DATA sc_oob_data;
|
||||
tSMP_IO_CAP peer_io_caps;
|
||||
tSMP_IO_CAP local_io_capability;
|
||||
tSMP_OOB_FLAG peer_oob_flag;
|
||||
tSMP_OOB_FLAG loc_oob_flag;
|
||||
tSMP_AUTH_REQ peer_auth_req;
|
||||
tSMP_AUTH_REQ loc_auth_req;
|
||||
tSMP_AUTH_REQ auth_mode;
|
||||
BOOLEAN secure_connections_only_mode_required;/* TRUE if locally SM is required to operate */
|
||||
/* either in Secure Connections mode or not at all */
|
||||
tSMP_ASSO_MODEL selected_association_model;
|
||||
BOOLEAN le_secure_connections_mode_is_used;
|
||||
BOOLEAN le_sc_kp_notif_is_used;
|
||||
tSMP_SC_KEY_TYPE local_keypress_notification;
|
||||
tSMP_SC_KEY_TYPE peer_keypress_notification;
|
||||
UINT8 round; /* authentication stage 1 round for passkey association model */
|
||||
UINT32 number_to_display;
|
||||
BT_OCTET16 mac_key;
|
||||
UINT8 peer_enc_size;
|
||||
UINT8 loc_enc_size;
|
||||
UINT8 peer_i_key;
|
||||
UINT8 peer_r_key;
|
||||
UINT8 local_i_key;
|
||||
UINT8 local_r_key;
|
||||
|
||||
BT_OCTET16 tk;
|
||||
BT_OCTET16 ltk;
|
||||
UINT16 div;
|
||||
BT_OCTET16 csrk; /* storage for local CSRK */
|
||||
UINT16 ediv;
|
||||
BT_OCTET8 enc_rand;
|
||||
UINT8 rand_enc_proc_state;
|
||||
UINT8 addr_type;
|
||||
BD_ADDR local_bda;
|
||||
BOOLEAN is_pair_cancel;
|
||||
BOOLEAN discard_sec_req;
|
||||
UINT8 rcvd_cmd_code;
|
||||
UINT8 rcvd_cmd_len;
|
||||
UINT16 total_tx_unacked;
|
||||
BOOLEAN wait_for_authorization_complete;
|
||||
BOOLEAN use_static_passkey;
|
||||
UINT32 static_passkey;
|
||||
BOOLEAN accept_specified_sec_auth;
|
||||
tSMP_AUTH_REQ origin_loc_auth_req;
|
||||
} tSMP_CB;
|
||||
|
||||
/* Server Action functions are of this type */
|
||||
typedef void (*tSMP_ACT)(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#if SMP_DYNAMIC_MEMORY == FALSE
|
||||
extern tSMP_CB smp_cb;
|
||||
#else
|
||||
extern tSMP_CB *smp_cb_ptr;
|
||||
#define smp_cb (*smp_cb_ptr)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Functions provided by att_main.c */
|
||||
extern void smp_init (void);
|
||||
|
||||
/* smp main */
|
||||
extern void smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data);
|
||||
|
||||
extern void smp_proc_sec_request(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_set_fail_nc (BOOLEAN enable);
|
||||
extern void smp_set_fail_conf (BOOLEAN enable);
|
||||
extern void smp_set_passk_entry_fail(BOOLEAN enable);
|
||||
extern void smp_set_oob_fail(BOOLEAN enable);
|
||||
extern void smp_set_peer_sc_notif(BOOLEAN enable);
|
||||
extern void smp_aes_cmac_rfc4493_chk (UINT8 *key, UINT8 *msg, UINT8 msg_len,
|
||||
UINT8 mac_len, UINT8 *mac);
|
||||
extern void smp_f4_calc_chk (UINT8 *U, UINT8 *V, UINT8 *X, UINT8 *Z, UINT8 *mac);
|
||||
extern void smp_g2_calc_chk (UINT8 *U, UINT8 *V, UINT8 *X, UINT8 *Y);
|
||||
extern void smp_h6_calc_chk (UINT8 *key, UINT8 *key_id, UINT8 *mac);
|
||||
extern void smp_f5_key_calc_chk (UINT8 *w, UINT8 *mac);
|
||||
extern void smp_f5_mackey_or_ltk_calc_chk(UINT8 *t, UINT8 *counter,
|
||||
UINT8 *key_id, UINT8 *n1,
|
||||
UINT8 *n2, UINT8 *a1, UINT8 *a2,
|
||||
UINT8 *length, UINT8 *mac);
|
||||
extern void smp_f5_calc_chk (UINT8 *w, UINT8 *n1, UINT8 *n2, UINT8 *a1, UINT8 *a2,
|
||||
UINT8 *mac_key, UINT8 *ltk);
|
||||
extern void smp_f6_calc_chk (UINT8 *w, UINT8 *n1, UINT8 *n2, UINT8 *r,
|
||||
UINT8 *iocap, UINT8 *a1, UINT8 *a2, UINT8 *mac);
|
||||
/* smp_main */
|
||||
extern void smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data);
|
||||
extern tSMP_STATE smp_get_state(void);
|
||||
extern void smp_set_state(tSMP_STATE state);
|
||||
|
||||
/* smp_br_main */
|
||||
extern void smp_br_state_machine_event(tSMP_CB *p_cb, tSMP_BR_EVENT event, void *p_data);
|
||||
extern tSMP_BR_STATE smp_get_br_state(void);
|
||||
extern void smp_set_br_state(tSMP_BR_STATE state);
|
||||
|
||||
|
||||
/* smp_act.c */
|
||||
extern void smp_send_pair_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_send_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_send_pair_fail(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_send_rand(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_send_pair_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_send_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_send_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_send_keypress_notification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_proc_pair_fail(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_proc_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_proc_rand(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_process_pairing_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_proc_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_proc_master_id(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_proc_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_proc_id_addr(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_proc_sec_grant(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_proc_sec_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_proc_sl_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_start_enc(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_enc_cmpl(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_proc_discard(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_pairing_cmpl(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_decide_association_model(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_send_app_cback(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_proc_compare(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_check_auth_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_process_io_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_send_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_send_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_send_csrk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_send_ltk_reply(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_proc_pair_cmd(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_pair_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_idle_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_send_pair_rsp(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_key_distribution(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_proc_srk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_generate_csrk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_fast_conn_param(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_key_pick_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_both_have_public_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_start_secure_connection_phase1(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_process_local_nonce(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_process_pairing_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_process_peer_nonce(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_process_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_match_dhkey_checks(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_process_keypress_notification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_move_to_secure_connections_phase2(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_phase_2_dhkey_checks_are_present(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_wait_for_both_public_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_start_passkey_verification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_process_secure_connection_oob_data(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_process_secure_connection_long_term_key(void);
|
||||
extern void smp_set_local_oob_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_set_local_oob_random_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_set_derive_link_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_derive_link_key_from_long_term_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_br_process_pairing_command(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_br_process_security_grant(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_br_process_slave_keys_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_br_send_pair_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_br_check_authorization_request(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_br_select_next_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_br_process_link_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_key_distribution_by_transport(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_br_pairing_complete(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
|
||||
/* smp_l2c */
|
||||
extern void smp_l2cap_if_init (void);
|
||||
extern void smp_data_ind (BD_ADDR bd_addr, BT_HDR *p_buf);
|
||||
|
||||
/* smp_util.c */
|
||||
extern BOOLEAN smp_send_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
|
||||
extern void smp_cb_cleanup(tSMP_CB *p_cb);
|
||||
extern void smp_reset_control_value(tSMP_CB *p_cb);
|
||||
extern void smp_proc_pairing_cmpl(tSMP_CB *p_cb);
|
||||
extern void smp_convert_string_to_tk(BT_OCTET16 tk, UINT32 passkey);
|
||||
extern void smp_mask_enc_key(UINT8 loc_enc_size, UINT8 *p_data);
|
||||
extern void smp_rsp_timeout(TIMER_LIST_ENT *p_tle);
|
||||
extern void smp_xor_128(BT_OCTET16 a, const BT_OCTET16 b);
|
||||
extern BOOLEAN smp_encrypt_data (UINT8 *key, UINT8 key_len,
|
||||
UINT8 *plain_text, UINT8 pt_len,
|
||||
tSMP_ENC *p_out);
|
||||
extern BOOLEAN smp_command_has_invalid_parameters(tSMP_CB *p_cb);
|
||||
extern void smp_reject_unexpected_pairing_command(BD_ADDR bd_addr);
|
||||
extern tSMP_ASSO_MODEL smp_select_association_model(tSMP_CB *p_cb);
|
||||
extern void smp_reverse_array(UINT8 *arr, UINT8 len);
|
||||
extern UINT8 smp_calculate_random_input(UINT8 *random, UINT8 round);
|
||||
extern void smp_collect_local_io_capabilities(UINT8 *iocap, tSMP_CB *p_cb);
|
||||
extern void smp_collect_peer_io_capabilities(UINT8 *iocap, tSMP_CB *p_cb);
|
||||
extern void smp_collect_local_ble_address(UINT8 *le_addr, tSMP_CB *p_cb);
|
||||
extern void smp_collect_peer_ble_address(UINT8 *le_addr, tSMP_CB *p_cb);
|
||||
extern BOOLEAN smp_check_commitment(tSMP_CB *p_cb);
|
||||
extern void smp_save_secure_connections_long_term_key(tSMP_CB *p_cb);
|
||||
extern BOOLEAN smp_calculate_f5_mackey_and_long_term_key(tSMP_CB *p_cb);
|
||||
extern void smp_remove_fixed_channel(tSMP_CB *p_cb);
|
||||
extern BOOLEAN smp_request_oob_data(tSMP_CB *p_cb);
|
||||
|
||||
/* smp_keys.c */
|
||||
extern void smp_generate_srand_mrand_confirm (tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_generate_compare (tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_generate_stk (tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_generate_ltk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_generate_passkey (tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_generate_rand_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_create_private_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_use_oob_private_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_compute_dhkey(tSMP_CB *p_cb);
|
||||
extern void smp_calculate_local_commitment(tSMP_CB *p_cb);
|
||||
extern void smp_calculate_peer_commitment(tSMP_CB *p_cb, BT_OCTET16 output_buf);
|
||||
extern void smp_calculate_numeric_comparison_display_number(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_calculate_local_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_calculate_peer_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
|
||||
extern void smp_start_nonce_generation(tSMP_CB *p_cb);
|
||||
extern BOOLEAN smp_calculate_link_key_from_long_term_key(tSMP_CB *p_cb);
|
||||
extern BOOLEAN smp_calculate_long_term_key_from_link_key(tSMP_CB *p_cb);
|
||||
extern void smp_calculate_f4(UINT8 *u, UINT8 *v, UINT8 *x, UINT8 z, UINT8 *c);
|
||||
extern UINT32 smp_calculate_g2(UINT8 *u, UINT8 *v, UINT8 *x, UINT8 *y);
|
||||
extern BOOLEAN smp_calculate_f5(UINT8 *w, UINT8 *n1, UINT8 *n2, UINT8 *a1, UINT8 *a2,
|
||||
UINT8 *mac_key, UINT8 *ltk);
|
||||
extern BOOLEAN smp_calculate_f5_mackey_or_long_term_key(UINT8 *t, UINT8 *counter,
|
||||
UINT8 *key_id, UINT8 *n1, UINT8 *n2, UINT8 *a1,
|
||||
UINT8 *a2, UINT8 *length, UINT8 *mac);
|
||||
extern BOOLEAN smp_calculate_f5_key(UINT8 *w, UINT8 *t);
|
||||
extern BOOLEAN smp_calculate_f6(UINT8 *w, UINT8 *n1, UINT8 *n2, UINT8 *r, UINT8 *iocap,
|
||||
UINT8 *a1, UINT8 *a2, UINT8 *f3);
|
||||
extern BOOLEAN smp_calculate_h6(UINT8 *w, UINT8 *keyid, UINT8 *h2);
|
||||
extern void smp_save_local_oob_data(tSMP_CB *p_cb);
|
||||
extern void smp_clear_local_oob_data(void);
|
||||
extern tSMP_LOC_OOB_DATA *smp_get_local_oob_data(void);
|
||||
#if SMP_DEBUG == TRUE
|
||||
extern void smp_debug_print_nbyte_little_endian (UINT8 *p, const UINT8 *key_name,
|
||||
UINT8 len);
|
||||
#endif
|
||||
|
||||
/* smp_cmac.c */
|
||||
extern BOOLEAN aes_cipher_msg_auth_code(BT_OCTET16 key, UINT8 *input, UINT16 length,
|
||||
UINT16 tlen, UINT8 *p_signature);
|
||||
extern void print128(BT_OCTET16 x, const UINT8 *key_name);
|
||||
|
||||
// #endif ///BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
|
||||
|
||||
#endif /* SMP_INT_H */
|
||||
@@ -0,0 +1,78 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2006-2015 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file contains simple pairing algorithms
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "p_256_ecc_pp.h"
|
||||
|
||||
void p_256_init_curve(UINT32 keyLength)
|
||||
{
|
||||
elliptic_curve_t *ec;
|
||||
|
||||
if (keyLength == KEY_LENGTH_DWORDS_P256) {
|
||||
ec = &curve_p256;
|
||||
|
||||
ec->p[7] = 0xFFFFFFFF;
|
||||
ec->p[6] = 0x00000001;
|
||||
ec->p[5] = 0x0;
|
||||
ec->p[4] = 0x0;
|
||||
ec->p[3] = 0x0;
|
||||
ec->p[2] = 0xFFFFFFFF;
|
||||
ec->p[1] = 0xFFFFFFFF;
|
||||
ec->p[0] = 0xFFFFFFFF;
|
||||
|
||||
memset(ec->omega, 0, KEY_LENGTH_DWORDS_P256 * sizeof(ec->omega[0]));
|
||||
memset(ec->a, 0, KEY_LENGTH_DWORDS_P256 * sizeof(ec->a[0]));
|
||||
|
||||
ec->a_minus3 = TRUE;
|
||||
|
||||
//b
|
||||
ec->b[7] = 0x5ac635d8;
|
||||
ec->b[6] = 0xaa3a93e7;
|
||||
ec->b[5] = 0xb3ebbd55;
|
||||
ec->b[4] = 0x769886bc;
|
||||
ec->b[3] = 0x651d06b0;
|
||||
ec->b[2] = 0xcc53b0f6;
|
||||
ec->b[1] = 0x3bce3c3e;
|
||||
ec->b[0] = 0x27d2604b;
|
||||
|
||||
//base point
|
||||
ec->G.x[7] = 0x6b17d1f2;
|
||||
ec->G.x[6] = 0xe12c4247;
|
||||
ec->G.x[5] = 0xf8bce6e5;
|
||||
ec->G.x[4] = 0x63a440f2;
|
||||
ec->G.x[3] = 0x77037d81;
|
||||
ec->G.x[2] = 0x2deb33a0;
|
||||
ec->G.x[1] = 0xf4a13945;
|
||||
ec->G.x[0] = 0xd898c296;
|
||||
|
||||
ec->G.y[7] = 0x4fe342e2;
|
||||
ec->G.y[6] = 0xfe1a7f9b;
|
||||
ec->G.y[5] = 0x8ee7eb4a;
|
||||
ec->G.y[4] = 0x7c0f9e16;
|
||||
ec->G.y[3] = 0x2bce3357;
|
||||
ec->G.y[2] = 0x6b315ece;
|
||||
ec->G.y[1] = 0xcbb64068;
|
||||
ec->G.y[0] = 0x37bf51f5;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2006-2015 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file contains simple pairing algorithms using Elliptic Curve Cryptography for private public key
|
||||
*
|
||||
******************************************************************************/
|
||||
//#include <stdio.h>
|
||||
//#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "p_256_ecc_pp.h"
|
||||
#include "p_256_multprecision.h"
|
||||
#include "common/bt_target.h"
|
||||
|
||||
#if SMP_DYNAMIC_MEMORY == FALSE
|
||||
elliptic_curve_t curve;
|
||||
elliptic_curve_t curve_p256;
|
||||
#else
|
||||
elliptic_curve_t *curve_ptr;
|
||||
elliptic_curve_t *curve_p256_ptr;
|
||||
#endif
|
||||
|
||||
static void p_256_init_point(Point *q)
|
||||
{
|
||||
memset(q, 0, sizeof(Point));
|
||||
}
|
||||
|
||||
static void p_256_copy_point(Point *q, Point *p)
|
||||
{
|
||||
memcpy(q, p, sizeof(Point));
|
||||
}
|
||||
|
||||
// q=2q
|
||||
static void ECC_Double(Point *q, Point *p, uint32_t keyLength)
|
||||
{
|
||||
DWORD t1[KEY_LENGTH_DWORDS_P256];
|
||||
DWORD t2[KEY_LENGTH_DWORDS_P256];
|
||||
DWORD t3[KEY_LENGTH_DWORDS_P256];
|
||||
DWORD *x1;
|
||||
DWORD *x3;
|
||||
DWORD *y1;
|
||||
DWORD *y3;
|
||||
DWORD *z1;
|
||||
DWORD *z3;
|
||||
|
||||
if (multiprecision_iszero(p->z, keyLength)) {
|
||||
multiprecision_init(q->z, keyLength);
|
||||
return; // return infinity
|
||||
}
|
||||
|
||||
x1 = p->x; y1 = p->y; z1 = p->z;
|
||||
x3 = q->x; y3 = q->y; z3 = q->z;
|
||||
|
||||
multiprecision_mersenns_squa_mod(t1, z1, keyLength); // t1=z1^2
|
||||
multiprecision_sub_mod(t2, x1, t1, keyLength); // t2=x1-t1
|
||||
multiprecision_add_mod(t1, x1, t1, keyLength); // t1=x1+t1
|
||||
multiprecision_mersenns_mult_mod(t2, t1, t2, keyLength); // t2=t2*t1
|
||||
multiprecision_lshift_mod(t3, t2, keyLength);
|
||||
multiprecision_add_mod(t2, t3, t2, keyLength); // t2=3t2
|
||||
|
||||
multiprecision_mersenns_mult_mod(z3, y1, z1, keyLength); // z3=y1*z1
|
||||
multiprecision_lshift_mod(z3, z3, keyLength);
|
||||
|
||||
multiprecision_mersenns_squa_mod(y3, y1, keyLength); // y3=y1^2
|
||||
multiprecision_lshift_mod(y3, y3, keyLength);
|
||||
multiprecision_mersenns_mult_mod(t3, y3, x1, keyLength); // t3=y3*x1=x1*y1^2
|
||||
multiprecision_lshift_mod(t3, t3, keyLength);
|
||||
multiprecision_mersenns_squa_mod(y3, y3, keyLength); // y3=y3^2=y1^4
|
||||
multiprecision_lshift_mod(y3, y3, keyLength);
|
||||
|
||||
multiprecision_mersenns_squa_mod(x3, t2, keyLength); // x3=t2^2
|
||||
multiprecision_lshift_mod(t1, t3, keyLength); // t1=2t3
|
||||
multiprecision_sub_mod(x3, x3, t1, keyLength); // x3=x3-t1
|
||||
multiprecision_sub_mod(t1, t3, x3, keyLength); // t1=t3-x3
|
||||
multiprecision_mersenns_mult_mod(t1, t1, t2, keyLength); // t1=t1*t2
|
||||
multiprecision_sub_mod(y3, t1, y3, keyLength); // y3=t1-y3
|
||||
}
|
||||
|
||||
// q=q+p, zp must be 1
|
||||
static void ECC_Add(Point *r, Point *p, Point *q, uint32_t keyLength)
|
||||
{
|
||||
DWORD t1[KEY_LENGTH_DWORDS_P256];
|
||||
DWORD t2[KEY_LENGTH_DWORDS_P256];
|
||||
DWORD *x1;
|
||||
DWORD *x2;
|
||||
DWORD *x3;
|
||||
DWORD *y1;
|
||||
DWORD *y2;
|
||||
DWORD *y3;
|
||||
DWORD *z1;
|
||||
DWORD *z2;
|
||||
DWORD *z3;
|
||||
|
||||
x1 = p->x; y1 = p->y; z1 = p->z;
|
||||
x2 = q->x; y2 = q->y; z2 = q->z;
|
||||
x3 = r->x; y3 = r->y; z3 = r->z;
|
||||
|
||||
// if Q=infinity, return p
|
||||
if (multiprecision_iszero(z2, keyLength)) {
|
||||
p_256_copy_point(r, p);
|
||||
return;
|
||||
}
|
||||
|
||||
// if P=infinity, return q
|
||||
if (multiprecision_iszero(z1, keyLength)) {
|
||||
p_256_copy_point(r, q);
|
||||
return;
|
||||
}
|
||||
|
||||
multiprecision_mersenns_squa_mod(t1, z1, keyLength); // t1=z1^2
|
||||
multiprecision_mersenns_mult_mod(t2, z1, t1, keyLength); // t2=t1*z1
|
||||
multiprecision_mersenns_mult_mod(t1, x2, t1, keyLength); // t1=t1*x2
|
||||
multiprecision_mersenns_mult_mod(t2, y2, t2, keyLength); // t2=t2*y2
|
||||
|
||||
multiprecision_sub_mod(t1, t1, x1, keyLength); // t1=t1-x1
|
||||
multiprecision_sub_mod(t2, t2, y1, keyLength); // t2=t2-y1
|
||||
|
||||
if (multiprecision_iszero(t1, keyLength)) {
|
||||
if (multiprecision_iszero(t2, keyLength)) {
|
||||
ECC_Double(r, q, keyLength) ;
|
||||
return;
|
||||
} else {
|
||||
multiprecision_init(z3, keyLength);
|
||||
return; // return infinity
|
||||
}
|
||||
}
|
||||
|
||||
multiprecision_mersenns_mult_mod(z3, z1, t1, keyLength); // z3=z1*t1
|
||||
multiprecision_mersenns_squa_mod(y3, t1, keyLength); // t3=t1^2
|
||||
multiprecision_mersenns_mult_mod(z1, y3, t1, keyLength); // t4=t3*t1
|
||||
multiprecision_mersenns_mult_mod(y3, y3, x1, keyLength); // t3=t3*x1
|
||||
multiprecision_lshift_mod(t1, y3, keyLength); // t1=2*t3
|
||||
multiprecision_mersenns_squa_mod(x3, t2, keyLength); // x3=t2^2
|
||||
multiprecision_sub_mod(x3, x3, t1, keyLength); // x3=x3-t1
|
||||
multiprecision_sub_mod(x3, x3, z1, keyLength); // x3=x3-t4
|
||||
multiprecision_sub_mod(y3, y3, x3, keyLength); // t3=t3-x3
|
||||
multiprecision_mersenns_mult_mod(y3, y3, t2, keyLength); // t3=t3*t2
|
||||
multiprecision_mersenns_mult_mod(z1, z1, y1, keyLength); // t4=t4*t1
|
||||
multiprecision_sub_mod(y3, y3, z1, keyLength);
|
||||
}
|
||||
|
||||
// Computing the Non-Adjacent Form of a positive integer
|
||||
static void ECC_NAF(uint8_t *naf, uint32_t *NumNAF, DWORD *k, uint32_t keyLength)
|
||||
{
|
||||
uint32_t sign;
|
||||
int i = 0;
|
||||
int j;
|
||||
uint32_t var;
|
||||
|
||||
while ((var = multiprecision_most_signbits(k, keyLength)) >= 1) {
|
||||
if (k[0] & 0x01) { // k is odd
|
||||
sign = (k[0] & 0x03); // 1 or 3
|
||||
|
||||
// k = k-naf[i]
|
||||
if (sign == 1) {
|
||||
k[0] = k[0] & 0xFFFFFFFE;
|
||||
} else {
|
||||
k[0] = k[0] + 1;
|
||||
if (k[0] == 0) { //overflow
|
||||
j = 1;
|
||||
do {
|
||||
k[j]++;
|
||||
} while (k[j++] == 0); //overflow
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sign = 0;
|
||||
}
|
||||
|
||||
multiprecision_rshift(k, k, keyLength);
|
||||
naf[i / 4] |= (sign) << ((i % 4) * 2);
|
||||
i++;
|
||||
}
|
||||
|
||||
*NumNAF = i;
|
||||
}
|
||||
|
||||
// Binary Non-Adjacent Form for point multiplication
|
||||
void ECC_PointMult_Bin_NAF(Point *q, Point *p, DWORD *n, uint32_t keyLength)
|
||||
{
|
||||
uint32_t sign;
|
||||
UINT8 naf[256 / 4 + 1];
|
||||
uint32_t NumNaf;
|
||||
Point minus_p;
|
||||
Point r;
|
||||
DWORD *modp;
|
||||
|
||||
if (keyLength == KEY_LENGTH_DWORDS_P256) {
|
||||
modp = curve_p256.p;
|
||||
} else {
|
||||
modp = curve.p;
|
||||
}
|
||||
|
||||
p_256_init_point(&r);
|
||||
multiprecision_init(p->z, keyLength);
|
||||
p->z[0] = 1;
|
||||
|
||||
// initialization
|
||||
p_256_init_point(q);
|
||||
|
||||
// -p
|
||||
multiprecision_copy(minus_p.x, p->x, keyLength);
|
||||
multiprecision_sub(minus_p.y, modp, p->y, keyLength);
|
||||
|
||||
multiprecision_init(minus_p.z, keyLength);
|
||||
minus_p.z[0] = 1;
|
||||
|
||||
// NAF
|
||||
memset(naf, 0, sizeof(naf));
|
||||
ECC_NAF(naf, &NumNaf, n, keyLength);
|
||||
|
||||
for (int i = NumNaf - 1; i >= 0; i--) {
|
||||
p_256_copy_point(&r, q);
|
||||
ECC_Double(q, &r, keyLength);
|
||||
sign = (naf[i / 4] >> ((i % 4) * 2)) & 0x03;
|
||||
|
||||
if (sign == 1) {
|
||||
p_256_copy_point(&r, q);
|
||||
ECC_Add(q, &r, p, keyLength);
|
||||
} else if (sign == 3) {
|
||||
p_256_copy_point(&r, q);
|
||||
ECC_Add(q, &r, &minus_p, keyLength);
|
||||
}
|
||||
}
|
||||
|
||||
multiprecision_inv_mod(minus_p.x, q->z, keyLength);
|
||||
multiprecision_mersenns_squa_mod(q->z, minus_p.x, keyLength);
|
||||
multiprecision_mersenns_mult_mod(q->x, q->x, q->z, keyLength);
|
||||
multiprecision_mersenns_mult_mod(q->z, q->z, minus_p.x, keyLength);
|
||||
multiprecision_mersenns_mult_mod(q->y, q->y, q->z, keyLength);
|
||||
}
|
||||
|
||||
bool ECC_CheckPointIsInElliCur_P256(Point *p)
|
||||
{
|
||||
/* y^2 % q */
|
||||
DWORD y_y_q[KEY_LENGTH_DWORDS_P256] = {0x0};
|
||||
/* x^2 % q */
|
||||
DWORD x_x_q[KEY_LENGTH_DWORDS_P256] = {0x0};
|
||||
/* x % q */
|
||||
DWORD x_q[KEY_LENGTH_DWORDS_P256] = {0x0};
|
||||
/* x^2, To prevent overflow, the length of the x square here needs to
|
||||
be expanded to two times the original one. */
|
||||
DWORD x_x[2*KEY_LENGTH_DWORDS_P256] = {0x0};
|
||||
/* y_y_q =(p->y)^2(mod q) */
|
||||
multiprecision_mersenns_squa_mod(y_y_q, p->y, KEY_LENGTH_DWORDS_P256);
|
||||
/* Calculate the value of p->x square, x_x = (p->x)^2 */
|
||||
multiprecision_mult(x_x, p->x, p->x, KEY_LENGTH_DWORDS_P256);
|
||||
/* The function of the elliptic curve is y^2 = x^3 - 3x + b (mod q) ==>
|
||||
y^2 = (x^2 - 3)*x + b (mod q),
|
||||
so we calculate the x^2 - 3 value here */
|
||||
x_x[0] -= 3;
|
||||
/* Using math relations. (a*b) % q = ((a%q)*(b%q)) % q ==>
|
||||
(x^2 - 3)*x = (((x^2 - 3) % q) * x % q) % q */
|
||||
multiprecision_fast_mod_P256(x_x_q, x_x);
|
||||
/* x_x = x_x_q * x_q */
|
||||
multiprecision_mult(x_x, x_x_q, p->x, KEY_LENGTH_DWORDS_P256);
|
||||
/* x_q = x_x % q */
|
||||
multiprecision_fast_mod_P256(x_q, x_x);
|
||||
/* Save the result in x_x_q */
|
||||
multiprecision_add_mod(x_x_q, x_q, curve_p256.b, KEY_LENGTH_DWORDS_P256);
|
||||
/* compare the y_y_q and x_x_q, see if they are on a given elliptic curve. */
|
||||
if (multiprecision_compare(y_y_q, x_x_q, KEY_LENGTH_DWORDS_P256)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,647 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2006-2015 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file contains simple pairing algorithms
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "common/bt_target.h"
|
||||
#include "p_256_ecc_pp.h"
|
||||
#include "p_256_multprecision.h"
|
||||
|
||||
void multiprecision_init(DWORD *c, uint32_t keyLength)
|
||||
{
|
||||
for (uint32_t i = 0; i < keyLength; i++) {
|
||||
c[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void multiprecision_copy(DWORD *c, DWORD *a, uint32_t keyLength)
|
||||
{
|
||||
for (uint32_t i = 0; i < keyLength; i++) {
|
||||
c[i] = a[i];
|
||||
}
|
||||
}
|
||||
|
||||
int multiprecision_compare(DWORD *a, DWORD *b, uint32_t keyLength)
|
||||
{
|
||||
for (int i = keyLength - 1; i >= 0; i--) {
|
||||
if (a[i] > b[i]) {
|
||||
return 1;
|
||||
}
|
||||
if (a[i] < b[i]) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int multiprecision_iszero(DWORD *a, uint32_t keyLength)
|
||||
{
|
||||
for (uint32_t i = 0; i < keyLength; i++)
|
||||
if (a[i]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
UINT32 multiprecision_dword_bits(DWORD a)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < DWORD_BITS; i++, a >>= 1)
|
||||
if (a == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
UINT32 multiprecision_most_signdwords(DWORD *a, uint32_t keyLength)
|
||||
{
|
||||
int i;
|
||||
for (i = keyLength - 1; i >= 0; i--)
|
||||
if (a[i]) {
|
||||
break;
|
||||
}
|
||||
return (i + 1);
|
||||
}
|
||||
|
||||
UINT32 multiprecision_most_signbits(DWORD *a, uint32_t keyLength)
|
||||
{
|
||||
int aMostSignDWORDs;
|
||||
|
||||
aMostSignDWORDs = multiprecision_most_signdwords(a, keyLength);
|
||||
if (aMostSignDWORDs == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (((aMostSignDWORDs - 1) << DWORD_BITS_SHIFT) +
|
||||
multiprecision_dword_bits(a[aMostSignDWORDs - 1]) );
|
||||
}
|
||||
|
||||
DWORD multiprecision_add(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
|
||||
{
|
||||
DWORD carrier;
|
||||
DWORD temp;
|
||||
|
||||
carrier = 0;
|
||||
for (uint32_t i = 0; i < keyLength; i++) {
|
||||
temp = a[i] + carrier;
|
||||
carrier = (temp < carrier);
|
||||
temp += b[i];
|
||||
carrier |= (temp < b[i]);
|
||||
c[i] = temp;
|
||||
}
|
||||
|
||||
return carrier;
|
||||
}
|
||||
|
||||
//c=a-b
|
||||
DWORD multiprecision_sub(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
|
||||
{
|
||||
DWORD borrow;
|
||||
DWORD temp;
|
||||
|
||||
borrow = 0;
|
||||
for (uint32_t i = 0; i < keyLength; i++) {
|
||||
temp = a[i] - borrow;
|
||||
borrow = (temp > a[i]);
|
||||
c[i] = temp - b[i];
|
||||
borrow |= (c[i] > temp);
|
||||
}
|
||||
|
||||
return borrow;
|
||||
}
|
||||
|
||||
// c = a << 1
|
||||
void multiprecision_lshift_mod(DWORD *c, DWORD *a, uint32_t keyLength)
|
||||
{
|
||||
DWORD carrier;
|
||||
DWORD *modp;
|
||||
|
||||
if (keyLength == KEY_LENGTH_DWORDS_P192) {
|
||||
modp = curve.p;
|
||||
} else if (keyLength == KEY_LENGTH_DWORDS_P256) {
|
||||
modp = curve_p256.p;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
carrier = multiprecision_lshift(c, a, keyLength);
|
||||
if (carrier) {
|
||||
multiprecision_sub(c, c, modp, keyLength);
|
||||
} else if (multiprecision_compare(c, modp, keyLength) >= 0) {
|
||||
multiprecision_sub(c, c, modp, keyLength);
|
||||
}
|
||||
}
|
||||
|
||||
// c=a>>1
|
||||
void multiprecision_rshift(DWORD *c, DWORD *a, uint32_t keyLength)
|
||||
{
|
||||
int j;
|
||||
DWORD b = 1;
|
||||
|
||||
j = DWORD_BITS - b;
|
||||
|
||||
DWORD carrier = 0;
|
||||
DWORD temp;
|
||||
for (int i = keyLength - 1; i >= 0; i--) {
|
||||
temp = a[i]; // in case of c==a
|
||||
c[i] = (temp >> b) | carrier;
|
||||
carrier = temp << j;
|
||||
}
|
||||
}
|
||||
|
||||
// Curve specific optimization when p is a pseudo-Mersenns prime, p=2^(KEY_LENGTH_BITS)-omega
|
||||
void multiprecision_mersenns_mult_mod(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
|
||||
{
|
||||
DWORD cc[2 * KEY_LENGTH_DWORDS_P256];
|
||||
|
||||
multiprecision_mult(cc, a, b, keyLength);
|
||||
if (keyLength == 6) {
|
||||
multiprecision_fast_mod(c, cc);
|
||||
} else if (keyLength == 8) {
|
||||
multiprecision_fast_mod_P256(c, cc);
|
||||
}
|
||||
}
|
||||
|
||||
// Curve specific optimization when p is a pseudo-Mersenns prime
|
||||
void multiprecision_mersenns_squa_mod(DWORD *c, DWORD *a, uint32_t keyLength)
|
||||
{
|
||||
multiprecision_mersenns_mult_mod(c, a, a, keyLength);
|
||||
}
|
||||
|
||||
// c=(a+b) mod p, b<p, a<p
|
||||
void multiprecision_add_mod(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
|
||||
{
|
||||
DWORD carrier;
|
||||
DWORD *modp;
|
||||
|
||||
if (keyLength == KEY_LENGTH_DWORDS_P192) {
|
||||
modp = curve.p;
|
||||
} else if (keyLength == KEY_LENGTH_DWORDS_P256) {
|
||||
modp = curve_p256.p;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
carrier = multiprecision_add(c, a, b, keyLength);
|
||||
if (carrier) {
|
||||
multiprecision_sub(c, c, modp, keyLength);
|
||||
} else if (multiprecision_compare(c, modp, keyLength) >= 0) {
|
||||
multiprecision_sub(c, c, modp, keyLength);
|
||||
}
|
||||
}
|
||||
|
||||
// c=(a-b) mod p, a<p, b<p
|
||||
void multiprecision_sub_mod(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
|
||||
{
|
||||
DWORD borrow;
|
||||
DWORD *modp;
|
||||
|
||||
if (keyLength == KEY_LENGTH_DWORDS_P192) {
|
||||
modp = curve.p;
|
||||
} else if (keyLength == KEY_LENGTH_DWORDS_P256) {
|
||||
modp = curve_p256.p;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
borrow = multiprecision_sub(c, a, b, keyLength);
|
||||
if (borrow) {
|
||||
multiprecision_add(c, c, modp, keyLength);
|
||||
}
|
||||
}
|
||||
|
||||
// c=a<<b, b<DWORD_BITS, c has a buffer size of NumDWORDs+1
|
||||
DWORD multiprecision_lshift(DWORD *c, DWORD *a, uint32_t keyLength)
|
||||
{
|
||||
int j;
|
||||
uint32_t b = 1;
|
||||
j = DWORD_BITS - b;
|
||||
|
||||
DWORD carrier = 0;
|
||||
DWORD temp;
|
||||
|
||||
for (uint32_t i = 0; i < keyLength; i++) {
|
||||
temp = a[i]; // in case c==a
|
||||
c[i] = (temp << b) | carrier;
|
||||
carrier = temp >> j;
|
||||
}
|
||||
|
||||
return carrier;
|
||||
}
|
||||
|
||||
// c=a*b; c must have a buffer of 2*Key_LENGTH_DWORDS, c != a != b
|
||||
void multiprecision_mult(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
|
||||
{
|
||||
DWORD W;
|
||||
DWORD U;
|
||||
DWORD V;
|
||||
|
||||
U = V = W = 0;
|
||||
multiprecision_init(c, keyLength);
|
||||
|
||||
//assume little endian right now
|
||||
for (uint32_t i = 0; i < keyLength; i++) {
|
||||
U = 0;
|
||||
for (uint32_t j = 0; j < keyLength; j++) {
|
||||
uint64_t result;
|
||||
result = ((UINT64)a[i]) * ((uint64_t) b[j]);
|
||||
W = result >> 32;
|
||||
V = a[i] * b[j];
|
||||
V = V + U;
|
||||
U = (V < U);
|
||||
U += W;
|
||||
V = V + c[i + j];
|
||||
U += (V < c[i + j]);
|
||||
c[i + j] = V;
|
||||
}
|
||||
c[i + keyLength] = U;
|
||||
}
|
||||
}
|
||||
|
||||
void multiprecision_fast_mod(DWORD *c, DWORD *a)
|
||||
{
|
||||
DWORD U;
|
||||
DWORD V;
|
||||
DWORD *modp = curve.p;
|
||||
|
||||
c[0] = a[0] + a[6];
|
||||
U = c[0] < a[0];
|
||||
c[0] += a[10];
|
||||
U += c[0] < a[10];
|
||||
|
||||
c[1] = a[1] + U;
|
||||
U = c[1] < a[1];
|
||||
c[1] += a[7];
|
||||
U += c[1] < a[7];
|
||||
c[1] += a[11];
|
||||
U += c[1] < a[11];
|
||||
|
||||
c[2] = a[2] + U;
|
||||
U = c[2] < a[2];
|
||||
c[2] += a[6];
|
||||
U += c[2] < a[6];
|
||||
c[2] += a[8];
|
||||
U += c[2] < a[8];
|
||||
c[2] += a[10];
|
||||
U += c[2] < a[10];
|
||||
|
||||
c[3] = a[3] + U;
|
||||
U = c[3] < a[3];
|
||||
c[3] += a[7];
|
||||
U += c[3] < a[7];
|
||||
c[3] += a[9];
|
||||
U += c[3] < a[9];
|
||||
c[3] += a[11];
|
||||
U += c[3] < a[11];
|
||||
|
||||
c[4] = a[4] + U;
|
||||
U = c[4] < a[4];
|
||||
c[4] += a[8];
|
||||
U += c[4] < a[8];
|
||||
c[4] += a[10];
|
||||
U += c[4] < a[10];
|
||||
|
||||
c[5] = a[5] + U;
|
||||
U = c[5] < a[5];
|
||||
c[5] += a[9];
|
||||
U += c[5] < a[9];
|
||||
c[5] += a[11];
|
||||
U += c[5] < a[11];
|
||||
|
||||
c[0] += U;
|
||||
V = c[0] < U;
|
||||
c[1] += V;
|
||||
V = c[1] < V;
|
||||
c[2] += V;
|
||||
V = c[2] < V;
|
||||
c[2] += U;
|
||||
V = c[2] < U;
|
||||
c[3] += V;
|
||||
V = c[3] < V;
|
||||
c[4] += V;
|
||||
V = c[4] < V;
|
||||
c[5] += V;
|
||||
V = c[5] < V;
|
||||
|
||||
if (V) {
|
||||
multiprecision_sub(c, c, modp, KEY_LENGTH_DWORDS_P192);
|
||||
} else if (multiprecision_compare(c, modp, KEY_LENGTH_DWORDS_P192) >= 0) {
|
||||
multiprecision_sub(c, c, modp, KEY_LENGTH_DWORDS_P192);
|
||||
}
|
||||
}
|
||||
|
||||
void multiprecision_fast_mod_P256(DWORD *c, DWORD *a)
|
||||
{
|
||||
DWORD A;
|
||||
DWORD B;
|
||||
DWORD C;
|
||||
DWORD D;
|
||||
DWORD E;
|
||||
DWORD F;
|
||||
DWORD G;
|
||||
uint8_t UA;
|
||||
uint8_t UB;
|
||||
uint8_t UC;
|
||||
uint8_t UD;
|
||||
uint8_t UE;
|
||||
uint8_t UF;
|
||||
uint8_t UG;
|
||||
DWORD U;
|
||||
DWORD *modp = curve_p256.p;
|
||||
|
||||
// C = a[13] + a[14] + a[15];
|
||||
C = a[13];
|
||||
C += a[14];
|
||||
UC = (C < a[14]);
|
||||
C += a[15];
|
||||
UC += (C < a[15]);
|
||||
|
||||
// E = a[8] + a[9];
|
||||
E = a[8];
|
||||
E += a[9];
|
||||
UE = (E < a[9]);
|
||||
|
||||
// F = a[9] + a[10];
|
||||
F = a[9];
|
||||
F += a[10];
|
||||
UF = (F < a[10]);
|
||||
|
||||
// G = a[10] + a[11]
|
||||
G = a[10];
|
||||
G += a[11];
|
||||
UG = (G < a[11]);
|
||||
|
||||
// B = a[12] + a[13] + a[14] + a[15] == C + a[12]
|
||||
B = C;
|
||||
UB = UC;
|
||||
B += a[12];
|
||||
UB += (B < a[12]);
|
||||
|
||||
// A = a[11] + a[12] + a[13] + a[14] == B + a[11] - a[15]
|
||||
A = B;
|
||||
UA = UB;
|
||||
A += a[11];
|
||||
UA += (A < a[11]);
|
||||
UA -= (A < a[15]);
|
||||
A -= a[15];
|
||||
|
||||
// D = a[10] + a[11] + a[12] + a[13] == A + a[10] - a[14]
|
||||
D = A;
|
||||
UD = UA;
|
||||
D += a[10];
|
||||
UD += (D < a[10]);
|
||||
UD -= (D < a[14]);
|
||||
D -= a[14];
|
||||
|
||||
c[0] = a[0];
|
||||
c[0] += E;
|
||||
U = (c[0] < E);
|
||||
U += UE;
|
||||
U -= (c[0] < A);
|
||||
U -= UA;
|
||||
c[0] -= A;
|
||||
|
||||
if (U & 0x80000000) {
|
||||
DWORD UU;
|
||||
UU = 0 - U;
|
||||
U = (a[1] < UU);
|
||||
c[1] = a[1] - UU;
|
||||
} else {
|
||||
c[1] = a[1] + U;
|
||||
U = (c[1] < a[1]);
|
||||
}
|
||||
|
||||
c[1] += F;
|
||||
U += (c[1] < F);
|
||||
U += UF;
|
||||
U -= (c[1] < B);
|
||||
U -= UB;
|
||||
c[1] -= B;
|
||||
|
||||
if (U & 0x80000000) {
|
||||
DWORD UU;
|
||||
UU = 0 - U;
|
||||
U = (a[2] < UU);
|
||||
c[2] = a[2] - UU;
|
||||
} else {
|
||||
c[2] = a[2] + U;
|
||||
U = (c[2] < a[2]);
|
||||
}
|
||||
|
||||
c[2] += G;
|
||||
U += (c[2] < G);
|
||||
U += UG;
|
||||
U -= (c[2] < C);
|
||||
U -= UC;
|
||||
c[2] -= C;
|
||||
|
||||
if (U & 0x80000000) {
|
||||
DWORD UU;
|
||||
UU = 0 - U;
|
||||
U = (a[3] < UU);
|
||||
c[3] = a[3] - UU;
|
||||
} else {
|
||||
c[3] = a[3] + U;
|
||||
U = (c[3] < a[3]);
|
||||
}
|
||||
|
||||
c[3] += A;
|
||||
U += (c[3] < A);
|
||||
U += UA;
|
||||
c[3] += a[11];
|
||||
U += (c[3] < a[11]);
|
||||
c[3] += a[12];
|
||||
U += (c[3] < a[12]);
|
||||
U -= (c[3] < a[14]);
|
||||
c[3] -= a[14];
|
||||
U -= (c[3] < a[15]);
|
||||
c[3] -= a[15];
|
||||
U -= (c[3] < E);
|
||||
U -= UE;
|
||||
c[3] -= E;
|
||||
|
||||
if (U & 0x80000000) {
|
||||
DWORD UU;
|
||||
UU = 0 - U;
|
||||
U = (a[4] < UU);
|
||||
c[4] = a[4] - UU;
|
||||
} else {
|
||||
c[4] = a[4] + U;
|
||||
U = (c[4] < a[4]);
|
||||
}
|
||||
|
||||
c[4] += B;
|
||||
U += (c[4] < B);
|
||||
U += UB;
|
||||
U -= (c[4] < a[15]);
|
||||
c[4] -= a[15];
|
||||
c[4] += a[12];
|
||||
U += (c[4] < a[12]);
|
||||
c[4] += a[13];
|
||||
U += (c[4] < a[13]);
|
||||
U -= (c[4] < F);
|
||||
U -= UF;
|
||||
c[4] -= F;
|
||||
|
||||
if (U & 0x80000000) {
|
||||
DWORD UU;
|
||||
UU = 0 - U;
|
||||
U = (a[5] < UU);
|
||||
c[5] = a[5] - UU;
|
||||
} else {
|
||||
c[5] = a[5] + U;
|
||||
U = (c[5] < a[5]);
|
||||
}
|
||||
|
||||
c[5] += C;
|
||||
U += (c[5] < C);
|
||||
U += UC;
|
||||
c[5] += a[13];
|
||||
U += (c[5] < a[13]);
|
||||
c[5] += a[14];
|
||||
U += (c[5] < a[14]);
|
||||
U -= (c[5] < G);
|
||||
U -= UG;
|
||||
c[5] -= G;
|
||||
|
||||
if (U & 0x80000000) {
|
||||
DWORD UU;
|
||||
UU = 0 - U;
|
||||
U = (a[6] < UU);
|
||||
c[6] = a[6] - UU;
|
||||
} else {
|
||||
c[6] = a[6] + U;
|
||||
U = (c[6] < a[6]);
|
||||
}
|
||||
|
||||
c[6] += C;
|
||||
U += (c[6] < C);
|
||||
U += UC;
|
||||
c[6] += a[14];
|
||||
U += (c[6] < a[14]);
|
||||
c[6] += a[14];
|
||||
U += (c[6] < a[14]);
|
||||
c[6] += a[15];
|
||||
U += (c[6] < a[15]);
|
||||
U -= (c[6] < E);
|
||||
U -= UE;
|
||||
c[6] -= E;
|
||||
|
||||
if (U & 0x80000000) {
|
||||
DWORD UU;
|
||||
UU = 0 - U;
|
||||
U = (a[7] < UU);
|
||||
c[7] = a[7] - UU;
|
||||
} else {
|
||||
c[7] = a[7] + U;
|
||||
U = (c[7] < a[7]);
|
||||
}
|
||||
|
||||
c[7] += a[15];
|
||||
U += (c[7] < a[15]);
|
||||
c[7] += a[15];
|
||||
U += (c[7] < a[15]);
|
||||
c[7] += a[15];
|
||||
U += (c[7] < a[15]);
|
||||
c[7] += a[8];
|
||||
U += (c[7] < a[8]);
|
||||
U -= (c[7] < D);
|
||||
U -= UD;
|
||||
c[7] -= D;
|
||||
|
||||
if (U & 0x80000000) {
|
||||
while (U) {
|
||||
multiprecision_add(c, c, modp, KEY_LENGTH_DWORDS_P256);
|
||||
U++;
|
||||
}
|
||||
} else if (U) {
|
||||
while (U) {
|
||||
multiprecision_sub(c, c, modp, KEY_LENGTH_DWORDS_P256);
|
||||
U--;
|
||||
}
|
||||
}
|
||||
|
||||
if (multiprecision_compare(c, modp, KEY_LENGTH_DWORDS_P256) >= 0) {
|
||||
multiprecision_sub(c, c, modp, KEY_LENGTH_DWORDS_P256);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void multiprecision_inv_mod(DWORD *aminus, DWORD *u, uint32_t keyLength)
|
||||
{
|
||||
DWORD v[KEY_LENGTH_DWORDS_P256];
|
||||
DWORD A[KEY_LENGTH_DWORDS_P256 + 1];
|
||||
DWORD C[KEY_LENGTH_DWORDS_P256 + 1];
|
||||
DWORD *modp;
|
||||
|
||||
if (keyLength == KEY_LENGTH_DWORDS_P256) {
|
||||
modp = curve_p256.p;
|
||||
} else {
|
||||
modp = curve.p;
|
||||
}
|
||||
|
||||
multiprecision_copy(v, modp, keyLength);
|
||||
multiprecision_init(A, keyLength);
|
||||
multiprecision_init(C, keyLength);
|
||||
A[0] = 1;
|
||||
|
||||
while (!multiprecision_iszero(u, keyLength)) {
|
||||
while (!(u[0] & 0x01)) { // u is even
|
||||
multiprecision_rshift(u, u, keyLength);
|
||||
if (!(A[0] & 0x01)) { // A is even
|
||||
multiprecision_rshift(A, A, keyLength);
|
||||
} else {
|
||||
A[keyLength] = multiprecision_add(A, A, modp, keyLength); // A =A+p
|
||||
multiprecision_rshift(A, A, keyLength);
|
||||
A[keyLength - 1] |= (A[keyLength] << 31);
|
||||
}
|
||||
}
|
||||
|
||||
while (!(v[0] & 0x01)) { // v is even
|
||||
multiprecision_rshift(v, v, keyLength);
|
||||
if (!(C[0] & 0x01)) { // C is even
|
||||
multiprecision_rshift(C, C, keyLength);
|
||||
} else {
|
||||
C[keyLength] = multiprecision_add(C, C, modp, keyLength); // C =C+p
|
||||
multiprecision_rshift(C, C, keyLength);
|
||||
C[keyLength - 1] |= (C[keyLength] << 31);
|
||||
}
|
||||
}
|
||||
|
||||
if (multiprecision_compare(u, v, keyLength) >= 0) {
|
||||
multiprecision_sub(u, u, v, keyLength);
|
||||
multiprecision_sub_mod(A, A, C, keyLength);
|
||||
} else {
|
||||
multiprecision_sub(v, v, u, keyLength);
|
||||
multiprecision_sub_mod(C, C, A, keyLength);
|
||||
}
|
||||
}
|
||||
|
||||
if (multiprecision_compare(C, modp, keyLength) >= 0) {
|
||||
multiprecision_sub(aminus, C, modp, keyLength);
|
||||
} else {
|
||||
multiprecision_copy(aminus, C, keyLength);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,615 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2008-2012 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file contains the implementation of the SMP interface used by
|
||||
* applications that can run over an SMP.
|
||||
*
|
||||
******************************************************************************/
|
||||
#include <string.h>
|
||||
|
||||
#include "common/bt_target.h"
|
||||
//#include "bt_utils.h"
|
||||
#if SMP_INCLUDED == TRUE
|
||||
#include "smp_int.h"
|
||||
#include "stack/smp_api.h"
|
||||
#include "stack/l2cdefs.h"
|
||||
#include "l2c_int.h"
|
||||
#include "btm_int.h"
|
||||
#include "stack/hcimsgs.h"
|
||||
|
||||
#include "stack/btu.h"
|
||||
#include "p_256_ecc_pp.h"
|
||||
#include "osi/allocator.h"
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function SMP_Init
|
||||
**
|
||||
** Description This function initializes the SMP unit.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void SMP_Init(void)
|
||||
{
|
||||
#if SMP_DYNAMIC_MEMORY
|
||||
smp_cb_ptr = (tSMP_CB *)osi_malloc(sizeof(tSMP_CB));
|
||||
curve_ptr = (elliptic_curve_t *)osi_malloc(sizeof(elliptic_curve_t));
|
||||
curve_p256_ptr = (elliptic_curve_t *)osi_malloc(sizeof(elliptic_curve_t));
|
||||
#endif
|
||||
memset(&smp_cb, 0, sizeof(tSMP_CB));
|
||||
memset(&curve, 0, sizeof(elliptic_curve_t));
|
||||
memset(&curve_p256, 0, sizeof(elliptic_curve_t));
|
||||
|
||||
#if defined(SMP_INITIAL_TRACE_LEVEL)
|
||||
smp_cb.trace_level = SMP_INITIAL_TRACE_LEVEL;
|
||||
#else
|
||||
smp_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */
|
||||
#endif
|
||||
SMP_TRACE_EVENT ("%s", __FUNCTION__);
|
||||
|
||||
smp_l2cap_if_init();
|
||||
/* initialization of P-256 parameters */
|
||||
p_256_init_curve(KEY_LENGTH_DWORDS_P256);
|
||||
}
|
||||
|
||||
void SMP_Free(void)
|
||||
{
|
||||
memset(&smp_cb, 0, sizeof(tSMP_CB));
|
||||
#if SMP_DYNAMIC_MEMORY
|
||||
FREE_AND_RESET(smp_cb_ptr);
|
||||
FREE_AND_RESET(curve_ptr);
|
||||
FREE_AND_RESET(curve_p256_ptr);
|
||||
#endif /* #if SMP_DYNAMIC_MEMORY */
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function SMP_SetTraceLevel
|
||||
**
|
||||
** Description This function sets the trace level for SMP. If called with
|
||||
** a value of 0xFF, it simply returns the current trace level.
|
||||
**
|
||||
** Input Parameters:
|
||||
** level: The level to set the GATT tracing to:
|
||||
** 0xff-returns the current setting.
|
||||
** 0-turns off tracing.
|
||||
** >= 1-Errors.
|
||||
** >= 2-Warnings.
|
||||
** >= 3-APIs.
|
||||
** >= 4-Events.
|
||||
** >= 5-Debug.
|
||||
**
|
||||
** Returns The new or current trace level
|
||||
**
|
||||
*******************************************************************************/
|
||||
extern UINT8 SMP_SetTraceLevel (UINT8 new_level)
|
||||
{
|
||||
if (new_level != 0xFF) {
|
||||
smp_cb.trace_level = new_level;
|
||||
}
|
||||
|
||||
return (smp_cb.trace_level);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function SMP_Register
|
||||
**
|
||||
** Description This function register for the SMP services callback.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN SMP_Register (tSMP_CALLBACK *p_cback)
|
||||
{
|
||||
SMP_TRACE_EVENT ("SMP_Register state=%d", smp_cb.state);
|
||||
|
||||
if (smp_cb.p_callback != NULL) {
|
||||
SMP_TRACE_WARNING ("SMP_Register: duplicate registration, overwrite it");
|
||||
}
|
||||
smp_cb.p_callback = p_cback;
|
||||
|
||||
return (TRUE);
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function SMP_Pair
|
||||
**
|
||||
** Description This function call to perform a SMP pairing with peer device.
|
||||
** Device support one SMP pairing at one time.
|
||||
**
|
||||
** Parameters bd_addr - peer device bd address.
|
||||
**
|
||||
** Returns None
|
||||
**
|
||||
*******************************************************************************/
|
||||
tSMP_STATUS SMP_Pair (BD_ADDR bd_addr)
|
||||
{
|
||||
tSMP_CB *p_cb = &smp_cb;
|
||||
UINT8 status = SMP_PAIR_INTERNAL_ERR;
|
||||
|
||||
SMP_TRACE_EVENT ("%s state=%d br_state=%d flag=0x%x \n",
|
||||
__FUNCTION__, p_cb->state, p_cb->br_state, p_cb->flags);
|
||||
if (p_cb->state != SMP_STATE_IDLE || p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD ||
|
||||
p_cb->smp_over_br) {
|
||||
/* pending security on going, reject this one */
|
||||
return SMP_BUSY;
|
||||
} else {
|
||||
p_cb->flags = SMP_PAIR_FLAGS_WE_STARTED_DD;
|
||||
|
||||
memcpy (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN);
|
||||
|
||||
if (!L2CA_ConnectFixedChnl (L2CAP_SMP_CID, bd_addr, BLE_ADDR_UNKNOWN_TYPE, FALSE)) {
|
||||
SMP_TRACE_ERROR("%s: L2C connect fixed channel failed.\n", __FUNCTION__);
|
||||
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
|
||||
return status;
|
||||
}
|
||||
|
||||
return SMP_STARTED;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function SMP_BR_PairWith
|
||||
**
|
||||
** Description This function is called to start a SMP pairing over BR/EDR.
|
||||
** Device support one SMP pairing at one time.
|
||||
**
|
||||
** Parameters bd_addr - peer device bd address.
|
||||
**
|
||||
** Returns SMP_STARTED if pairing started, otherwise reason for failure.
|
||||
**
|
||||
*******************************************************************************/
|
||||
#if (CLASSIC_BT_INCLUDED == TRUE)
|
||||
tSMP_STATUS SMP_BR_PairWith (BD_ADDR bd_addr)
|
||||
{
|
||||
tSMP_CB *p_cb = &smp_cb;
|
||||
UINT8 status = SMP_PAIR_INTERNAL_ERR;
|
||||
|
||||
SMP_TRACE_EVENT ("%s state=%d br_state=%d flag=0x%x ",
|
||||
__func__, p_cb->state, p_cb->br_state, p_cb->flags);
|
||||
|
||||
if (p_cb->state != SMP_STATE_IDLE ||
|
||||
p_cb->smp_over_br ||
|
||||
p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD) {
|
||||
/* pending security on going, reject this one */
|
||||
return SMP_BUSY;
|
||||
}
|
||||
|
||||
p_cb->role = HCI_ROLE_MASTER;
|
||||
p_cb->flags = SMP_PAIR_FLAGS_WE_STARTED_DD;
|
||||
p_cb->smp_over_br = TRUE;
|
||||
|
||||
memcpy (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN);
|
||||
|
||||
if (!L2CA_ConnectFixedChnl (L2CAP_SMP_BR_CID, bd_addr, BLE_ADDR_UNKNOWN_TYPE, FALSE)) {
|
||||
SMP_TRACE_ERROR("%s: L2C connect fixed channel failed.", __FUNCTION__);
|
||||
smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &status);
|
||||
return status;
|
||||
}
|
||||
|
||||
return SMP_STARTED;
|
||||
}
|
||||
#endif ///CLASSIC_BT_INCLUDED == TRUE
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function SMP_PairCancel
|
||||
**
|
||||
** Description This function call to cancel a SMP pairing with peer device.
|
||||
**
|
||||
** Parameters bd_addr - peer device bd address.
|
||||
**
|
||||
** Returns TRUE - Pairining is cancelled
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN SMP_PairCancel (BD_ADDR bd_addr)
|
||||
{
|
||||
tSMP_CB *p_cb = &smp_cb;
|
||||
UINT8 err_code = SMP_PAIR_FAIL_UNKNOWN;
|
||||
BOOLEAN status = FALSE;
|
||||
|
||||
BTM_TRACE_EVENT ("SMP_CancelPair state=%d flag=0x%x ", p_cb->state, p_cb->flags);
|
||||
if ( (p_cb->state != SMP_STATE_IDLE) &&
|
||||
(!memcmp (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN)) ) {
|
||||
p_cb->is_pair_cancel = TRUE;
|
||||
SMP_TRACE_DEBUG("Cancel Pairing: set fail reason Unknown");
|
||||
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &err_code);
|
||||
status = TRUE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function SMP_SecurityGrant
|
||||
**
|
||||
** Description This function is called to grant security process.
|
||||
**
|
||||
** Parameters bd_addr - peer device bd address.
|
||||
** res - result of the operation SMP_SUCCESS if success.
|
||||
** Otherwise, SMP_REPEATED_ATTEMPTS is too many attempts.
|
||||
**
|
||||
** Returns None
|
||||
**
|
||||
*******************************************************************************/
|
||||
void SMP_SecurityGrant(BD_ADDR bd_addr, UINT8 res)
|
||||
{
|
||||
SMP_TRACE_EVENT ("SMP_SecurityGrant ");
|
||||
|
||||
#if (CLASSIC_BT_INCLUDED == TRUE)
|
||||
if (smp_cb.smp_over_br) {
|
||||
if (smp_cb.br_state != SMP_BR_STATE_WAIT_APP_RSP ||
|
||||
smp_cb.cb_evt != SMP_SEC_REQUEST_EVT ||
|
||||
memcmp (smp_cb.pairing_bda, bd_addr, BD_ADDR_LEN)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* clear the SMP_SEC_REQUEST_EVT event after get grant */
|
||||
/* avoid generating duplicate pair request */
|
||||
smp_cb.cb_evt = 0;
|
||||
smp_br_state_machine_event(&smp_cb, SMP_BR_API_SEC_GRANT_EVT, &res);
|
||||
return;
|
||||
}
|
||||
#endif ///CLASSIC_BT_INCLUDED == TRUE
|
||||
|
||||
if (smp_cb.state != SMP_STATE_WAIT_APP_RSP ||
|
||||
smp_cb.cb_evt != SMP_SEC_REQUEST_EVT ||
|
||||
memcmp (smp_cb.pairing_bda, bd_addr, BD_ADDR_LEN)) {
|
||||
return;
|
||||
}
|
||||
/* clear the SMP_SEC_REQUEST_EVT event after get grant */
|
||||
/* avoid generate duplicate pair request */
|
||||
smp_cb.cb_evt = 0;
|
||||
smp_sm_event(&smp_cb, SMP_API_SEC_GRANT_EVT, &res);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function SMP_PasskeyReply
|
||||
**
|
||||
** Description This function is called after Security Manager submitted
|
||||
** passkey request to the application.
|
||||
**
|
||||
** Parameters: bd_addr - Address of the device for which passkey was requested
|
||||
** res - result of the operation SMP_SUCCESS if success
|
||||
** passkey - numeric value in the range of
|
||||
** BTM_MIN_PASSKEY_VAL(0) - BTM_MAX_PASSKEY_VAL(999999(0xF423F)).
|
||||
**
|
||||
*******************************************************************************/
|
||||
void SMP_PasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey)
|
||||
{
|
||||
tSMP_CB *p_cb = & smp_cb;
|
||||
UINT8 failure = SMP_PASSKEY_ENTRY_FAIL;
|
||||
|
||||
SMP_TRACE_EVENT ("SMP_PasskeyReply: Key: %d Result:%d",
|
||||
passkey, res);
|
||||
|
||||
/* If timeout already expired or has been canceled, ignore the reply */
|
||||
if (p_cb->cb_evt != SMP_PASSKEY_REQ_EVT) {
|
||||
SMP_TRACE_WARNING ("SMP_PasskeyReply() - Wrong State: %d", p_cb->state);
|
||||
return;
|
||||
}
|
||||
|
||||
if (memcmp (bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) != 0) {
|
||||
SMP_TRACE_ERROR ("SMP_PasskeyReply() - Wrong BD Addr");
|
||||
return;
|
||||
}
|
||||
|
||||
if (btm_find_dev (bd_addr) == NULL) {
|
||||
SMP_TRACE_ERROR ("SMP_PasskeyReply() - no dev CB");
|
||||
return;
|
||||
}
|
||||
|
||||
if (passkey > BTM_MAX_PASSKEY_VAL || res != SMP_SUCCESS) {
|
||||
SMP_TRACE_WARNING ("SMP_PasskeyReply() - Wrong key len: %d or passkey entry fail", passkey);
|
||||
/* send pairing failure */
|
||||
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
|
||||
|
||||
} else if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_PASSKEY_ENT) {
|
||||
smp_sm_event(&smp_cb, SMP_SC_KEY_READY_EVT, &passkey);
|
||||
} else {
|
||||
smp_convert_string_to_tk(p_cb->tk, passkey);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function SMP_SetStaticPasskey
|
||||
**
|
||||
** Description This function is called to set static passkey
|
||||
**
|
||||
**
|
||||
** Parameters: add - set static passkey when add is TRUE
|
||||
** clear static passkey when add is FALSE
|
||||
** passkey - static passkey
|
||||
**
|
||||
**
|
||||
*******************************************************************************/
|
||||
void SMP_SetStaticPasskey (BOOLEAN add, UINT32 passkey)
|
||||
{
|
||||
SMP_TRACE_DEBUG("static passkey %6d", passkey);
|
||||
tSMP_CB *p_cb = & smp_cb;
|
||||
if(add) {
|
||||
p_cb->static_passkey = passkey;
|
||||
p_cb->use_static_passkey = true;
|
||||
} else {
|
||||
p_cb->static_passkey = 0;
|
||||
p_cb->use_static_passkey = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function SMP_ConfirmReply
|
||||
**
|
||||
** Description This function is called after Security Manager submitted
|
||||
** numeric comparison request to the application.
|
||||
**
|
||||
** Parameters: bd_addr - Address of the device with which numeric
|
||||
** comparison was requested
|
||||
** res - comparison result SMP_SUCCESS if success
|
||||
**
|
||||
*******************************************************************************/
|
||||
void SMP_ConfirmReply (BD_ADDR bd_addr, UINT8 res)
|
||||
{
|
||||
tSMP_CB *p_cb = & smp_cb;
|
||||
UINT8 failure = SMP_NUMERIC_COMPAR_FAIL;
|
||||
|
||||
SMP_TRACE_EVENT ("%s: Result:%d", __FUNCTION__, res);
|
||||
|
||||
/* If timeout already expired or has been canceled, ignore the reply */
|
||||
if (p_cb->cb_evt != SMP_NC_REQ_EVT) {
|
||||
SMP_TRACE_WARNING ("%s() - Wrong State: %d", __FUNCTION__, p_cb->state);
|
||||
return;
|
||||
}
|
||||
|
||||
if (memcmp (bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) != 0) {
|
||||
SMP_TRACE_ERROR ("%s() - Wrong BD Addr", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (btm_find_dev (bd_addr) == NULL) {
|
||||
SMP_TRACE_ERROR ("%s() - no dev CB", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (res != SMP_SUCCESS) {
|
||||
SMP_TRACE_WARNING ("%s() - Numeric Comparison fails", __FUNCTION__);
|
||||
/* send pairing failure */
|
||||
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
|
||||
} else {
|
||||
smp_sm_event(p_cb, SMP_SC_NC_OK_EVT, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function SMP_OobDataReply
|
||||
**
|
||||
** Description This function is called to provide the OOB data for
|
||||
** SMP in response to SMP_OOB_REQ_EVT
|
||||
**
|
||||
** Parameters: bd_addr - Address of the peer device
|
||||
** res - result of the operation SMP_SUCCESS if success
|
||||
** p_data - simple pairing Randomizer C.
|
||||
**
|
||||
*******************************************************************************/
|
||||
void SMP_OobDataReply(BD_ADDR bd_addr, tSMP_STATUS res, UINT8 len, UINT8 *p_data)
|
||||
{
|
||||
tSMP_CB *p_cb = & smp_cb;
|
||||
UINT8 failure = SMP_OOB_FAIL;
|
||||
tSMP_KEY key;
|
||||
|
||||
SMP_TRACE_EVENT ("%s State: %d res:%d", __FUNCTION__, smp_cb.state, res);
|
||||
|
||||
/* If timeout already expired or has been canceled, ignore the reply */
|
||||
if (p_cb->state != SMP_STATE_WAIT_APP_RSP || p_cb->cb_evt != SMP_OOB_REQ_EVT) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (res != SMP_SUCCESS || len == 0 || !p_data) {
|
||||
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
|
||||
} else {
|
||||
if (len > BT_OCTET16_LEN) {
|
||||
len = BT_OCTET16_LEN;
|
||||
}
|
||||
|
||||
memcpy(p_cb->tk, p_data, len);
|
||||
|
||||
key.key_type = SMP_KEY_TYPE_TK;
|
||||
key.p_data = p_cb->tk;
|
||||
|
||||
smp_sm_event(&smp_cb, SMP_KEY_READY_EVT, &key);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function SMP_SecureConnectionOobDataReply
|
||||
**
|
||||
** Description This function is called to provide the SC OOB data for
|
||||
** SMP in response to SMP_SC_OOB_REQ_EVT
|
||||
**
|
||||
** Parameters: p_data - pointer to the data
|
||||
**
|
||||
*******************************************************************************/
|
||||
void SMP_SecureConnectionOobDataReply(UINT8 *p_data)
|
||||
{
|
||||
tSMP_CB *p_cb = &smp_cb;
|
||||
|
||||
UINT8 failure = SMP_OOB_FAIL;
|
||||
tSMP_SC_OOB_DATA *p_oob = (tSMP_SC_OOB_DATA *) p_data;
|
||||
if (!p_oob) {
|
||||
SMP_TRACE_ERROR("%s received no data", __FUNCTION__);
|
||||
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set local oob data when req_oob_type = SMP_OOB_BOTH */
|
||||
memcpy(&p_oob->loc_oob_data, smp_get_local_oob_data(), sizeof(tSMP_LOC_OOB_DATA));
|
||||
|
||||
SMP_TRACE_EVENT ("%s req_oob_type: %d, loc_oob_data.present: %d, "
|
||||
"peer_oob_data.present: %d",
|
||||
__FUNCTION__, p_cb->req_oob_type, p_oob->loc_oob_data.present,
|
||||
p_oob->peer_oob_data.present);
|
||||
|
||||
if (p_cb->state != SMP_STATE_WAIT_APP_RSP || p_cb->cb_evt != SMP_SC_OOB_REQ_EVT) {
|
||||
return;
|
||||
}
|
||||
|
||||
BOOLEAN data_missing = FALSE;
|
||||
switch (p_cb->req_oob_type) {
|
||||
case SMP_OOB_PEER:
|
||||
if (!p_oob->peer_oob_data.present) {
|
||||
data_missing = TRUE;
|
||||
}
|
||||
break;
|
||||
case SMP_OOB_LOCAL:
|
||||
if (!p_oob->loc_oob_data.present) {
|
||||
data_missing = TRUE;
|
||||
}
|
||||
break;
|
||||
case SMP_OOB_BOTH:
|
||||
if (!p_oob->loc_oob_data.present || !p_oob->peer_oob_data.present) {
|
||||
data_missing = TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SMP_TRACE_EVENT ("Unexpected OOB data type requested. Fail OOB");
|
||||
data_missing = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (data_missing) {
|
||||
SMP_TRACE_ERROR("%s data missing", __func__);
|
||||
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
|
||||
return;
|
||||
}
|
||||
|
||||
p_cb->sc_oob_data = *p_oob;
|
||||
|
||||
smp_sm_event(&smp_cb, SMP_SC_OOB_DATA_EVT, p_data);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function SMP_Encrypt
|
||||
**
|
||||
** Description This function is called to encrypt the data with the specified
|
||||
** key
|
||||
**
|
||||
** Parameters: key - Pointer to key key[0] conatins the MSB
|
||||
** key_len - key length
|
||||
** plain_text - Pointer to data to be encrypted
|
||||
** plain_text[0] conatins the MSB
|
||||
** pt_len - plain text length
|
||||
** p_out - output of the encrypted texts
|
||||
**
|
||||
** Returns Boolean - request is successful
|
||||
*******************************************************************************/
|
||||
BOOLEAN SMP_Encrypt (UINT8 *key, UINT8 key_len,
|
||||
UINT8 *plain_text, UINT8 pt_len,
|
||||
tSMP_ENC *p_out)
|
||||
|
||||
{
|
||||
BOOLEAN status = FALSE;
|
||||
status = smp_encrypt_data(key, key_len, plain_text, pt_len, p_out);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function SMP_KeypressNotification
|
||||
**
|
||||
** Description This function is called to notify Security Manager about Keypress Notification.
|
||||
**
|
||||
** Parameters: bd_addr Address of the device to send keypress notification to
|
||||
** value Keypress notification parameter value
|
||||
**
|
||||
*******************************************************************************/
|
||||
void SMP_KeypressNotification (BD_ADDR bd_addr, UINT8 value)
|
||||
{
|
||||
tSMP_CB *p_cb = &smp_cb;
|
||||
|
||||
SMP_TRACE_EVENT ("%s: Value: %d", __FUNCTION__, value);
|
||||
|
||||
if (memcmp (bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) != 0) {
|
||||
SMP_TRACE_ERROR ("%s() - Wrong BD Addr", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (btm_find_dev (bd_addr) == NULL) {
|
||||
SMP_TRACE_ERROR ("%s() - no dev CB", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Keypress Notification is used by a device with KeyboardOnly IO capabilities */
|
||||
/* during the passkey entry protocol */
|
||||
if (p_cb->local_io_capability != SMP_IO_CAP_IN) {
|
||||
SMP_TRACE_ERROR ("%s() - wrong local IO capabilities %d",
|
||||
__FUNCTION__, p_cb->local_io_capability);
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_cb->selected_association_model != SMP_MODEL_SEC_CONN_PASSKEY_ENT) {
|
||||
SMP_TRACE_ERROR ("%s() - wrong protocol %d", __FUNCTION__,
|
||||
p_cb->selected_association_model);
|
||||
return;
|
||||
}
|
||||
|
||||
smp_sm_event(p_cb, SMP_KEYPRESS_NOTIFICATION_EVENT, &value);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function SMP_CreateLocalSecureConnectionsOobData
|
||||
**
|
||||
** Description This function is called to start creation of local SC OOB
|
||||
** data set (tSMP_LOC_OOB_DATA).
|
||||
**
|
||||
** Returns Boolean - TRUE: creation of local SC OOB data set started.
|
||||
*******************************************************************************/
|
||||
BOOLEAN SMP_CreateLocalSecureConnectionsOobData (void)
|
||||
{
|
||||
tSMP_CB *p_cb = &smp_cb;
|
||||
|
||||
SMP_TRACE_EVENT ("%s state: %u, br_state: %u", __FUNCTION__, p_cb->state, p_cb->br_state);
|
||||
|
||||
if ((p_cb->state != SMP_STATE_IDLE) || (p_cb->smp_over_br)) {
|
||||
SMP_TRACE_WARNING ("%s creation of local OOB data set "\
|
||||
"starts only in IDLE state", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
smp_sm_event(p_cb, SMP_CR_LOC_SC_OOB_DATA_EVT, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif /* SMP_INCLUDED */
|
||||
@@ -0,0 +1,369 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2014-2015 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "common/bt_target.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "smp_int.h"
|
||||
|
||||
#if ( CLASSIC_BT_INCLUDED== TRUE && SMP_INCLUDED == TRUE)
|
||||
|
||||
const char *const smp_br_state_name [SMP_BR_STATE_MAX + 1] = {
|
||||
"SMP_BR_STATE_IDLE",
|
||||
"SMP_BR_STATE_WAIT_APP_RSP",
|
||||
"SMP_BR_STATE_PAIR_REQ_RSP",
|
||||
"SMP_BR_STATE_BOND_PENDING",
|
||||
"SMP_BR_STATE_OUT_OF_RANGE"
|
||||
};
|
||||
|
||||
const char *const smp_br_event_name [SMP_BR_MAX_EVT] = {
|
||||
"BR_PAIRING_REQ_EVT",
|
||||
"BR_PAIRING_RSP_EVT",
|
||||
"BR_CONFIRM_EVT",
|
||||
"BR_RAND_EVT",
|
||||
"BR_PAIRING_FAILED_EVT",
|
||||
"BR_ENCRPTION_INFO_EVT",
|
||||
"BR_MASTER_ID_EVT",
|
||||
"BR_ID_INFO_EVT",
|
||||
"BR_ID_ADDR_EVT",
|
||||
"BR_SIGN_INFO_EVT",
|
||||
"BR_SECURITY_REQ_EVT",
|
||||
"BR_PAIR_PUBLIC_KEY_EVT",
|
||||
"BR_PAIR_DHKEY_CHCK_EVT",
|
||||
"BR_PAIR_KEYPR_NOTIF_EVT",
|
||||
"BR_KEY_READY_EVT",
|
||||
"BR_ENCRYPTED_EVT",
|
||||
"BR_L2CAP_CONN_EVT",
|
||||
"BR_L2CAP_DISCONN_EVT",
|
||||
"BR_KEYS_RSP_EVT",
|
||||
"BR_API_SEC_GRANT_EVT",
|
||||
"BR_TK_REQ_EVT",
|
||||
"BR_AUTH_CMPL_EVT",
|
||||
"BR_ENC_REQ_EVT",
|
||||
"BR_BOND_REQ_EVT",
|
||||
"BR_DISCARD_SEC_REQ_EVT",
|
||||
"BR_OUT_OF_RANGE_EVT"
|
||||
};
|
||||
|
||||
const char *smp_get_br_event_name(tSMP_BR_EVENT event);
|
||||
const char *smp_get_br_state_name(tSMP_BR_STATE state);
|
||||
|
||||
#define SMP_BR_SM_IGNORE 0
|
||||
#define SMP_BR_NUM_ACTIONS 2
|
||||
#define SMP_BR_SME_NEXT_STATE 2
|
||||
#define SMP_BR_SM_NUM_COLS 3
|
||||
typedef const UINT8 (*tSMP_BR_SM_TBL)[SMP_BR_SM_NUM_COLS];
|
||||
|
||||
enum {
|
||||
SMP_SEND_PAIR_REQ,
|
||||
SMP_BR_SEND_PAIR_RSP,
|
||||
SMP_SEND_PAIR_FAIL,
|
||||
SMP_SEND_ID_INFO,
|
||||
SMP_BR_PROC_PAIR_CMD,
|
||||
SMP_PROC_PAIR_FAIL,
|
||||
SMP_PROC_ID_INFO,
|
||||
SMP_PROC_ID_ADDR,
|
||||
SMP_PROC_SRK_INFO,
|
||||
SMP_BR_PROC_SEC_GRANT,
|
||||
SMP_BR_PROC_SL_KEYS_RSP,
|
||||
SMP_BR_KEY_DISTRIBUTION,
|
||||
SMP_BR_PAIRING_COMPLETE,
|
||||
SMP_SEND_APP_CBACK,
|
||||
SMP_BR_CHECK_AUTH_REQ,
|
||||
SMP_PAIR_TERMINATE,
|
||||
SMP_IDLE_TERMINATE,
|
||||
SMP_BR_SM_NO_ACTION
|
||||
};
|
||||
|
||||
static const tSMP_ACT smp_br_sm_action[] = {
|
||||
smp_send_pair_req,
|
||||
smp_br_send_pair_response,
|
||||
smp_send_pair_fail,
|
||||
smp_send_id_info,
|
||||
smp_br_process_pairing_command,
|
||||
smp_proc_pair_fail,
|
||||
smp_proc_id_info,
|
||||
smp_proc_id_addr,
|
||||
smp_proc_srk_info,
|
||||
smp_br_process_security_grant,
|
||||
smp_br_process_slave_keys_response,
|
||||
smp_br_select_next_key,
|
||||
smp_br_pairing_complete,
|
||||
smp_send_app_cback,
|
||||
smp_br_check_authorization_request,
|
||||
smp_pair_terminate,
|
||||
smp_idle_terminate
|
||||
};
|
||||
|
||||
static const UINT8 smp_br_all_table[][SMP_BR_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* BR_PAIRING_FAILED */ {SMP_PROC_PAIR_FAIL, SMP_BR_PAIRING_COMPLETE, SMP_BR_STATE_IDLE},
|
||||
/* BR_AUTH_CMPL */ {SMP_SEND_PAIR_FAIL, SMP_BR_PAIRING_COMPLETE, SMP_BR_STATE_IDLE},
|
||||
/* BR_L2CAP_DISCONN */ {SMP_PAIR_TERMINATE, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_IDLE}
|
||||
};
|
||||
|
||||
/************ SMP Master FSM State/Event Indirection Table **************/
|
||||
static const UINT8 smp_br_master_entry_map[][SMP_BR_STATE_MAX] = {
|
||||
/* br_state name: Idle WaitApp Pair Bond
|
||||
Rsp ReqRsp Pend */
|
||||
/* BR_PAIRING_REQ */ { 0, 0, 0, 0 },
|
||||
/* BR_PAIRING_RSP */ { 0, 0, 1, 0 },
|
||||
/* BR_CONFIRM */ { 0, 0, 0, 0 },
|
||||
/* BR_RAND */ { 0, 0, 0, 0 },
|
||||
/* BR_PAIRING_FAILED */ { 0, 0x81, 0x81, 0 },
|
||||
/* BR_ENCRPTION_INFO */ { 0, 0, 0, 0 },
|
||||
/* BR_MASTER_ID */ { 0, 0, 0, 0 },
|
||||
/* BR_ID_INFO */ { 0, 0, 0, 1 },
|
||||
/* BR_ID_ADDR */ { 0, 0, 0, 2 },
|
||||
/* BR_SIGN_INFO */ { 0, 0, 0, 3 },
|
||||
/* BR_SECURITY_REQ */ { 0, 0, 0, 0 },
|
||||
/* BR_PAIR_PUBLIC_KEY_EVT */ { 0, 0, 0, 0 },
|
||||
/* BR_PAIR_DHKEY_CHCK_EVT */ { 0, 0, 0, 0 },
|
||||
/* BR_PAIR_KEYPR_NOTIF_EVT */ { 0, 0, 0, 0 },
|
||||
/* BR_KEY_READY */ { 0, 0, 0, 0 },
|
||||
/* BR_ENCRYPTED */ { 0, 0, 0, 0 },
|
||||
/* BR_L2CAP_CONN */ { 1, 0, 0, 0 },
|
||||
/* BR_L2CAP_DISCONN */ { 2, 0x83, 0x83, 0x83 },
|
||||
/* BR_KEYS_RSP */ { 0, 1, 0, 0 },
|
||||
/* BR_API_SEC_GRANT */ { 0, 0, 0, 0 },
|
||||
/* BR_TK_REQ */ { 0, 0, 0, 0 },
|
||||
/* BR_AUTH_CMPL */ { 0, 0x82, 0x82, 0x82 },
|
||||
/* BR_ENC_REQ */ { 0, 0, 0, 0 },
|
||||
/* BR_BOND_REQ */ { 0, 0, 2, 0 },
|
||||
/* BR_DISCARD_SEC_REQ */ { 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static const UINT8 smp_br_master_idle_table[][SMP_BR_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* BR_L2CAP_CONN */ {SMP_SEND_APP_CBACK, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_WAIT_APP_RSP},
|
||||
/* BR_L2CAP_DISCONN */ {SMP_IDLE_TERMINATE, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_IDLE}
|
||||
};
|
||||
|
||||
static const UINT8 smp_br_master_wait_appln_response_table[][SMP_BR_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* BR_KEYS_RSP */{SMP_SEND_PAIR_REQ, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_PAIR_REQ_RSP}
|
||||
};
|
||||
|
||||
static const UINT8 smp_br_master_pair_request_response_table [][SMP_BR_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* BR_PAIRING_RSP */ {SMP_BR_PROC_PAIR_CMD, SMP_BR_CHECK_AUTH_REQ, SMP_BR_STATE_PAIR_REQ_RSP},
|
||||
/* BR_BOND_REQ */ {SMP_BR_SM_NO_ACTION, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING}
|
||||
};
|
||||
|
||||
static const UINT8 smp_br_master_bond_pending_table[][SMP_BR_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* BR_ID_INFO */{SMP_PROC_ID_INFO, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING},
|
||||
/* BR_ID_ADDR */{SMP_PROC_ID_ADDR, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING},
|
||||
/* BR_SIGN_INFO */{SMP_PROC_SRK_INFO, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING}
|
||||
};
|
||||
|
||||
static const UINT8 smp_br_slave_entry_map[][SMP_BR_STATE_MAX] = {
|
||||
/* br_state name: Idle WaitApp Pair Bond
|
||||
Rsp ReqRsp Pend */
|
||||
/* BR_PAIRING_REQ */ { 1, 0, 0, 0 },
|
||||
/* BR_PAIRING_RSP */ { 0, 0, 0, 0 },
|
||||
/* BR_CONFIRM */ { 0, 0, 0, 0 },
|
||||
/* BR_RAND */ { 0, 0, 0, 0 },
|
||||
/* BR_PAIRING_FAILED */ { 0, 0x81, 0x81, 0x81 },
|
||||
/* BR_ENCRPTION_INFO */ { 0, 0, 0, 0 },
|
||||
/* BR_MASTER_ID */ { 0, 0, 0, 0 },
|
||||
/* BR_ID_INFO */ { 0, 0, 0, 1 },
|
||||
/* BR_ID_ADDR */ { 0, 0, 0, 2 },
|
||||
/* BR_SIGN_INFO */ { 0, 0, 0, 3 },
|
||||
/* BR_SECURITY_REQ */ { 0, 0, 0, 0 },
|
||||
/* BR_PAIR_PUBLIC_KEY_EVT */ { 0, 0, 0, 0 },
|
||||
/* BR_PAIR_DHKEY_CHCK_EVT */ { 0, 0, 0, 0 },
|
||||
/* BR_PAIR_KEYPR_NOTIF_EVT */ { 0, 0, 0, 0 },
|
||||
/* BR_KEY_READY */ { 0, 0, 0, 0 },
|
||||
/* BR_ENCRYPTED */ { 0, 0, 0, 0 },
|
||||
/* BR_L2CAP_CONN */ { 0, 0, 0, 0 },
|
||||
/* BR_L2CAP_DISCONN */ { 0, 0x83, 0x83, 0x83 },
|
||||
/* BR_KEYS_RSP */ { 0, 2, 0, 0 },
|
||||
/* BR_API_SEC_GRANT */ { 0, 1, 0, 0 },
|
||||
/* BR_TK_REQ */ { 0, 0, 0, 0 },
|
||||
/* BR_AUTH_CMPL */ { 0, 0x82, 0x82, 0x82 },
|
||||
/* BR_ENC_REQ */ { 0, 0, 0, 0 },
|
||||
/* BR_BOND_REQ */ { 0, 3, 0, 0 },
|
||||
/* BR_DISCARD_SEC_REQ */ { 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static const UINT8 smp_br_slave_idle_table[][SMP_BR_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* BR_PAIRING_REQ */ {SMP_BR_PROC_PAIR_CMD, SMP_SEND_APP_CBACK, SMP_BR_STATE_WAIT_APP_RSP}
|
||||
};
|
||||
|
||||
static const UINT8 smp_br_slave_wait_appln_response_table [][SMP_BR_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* BR_API_SEC_GRANT */ {SMP_BR_PROC_SEC_GRANT, SMP_SEND_APP_CBACK, SMP_BR_STATE_WAIT_APP_RSP},
|
||||
/* BR_KEYS_RSP */{SMP_BR_PROC_SL_KEYS_RSP, SMP_BR_CHECK_AUTH_REQ, SMP_BR_STATE_WAIT_APP_RSP},
|
||||
/* BR_BOND_REQ */ {SMP_BR_KEY_DISTRIBUTION, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING}
|
||||
};
|
||||
|
||||
static const UINT8 smp_br_slave_bond_pending_table[][SMP_BR_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* BR_ID_INFO */ {SMP_PROC_ID_INFO, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING},
|
||||
/* BR_ID_ADDR */ {SMP_PROC_ID_ADDR, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING},
|
||||
/* BR_SIGN_INFO */ {SMP_PROC_SRK_INFO, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING}
|
||||
};
|
||||
|
||||
static const tSMP_BR_SM_TBL smp_br_state_table[][2] = {
|
||||
/* SMP_BR_STATE_IDLE */
|
||||
{smp_br_master_idle_table, smp_br_slave_idle_table},
|
||||
|
||||
/* SMP_BR_STATE_WAIT_APP_RSP */
|
||||
{smp_br_master_wait_appln_response_table, smp_br_slave_wait_appln_response_table},
|
||||
|
||||
/* SMP_BR_STATE_PAIR_REQ_RSP */
|
||||
{smp_br_master_pair_request_response_table, NULL},
|
||||
|
||||
/* SMP_BR_STATE_BOND_PENDING */
|
||||
{smp_br_master_bond_pending_table, smp_br_slave_bond_pending_table},
|
||||
};
|
||||
|
||||
typedef const UINT8 (*tSMP_BR_ENTRY_TBL)[SMP_BR_STATE_MAX];
|
||||
|
||||
static const tSMP_BR_ENTRY_TBL smp_br_entry_table[] = {
|
||||
smp_br_master_entry_map,
|
||||
smp_br_slave_entry_map
|
||||
};
|
||||
|
||||
#define SMP_BR_ALL_TABLE_MASK 0x80
|
||||
|
||||
/*******************************************************************************
|
||||
** Function smp_set_br_state
|
||||
** Returns None
|
||||
*******************************************************************************/
|
||||
void smp_set_br_state(tSMP_BR_STATE br_state)
|
||||
{
|
||||
if (br_state < SMP_BR_STATE_MAX) {
|
||||
SMP_TRACE_DEBUG( "BR_State change: %s(%d) ==> %s(%d)",
|
||||
smp_get_br_state_name(smp_cb.br_state), smp_cb.br_state,
|
||||
smp_get_br_state_name(br_state), br_state );
|
||||
smp_cb.br_state = br_state;
|
||||
} else {
|
||||
SMP_TRACE_DEBUG("%s invalid br_state =%d", __FUNCTION__, br_state );
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
** Function smp_get_br_state
|
||||
** Returns The smp_br state
|
||||
*******************************************************************************/
|
||||
tSMP_BR_STATE smp_get_br_state(void)
|
||||
{
|
||||
return smp_cb.br_state;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
** Function smp_get_br_state_name
|
||||
** Returns The smp_br state name.
|
||||
*******************************************************************************/
|
||||
const char *smp_get_br_state_name(tSMP_BR_STATE br_state)
|
||||
{
|
||||
const char *p_str = smp_br_state_name[SMP_BR_STATE_MAX];
|
||||
|
||||
if (br_state < SMP_BR_STATE_MAX) {
|
||||
p_str = smp_br_state_name[br_state];
|
||||
}
|
||||
|
||||
return p_str;
|
||||
}
|
||||
/*******************************************************************************
|
||||
** Function smp_get_br_event_name
|
||||
** Returns The smp_br event name.
|
||||
*******************************************************************************/
|
||||
const char *smp_get_br_event_name(tSMP_BR_EVENT event)
|
||||
{
|
||||
const char *p_str = smp_br_event_name[SMP_BR_MAX_EVT - 1];
|
||||
|
||||
if (event < SMP_BR_MAX_EVT) {
|
||||
p_str = smp_br_event_name[event - 1];
|
||||
}
|
||||
return p_str;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function smp_br_state_machine_event
|
||||
**
|
||||
** Description Handle events to the state machine. It looks up the entry
|
||||
** in the smp_br_entry_table array.
|
||||
** If it is a valid entry, it gets the state table.Set the next state,
|
||||
** if not NULL state. Execute the action function according to the
|
||||
** state table. If the state returned by action function is not NULL
|
||||
** state, adjust the new state to the returned state.
|
||||
**
|
||||
** Returns void.
|
||||
**
|
||||
*******************************************************************************/
|
||||
void smp_br_state_machine_event(tSMP_CB *p_cb, tSMP_BR_EVENT event, void *p_data)
|
||||
{
|
||||
tSMP_BR_STATE curr_state = p_cb->br_state;
|
||||
tSMP_BR_SM_TBL state_table;
|
||||
UINT8 action, entry;
|
||||
tSMP_BR_ENTRY_TBL entry_table = smp_br_entry_table[p_cb->role];
|
||||
|
||||
SMP_TRACE_EVENT("main %s", __func__);
|
||||
if (curr_state >= SMP_BR_STATE_MAX) {
|
||||
SMP_TRACE_DEBUG( "Invalid br_state: %d", curr_state) ;
|
||||
return;
|
||||
}
|
||||
|
||||
SMP_TRACE_DEBUG( "SMP Role: %s State: [%s (%d)], Event: [%s (%d)]",
|
||||
(p_cb->role == HCI_ROLE_SLAVE) ? "Slave" : "Master",
|
||||
smp_get_br_state_name( p_cb->br_state),
|
||||
p_cb->br_state, smp_get_br_event_name(event), event) ;
|
||||
|
||||
/* look up the state table for the current state */
|
||||
/* lookup entry / w event & curr_state */
|
||||
/* If entry is ignore, return.
|
||||
* Otherwise, get state table (according to curr_state or all_state) */
|
||||
if ((event <= SMP_BR_MAX_EVT) && ( (entry = entry_table[event - 1][curr_state])
|
||||
!= SMP_BR_SM_IGNORE )) {
|
||||
if (entry & SMP_BR_ALL_TABLE_MASK) {
|
||||
entry &= ~SMP_BR_ALL_TABLE_MASK;
|
||||
state_table = smp_br_all_table;
|
||||
} else {
|
||||
state_table = smp_br_state_table[curr_state][p_cb->role];
|
||||
}
|
||||
} else {
|
||||
SMP_TRACE_DEBUG( "Ignore event [%s (%d)] in state [%s (%d)]",
|
||||
smp_get_br_event_name(event), event,
|
||||
smp_get_br_state_name(curr_state), curr_state);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get possible next state from state table. */
|
||||
|
||||
smp_set_br_state(state_table[entry - 1][SMP_BR_SME_NEXT_STATE]);
|
||||
|
||||
/* If action is not ignore, clear param, exec action and get next state.
|
||||
* The action function may set the Param for cback.
|
||||
* Depending on param, call cback or free buffer. */
|
||||
/* execute action functions */
|
||||
for (UINT8 i = 0; i < SMP_BR_NUM_ACTIONS; i++) {
|
||||
if ((action = state_table[entry - 1][i]) != SMP_BR_SM_NO_ACTION) {
|
||||
(*smp_br_sm_action[action])(p_cb, (tSMP_INT_DATA *)p_data);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
SMP_TRACE_DEBUG( "result state = %s", smp_get_br_state_name( p_cb->br_state ) ) ;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,369 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2008-2012 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file contains the implementation of the AES128 CMAC algorithm.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "common/bt_target.h"
|
||||
#include "osi/allocator.h"
|
||||
|
||||
#if SMP_INCLUDED == TRUE
|
||||
// #include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "stack/btm_ble_api.h"
|
||||
#include "smp_int.h"
|
||||
#include "stack/hcimsgs.h"
|
||||
|
||||
typedef struct {
|
||||
UINT8 *text;
|
||||
UINT16 len;
|
||||
UINT16 round;
|
||||
} tCMAC_CB;
|
||||
|
||||
tCMAC_CB cmac_cb;
|
||||
|
||||
/* Rb for AES-128 as block cipher, LSB as [0] */
|
||||
const BT_OCTET16 const_Rb = {
|
||||
0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
void print128(BT_OCTET16 x, const UINT8 *key_name)
|
||||
{
|
||||
#if SMP_DEBUG == TRUE && SMP_DEBUG_VERBOSE == TRUE
|
||||
UINT8 *p = (UINT8 *)x;
|
||||
UINT8 i;
|
||||
|
||||
SMP_TRACE_WARNING("%s(MSB ~ LSB) = ", key_name);
|
||||
|
||||
for (i = 0; i < 4; i ++) {
|
||||
SMP_TRACE_WARNING("%02x %02x %02x %02x",
|
||||
p[BT_OCTET16_LEN - i * 4 - 1], p[BT_OCTET16_LEN - i * 4 - 2],
|
||||
p[BT_OCTET16_LEN - i * 4 - 3], p[BT_OCTET16_LEN - i * 4 - 4]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function padding
|
||||
**
|
||||
** Description utility function to padding the given text to be a 128 bits
|
||||
** data. The parameter dest is input and output parameter, it
|
||||
** must point to a BT_OCTET16_LEN memory space; where include
|
||||
** length bytes valid data.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void padding ( BT_OCTET16 dest, UINT8 length )
|
||||
{
|
||||
UINT8 i, *p = dest;
|
||||
/* original last block */
|
||||
for ( i = length ; i < BT_OCTET16_LEN; i++ ) {
|
||||
p[BT_OCTET16_LEN - i - 1] = ( i == length ) ? 0x80 : 0;
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function leftshift_onebit
|
||||
**
|
||||
** Description utility function to left shift one bit for a 128 bits value.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void leftshift_onebit(UINT8 *input, UINT8 *output)
|
||||
{
|
||||
UINT8 i, overflow = 0 , next_overflow = 0;
|
||||
SMP_TRACE_EVENT ("leftshift_onebit ");
|
||||
/* input[0] is LSB */
|
||||
for ( i = 0; i < BT_OCTET16_LEN ; i ++ ) {
|
||||
next_overflow = (input[i] & 0x80) ? 1 : 0;
|
||||
output[i] = (input[i] << 1) | overflow;
|
||||
overflow = next_overflow;
|
||||
}
|
||||
return;
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function cmac_aes_cleanup
|
||||
**
|
||||
** Description clean up function for AES_CMAC algorithm.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void cmac_aes_cleanup(void)
|
||||
{
|
||||
if (cmac_cb.text != NULL) {
|
||||
osi_free(cmac_cb.text);
|
||||
}
|
||||
memset(&cmac_cb, 0, sizeof(tCMAC_CB));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function cmac_aes_k_calculate
|
||||
**
|
||||
** Description This function is the calculation of block cipher using AES-128.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static BOOLEAN cmac_aes_k_calculate(BT_OCTET16 key, UINT8 *p_signature, UINT16 tlen)
|
||||
{
|
||||
tSMP_ENC output;
|
||||
UINT16 i = 1, err = 0;
|
||||
UINT8 x[16] = {0};
|
||||
UINT8 *p_mac;
|
||||
|
||||
SMP_TRACE_EVENT ("cmac_aes_k_calculate ");
|
||||
|
||||
while (i <= cmac_cb.round) {
|
||||
smp_xor_128(&cmac_cb.text[(cmac_cb.round - i)*BT_OCTET16_LEN], x); /* Mi' := Mi (+) X */
|
||||
|
||||
if (!SMP_Encrypt(key, BT_OCTET16_LEN, &cmac_cb.text[(cmac_cb.round - i)*BT_OCTET16_LEN], BT_OCTET16_LEN, &output)) {
|
||||
err = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(x, output.param_buf, BT_OCTET16_LEN);
|
||||
i ++;
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
p_mac = output.param_buf + (BT_OCTET16_LEN - tlen);
|
||||
memcpy(p_signature, p_mac, tlen);
|
||||
|
||||
SMP_TRACE_DEBUG("tlen = %d p_mac = %p", tlen, p_mac);
|
||||
SMP_TRACE_DEBUG("p_mac[0] = 0x%02x p_mac[1] = 0x%02x p_mac[2] = 0x%02x p_mac[3] = 0x%02x",
|
||||
*p_mac, *(p_mac + 1), *(p_mac + 2), *(p_mac + 3));
|
||||
SMP_TRACE_DEBUG("p_mac[4] = 0x%02x p_mac[5] = 0x%02x p_mac[6] = 0x%02x p_mac[7] = 0x%02x",
|
||||
*(p_mac + 4), *(p_mac + 5), *(p_mac + 6), *(p_mac + 7));
|
||||
|
||||
return TRUE;
|
||||
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function cmac_prepare_last_block
|
||||
**
|
||||
** Description This function proceeed to prepare the last block of message
|
||||
** Mn depending on the size of the message.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void cmac_prepare_last_block (BT_OCTET16 k1, BT_OCTET16 k2)
|
||||
{
|
||||
// UINT8 x[16] = {0};
|
||||
BOOLEAN flag;
|
||||
|
||||
SMP_TRACE_EVENT ("cmac_prepare_last_block ");
|
||||
/* last block is a complete block set flag to 1 */
|
||||
flag = ((cmac_cb.len % BT_OCTET16_LEN) == 0 && cmac_cb.len != 0) ? TRUE : FALSE;
|
||||
|
||||
SMP_TRACE_DEBUG("flag = %d round = %d", flag, cmac_cb.round);
|
||||
|
||||
if ( flag ) {
|
||||
/* last block is complete block */
|
||||
smp_xor_128(&cmac_cb.text[0], k1);
|
||||
} else { /* padding then xor with k2 */
|
||||
padding(&cmac_cb.text[0], (UINT8)(cmac_cb.len % 16));
|
||||
|
||||
smp_xor_128(&cmac_cb.text[0], k2);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function cmac_subkey_cont
|
||||
**
|
||||
** Description This is the callback function when CIPHk(0[128]) is completed.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void cmac_subkey_cont(tSMP_ENC *p)
|
||||
{
|
||||
UINT8 k1[BT_OCTET16_LEN], k2[BT_OCTET16_LEN];
|
||||
UINT8 *pp = p->param_buf;
|
||||
SMP_TRACE_EVENT ("cmac_subkey_cont ");
|
||||
print128(pp, (const UINT8 *)"K1 before shift");
|
||||
|
||||
/* If MSB(L) = 0, then K1 = L << 1 */
|
||||
if ( (pp[BT_OCTET16_LEN - 1] & 0x80) != 0 ) {
|
||||
/* Else K1 = ( L << 1 ) (+) Rb */
|
||||
leftshift_onebit(pp, k1);
|
||||
smp_xor_128(k1, const_Rb);
|
||||
} else {
|
||||
leftshift_onebit(pp, k1);
|
||||
}
|
||||
|
||||
if ( (k1[BT_OCTET16_LEN - 1] & 0x80) != 0 ) {
|
||||
/* K2 = (K1 << 1) (+) Rb */
|
||||
leftshift_onebit(k1, k2);
|
||||
smp_xor_128(k2, const_Rb);
|
||||
} else {
|
||||
/* If MSB(K1) = 0, then K2 = K1 << 1 */
|
||||
leftshift_onebit(k1, k2);
|
||||
}
|
||||
|
||||
print128(k1, (const UINT8 *)"K1");
|
||||
print128(k2, (const UINT8 *)"K2");
|
||||
|
||||
cmac_prepare_last_block (k1, k2);
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function cmac_generate_subkey
|
||||
**
|
||||
** Description This is the function to generate the two subkeys.
|
||||
**
|
||||
** Parameters key - CMAC key, expect SRK when used by SMP.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static BOOLEAN cmac_generate_subkey(BT_OCTET16 key)
|
||||
{
|
||||
BT_OCTET16 z = {0};
|
||||
BOOLEAN ret = TRUE;
|
||||
tSMP_ENC output;
|
||||
SMP_TRACE_EVENT (" cmac_generate_subkey");
|
||||
|
||||
if (SMP_Encrypt(key, BT_OCTET16_LEN, z, BT_OCTET16_LEN, &output)) {
|
||||
cmac_subkey_cont(&output);;
|
||||
} else {
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function aes_cipher_msg_auth_code
|
||||
**
|
||||
** Description This is the AES-CMAC Generation Function with tlen implemented.
|
||||
**
|
||||
** Parameters key - CMAC key in little endian order, expect SRK when used by SMP.
|
||||
** input - text to be signed in little endian byte order.
|
||||
** length - length of the input in byte.
|
||||
** tlen - lenth of mac desired
|
||||
** p_signature - data pointer to where signed data to be stored, tlen long.
|
||||
**
|
||||
** Returns FALSE if out of resources, TRUE in other cases.
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN aes_cipher_msg_auth_code(BT_OCTET16 key, UINT8 *input, UINT16 length,
|
||||
UINT16 tlen, UINT8 *p_signature)
|
||||
{
|
||||
UINT16 len, diff;
|
||||
UINT16 n = (length + BT_OCTET16_LEN - 1) / BT_OCTET16_LEN; /* n is number of rounds */
|
||||
BOOLEAN ret = FALSE;
|
||||
|
||||
SMP_TRACE_EVENT ("%s", __func__);
|
||||
|
||||
if (n == 0) {
|
||||
n = 1;
|
||||
}
|
||||
len = n * BT_OCTET16_LEN;
|
||||
|
||||
SMP_TRACE_DEBUG("AES128_CMAC started, allocate buffer size = %d", len);
|
||||
/* allocate a memory space of multiple of 16 bytes to hold text */
|
||||
if ((cmac_cb.text = (UINT8 *)osi_malloc(len)) != NULL) {
|
||||
cmac_cb.round = n;
|
||||
|
||||
memset(cmac_cb.text, 0, len);
|
||||
diff = len - length;
|
||||
|
||||
if (input != NULL && length > 0) {
|
||||
memcpy(&cmac_cb.text[diff] , input, (int)length);
|
||||
cmac_cb.len = length;
|
||||
} else {
|
||||
cmac_cb.len = 0;
|
||||
}
|
||||
|
||||
/* prepare calculation for subkey s and last block of data */
|
||||
if (cmac_generate_subkey(key)) {
|
||||
/* start calculation */
|
||||
ret = cmac_aes_k_calculate(key, p_signature, tlen);
|
||||
}
|
||||
/* clean up */
|
||||
cmac_aes_cleanup();
|
||||
} else {
|
||||
ret = FALSE;
|
||||
SMP_TRACE_ERROR("No resources");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0 /* testing code, sample data from spec */
|
||||
void test_cmac_cback(UINT8 *p_mac, UINT16 tlen)
|
||||
{
|
||||
SMP_TRACE_EVENT ("test_cmac_cback ");
|
||||
SMP_TRACE_ERROR("test_cmac_cback");
|
||||
}
|
||||
|
||||
void test_cmac(void)
|
||||
{
|
||||
SMP_TRACE_EVENT ("test_cmac ");
|
||||
UINT8 M[64] = {
|
||||
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
|
||||
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
|
||||
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
|
||||
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
|
||||
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
|
||||
0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
|
||||
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
|
||||
0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
|
||||
};
|
||||
|
||||
UINT8 key[16] = {
|
||||
0x3c, 0x4f, 0xcf, 0x09, 0x88, 0x15, 0xf7, 0xab,
|
||||
0xa6, 0xd2, 0xae, 0x28, 0x16, 0x15, 0x7e, 0x2b
|
||||
};
|
||||
UINT8 i = 0, tmp;
|
||||
UINT16 len;
|
||||
|
||||
len = 64;
|
||||
|
||||
for (i = 0; i < len / 2; i ++) {
|
||||
tmp = M[i];
|
||||
M[i] = M[len - 1 - i];
|
||||
M[len - 1 - i] = tmp;
|
||||
}
|
||||
|
||||
|
||||
memset(&cmac_cb, 0, sizeof(tCMAC_CB));
|
||||
|
||||
SMP_TRACE_WARNING("\n Example 1: len = %d\n", len);
|
||||
|
||||
aes_cipher_msg_auth_code(key, M, len, 128, test_cmac_cback, 0);
|
||||
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,344 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2012 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file contains functions for the SMP L2Cap interface
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "common/bt_target.h"
|
||||
#include "osi/allocator.h"
|
||||
|
||||
#if SMP_INCLUDED == TRUE
|
||||
|
||||
#include <string.h>
|
||||
#include "stack/btm_ble_api.h"
|
||||
#include "stack/l2c_api.h"
|
||||
|
||||
#include "smp_int.h"
|
||||
|
||||
|
||||
static void smp_tx_complete_callback(UINT16 cid, UINT16 num_pkt);
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
|
||||
static void smp_connect_callback(UINT16 channel, BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason,
|
||||
tBT_TRANSPORT transport);
|
||||
static void smp_data_received(UINT16 channel, BD_ADDR bd_addr, BT_HDR *p_buf);
|
||||
#endif ///BLE_INCLUDED == TRUE
|
||||
#if (CLASSIC_BT_INCLUDED == TRUE)
|
||||
static void smp_br_connect_callback(UINT16 channel, BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason,
|
||||
tBT_TRANSPORT transport);
|
||||
static void smp_br_data_received(UINT16 channel, BD_ADDR bd_addr, BT_HDR *p_buf);
|
||||
#endif ///CLASSIC_BT_INCLUDED == TRUE
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function smp_l2cap_if_init
|
||||
**
|
||||
** Description This function is called during the SMP task startup
|
||||
** to register interface functions with L2CAP.
|
||||
**
|
||||
*******************************************************************************/
|
||||
void smp_l2cap_if_init (void)
|
||||
{
|
||||
tL2CAP_FIXED_CHNL_REG fixed_reg;
|
||||
SMP_TRACE_EVENT ("SMDBG l2c %s", __func__);
|
||||
fixed_reg.fixed_chnl_opts.mode = L2CAP_FCR_BASIC_MODE;
|
||||
fixed_reg.fixed_chnl_opts.max_transmit = 0;
|
||||
fixed_reg.fixed_chnl_opts.rtrans_tout = 0;
|
||||
fixed_reg.fixed_chnl_opts.mon_tout = 0;
|
||||
fixed_reg.fixed_chnl_opts.mps = 0;
|
||||
fixed_reg.fixed_chnl_opts.tx_win_sz = 0;
|
||||
|
||||
fixed_reg.pL2CA_FixedTxComplete_Cb = smp_tx_complete_callback;
|
||||
|
||||
fixed_reg.pL2CA_FixedCong_Cb = NULL; /* do not handle congestion on this channel */
|
||||
fixed_reg.default_idle_tout = 0; /* set 0 seconds timeout, 0xffff default idle timeout.
|
||||
This timeout is used to wait for the end of the pairing
|
||||
and then make a disconnect request, setting a larger value
|
||||
will cause the disconnect event to go back up for a long time.
|
||||
Set to 0 will be disconnected directly, and it will come up
|
||||
pairing failure, so it will not cause adverse effects. */
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
fixed_reg.pL2CA_FixedConn_Cb = smp_connect_callback;
|
||||
fixed_reg.pL2CA_FixedData_Cb = smp_data_received;
|
||||
L2CA_RegisterFixedChannel (L2CAP_SMP_CID, &fixed_reg);
|
||||
#endif ///BLE_INCLUDED == TRUE
|
||||
|
||||
#if (CLASSIC_BT_INCLUDED == TRUE)
|
||||
fixed_reg.pL2CA_FixedConn_Cb = smp_br_connect_callback;
|
||||
fixed_reg.pL2CA_FixedData_Cb = smp_br_data_received;
|
||||
|
||||
L2CA_RegisterFixedChannel (L2CAP_SMP_BR_CID, &fixed_reg);
|
||||
#endif ///CLASSIC_BT_INCLUDED == TRUE
|
||||
}
|
||||
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function smp_connect_callback
|
||||
**
|
||||
** Description This callback function is called by L2CAP to indicate that
|
||||
** SMP channel is
|
||||
** connected (conn = TRUE)/disconnected (conn = FALSE).
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void smp_connect_callback (UINT16 channel, BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason,
|
||||
tBT_TRANSPORT transport)
|
||||
{
|
||||
tSMP_CB *p_cb = &smp_cb;
|
||||
tSMP_INT_DATA int_data;
|
||||
BD_ADDR dummy_bda = {0};
|
||||
|
||||
SMP_TRACE_EVENT ("SMDBG l2c %s\n", __FUNCTION__);
|
||||
|
||||
if (transport == BT_TRANSPORT_BR_EDR || memcmp(bd_addr, dummy_bda, BD_ADDR_LEN) == 0) {
|
||||
return;
|
||||
}
|
||||
if(!connected) {
|
||||
//free timer
|
||||
btu_free_timer(&p_cb->rsp_timer_ent);
|
||||
}
|
||||
if (memcmp(bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) == 0) {
|
||||
SMP_TRACE_EVENT ("%s() for pairing BDA: %08x%04x Event: %s\n",
|
||||
__FUNCTION__,
|
||||
(bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) + bd_addr[3],
|
||||
(bd_addr[4] << 8) + bd_addr[5],
|
||||
(connected) ? "connected" : "disconnected");
|
||||
|
||||
if (connected) {
|
||||
if (!p_cb->connect_initialized) {
|
||||
p_cb->connect_initialized = TRUE;
|
||||
/* initiating connection established */
|
||||
p_cb->role = L2CA_GetBleConnRole(bd_addr);
|
||||
|
||||
/* initialize local i/r key to be default keys */
|
||||
p_cb->local_r_key = p_cb->local_i_key = SMP_SEC_DEFAULT_KEY;
|
||||
p_cb->loc_auth_req = p_cb->peer_auth_req = SMP_DEFAULT_AUTH_REQ;
|
||||
p_cb->cb_evt = SMP_IO_CAP_REQ_EVT;
|
||||
smp_sm_event(p_cb, SMP_L2CAP_CONN_EVT, NULL);
|
||||
}
|
||||
} else {
|
||||
int_data.reason = reason;
|
||||
/* Disconnected while doing security */
|
||||
smp_sm_event(p_cb, SMP_L2CAP_DISCONN_EVT, &int_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function smp_data_received
|
||||
**
|
||||
** Description This function is called when data is received from L2CAP on
|
||||
** SMP channel.
|
||||
**
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void smp_data_received(UINT16 channel, BD_ADDR bd_addr, BT_HDR *p_buf)
|
||||
{
|
||||
tSMP_CB *p_cb = &smp_cb;
|
||||
UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
|
||||
UINT8 cmd ;
|
||||
SMP_TRACE_EVENT ("\nSMDBG l2c %s\n", __FUNCTION__);
|
||||
|
||||
STREAM_TO_UINT8(cmd, p);
|
||||
|
||||
/* sanity check */
|
||||
if ((SMP_OPCODE_MAX < cmd) || (SMP_OPCODE_MIN > cmd)) {
|
||||
SMP_TRACE_WARNING( "Ignore received command with RESERVED code 0x%02x\n", cmd);
|
||||
osi_free (p_buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/* reject the pairing request if there is an on-going SMP pairing */
|
||||
if (SMP_OPCODE_PAIRING_REQ == cmd || SMP_OPCODE_SEC_REQ == cmd) {
|
||||
if ((p_cb->state == SMP_STATE_IDLE) && (p_cb->br_state == SMP_BR_STATE_IDLE) &&
|
||||
!(p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)) {
|
||||
p_cb->role = L2CA_GetBleConnRole(bd_addr);
|
||||
memcpy(&p_cb->pairing_bda[0], bd_addr, BD_ADDR_LEN);
|
||||
} else if (memcmp(&bd_addr[0], p_cb->pairing_bda, BD_ADDR_LEN)) {
|
||||
osi_free (p_buf);
|
||||
smp_reject_unexpected_pairing_command(bd_addr);
|
||||
return;
|
||||
}
|
||||
/* else, out of state pairing request/security request received, passed into SM */
|
||||
}
|
||||
|
||||
if (memcmp(&bd_addr[0], p_cb->pairing_bda, BD_ADDR_LEN) == 0) {
|
||||
btu_stop_timer (&p_cb->rsp_timer_ent);
|
||||
btu_start_timer (&p_cb->rsp_timer_ent, BTU_TTYPE_SMP_PAIRING_CMD,
|
||||
SMP_WAIT_FOR_RSP_TOUT);
|
||||
|
||||
if (cmd == SMP_OPCODE_CONFIRM) {
|
||||
SMP_TRACE_DEBUG ("in %s cmd = 0x%02x, peer_auth_req = 0x%02x,"
|
||||
"loc_auth_req = 0x%02x\n",
|
||||
__FUNCTION__, cmd, p_cb->peer_auth_req, p_cb->loc_auth_req);
|
||||
|
||||
if ((p_cb->peer_auth_req & SMP_SC_SUPPORT_BIT) &&
|
||||
(p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT)) {
|
||||
cmd = SMP_OPCODE_PAIR_COMMITM;
|
||||
}
|
||||
}
|
||||
|
||||
p_cb->rcvd_cmd_code = cmd;
|
||||
p_cb->rcvd_cmd_len = (UINT8) p_buf->len;
|
||||
smp_sm_event(p_cb, cmd, p);
|
||||
}
|
||||
|
||||
osi_free (p_buf);
|
||||
}
|
||||
#endif ///BLE_INCLUDED == TRUE
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function smp_tx_complete_callback
|
||||
**
|
||||
** Description SMP channel tx complete callback
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void smp_tx_complete_callback (UINT16 cid, UINT16 num_pkt)
|
||||
{
|
||||
tSMP_CB *p_cb = &smp_cb;
|
||||
|
||||
if (p_cb->total_tx_unacked >= num_pkt) {
|
||||
p_cb->total_tx_unacked -= num_pkt;
|
||||
} else {
|
||||
SMP_TRACE_ERROR("Unexpected %s: num_pkt = %d", __func__, num_pkt);
|
||||
}
|
||||
|
||||
UINT8 reason = SMP_SUCCESS;
|
||||
if (p_cb->total_tx_unacked == 0 && p_cb->wait_for_authorization_complete) {
|
||||
if (cid == L2CAP_SMP_CID) {
|
||||
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
|
||||
} else {
|
||||
#if (CLASSIC_BT_INCLUDED == TRUE)
|
||||
smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &reason);
|
||||
#endif ///CLASSIC_BT_INCLUDED == TRUE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function smp_br_connect_callback
|
||||
**
|
||||
** Description This callback function is called by L2CAP to indicate that
|
||||
** SMP BR channel is
|
||||
** connected (conn = TRUE)/disconnected (conn = FALSE).
|
||||
**
|
||||
*******************************************************************************/
|
||||
#if (CLASSIC_BT_INCLUDED == TRUE)
|
||||
static void smp_br_connect_callback(UINT16 channel, BD_ADDR bd_addr, BOOLEAN connected,
|
||||
UINT16 reason, tBT_TRANSPORT transport)
|
||||
{
|
||||
tSMP_CB *p_cb = &smp_cb;
|
||||
tSMP_INT_DATA int_data;
|
||||
|
||||
SMP_TRACE_EVENT ("%s", __func__);
|
||||
|
||||
if (transport != BT_TRANSPORT_BR_EDR) {
|
||||
SMP_TRACE_EVENT ("%s is called on unexpected transport %d\n",
|
||||
__func__, transport);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(memcmp(bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SMP_TRACE_EVENT ("%s for pairing BDA: %08x%04x Event: %s\n",
|
||||
__func__,
|
||||
(bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) + bd_addr[3],
|
||||
(bd_addr[4] << 8) + bd_addr[5],
|
||||
(connected) ? "connected" : "disconnected");
|
||||
|
||||
if (connected) {
|
||||
if (!p_cb->connect_initialized) {
|
||||
p_cb->connect_initialized = TRUE;
|
||||
/* initialize local i/r key to be default keys */
|
||||
p_cb->local_r_key = p_cb->local_i_key = SMP_BR_SEC_DEFAULT_KEY;
|
||||
p_cb->loc_auth_req = p_cb->peer_auth_req = 0;
|
||||
p_cb->cb_evt = SMP_BR_KEYS_REQ_EVT;
|
||||
smp_br_state_machine_event(p_cb, SMP_BR_L2CAP_CONN_EVT, NULL);
|
||||
}
|
||||
} else {
|
||||
int_data.reason = reason;
|
||||
/* Disconnected while doing security */
|
||||
smp_br_state_machine_event(p_cb, SMP_BR_L2CAP_DISCONN_EVT, &int_data);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function smp_br_data_received
|
||||
**
|
||||
** Description This function is called when data is received from L2CAP on
|
||||
** SMP BR channel.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void smp_br_data_received(UINT16 channel, BD_ADDR bd_addr, BT_HDR *p_buf)
|
||||
{
|
||||
tSMP_CB *p_cb = &smp_cb;
|
||||
UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
|
||||
UINT8 cmd ;
|
||||
SMP_TRACE_EVENT ("SMDBG l2c %s\n", __func__);
|
||||
|
||||
STREAM_TO_UINT8(cmd, p);
|
||||
|
||||
/* sanity check */
|
||||
if ((SMP_OPCODE_MAX < cmd) || (SMP_OPCODE_MIN > cmd)) {
|
||||
SMP_TRACE_WARNING( "Ignore received command with RESERVED code 0x%02x", cmd);
|
||||
osi_free(p_buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/* reject the pairing request if there is an on-going SMP pairing */
|
||||
if (SMP_OPCODE_PAIRING_REQ == cmd) {
|
||||
if ((p_cb->state == SMP_STATE_IDLE) && (p_cb->br_state == SMP_BR_STATE_IDLE)) {
|
||||
p_cb->role = HCI_ROLE_SLAVE;
|
||||
p_cb->smp_over_br = TRUE;
|
||||
memcpy(&p_cb->pairing_bda[0], bd_addr, BD_ADDR_LEN);
|
||||
} else if (memcmp(&bd_addr[0], p_cb->pairing_bda, BD_ADDR_LEN)) {
|
||||
osi_free (p_buf);
|
||||
smp_reject_unexpected_pairing_command(bd_addr);
|
||||
return;
|
||||
}
|
||||
/* else, out of state pairing request received, passed into State Machine */
|
||||
}
|
||||
|
||||
if (memcmp(&bd_addr[0], p_cb->pairing_bda, BD_ADDR_LEN) == 0) {
|
||||
btu_stop_timer (&p_cb->rsp_timer_ent);
|
||||
btu_start_timer (&p_cb->rsp_timer_ent, BTU_TTYPE_SMP_PAIRING_CMD,
|
||||
SMP_WAIT_FOR_RSP_TOUT);
|
||||
|
||||
p_cb->rcvd_cmd_code = cmd;
|
||||
p_cb->rcvd_cmd_len = (UINT8) p_buf->len;
|
||||
smp_br_state_machine_event(p_cb, cmd, p);
|
||||
}
|
||||
|
||||
osi_free (p_buf);
|
||||
}
|
||||
#endif /* CLASSIC_BT_INCLUDED == TRUE */
|
||||
|
||||
#endif /* SMP_INCLUDED == TRUE */
|
||||
@@ -0,0 +1,810 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2003-2012 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "common/bt_target.h"
|
||||
|
||||
#if SMP_INCLUDED == TRUE
|
||||
|
||||
#include <string.h>
|
||||
#include "smp_int.h"
|
||||
|
||||
const char *const smp_state_name [] = {
|
||||
"SMP_STATE_IDLE",
|
||||
"SMP_STATE_WAIT_APP_RSP",
|
||||
"SMP_STATE_SEC_REQ_PENDING",
|
||||
"SMP_STATE_PAIR_REQ_RSP",
|
||||
"SMP_STATE_WAIT_CONFIRM",
|
||||
"SMP_STATE_CONFIRM",
|
||||
"SMP_STATE_RAND",
|
||||
"SMP_STATE_PUBLIC_KEY_EXCH",
|
||||
"SMP_STATE_SEC_CONN_PHS1_START",
|
||||
"SMP_STATE_WAIT_COMMITMENT",
|
||||
"SMP_STATE_WAIT_NONCE",
|
||||
"SMP_STATE_SEC_CONN_PHS2_START",
|
||||
"SMP_STATE_WAIT_DHK_CHECK",
|
||||
"SMP_STATE_DHK_CHECK",
|
||||
"SMP_STATE_ENCRYPTION_PENDING",
|
||||
"SMP_STATE_BOND_PENDING",
|
||||
"SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA",
|
||||
"SMP_STATE_MAX"
|
||||
};
|
||||
|
||||
const char *const smp_event_name [] = {
|
||||
"PAIRING_REQ_EVT",
|
||||
"PAIRING_RSP_EVT",
|
||||
"CONFIRM_EVT",
|
||||
"RAND_EVT",
|
||||
"PAIRING_FAILED_EVT",
|
||||
"ENC_INFO_EVT",
|
||||
"MASTER_ID_EVT",
|
||||
"ID_INFO_EVT",
|
||||
"ID_ADDR_EVT",
|
||||
"SIGN_INFO_EVT",
|
||||
"SECURITY_REQ_EVT",
|
||||
"PAIR_PUBLIC_KEY_EVT",
|
||||
"PAIR_DHKEY_CHECK_EVT",
|
||||
"PAIR_KEYPRESS_NOTIFICATION_EVT",
|
||||
"PAIR_COMMITMENT_EVT",
|
||||
"KEY_READY_EVT",
|
||||
"ENCRYPTED_EVT",
|
||||
"L2CAP_CONN_EVT",
|
||||
"L2CAP_DISCONN_EVT",
|
||||
"API_IO_RSP_EVT",
|
||||
"API_SEC_GRANT_EVT",
|
||||
"TK_REQ_EVT",
|
||||
"AUTH_CMPL_EVT",
|
||||
"ENC_REQ_EVT",
|
||||
"BOND_REQ_EVT",
|
||||
"DISCARD_SEC_REQ_EVT",
|
||||
"PUBLIC_KEY_EXCHANGE_REQ_EVT",
|
||||
"LOCAL_PUBLIC_KEY_CRTD_EVT",
|
||||
"BOTH_PUBLIC_KEYS_RCVD_EVT",
|
||||
"SEC_CONN_DHKEY_COMPLETE_EVT",
|
||||
"HAVE_LOCAL_NONCE_EVT",
|
||||
"SEC_CONN_PHASE1_CMPLT_EVT",
|
||||
"SEC_CONN_CALC_NC_EVT",
|
||||
"SEC_CONN_DISPLAY_NC_EVT",
|
||||
"SEC_CONN_OK_EVT",
|
||||
"SEC_CONN_2_DHCK_CHECKS_PRESENT_EVT",
|
||||
"SEC_CONN_KEY_READY_EVT",
|
||||
"KEYPRESS_NOTIFICATION_EVT",
|
||||
"SEC_CONN_OOB_DATA_EVT",
|
||||
"CREATE_LOCAL_SEC_CONN_OOB_DATA_EVT",
|
||||
"OUT_OF_RANGE_EVT"
|
||||
};
|
||||
|
||||
const char *smp_get_event_name(tSMP_EVENT event);
|
||||
const char *smp_get_state_name(tSMP_STATE state);
|
||||
|
||||
#define SMP_SM_IGNORE 0
|
||||
#define SMP_NUM_ACTIONS 2
|
||||
#define SMP_SME_NEXT_STATE 2
|
||||
#define SMP_SM_NUM_COLS 3
|
||||
|
||||
typedef const UINT8(*tSMP_SM_TBL)[SMP_SM_NUM_COLS];
|
||||
|
||||
enum {
|
||||
SMP_PROC_SEC_REQ,
|
||||
SMP_SEND_PAIR_REQ,
|
||||
SMP_SEND_PAIR_RSP,
|
||||
SMP_SEND_CONFIRM,
|
||||
SMP_SEND_PAIR_FAIL,
|
||||
SMP_SEND_RAND,
|
||||
SMP_SEND_ENC_INFO,
|
||||
SMP_SEND_ID_INFO,
|
||||
SMP_SEND_LTK_REPLY,
|
||||
SMP_PROC_PAIR_CMD,
|
||||
SMP_PROC_PAIR_FAIL,
|
||||
SMP_PROC_CONFIRM,
|
||||
SMP_PROC_RAND,
|
||||
SMP_PROC_ENC_INFO,
|
||||
SMP_PROC_MASTER_ID,
|
||||
SMP_PROC_ID_INFO,
|
||||
SMP_PROC_ID_ADDR,
|
||||
SMP_PROC_SRK_INFO,
|
||||
SMP_PROC_SEC_GRANT,
|
||||
SMP_PROC_SL_KEY,
|
||||
SMP_PROC_COMPARE,
|
||||
SMP_PROC_IO_RSP,
|
||||
SMP_GENERATE_COMPARE,
|
||||
SMP_GENERATE_CONFIRM,
|
||||
SMP_GENERATE_STK,
|
||||
SMP_KEY_DISTRIBUTE,
|
||||
SMP_START_ENC,
|
||||
SMP_PAIRING_CMPL,
|
||||
SMP_DECIDE_ASSO_MODEL,
|
||||
SMP_SEND_APP_CBACK,
|
||||
SMP_CHECK_AUTH_REQ,
|
||||
SMP_PAIR_TERMINATE,
|
||||
SMP_ENC_CMPL,
|
||||
SMP_PROC_DISCARD,
|
||||
SMP_CREATE_PRIVATE_KEY,
|
||||
SMP_USE_OOB_PRIVATE_KEY,
|
||||
SMP_SEND_PAIR_PUBLIC_KEY,
|
||||
SMP_PROCESS_PAIR_PUBLIC_KEY,
|
||||
SMP_HAVE_BOTH_PUBLIC_KEYS,
|
||||
SMP_START_SEC_CONN_PHASE1,
|
||||
SMP_PROCESS_LOCAL_NONCE,
|
||||
SMP_SEND_COMMITMENT,
|
||||
SMP_PROCESS_PAIRING_COMMITMENT,
|
||||
SMP_PROCESS_PEER_NONCE,
|
||||
SMP_CALCULATE_LOCAL_DHKEY_CHECK,
|
||||
SMP_SEND_DHKEY_CHECK,
|
||||
SMP_PROCESS_DHKEY_CHECK,
|
||||
SMP_CALCULATE_PEER_DHKEY_CHECK,
|
||||
SMP_MATCH_DHKEY_CHECKS,
|
||||
SMP_CALCULATE_NUMERIC_COMPARISON_DISPLAY_NUMBER,
|
||||
SMP_MOVE_TO_SEC_CONN_PHASE2,
|
||||
SMP_PH2_DHKEY_CHECKS_ARE_PRESENT,
|
||||
SMP_WAIT_FOR_BOTH_PUBLIC_KEYS,
|
||||
SMP_START_PASSKEY_VERIFICATION,
|
||||
SMP_SEND_KEYPRESS_NOTIFICATION,
|
||||
SMP_PROCESS_KEYPRESS_NOTIFICATION,
|
||||
SMP_PROCESS_SECURE_CONNECTION_OOB_DATA,
|
||||
SMP_SET_LOCAL_OOB_KEYS,
|
||||
SMP_SET_LOCAL_OOB_RAND_COMMITMENT,
|
||||
SMP_IDLE_TERMINATE,
|
||||
SMP_FAST_CONN_PARAM,
|
||||
SMP_SM_NO_ACTION
|
||||
};
|
||||
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
static const tSMP_ACT smp_sm_action[SMP_SM_NO_ACTION] = {
|
||||
smp_proc_sec_req,
|
||||
smp_send_pair_req,
|
||||
smp_send_pair_rsp,
|
||||
smp_send_confirm,
|
||||
smp_send_pair_fail,
|
||||
smp_send_rand,
|
||||
smp_send_enc_info,
|
||||
smp_send_id_info,
|
||||
smp_send_ltk_reply,
|
||||
smp_proc_pair_cmd,
|
||||
smp_proc_pair_fail,
|
||||
smp_proc_confirm,
|
||||
smp_proc_rand,
|
||||
smp_proc_enc_info,
|
||||
smp_proc_master_id,
|
||||
smp_proc_id_info,
|
||||
smp_proc_id_addr,
|
||||
smp_proc_srk_info,
|
||||
smp_proc_sec_grant,
|
||||
smp_proc_sl_key,
|
||||
smp_proc_compare,
|
||||
smp_process_io_response,
|
||||
smp_generate_compare,
|
||||
smp_generate_srand_mrand_confirm,
|
||||
smp_generate_stk,
|
||||
smp_key_distribution,
|
||||
smp_start_enc,
|
||||
smp_pairing_cmpl,
|
||||
smp_decide_association_model,
|
||||
smp_send_app_cback,
|
||||
smp_check_auth_req,
|
||||
smp_pair_terminate,
|
||||
smp_enc_cmpl,
|
||||
smp_proc_discard,
|
||||
smp_create_private_key,
|
||||
smp_use_oob_private_key,
|
||||
smp_send_pair_public_key,
|
||||
smp_process_pairing_public_key,
|
||||
smp_both_have_public_keys,
|
||||
smp_start_secure_connection_phase1,
|
||||
smp_process_local_nonce,
|
||||
smp_send_commitment,
|
||||
smp_process_pairing_commitment,
|
||||
smp_process_peer_nonce,
|
||||
smp_calculate_local_dhkey_check,
|
||||
smp_send_dhkey_check,
|
||||
smp_process_dhkey_check,
|
||||
smp_calculate_peer_dhkey_check,
|
||||
smp_match_dhkey_checks,
|
||||
smp_calculate_numeric_comparison_display_number,
|
||||
smp_move_to_secure_connections_phase2,
|
||||
smp_phase_2_dhkey_checks_are_present,
|
||||
smp_wait_for_both_public_keys,
|
||||
smp_start_passkey_verification,
|
||||
smp_send_keypress_notification,
|
||||
smp_process_keypress_notification,
|
||||
smp_process_secure_connection_oob_data,
|
||||
smp_set_local_oob_keys,
|
||||
smp_set_local_oob_random_commitment,
|
||||
smp_idle_terminate,
|
||||
smp_fast_conn_param
|
||||
};
|
||||
#else
|
||||
static const tSMP_ACT smp_sm_action[SMP_SM_NO_ACTION] = {NULL};
|
||||
#endif ///BLE_INCLUDED == TRUE
|
||||
|
||||
/************ SMP Master FSM State/Event Indirection Table **************/
|
||||
static const UINT8 smp_master_entry_map[][SMP_STATE_MAX] = {
|
||||
/* state name: Idle WaitApp SecReq Pair Wait Confirm Rand PublKey SCPhs1 Wait Wait SCPhs2 Wait DHKChk Enc Bond CrLocSc
|
||||
Rsp Pend ReqRsp Cfm Exch Strt Cmtm Nonce Strt DHKChk Pend Pend OobData */
|
||||
/* PAIR_REQ */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* PAIR_RSP */{ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* CONFIRM */{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* RAND */{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
|
||||
/* PAIR_FAIL */{ 0, 0x81, 0, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0, 0x81, 0 },
|
||||
/* ENC_INFO */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 },
|
||||
/* MASTER_ID */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0 },
|
||||
/* ID_INFO */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0 },
|
||||
/* ID_ADDR */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0 },
|
||||
/* SIGN_INFO */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0 },
|
||||
/* SEC_REQ */{ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* PAIR_PUBLIC_KEY */{ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* PAIR_DHKEY_CHCK */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 },
|
||||
/* PAIR_KEYPR_NOTIF */{ 0, 8, 0, 0, 0, 0, 0, 0, 5, 2, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* PAIR_COMMITM */{ 0, 0, 0, 0, 0, 0, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* KEY_READY */{ 0, 3, 0, 3, 1, 0, 2, 0, 4, 0, 0, 0, 0, 0, 1, 6, 0 },
|
||||
/* ENC_CMPL */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 },
|
||||
/* L2C_CONN */{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* L2C_DISC */{ 3, 0x83, 0, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0 },
|
||||
/* IO_RSP */{ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* SEC_GRANT */{ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* TK_REQ */{ 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* AUTH_CMPL */{ 4, 0x82, 0, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0 },
|
||||
/* ENC_REQ */{ 0, 4, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 },
|
||||
/* BOND_REQ */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 },
|
||||
/* DISCARD_SEC_REQ */{ 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 },
|
||||
/* PUBL_KEY_EXCH_REQ */{ 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* LOC_PUBL_KEY_CRTD */{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
||||
/* BOTH_PUBL_KEYS_RCVD */{ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* SC_DHKEY_CMPLT */{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* HAVE_LOC_NONCE */{ 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2 },
|
||||
/* SC_PHASE1_CMPLT */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
|
||||
/* SC_CALC_NC */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 },
|
||||
/* SC_DSPL_NC */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0 },
|
||||
/* SC_NC_OK */{ 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* SC_2_DHCK_CHKS_PRES */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* SC_KEY_READY */{ 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
|
||||
/* KEYPR_NOTIF */{ 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* SC_OOB_DATA */{ 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* CR_LOC_SC_OOB_DATA */{ 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static const UINT8 smp_all_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* PAIR_FAIL */ {SMP_PROC_PAIR_FAIL, SMP_PAIRING_CMPL, SMP_STATE_IDLE},
|
||||
/* AUTH_CMPL */ {SMP_SEND_PAIR_FAIL, SMP_PAIRING_CMPL, SMP_STATE_IDLE},
|
||||
/* L2C_DISC */ {SMP_PAIR_TERMINATE, SMP_SM_NO_ACTION, SMP_STATE_IDLE}
|
||||
};
|
||||
|
||||
static const UINT8 smp_master_idle_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* L2C_CONN */ {SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
|
||||
/* SEC_REQ */ {SMP_PROC_SEC_REQ, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_APP_RSP},
|
||||
/* L2C_DISC */ {SMP_IDLE_TERMINATE, SMP_SM_NO_ACTION, SMP_STATE_IDLE},
|
||||
/* AUTH_CMPL */ {SMP_PAIRING_CMPL, SMP_SM_NO_ACTION, SMP_STATE_IDLE}
|
||||
/* CR_LOC_SC_OOB_DATA */ , {SMP_CREATE_PRIVATE_KEY, SMP_SM_NO_ACTION, SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA}
|
||||
|
||||
};
|
||||
|
||||
static const UINT8 smp_master_wait_for_app_response_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* SEC_GRANT */ {SMP_PROC_SEC_GRANT, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_APP_RSP},
|
||||
/* IO_RSP */ {SMP_SEND_PAIR_REQ, SMP_FAST_CONN_PARAM, SMP_STATE_PAIR_REQ_RSP},
|
||||
|
||||
/* TK ready */
|
||||
/* KEY_READY */ {SMP_GENERATE_CONFIRM, SMP_SM_NO_ACTION, SMP_STATE_WAIT_CONFIRM},
|
||||
|
||||
/* start enc mode setup */
|
||||
/* ENC_REQ */ { SMP_START_ENC, SMP_FAST_CONN_PARAM, SMP_STATE_ENCRYPTION_PENDING},
|
||||
/* DISCARD_SEC_REQ */ { SMP_PROC_DISCARD, SMP_SM_NO_ACTION, SMP_STATE_IDLE}
|
||||
/* user confirms NC 'OK', i.e. phase 1 is completed */
|
||||
/* SC_NC_OK */, { SMP_MOVE_TO_SEC_CONN_PHASE2, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS2_START},
|
||||
/* user-provided passkey is rcvd */
|
||||
/* SC_KEY_READY */ { SMP_START_PASSKEY_VERIFICATION, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
|
||||
/* PAIR_KEYPR_NOTIF */ { SMP_PROCESS_KEYPRESS_NOTIFICATION, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_APP_RSP},
|
||||
/* KEYPR_NOTIF */ { SMP_SEND_KEYPRESS_NOTIFICATION, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
|
||||
/* SC_OOB_DATA */ { SMP_USE_OOB_PRIVATE_KEY, SMP_SM_NO_ACTION, SMP_STATE_PUBLIC_KEY_EXCH}
|
||||
};
|
||||
|
||||
static const UINT8 smp_master_pair_request_response_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* PAIR_RSP */ { SMP_PROC_PAIR_CMD, SMP_SM_NO_ACTION, SMP_STATE_PAIR_REQ_RSP},
|
||||
/* TK_REQ */ { SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
|
||||
|
||||
/* TK ready */
|
||||
/* KEY_READY */{ SMP_GENERATE_CONFIRM, SMP_SM_NO_ACTION, SMP_STATE_WAIT_CONFIRM}
|
||||
/* PUBL_KEY_EXCH_REQ */, { SMP_CREATE_PRIVATE_KEY, SMP_SM_NO_ACTION, SMP_STATE_PUBLIC_KEY_EXCH}
|
||||
};
|
||||
|
||||
static const UINT8 smp_master_wait_for_confirm_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* KEY_READY*/ {SMP_SEND_CONFIRM, SMP_SM_NO_ACTION, SMP_STATE_CONFIRM}/* CONFIRM ready */
|
||||
};
|
||||
|
||||
static const UINT8 smp_master_confirm_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* CONFIRM */ { SMP_PROC_CONFIRM, SMP_SEND_RAND, SMP_STATE_RAND}
|
||||
};
|
||||
|
||||
static const UINT8 smp_master_rand_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* RAND */ { SMP_PROC_RAND, SMP_GENERATE_COMPARE, SMP_STATE_RAND},
|
||||
/* KEY_READY*/ { SMP_PROC_COMPARE, SMP_SM_NO_ACTION, SMP_STATE_RAND}, /* Compare ready */
|
||||
/* ENC_REQ */ { SMP_GENERATE_STK, SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING}
|
||||
};
|
||||
|
||||
static const UINT8 smp_master_public_key_exchange_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* LOC_PUBL_KEY_CRTD */{ SMP_SEND_PAIR_PUBLIC_KEY, SMP_SM_NO_ACTION, SMP_STATE_PUBLIC_KEY_EXCH},
|
||||
/* PAIR_PUBLIC_KEY */{ SMP_PROCESS_PAIR_PUBLIC_KEY, SMP_SM_NO_ACTION, SMP_STATE_PUBLIC_KEY_EXCH},
|
||||
/* BOTH_PUBL_KEYS_RCVD */{ SMP_HAVE_BOTH_PUBLIC_KEYS, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
|
||||
};
|
||||
|
||||
static const UINT8 smp_master_sec_conn_phs1_start_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* SC_DHKEY_CMPLT */{ SMP_START_SEC_CONN_PHASE1, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
|
||||
/* HAVE_LOC_NONCE */{ SMP_PROCESS_LOCAL_NONCE, SMP_SM_NO_ACTION, SMP_STATE_WAIT_COMMITMENT},
|
||||
/* TK_REQ */{ SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
|
||||
/* SMP_MODEL_SEC_CONN_PASSKEY_DISP model, passkey is sent up to display,*/
|
||||
/* It's time to start commitment calculation */
|
||||
/* KEY_READY */{ SMP_START_PASSKEY_VERIFICATION, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
|
||||
/* PAIR_KEYPR_NOTIF */{ SMP_PROCESS_KEYPRESS_NOTIFICATION, SMP_SEND_APP_CBACK, SMP_STATE_SEC_CONN_PHS1_START},
|
||||
/* PAIR_COMMITM */{ SMP_PROCESS_PAIRING_COMMITMENT, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
|
||||
};
|
||||
|
||||
static const UINT8 smp_master_wait_commitment_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* PAIR_COMMITM */{ SMP_PROCESS_PAIRING_COMMITMENT, SMP_SEND_RAND, SMP_STATE_WAIT_NONCE},
|
||||
/* PAIR_KEYPR_NOTIF */{ SMP_PROCESS_KEYPRESS_NOTIFICATION, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_COMMITMENT},
|
||||
};
|
||||
|
||||
static const UINT8 smp_master_wait_nonce_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* peer nonce is received */
|
||||
/* RAND */{SMP_PROC_RAND, SMP_PROCESS_PEER_NONCE, SMP_STATE_SEC_CONN_PHS2_START},
|
||||
/* NC model, time to calculate number for NC */
|
||||
/* SC_CALC_NC */{SMP_CALCULATE_NUMERIC_COMPARISON_DISPLAY_NUMBER, SMP_SM_NO_ACTION, SMP_STATE_WAIT_NONCE},
|
||||
/* NC model, time to display calculated number for NC to the user */
|
||||
/* SC_DSPL_NC */{SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
|
||||
};
|
||||
|
||||
static const UINT8 smp_master_sec_conn_phs2_start_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* SC_PHASE1_CMPLT */{SMP_CALCULATE_LOCAL_DHKEY_CHECK, SMP_SEND_DHKEY_CHECK, SMP_STATE_WAIT_DHK_CHECK},
|
||||
};
|
||||
|
||||
static const UINT8 smp_master_wait_dhk_check_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* PAIR_DHKEY_CHCK */{SMP_PROCESS_DHKEY_CHECK, SMP_CALCULATE_PEER_DHKEY_CHECK, SMP_STATE_DHK_CHECK},
|
||||
};
|
||||
|
||||
static const UINT8 smp_master_dhk_check_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* locally calculated peer dhkey check is ready -> compare it withs DHKey Check actually received from peer */
|
||||
/* SC_KEY_READY */{SMP_MATCH_DHKEY_CHECKS, SMP_SM_NO_ACTION, SMP_STATE_DHK_CHECK},
|
||||
/* locally calculated peer dhkey check is ready -> calculate STK, go to sending */
|
||||
/* HCI LE Start Encryption command */
|
||||
/* ENC_REQ */{SMP_GENERATE_STK, SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
|
||||
};
|
||||
|
||||
static const UINT8 smp_master_enc_pending_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* STK ready */
|
||||
/* KEY_READY */ { SMP_START_ENC, SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
|
||||
/* ENCRYPTED */ { SMP_CHECK_AUTH_REQ, SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
|
||||
/* BOND_REQ */ { SMP_KEY_DISTRIBUTE, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING}
|
||||
};
|
||||
static const UINT8 smp_master_bond_pending_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* ENC_INFO */ { SMP_PROC_ENC_INFO, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
|
||||
/* ID_INFO */ { SMP_PROC_ID_INFO, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
|
||||
/* SIGN_INFO*/ { SMP_PROC_SRK_INFO, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
|
||||
/* MASTER_ID*/ { SMP_PROC_MASTER_ID, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
|
||||
/* ID_ADDR */ { SMP_PROC_ID_ADDR, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
|
||||
/* KEY_READY */{SMP_SEND_ENC_INFO, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING} /* LTK ready */
|
||||
};
|
||||
|
||||
static const UINT8 smp_master_create_local_sec_conn_oob_data[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* LOC_PUBL_KEY_CRTD */ {SMP_SET_LOCAL_OOB_KEYS, SMP_SM_NO_ACTION, SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA},
|
||||
/* HAVE_LOC_NONCE */ {SMP_SET_LOCAL_OOB_RAND_COMMITMENT, SMP_SM_NO_ACTION, SMP_STATE_IDLE}
|
||||
};
|
||||
|
||||
|
||||
/************ SMP Slave FSM State/Event Indirection Table **************/
|
||||
static const UINT8 smp_slave_entry_map[][SMP_STATE_MAX] = {
|
||||
/* state name: Idle WaitApp SecReq Pair Wait Confirm Rand PublKey SCPhs1 Wait Wait SCPhs2 Wait DHKChk Enc Bond CrLocSc
|
||||
Rsp Pend ReqRsp Cfm Exch Strt Cmtm Nonce Strt DHKChk Pend Pend OobData */
|
||||
/* PAIR_REQ */{ 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* PAIR_RSP */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* CONFIRM */{ 0, 4, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* RAND */{ 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
|
||||
/* PAIR_FAIL */{ 0, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0, 0 },
|
||||
/* ENC_INFO */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0 },
|
||||
/* MASTER_ID */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0 },
|
||||
/* ID_INFO */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0 },
|
||||
/* ID_ADDR */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0 },
|
||||
/* SIGN_INFO */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0 },
|
||||
/* SEC_REQ */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* PAIR_PUBLIC_KEY */{ 0, 0, 0, 5, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* PAIR_DHKEY_CHCK */{ 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 0, 0, 0 },
|
||||
/* PAIR_KEYPR_NOTIF */{ 0, 9, 0, 0, 0, 0, 0, 0, 5, 2, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* PAIR_COMMITM */{ 0, 8, 0, 0, 0, 0, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* KEY_READY */{ 0, 3, 0, 3, 2, 2, 1, 0, 4, 0, 0, 0, 0, 0, 2, 1, 0 },
|
||||
/* ENC_CMPL */{ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 },
|
||||
/* L2C_CONN */{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* L2C_DISC */{ 0, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0 },
|
||||
/* IO_RSP */{ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* SEC_GRANT */{ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* TK_REQ */{ 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* AUTH_CMPL */{ 0, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0 },
|
||||
/* ENC_REQ */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
|
||||
/* BOND_REQ */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0 },
|
||||
/* DISCARD_SEC_REQ */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* PUBL_KEY_EXCH_REQ */{ 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* LOC_PUBL_KEY_CRTD */{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
||||
/* BOTH_PUBL_KEYS_RCVD */{ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* SC_DHKEY_CMPLT */{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* HAVE_LOC_NONCE */{ 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2 },
|
||||
/* SC_PHASE1_CMPLT */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
|
||||
/* SC_CALC_NC */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 },
|
||||
/* SC_DSPL_NC */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0 },
|
||||
/* SC_NC_OK */{ 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* SC_2_DHCK_CHKS_PRES */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0 },
|
||||
/* SC_KEY_READY */{ 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
|
||||
/* KEYPR_NOTIF */{ 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* SC_OOB_DATA */{ 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* CR_LOC_SC_OOB_DATA */{ 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static const UINT8 smp_slave_idle_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* L2C_CONN */ {SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
|
||||
/* PAIR_REQ */ {SMP_PROC_PAIR_CMD, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_APP_RSP}
|
||||
/* CR_LOC_SC_OOB_DATA */ , {SMP_CREATE_PRIVATE_KEY, SMP_SM_NO_ACTION, SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA}
|
||||
};
|
||||
|
||||
static const UINT8 smp_slave_wait_for_app_response_table [][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* IO_RSP */ {SMP_PROC_IO_RSP, SMP_FAST_CONN_PARAM, SMP_STATE_PAIR_REQ_RSP},
|
||||
/* SEC_GRANT */ {SMP_PROC_SEC_GRANT, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_APP_RSP},
|
||||
|
||||
/* TK ready */
|
||||
/* KEY_READY */ {SMP_PROC_SL_KEY, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
|
||||
/* CONFIRM */ {SMP_PROC_CONFIRM, SMP_SM_NO_ACTION, SMP_STATE_CONFIRM}
|
||||
/* DHKey Check from master is received before phase 1 is completed - race */
|
||||
/* PAIR_DHKEY_CHCK */, {SMP_PROCESS_DHKEY_CHECK, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
|
||||
/* user confirms NC 'OK', i.e. phase 1 is completed */
|
||||
/* SC_NC_OK */ {SMP_MOVE_TO_SEC_CONN_PHASE2, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS2_START},
|
||||
/* user-provided passkey is rcvd */
|
||||
/* SC_KEY_READY */ {SMP_START_PASSKEY_VERIFICATION, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
|
||||
/* PAIR_COMMITM */ {SMP_PROCESS_PAIRING_COMMITMENT, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
|
||||
/* PAIR_KEYPR_NOTIF */ {SMP_PROCESS_KEYPRESS_NOTIFICATION, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_APP_RSP},
|
||||
/* KEYPR_NOTIF */ {SMP_SEND_KEYPRESS_NOTIFICATION, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
|
||||
/* SC_OOB_DATA */ {SMP_SEND_PAIR_RSP, SMP_SM_NO_ACTION, SMP_STATE_PAIR_REQ_RSP},
|
||||
};
|
||||
|
||||
static const UINT8 smp_slave_sec_request_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* PAIR_REQ */{SMP_PROC_PAIR_CMD, SMP_SM_NO_ACTION, SMP_STATE_PAIR_REQ_RSP},
|
||||
/* ENCRYPTED*/{SMP_ENC_CMPL, SMP_SM_NO_ACTION, SMP_STATE_PAIR_REQ_RSP},
|
||||
};
|
||||
|
||||
static const UINT8 smp_slave_pair_request_response_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* CONFIRM */ {SMP_PROC_CONFIRM, SMP_SM_NO_ACTION, SMP_STATE_CONFIRM},
|
||||
/* TK_REQ */ {SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
|
||||
/* TK/Confirm ready */
|
||||
/* KEY_READY */{SMP_PROC_SL_KEY, SMP_SM_NO_ACTION, SMP_STATE_PAIR_REQ_RSP}
|
||||
/* PUBL_KEY_EXCH_REQ */, { SMP_CREATE_PRIVATE_KEY, SMP_SM_NO_ACTION, SMP_STATE_PUBLIC_KEY_EXCH},
|
||||
/* PAIR_PUBLIC_KEY */ { SMP_PROCESS_PAIR_PUBLIC_KEY, SMP_SM_NO_ACTION, SMP_STATE_PAIR_REQ_RSP},
|
||||
};
|
||||
|
||||
static const UINT8 smp_slave_wait_confirm_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* CONFIRM */ {SMP_PROC_CONFIRM, SMP_SEND_CONFIRM, SMP_STATE_CONFIRM},
|
||||
/* KEY_READY*/ {SMP_PROC_SL_KEY, SMP_SM_NO_ACTION, SMP_STATE_WAIT_CONFIRM}
|
||||
};
|
||||
|
||||
static const UINT8 smp_slave_confirm_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* RAND */ {SMP_PROC_RAND, SMP_GENERATE_COMPARE, SMP_STATE_RAND},
|
||||
|
||||
/* TK/Confirm ready */
|
||||
/* KEY_READY*/ {SMP_PROC_SL_KEY, SMP_SM_NO_ACTION, SMP_STATE_CONFIRM}
|
||||
};
|
||||
|
||||
static const UINT8 smp_slave_rand_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* KEY_READY */ {SMP_PROC_COMPARE, SMP_SM_NO_ACTION, SMP_STATE_RAND}, /* compare match */
|
||||
/* RAND */ {SMP_SEND_RAND, SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING}
|
||||
};
|
||||
|
||||
static const UINT8 smp_slave_public_key_exch_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* LOC_PUBL_KEY_CRTD */{ SMP_WAIT_FOR_BOTH_PUBLIC_KEYS, SMP_SM_NO_ACTION, SMP_STATE_PUBLIC_KEY_EXCH},
|
||||
/* PAIR_PUBLIC_KEY */{ SMP_PROCESS_PAIR_PUBLIC_KEY, SMP_SM_NO_ACTION, SMP_STATE_PUBLIC_KEY_EXCH},
|
||||
/* BOTH_PUBL_KEYS_RCVD */{ SMP_HAVE_BOTH_PUBLIC_KEYS, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
|
||||
};
|
||||
|
||||
static const UINT8 smp_slave_sec_conn_phs1_start_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* SC_DHKEY_CMPLT */{ SMP_START_SEC_CONN_PHASE1, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
|
||||
/* HAVE_LOC_NONCE */{ SMP_PROCESS_LOCAL_NONCE, SMP_SM_NO_ACTION, SMP_STATE_WAIT_COMMITMENT},
|
||||
/* TK_REQ */{ SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
|
||||
/* SMP_MODEL_SEC_CONN_PASSKEY_DISP model, passkey is sent up to display, it's time to start */
|
||||
/* commitment calculation */
|
||||
/* KEY_READY */{ SMP_START_PASSKEY_VERIFICATION, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
|
||||
/* PAIR_KEYPR_NOTIF */{ SMP_PROCESS_KEYPRESS_NOTIFICATION, SMP_SEND_APP_CBACK, SMP_STATE_SEC_CONN_PHS1_START},
|
||||
/*COMMIT*/{SMP_PROCESS_PAIRING_COMMITMENT, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
|
||||
};
|
||||
|
||||
static const UINT8 smp_slave_wait_commitment_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* PAIR_COMMITM */{SMP_PROCESS_PAIRING_COMMITMENT, SMP_SEND_COMMITMENT, SMP_STATE_WAIT_NONCE},
|
||||
/* PAIR_KEYPR_NOTIF */{SMP_PROCESS_KEYPRESS_NOTIFICATION, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_COMMITMENT},
|
||||
};
|
||||
|
||||
static const UINT8 smp_slave_wait_nonce_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* peer nonce is received */
|
||||
/* RAND */{SMP_PROC_RAND, SMP_PROCESS_PEER_NONCE, SMP_STATE_SEC_CONN_PHS2_START},
|
||||
/* NC model, time to calculate number for NC */
|
||||
/* SC_CALC_NC */{SMP_CALCULATE_NUMERIC_COMPARISON_DISPLAY_NUMBER, SMP_SM_NO_ACTION, SMP_STATE_WAIT_NONCE},
|
||||
/* NC model, time to display calculated number for NC to the user */
|
||||
/* SC_DSPL_NC */{SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
|
||||
};
|
||||
|
||||
static const UINT8 smp_slave_sec_conn_phs2_start_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* SC_PHASE1_CMPLT */{SMP_CALCULATE_LOCAL_DHKEY_CHECK, SMP_PH2_DHKEY_CHECKS_ARE_PRESENT, SMP_STATE_WAIT_DHK_CHECK},
|
||||
/* DHKey Check from master is received before slave DHKey calculation is completed - race */
|
||||
/* PAIR_DHKEY_CHCK */{SMP_PROCESS_DHKEY_CHECK, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS2_START},
|
||||
};
|
||||
|
||||
static const UINT8 smp_slave_wait_dhk_check_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* PAIR_DHKEY_CHCK */{SMP_PROCESS_DHKEY_CHECK, SMP_CALCULATE_PEER_DHKEY_CHECK, SMP_STATE_DHK_CHECK},
|
||||
/* DHKey Check from master was received before slave came to this state */
|
||||
/* SC_2_DHCK_CHKS_PRES */{SMP_CALCULATE_PEER_DHKEY_CHECK, SMP_SM_NO_ACTION, SMP_STATE_DHK_CHECK},
|
||||
};
|
||||
|
||||
static const UINT8 smp_slave_dhk_check_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
|
||||
/* locally calculated peer dhkey check is ready -> compare it withs DHKey Check */
|
||||
/* actually received from peer */
|
||||
/* SC_KEY_READY */{SMP_MATCH_DHKEY_CHECKS, SMP_SM_NO_ACTION, SMP_STATE_DHK_CHECK},
|
||||
|
||||
/* dhkey checks match -> send local dhkey check to master, go to wait for HCI LE */
|
||||
/* Long Term Key Request Event */
|
||||
/* PAIR_DHKEY_CHCK */{SMP_SEND_DHKEY_CHECK, SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
|
||||
};
|
||||
|
||||
static const UINT8 smp_slave_enc_pending_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* ENC_REQ */ {SMP_GENERATE_STK, SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
|
||||
|
||||
/* STK ready */
|
||||
/* KEY_READY */ {SMP_SEND_LTK_REPLY, SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
|
||||
/* ENCRYPTED */ {SMP_CHECK_AUTH_REQ, SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
|
||||
/* BOND_REQ */ {SMP_KEY_DISTRIBUTE, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING}
|
||||
};
|
||||
static const UINT8 smp_slave_bond_pending_table[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
|
||||
/* LTK ready */
|
||||
/* KEY_READY */{ SMP_SEND_ENC_INFO, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
|
||||
|
||||
/* rev SRK */
|
||||
/* SIGN_INFO */{ SMP_PROC_SRK_INFO, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
|
||||
/* ENC_INFO */ { SMP_PROC_ENC_INFO, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
|
||||
/* ID_INFO */ { SMP_PROC_ID_INFO, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
|
||||
/* MASTER_ID*/ { SMP_PROC_MASTER_ID, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
|
||||
/* ID_ADDR */ { SMP_PROC_ID_ADDR, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING}
|
||||
|
||||
};
|
||||
|
||||
static const UINT8 smp_slave_create_local_sec_conn_oob_data[][SMP_SM_NUM_COLS] = {
|
||||
/* Event Action Next State */
|
||||
/* LOC_PUBL_KEY_CRTD */ {SMP_SET_LOCAL_OOB_KEYS, SMP_SM_NO_ACTION, SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA},
|
||||
/* HAVE_LOC_NONCE */ {SMP_SET_LOCAL_OOB_RAND_COMMITMENT, SMP_SM_NO_ACTION, SMP_STATE_IDLE}
|
||||
};
|
||||
|
||||
static const tSMP_SM_TBL smp_state_table[][2] = {
|
||||
/* SMP_STATE_IDLE */
|
||||
{smp_master_idle_table, smp_slave_idle_table},
|
||||
|
||||
/* SMP_STATE_WAIT_APP_RSP */
|
||||
{smp_master_wait_for_app_response_table, smp_slave_wait_for_app_response_table},
|
||||
|
||||
/* SMP_STATE_SEC_REQ_PENDING */
|
||||
{NULL, smp_slave_sec_request_table},
|
||||
|
||||
/* SMP_STATE_PAIR_REQ_RSP */
|
||||
{smp_master_pair_request_response_table, smp_slave_pair_request_response_table},
|
||||
|
||||
/* SMP_STATE_WAIT_CONFIRM */
|
||||
{smp_master_wait_for_confirm_table, smp_slave_wait_confirm_table},
|
||||
|
||||
/* SMP_STATE_CONFIRM */
|
||||
{smp_master_confirm_table, smp_slave_confirm_table},
|
||||
|
||||
/* SMP_STATE_RAND */
|
||||
{smp_master_rand_table, smp_slave_rand_table},
|
||||
|
||||
/* SMP_STATE_PUBLIC_KEY_EXCH */
|
||||
{smp_master_public_key_exchange_table, smp_slave_public_key_exch_table},
|
||||
|
||||
/* SMP_STATE_SEC_CONN_PHS1_START */
|
||||
{smp_master_sec_conn_phs1_start_table, smp_slave_sec_conn_phs1_start_table},
|
||||
|
||||
/* SMP_STATE_WAIT_COMMITMENT */
|
||||
{smp_master_wait_commitment_table, smp_slave_wait_commitment_table},
|
||||
|
||||
/* SMP_STATE_WAIT_NONCE */
|
||||
{smp_master_wait_nonce_table, smp_slave_wait_nonce_table},
|
||||
|
||||
/* SMP_STATE_SEC_CONN_PHS2_START */
|
||||
{smp_master_sec_conn_phs2_start_table, smp_slave_sec_conn_phs2_start_table},
|
||||
|
||||
/* SMP_STATE_WAIT_DHK_CHECK */
|
||||
{smp_master_wait_dhk_check_table, smp_slave_wait_dhk_check_table},
|
||||
|
||||
/* SMP_STATE_DHK_CHECK */
|
||||
{smp_master_dhk_check_table, smp_slave_dhk_check_table},
|
||||
|
||||
/* SMP_STATE_ENCRYPTION_PENDING */
|
||||
{smp_master_enc_pending_table, smp_slave_enc_pending_table},
|
||||
|
||||
/* SMP_STATE_BOND_PENDING */
|
||||
{smp_master_bond_pending_table, smp_slave_bond_pending_table},
|
||||
|
||||
/* SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA */
|
||||
{smp_master_create_local_sec_conn_oob_data, smp_slave_create_local_sec_conn_oob_data}
|
||||
};
|
||||
|
||||
typedef const UINT8 (*tSMP_ENTRY_TBL)[SMP_STATE_MAX];
|
||||
static const tSMP_ENTRY_TBL smp_entry_table[] = {
|
||||
smp_master_entry_map,
|
||||
smp_slave_entry_map
|
||||
};
|
||||
|
||||
#if SMP_DYNAMIC_MEMORY == FALSE
|
||||
tSMP_CB smp_cb;
|
||||
#else
|
||||
tSMP_CB *smp_cb_ptr;
|
||||
#endif
|
||||
#define SMP_ALL_TBL_MASK 0x80
|
||||
|
||||
/*******************************************************************************
|
||||
** Function smp_set_state
|
||||
** Returns None
|
||||
*******************************************************************************/
|
||||
void smp_set_state(tSMP_STATE state)
|
||||
{
|
||||
if (state < SMP_STATE_MAX) {
|
||||
SMP_TRACE_DEBUG( "State change: %s(%d) ==> %s(%d)",
|
||||
smp_get_state_name(smp_cb.state), smp_cb.state,
|
||||
smp_get_state_name(state), state );
|
||||
smp_cb.state = state;
|
||||
} else {
|
||||
SMP_TRACE_DEBUG("smp_set_state invalid state =%d", state );
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
** Function smp_get_state
|
||||
** Returns The smp state
|
||||
*******************************************************************************/
|
||||
tSMP_STATE smp_get_state(void)
|
||||
{
|
||||
return smp_cb.state;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function smp_sm_event
|
||||
**
|
||||
** Description Handle events to the state machine. It looks up the entry
|
||||
** in the smp_entry_table array.
|
||||
** If it is a valid entry, it gets the state table.Set the next state,
|
||||
** if not NULL state.Execute the action function according to the
|
||||
** state table. If the state returned by action function is not NULL
|
||||
** state, adjust the new state to the returned state.If (api_evt != MAX),
|
||||
** call callback function.
|
||||
**
|
||||
** Returns void.
|
||||
**
|
||||
*******************************************************************************/
|
||||
void smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data)
|
||||
{
|
||||
UINT8 curr_state = p_cb->state;
|
||||
tSMP_SM_TBL state_table;
|
||||
UINT8 action, entry, i;
|
||||
tSMP_ENTRY_TBL entry_table = smp_entry_table[p_cb->role];
|
||||
|
||||
SMP_TRACE_EVENT("main smp_sm_event\n");
|
||||
if (curr_state >= SMP_STATE_MAX) {
|
||||
SMP_TRACE_DEBUG( "Invalid state: %d\n", curr_state) ;
|
||||
return;
|
||||
}
|
||||
|
||||
SMP_TRACE_DEBUG( "SMP Role: %s State: [%s (%d)], Event: [%s (%d)]", \
|
||||
(p_cb->role == 0x01) ? "Slave" : "Master\n", smp_get_state_name( p_cb->state),
|
||||
p_cb->state, smp_get_event_name(event), event) ;
|
||||
|
||||
/* look up the state table for the current state */
|
||||
/* lookup entry /w event & curr_state */
|
||||
/* If entry is ignore, return.
|
||||
* Otherwise, get state table (according to curr_state or all_state) */
|
||||
if ((event <= SMP_MAX_EVT) && ( (entry = entry_table[event - 1][curr_state]) != SMP_SM_IGNORE )) {
|
||||
if (entry & SMP_ALL_TBL_MASK) {
|
||||
entry &= ~SMP_ALL_TBL_MASK;
|
||||
state_table = smp_all_table;
|
||||
} else {
|
||||
state_table = smp_state_table[curr_state][p_cb->role ? 1 : 0];
|
||||
}
|
||||
} else {
|
||||
SMP_TRACE_DEBUG( "Ignore event [%s (%d)] in state [%s (%d)]\n",
|
||||
smp_get_event_name(event), event, smp_get_state_name(curr_state),
|
||||
curr_state);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get possible next state from state table. */
|
||||
|
||||
smp_set_state(state_table[entry - 1][SMP_SME_NEXT_STATE]);
|
||||
|
||||
/* If action is not ignore, clear param, exec action and get next state.
|
||||
* The action function may set the Param for cback.
|
||||
* Depending on param, call cback or free buffer. */
|
||||
/* execute action */
|
||||
/* execute action functions */
|
||||
for (i = 0; i < SMP_NUM_ACTIONS; i++) {
|
||||
if ((action = state_table[entry - 1][i]) != SMP_SM_NO_ACTION && smp_sm_action[action] != NULL) {
|
||||
(*smp_sm_action[action])(p_cb, (tSMP_INT_DATA *)p_data);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
SMP_TRACE_DEBUG( "result state = %s\n", smp_get_state_name( p_cb->state ) ) ;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
** Function smp_get_state_name
|
||||
** Returns The smp state name.
|
||||
*******************************************************************************/
|
||||
const char *smp_get_state_name(tSMP_STATE state)
|
||||
{
|
||||
const char *p_str = smp_state_name[SMP_STATE_MAX];
|
||||
|
||||
if (state < SMP_STATE_MAX) {
|
||||
p_str = smp_state_name[state];
|
||||
}
|
||||
return p_str;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
** Function smp_get_event_name
|
||||
** Returns The smp event name.
|
||||
*******************************************************************************/
|
||||
const char *smp_get_event_name(tSMP_EVENT event)
|
||||
{
|
||||
const char *p_str = smp_event_name[SMP_MAX_EVT];
|
||||
|
||||
if (event <= SMP_MAX_EVT) {
|
||||
p_str = smp_event_name[event - 1];
|
||||
}
|
||||
return p_str;
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user