mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-11-02 10:32:46 +00:00
nimble/ll: Add DRBG for Channel Sounding
A dedicated CS DRBG is used to coordinate the randomization of several transaction types during a CS procedure.
This commit is contained in:
committed by
Szymon Janc
parent
0552255986
commit
c5cb9e47c7
@@ -0,0 +1,682 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 <syscfg/syscfg.h>
|
||||
#if MYNEWT_VAL(BLE_LL_CHANNEL_SOUNDING)
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <os/endian.h>
|
||||
#include "nimble/ble.h"
|
||||
#include "mbedtls/aes.h"
|
||||
#include "ble_ll_cs_drbg_priv.h"
|
||||
#if !(BABBLESIM || MYNEWT_VAL(SELFTEST))
|
||||
#include "controller/ble_hw.h"
|
||||
#endif
|
||||
|
||||
static const uint8_t rtt_seq_len[] = { 0, 4, 12, 4, 8, 12, 16 };
|
||||
|
||||
/**
|
||||
* Security function e generates 128-bit encrypted_data from a 128-bit key
|
||||
* and 128-bit data using the AES-128-bit block cypher.
|
||||
*/
|
||||
int
|
||||
ble_ll_cs_drbg_e(const uint8_t *key, const uint8_t *data, uint8_t *out_data)
|
||||
{
|
||||
struct ble_encryption_block ecb;
|
||||
int rc = 0;
|
||||
|
||||
/* The cryptographic function uses the leftmost to rightmost
|
||||
* representation (MSO to LSO).
|
||||
*/
|
||||
swap_buf(ecb.key, key, BLE_ENC_BLOCK_SIZE);
|
||||
swap_buf(ecb.plain_text, data, BLE_ENC_BLOCK_SIZE);
|
||||
|
||||
#if BABBLESIM || MYNEWT_VAL(SELFTEST)
|
||||
/* Use software to encrypt the data */
|
||||
mbedtls_aes_context aes_ctx;
|
||||
mbedtls_aes_init(&aes_ctx);
|
||||
mbedtls_aes_setkey_enc(&aes_ctx, ecb.key, 16 * 8);
|
||||
rc = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, ecb.plain_text,
|
||||
ecb.cipher_text);
|
||||
mbedtls_aes_free(&aes_ctx);
|
||||
#else
|
||||
/* Use hardware to encrypt the data */
|
||||
rc = ble_hw_encrypt_block(&ecb);
|
||||
#endif
|
||||
|
||||
if (!rc) {
|
||||
swap_buf(out_data, ecb.cipher_text, BLE_ENC_BLOCK_SIZE);
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* DRBG chain function f7.
|
||||
* - k - 128-bit key
|
||||
* - in - an input bit string whose length is a multiple of 128 bits and
|
||||
* generates an output that is 128 bits long using a cipher block
|
||||
* chaining technique.
|
||||
* - out - processed bit string
|
||||
*/
|
||||
int
|
||||
ble_ll_cs_drbg_f7(const uint8_t *k, const uint8_t *in, uint8_t len, uint8_t *out)
|
||||
{
|
||||
int rc = 0;
|
||||
int i;
|
||||
const uint64_t *block;
|
||||
uint64_t *hout = (uint64_t *)out;
|
||||
|
||||
memset(hout, 0, 16);
|
||||
|
||||
/* Starting with the leftmost bits (MSO) of input_bit_string, split into
|
||||
* 128-bit blocks
|
||||
*/
|
||||
for (i = len - 16; i >= 0; i -= 16) {
|
||||
block = (uint64_t *)&in[i];
|
||||
/* XOR a 128-bit block in two steps */
|
||||
*hout ^= *block;
|
||||
*(hout + 1) ^= *(block + 1);
|
||||
|
||||
rc = ble_ll_cs_drbg_e(k, out, out);
|
||||
if (rc) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* DRBG derivation function f8.
|
||||
* - input - 320-bit input bit string
|
||||
* - sm - output, generated 256-bit seed material (SM)
|
||||
*/
|
||||
int
|
||||
ble_ll_cs_drbg_f8(const uint8_t *input, uint8_t *sm)
|
||||
{
|
||||
int rc;
|
||||
uint8_t k[16] = { 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08,
|
||||
0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
|
||||
uint8_t k2[16] = { 0 };
|
||||
uint8_t x[16] = { 0 };
|
||||
/* buf contains V || S */
|
||||
uint8_t buf[80] = { 0 };
|
||||
uint8_t *s = buf;
|
||||
uint8_t *v = buf + 64;
|
||||
|
||||
/* S = 0x0000002800000020 || input_bit_string || 0x80 ||
|
||||
* 0x000000000000000000000000000000
|
||||
*/
|
||||
s[15] = 0x80;
|
||||
memcpy(s + 16, input, 40);
|
||||
put_le64(s + 56, 0x0000002800000020);
|
||||
|
||||
/* K2 = f7( K, V || S ) */
|
||||
rc = ble_ll_cs_drbg_f7(k, buf, 80, k2);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* V = 0x00000001000000000000000000000000 */
|
||||
v[12] = 0x01;
|
||||
|
||||
/* X = f7( K, V || S ) */
|
||||
rc = ble_ll_cs_drbg_f7(k, buf, 80, x);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Calculate the most significant part of SM:
|
||||
* SM = e( K2, X )
|
||||
*/
|
||||
rc = ble_ll_cs_drbg_e(k2, x, sm + 16);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Calculate the least significant part of SM and concatenate
|
||||
* both parts:
|
||||
* SM = SM || e( K2, SM )
|
||||
*/
|
||||
rc = ble_ll_cs_drbg_e(k2, sm + 16, sm);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* DRBG update function f9 is used to update and refresh a DRBG 128-bit
|
||||
* temporal key K and a 128-bit nonce vector V using a 256-bit seed material
|
||||
* (SM) that may carry fresh entropy. The SM value may also be 0 if f9 is
|
||||
* called for backtracking purposes.
|
||||
* - sm - 256-bit seed material
|
||||
* - k_in - 128-bit key
|
||||
* - v_in - 128-bit nonce vector
|
||||
*/
|
||||
int
|
||||
ble_ll_cs_drbg_f9(const uint8_t *sm, uint8_t *k, uint8_t *v)
|
||||
{
|
||||
int rc;
|
||||
uint8_t x[32] = { 0 };
|
||||
uint64_t *x_p = (uint64_t *)x;
|
||||
uint64_t *sm_p = (uint64_t *)sm;
|
||||
|
||||
/* V = V[127:8] || (( V[7:0] + 1 ) mod 2^8) */
|
||||
v[0]++;
|
||||
rc = ble_ll_cs_drbg_e(k, v, x + 16);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
v[0]++;
|
||||
/* Again V = V[127:8] || (( V[7:0] + 1 ) mod 2^8) */
|
||||
rc = ble_ll_cs_drbg_e(k, v, x);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* X = X ⊕ SM */
|
||||
x_p[0] ^= sm_p[0];
|
||||
x_p[1] ^= sm_p[1];
|
||||
x_p[2] ^= sm_p[2];
|
||||
x_p[3] ^= sm_p[3];
|
||||
|
||||
memcpy(v, x, 16);
|
||||
memcpy(k, x + 16, 16);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* DRBG instantiation function h9.
|
||||
* - iv - 128-bit initialization vector (CS_IV)
|
||||
* - in - 64-bit instantiation nonce (CS_IN)
|
||||
* - pv - 128-bit personalization vector (CS_PV)
|
||||
* - key - output, 128-bit temporal key (K_DRBG)
|
||||
* - nonce_v - output, 128-bit nonce vector (V_DRBG)
|
||||
*/
|
||||
int
|
||||
ble_ll_cs_drbg_h9(const uint8_t *iv, const uint8_t *in, const uint8_t *pv,
|
||||
uint8_t *key, uint8_t *nonce_v)
|
||||
{
|
||||
int rc;
|
||||
uint8_t input_bit_string[40] = { 0 };
|
||||
uint8_t sm[32] = { 0 };
|
||||
|
||||
/* 320-bit input bit string created from concatenated vectors
|
||||
* CS_IV || CS_IN || CS_PV
|
||||
*/
|
||||
memcpy(input_bit_string, pv, 16);
|
||||
memcpy(input_bit_string + 16, in, 8);
|
||||
memcpy(input_bit_string + 24, iv, 16);
|
||||
|
||||
/* Generate seed material (SM) */
|
||||
rc = ble_ll_cs_drbg_f8(input_bit_string, sm);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Generate K_DRBG and V_DRBG */
|
||||
memset(key, 0, 16);
|
||||
memset(nonce_v, 0, 16);
|
||||
rc = ble_ll_cs_drbg_f9(sm, key, nonce_v);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Random bit generation function CS_DRBG
|
||||
* - transaction_id - CSTransactionID,
|
||||
* - drbg_ctx - the drbg context, already inited with keys,
|
||||
* - output - output buffer,
|
||||
* - len - number of bytes to be generated.
|
||||
*/
|
||||
int
|
||||
ble_ll_cs_drbg_rand(struct ble_ll_cs_drbg_ctx *drbg_ctx, uint16_t step_count,
|
||||
uint8_t transaction_id, uint8_t *output, uint8_t len)
|
||||
{
|
||||
int rc;
|
||||
uint8_t rand_len = 0;
|
||||
uint8_t nonce[16];
|
||||
struct ble_ll_cs_transaction_cache *cache = &drbg_ctx->t_cache[transaction_id];
|
||||
|
||||
/* Set the fixed values of the DRGB nonce */
|
||||
memcpy(nonce, drbg_ctx->nonce_v, sizeof(nonce));
|
||||
/* Set the Transaction_Counter */
|
||||
if (cache->last_step_count != step_count) {
|
||||
cache->transaction_counter = 0;
|
||||
cache->last_step_count = step_count;
|
||||
}
|
||||
nonce[0] += cache->transaction_counter;
|
||||
/* Set the Transaction_Identifier */
|
||||
nonce[1] += transaction_id;
|
||||
/* Set the CS Step_Counter */
|
||||
put_le16(&nonce[2], step_count + get_le16(&nonce[2]));
|
||||
|
||||
while (len > 0) {
|
||||
if (cache->free_bytes > 0) {
|
||||
/* Use bytes from previous DRBG invocation */
|
||||
|
||||
if (len < cache->free_bytes) {
|
||||
rand_len = len;
|
||||
} else {
|
||||
rand_len = cache->free_bytes;
|
||||
}
|
||||
|
||||
cache->free_bytes -= rand_len;
|
||||
/* [0] is LSO, [15] is MSO. Return cached bytes starting from MSO. */
|
||||
memcpy(output, cache->random_bytes + cache->free_bytes, rand_len);
|
||||
|
||||
len -= rand_len;
|
||||
output += rand_len;
|
||||
} else {
|
||||
/* Invoke CS_DRBG to get fresh 128-bit sequence */
|
||||
rc = ble_ll_cs_drbg_e(drbg_ctx->key, nonce, cache->random_bytes);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
cache->free_bytes = sizeof(cache->random_bytes);
|
||||
/* Increment the transaction counter */
|
||||
++nonce[0];
|
||||
++cache->transaction_counter;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Channel Sounding random number generation function hr1 */
|
||||
int
|
||||
ble_ll_cs_drbg_rand_hr1(struct ble_ll_cs_drbg_ctx *drbg_ctx, uint16_t step_count,
|
||||
uint8_t transaction_id, uint8_t r, uint8_t *r_out)
|
||||
{
|
||||
int rc;
|
||||
uint16_t t_rand;
|
||||
uint8_t random_bits;
|
||||
|
||||
if (r <= 1) {
|
||||
*r_out = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = ble_ll_cs_drbg_rand(drbg_ctx, step_count, transaction_id, &random_bits, 1);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
t_rand = r * random_bits;
|
||||
|
||||
if ((t_rand & 0xFF) < (256 % r)) {
|
||||
rc = ble_ll_cs_drbg_rand(drbg_ctx, step_count, transaction_id,
|
||||
&random_bits, 1);
|
||||
*r_out = ((256 * random_bits * r) + t_rand) / 65536;
|
||||
} else {
|
||||
*r_out = t_rand / 256;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_cs_drbg_shuffle_cr1(struct ble_ll_cs_drbg_ctx *drbg_ctx, uint16_t step_count,
|
||||
uint8_t transaction_id, uint8_t *channel_array,
|
||||
uint8_t *shuffled_array, uint8_t len)
|
||||
{
|
||||
int rc;
|
||||
uint8_t i, j;
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
rc = ble_ll_cs_drbg_rand_hr1(drbg_ctx, step_count, transaction_id, i + 1, &j);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (i != j) {
|
||||
shuffled_array[i] = shuffled_array[j];
|
||||
}
|
||||
|
||||
shuffled_array[j] = channel_array[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
cs_autocorrelation_score(uint32_t sequence)
|
||||
{
|
||||
int c;
|
||||
uint32_t s, score = 0;
|
||||
uint8_t i, k;
|
||||
|
||||
for (k = 1; k <= 3; ++k) {
|
||||
c = 0;
|
||||
s = sequence;
|
||||
for (i = 1; i <= 32 - k; ++i) {
|
||||
c += (s & 1) ^ ((s >> k) & 1);
|
||||
s >>= 1;
|
||||
}
|
||||
score += abs(2 * c - (32 - k));
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_cs_drbg_generate_aa(struct ble_ll_cs_drbg_ctx *drbg_ctx, uint16_t step_count,
|
||||
uint32_t *initiator_aa, uint32_t *reflector_aa)
|
||||
{
|
||||
int rc;
|
||||
uint8_t buf[16];
|
||||
uint32_t s0, s1, s2, s3;
|
||||
|
||||
rc = ble_ll_cs_drbg_rand(drbg_ctx, step_count,
|
||||
BLE_LL_CS_DRBG_ACCESS_ADDRESS, buf, sizeof(buf));
|
||||
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* The buf[15] is the first generated octet */
|
||||
s0 = get_le32(&buf[12]);
|
||||
s1 = get_le32(&buf[8]);
|
||||
s2 = get_le32(&buf[4]);
|
||||
s3 = get_le32(&buf[0]);
|
||||
|
||||
/* The sequence with the lower autocorrelation score is selected
|
||||
* as the CS Access Address. See 2.2.1 Channel Sounding Access Address
|
||||
* selection rules.
|
||||
*/
|
||||
if (cs_autocorrelation_score(s0) < cs_autocorrelation_score(s1)) {
|
||||
*initiator_aa = s0;
|
||||
} else {
|
||||
*initiator_aa = s1;
|
||||
}
|
||||
|
||||
if (cs_autocorrelation_score(s2) < cs_autocorrelation_score(s3)) {
|
||||
*reflector_aa = s2;
|
||||
} else {
|
||||
*reflector_aa = s3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_cs_drbg_rand_marker_position(struct ble_ll_cs_drbg_ctx *drbg_ctx,
|
||||
uint16_t step_count, uint8_t rtt_type,
|
||||
uint8_t *position1, uint8_t *position2)
|
||||
{
|
||||
int rc;
|
||||
uint8_t rand_range;
|
||||
|
||||
if (rtt_type == BLE_LL_CS_RTT_32_BIT_SOUNDING_SEQUENCE) {
|
||||
rand_range = 29;
|
||||
} else { /* BLE_LL_CS_RTT_96_BIT_SOUNDING_SEQUENCE */
|
||||
rand_range = 64;
|
||||
}
|
||||
|
||||
rc = ble_ll_cs_drbg_rand_hr1(drbg_ctx, step_count,
|
||||
BLE_LL_CS_DRBG_SEQ_MARKER_POSITION,
|
||||
rand_range, position1);
|
||||
if (rc) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rtt_type == BLE_LL_CS_RTT_32_BIT_SOUNDING_SEQUENCE) {
|
||||
*position2 = 0xFF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = ble_ll_cs_drbg_rand_hr1(drbg_ctx, step_count,
|
||||
BLE_LL_CS_DRBG_SEQ_MARKER_POSITION, 75, position2);
|
||||
if (rc) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*position2 += 67;
|
||||
if (*position2 > 92) {
|
||||
/* Omit the second marker */
|
||||
*position2 = 0xFF;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_cs_drbg_rand_marker_selection(struct ble_ll_cs_drbg_ctx *drbg_ctx,
|
||||
uint8_t step_count, uint8_t *marker_selection)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (drbg_ctx->marker_selection_free_bits == 0) {
|
||||
rc = ble_ll_cs_drbg_rand(drbg_ctx, step_count, BLE_LL_CS_DRBG_SEQ_MARKER_SIGNAL,
|
||||
&drbg_ctx->marker_selection_cache, 1);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
drbg_ctx->marker_selection_free_bits = 8;
|
||||
}
|
||||
|
||||
*marker_selection = drbg_ctx->marker_selection_cache & 0x80;
|
||||
drbg_ctx->marker_selection_cache <<= 1;
|
||||
--drbg_ctx->marker_selection_free_bits;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_cs_drbg_rand_main_mode_steps(struct ble_ll_cs_drbg_ctx *drbg_ctx,
|
||||
uint8_t step_count, uint8_t main_mode_min_steps,
|
||||
uint8_t main_mode_max_steps,
|
||||
uint8_t *main_mode_steps)
|
||||
{
|
||||
int rc;
|
||||
uint8_t r;
|
||||
uint8_t r_out;
|
||||
|
||||
r = main_mode_max_steps - main_mode_min_steps + 1;
|
||||
rc = ble_ll_cs_drbg_rand_hr1(drbg_ctx, step_count,
|
||||
BLE_LL_CS_DRBG_SUBEVT_SUBMODE, r, &r_out);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
*main_mode_steps = r_out + main_mode_min_steps;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_ll_cs_drbg_apply_marker_signal(struct ble_ll_cs_drbg_ctx *drbg_ctx,
|
||||
uint8_t step_count, uint8_t *buf, uint8_t position)
|
||||
{
|
||||
int rc;
|
||||
uint16_t *byte_ptr;
|
||||
uint16_t marker_signal;
|
||||
uint8_t marker_selection;
|
||||
uint8_t byte_id = 0;
|
||||
uint8_t bit_offset = 0;
|
||||
|
||||
rc = ble_ll_cs_drbg_rand_marker_selection(drbg_ctx, step_count, &marker_selection);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (marker_selection) {
|
||||
/* '0011' in transmission order */
|
||||
marker_signal = 0b1100;
|
||||
} else {
|
||||
/* '1100' in transmission order */
|
||||
marker_signal = 0b0011;
|
||||
}
|
||||
|
||||
byte_id = position / 8;
|
||||
byte_ptr = (uint16_t *)&buf[byte_id];
|
||||
bit_offset = position % 8;
|
||||
*byte_ptr &= ~(0xF << bit_offset);
|
||||
*byte_ptr |= ~(marker_signal << bit_offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_ll_cs_generate_sounding_sequence(struct ble_ll_cs_drbg_ctx *drbg_ctx,
|
||||
uint8_t step_count, uint8_t rtt_type,
|
||||
uint8_t *buf, uint8_t sequence_len)
|
||||
{
|
||||
int rc;
|
||||
uint8_t i;
|
||||
uint8_t position1;
|
||||
uint8_t position2;
|
||||
|
||||
for (i = 0; i < sequence_len; ++i) {
|
||||
buf[i] = 0b10101010;
|
||||
}
|
||||
|
||||
rc = ble_ll_cs_drbg_rand_marker_position(drbg_ctx, step_count, rtt_type,
|
||||
&position1, &position2);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ble_ll_cs_drbg_apply_marker_signal(drbg_ctx, step_count, buf, position1);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (position2 != 0xFF) {
|
||||
rc = ble_ll_cs_drbg_apply_marker_signal(drbg_ctx, step_count, buf, position2);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_cs_drbg_generate_sync_sequence(struct ble_ll_cs_drbg_ctx *drbg_ctx,
|
||||
uint8_t step_count, uint8_t rtt_type,
|
||||
uint8_t *buf, uint8_t *sequence_len)
|
||||
{
|
||||
int rc = -1;
|
||||
|
||||
*sequence_len = rtt_seq_len[rtt_type];
|
||||
|
||||
switch (rtt_type) {
|
||||
case BLE_LL_CS_RTT_32_BIT_SOUNDING_SEQUENCE:
|
||||
rc = ble_ll_cs_generate_sounding_sequence(drbg_ctx, step_count,
|
||||
rtt_type, buf, *sequence_len);
|
||||
break;
|
||||
case BLE_LL_CS_RTT_96_BIT_SOUNDING_SEQUENCE:
|
||||
rc = ble_ll_cs_generate_sounding_sequence(drbg_ctx, step_count,
|
||||
rtt_type, buf, *sequence_len);
|
||||
break;
|
||||
case BLE_LL_CS_RTT_32_BIT_RANDOM_SEQUENCE:
|
||||
case BLE_LL_CS_RTT_64_BIT_RANDOM_SEQUENCE:
|
||||
case BLE_LL_CS_RTT_96_BIT_RANDOM_SEQUENCE:
|
||||
case BLE_LL_CS_RTT_128_BIT_RANDOM_SEQUENCE:
|
||||
rc = ble_ll_cs_drbg_rand(drbg_ctx, step_count,
|
||||
BLE_LL_CS_DRBG_RAND_SEQ_GENERATION, buf,
|
||||
*sequence_len);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_cs_drbg_rand_tone_ext_presence(struct ble_ll_cs_drbg_ctx *drbg_ctx,
|
||||
uint8_t step_count, uint8_t *presence)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (drbg_ctx->tone_ext_presence_free_bits == 0) {
|
||||
rc = ble_ll_cs_drbg_rand(drbg_ctx, step_count,
|
||||
BLE_LL_CS_DRBG_T_PM_TONE_SLOT_PRESENCE,
|
||||
&drbg_ctx->tone_ext_presence_cache, 1);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
drbg_ctx->tone_ext_presence_free_bits = 8;
|
||||
}
|
||||
|
||||
*presence = drbg_ctx->tone_ext_presence_cache & 0x80 ? 1 : 0;
|
||||
drbg_ctx->tone_ext_presence_cache <<= 1;
|
||||
--drbg_ctx->tone_ext_presence_free_bits;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_cs_drbg_rand_antenna_path_perm_id(struct ble_ll_cs_drbg_ctx *drbg_ctx,
|
||||
uint16_t step_count, uint8_t n_ap,
|
||||
uint8_t *ap_id)
|
||||
{
|
||||
int rc;
|
||||
uint8_t i;
|
||||
uint8_t n_ap_f = 0;
|
||||
|
||||
if (n_ap <= 1) {
|
||||
*ap_id = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(n_ap <= 4);
|
||||
|
||||
for (i = 1; i <= n_ap; ++i) {
|
||||
n_ap_f *= i;
|
||||
}
|
||||
|
||||
rc = ble_ll_cs_drbg_rand_hr1(drbg_ctx, step_count,
|
||||
BLE_LL_CS_DRBG_ANTENNA_PATH_PERMUTATION,
|
||||
n_ap_f, ap_id);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_cs_drbg_clear_cache(struct ble_ll_cs_drbg_ctx *drbg_ctx)
|
||||
{
|
||||
memset(drbg_ctx->t_cache, 0, sizeof(drbg_ctx->t_cache));
|
||||
drbg_ctx->marker_selection_cache = 0;
|
||||
drbg_ctx->marker_selection_free_bits = 0;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_cs_drbg_init(struct ble_ll_cs_drbg_ctx *drbg_ctx)
|
||||
{
|
||||
/* Calculate temporal key K and nonce vector V */
|
||||
return ble_ll_cs_drbg_h9(drbg_ctx->iv, drbg_ctx->in, drbg_ctx->pv,
|
||||
drbg_ctx->key, drbg_ctx->nonce_v);
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_cs_drbg_free(struct ble_ll_cs_drbg_ctx *drbg_ctx)
|
||||
{
|
||||
memset(drbg_ctx, 0, sizeof(*drbg_ctx));
|
||||
}
|
||||
#endif /* BLE_LL_CHANNEL_SOUNDING */
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_LL_CS_DRBG_PRIV
|
||||
#define H_BLE_LL_CS_DRBG_PRIV
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BLE_LL_CS_DRBG_HOP_CHAN_NON_MODE0 (0x00)
|
||||
#define BLE_LL_CS_DRBG_HOP_CHAN_MODE0 (0x01)
|
||||
#define BLE_LL_CS_DRBG_SUBEVT_SUBMODE (0x02)
|
||||
#define BLE_LL_CS_DRBG_T_PM_TONE_SLOT_PRESENCE (0x03)
|
||||
#define BLE_LL_CS_DRBG_ANTENNA_PATH_PERMUTATION (0x04)
|
||||
#define BLE_LL_CS_DRBG_ACCESS_ADDRESS (0x05)
|
||||
#define BLE_LL_CS_DRBG_SEQ_MARKER_POSITION (0x06)
|
||||
#define BLE_LL_CS_DRBG_SEQ_MARKER_SIGNAL (0x07)
|
||||
#define BLE_LL_CS_DRBG_RAND_SEQ_GENERATION (0x08)
|
||||
#define BLE_LL_CS_DRBG_BACKTRACKING_RESISTANCE (0x09)
|
||||
#define BLE_LL_CS_DRBG_TRANSACTION_IDS_NUMBER (0x0a)
|
||||
|
||||
#define BLE_LL_CS_RTT_AA_ONLY (0x00)
|
||||
#define BLE_LL_CS_RTT_32_BIT_SOUNDING_SEQUENCE (0x01)
|
||||
#define BLE_LL_CS_RTT_96_BIT_SOUNDING_SEQUENCE (0x02)
|
||||
#define BLE_LL_CS_RTT_32_BIT_RANDOM_SEQUENCE (0x03)
|
||||
#define BLE_LL_CS_RTT_64_BIT_RANDOM_SEQUENCE (0x04)
|
||||
#define BLE_LL_CS_RTT_96_BIT_RANDOM_SEQUENCE (0x05)
|
||||
#define BLE_LL_CS_RTT_128_BIT_RANDOM_SEQUENCE (0x06)
|
||||
|
||||
struct ble_ll_cs_transaction_cache {
|
||||
uint16_t last_step_count;
|
||||
/* 1-octet CSTransactionCounter per each CS Transaction ID. Should
|
||||
* be reset each time the nonce V CS Step_Counter field is set to
|
||||
* a new value.
|
||||
*/
|
||||
uint8_t transaction_counter;
|
||||
/* Random bits cache */
|
||||
uint8_t random_bytes[16];
|
||||
/* The number of cached bytes that have been already used */
|
||||
uint8_t free_bytes;
|
||||
};
|
||||
|
||||
/* DRBG context */
|
||||
struct ble_ll_cs_drbg_ctx {
|
||||
/* Initialization vector, entropy input */
|
||||
uint8_t iv[16];
|
||||
/* Instantiation nonce */
|
||||
uint8_t in[8];
|
||||
/* Personalization vector/string */
|
||||
uint8_t pv[16];
|
||||
/* Temporal key K */
|
||||
uint8_t key[16];
|
||||
/* DRBG nonce/counter (V), the starting value from which the DRBG operates.
|
||||
* Initialized once per LE Connection.
|
||||
*/
|
||||
uint8_t nonce_v[16];
|
||||
/* Cache bits generated with single DRBG transation */
|
||||
struct ble_ll_cs_transaction_cache t_cache[BLE_LL_CS_DRBG_TRANSACTION_IDS_NUMBER];
|
||||
|
||||
uint8_t marker_selection_free_bits;
|
||||
uint8_t marker_selection_cache;
|
||||
|
||||
uint8_t tone_ext_presence_free_bits;
|
||||
uint8_t tone_ext_presence_cache;
|
||||
};
|
||||
|
||||
int ble_ll_cs_drbg_e(const uint8_t *key, const uint8_t *data, uint8_t *out_data);
|
||||
int ble_ll_cs_drbg_f7(const uint8_t *k, const uint8_t *in, uint8_t len, uint8_t *out);
|
||||
int ble_ll_cs_drbg_f8(const uint8_t *input, uint8_t *sm);
|
||||
int ble_ll_cs_drbg_f9(const uint8_t *sm, uint8_t *k, uint8_t *v);
|
||||
int ble_ll_cs_drbg_h9(const uint8_t *iv, const uint8_t *in, const uint8_t *pv,
|
||||
uint8_t *key, uint8_t *nonce_v);
|
||||
int ble_ll_cs_drbg_rand(struct ble_ll_cs_drbg_ctx *drbg_ctx, uint16_t step_count,
|
||||
uint8_t transaction_id, uint8_t *output, uint8_t len);
|
||||
int ble_ll_cs_drbg_rand_hr1(struct ble_ll_cs_drbg_ctx *drbg_ctx, uint16_t step_count,
|
||||
uint8_t transaction_id, uint8_t r, uint8_t *r_out);
|
||||
int ble_ll_cs_drbg_shuffle_cr1(struct ble_ll_cs_drbg_ctx *drbg_ctx, uint16_t step_count,
|
||||
uint8_t transaction_id, uint8_t *channel_array,
|
||||
uint8_t *shuffled_array, uint8_t len);
|
||||
int ble_ll_cs_drbg_generate_aa(struct ble_ll_cs_drbg_ctx *drbg_ctx, uint16_t step_count,
|
||||
uint32_t *initiator_aa, uint32_t *reflector_aa);
|
||||
int ble_ll_cs_drbg_rand_marker_position(struct ble_ll_cs_drbg_ctx *drbg_ctx,
|
||||
uint16_t step_count, uint8_t rtt_type,
|
||||
uint8_t *position1, uint8_t *position2);
|
||||
int ble_ll_cs_drbg_rand_marker_selection(struct ble_ll_cs_drbg_ctx *drbg_ctx,
|
||||
uint8_t step_count,
|
||||
uint8_t *marker_selection);
|
||||
int ble_ll_cs_drbg_rand_main_mode_steps(struct ble_ll_cs_drbg_ctx *drbg_ctx,
|
||||
uint8_t step_count, uint8_t main_mode_min_steps,
|
||||
uint8_t main_mode_max_steps,
|
||||
uint8_t *main_mode_steps);
|
||||
int ble_ll_cs_drbg_generate_sync_sequence(struct ble_ll_cs_drbg_ctx *drbg_ctx,
|
||||
uint8_t step_count, uint8_t rtt_type,
|
||||
uint8_t *buf, uint8_t *sequence_len);
|
||||
int ble_ll_cs_drbg_rand_antenna_path_perm_id(struct ble_ll_cs_drbg_ctx *drbg_ctx,
|
||||
uint16_t step_count, uint8_t n_ap,
|
||||
uint8_t *ap_id);
|
||||
int ble_ll_cs_drbg_rand_tone_ext_presence(struct ble_ll_cs_drbg_ctx *drbg_ctx,
|
||||
uint8_t step_count, uint8_t *presence);
|
||||
int ble_ll_cs_drbg_init(struct ble_ll_cs_drbg_ctx *drbg_ctx);
|
||||
void ble_ll_cs_drbg_free(struct ble_ll_cs_drbg_ctx *drbg_ctx);
|
||||
void ble_ll_cs_drbg_clear_cache(struct ble_ll_cs_drbg_ctx *drbg_ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_LL_CS_DRBG_PRIV */
|
||||
Reference in New Issue
Block a user