Fork ESP-IDF's bluetooth component

i want better sbc encoding, and no cla will stop me
This commit is contained in:
jacqueline
2024-03-28 14:32:49 +11:00
parent 239e6d8950
commit ee29c25b29
1761 changed files with 737738 additions and 0 deletions
+938
View File
@@ -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
+615
View File
@@ -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
+369
View File
@@ -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
+344
View File
@@ -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 */
+810
View File
@@ -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