mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #5841 from ARMmbed/release-candidate
Release candidate for mbed-os-5.7.3pull/5952/merge mbed_lib_rev158
commit
96d9a00d0a
|
@ -28,7 +28,7 @@ The [release notes](https://os.mbed.com/releases) detail the current release. Yo
|
||||||
|
|
||||||
## Getting started for developers
|
## Getting started for developers
|
||||||
|
|
||||||
We have a [developer webiste](https://os.mbed.com) for asking questions, engaging with others, finding information on boards and components, using an online IDE and compiler, reading the documentation and learning about what's new and what's coming next in Mbed OS.
|
We have a [developer website](https://os.mbed.com) for asking questions, engaging with others, finding information on boards and components, using an online IDE and compiler, reading the documentation and learning about what's new and what's coming next in Mbed OS.
|
||||||
|
|
||||||
## Getting started for contributors
|
## Getting started for contributors
|
||||||
|
|
||||||
|
|
|
@ -51,13 +51,17 @@ extern uint32_t SystemCoreClock;
|
||||||
* For K64F DELTA = (80000 / 120000000) * 1000000 = 666[us]
|
* For K64F DELTA = (80000 / 120000000) * 1000000 = 666[us]
|
||||||
* For NUCLEO_F070RB DELTA = (80000 / 48000000) * 1000000 = 1666[us]
|
* For NUCLEO_F070RB DELTA = (80000 / 48000000) * 1000000 = 1666[us]
|
||||||
* For NRF51_DK DELTA = (80000 / 16000000) * 1000000 = 5000[us]
|
* For NRF51_DK DELTA = (80000 / 16000000) * 1000000 = 5000[us]
|
||||||
|
*
|
||||||
|
* As low power timer cannot be too much accurate, this DELTA should not be more precise than 500us,
|
||||||
|
* which corresponds to a maximum CPU clock around 130MHz
|
||||||
*/
|
*/
|
||||||
#define US_PER_SEC 1000000
|
#define US_PER_SEC 1000000
|
||||||
#define US_PER_MSEC 1000
|
#define US_PER_MSEC 1000
|
||||||
#define TOLERANCE_FACTOR 80000.0f
|
#define TOLERANCE_FACTOR 80000.0f
|
||||||
#define US_FACTOR 1000000.0f
|
#define US_FACTOR 1000000.0f
|
||||||
|
#define CLOCK_MAX 130000000
|
||||||
|
|
||||||
static const int delta_sys_clk_us = ((int) (TOLERANCE_FACTOR / (float) SystemCoreClock * US_FACTOR));
|
static const int delta_sys_clk_us = (SystemCoreClock < CLOCK_MAX? ((int) (TOLERANCE_FACTOR / (float) SystemCoreClock * US_FACTOR)):((int) (TOLERANCE_FACTOR / (float) CLOCK_MAX * US_FACTOR)));
|
||||||
|
|
||||||
/* When test performs time measurement using Timer in sequence, then measurement error accumulates
|
/* When test performs time measurement using Timer in sequence, then measurement error accumulates
|
||||||
* in the successive attempts. */
|
* in the successive attempts. */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
|
* Copyright (c) 2013-2017, ARM Limited, All Rights Reserved
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
@ -28,15 +28,27 @@
|
||||||
#error [NOT_SUPPORTED] test not supported
|
#error [NOT_SUPPORTED] test not supported
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace utest::v1;
|
using utest::v1::Case;
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* Helper functions and data structures */
|
/* Helper functions and data structures */
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
#define THREAD_STACK_SIZE 384
|
||||||
|
#define NUM_TEST_THREADS 3
|
||||||
|
|
||||||
|
template<osPriority PRIORITY, uint32_t STACK_SIZE>
|
||||||
|
class TestThread : public Thread {
|
||||||
|
uint8_t stack[STACK_SIZE];
|
||||||
|
public:
|
||||||
|
TestThread() : Thread(PRIORITY, STACK_SIZE, stack) { }
|
||||||
|
};
|
||||||
|
|
||||||
// This structure keeps data about the various memory allocation operations,
|
// This structure keeps data about the various memory allocation operations,
|
||||||
// as traced by 'test_trace_cb' below.
|
// as traced by 'test_trace_cb' below.
|
||||||
#define TEST_MAX_MEMORY_OPS 10
|
#define TEST_MAX_MEMORY_OPS 10
|
||||||
|
|
||||||
// Trace results for all possible operations
|
// Trace results for all possible operations
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t op;
|
uint8_t op;
|
||||||
|
@ -58,24 +70,28 @@ typedef struct {
|
||||||
} free_info;
|
} free_info;
|
||||||
};
|
};
|
||||||
} mem_trace_data_t;
|
} mem_trace_data_t;
|
||||||
|
|
||||||
// Memory operation statistics
|
// Memory operation statistics
|
||||||
typedef struct {
|
typedef struct {
|
||||||
mem_trace_data_t op_data[TEST_MAX_MEMORY_OPS];
|
mem_trace_data_t op_data[TEST_MAX_MEMORY_OPS];
|
||||||
uint32_t total_ops;
|
uint32_t total_ops;
|
||||||
bool invalid_op, overflow;
|
bool invalid_op, overflow;
|
||||||
} stats_t;
|
} stats_t;
|
||||||
|
|
||||||
static stats_t stats;
|
static stats_t stats;
|
||||||
|
|
||||||
|
|
||||||
// Clear all the memory statistics
|
// Clear all the memory statistics
|
||||||
static void test_clear_stats() {
|
static void test_clear_stats()
|
||||||
|
{
|
||||||
memset(&stats, 0, sizeof(stats));
|
memset(&stats, 0, sizeof(stats));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Memory tracer callback that records each operation in "stats" (above)
|
// Memory tracer callback that records each operation in "stats" (above)
|
||||||
extern "C" void test_trace_cb(uint8_t op, void *res, void *caller, ...) {
|
extern "C" void test_trace_cb(uint8_t op, void *res, void *caller, ...)
|
||||||
|
{
|
||||||
va_list va;
|
va_list va;
|
||||||
mem_trace_data_t *pmem = stats.op_data + stats.total_ops;
|
mem_trace_data_t *pmem = stats.op_data + stats.total_ops;
|
||||||
|
|
||||||
if (stats.total_ops >= TEST_MAX_MEMORY_OPS) {
|
if (stats.total_ops >= TEST_MAX_MEMORY_OPS) {
|
||||||
stats.overflow = true;
|
stats.overflow = true;
|
||||||
return;
|
return;
|
||||||
|
@ -110,180 +126,305 @@ extern "C" void test_trace_cb(uint8_t op, void *res, void *caller, ...) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic sanity checks for the tracer
|
// Generic sanity checks for the tracer
|
||||||
static void check_sanity(uint32_t expected_ops) {
|
static void check_sanity(uint32_t expected_ops)
|
||||||
|
{
|
||||||
TEST_ASSERT_FALSE(stats.overflow);
|
TEST_ASSERT_FALSE(stats.overflow);
|
||||||
TEST_ASSERT_FALSE(stats.invalid_op);
|
TEST_ASSERT_FALSE(stats.invalid_op);
|
||||||
TEST_ASSERT_EQUAL_UINT32(stats.total_ops, expected_ops);
|
TEST_ASSERT_EQUAL_UINT32(expected_ops, stats.total_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check a "malloc" operation
|
// Check a "malloc" operation
|
||||||
static void check_malloc_op(const mem_trace_data_t *p, void *expected_res, size_t expected_arg_size) {
|
static void check_malloc_op(const mem_trace_data_t *p, void *expected_res, size_t expected_arg_size)
|
||||||
TEST_ASSERT_EQUAL_UINT8(p->op, MBED_MEM_TRACE_MALLOC);
|
{
|
||||||
TEST_ASSERT_EQUAL_PTR(p->res, expected_res);
|
TEST_ASSERT_EQUAL_UINT8(MBED_MEM_TRACE_MALLOC, p->op);
|
||||||
TEST_ASSERT_EQUAL_UINT32(p->malloc_info.arg_size, expected_arg_size);
|
TEST_ASSERT_EQUAL_PTR(expected_res, p->res);
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(expected_arg_size, p->malloc_info.arg_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check a "free" operation
|
// Check a "free" operation
|
||||||
static void check_free_op(const mem_trace_data_t *p, void *expected_arg_ptr) {
|
static void check_free_op(const mem_trace_data_t *p, void *expected_arg_ptr)
|
||||||
TEST_ASSERT_EQUAL_UINT8(p->op, MBED_MEM_TRACE_FREE);
|
{
|
||||||
TEST_ASSERT_EQUAL_PTR(p->free_info.arg_ptr, expected_arg_ptr);
|
TEST_ASSERT_EQUAL_UINT8(MBED_MEM_TRACE_FREE, p->op);
|
||||||
|
TEST_ASSERT_EQUAL_PTR(expected_arg_ptr, p->free_info.arg_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check a "realloc" operation
|
// Check a "realloc" operation
|
||||||
static void check_realloc_op(const mem_trace_data_t *p, void *expected_res, void *expected_arg_ptr, size_t expected_arg_size) {
|
static void check_realloc_op(const mem_trace_data_t *p, void *expected_res, void *expected_arg_ptr, size_t expected_arg_size)
|
||||||
TEST_ASSERT_EQUAL_UINT8(p->op, MBED_MEM_TRACE_REALLOC);
|
{
|
||||||
TEST_ASSERT_EQUAL_PTR(p->res, expected_res);
|
TEST_ASSERT_EQUAL_UINT8(MBED_MEM_TRACE_REALLOC, p->op);
|
||||||
TEST_ASSERT_EQUAL_UINT32(p->realloc_info.arg_ptr, expected_arg_ptr);
|
TEST_ASSERT_EQUAL_PTR(expected_res, p->res);
|
||||||
TEST_ASSERT_EQUAL_UINT32(p->realloc_info.arg_size, expected_arg_size);
|
TEST_ASSERT_EQUAL_UINT32(expected_arg_ptr, p->realloc_info.arg_ptr);
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(expected_arg_size, p->realloc_info.arg_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check a "calloc" operation
|
// Check a "calloc" operation
|
||||||
static void check_calloc_op(const mem_trace_data_t *p, void *expected_res, size_t expected_arg_nmemb, size_t expected_arg_size) {
|
static void check_calloc_op(const mem_trace_data_t *p, void *expected_res, size_t expected_arg_nmemb, size_t expected_arg_size)
|
||||||
TEST_ASSERT_EQUAL_UINT8(p->op, MBED_MEM_TRACE_CALLOC);
|
{
|
||||||
TEST_ASSERT_EQUAL_PTR(p->res, expected_res);
|
TEST_ASSERT_EQUAL_UINT8(MBED_MEM_TRACE_CALLOC, p->op);
|
||||||
TEST_ASSERT_EQUAL_UINT32(p->calloc_info.arg_nmemb, expected_arg_nmemb);
|
TEST_ASSERT_EQUAL_PTR(expected_res, p->res);
|
||||||
TEST_ASSERT_EQUAL_UINT32(p->calloc_info.arg_size, expected_arg_size);
|
TEST_ASSERT_EQUAL_UINT32(expected_arg_nmemb, p->calloc_info.arg_nmemb);
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(expected_arg_size, p->calloc_info.arg_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
// Memory tracer callback to test thread safety
|
||||||
/* Tests */
|
extern "C" void test_trace_cb_multithread(uint8_t op, void *res, void *caller, ...)
|
||||||
/******************************************************************************/
|
{
|
||||||
|
volatile static int trace_guard = 0;
|
||||||
|
trace_guard++;
|
||||||
|
TEST_ASSERT_TRUE_MESSAGE(trace_guard == 1, "Race condition occurred !!!!");
|
||||||
|
trace_guard--;
|
||||||
|
}
|
||||||
|
|
||||||
// Allocate a single buffer, then free it. Check that tracing matches the operations.
|
// Thread function
|
||||||
static void test_case_single_malloc_free() {
|
void malloc_free(volatile bool *thread_continue)
|
||||||
|
{
|
||||||
|
const size_t block_size = 126;
|
||||||
|
|
||||||
|
while(*thread_continue) {
|
||||||
|
void *p = malloc(block_size);
|
||||||
|
TEST_ASSERT_NOT_EQUAL(p, NULL);
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Test single malloc/free tracing
|
||||||
|
*
|
||||||
|
* Given a memory trace mechanism
|
||||||
|
* When perform single memory allocation/deallocation using malloc/free
|
||||||
|
* Then tracing matches the operations
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void test_case_single_malloc_free()
|
||||||
|
{
|
||||||
|
const uint32_t num_op = 2;
|
||||||
const size_t block_size = 126;
|
const size_t block_size = 126;
|
||||||
const mem_trace_data_t *pmem = stats.op_data;
|
const mem_trace_data_t *pmem = stats.op_data;
|
||||||
|
|
||||||
test_clear_stats();
|
test_clear_stats();
|
||||||
mbed_mem_trace_set_callback(test_trace_cb);
|
mbed_mem_trace_set_callback(test_trace_cb);
|
||||||
|
|
||||||
// Allocate a single memory block
|
// Allocate a single memory block
|
||||||
void *p = malloc(block_size);
|
void *p = malloc(block_size);
|
||||||
TEST_ASSERT_NOT_EQUAL(p, NULL);
|
TEST_ASSERT_NOT_EQUAL(p, NULL);
|
||||||
|
|
||||||
// Free the memory block
|
// Free the memory block
|
||||||
free(p);
|
free(p);
|
||||||
|
|
||||||
// Stop tracing
|
// Stop tracing
|
||||||
mbed_mem_trace_set_callback(NULL);
|
mbed_mem_trace_set_callback(NULL);
|
||||||
|
|
||||||
// Check tracer result
|
// Check tracer result
|
||||||
check_sanity(2);
|
check_sanity(num_op);
|
||||||
check_malloc_op(pmem ++, p, block_size);
|
check_malloc_op(pmem++, p, block_size);
|
||||||
check_free_op(pmem, p);
|
check_free_op(pmem, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test all memory operations (malloc, realloc, free, calloc)
|
|
||||||
static void test_case_all_memory_ops() {
|
/** Test all memory operations (malloc, realloc, free, calloc) tracing
|
||||||
|
*
|
||||||
|
* Given a memory trace mechanism
|
||||||
|
* When perform all memory operations
|
||||||
|
* Then tracing matches the operations
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void test_case_all_memory_ops()
|
||||||
|
{
|
||||||
|
const uint32_t num_op = 5;
|
||||||
const size_t malloc_size = 40, realloc_size = 80, nmemb = 25, size = 10;
|
const size_t malloc_size = 40, realloc_size = 80, nmemb = 25, size = 10;
|
||||||
const mem_trace_data_t *pmem = stats.op_data;
|
const mem_trace_data_t *pmem = stats.op_data;
|
||||||
|
|
||||||
test_clear_stats();
|
test_clear_stats();
|
||||||
mbed_mem_trace_set_callback(test_trace_cb);
|
mbed_mem_trace_set_callback(test_trace_cb);
|
||||||
|
|
||||||
// Allocate a single memory block, the realloc it
|
// Allocate a single memory block, the realloc it
|
||||||
void *p_malloc = malloc(malloc_size);
|
void *p_malloc = malloc(malloc_size);
|
||||||
TEST_ASSERT_NOT_EQUAL(p_malloc, NULL);
|
TEST_ASSERT_NOT_EQUAL(p_malloc, NULL);
|
||||||
void *p_realloc = realloc(p_malloc, realloc_size);
|
void *p_realloc = realloc(p_malloc, realloc_size);
|
||||||
TEST_ASSERT_NOT_EQUAL(p_realloc, NULL);
|
TEST_ASSERT_NOT_EQUAL(p_realloc, NULL);
|
||||||
|
|
||||||
// Use calloc() now
|
// Use calloc() now
|
||||||
void *p_calloc = calloc(nmemb, size);
|
void *p_calloc = calloc(nmemb, size);
|
||||||
//TEST_ASSERT_NOT_EQUAL(p_calloc, NULL);
|
TEST_ASSERT_NOT_EQUAL(p_calloc, NULL);
|
||||||
|
|
||||||
// Free the realloc() pointer first, then the calloc() one
|
// Free the realloc() pointer first, then the calloc() one
|
||||||
free(p_realloc);
|
free(p_realloc);
|
||||||
free(p_calloc);
|
free(p_calloc);
|
||||||
|
|
||||||
// Stop tracing
|
// Stop tracing
|
||||||
mbed_mem_trace_set_callback(NULL);
|
mbed_mem_trace_set_callback(NULL);
|
||||||
|
|
||||||
// Check tracer result
|
// Check tracer result
|
||||||
check_sanity(6);
|
check_sanity(num_op);
|
||||||
check_malloc_op(pmem ++, p_malloc, malloc_size);
|
check_malloc_op(pmem++, p_malloc, malloc_size);
|
||||||
check_realloc_op(pmem ++, p_realloc, p_malloc, realloc_size);
|
check_realloc_op(pmem++, p_realloc, p_malloc, realloc_size);
|
||||||
// calloc() calls malloc() internally
|
check_calloc_op(pmem++, p_calloc, nmemb, size);
|
||||||
check_malloc_op(pmem ++, p_calloc, nmemb * size);
|
check_free_op(pmem++, p_realloc);
|
||||||
check_calloc_op(pmem ++, p_calloc, nmemb, size);
|
|
||||||
check_free_op(pmem ++, p_realloc);
|
|
||||||
check_free_op(pmem, p_calloc);
|
check_free_op(pmem, p_calloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that tracing is off when using a NULL callback
|
|
||||||
static void test_case_trace_off() {
|
/** Test that tracing is off when using a NULL callback
|
||||||
|
*
|
||||||
|
* Given a memory trace mechanism
|
||||||
|
* When tracing is turned off
|
||||||
|
* Then performed memory operations doesn't report any tracing
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void test_case_trace_off()
|
||||||
|
{
|
||||||
|
const uint32_t num_op = 0;
|
||||||
const size_t malloc_size = 10;
|
const size_t malloc_size = 10;
|
||||||
|
|
||||||
test_clear_stats();
|
test_clear_stats();
|
||||||
// We don't want any tracing
|
// We don't want any tracing
|
||||||
mbed_mem_trace_set_callback(NULL);
|
mbed_mem_trace_set_callback(NULL);
|
||||||
|
|
||||||
// Allocate a buffer and free it
|
// Allocate a buffer and free it
|
||||||
void *p_malloc = malloc(malloc_size);
|
void *p_malloc = malloc(malloc_size);
|
||||||
TEST_ASSERT_NOT_EQUAL(p_malloc, NULL);
|
TEST_ASSERT_NOT_EQUAL(p_malloc, NULL);
|
||||||
free(p_malloc);
|
free(p_malloc);
|
||||||
|
|
||||||
// Check that we didn't trace anything
|
// Check that we didn't trace anything
|
||||||
check_sanity(0);
|
check_sanity(num_op);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test partial tracing (start tracing, stop tracing, restart later)
|
|
||||||
static void test_case_partial_trace() {
|
/** Test partial tracing
|
||||||
|
*
|
||||||
|
* Given a memory trace mechanism
|
||||||
|
* When perform memory operations while tracing is on then off and on again
|
||||||
|
* Then tracing report only part of operations
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void test_case_partial_trace()
|
||||||
|
{
|
||||||
|
const uint32_t num_op = 2;
|
||||||
const size_t malloc_size_1 = 20, malloc_size_2 = 30;
|
const size_t malloc_size_1 = 20, malloc_size_2 = 30;
|
||||||
const mem_trace_data_t *pmem = stats.op_data;
|
const mem_trace_data_t *pmem = stats.op_data;
|
||||||
|
|
||||||
test_clear_stats();
|
test_clear_stats();
|
||||||
|
|
||||||
// Start tracing
|
// Start tracing
|
||||||
mbed_mem_trace_set_callback(test_trace_cb);
|
mbed_mem_trace_set_callback(test_trace_cb);
|
||||||
|
|
||||||
// Allocate a buffer
|
// Allocate a buffer
|
||||||
void *p_malloc_1 = malloc(malloc_size_1);
|
void *p_malloc_1 = malloc(malloc_size_1);
|
||||||
TEST_ASSERT_NOT_EQUAL(p_malloc_1, NULL);
|
TEST_ASSERT_NOT_EQUAL(p_malloc_1, NULL);
|
||||||
|
|
||||||
// Disable tracing before freeing the first buffer
|
// Disable tracing before freeing the first buffer
|
||||||
mbed_mem_trace_set_callback(NULL);
|
mbed_mem_trace_set_callback(NULL);
|
||||||
free(p_malloc_1);
|
free(p_malloc_1);
|
||||||
|
|
||||||
// Allocate another buffer (still not traced)
|
// Allocate another buffer (still not traced)
|
||||||
void *p_malloc_2 = malloc(malloc_size_2);
|
void *p_malloc_2 = malloc(malloc_size_2);
|
||||||
TEST_ASSERT_NOT_EQUAL(p_malloc_2, NULL);
|
TEST_ASSERT_NOT_EQUAL(p_malloc_2, NULL);
|
||||||
|
|
||||||
// Re-enable tracing
|
// Re-enable tracing
|
||||||
mbed_mem_trace_set_callback(test_trace_cb);
|
mbed_mem_trace_set_callback(test_trace_cb);
|
||||||
|
|
||||||
// And free the second buffer (this operation should be tracer)
|
// And free the second buffer (this operation should be tracer)
|
||||||
free(p_malloc_2);
|
free(p_malloc_2);
|
||||||
|
|
||||||
// Stop tracing
|
// Stop tracing
|
||||||
mbed_mem_trace_set_callback(NULL);
|
mbed_mem_trace_set_callback(NULL);
|
||||||
|
|
||||||
// Check tracer result
|
// Check tracer result
|
||||||
check_sanity(2);
|
check_sanity(num_op);
|
||||||
check_malloc_op(pmem ++, p_malloc_1, malloc_size_1);
|
check_malloc_op(pmem++, p_malloc_1, malloc_size_1);
|
||||||
check_free_op(pmem, p_malloc_2);
|
check_free_op(pmem, p_malloc_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test new/delete tracing
|
|
||||||
static void test_case_new_delete() {
|
/** Test new/delete tracing
|
||||||
|
*
|
||||||
|
* Given a memory trace mechanism
|
||||||
|
* When memory allocation/deallocation is performed using new/delete
|
||||||
|
* Then tracing matches the operations
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void test_case_new_delete()
|
||||||
|
{
|
||||||
|
const uint32_t num_op = 4;
|
||||||
const mem_trace_data_t *pmem = stats.op_data;
|
const mem_trace_data_t *pmem = stats.op_data;
|
||||||
|
|
||||||
test_clear_stats();
|
test_clear_stats();
|
||||||
|
|
||||||
// Start tracing
|
// Start tracing
|
||||||
mbed_mem_trace_set_callback(test_trace_cb);
|
mbed_mem_trace_set_callback(test_trace_cb);
|
||||||
|
|
||||||
// Test new, new[], delete and delete[]
|
// Test new, new[], delete and delete[]
|
||||||
int *p_int = new int;
|
int *p_int = new int;
|
||||||
int *p_int_array = new int[10];
|
int *p_int_array = new int[10];
|
||||||
delete p_int;
|
delete p_int;
|
||||||
delete[] p_int_array;
|
delete[] p_int_array;
|
||||||
|
|
||||||
// Stop tracing
|
// Stop tracing
|
||||||
mbed_mem_trace_set_callback(NULL);
|
mbed_mem_trace_set_callback(NULL);
|
||||||
|
|
||||||
// Check tracer result
|
// Check tracer result
|
||||||
check_sanity(4);
|
check_sanity(num_op);
|
||||||
check_malloc_op(pmem ++, p_int, sizeof(int));
|
check_malloc_op(pmem++, p_int, sizeof(int));
|
||||||
check_malloc_op(pmem ++, p_int_array, 10 * sizeof(int));
|
check_malloc_op(pmem++, p_int_array, 10 * sizeof(int));
|
||||||
check_free_op(pmem ++, p_int);
|
check_free_op(pmem++, p_int);
|
||||||
check_free_op(pmem ++, p_int_array);
|
check_free_op(pmem, p_int_array);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Case cases[] = {
|
|
||||||
Case("single malloc/free", test_case_single_malloc_free),
|
/** Test tracing thread safety
|
||||||
Case("all memory operations", test_case_all_memory_ops),
|
*
|
||||||
Case("trace off", test_case_trace_off),
|
* Given a memory trace mechanism and multiple threads are started in parallel
|
||||||
Case("partial trace", test_case_partial_trace),
|
* When each of the threads perform memory allocation/deallocation (thus uses memory trace mechanisms)
|
||||||
Case("test new/delete", test_case_new_delete)
|
* Then tracing is protected against simultaneous multithreaded access
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void test_case_multithread_malloc_free()
|
||||||
|
{
|
||||||
|
const uint32_t wait_time_us = 10000;
|
||||||
|
volatile bool threads_continue;
|
||||||
|
TestThread<osPriorityNormal, THREAD_STACK_SIZE> threads[NUM_TEST_THREADS];
|
||||||
|
|
||||||
|
mbed_mem_trace_set_callback(test_trace_cb_multithread);
|
||||||
|
|
||||||
|
threads_continue = true;
|
||||||
|
for (int i = 0; i < NUM_TEST_THREADS; i++) {
|
||||||
|
threads[i].start(callback(malloc_free, &threads_continue));
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread::wait(wait_time_us);
|
||||||
|
threads_continue = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_TEST_THREADS; i++) {
|
||||||
|
threads[i].join();
|
||||||
|
}
|
||||||
|
|
||||||
|
mbed_mem_trace_set_callback(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static Case cases[] =
|
||||||
|
{
|
||||||
|
Case("Test single malloc/free trace", test_case_single_malloc_free),
|
||||||
|
Case("Test all memory operations trace", test_case_all_memory_ops),
|
||||||
|
Case("Test trace off", test_case_trace_off),
|
||||||
|
Case("Test partial trace", test_case_partial_trace),
|
||||||
|
Case("Test new/delete trace", test_case_new_delete),
|
||||||
|
Case("Test multithreaded trace", test_case_multithread_malloc_free)
|
||||||
};
|
};
|
||||||
|
|
||||||
static status_t greentea_test_setup(const size_t number_of_cases) {
|
static utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
|
||||||
GREENTEA_SETUP(20, "default_auto");
|
{
|
||||||
return greentea_test_setup_handler(number_of_cases);
|
GREENTEA_SETUP(15, "default_auto");
|
||||||
|
return utest::v1::greentea_test_setup_handler(number_of_cases);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
|
static utest::v1::Specification specification(greentea_test_setup, cases, utest::v1::greentea_test_teardown_handler);
|
||||||
|
|
||||||
int main() {
|
int main()
|
||||||
|
{
|
||||||
// Disable stdout buffering to prevent any unwanted allocations
|
// Disable stdout buffering to prevent any unwanted allocations
|
||||||
setvbuf(stdout, NULL, _IONBF, 0);
|
setvbuf(stdout, NULL, _IONBF, 0);
|
||||||
Harness::run(specification);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return !utest::v1::Harness::run(specification);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Description
|
||||||
|
|
||||||
|
This document describes how to run EMAC tests. The EMAC test cases are made using Ethernet Configuration Testing Protocol (CTP). To run the tests, one device in the Ethernet segment needs to be configured to be a CTP echo server. The devices running the test cases, use the echo server to forward the CTP Ethernet frames back.
|
||||||
|
|
||||||
|
# Configuring CTP echo server
|
||||||
|
|
||||||
|
A device can be configured to be a CTP echo server by enabling `echo-server` setting in the test environment's application `json` file. When device is configured to be a CTP echo server, it starts to forward CTP messages automatically after power up and will continue forwarding until power down.
|
||||||
|
|
||||||
|
# Test cases
|
||||||
|
|
||||||
|
## EMAC interface initialise
|
||||||
|
|
||||||
|
Initializes EMAC interface driver.
|
||||||
|
|
||||||
|
For WLAN installs test case so that it can intercept incoming Ethernet messages from the WLAN driver. Incoming CTP frames are handed by the test case and other frames are forwarded to the LWIP stack.
|
||||||
|
|
||||||
|
## EMAC interface broadcast
|
||||||
|
|
||||||
|
Sends three 100 byte CTP broadcast messages, waits for three seconds and sends three 50 byte CTP broadcast messages. Listens for the CTP echo server responses and stores the addresses of the echo servers if replies are received. The test case will pass if there are no responses from echo server, but further test cases will be skipped.
|
||||||
|
|
||||||
|
## EMAC interface unicast
|
||||||
|
|
||||||
|
Sends three CTP unicast messages to the CTP echo server. Verifies that all are replied.
|
||||||
|
|
||||||
|
## EMAC interface unicast frame length
|
||||||
|
|
||||||
|
Sends CTP unicast messages with Ethernet message length from 100 bytes to maximum. Verifies that all are replied.
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017, ARM Limited, All Rights Reserved
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* 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 "greentea-client/test_env.h"
|
||||||
|
#include "unity/unity.h"
|
||||||
|
#include "utest.h"
|
||||||
|
|
||||||
|
#if MBED_CONF_APP_TEST_WIFI || MBED_CONF_APP_TEST_ETHERNET
|
||||||
|
|
||||||
|
#include "mbed.h"
|
||||||
|
|
||||||
|
#include "lwip/opt.h" /* ETH_PAD_SIZE */
|
||||||
|
|
||||||
|
#include "emac_stack_mem.h"
|
||||||
|
#include "emac_api.h"
|
||||||
|
|
||||||
|
#include "emac_tests.h"
|
||||||
|
#include "emac_ctp.h"
|
||||||
|
|
||||||
|
#include "emac_initialize.h"
|
||||||
|
#include "emac_util.h"
|
||||||
|
#include "emac_membuf.h"
|
||||||
|
|
||||||
|
using namespace utest::v1;
|
||||||
|
|
||||||
|
// Unique identifier for message
|
||||||
|
static int receipt_number = 0;
|
||||||
|
|
||||||
|
static int emac_if_ctp_header_build(unsigned char *eth_frame, const unsigned char *dest_addr, const unsigned char *origin_addr, const unsigned char *forward_addr)
|
||||||
|
{
|
||||||
|
memcpy(ð_frame[0], dest_addr, 6);
|
||||||
|
memcpy(ð_frame[6], origin_addr, 6);
|
||||||
|
|
||||||
|
eth_frame[12] = 0x90; /* loop back */
|
||||||
|
eth_frame[13] = 0x00;
|
||||||
|
|
||||||
|
eth_frame[14] = 0x00; /* skip count */
|
||||||
|
eth_frame[15] = 0x00;
|
||||||
|
|
||||||
|
eth_frame[16] = 0x02; /* function, forward */
|
||||||
|
eth_frame[17] = 0x00;
|
||||||
|
|
||||||
|
memcpy(ð_frame[18], forward_addr, 6);
|
||||||
|
|
||||||
|
eth_frame[24] = 0x01; /* function, reply */
|
||||||
|
eth_frame[25] = 0x00;
|
||||||
|
|
||||||
|
receipt_number++;
|
||||||
|
|
||||||
|
eth_frame[26] = receipt_number; /* receipt number */
|
||||||
|
eth_frame[27] = receipt_number >> 8;
|
||||||
|
|
||||||
|
return receipt_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctp_function emac_if_ctp_header_handle(unsigned char *eth_input_frame, unsigned char *eth_output_frame, unsigned char *origin_addr, int *receipt_number)
|
||||||
|
{
|
||||||
|
if (eth_input_frame[12] != 0x90 || eth_input_frame[13] != 0x00) {
|
||||||
|
return CTP_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int skip_count = eth_input_frame[15] << 8 | eth_input_frame[14];
|
||||||
|
unsigned char *ethernet_ptr = ð_input_frame[16] + skip_count;
|
||||||
|
|
||||||
|
int function = ethernet_ptr[1] << 8 | ethernet_ptr[0];
|
||||||
|
ethernet_ptr += 2;
|
||||||
|
|
||||||
|
// Forward
|
||||||
|
if (function == 0x0002) {
|
||||||
|
memcpy(eth_output_frame, eth_input_frame, ETH_FRAME_HEADER_LEN);
|
||||||
|
// Update skip count
|
||||||
|
skip_count += 8;
|
||||||
|
eth_output_frame[14] = skip_count;
|
||||||
|
eth_output_frame[15] = skip_count >> 8;
|
||||||
|
// Set forward address to destination address
|
||||||
|
memcpy(ð_output_frame[0], ethernet_ptr, 6);
|
||||||
|
// Copy own address to origin
|
||||||
|
memcpy(ð_output_frame[6], origin_addr, 6);
|
||||||
|
return CTP_FORWARD;
|
||||||
|
// reply
|
||||||
|
} else if (function == 0x0001) {
|
||||||
|
*receipt_number = ethernet_ptr[1] << 8 | ethernet_ptr[0];
|
||||||
|
return CTP_REPLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CTP_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emac_if_ctp_msg_build(int eth_frame_len, const unsigned char *dest_addr, const unsigned char *origin_addr, const unsigned char *forward_addr)
|
||||||
|
{
|
||||||
|
if (eth_frame_len < ETH_FRAME_HEADER_LEN) {
|
||||||
|
eth_frame_len = ETH_FRAME_HEADER_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("message sent %x:%x:%x:%x:%x:%x\r\n\r\n", dest_addr[0], dest_addr[1], dest_addr[2], dest_addr[3], dest_addr[4], dest_addr[5]);
|
||||||
|
|
||||||
|
int outgoing_msg_index = emac_if_add_outgoing_msg(eth_frame_len);
|
||||||
|
|
||||||
|
if (outgoing_msg_index < 0) {
|
||||||
|
SET_ERROR_FLAGS(OUT_OF_MSG_DATA);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
emac_stack_mem_chain_t *mem_chain_p = emac_stack_mem_alloc(0, eth_frame_len + ETH_PAD_SIZE, 0);
|
||||||
|
|
||||||
|
if (!mem_chain_p) {
|
||||||
|
SET_ERROR_FLAGS(NO_FREE_MEM_BUF);
|
||||||
|
emac_if_free_outgoing_msg(outgoing_msg_index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(dest_addr, eth_mac_broadcast_addr, 6) == 0) {
|
||||||
|
emac_if_set_outgoing_msg_flags(outgoing_msg_index, BROADCAST);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char eth_output_frame_data[ETH_FRAME_HEADER_LEN];
|
||||||
|
int receipt_number = emac_if_ctp_header_build(eth_output_frame_data, dest_addr, origin_addr, forward_addr);
|
||||||
|
emac_if_set_outgoing_msg_receipt_num(outgoing_msg_index, receipt_number);
|
||||||
|
|
||||||
|
emac_if_memory_buffer_write(mem_chain_p, eth_output_frame_data, true);
|
||||||
|
|
||||||
|
//emac_if->ops.link_out(hw_driver, mem_chain_p);
|
||||||
|
emac_if_get()->ops.link_out(emac_if_get(), mem_chain_p);
|
||||||
|
|
||||||
|
emac_stack_mem_free(0, mem_chain_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017, ARM Limited, All Rights Reserved
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EMAC_CTP_H
|
||||||
|
#define EMAC_CTP_H
|
||||||
|
|
||||||
|
enum ctp_function {
|
||||||
|
CTP_NONE,
|
||||||
|
CTP_FORWARD,
|
||||||
|
CTP_REPLY
|
||||||
|
};
|
||||||
|
|
||||||
|
ctp_function emac_if_ctp_header_handle(unsigned char *eth_input_frame, unsigned char *eth_output_frame, unsigned char *origin_addr, int *receipt_number);
|
||||||
|
void emac_if_ctp_msg_build(int eth_frame_len, const unsigned char *dest_addr, const unsigned char *origin_addr, const unsigned char *forward_addr);
|
||||||
|
void emac_if_ctp_reply_handle(int lenght, int invalid_data_index);
|
||||||
|
|
||||||
|
#endif /* EMAC_CTP_H */
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017, ARM Limited, All Rights Reserved
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EMAC_INITIALIZE_H
|
||||||
|
#define EMAC_INITIALIZE_H
|
||||||
|
|
||||||
|
uint8_t *emac_if_get_hw_addr(void);
|
||||||
|
emac_interface_t *emac_if_get(void);
|
||||||
|
|
||||||
|
#endif /* EMAC_INITIALIZE_H */
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017, ARM Limited, All Rights Reserved
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* 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 "mbed.h"
|
||||||
|
#include "greentea-client/test_env.h"
|
||||||
|
#include "unity.h"
|
||||||
|
#include "utest.h"
|
||||||
|
|
||||||
|
#if MBED_CONF_APP_TEST_WIFI || MBED_CONF_APP_TEST_ETHERNET
|
||||||
|
|
||||||
|
#include "lwip/opt.h" /* ETH_PAD_SIZE */
|
||||||
|
|
||||||
|
#include "emac_api.h"
|
||||||
|
#include "emac_stack_mem.h"
|
||||||
|
|
||||||
|
#include "emac_membuf.h"
|
||||||
|
#include "emac_util.h"
|
||||||
|
|
||||||
|
int emac_if_memory_buffer_read(emac_stack_mem_chain_t *mem_chain_p, unsigned char *eth_frame)
|
||||||
|
{
|
||||||
|
int eth_frame_index = 0;
|
||||||
|
int invalid_data_index = 0;
|
||||||
|
int index = ETH_PAD_SIZE;
|
||||||
|
|
||||||
|
for (emac_stack_mem_t *mem_p = emac_stack_mem_chain_dequeue(0, &mem_chain_p); mem_p != NULL; mem_p = emac_stack_mem_chain_dequeue(0, &mem_chain_p)) {
|
||||||
|
unsigned char *buf_payload = (unsigned char *) emac_stack_mem_ptr(0, mem_p);
|
||||||
|
int buf_payload_len = emac_stack_mem_len(0, mem_p);
|
||||||
|
|
||||||
|
for (; index < buf_payload_len; index++) {
|
||||||
|
if (eth_frame_index < ETH_FRAME_HEADER_LEN) {
|
||||||
|
eth_frame[eth_frame_index] = buf_payload[index];
|
||||||
|
} else {
|
||||||
|
if (buf_payload[index] != (uint8_t) eth_frame_index) {
|
||||||
|
invalid_data_index = eth_frame_index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eth_frame_index++;
|
||||||
|
}
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return invalid_data_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emac_if_memory_buffer_write(emac_stack_mem_chain_t *mem_chain_p, unsigned char *eth_frame, bool write_data)
|
||||||
|
{
|
||||||
|
int eth_frame_index = 0;
|
||||||
|
int index = ETH_PAD_SIZE;
|
||||||
|
|
||||||
|
for (emac_stack_mem_t *mem_p = emac_stack_mem_chain_dequeue(0, &mem_chain_p); mem_p != NULL; mem_p = emac_stack_mem_chain_dequeue(0, &mem_chain_p)) {
|
||||||
|
unsigned char *buf_payload = (unsigned char *) emac_stack_mem_ptr(0, mem_p);
|
||||||
|
int buf_payload_len = emac_stack_mem_len(0, mem_p);
|
||||||
|
|
||||||
|
for (; index < buf_payload_len; index++) {
|
||||||
|
if (eth_frame_index < ETH_FRAME_HEADER_LEN) {
|
||||||
|
buf_payload[index] = eth_frame[eth_frame_index];
|
||||||
|
} else if (write_data) {
|
||||||
|
buf_payload[index] = (char) eth_frame_index;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
eth_frame_index++;
|
||||||
|
}
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017, ARM Limited, All Rights Reserved
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EMAC_MEMBUF_H
|
||||||
|
#define EMAC_MEMBUF_H
|
||||||
|
|
||||||
|
int emac_if_memory_buffer_read(emac_stack_mem_chain_t *mem_chain_p, unsigned char *eth_frame);
|
||||||
|
void emac_if_memory_buffer_write(emac_stack_mem_chain_t *mem_chain_p, unsigned char *eth_frame, bool write_data);
|
||||||
|
|
||||||
|
#endif /* EMAC_MEMBUF_H */
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017, ARM Limited, All Rights Reserved
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* 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 "mbed.h"
|
||||||
|
#include "greentea-client/test_env.h"
|
||||||
|
#include "unity.h"
|
||||||
|
#include "utest.h"
|
||||||
|
|
||||||
|
#if MBED_CONF_APP_TEST_WIFI || MBED_CONF_APP_TEST_ETHERNET
|
||||||
|
|
||||||
|
#include "emac_tests.h"
|
||||||
|
#include "emac_util.h"
|
||||||
|
#include "emac_ctp.h"
|
||||||
|
|
||||||
|
using namespace utest::v1;
|
||||||
|
|
||||||
|
void test_emac_broadcast_cb(void)
|
||||||
|
{
|
||||||
|
emac_if_validate_outgoing_msg();
|
||||||
|
|
||||||
|
static int counter = 0;
|
||||||
|
|
||||||
|
// Send three broadcast
|
||||||
|
if (counter < 3) {
|
||||||
|
emac_if_ctp_msg_build(100, eth_mac_broadcast_addr, emac_if_get_own_addr(), emac_if_get_own_addr());
|
||||||
|
counter++;
|
||||||
|
} else if (counter < 6) {
|
||||||
|
counter++;
|
||||||
|
} else if (counter < 9) {
|
||||||
|
emac_if_ctp_msg_build(50, eth_mac_broadcast_addr, emac_if_get_own_addr(), emac_if_get_own_addr());
|
||||||
|
counter++;
|
||||||
|
} else if (counter < 12) {
|
||||||
|
counter++;
|
||||||
|
} else if (counter == 12) {
|
||||||
|
emac_if_reset_outgoing_msg();
|
||||||
|
// ignore errors since just probing
|
||||||
|
RESET_ERROR_FLAGS;
|
||||||
|
#if MBED_CONF_APP_ECHO_SERVER
|
||||||
|
printf("echo server started successfully\r\n\r\n");
|
||||||
|
counter = 255;
|
||||||
|
#else
|
||||||
|
worker_loop_end();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_emac_broadcast(void)
|
||||||
|
{
|
||||||
|
RESET_ERROR_FLAGS;
|
||||||
|
SET_TRACE_LEVEL(TRACE_ETH_FRAMES | TRACE_SUCCESS | TRACE_FAILURE);
|
||||||
|
|
||||||
|
worker_loop_start(test_emac_broadcast_cb, 10 * SECOND_TO_MS);
|
||||||
|
|
||||||
|
PRINT_ERROR_FLAGS;
|
||||||
|
TEST_ASSERT_FALSE(ERROR_FLAGS);
|
||||||
|
RESET_OUTGOING_MSG_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017, ARM Limited, All Rights Reserved
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* 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 "mbed.h"
|
||||||
|
#include "greentea-client/test_env.h"
|
||||||
|
#include "unity.h"
|
||||||
|
#include "utest.h"
|
||||||
|
|
||||||
|
#if MBED_CONF_APP_TEST_WIFI || MBED_CONF_APP_TEST_ETHERNET
|
||||||
|
|
||||||
|
#include "inttypes.h"
|
||||||
|
|
||||||
|
#if MBED_CONF_APP_TEST_WIFI
|
||||||
|
#ifdef TARGET_UBLOX_EVK_ODIN_W2
|
||||||
|
#include "wifi_emac_api.h"
|
||||||
|
#include "OdinWiFiInterface.h"
|
||||||
|
#endif
|
||||||
|
#ifdef TARGET_REALTEK_RTL8195AM
|
||||||
|
#include "rtw_emac.h"
|
||||||
|
#include "RTWInterface.h"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "emac_api.h"
|
||||||
|
#include "emac_tests.h"
|
||||||
|
#include "emac_util.h"
|
||||||
|
|
||||||
|
using namespace utest::v1;
|
||||||
|
|
||||||
|
static unsigned char eth_mac_addr[ETH_MAC_ADDR_LEN];
|
||||||
|
|
||||||
|
static char emac_if_link_state_change_cb_data[] = "link_state_change_cb_data";
|
||||||
|
static char emac_if_link_input_cb_data[] = "link_input_cb_data";
|
||||||
|
|
||||||
|
static bool emac_if_init(void);
|
||||||
|
|
||||||
|
void test_emac_initialize()
|
||||||
|
{
|
||||||
|
#if MBED_CONF_APP_TEST_WIFI
|
||||||
|
static WiFiInterface *wifi;
|
||||||
|
|
||||||
|
#ifdef TARGET_UBLOX_EVK_ODIN_W2
|
||||||
|
wifi = new OdinWiFiInterface;
|
||||||
|
#endif
|
||||||
|
#ifdef TARGET_REALTEK_RTL8195AM
|
||||||
|
wifi = new RTWInterface;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MBED_CONF_APP_WIFI_SCAN
|
||||||
|
WiFiAccessPoint ap[30];
|
||||||
|
|
||||||
|
int size = wifi->scan(ap, 30);
|
||||||
|
|
||||||
|
for (int i=0; i<size; i++) {
|
||||||
|
const char *ssid = ap[i].get_ssid();
|
||||||
|
nsapi_security_t security = ap[i].get_security();
|
||||||
|
int8_t rssi = ap[i].get_rssi();
|
||||||
|
char ch = ap[i].get_channel();
|
||||||
|
|
||||||
|
printf("BS %i\r\n", i);
|
||||||
|
printf("ssid %s\r\n", ssid);
|
||||||
|
printf("security %i\r\n", security);
|
||||||
|
printf("rssi %i\r\n", rssi);
|
||||||
|
printf("ch %i\r\n\r\n", ch);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wifi->set_credentials(MBED_CONF_APP_WIFI_SSID, MBED_CONF_APP_WIFI_PASSWORD, MBED_CONF_APP_WIFI_SECURITY);
|
||||||
|
wifi->connect();
|
||||||
|
|
||||||
|
const char *ip_addr = wifi->get_ip_address();
|
||||||
|
printf("connected IP %s\r\n\r\n", ip_addr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TEST_ASSERT(emac_if_init());
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *emac_if_get_hw_addr(void)
|
||||||
|
{
|
||||||
|
return ð_mac_addr[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
emac_interface_t *emac_if_get(void)
|
||||||
|
{
|
||||||
|
#if MBED_CONF_APP_TEST_WIFI
|
||||||
|
#ifdef TARGET_UBLOX_EVK_ODIN_W2
|
||||||
|
return wifi_emac_get_interface();
|
||||||
|
#endif
|
||||||
|
#ifdef TARGET_REALTEK_RTL8195AM
|
||||||
|
return wlan_emac_init_interface();
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool emac_if_init(void)
|
||||||
|
{
|
||||||
|
emac_interface_t *emac_if = emac_if_get();
|
||||||
|
|
||||||
|
emac_if->ops.set_link_input_cb(emac_if, emac_if_link_input_cb, emac_if_link_input_cb_data);
|
||||||
|
emac_if->ops.set_link_state_cb(emac_if, emac_if_link_state_change_cb, emac_if_link_state_change_cb_data);
|
||||||
|
|
||||||
|
int hwaddr_len = emac_if->ops.get_hwaddr_size(emac_if);
|
||||||
|
printf("emac hwaddr length %i\r\n\r\n", hwaddr_len);
|
||||||
|
|
||||||
|
if (hwaddr_len == 6) {
|
||||||
|
emac_if->ops.get_hwaddr(emac_if, eth_mac_addr);
|
||||||
|
printf("emac hwaddr %x:%x:%x:%x:%x:%x\r\n\r\n", eth_mac_addr[0],eth_mac_addr[1],eth_mac_addr[2],eth_mac_addr[3],eth_mac_addr[4],eth_mac_addr[5]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mtu = emac_if->ops.get_mtu_size(emac_if);
|
||||||
|
printf("emac mtu %i\r\n\r\n", mtu);
|
||||||
|
|
||||||
|
char hw_name[11];
|
||||||
|
emac_if->ops.get_ifname(emac_if, hw_name, 10);
|
||||||
|
printf("emac if name %s\r\n\r\n", hw_name);
|
||||||
|
|
||||||
|
if (!emac_if->ops.power_up(emac_if)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017, ARM Limited, All Rights Reserved
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* 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 "mbed.h"
|
||||||
|
#include "greentea-client/test_env.h"
|
||||||
|
#include "unity.h"
|
||||||
|
#include "utest.h"
|
||||||
|
|
||||||
|
#if MBED_CONF_APP_TEST_WIFI || MBED_CONF_APP_TEST_ETHERNET
|
||||||
|
|
||||||
|
#include "emac_tests.h"
|
||||||
|
#include "emac_util.h"
|
||||||
|
#include "emac_ctp.h"
|
||||||
|
|
||||||
|
using namespace utest::v1;
|
||||||
|
|
||||||
|
void test_emac_unicast_cb(void)
|
||||||
|
{
|
||||||
|
emac_if_validate_outgoing_msg();
|
||||||
|
|
||||||
|
static uint8_t counter = 0;
|
||||||
|
|
||||||
|
// Send three unicast
|
||||||
|
if (counter < 3) {
|
||||||
|
emac_if_ctp_msg_build(100, emac_if_get_echo_server_addr(0), emac_if_get_own_addr(), emac_if_get_own_addr());
|
||||||
|
}
|
||||||
|
|
||||||
|
// End test
|
||||||
|
if (counter > 10) {
|
||||||
|
worker_loop_end();
|
||||||
|
|
||||||
|
if (emac_if_count_outgoing_msg() != 0) {
|
||||||
|
SET_ERROR_FLAGS(TEST_FAILED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_emac_unicast()
|
||||||
|
{
|
||||||
|
RESET_ERROR_FLAGS;
|
||||||
|
SET_TRACE_LEVEL(TRACE_ETH_FRAMES | TRACE_SUCCESS | TRACE_FAILURE);
|
||||||
|
|
||||||
|
if (emac_if_count_echo_server_addr()) {
|
||||||
|
worker_loop_start(test_emac_unicast_cb, 1 * SECOND_TO_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINT_ERROR_FLAGS;
|
||||||
|
TEST_ASSERT_FALSE(ERROR_FLAGS);
|
||||||
|
RESET_OUTGOING_MSG_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017, ARM Limited, All Rights Reserved
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* 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 "mbed.h"
|
||||||
|
#include "greentea-client/test_env.h"
|
||||||
|
#include "unity.h"
|
||||||
|
#include "utest.h"
|
||||||
|
|
||||||
|
#if MBED_CONF_APP_TEST_WIFI || MBED_CONF_APP_TEST_ETHERNET
|
||||||
|
|
||||||
|
#include "emac_tests.h"
|
||||||
|
#include "emac_util.h"
|
||||||
|
#include "emac_ctp.h"
|
||||||
|
|
||||||
|
using namespace utest::v1;
|
||||||
|
|
||||||
|
void test_emac_unicast_frame_len_cb(void)
|
||||||
|
{
|
||||||
|
emac_if_validate_outgoing_msg();
|
||||||
|
|
||||||
|
static uint32_t counter = 0;
|
||||||
|
|
||||||
|
// Send unicast to echo server
|
||||||
|
if (counter < 16) {
|
||||||
|
static uint32_t msg_len = 0;
|
||||||
|
|
||||||
|
emac_if_ctp_msg_build(msg_len, emac_if_get_echo_server_addr(0), emac_if_get_own_addr(), emac_if_get_own_addr());
|
||||||
|
|
||||||
|
msg_len += 100;
|
||||||
|
|
||||||
|
if (msg_len > 1514) {
|
||||||
|
msg_len = 1514;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (counter > 18) {
|
||||||
|
if (emac_if_count_outgoing_msg() == 0) {
|
||||||
|
worker_loop_end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_emac_unicast_frame_len()
|
||||||
|
{
|
||||||
|
RESET_ERROR_FLAGS;
|
||||||
|
SET_TRACE_LEVEL(TRACE_SUCCESS | TRACE_FAILURE);
|
||||||
|
|
||||||
|
if (emac_if_count_echo_server_addr()) {
|
||||||
|
worker_loop_start(test_emac_unicast_frame_len_cb, 1 * SECOND_TO_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINT_ERROR_FLAGS;
|
||||||
|
TEST_ASSERT_FALSE(ERROR_FLAGS);
|
||||||
|
RESET_OUTGOING_MSG_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017, ARM Limited, All Rights Reserved
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EMAC_TESTS_H
|
||||||
|
#define EMAC_TESTS_H
|
||||||
|
|
||||||
|
void test_emac_initialize();
|
||||||
|
void test_emac_broadcast();
|
||||||
|
void test_emac_unicast();
|
||||||
|
void test_emac_unicast_frame_len();
|
||||||
|
|
||||||
|
#endif /* EMAC_TESTS_H */
|
|
@ -0,0 +1,436 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017, ARM Limited, All Rights Reserved
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* 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 "mbed.h"
|
||||||
|
#include "greentea-client/test_env.h"
|
||||||
|
#include "unity.h"
|
||||||
|
#include "utest.h"
|
||||||
|
|
||||||
|
#if MBED_CONF_APP_TEST_WIFI || MBED_CONF_APP_TEST_ETHERNET
|
||||||
|
|
||||||
|
extern "C" { // netif input
|
||||||
|
#include "tcpip.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "emac_api.h"
|
||||||
|
#include "emac_stack_mem.h"
|
||||||
|
|
||||||
|
#include "emac_tests.h"
|
||||||
|
#include "emac_initialize.h"
|
||||||
|
#include "emac_util.h"
|
||||||
|
#include "emac_membuf.h"
|
||||||
|
#include "emac_ctp.h"
|
||||||
|
|
||||||
|
using namespace utest::v1;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int length;
|
||||||
|
int receipt_number;
|
||||||
|
unsigned short flags;
|
||||||
|
unsigned short lifetime;
|
||||||
|
} outgoing_msg_t;
|
||||||
|
|
||||||
|
#define ECHO_SERVER_COUNT 5
|
||||||
|
|
||||||
|
#define OUTGOING_MSG_COUNT 100
|
||||||
|
|
||||||
|
// Event flags
|
||||||
|
#define LINK_UP 0x01
|
||||||
|
#define LINK_DOWN 0x02
|
||||||
|
|
||||||
|
// Hook to lwip input function
|
||||||
|
extern struct netif *netif_list;
|
||||||
|
|
||||||
|
// Broadcast address
|
||||||
|
const unsigned char eth_mac_broadcast_addr[ETH_MAC_ADDR_LEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
|
||||||
|
|
||||||
|
// Event queue
|
||||||
|
static EventQueue worker_loop_event_queue;
|
||||||
|
static void worker_loop_event_cb(int event);
|
||||||
|
static Event<void(int)> worker_loop_event(&worker_loop_event_queue, worker_loop_event_cb);
|
||||||
|
static void link_input_event_cb(emac_stack_mem_chain_t *mem_chain_p);
|
||||||
|
static Event<void(emac_stack_mem_chain_t *)> link_input_event(&worker_loop_event_queue, link_input_event_cb);
|
||||||
|
|
||||||
|
// Found echo server addresses
|
||||||
|
static unsigned char eth_mac_echo_server_addr[ECHO_SERVER_COUNT][ETH_MAC_ADDR_LEN];
|
||||||
|
static int etc_mac_echo_server_free_index = 0;
|
||||||
|
|
||||||
|
// Outgoing messages
|
||||||
|
static outgoing_msg_t outgoing_msgs[OUTGOING_MSG_COUNT];
|
||||||
|
|
||||||
|
static unsigned int trace_level = 0;
|
||||||
|
static unsigned int error_flags = 0;
|
||||||
|
static unsigned int no_response_cnt = 0;
|
||||||
|
|
||||||
|
int emac_if_find_outgoing_msg(int receipt_number)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < OUTGOING_MSG_COUNT; i++) {
|
||||||
|
if (outgoing_msgs[i].length && outgoing_msgs[i].receipt_number == receipt_number) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emac_if_free_outgoing_msg(int index)
|
||||||
|
{
|
||||||
|
outgoing_msgs[index].length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int emac_if_count_outgoing_msg(void)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < OUTGOING_MSG_COUNT; i++) {
|
||||||
|
if (outgoing_msgs[i].length) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emac_if_reset_outgoing_msg(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < OUTGOING_MSG_COUNT; i++) {
|
||||||
|
if (outgoing_msgs[i].length) {
|
||||||
|
outgoing_msgs[i].length = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int emac_if_add_outgoing_msg(int length)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < OUTGOING_MSG_COUNT; i++) {
|
||||||
|
if (!outgoing_msgs[i].length) {
|
||||||
|
outgoing_msgs[i].receipt_number = 0;
|
||||||
|
outgoing_msgs[i].length = length;
|
||||||
|
outgoing_msgs[i].flags = 0;
|
||||||
|
outgoing_msgs[i].lifetime = 10;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emac_if_set_outgoing_msg_receipt_num(int index, int receipt_number)
|
||||||
|
{
|
||||||
|
outgoing_msgs[index].receipt_number = receipt_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emac_if_set_outgoing_msg_flags(int index, int flags)
|
||||||
|
{
|
||||||
|
outgoing_msgs[index].flags |= flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emac_if_timeout_outgoing_msg(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < OUTGOING_MSG_COUNT; i++) {
|
||||||
|
if (outgoing_msgs[i].length) {
|
||||||
|
if (outgoing_msgs[i].lifetime) {
|
||||||
|
outgoing_msgs[i].lifetime--;
|
||||||
|
if (outgoing_msgs[i].lifetime == 0) {
|
||||||
|
SET_ERROR_FLAGS(NO_RESPONSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void emac_if_validate_outgoing_msg(void)
|
||||||
|
{
|
||||||
|
static char broadcast_resp_count = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < OUTGOING_MSG_COUNT; i++) {
|
||||||
|
if (outgoing_msgs[i].length) {
|
||||||
|
|
||||||
|
if (outgoing_msgs[i].flags & RESPONSE_RECEIVED) {
|
||||||
|
|
||||||
|
int failure = outgoing_msgs[i].flags & (INVALID_LENGHT | INVALID_DATA);
|
||||||
|
|
||||||
|
if (failure) {
|
||||||
|
SET_ERROR_FLAGS(MSG_VALID_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(outgoing_msgs[i].flags & PRINTED)) {
|
||||||
|
if ((trace_level & TRACE_SUCCESS) || ((trace_level & TRACE_FAILURE) && failure)) {
|
||||||
|
printf("response: receipt number %i %s %s %s\r\n\r\n", outgoing_msgs[i].receipt_number,
|
||||||
|
outgoing_msgs[i].flags & INVALID_LENGHT ? "LENGTH INVALID" : "LENGTH OK",
|
||||||
|
outgoing_msgs[i].flags & INVALID_DATA ? "DATA INVALID" : "DATA OK",
|
||||||
|
outgoing_msgs[i].flags & BROADCAST ? "BROADCAST" : "UNICAST");
|
||||||
|
outgoing_msgs[i].flags |= PRINTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outgoing_msgs[i].flags & BROADCAST) {
|
||||||
|
outgoing_msgs[i].lifetime = 2;
|
||||||
|
broadcast_resp_count++;
|
||||||
|
if (broadcast_resp_count > 5) {
|
||||||
|
emac_if_free_outgoing_msg(i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emac_if_free_outgoing_msg(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!outgoing_msgs[i].lifetime) {
|
||||||
|
if (!(outgoing_msgs[i].flags & RESPONSE_RECEIVED) && (trace_level & TRACE_FAILURE)) {
|
||||||
|
printf("NO RESPONSE: receipt number %i\r\n\r\n", outgoing_msgs[i].receipt_number);
|
||||||
|
}
|
||||||
|
emac_if_free_outgoing_msg(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void emac_if_update_reply_to_outgoing_msg(int receipt_number, int lenght, int invalid_data_index)
|
||||||
|
{
|
||||||
|
int32_t outgoing_msg_index = emac_if_find_outgoing_msg(receipt_number);
|
||||||
|
|
||||||
|
if (outgoing_msg_index >= 0) {
|
||||||
|
outgoing_msgs[outgoing_msg_index].flags |= RESPONSE_RECEIVED;
|
||||||
|
|
||||||
|
#if MBED_CONF_APP_TEST_ETHERNET
|
||||||
|
if (outgoing_msgs[outgoing_msg_index].length < ETH_FRAME_MIN_LEN) {
|
||||||
|
if (lenght != ETH_FRAME_MIN_LEN) {
|
||||||
|
outgoing_msgs[outgoing_msg_index].flags |= INVALID_LENGHT;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
if (outgoing_msgs[outgoing_msg_index].length != lenght) {
|
||||||
|
outgoing_msgs[outgoing_msg_index].flags |= INVALID_LENGHT;
|
||||||
|
}
|
||||||
|
#if MBED_CONF_APP_TEST_ETHERNET
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (invalid_data_index && invalid_data_index < outgoing_msgs[outgoing_msg_index].length) {
|
||||||
|
outgoing_msgs[outgoing_msg_index].flags |= INVALID_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void emac_if_add_echo_server_addr(unsigned char *addr)
|
||||||
|
{
|
||||||
|
if (etc_mac_echo_server_free_index == ECHO_SERVER_COUNT) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < etc_mac_echo_server_free_index; i++) {
|
||||||
|
if (memcmp(ð_mac_echo_server_addr[i][0], addr, ETH_MAC_ADDR_LEN) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ð_mac_echo_server_addr[etc_mac_echo_server_free_index][0], addr, ETH_MAC_ADDR_LEN);
|
||||||
|
etc_mac_echo_server_free_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int emac_if_count_echo_server_addr(void)
|
||||||
|
{
|
||||||
|
return etc_mac_echo_server_free_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *emac_if_get_echo_server_addr(int index)
|
||||||
|
{
|
||||||
|
if (index < etc_mac_echo_server_free_index) {
|
||||||
|
return ð_mac_echo_server_addr[index][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emac_if_set_error_flags(unsigned int error_flags_value)
|
||||||
|
{
|
||||||
|
error_flags |= error_flags_value;
|
||||||
|
|
||||||
|
if (error_flags_value & NO_RESPONSE) {
|
||||||
|
no_response_cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int emac_if_get_error_flags(void)
|
||||||
|
{
|
||||||
|
int error_flags_value = error_flags;
|
||||||
|
|
||||||
|
// Indicate no response error only if more than three messages are lost
|
||||||
|
if (error_flags_value & NO_RESPONSE) {
|
||||||
|
if (no_response_cnt < 3) {
|
||||||
|
error_flags_value &= ~NO_RESPONSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return error_flags_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emac_if_reset_error_flags(void)
|
||||||
|
{
|
||||||
|
error_flags = 0;
|
||||||
|
no_response_cnt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emac_if_print_error_flags(void)
|
||||||
|
{
|
||||||
|
int error_flags_value = emac_if_get_error_flags();
|
||||||
|
|
||||||
|
char no_resp_message[50];
|
||||||
|
if (error_flags_value & NO_RESPONSE) {
|
||||||
|
snprintf(no_resp_message, 50, "no response from echo server, counter: %i", no_response_cnt);
|
||||||
|
} else if (no_response_cnt > 0) {
|
||||||
|
printf("no response from echo server, counter: %i\r\n\r\n", no_response_cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("test result: %s%s%s%s%s%s\r\n\r\n",
|
||||||
|
error_flags_value ? "Test FAILED, reason: ": "PASS",
|
||||||
|
error_flags_value & TEST_FAILED ? "test failed ": "",
|
||||||
|
error_flags_value & MSG_VALID_ERROR ? "message content validation error ": "",
|
||||||
|
error_flags_value & OUT_OF_MSG_DATA ? "out of message validation data storage ": "",
|
||||||
|
error_flags_value & NO_FREE_MEM_BUF ? "no free memory buffers ": "",
|
||||||
|
error_flags_value & NO_RESPONSE ? no_resp_message: "");
|
||||||
|
}
|
||||||
|
|
||||||
|
void emac_if_set_trace_level(char trace_level_value)
|
||||||
|
{
|
||||||
|
trace_level = trace_level_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emac_if_trace_to_ascii_hex_dump(const char *prefix, int len, unsigned char *data)
|
||||||
|
{
|
||||||
|
int line_len = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
if ((line_len % 14) == 0) {
|
||||||
|
if (line_len != 0) {
|
||||||
|
printf("\r\n");
|
||||||
|
}
|
||||||
|
printf("%s %06x", prefix, line_len);
|
||||||
|
}
|
||||||
|
line_len++;
|
||||||
|
printf(" %02x", data[i]);
|
||||||
|
}
|
||||||
|
printf("\r\n\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void emac_if_link_state_change_cb(void *data, bool up)
|
||||||
|
{
|
||||||
|
if (up) {
|
||||||
|
worker_loop_event.post(LINK_UP);
|
||||||
|
} else {
|
||||||
|
worker_loop_event.post(LINK_DOWN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void emac_if_link_input_cb(void *data, emac_stack_mem_chain_t *mem_chain_p)
|
||||||
|
{
|
||||||
|
link_input_event.post(mem_chain_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void link_input_event_cb(emac_stack_mem_chain_t *mem_chain_p)
|
||||||
|
{
|
||||||
|
int lenght = emac_stack_mem_len(0, mem_chain_p);
|
||||||
|
|
||||||
|
if (lenght >= ETH_FRAME_HEADER_LEN) {
|
||||||
|
// Ethernet input frame
|
||||||
|
unsigned char eth_input_frame_data[ETH_FRAME_HEADER_LEN];
|
||||||
|
memset(eth_input_frame_data, 0, ETH_FRAME_HEADER_LEN);
|
||||||
|
|
||||||
|
int invalid_data_index = emac_if_memory_buffer_read(mem_chain_p, eth_input_frame_data);
|
||||||
|
|
||||||
|
if (eth_input_frame_data[12] == 0x90 && eth_input_frame_data[13] == 0x00) {
|
||||||
|
unsigned char eth_output_frame_data[ETH_FRAME_HEADER_LEN];
|
||||||
|
int receipt_number;
|
||||||
|
|
||||||
|
ctp_function function = emac_if_ctp_header_handle(eth_input_frame_data, eth_output_frame_data, emac_if_get_hw_addr(), &receipt_number);
|
||||||
|
|
||||||
|
if (function == CTP_REPLY) {
|
||||||
|
emac_if_update_reply_to_outgoing_msg(receipt_number, lenght, invalid_data_index);
|
||||||
|
#if MBED_CONF_APP_ECHO_SERVER
|
||||||
|
// Echoes only if configured as echo server
|
||||||
|
} else if (function == CTP_FORWARD) {
|
||||||
|
emac_if_memory_buffer_write(mem_chain_p, eth_output_frame_data, false);
|
||||||
|
emac_if_get()->ops.link_out(emac_if_get(), mem_chain_p);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
emac_if_add_echo_server_addr(ð_input_frame_data[6]);
|
||||||
|
|
||||||
|
emac_stack_mem_free(0, mem_chain_p);
|
||||||
|
|
||||||
|
if (trace_level & TRACE_ETH_FRAMES) {
|
||||||
|
printf("LEN %i\r\n\r\n", lenght);
|
||||||
|
const char trace_type[] = "INP>";
|
||||||
|
emac_if_trace_to_ascii_hex_dump(trace_type, ETH_FRAME_HEADER_LEN, eth_input_frame_data);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forward other than CTP frames to lwip
|
||||||
|
struct netif *netif;
|
||||||
|
|
||||||
|
/* loop through netif's */
|
||||||
|
netif = netif_list;
|
||||||
|
if (netif != NULL) {
|
||||||
|
struct pbuf *p = (struct pbuf *)mem_chain_p;
|
||||||
|
|
||||||
|
/* pass all packets to ethernet_input, which decides what packets it supports */
|
||||||
|
if (netif->input(p, netif) != ERR_OK) {
|
||||||
|
emac_stack_mem_free(0, mem_chain_p);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emac_stack_mem_free(0, mem_chain_p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void worker_loop_start(void (*test_step_cb_fnc)(void), int timeout)
|
||||||
|
{
|
||||||
|
int test_step_cb_timer = worker_loop_event_queue.call_every(timeout, test_step_cb_fnc);
|
||||||
|
int timeout_outgoing_msg_timer = worker_loop_event_queue.call_every(1000, emac_if_timeout_outgoing_msg);
|
||||||
|
|
||||||
|
#if MBED_CONF_APP_ECHO_SERVER
|
||||||
|
worker_loop_event_queue.dispatch_forever();
|
||||||
|
#else
|
||||||
|
worker_loop_event_queue.dispatch(600 * SECOND_TO_MS);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
worker_loop_event_queue.cancel(test_step_cb_timer);
|
||||||
|
worker_loop_event_queue.cancel(timeout_outgoing_msg_timer);
|
||||||
|
|
||||||
|
worker_loop_event_queue.dispatch(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void worker_loop_event_cb(int event)
|
||||||
|
{
|
||||||
|
if (event == LINK_UP) {
|
||||||
|
printf("cable connected\r\n\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event == LINK_DOWN) {
|
||||||
|
printf("cable disconnected\r\n\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void worker_loop_end(void)
|
||||||
|
{
|
||||||
|
worker_loop_event_queue.break_dispatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *emac_if_get_own_addr(void)
|
||||||
|
{
|
||||||
|
return (emac_if_get_hw_addr());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017, ARM Limited, All Rights Reserved
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EMAC_UTIL_H
|
||||||
|
#define EMAC_UTIL_H
|
||||||
|
|
||||||
|
#define SECOND_TO_US 1000000
|
||||||
|
#define SECOND_TO_MS 1000
|
||||||
|
#define MS_TO_US 1000
|
||||||
|
|
||||||
|
extern const unsigned char eth_mac_broadcast_addr[];
|
||||||
|
|
||||||
|
// Trace flags
|
||||||
|
#define TRACE_ETH_FRAMES 0x01
|
||||||
|
#define TRACE_SUCCESS 0x02
|
||||||
|
#define TRACE_FAILURE 0x04
|
||||||
|
#define SET_TRACE_LEVEL(level) emac_if_set_trace_level(level)
|
||||||
|
|
||||||
|
// Message validation flags
|
||||||
|
#define BROADCAST 0x01
|
||||||
|
#define RESPONSE_RECEIVED 0x02
|
||||||
|
#define INVALID_LENGHT 0x04
|
||||||
|
#define INVALID_DATA 0x08
|
||||||
|
#define PRINTED 0x10
|
||||||
|
|
||||||
|
#define RESET_OUTGOING_MSG_DATA emac_if_reset_outgoing_msg()
|
||||||
|
|
||||||
|
// General error flags
|
||||||
|
#define TEST_FAILED 0x01
|
||||||
|
#define MSG_VALID_ERROR 0x02
|
||||||
|
#define OUT_OF_MSG_DATA 0x04
|
||||||
|
#define NO_FREE_MEM_BUF 0x08
|
||||||
|
#define NO_RESPONSE 0x10
|
||||||
|
|
||||||
|
#define ERROR_FLAGS emac_if_get_error_flags()
|
||||||
|
#define RESET_ERROR_FLAGS emac_if_reset_error_flags()
|
||||||
|
#define PRINT_ERROR_FLAGS emac_if_print_error_flags()
|
||||||
|
#define SET_ERROR_FLAGS(flags) emac_if_set_error_flags(flags)
|
||||||
|
|
||||||
|
#define ETH_FRAME_HEADER_LEN 28
|
||||||
|
#define ETH_FRAME_MIN_LEN 60
|
||||||
|
#define ETH_MAC_ADDR_LEN 6
|
||||||
|
|
||||||
|
int emac_if_find_outgoing_msg(int receipt_number);
|
||||||
|
void emac_if_free_outgoing_msg(int index);
|
||||||
|
int emac_if_count_outgoing_msg(void);
|
||||||
|
void emac_if_reset_outgoing_msg(void);
|
||||||
|
int emac_if_add_outgoing_msg(int length);
|
||||||
|
void emac_if_timeout_outgoing_msg(void);
|
||||||
|
void emac_if_validate_outgoing_msg(void);
|
||||||
|
void emac_if_set_outgoing_msg_receipt_num(int index, int receipt_number);
|
||||||
|
void emac_if_set_outgoing_msg_flags(int index, int flags);
|
||||||
|
|
||||||
|
void emac_if_add_echo_server_addr(unsigned char *addr);
|
||||||
|
int emac_if_count_echo_server_addr(void);
|
||||||
|
unsigned char *emac_if_get_echo_server_addr(int index);
|
||||||
|
|
||||||
|
void emac_if_set_error_flags(unsigned int error_flags_value);
|
||||||
|
unsigned int emac_if_get_error_flags(void);
|
||||||
|
void emac_if_reset_error_flags(void);
|
||||||
|
void emac_if_print_error_flags(void);
|
||||||
|
|
||||||
|
void emac_if_set_trace_level(char trace_level_value);
|
||||||
|
|
||||||
|
void emac_if_trace_to_ascii_hex_dump(const char *prefix, int len, char *data);
|
||||||
|
|
||||||
|
void emac_if_link_state_change_cb(void *data, bool up);
|
||||||
|
|
||||||
|
unsigned char *emac_if_get_own_addr(void);
|
||||||
|
|
||||||
|
extern void emac_if_link_input_cb(void *data, void *mem_chain_p);
|
||||||
|
extern void emac_if_link_state_change_cb(void *data, bool up);
|
||||||
|
|
||||||
|
void worker_loop_start(void (*test_step_cb_fnc)(void), int timeout);
|
||||||
|
void worker_loop_end(void);
|
||||||
|
|
||||||
|
void emac_if_init_main_thread(void);
|
||||||
|
|
||||||
|
#endif /* EMAC_UTIL_H */
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017, ARM Limited, All Rights Reserved
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(MBED_CONF_APP_TEST_WIFI) || \
|
||||||
|
!defined(MBED_CONF_APP_TEST_ETHERNET) || \
|
||||||
|
!defined(MBED_CONF_APP_ECHO_SERVER) || \
|
||||||
|
!defined(MBED_CONF_APP_WIFI_SCAN) || \
|
||||||
|
!defined(MBED_CONF_APP_WIFI_SSID ) || \
|
||||||
|
!defined(MBED_CONF_APP_WIFI_SECURITY) || \
|
||||||
|
!defined(MBED_CONF_APP_WIFI_PASSWORD)
|
||||||
|
#error [NOT_SUPPORTED] Requires parameters from mbed_app.json
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !MBED_CONF_APP_TEST_WIFI && !MBED_CONF_APP_TEST_ETHERNET
|
||||||
|
#error [NOT_SUPPORTED] Either wifi or ethernet testing need to be enabled
|
||||||
|
#endif
|
||||||
|
#if MBED_CONF_APP_TEST_WIFI
|
||||||
|
#if !defined(TARGET_UBLOX_EVK_ODIN_W2) && !defined(TARGET_REALTEK_RTL8195AM)
|
||||||
|
#error [NOT_SUPPORTED] Tests are valid only for UBLOX_EVK_ODIN_W2 and REALTEK_RTL8195AM
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if MBED_CONF_APP_TEST_ETHERNET
|
||||||
|
#error [NOT_SUPPORTED] Ethernet testing not supported
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "greentea-client/test_env.h"
|
||||||
|
#include "unity/unity.h"
|
||||||
|
#include "utest.h"
|
||||||
|
|
||||||
|
#include "emac_tests.h"
|
||||||
|
#include "emac_util.h"
|
||||||
|
|
||||||
|
using namespace utest::v1;
|
||||||
|
|
||||||
|
// Test setup
|
||||||
|
utest::v1::status_t test_setup(const size_t number_of_cases) {
|
||||||
|
#if !MBED_CONF_APP_ECHO_SERVER
|
||||||
|
GREENTEA_SETUP(600, "default_auto");
|
||||||
|
#endif
|
||||||
|
return verbose_test_setup_handler(number_of_cases);
|
||||||
|
}
|
||||||
|
|
||||||
|
Case cases[] = {
|
||||||
|
Case("EMAC interface initialize", test_emac_initialize),
|
||||||
|
Case("EMAC interface broadcast", test_emac_broadcast),
|
||||||
|
Case("EMAC interface unicast", test_emac_unicast),
|
||||||
|
Case("EMAC interface unicast frame length", test_emac_unicast_frame_len),
|
||||||
|
Case("EMAC interface broadcast (run again)", test_emac_broadcast)
|
||||||
|
};
|
||||||
|
|
||||||
|
Specification specification(test_setup, cases);
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
return !Harness::run(specification);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"test-ethernet": {
|
||||||
|
"help": "Enable ethernet testing",
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
"test-wifi": {
|
||||||
|
"help": "Enable wifi testing",
|
||||||
|
"value": 1
|
||||||
|
},
|
||||||
|
"echo-server": {
|
||||||
|
"help": "Build test to be echo server",
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
"wifi-scan": {
|
||||||
|
"help": "Scan and list access points",
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
"wifi-ssid": {
|
||||||
|
"help": "WiFi SSID for network",
|
||||||
|
"value": "\"SSID\""
|
||||||
|
},
|
||||||
|
"wifi-security": {
|
||||||
|
"help": "WiFi Security",
|
||||||
|
"value": "NSAPI_SECURITY_WPA_WPA2"
|
||||||
|
},
|
||||||
|
"wifi-password": {
|
||||||
|
"help": "WiFi Password",
|
||||||
|
"value": "\"PASSWORD\""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,9 +28,10 @@ SingletonPtr<PlatformMutex> I2C::_mutex;
|
||||||
|
|
||||||
I2C::I2C(PinName sda, PinName scl) :
|
I2C::I2C(PinName sda, PinName scl) :
|
||||||
#if DEVICE_I2C_ASYNCH
|
#if DEVICE_I2C_ASYNCH
|
||||||
_irq(this), _usage(DMA_USAGE_NEVER),
|
_irq(this), _usage(DMA_USAGE_NEVER), _deep_sleep_locked(false),
|
||||||
#endif
|
#endif
|
||||||
_i2c(), _hz(100000) {
|
_i2c(), _hz(100000)
|
||||||
|
{
|
||||||
// No lock needed in the constructor
|
// No lock needed in the constructor
|
||||||
|
|
||||||
// The init function also set the frequency to 100000
|
// The init function also set the frequency to 100000
|
||||||
|
@ -133,7 +134,7 @@ int I2C::transfer(int address, const char *tx_buffer, int tx_length, char *rx_bu
|
||||||
unlock();
|
unlock();
|
||||||
return -1; // transaction ongoing
|
return -1; // transaction ongoing
|
||||||
}
|
}
|
||||||
sleep_manager_lock_deep_sleep();
|
lock_deep_sleep();
|
||||||
aquire();
|
aquire();
|
||||||
|
|
||||||
_callback = callback;
|
_callback = callback;
|
||||||
|
@ -148,7 +149,7 @@ void I2C::abort_transfer(void)
|
||||||
{
|
{
|
||||||
lock();
|
lock();
|
||||||
i2c_abort_asynch(&_i2c);
|
i2c_abort_asynch(&_i2c);
|
||||||
sleep_manager_unlock_deep_sleep();
|
unlock_deep_sleep();
|
||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,11 +160,26 @@ void I2C::irq_handler_asynch(void)
|
||||||
_callback.call(event);
|
_callback.call(event);
|
||||||
}
|
}
|
||||||
if (event) {
|
if (event) {
|
||||||
sleep_manager_unlock_deep_sleep();
|
unlock_deep_sleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void I2C::lock_deep_sleep()
|
||||||
|
{
|
||||||
|
if (_deep_sleep_locked == false) {
|
||||||
|
sleep_manager_lock_deep_sleep();
|
||||||
|
_deep_sleep_locked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2C::unlock_deep_sleep()
|
||||||
|
{
|
||||||
|
if (_deep_sleep_locked == true) {
|
||||||
|
sleep_manager_unlock_deep_sleep();
|
||||||
|
_deep_sleep_locked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -176,11 +176,19 @@ public:
|
||||||
/** Abort the on-going I2C transfer
|
/** Abort the on-going I2C transfer
|
||||||
*/
|
*/
|
||||||
void abort_transfer();
|
void abort_transfer();
|
||||||
protected:
|
|
||||||
|
protected:
|
||||||
|
/** Lock deep sleep only if it is not yet locked */
|
||||||
|
void lock_deep_sleep();
|
||||||
|
|
||||||
|
/** Unlock deep sleep only if it has been locked */
|
||||||
|
void unlock_deep_sleep();
|
||||||
|
|
||||||
void irq_handler_asynch(void);
|
void irq_handler_asynch(void);
|
||||||
event_callback_t _callback;
|
event_callback_t _callback;
|
||||||
CThunk<I2C> _irq;
|
CThunk<I2C> _irq;
|
||||||
DMAUsage _usage;
|
DMAUsage _usage;
|
||||||
|
bool _deep_sleep_locked;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -33,6 +33,7 @@ SPI::SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel) :
|
||||||
#if DEVICE_SPI_ASYNCH
|
#if DEVICE_SPI_ASYNCH
|
||||||
_irq(this),
|
_irq(this),
|
||||||
_usage(DMA_USAGE_NEVER),
|
_usage(DMA_USAGE_NEVER),
|
||||||
|
_deep_sleep_locked(false),
|
||||||
#endif
|
#endif
|
||||||
_bits(8),
|
_bits(8),
|
||||||
_mode(0),
|
_mode(0),
|
||||||
|
@ -140,7 +141,7 @@ int SPI::transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_
|
||||||
void SPI::abort_transfer()
|
void SPI::abort_transfer()
|
||||||
{
|
{
|
||||||
spi_abort_asynch(&_spi);
|
spi_abort_asynch(&_spi);
|
||||||
sleep_manager_unlock_deep_sleep();
|
unlock_deep_sleep();
|
||||||
#if TRANSACTION_QUEUE_SIZE_SPI
|
#if TRANSACTION_QUEUE_SIZE_SPI
|
||||||
dequeue_transaction();
|
dequeue_transaction();
|
||||||
#endif
|
#endif
|
||||||
|
@ -200,13 +201,29 @@ int SPI::queue_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, i
|
||||||
|
|
||||||
void SPI::start_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, unsigned char bit_width, const event_callback_t& callback, int event)
|
void SPI::start_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, unsigned char bit_width, const event_callback_t& callback, int event)
|
||||||
{
|
{
|
||||||
sleep_manager_lock_deep_sleep();
|
lock_deep_sleep();
|
||||||
_acquire();
|
_acquire();
|
||||||
_callback = callback;
|
_callback = callback;
|
||||||
_irq.callback(&SPI::irq_handler_asynch);
|
_irq.callback(&SPI::irq_handler_asynch);
|
||||||
spi_master_transfer(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, bit_width, _irq.entry(), event , _usage);
|
spi_master_transfer(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, bit_width, _irq.entry(), event , _usage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SPI::lock_deep_sleep()
|
||||||
|
{
|
||||||
|
if (_deep_sleep_locked == false) {
|
||||||
|
sleep_manager_lock_deep_sleep();
|
||||||
|
_deep_sleep_locked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPI::unlock_deep_sleep()
|
||||||
|
{
|
||||||
|
if (_deep_sleep_locked == true) {
|
||||||
|
sleep_manager_unlock_deep_sleep();
|
||||||
|
_deep_sleep_locked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if TRANSACTION_QUEUE_SIZE_SPI
|
#if TRANSACTION_QUEUE_SIZE_SPI
|
||||||
|
|
||||||
void SPI::start_transaction(transaction_t *data)
|
void SPI::start_transaction(transaction_t *data)
|
||||||
|
@ -230,7 +247,7 @@ void SPI::irq_handler_asynch(void)
|
||||||
{
|
{
|
||||||
int event = spi_irq_handler_asynch(&_spi);
|
int event = spi_irq_handler_asynch(&_spi);
|
||||||
if (_callback && (event & SPI_EVENT_ALL)) {
|
if (_callback && (event & SPI_EVENT_ALL)) {
|
||||||
sleep_manager_unlock_deep_sleep();
|
unlock_deep_sleep();
|
||||||
_callback.call(event & SPI_EVENT_ALL);
|
_callback.call(event & SPI_EVENT_ALL);
|
||||||
}
|
}
|
||||||
#if TRANSACTION_QUEUE_SIZE_SPI
|
#if TRANSACTION_QUEUE_SIZE_SPI
|
||||||
|
|
|
@ -246,6 +246,14 @@ protected:
|
||||||
*/
|
*/
|
||||||
void start_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, unsigned char bit_width, const event_callback_t& callback, int event);
|
void start_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, unsigned char bit_width, const event_callback_t& callback, int event);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** Lock deep sleep only if it is not yet locked */
|
||||||
|
void lock_deep_sleep();
|
||||||
|
|
||||||
|
/** Unlock deep sleep in case it is locked */
|
||||||
|
void unlock_deep_sleep();
|
||||||
|
|
||||||
|
|
||||||
#if TRANSACTION_QUEUE_SIZE_SPI
|
#if TRANSACTION_QUEUE_SIZE_SPI
|
||||||
|
|
||||||
/** Start a new transaction
|
/** Start a new transaction
|
||||||
|
@ -274,6 +282,7 @@ protected:
|
||||||
CThunk<SPI> _irq;
|
CThunk<SPI> _irq;
|
||||||
event_callback_t _callback;
|
event_callback_t _callback;
|
||||||
DMAUsage _usage;
|
DMAUsage _usage;
|
||||||
|
bool _deep_sleep_locked;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void aquire(void);
|
void aquire(void);
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#ifndef MBED_UUID_H__
|
#ifndef MBED_UUID_H__
|
||||||
#define MBED_UUID_H__
|
#define MBED_UUID_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
|
@ -26,27 +26,12 @@
|
||||||
namespace ble {
|
namespace ble {
|
||||||
namespace generic {
|
namespace generic {
|
||||||
|
|
||||||
// forward declarations
|
|
||||||
struct procedure_control_block_t;
|
|
||||||
struct discovery_control_block_t;
|
|
||||||
struct read_control_block_t;
|
|
||||||
struct write_control_block_t;
|
|
||||||
struct descriptor_discovery_control_block_t;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic implementation of the GattClient.
|
* Generic implementation of the GattClient.
|
||||||
* It requires a pal::GattClient injected at construction site.
|
* It requires a pal::GattClient injected at construction site.
|
||||||
* @attention: Not part of the public interface of BLE API.
|
* @attention: Not part of the public interface of BLE API.
|
||||||
*/
|
*/
|
||||||
class GenericGattClient : public GattClient {
|
class GenericGattClient : public GattClient {
|
||||||
|
|
||||||
// give access to control block classes
|
|
||||||
friend struct procedure_control_block_t;
|
|
||||||
friend struct discovery_control_block_t;
|
|
||||||
friend struct read_control_block_t;
|
|
||||||
friend struct write_control_block_t;
|
|
||||||
friend struct descriptor_discovery_control_block_t;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Create a GenericGattClient from a pal::GattClient
|
* Create a GenericGattClient from a pal::GattClient
|
||||||
|
@ -130,10 +115,16 @@ public:
|
||||||
virtual ble_error_t reset(void);
|
virtual ble_error_t reset(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
procedure_control_block_t* get_control_block(Gap::Handle_t connection);
|
struct ProcedureControlBlock;
|
||||||
const procedure_control_block_t* get_control_block(Gap::Handle_t connection) const;
|
struct DiscoveryControlBlock;
|
||||||
void insert_control_block(procedure_control_block_t* cb) const;
|
struct ReadControlBlock;
|
||||||
void remove_control_block(procedure_control_block_t* cb) const;
|
struct WriteControlBlock;
|
||||||
|
struct DescriptorDiscoveryControlBlock;
|
||||||
|
|
||||||
|
ProcedureControlBlock* get_control_block(Gap::Handle_t connection);
|
||||||
|
const ProcedureControlBlock* get_control_block(Gap::Handle_t connection) const;
|
||||||
|
void insert_control_block(ProcedureControlBlock* cb) const;
|
||||||
|
void remove_control_block(ProcedureControlBlock* cb) const;
|
||||||
|
|
||||||
void on_termination(Gap::Handle_t connection_handle);
|
void on_termination(Gap::Handle_t connection_handle);
|
||||||
void on_server_message_received(connection_handle_t, const pal::AttServerMessage&);
|
void on_server_message_received(connection_handle_t, const pal::AttServerMessage&);
|
||||||
|
@ -145,7 +136,8 @@ private:
|
||||||
|
|
||||||
pal::GattClient* const _pal_client;
|
pal::GattClient* const _pal_client;
|
||||||
ServiceDiscovery::TerminationCallback_t _termination_callback;
|
ServiceDiscovery::TerminationCallback_t _termination_callback;
|
||||||
mutable procedure_control_block_t* control_blocks;
|
mutable ProcedureControlBlock* control_blocks;
|
||||||
|
bool _is_reseting;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,14 +55,14 @@ enum procedure_type_t {
|
||||||
/*
|
/*
|
||||||
* Base class for a procedure control block
|
* Base class for a procedure control block
|
||||||
*/
|
*/
|
||||||
struct procedure_control_block_t {
|
struct GenericGattClient::ProcedureControlBlock {
|
||||||
/*
|
/*
|
||||||
* Base constructor for procedure control block.
|
* Base constructor for procedure control block.
|
||||||
*/
|
*/
|
||||||
procedure_control_block_t(procedure_type_t type, Gap::Handle_t handle) :
|
ProcedureControlBlock(procedure_type_t type, Gap::Handle_t handle) :
|
||||||
type(type), connection_handle(handle), next(NULL) { }
|
type(type), connection_handle(handle), next(NULL) { }
|
||||||
|
|
||||||
virtual ~procedure_control_block_t() { }
|
virtual ~ProcedureControlBlock() { }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Entry point of the control block stack machine.
|
* Entry point of the control block stack machine.
|
||||||
|
@ -74,23 +74,28 @@ struct procedure_control_block_t {
|
||||||
*/
|
*/
|
||||||
virtual void handle_timeout_error(GenericGattClient* client) = 0;
|
virtual void handle_timeout_error(GenericGattClient* client) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called when the procedure is aborted
|
||||||
|
*/
|
||||||
|
virtual void abort(GenericGattClient *client) = 0;
|
||||||
|
|
||||||
procedure_type_t type;
|
procedure_type_t type;
|
||||||
Gap::Handle_t connection_handle;
|
Gap::Handle_t connection_handle;
|
||||||
procedure_control_block_t* next;
|
ProcedureControlBlock* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Procedure control block for the discovery process.
|
* Procedure control block for the discovery process.
|
||||||
*/
|
*/
|
||||||
struct discovery_control_block_t : public procedure_control_block_t {
|
struct GenericGattClient::DiscoveryControlBlock : public ProcedureControlBlock {
|
||||||
discovery_control_block_t(
|
DiscoveryControlBlock(
|
||||||
Gap::Handle_t handle,
|
Gap::Handle_t handle,
|
||||||
ServiceDiscovery::ServiceCallback_t service_callback,
|
ServiceDiscovery::ServiceCallback_t service_callback,
|
||||||
ServiceDiscovery::CharacteristicCallback_t characteristic_callback,
|
ServiceDiscovery::CharacteristicCallback_t characteristic_callback,
|
||||||
UUID matching_service_uuid,
|
UUID matching_service_uuid,
|
||||||
UUID matching_characteristic_uuid
|
UUID matching_characteristic_uuid
|
||||||
) : procedure_control_block_t(COMPLETE_DISCOVERY_PROCEDURE, handle),
|
) : ProcedureControlBlock(COMPLETE_DISCOVERY_PROCEDURE, handle),
|
||||||
service_callback(service_callback),
|
service_callback(service_callback),
|
||||||
characteristic_callback(characteristic_callback),
|
characteristic_callback(characteristic_callback),
|
||||||
matching_service_uuid(matching_service_uuid),
|
matching_service_uuid(matching_service_uuid),
|
||||||
|
@ -99,7 +104,7 @@ struct discovery_control_block_t : public procedure_control_block_t {
|
||||||
done(false) {
|
done(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~discovery_control_block_t() {
|
virtual ~DiscoveryControlBlock() {
|
||||||
while(services_discovered) {
|
while(services_discovered) {
|
||||||
service_t* tmp = services_discovered->next;
|
service_t* tmp = services_discovered->next;
|
||||||
delete services_discovered;
|
delete services_discovered;
|
||||||
|
@ -111,6 +116,10 @@ struct discovery_control_block_t : public procedure_control_block_t {
|
||||||
terminate(client);
|
terminate(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void abort(GenericGattClient *client) {
|
||||||
|
terminate(client);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void handle(GenericGattClient* client, const AttServerMessage& message) {
|
virtual void handle(GenericGattClient* client, const AttServerMessage& message) {
|
||||||
// if end of discovery has been requested, ends it immediately
|
// if end of discovery has been requested, ends it immediately
|
||||||
if (done) {
|
if (done) {
|
||||||
|
@ -409,15 +418,15 @@ struct discovery_control_block_t : public procedure_control_block_t {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct read_control_block_t : public procedure_control_block_t {
|
struct GenericGattClient::ReadControlBlock : public ProcedureControlBlock {
|
||||||
read_control_block_t(
|
ReadControlBlock(
|
||||||
Gap::Handle_t connection_handle, uint16_t attribute_handle, uint16_t offset
|
Gap::Handle_t connection_handle, uint16_t attribute_handle, uint16_t offset
|
||||||
) : procedure_control_block_t(READ_PROCEDURE, connection_handle),
|
) : ProcedureControlBlock(READ_PROCEDURE, connection_handle),
|
||||||
attribute_handle(attribute_handle),
|
attribute_handle(attribute_handle),
|
||||||
offset(offset), current_offset(offset), data(NULL) {
|
offset(offset), current_offset(offset), data(NULL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~read_control_block_t() {
|
virtual ~ReadControlBlock() {
|
||||||
if (data != NULL) {
|
if (data != NULL) {
|
||||||
free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
|
@ -436,6 +445,19 @@ struct read_control_block_t : public procedure_control_block_t {
|
||||||
terminate(client, response);
|
terminate(client, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void abort(GenericGattClient *client) {
|
||||||
|
GattReadCallbackParams response = {
|
||||||
|
connection_handle,
|
||||||
|
attribute_handle,
|
||||||
|
offset,
|
||||||
|
0, // size of 0
|
||||||
|
NULL, // no data
|
||||||
|
BLE_ERROR_INVALID_STATE,
|
||||||
|
|
||||||
|
};
|
||||||
|
terminate(client, response);
|
||||||
|
}
|
||||||
|
|
||||||
void terminate(GenericGattClient* client, const GattReadCallbackParams& response) {
|
void terminate(GenericGattClient* client, const GattReadCallbackParams& response) {
|
||||||
client->remove_control_block(this);
|
client->remove_control_block(this);
|
||||||
client->processReadResponse(&response);
|
client->processReadResponse(&response);
|
||||||
|
@ -593,16 +615,16 @@ struct read_control_block_t : public procedure_control_block_t {
|
||||||
/*
|
/*
|
||||||
* Control block for the write process
|
* Control block for the write process
|
||||||
*/
|
*/
|
||||||
struct write_control_block_t : public procedure_control_block_t {
|
struct GenericGattClient::WriteControlBlock : public ProcedureControlBlock {
|
||||||
write_control_block_t(
|
WriteControlBlock(
|
||||||
Gap::Handle_t connection_handle, uint16_t attribute_handle,
|
Gap::Handle_t connection_handle, uint16_t attribute_handle,
|
||||||
uint8_t* data, uint16_t len
|
uint8_t* data, uint16_t len
|
||||||
) : procedure_control_block_t(WRITE_PROCEDURE, connection_handle),
|
) : ProcedureControlBlock(WRITE_PROCEDURE, connection_handle),
|
||||||
attribute_handle(attribute_handle), len(len), offset(0), data(data),
|
attribute_handle(attribute_handle), len(len), offset(0), data(data),
|
||||||
prepare_success(false), status(BLE_ERROR_UNSPECIFIED), error_code(0xFF) {
|
prepare_success(false), status(BLE_ERROR_UNSPECIFIED), error_code(0xFF) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~write_control_block_t() {
|
virtual ~WriteControlBlock() {
|
||||||
free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,6 +639,17 @@ struct write_control_block_t : public procedure_control_block_t {
|
||||||
terminate(client, response);
|
terminate(client, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void abort(GenericGattClient *client) {
|
||||||
|
GattWriteCallbackParams response = {
|
||||||
|
connection_handle,
|
||||||
|
attribute_handle,
|
||||||
|
GattWriteCallbackParams::OP_WRITE_REQ,
|
||||||
|
BLE_ERROR_INVALID_STATE,
|
||||||
|
0x00
|
||||||
|
};
|
||||||
|
terminate(client, response);
|
||||||
|
}
|
||||||
|
|
||||||
void terminate(GenericGattClient* client, const GattWriteCallbackParams& response) {
|
void terminate(GenericGattClient* client, const GattWriteCallbackParams& response) {
|
||||||
client->remove_control_block(this);
|
client->remove_control_block(this);
|
||||||
client->processWriteResponse(&response);
|
client->processWriteResponse(&response);
|
||||||
|
@ -785,12 +818,12 @@ struct write_control_block_t : public procedure_control_block_t {
|
||||||
/*
|
/*
|
||||||
* Control block for the descriptor discovery process
|
* Control block for the descriptor discovery process
|
||||||
*/
|
*/
|
||||||
struct descriptor_discovery_control_block_t : public procedure_control_block_t {
|
struct GenericGattClient::DescriptorDiscoveryControlBlock : public ProcedureControlBlock {
|
||||||
descriptor_discovery_control_block_t(
|
DescriptorDiscoveryControlBlock(
|
||||||
const DiscoveredCharacteristic& characteristic,
|
const DiscoveredCharacteristic& characteristic,
|
||||||
const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback,
|
const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback,
|
||||||
const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback
|
const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback
|
||||||
) : procedure_control_block_t(DESCRIPTOR_DISCOVERY_PROCEDURE, characteristic.getConnectionHandle()),
|
) : ProcedureControlBlock(DESCRIPTOR_DISCOVERY_PROCEDURE, characteristic.getConnectionHandle()),
|
||||||
characteristic(characteristic),
|
characteristic(characteristic),
|
||||||
discovery_cb(discoveryCallback),
|
discovery_cb(discoveryCallback),
|
||||||
termination_cb(terminationCallback),
|
termination_cb(terminationCallback),
|
||||||
|
@ -798,7 +831,7 @@ struct descriptor_discovery_control_block_t : public procedure_control_block_t {
|
||||||
done(false) {
|
done(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~descriptor_discovery_control_block_t() { }
|
virtual ~DescriptorDiscoveryControlBlock() { }
|
||||||
|
|
||||||
ble_error_t start(GenericGattClient* client) {
|
ble_error_t start(GenericGattClient* client) {
|
||||||
return client->_pal_client->discover_characteristics_descriptors(
|
return client->_pal_client->discover_characteristics_descriptors(
|
||||||
|
@ -814,6 +847,10 @@ struct descriptor_discovery_control_block_t : public procedure_control_block_t {
|
||||||
terminate(client, BLE_ERROR_UNSPECIFIED);
|
terminate(client, BLE_ERROR_UNSPECIFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void abort(GenericGattClient *client) {
|
||||||
|
terminate(client, BLE_ERROR_INVALID_STATE);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void handle(GenericGattClient* client, const AttServerMessage& message) {
|
virtual void handle(GenericGattClient* client, const AttServerMessage& message) {
|
||||||
if (done) {
|
if (done) {
|
||||||
terminate(client, BLE_ERROR_NONE);
|
terminate(client, BLE_ERROR_NONE);
|
||||||
|
@ -892,7 +929,8 @@ struct descriptor_discovery_control_block_t : public procedure_control_block_t {
|
||||||
GenericGattClient::GenericGattClient(pal::GattClient* pal_client) :
|
GenericGattClient::GenericGattClient(pal::GattClient* pal_client) :
|
||||||
_pal_client(pal_client),
|
_pal_client(pal_client),
|
||||||
_termination_callback(),
|
_termination_callback(),
|
||||||
control_blocks(NULL) {
|
control_blocks(NULL),
|
||||||
|
_is_reseting(false) {
|
||||||
_pal_client->when_server_message_received(
|
_pal_client->when_server_message_received(
|
||||||
mbed::callback(this, &GenericGattClient::on_server_message_received)
|
mbed::callback(this, &GenericGattClient::on_server_message_received)
|
||||||
);
|
);
|
||||||
|
@ -909,7 +947,7 @@ ble_error_t GenericGattClient::launchServiceDiscovery(
|
||||||
const UUID& matching_characteristic_uuid
|
const UUID& matching_characteristic_uuid
|
||||||
) {
|
) {
|
||||||
// verify that there is no other procedures going on this connection
|
// verify that there is no other procedures going on this connection
|
||||||
if (get_control_block(connection_handle)) {
|
if (_is_reseting || get_control_block(connection_handle)) {
|
||||||
return BLE_ERROR_INVALID_STATE;
|
return BLE_ERROR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -919,7 +957,7 @@ ble_error_t GenericGattClient::launchServiceDiscovery(
|
||||||
return BLE_ERROR_NONE;
|
return BLE_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
discovery_control_block_t* discovery_pcb = new(std::nothrow) discovery_control_block_t(
|
DiscoveryControlBlock* discovery_pcb = new(std::nothrow) DiscoveryControlBlock(
|
||||||
connection_handle,
|
connection_handle,
|
||||||
service_callback,
|
service_callback,
|
||||||
characteristic_callback,
|
characteristic_callback,
|
||||||
|
@ -959,7 +997,7 @@ ble_error_t GenericGattClient::launchServiceDiscovery(
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GenericGattClient::isServiceDiscoveryActive() const {
|
bool GenericGattClient::isServiceDiscoveryActive() const {
|
||||||
procedure_control_block_t* pcb = control_blocks;
|
ProcedureControlBlock* pcb = control_blocks;
|
||||||
|
|
||||||
while (pcb) {
|
while (pcb) {
|
||||||
if (pcb->type == COMPLETE_DISCOVERY_PROCEDURE) {
|
if (pcb->type == COMPLETE_DISCOVERY_PROCEDURE) {
|
||||||
|
@ -973,10 +1011,10 @@ bool GenericGattClient::isServiceDiscoveryActive() const {
|
||||||
|
|
||||||
void GenericGattClient::terminateServiceDiscovery()
|
void GenericGattClient::terminateServiceDiscovery()
|
||||||
{
|
{
|
||||||
procedure_control_block_t* pcb = control_blocks;
|
ProcedureControlBlock* pcb = control_blocks;
|
||||||
while (pcb) {
|
while (pcb) {
|
||||||
if (pcb->type == COMPLETE_DISCOVERY_PROCEDURE) {
|
if (pcb->type == COMPLETE_DISCOVERY_PROCEDURE) {
|
||||||
static_cast<discovery_control_block_t*>(pcb)->done = true;
|
static_cast<DiscoveryControlBlock*>(pcb)->done = true;
|
||||||
}
|
}
|
||||||
pcb = pcb->next;
|
pcb = pcb->next;
|
||||||
}
|
}
|
||||||
|
@ -988,11 +1026,11 @@ ble_error_t GenericGattClient::read(
|
||||||
uint16_t offset) const
|
uint16_t offset) const
|
||||||
{
|
{
|
||||||
// verify that there is no other procedures going on this connection
|
// verify that there is no other procedures going on this connection
|
||||||
if (get_control_block(connection_handle)) {
|
if (_is_reseting || get_control_block(connection_handle)) {
|
||||||
return BLE_ERROR_INVALID_STATE;
|
return BLE_ERROR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
read_control_block_t* read_pcb = new(std::nothrow) read_control_block_t(
|
ReadControlBlock* read_pcb = new(std::nothrow) ReadControlBlock(
|
||||||
connection_handle,
|
connection_handle,
|
||||||
attribute_handle,
|
attribute_handle,
|
||||||
offset
|
offset
|
||||||
|
@ -1032,7 +1070,7 @@ ble_error_t GenericGattClient::write(
|
||||||
const uint8_t* value
|
const uint8_t* value
|
||||||
) const {
|
) const {
|
||||||
// verify that there is no other procedures going on this connection
|
// verify that there is no other procedures going on this connection
|
||||||
if (get_control_block(connection_handle)) {
|
if (_is_reseting || get_control_block(connection_handle)) {
|
||||||
return BLE_ERROR_INVALID_STATE;
|
return BLE_ERROR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1058,7 +1096,7 @@ ble_error_t GenericGattClient::write(
|
||||||
memcpy(data, value, length);
|
memcpy(data, value, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
write_control_block_t* write_pcb = new(std::nothrow) write_control_block_t(
|
WriteControlBlock* write_pcb = new(std::nothrow) WriteControlBlock(
|
||||||
connection_handle,
|
connection_handle,
|
||||||
attribute_handle,
|
attribute_handle,
|
||||||
data,
|
data,
|
||||||
|
@ -1111,7 +1149,7 @@ ble_error_t GenericGattClient::discoverCharacteristicDescriptors(
|
||||||
const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback
|
const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback
|
||||||
) {
|
) {
|
||||||
// verify that there is no other procedures going on this connection
|
// verify that there is no other procedures going on this connection
|
||||||
if (get_control_block(characteristic.getConnectionHandle())) {
|
if (_is_reseting || get_control_block(characteristic.getConnectionHandle())) {
|
||||||
return BLE_ERROR_INVALID_STATE;
|
return BLE_ERROR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1126,8 +1164,8 @@ ble_error_t GenericGattClient::discoverCharacteristicDescriptors(
|
||||||
return BLE_ERROR_NONE;
|
return BLE_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptor_discovery_control_block_t* discovery_pcb =
|
DescriptorDiscoveryControlBlock* discovery_pcb =
|
||||||
new(std::nothrow) descriptor_discovery_control_block_t(
|
new(std::nothrow) DescriptorDiscoveryControlBlock(
|
||||||
characteristic,
|
characteristic,
|
||||||
discoveryCallback,
|
discoveryCallback,
|
||||||
terminationCallback
|
terminationCallback
|
||||||
|
@ -1152,11 +1190,11 @@ ble_error_t GenericGattClient::discoverCharacteristicDescriptors(
|
||||||
bool GenericGattClient::isCharacteristicDescriptorDiscoveryActive(
|
bool GenericGattClient::isCharacteristicDescriptorDiscoveryActive(
|
||||||
const DiscoveredCharacteristic& characteristic
|
const DiscoveredCharacteristic& characteristic
|
||||||
) const {
|
) const {
|
||||||
procedure_control_block_t* pcb = control_blocks;
|
ProcedureControlBlock* pcb = control_blocks;
|
||||||
|
|
||||||
while (pcb) {
|
while (pcb) {
|
||||||
if (pcb->type == DESCRIPTOR_DISCOVERY_PROCEDURE &&
|
if (pcb->type == DESCRIPTOR_DISCOVERY_PROCEDURE &&
|
||||||
static_cast<descriptor_discovery_control_block_t*>(pcb)->characteristic == characteristic) {
|
static_cast<DescriptorDiscoveryControlBlock*>(pcb)->characteristic == characteristic) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
pcb = pcb->next;
|
pcb = pcb->next;
|
||||||
|
@ -1168,12 +1206,12 @@ bool GenericGattClient::isCharacteristicDescriptorDiscoveryActive(
|
||||||
void GenericGattClient::terminateCharacteristicDescriptorDiscovery(
|
void GenericGattClient::terminateCharacteristicDescriptorDiscovery(
|
||||||
const DiscoveredCharacteristic& characteristic
|
const DiscoveredCharacteristic& characteristic
|
||||||
) {
|
) {
|
||||||
procedure_control_block_t* pcb = control_blocks;
|
ProcedureControlBlock* pcb = control_blocks;
|
||||||
|
|
||||||
while (pcb) {
|
while (pcb) {
|
||||||
if (pcb->type == DESCRIPTOR_DISCOVERY_PROCEDURE) {
|
if (pcb->type == DESCRIPTOR_DISCOVERY_PROCEDURE) {
|
||||||
descriptor_discovery_control_block_t* dpcb =
|
DescriptorDiscoveryControlBlock* dpcb =
|
||||||
static_cast<descriptor_discovery_control_block_t*>(pcb);
|
static_cast<DescriptorDiscoveryControlBlock*>(pcb);
|
||||||
if (dpcb->characteristic == characteristic) {
|
if (dpcb->characteristic == characteristic) {
|
||||||
dpcb->done = true;
|
dpcb->done = true;
|
||||||
return;
|
return;
|
||||||
|
@ -1186,7 +1224,17 @@ void GenericGattClient::terminateCharacteristicDescriptorDiscovery(
|
||||||
}
|
}
|
||||||
|
|
||||||
ble_error_t GenericGattClient::reset(void) {
|
ble_error_t GenericGattClient::reset(void) {
|
||||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
|
||||||
|
// _is_reseting prevent executions of new procedure while the instance resets.
|
||||||
|
// otherwise new procedures can be launched from callbacks generated by the
|
||||||
|
// reset.
|
||||||
|
_is_reseting = true;
|
||||||
|
while (control_blocks) {
|
||||||
|
control_blocks->abort(this);
|
||||||
|
}
|
||||||
|
_is_reseting = false;
|
||||||
|
|
||||||
|
return BLE_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericGattClient::on_termination(Gap::Handle_t connection_handle) {
|
void GenericGattClient::on_termination(Gap::Handle_t connection_handle) {
|
||||||
|
@ -1230,7 +1278,7 @@ void GenericGattClient::on_server_response(
|
||||||
connection_handle_t connection,
|
connection_handle_t connection,
|
||||||
const AttServerMessage& message
|
const AttServerMessage& message
|
||||||
) {
|
) {
|
||||||
procedure_control_block_t* pcb = get_control_block(connection);
|
ProcedureControlBlock* pcb = get_control_block(connection);
|
||||||
if (pcb == NULL) {
|
if (pcb == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1270,7 +1318,7 @@ void GenericGattClient::on_server_event(connection_handle_t connection, const At
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericGattClient::on_transaction_timeout(connection_handle_t connection) {
|
void GenericGattClient::on_transaction_timeout(connection_handle_t connection) {
|
||||||
procedure_control_block_t* pcb = get_control_block(connection);
|
ProcedureControlBlock* pcb = get_control_block(connection);
|
||||||
if (pcb == NULL) {
|
if (pcb == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1278,36 +1326,36 @@ void GenericGattClient::on_transaction_timeout(connection_handle_t connection) {
|
||||||
pcb->handle_timeout_error(this);
|
pcb->handle_timeout_error(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
procedure_control_block_t* GenericGattClient::get_control_block(Gap::Handle_t connection) {
|
GenericGattClient::ProcedureControlBlock* GenericGattClient::get_control_block(Gap::Handle_t connection) {
|
||||||
procedure_control_block_t* it = control_blocks;
|
ProcedureControlBlock* it = control_blocks;
|
||||||
while (it && it->connection_handle != connection) {
|
while (it && it->connection_handle != connection) {
|
||||||
it = it->next;
|
it = it->next;
|
||||||
}
|
}
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
const procedure_control_block_t* GenericGattClient::get_control_block(Gap::Handle_t connection) const {
|
const GenericGattClient::ProcedureControlBlock* GenericGattClient::get_control_block(Gap::Handle_t connection) const {
|
||||||
procedure_control_block_t* it = control_blocks;
|
ProcedureControlBlock* it = control_blocks;
|
||||||
while (it && it->connection_handle != connection) {
|
while (it && it->connection_handle != connection) {
|
||||||
it = it->next;
|
it = it->next;
|
||||||
}
|
}
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericGattClient::insert_control_block(procedure_control_block_t* cb) const {
|
void GenericGattClient::insert_control_block(ProcedureControlBlock* cb) const {
|
||||||
if (control_blocks == NULL) {
|
if (control_blocks == NULL) {
|
||||||
control_blocks = cb;
|
control_blocks = cb;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
procedure_control_block_t* current = control_blocks;
|
ProcedureControlBlock* current = control_blocks;
|
||||||
while (current->next) {
|
while (current->next) {
|
||||||
current = current->next;
|
current = current->next;
|
||||||
}
|
}
|
||||||
current->next = cb;
|
current->next = cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericGattClient::remove_control_block(procedure_control_block_t* cb) const {
|
void GenericGattClient::remove_control_block(ProcedureControlBlock* cb) const {
|
||||||
if (control_blocks == NULL) {
|
if (control_blocks == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1317,7 +1365,7 @@ void GenericGattClient::remove_control_block(procedure_control_block_t* cb) cons
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
procedure_control_block_t* current = control_blocks;
|
ProcedureControlBlock* current = control_blocks;
|
||||||
while (current->next && current->next != cb) {
|
while (current->next && current->next != cb) {
|
||||||
current = current->next;
|
current = current->next;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,11 +51,9 @@ extern "C" {
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "nrf_ble_hci.h"
|
#include "nrf_ble_hci.h"
|
||||||
#include "btle_discovery.h"
|
|
||||||
|
|
||||||
#include "nRF5xGattClient.h"
|
#include "nRF5XPalGattClient.h"
|
||||||
#include "nRF5xServiceDiscovery.h"
|
|
||||||
#include "nRF5xCharacteristicDescriptorDiscoverer.h"
|
|
||||||
|
|
||||||
|
|
||||||
bool isEventsSignaled = false;
|
bool isEventsSignaled = false;
|
||||||
|
@ -67,23 +65,6 @@ extern "C" void SD_EVT_IRQHandler(void); // export the softdevice event handler
|
||||||
|
|
||||||
static void btle_handler(ble_evt_t *p_ble_evt);
|
static void btle_handler(ble_evt_t *p_ble_evt);
|
||||||
|
|
||||||
#if 0
|
|
||||||
#define CENTRAL_LINK_COUNT (YOTTA_CFG_NORDIC_BLE_CENTRAL_LINKS) /**<number of central links used by the application. When changing this number remember to adjust the RAM settings */
|
|
||||||
/** If value for YOTTA_CFG_NORDIC_BLE_PERIPHERAL_LINKS was used, ram settings are adjusted by the yotta target module. */
|
|
||||||
#define PERIPHERAL_LINK_COUNT (YOTTA_CFG_NORDIC_BLE_PERIPHERAL_LINKS) /**<number of peripheral links used by the application. When changing this number remember to adjust the RAM settings*/
|
|
||||||
/** If value for YOTTA_CFG_NORDIC_BLE_CENTRAL_LINKS was used, ram settings are adjusted by the yotta target module. */
|
|
||||||
#define GATTS_ATTR_TAB_SIZE (YOTTA_CFG_NORDIC_BLE_GATTS_ATTR_TAB_SIZE) /**< GATTS attribite table size. */
|
|
||||||
/** If value for YOTTA_CFG_NORDIC_BLE_GATTS_ATTR_TAB_SIZE was used, ram settings are adjusted by the yotta target module. */
|
|
||||||
#else
|
|
||||||
#define CENTRAL_LINK_COUNT 3 /**<number of central links used by the application. When changing this number remember to adjust the RAM settings */
|
|
||||||
/** If value for YOTTA_CFG_NORDIC_BLE_PERIPHERAL_LINKS was used, ram settings are adjusted by the yotta target module. */
|
|
||||||
#define PERIPHERAL_LINK_COUNT 1 /**<number of peripheral links used by the application. When changing this number remember to adjust the RAM settings*/
|
|
||||||
/** If value for YOTTA_CFG_NORDIC_BLE_CENTRAL_LINKS was used, ram settings are adjusted by the yotta target module. */
|
|
||||||
#define GATTS_ATTR_TAB_SIZE 0x600 /**< GATTS attribite table size. */
|
|
||||||
/** If value for YOTTA_CFG_NORDIC_BLE_GATTS_ATTR_TAB_SIZE was used, ram settings are adjusted by the yotta target module. */
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void sys_evt_dispatch(uint32_t sys_evt)
|
static void sys_evt_dispatch(uint32_t sys_evt)
|
||||||
{
|
{
|
||||||
#if (IS_LEGACY_DEVICE_MANAGER_ENABLED)
|
#if (IS_LEGACY_DEVICE_MANAGER_ENABLED)
|
||||||
|
@ -121,7 +102,7 @@ error_t btle_init(void)
|
||||||
|
|
||||||
// register softdevice handler vector
|
// register softdevice handler vector
|
||||||
NVIC_SetVector(SD_EVT_IRQn, (uint32_t) SD_EVT_IRQHandler);
|
NVIC_SetVector(SD_EVT_IRQn, (uint32_t) SD_EVT_IRQHandler);
|
||||||
|
|
||||||
// Configure the LF clock according to values provided by btle_clock.h.
|
// Configure the LF clock according to values provided by btle_clock.h.
|
||||||
// It is input from the chain of the yotta configuration system.
|
// It is input from the chain of the yotta configuration system.
|
||||||
clockConfiguration.source = LFCLK_CONF_SOURCE;
|
clockConfiguration.source = LFCLK_CONF_SOURCE;
|
||||||
|
@ -189,6 +170,8 @@ error_t btle_init(void)
|
||||||
|
|
||||||
static void btle_handler(ble_evt_t *p_ble_evt)
|
static void btle_handler(ble_evt_t *p_ble_evt)
|
||||||
{
|
{
|
||||||
|
using ble::pal::vendor::nordic::nRF5XGattClient;
|
||||||
|
|
||||||
/* Library service handlers */
|
/* Library service handlers */
|
||||||
#if SDK_CONN_PARAMS_MODULE_ENABLE
|
#if SDK_CONN_PARAMS_MODULE_ENABLE
|
||||||
ble_conn_params_on_ble_evt(p_ble_evt);
|
ble_conn_params_on_ble_evt(p_ble_evt);
|
||||||
|
@ -206,7 +189,7 @@ static void btle_handler(ble_evt_t *p_ble_evt)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
|
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
|
||||||
bleGattcEventHandler(p_ble_evt);
|
nRF5XGattClient::handle_events(p_ble_evt);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE);
|
nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE);
|
||||||
|
@ -229,7 +212,7 @@ static void btle_handler(ble_evt_t *p_ble_evt)
|
||||||
const ble_gap_addr_t *peer = &p_ble_evt->evt.gap_evt.params.connected.peer_addr;
|
const ble_gap_addr_t *peer = &p_ble_evt->evt.gap_evt.params.connected.peer_addr;
|
||||||
#if (NRF_SD_BLE_API_VERSION <= 2)
|
#if (NRF_SD_BLE_API_VERSION <= 2)
|
||||||
const ble_gap_addr_t *own = &p_ble_evt->evt.gap_evt.params.connected.own_addr;
|
const ble_gap_addr_t *own = &p_ble_evt->evt.gap_evt.params.connected.own_addr;
|
||||||
|
|
||||||
gap.processConnectionEvent(handle,
|
gap.processConnectionEvent(handle,
|
||||||
role,
|
role,
|
||||||
static_cast<BLEProtocol::AddressType_t>(peer->addr_type), peer->addr,
|
static_cast<BLEProtocol::AddressType_t>(peer->addr_type), peer->addr,
|
||||||
|
@ -275,9 +258,7 @@ static void btle_handler(ble_evt_t *p_ble_evt)
|
||||||
|
|
||||||
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
|
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
|
||||||
// Close all pending discoveries for this connection
|
// Close all pending discoveries for this connection
|
||||||
nRF5xGattClient& gattClient = ble.getGattClient();
|
nRF5XGattClient::handle_connection_termination(handle);
|
||||||
gattClient.characteristicDescriptorDiscoverer().terminate(handle, BLE_ERROR_INVALID_STATE);
|
|
||||||
gattClient.discovery().terminate(handle);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gap.processDisconnectionEvent(handle, reason);
|
gap.processDisconnectionEvent(handle, reason);
|
||||||
|
|
|
@ -26,6 +26,13 @@ extern "C" {
|
||||||
#include "ble_srv_common.h"
|
#include "ble_srv_common.h"
|
||||||
#include "headers/nrf_ble.h"
|
#include "headers/nrf_ble.h"
|
||||||
|
|
||||||
|
#define CENTRAL_LINK_COUNT 3 /**<number of central links used by the application. When changing this number remember to adjust the RAM settings */
|
||||||
|
/** If value for YOTTA_CFG_NORDIC_BLE_PERIPHERAL_LINKS was used, ram settings are adjusted by the yotta target module. */
|
||||||
|
#define PERIPHERAL_LINK_COUNT 1 /**<number of peripheral links used by the application. When changing this number remember to adjust the RAM settings*/
|
||||||
|
/** If value for YOTTA_CFG_NORDIC_BLE_CENTRAL_LINKS was used, ram settings are adjusted by the yotta target module. */
|
||||||
|
#define GATTS_ATTR_TAB_SIZE 0x600 /**< GATTS attribite table size. */
|
||||||
|
/** If value for YOTTA_CFG_NORDIC_BLE_GATTS_ATTR_TAB_SIZE was used, ram settings are adjusted by the yotta target module. */
|
||||||
|
|
||||||
error_t btle_init(void);
|
error_t btle_init(void);
|
||||||
|
|
||||||
// flag indicating if events have been signaled or not
|
// flag indicating if events have been signaled or not
|
||||||
|
|
|
@ -1,147 +0,0 @@
|
||||||
/* mbed Microcontroller Library
|
|
||||||
* Copyright (c) 2006-2013 ARM Limited
|
|
||||||
*
|
|
||||||
* 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 "nRF5xServiceDiscovery.h"
|
|
||||||
#include "nRF5xCharacteristicDescriptorDiscoverer.h"
|
|
||||||
#include "nRF5xGattClient.h"
|
|
||||||
#include "nRF5xn.h"
|
|
||||||
|
|
||||||
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
|
|
||||||
void bleGattcEventHandler(const ble_evt_t *p_ble_evt)
|
|
||||||
{
|
|
||||||
nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE);
|
|
||||||
nRF5xGattClient &gattClient = (nRF5xGattClient &) ble.getGattClient();
|
|
||||||
nRF5xServiceDiscovery &sdSingleton = gattClient.discovery();
|
|
||||||
nRF5xCharacteristicDescriptorDiscoverer &characteristicDescriptorDiscoverer =
|
|
||||||
gattClient.characteristicDescriptorDiscoverer();
|
|
||||||
|
|
||||||
switch (p_ble_evt->header.evt_id) {
|
|
||||||
case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
|
|
||||||
switch (p_ble_evt->evt.gattc_evt.gatt_status) {
|
|
||||||
case BLE_GATT_STATUS_SUCCESS:
|
|
||||||
sdSingleton.setupDiscoveredServices(&p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND:
|
|
||||||
default:
|
|
||||||
sdSingleton.terminate();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BLE_GATTC_EVT_CHAR_DISC_RSP:
|
|
||||||
switch (p_ble_evt->evt.gattc_evt.gatt_status) {
|
|
||||||
case BLE_GATT_STATUS_SUCCESS:
|
|
||||||
sdSingleton.setupDiscoveredCharacteristics(&p_ble_evt->evt.gattc_evt.params.char_disc_rsp);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND:
|
|
||||||
default:
|
|
||||||
sdSingleton.terminateCharacteristicDiscovery(BLE_ERROR_NONE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP:
|
|
||||||
if (sdSingleton.isActive()) {
|
|
||||||
sdSingleton.processDiscoverUUIDResponse(&p_ble_evt->evt.gattc_evt);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BLE_GATTC_EVT_READ_RSP: {
|
|
||||||
GattReadCallbackParams response = {
|
|
||||||
/* .connHandle = */ p_ble_evt->evt.gattc_evt.conn_handle,
|
|
||||||
/* .handle = */ p_ble_evt->evt.gattc_evt.params.read_rsp.handle,
|
|
||||||
/* .offset = */ p_ble_evt->evt.gattc_evt.params.read_rsp.offset,
|
|
||||||
/* .len = */ p_ble_evt->evt.gattc_evt.params.read_rsp.len,
|
|
||||||
/* .data = */ p_ble_evt->evt.gattc_evt.params.read_rsp.data,
|
|
||||||
};
|
|
||||||
gattClient.processReadResponse(&response);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BLE_GATTC_EVT_WRITE_RSP: {
|
|
||||||
GattWriteCallbackParams response = {
|
|
||||||
/* .connHandle = */ p_ble_evt->evt.gattc_evt.conn_handle,
|
|
||||||
/* .handle = */ p_ble_evt->evt.gattc_evt.params.write_rsp.handle,
|
|
||||||
/* .writeOp = */ (GattWriteCallbackParams::WriteOp_t)(p_ble_evt->evt.gattc_evt.params.write_rsp.write_op),
|
|
||||||
/* .offset = */ p_ble_evt->evt.gattc_evt.params.write_rsp.offset,
|
|
||||||
/* .len = */ p_ble_evt->evt.gattc_evt.params.write_rsp.len,
|
|
||||||
/* .data = */ p_ble_evt->evt.gattc_evt.params.write_rsp.data,
|
|
||||||
};
|
|
||||||
gattClient.processWriteResponse(&response);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BLE_GATTC_EVT_HVX: {
|
|
||||||
GattHVXCallbackParams params = {
|
|
||||||
/* connHandle = */ p_ble_evt->evt.gattc_evt.conn_handle,
|
|
||||||
/* handle = */ p_ble_evt->evt.gattc_evt.params.hvx.handle,
|
|
||||||
/* type = */ static_cast<HVXType_t>(p_ble_evt->evt.gattc_evt.params.hvx.type),
|
|
||||||
/* len = */ p_ble_evt->evt.gattc_evt.params.hvx.len,
|
|
||||||
/* data = */ p_ble_evt->evt.gattc_evt.params.hvx.data
|
|
||||||
};
|
|
||||||
|
|
||||||
gattClient.processHVXEvent(¶ms);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BLE_GATTC_EVT_DESC_DISC_RSP: {
|
|
||||||
uint16_t conn_handle = p_ble_evt->evt.gattc_evt.conn_handle;
|
|
||||||
uint16_t status = p_ble_evt->evt.gattc_evt.gatt_status;
|
|
||||||
const ble_gattc_evt_desc_disc_rsp_t& discovered_descriptors = p_ble_evt->evt.gattc_evt.params.desc_disc_rsp;
|
|
||||||
|
|
||||||
switch(status) {
|
|
||||||
case BLE_GATT_STATUS_SUCCESS:
|
|
||||||
characteristicDescriptorDiscoverer.process(
|
|
||||||
conn_handle,
|
|
||||||
discovered_descriptors
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND:
|
|
||||||
// end of discovery
|
|
||||||
characteristicDescriptorDiscoverer.terminate(conn_handle, BLE_ERROR_NONE);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
characteristicDescriptorDiscoverer.terminate(conn_handle, BLE_ERROR_UNSPECIFIED);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case BLE_GATTC_EVT_ATTR_INFO_DISC_RSP : {
|
|
||||||
uint16_t conn_handle = p_ble_evt->evt.gattc_evt.conn_handle;
|
|
||||||
uint16_t status = p_ble_evt->evt.gattc_evt.gatt_status;
|
|
||||||
const ble_gattc_evt_attr_info_disc_rsp_t& infos = p_ble_evt->evt.gattc_evt.params.attr_info_disc_rsp;
|
|
||||||
|
|
||||||
switch(status) {
|
|
||||||
case BLE_GATT_STATUS_SUCCESS:
|
|
||||||
characteristicDescriptorDiscoverer.processAttributeInformation(
|
|
||||||
conn_handle,
|
|
||||||
infos
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
characteristicDescriptorDiscoverer.terminate(conn_handle, BLE_ERROR_UNSPECIFIED);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
|
|
||||||
sdSingleton.progressCharacteristicDiscovery();
|
|
||||||
sdSingleton.progressServiceDiscovery();
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,22 +0,0 @@
|
||||||
/* mbed Microcontroller Library
|
|
||||||
* Copyright (c) 2006-2013 ARM Limited
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _BTLE_DISCOVERY_H_
|
|
||||||
#define _BTLE_DISCOVERY_H_
|
|
||||||
|
|
||||||
void bleGattcEventHandler(const ble_evt_t *p_ble_evt);
|
|
||||||
|
|
||||||
#endif /*_BTLE_DISCOVERY_H_*/
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,257 @@
|
||||||
|
/* mbed Microcontroller Library
|
||||||
|
* Copyright (c) 2017-2017 ARM Limited
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BLE_NORDIC_PAL_GATT_CLIENT_H_
|
||||||
|
#define BLE_NORDIC_PAL_GATT_CLIENT_H_
|
||||||
|
|
||||||
|
#include "ble/pal/PalGattClient.h"
|
||||||
|
#include "ble/blecommon.h"
|
||||||
|
#include "ble/UUID.h"
|
||||||
|
|
||||||
|
#include "nrf_ble_gatt.h"
|
||||||
|
#include "nrf_ble.h"
|
||||||
|
#include "nrf_ble_types.h"
|
||||||
|
#include "btle.h"
|
||||||
|
|
||||||
|
namespace ble {
|
||||||
|
namespace pal {
|
||||||
|
namespace vendor {
|
||||||
|
namespace nordic {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of pal::GattClient for the Nordic stack.
|
||||||
|
*/
|
||||||
|
class nRF5XGattClient : public ble::pal::GattClient {
|
||||||
|
|
||||||
|
public:
|
||||||
|
nRF5XGattClient();
|
||||||
|
|
||||||
|
virtual ~nRF5XGattClient();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* see pal::GattClient::initialize .
|
||||||
|
*/
|
||||||
|
virtual ble_error_t initialize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* see pal::GattClient::terminate .
|
||||||
|
*/
|
||||||
|
virtual ble_error_t terminate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* see pal::GattClient::exchange_mtu .
|
||||||
|
*/
|
||||||
|
virtual ble_error_t exchange_mtu(connection_handle_t connection);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* see pal::GattClient::get_mtu_size .
|
||||||
|
*/
|
||||||
|
virtual ble_error_t get_mtu_size(
|
||||||
|
connection_handle_t connection_handle, uint16_t& mtu_size
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* see pal::GattClient::discover_primary_service .
|
||||||
|
*/
|
||||||
|
virtual ble_error_t discover_primary_service(
|
||||||
|
connection_handle_t connection,
|
||||||
|
attribute_handle_t discovery_range_begining
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* see pal::GattClient::discover_primary_service_by_service_uuid .
|
||||||
|
*/
|
||||||
|
virtual ble_error_t discover_primary_service_by_service_uuid(
|
||||||
|
connection_handle_t connection_handle,
|
||||||
|
attribute_handle_t discovery_range_beginning,
|
||||||
|
const UUID& uuid
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* see pal::GattClient::find_included_service .
|
||||||
|
*/
|
||||||
|
virtual ble_error_t find_included_service(
|
||||||
|
connection_handle_t connection_handle,
|
||||||
|
attribute_handle_range_t service_range
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* see pal::GattClient::discover_characteristics_of_a_service .
|
||||||
|
*/
|
||||||
|
virtual ble_error_t discover_characteristics_of_a_service(
|
||||||
|
connection_handle_t connection_handle,
|
||||||
|
attribute_handle_range_t discovery_range
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* see pal::GattClient::discover_characteristics_descriptors .
|
||||||
|
*/
|
||||||
|
virtual ble_error_t discover_characteristics_descriptors(
|
||||||
|
connection_handle_t connection_handle,
|
||||||
|
attribute_handle_range_t descriptors_discovery_range
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* see pal::GattClient::read_attribute_value .
|
||||||
|
*/
|
||||||
|
virtual ble_error_t read_attribute_value(
|
||||||
|
connection_handle_t connection_handle,
|
||||||
|
attribute_handle_t attribute_handle
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* see pal::GattClient::read_using_characteristic_uuid .
|
||||||
|
*/
|
||||||
|
virtual ble_error_t read_using_characteristic_uuid(
|
||||||
|
connection_handle_t connection_handle,
|
||||||
|
attribute_handle_range_t read_range,
|
||||||
|
const UUID& uuid
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* see pal::GattClient::read_attribute_blob .
|
||||||
|
*/
|
||||||
|
virtual ble_error_t read_attribute_blob(
|
||||||
|
connection_handle_t connection,
|
||||||
|
attribute_handle_t attribute_handle,
|
||||||
|
uint16_t offset
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* see pal::GattClient::read_multiple_characteristic_values .
|
||||||
|
*/
|
||||||
|
virtual ble_error_t read_multiple_characteristic_values(
|
||||||
|
connection_handle_t connection,
|
||||||
|
const ArrayView<const attribute_handle_t>& characteristic_handles
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* see pal::GattClient::write_without_response .
|
||||||
|
*/
|
||||||
|
virtual ble_error_t write_without_response(
|
||||||
|
connection_handle_t connection_handle,
|
||||||
|
attribute_handle_t characteristic_value_handle,
|
||||||
|
const ArrayView<const uint8_t>& value
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* see pal::GattClient::signed_write_without_response .
|
||||||
|
*/
|
||||||
|
virtual ble_error_t signed_write_without_response(
|
||||||
|
connection_handle_t connection_handle,
|
||||||
|
attribute_handle_t characteristic_value_handle,
|
||||||
|
const ArrayView<const uint8_t>& value
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* see pal::GattClient::write_attribute .
|
||||||
|
*/
|
||||||
|
virtual ble_error_t write_attribute(
|
||||||
|
connection_handle_t connection_handle,
|
||||||
|
attribute_handle_t attribute_handle,
|
||||||
|
const ArrayView<const uint8_t>& value
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* see pal::GattClient::queue_prepare_write .
|
||||||
|
*/
|
||||||
|
virtual ble_error_t queue_prepare_write(
|
||||||
|
connection_handle_t connection_handle,
|
||||||
|
attribute_handle_t characteristic_value_handle,
|
||||||
|
const ArrayView<const uint8_t>& value,
|
||||||
|
uint16_t offset
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* see pal::GattClient::execute_write_queue .
|
||||||
|
*/
|
||||||
|
virtual ble_error_t execute_write_queue(
|
||||||
|
connection_handle_t connection_handle,
|
||||||
|
bool execute
|
||||||
|
);
|
||||||
|
|
||||||
|
// singleton of the ARM Cordio client
|
||||||
|
static nRF5XGattClient& get_client();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function call from btle.cpp
|
||||||
|
*
|
||||||
|
* Do not call directly.
|
||||||
|
*/
|
||||||
|
static void handle_events(const ble_evt_t *p_ble_evt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by btle.cpp when a disconnection happens.
|
||||||
|
*/
|
||||||
|
static void handle_connection_termination(connection_handle_t connection);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct GattProcedure;
|
||||||
|
struct RegularGattProcedure;
|
||||||
|
struct DiscoverPrimaryServiceProcedure;
|
||||||
|
struct DiscoverPrimaryServiceByUUIDProcedure;
|
||||||
|
struct FindIncludedServicesProcedure;
|
||||||
|
struct DiscoverCharacteristicsProcedure;
|
||||||
|
struct DiscoverDescriptorsProcedure;
|
||||||
|
struct ReadAttributeProcedure;
|
||||||
|
struct ReadUsingCharacteristicUUIDProcedure;
|
||||||
|
struct ReadAttributeBlobProcedure;
|
||||||
|
struct ReadMultipleCharacteristicsProcedure;
|
||||||
|
struct WriteAttributeProcedure;
|
||||||
|
struct QueuePrepareWriteProcedure;
|
||||||
|
struct ExecuteWriteQueueProcedure;
|
||||||
|
|
||||||
|
template<typename ProcType, typename A0>
|
||||||
|
ble_error_t launch_procedure(connection_handle_t connection, const A0& a0);
|
||||||
|
|
||||||
|
template<typename ProcType, typename A0, typename A1>
|
||||||
|
ble_error_t launch_procedure(
|
||||||
|
connection_handle_t connection, const A0& a0, const A1& a1
|
||||||
|
);
|
||||||
|
|
||||||
|
template<typename ProcType, typename A0, typename A1, typename A2>
|
||||||
|
ble_error_t launch_procedure(
|
||||||
|
connection_handle_t connection,
|
||||||
|
const A0& a0, const A1& a1, const A2& a2
|
||||||
|
);
|
||||||
|
|
||||||
|
template<typename ProcType, typename A0, typename A1, typename A2, typename A3>
|
||||||
|
ble_error_t launch_procedure(
|
||||||
|
connection_handle_t connection,
|
||||||
|
const A0& a0, const A1& a1, const A2& a2, const A3& a3
|
||||||
|
);
|
||||||
|
|
||||||
|
GattProcedure* get_procedure(connection_handle_t) const;
|
||||||
|
bool register_procedure(GattProcedure*);
|
||||||
|
bool remove_procedure(GattProcedure*);
|
||||||
|
|
||||||
|
void handle_procedure_event(const ble_evt_t &evt);
|
||||||
|
void handle_hvx_event(const ble_evt_t &evt);
|
||||||
|
void handle_timeout_event(const ble_evt_t &evt);
|
||||||
|
|
||||||
|
static const size_t max_procedures_count =
|
||||||
|
CENTRAL_LINK_COUNT + PERIPHERAL_LINK_COUNT;
|
||||||
|
|
||||||
|
// Note: Ideally we would have used an array of variant here
|
||||||
|
GattProcedure* _procedures[max_procedures_count];
|
||||||
|
};
|
||||||
|
|
||||||
|
} // nordic
|
||||||
|
} // vendor
|
||||||
|
} // pal
|
||||||
|
} // ble
|
||||||
|
|
||||||
|
#endif /* BLE_NORDIC_PAL_GATT_CLIENT_H_ */
|
|
@ -1,325 +0,0 @@
|
||||||
/* mbed Microcontroller Library
|
|
||||||
* Copyright (c) 2006-2015 ARM Limited
|
|
||||||
*
|
|
||||||
* 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 "nRF5xCharacteristicDescriptorDiscoverer.h"
|
|
||||||
#include "headers/nrf_ble_err.h"
|
|
||||||
#include "ble/DiscoveredCharacteristicDescriptor.h"
|
|
||||||
|
|
||||||
nRF5xCharacteristicDescriptorDiscoverer::nRF5xCharacteristicDescriptorDiscoverer() :
|
|
||||||
discoveryRunning() {
|
|
||||||
// nothing to do
|
|
||||||
}
|
|
||||||
|
|
||||||
nRF5xCharacteristicDescriptorDiscoverer::~nRF5xCharacteristicDescriptorDiscoverer() {
|
|
||||||
// nothing to do
|
|
||||||
}
|
|
||||||
|
|
||||||
ble_error_t nRF5xCharacteristicDescriptorDiscoverer::launch(
|
|
||||||
const DiscoveredCharacteristic& characteristic,
|
|
||||||
const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback,
|
|
||||||
const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback
|
|
||||||
) {
|
|
||||||
Gap::Handle_t connHandle = characteristic.getConnectionHandle();
|
|
||||||
// it is ok to deduce that the start handle for descriptors is after
|
|
||||||
// the characteristic declaration and the characteristic value declaration
|
|
||||||
// see BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part G] (3.3)
|
|
||||||
Gap::Handle_t descriptorStartHandle = characteristic.getDeclHandle() + 2;
|
|
||||||
Gap::Handle_t descriptorEndHandle = characteristic.getLastHandle();
|
|
||||||
|
|
||||||
// check if there is any descriptor to discover
|
|
||||||
if (descriptorEndHandle < descriptorStartHandle) {
|
|
||||||
CharacteristicDescriptorDiscovery::TerminationCallbackParams_t termParams = {
|
|
||||||
characteristic,
|
|
||||||
BLE_ERROR_NONE
|
|
||||||
};
|
|
||||||
terminationCallback.call(&termParams);
|
|
||||||
return BLE_ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if we can run this discovery
|
|
||||||
if (isConnectionInUse(connHandle)) {
|
|
||||||
return BLE_STACK_BUSY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get a new discovery slot, if none are available, just return
|
|
||||||
Discovery* discovery = getAvailableDiscoverySlot();
|
|
||||||
if(discovery == NULL) {
|
|
||||||
return BLE_STACK_BUSY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// try to launch the discovery
|
|
||||||
ble_error_t err = gattc_descriptors_discover(connHandle, descriptorStartHandle, descriptorEndHandle);
|
|
||||||
if(!err) {
|
|
||||||
// commit the new discovery to its slot
|
|
||||||
*discovery = Discovery(characteristic, discoveryCallback, terminationCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool nRF5xCharacteristicDescriptorDiscoverer::isActive(const DiscoveredCharacteristic& characteristic) const {
|
|
||||||
for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
|
|
||||||
if(discoveryRunning[i].getCharacteristic() == characteristic) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nRF5xCharacteristicDescriptorDiscoverer::requestTerminate(const DiscoveredCharacteristic& characteristic) {
|
|
||||||
Discovery* discovery = findRunningDiscovery(characteristic);
|
|
||||||
if(discovery) {
|
|
||||||
// call terminate anyway
|
|
||||||
terminate(discovery, BLE_ERROR_NONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void nRF5xCharacteristicDescriptorDiscoverer::process(uint16_t connectionHandle, const ble_gattc_evt_desc_disc_rsp_t& descriptors) {
|
|
||||||
Discovery* discovery = findRunningDiscovery(connectionHandle);
|
|
||||||
// the discovery has been removed
|
|
||||||
if(!discovery) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint16_t i = 0; i < descriptors.count; ++i) {
|
|
||||||
const ble_gattc_desc_t& desc = descriptors.descs[i];
|
|
||||||
const ble_uuid_t& uuid = desc.uuid;
|
|
||||||
|
|
||||||
if (uuid.type == BLE_UUID_TYPE_BLE) {
|
|
||||||
discovery->process(
|
|
||||||
desc.handle, UUID(uuid.uuid)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// discover attribute infos of the descriptor
|
|
||||||
ble_error_t err = gattc_attr_info_discover(connectionHandle, desc.handle, desc.handle);
|
|
||||||
if (err) {
|
|
||||||
terminate(discovery, err);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// prepare the next discovery request (if needed)
|
|
||||||
uint16_t startHandle = descriptors.descs[descriptors.count - 1].handle + 1;
|
|
||||||
uint16_t endHandle = discovery->getCharacteristic().getLastHandle();
|
|
||||||
|
|
||||||
if(startHandle > endHandle) {
|
|
||||||
terminate(discovery, BLE_ERROR_NONE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ble_error_t err = gattc_descriptors_discover(connectionHandle, startHandle, endHandle);
|
|
||||||
if(err) {
|
|
||||||
terminate(discovery, err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void nRF5xCharacteristicDescriptorDiscoverer::processAttributeInformation(
|
|
||||||
uint16_t connectionHandle, const ble_gattc_evt_attr_info_disc_rsp_t& infos) {
|
|
||||||
Discovery* discovery = findRunningDiscovery(connectionHandle);
|
|
||||||
// the discovery has been removed
|
|
||||||
if(!discovery) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if (NRF_SD_BLE_API_VERSION <= 2)
|
|
||||||
// for all UUIDS found, process the discovery
|
|
||||||
for (uint16_t i = 0; i < infos.count; ++i) {
|
|
||||||
bool use_16bits_uuids = infos.format == BLE_GATTC_ATTR_INFO_FORMAT_16BIT;
|
|
||||||
const ble_gattc_attr_info_t& attr_info = infos.attr_info[i];
|
|
||||||
UUID uuid = use_16bits_uuids ? UUID(attr_info.info.uuid16.uuid) : UUID(attr_info.info.uuid128.uuid128, UUID::LSB);
|
|
||||||
discovery->process(attr_info.handle, uuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
// prepare the next round of descriptors discovery
|
|
||||||
uint16_t startHandle = infos.attr_info[infos.count - 1].handle + 1;
|
|
||||||
#else
|
|
||||||
uint16_t startHandle;
|
|
||||||
// for all UUIDS found, process the discovery
|
|
||||||
if (infos.format == BLE_GATTC_ATTR_INFO_FORMAT_16BIT) {
|
|
||||||
for (uint16_t i = 0; i < infos.count; ++i) {
|
|
||||||
UUID uuid = UUID(infos.info.attr_info16[i].uuid.uuid);
|
|
||||||
discovery->process(infos.info.attr_info16[i].handle, uuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
// prepare the next round of descriptors discovery
|
|
||||||
startHandle = infos.info.attr_info16[infos.count - 1].handle + 1;
|
|
||||||
} else {
|
|
||||||
for (uint16_t i = 0; i < infos.count; ++i) {
|
|
||||||
UUID uuid = UUID(infos.info.attr_info128[i].uuid.uuid128, UUID::LSB);
|
|
||||||
discovery->process(infos.info.attr_info128[i].handle, uuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
// prepare the next round of descriptors discovery
|
|
||||||
startHandle = infos.info.attr_info128[infos.count - 1].handle + 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
uint16_t endHandle = discovery->getCharacteristic().getLastHandle();
|
|
||||||
|
|
||||||
if(startHandle > endHandle) {
|
|
||||||
terminate(discovery, BLE_ERROR_NONE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ble_error_t err = gattc_descriptors_discover(connectionHandle, startHandle, endHandle);
|
|
||||||
if(err) {
|
|
||||||
terminate(discovery, err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void nRF5xCharacteristicDescriptorDiscoverer::terminate(uint16_t handle, ble_error_t err) {
|
|
||||||
Discovery* discovery = findRunningDiscovery(handle);
|
|
||||||
// the discovery has already been terminated
|
|
||||||
if(!discovery) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
terminate(discovery, err);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nRF5xCharacteristicDescriptorDiscoverer::terminate(Discovery* discovery, ble_error_t err) {
|
|
||||||
// temporary copy, user code can try to launch a new discovery in the onTerminate
|
|
||||||
// callback. So, this discovery should not appear in such case.
|
|
||||||
Discovery tmp = *discovery;
|
|
||||||
*discovery = Discovery();
|
|
||||||
tmp.terminate(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
nRF5xCharacteristicDescriptorDiscoverer::Discovery*
|
|
||||||
nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(const DiscoveredCharacteristic& characteristic) {
|
|
||||||
for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
|
|
||||||
if((discoveryRunning[i].getCharacteristic() == characteristic) &&
|
|
||||||
(discoveryRunning[i].isEmpty() == false)) {
|
|
||||||
return &discoveryRunning[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
nRF5xCharacteristicDescriptorDiscoverer::Discovery*
|
|
||||||
nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(uint16_t handle) {
|
|
||||||
for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
|
|
||||||
if((discoveryRunning[i].getCharacteristic().getConnectionHandle() == handle) &&
|
|
||||||
(discoveryRunning[i].isEmpty() == false)) {
|
|
||||||
return &discoveryRunning[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
nRF5xCharacteristicDescriptorDiscoverer::Discovery*
|
|
||||||
nRF5xCharacteristicDescriptorDiscoverer::getAvailableDiscoverySlot() {
|
|
||||||
for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
|
|
||||||
if(discoveryRunning[i].isEmpty()) {
|
|
||||||
return &discoveryRunning[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool nRF5xCharacteristicDescriptorDiscoverer::isConnectionInUse(uint16_t connHandle) {
|
|
||||||
return findRunningDiscovery(connHandle) != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ble_error_t nRF5xCharacteristicDescriptorDiscoverer::gattc_descriptors_discover(
|
|
||||||
uint16_t connection_handle, uint16_t start_handle, uint16_t end_handle) {
|
|
||||||
|
|
||||||
ble_gattc_handle_range_t discoveryRange = {
|
|
||||||
start_handle,
|
|
||||||
end_handle
|
|
||||||
};
|
|
||||||
uint32_t err = sd_ble_gattc_descriptors_discover(connection_handle, &discoveryRange);
|
|
||||||
|
|
||||||
switch(err) {
|
|
||||||
case NRF_SUCCESS:
|
|
||||||
return BLE_ERROR_NONE;
|
|
||||||
case BLE_ERROR_INVALID_CONN_HANDLE:
|
|
||||||
return BLE_ERROR_INVALID_PARAM;
|
|
||||||
case NRF_ERROR_INVALID_ADDR:
|
|
||||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
|
||||||
case NRF_ERROR_BUSY:
|
|
||||||
return BLE_STACK_BUSY;
|
|
||||||
default:
|
|
||||||
return BLE_ERROR_UNSPECIFIED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ble_error_t nRF5xCharacteristicDescriptorDiscoverer::gattc_attr_info_discover(
|
|
||||||
uint16_t connection_handle, uint16_t start_handle, uint16_t end_handle) {
|
|
||||||
ble_gattc_handle_range_t handle_range = { start_handle, end_handle };
|
|
||||||
uint32_t err = sd_ble_gattc_attr_info_discover(connection_handle, &handle_range);
|
|
||||||
|
|
||||||
switch(err) {
|
|
||||||
case NRF_SUCCESS:
|
|
||||||
return BLE_ERROR_NONE;
|
|
||||||
case BLE_ERROR_INVALID_CONN_HANDLE:
|
|
||||||
return BLE_ERROR_INVALID_PARAM;
|
|
||||||
case NRF_ERROR_INVALID_ADDR:
|
|
||||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
|
||||||
case NRF_ERROR_BUSY:
|
|
||||||
return BLE_STACK_BUSY;
|
|
||||||
case NRF_ERROR_INVALID_STATE:
|
|
||||||
return BLE_ERROR_INVALID_STATE;
|
|
||||||
default:
|
|
||||||
return BLE_ERROR_UNSPECIFIED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// implementation of nRF5xCharacteristicDescriptorDiscoverer::Discovery
|
|
||||||
|
|
||||||
nRF5xCharacteristicDescriptorDiscoverer::Discovery::Discovery() :
|
|
||||||
characteristic(), onDiscovery(), onTerminate() {
|
|
||||||
}
|
|
||||||
|
|
||||||
nRF5xCharacteristicDescriptorDiscoverer::Discovery::Discovery(
|
|
||||||
const DiscoveredCharacteristic& c, const DiscoveryCallback_t& dCb, const TerminationCallback_t& tCb) :
|
|
||||||
characteristic(c), onDiscovery(dCb), onTerminate(tCb) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void nRF5xCharacteristicDescriptorDiscoverer::Discovery::process(
|
|
||||||
GattAttribute::Handle_t handle, const UUID& uuid) {
|
|
||||||
CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t params = {
|
|
||||||
characteristic,
|
|
||||||
DiscoveredCharacteristicDescriptor(
|
|
||||||
characteristic.getGattClient(),
|
|
||||||
characteristic.getConnectionHandle(),
|
|
||||||
handle,
|
|
||||||
uuid
|
|
||||||
)
|
|
||||||
};
|
|
||||||
onDiscovery.call(¶ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nRF5xCharacteristicDescriptorDiscoverer::Discovery::terminate(ble_error_t err) {
|
|
||||||
CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = {
|
|
||||||
characteristic,
|
|
||||||
err
|
|
||||||
};
|
|
||||||
|
|
||||||
onTerminate.call(¶ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool nRF5xCharacteristicDescriptorDiscoverer::Discovery::isEmpty() const {
|
|
||||||
return *this == Discovery();
|
|
||||||
}
|
|
||||||
|
|
||||||
const DiscoveredCharacteristic& nRF5xCharacteristicDescriptorDiscoverer::Discovery::getCharacteristic() const {
|
|
||||||
return characteristic;
|
|
||||||
}
|
|
|
@ -1,227 +0,0 @@
|
||||||
/* mbed Microcontroller Library
|
|
||||||
* Copyright (c) 2006-2015 ARM Limited
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __NRF_CHARACTERISTIC_DESCRIPTOR_DISCOVERY_H__
|
|
||||||
#define __NRF_CHARACTERISTIC_DESCRIPTOR_DISCOVERY_H__
|
|
||||||
|
|
||||||
#include "ble/Gap.h"
|
|
||||||
#include "ble/DiscoveredCharacteristic.h"
|
|
||||||
#include "ble/CharacteristicDescriptorDiscovery.h"
|
|
||||||
#include "ble/GattClient.h"
|
|
||||||
#include "headers/nrf_ble_gattc.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Manage the discovery of Characteristic descriptors
|
|
||||||
* @details is a bridge between BLE API and Nordic stack regarding Characteristic
|
|
||||||
* Descriptor discovery. The BLE API can launch, monitor and ask for termination
|
|
||||||
* of a discovery. The Nordic stack will provide new descriptors and indicate when
|
|
||||||
* the discovery is done.
|
|
||||||
*/
|
|
||||||
class nRF5xCharacteristicDescriptorDiscoverer
|
|
||||||
{
|
|
||||||
typedef CharacteristicDescriptorDiscovery::DiscoveryCallback_t DiscoveryCallback_t;
|
|
||||||
typedef CharacteristicDescriptorDiscovery::TerminationCallback_t TerminationCallback_t;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Construct a new characteristic descriptor discoverer.
|
|
||||||
*/
|
|
||||||
nRF5xCharacteristicDescriptorDiscoverer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Destroy a characteristic descriptor discoverer.
|
|
||||||
*/
|
|
||||||
~nRF5xCharacteristicDescriptorDiscoverer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Launch a new characteristic descriptor discovery for a given DiscoveredCharacteristic.
|
|
||||||
* @param characteristic The characteristic owning the descriptors to discover.
|
|
||||||
* @param discoveryCallback The callback called when a descriptor is discovered.
|
|
||||||
* @param terminationCallback The callback called when the discovery process end.
|
|
||||||
* @return BLE_ERROR_NONE if characteristic descriptor discovery is launched successfully;
|
|
||||||
* else an appropriate error.
|
|
||||||
* @note: this will be called by BLE API side.
|
|
||||||
*/
|
|
||||||
ble_error_t launch(
|
|
||||||
const DiscoveredCharacteristic& characteristic,
|
|
||||||
const DiscoveryCallback_t& discoveryCallback,
|
|
||||||
const TerminationCallback_t& terminationCallback
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief indicate if a characteristic descriptor discovery is active for a
|
|
||||||
* given DiscoveredCharacteristic.
|
|
||||||
* @param characteristic The characteristic for whom the descriptor might be
|
|
||||||
* currently discovered.
|
|
||||||
* @return true if descriptors of characteristic are discovered, false otherwise.
|
|
||||||
* @note: this will be called by BLE API side.
|
|
||||||
*/
|
|
||||||
bool isActive(const DiscoveredCharacteristic& characteristic) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief request the termination of characteristic descriptor discovery
|
|
||||||
* for a give DiscoveredCharacteristic
|
|
||||||
* @param characteristic The characteristic for whom the descriptor discovery
|
|
||||||
* should be stopped.
|
|
||||||
* @note: this will be called by BLE API side.
|
|
||||||
*/
|
|
||||||
void requestTerminate(const DiscoveredCharacteristic& characteristic);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief process descriptors discovered from the Nordic stack.
|
|
||||||
* @param connectionHandle The connection handle upon which descriptors has been
|
|
||||||
* discovered.
|
|
||||||
* @param descriptors Discovered descriptors.
|
|
||||||
* @note This will be called by the Nordic stack.
|
|
||||||
*/
|
|
||||||
void process(uint16_t connectionHandle, const ble_gattc_evt_desc_disc_rsp_t& descriptors);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Called by the Nordic stack when the discovery is over.
|
|
||||||
* @param The connection handle upon which the discovery process is done.
|
|
||||||
* @param err An error if the termination is due to an error.
|
|
||||||
*/
|
|
||||||
void terminate(uint16_t connectionHandle, ble_error_t err);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief process attribute informations from the Nordic stack.
|
|
||||||
* @param connectionHandle The connection handle upon which
|
|
||||||
* attribute informations has been fetch.
|
|
||||||
* @param infos Informations around attribute, in that case the
|
|
||||||
* 128bit UUID of a descriptor.
|
|
||||||
* @note This will be called by the Nordic stack.
|
|
||||||
*/
|
|
||||||
void processAttributeInformation(uint16_t handle, const ble_gattc_evt_attr_info_disc_rsp_t& infos);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// protection against copy construction and assignment
|
|
||||||
nRF5xCharacteristicDescriptorDiscoverer(const nRF5xCharacteristicDescriptorDiscoverer&);
|
|
||||||
nRF5xCharacteristicDescriptorDiscoverer& operator=(const nRF5xCharacteristicDescriptorDiscoverer&);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Discovery process, it store the DiscoveredCharacteristic, the
|
|
||||||
* discovery callback and the termination callback.
|
|
||||||
*/
|
|
||||||
class Discovery {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Construct an empty discovery, such can be considerate as a not running discovery.
|
|
||||||
* @note #isEmpty function will return true
|
|
||||||
*/
|
|
||||||
Discovery();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Construct a valid discovery process.
|
|
||||||
*
|
|
||||||
* @param c the characteristic from whom descriptors will be discovered.
|
|
||||||
* @param dCb The discovery callback called each time a descriptor is discovered.
|
|
||||||
* @param tCb The termination callback called when the discovery terminate.
|
|
||||||
*
|
|
||||||
* @note #isEmpty function will return false
|
|
||||||
*/
|
|
||||||
Discovery(const DiscoveredCharacteristic& c, const DiscoveryCallback_t& dCb, const TerminationCallback_t& tCb);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Process the discovery of a descriptor.
|
|
||||||
*
|
|
||||||
* @param handle The attribute handle of the descriptor found
|
|
||||||
* @param uuid The UUID of the descriptor found.
|
|
||||||
*/
|
|
||||||
void process(GattAttribute::Handle_t handle, const UUID& uuid);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Terminate the discovery process.
|
|
||||||
*
|
|
||||||
* @param err Error associate with the termination
|
|
||||||
* @note after this call #isEmpty function will return true.
|
|
||||||
*/
|
|
||||||
void terminate(ble_error_t err);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief check if the discovery process is empty or not. Empty discovery are
|
|
||||||
* not running.
|
|
||||||
*
|
|
||||||
* @detail Discovery are empty after:
|
|
||||||
* - a default construction
|
|
||||||
* - a copy construction form a default constructed
|
|
||||||
* - an assignment from a default constructed Discovery
|
|
||||||
* @return true if the Discovery is empty and false otherwise.
|
|
||||||
*/
|
|
||||||
bool isEmpty() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief return the characteristic from whom descriptors are discovered.
|
|
||||||
* @return the characteristic from whom descriptors are discovered.
|
|
||||||
*/
|
|
||||||
const DiscoveredCharacteristic& getCharacteristic() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief equal to operator, test if two discovery process are equal
|
|
||||||
*
|
|
||||||
* @param lhs left hand side of the expression
|
|
||||||
* @param rhs right hand side of the expression
|
|
||||||
* @return true if lhs == rhs
|
|
||||||
*/
|
|
||||||
friend bool operator==(const Discovery& lhs, const Discovery& rhs) {
|
|
||||||
return lhs.characteristic == rhs.characteristic &&
|
|
||||||
lhs.onDiscovery == rhs.onDiscovery &&
|
|
||||||
lhs.onTerminate == rhs.onTerminate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief not equal to operator, test if two discovery process are not equal
|
|
||||||
*
|
|
||||||
* @param lhs left hand side of the expression
|
|
||||||
* @param rhs right hand side of the expression
|
|
||||||
* @return true if lhs != rhs
|
|
||||||
*/
|
|
||||||
friend bool operator!=(const Discovery& lhs, const Discovery& rhs) {
|
|
||||||
return !(lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
DiscoveredCharacteristic characteristic;
|
|
||||||
DiscoveryCallback_t onDiscovery;
|
|
||||||
TerminationCallback_t onTerminate;
|
|
||||||
};
|
|
||||||
|
|
||||||
// find a running discovery process
|
|
||||||
Discovery* findRunningDiscovery(const DiscoveredCharacteristic& characteristic);
|
|
||||||
Discovery* findRunningDiscovery(uint16_t handle);
|
|
||||||
|
|
||||||
// Called to terminate a discovery is over.
|
|
||||||
void terminate(Discovery* discovery, ble_error_t err);
|
|
||||||
|
|
||||||
// get one slot for a discovery process
|
|
||||||
Discovery* getAvailableDiscoverySlot();
|
|
||||||
|
|
||||||
// indicate if a connection is already running a discovery
|
|
||||||
bool isConnectionInUse(uint16_t connHandle);
|
|
||||||
|
|
||||||
// low level start of a discovery
|
|
||||||
static ble_error_t gattc_descriptors_discover(uint16_t connection_handle, uint16_t start_handle, uint16_t end_handle);
|
|
||||||
|
|
||||||
// discovery of 128bits UUIDS
|
|
||||||
static ble_error_t gattc_attr_info_discover(uint16_t connection_handle, uint16_t start_handle, uint16_t end_handle);
|
|
||||||
|
|
||||||
// count of concurrent connections which can run a descriptor discovery process
|
|
||||||
static const size_t MAXIMUM_CONCURRENT_CONNECTIONS_COUNT = 3;
|
|
||||||
|
|
||||||
// array of running discoveries
|
|
||||||
Discovery discoveryRunning[MAXIMUM_CONCURRENT_CONNECTIONS_COUNT];
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /*__NRF_CHARACTERISTIC_DESCRIPTOR_DISCOVERY_H__*/
|
|
|
@ -1,63 +0,0 @@
|
||||||
/* mbed Microcontroller Library
|
|
||||||
* Copyright (c) 2006-2013 ARM Limited
|
|
||||||
*
|
|
||||||
* 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 "nRF5xDiscoveredCharacteristic.h"
|
|
||||||
#include "nRF5xGattClient.h"
|
|
||||||
#include "headers/nrf_ble_gatt.h"
|
|
||||||
|
|
||||||
void
|
|
||||||
nRF5xDiscoveredCharacteristic::setup(nRF5xGattClient *gattcIn,
|
|
||||||
Gap::Handle_t connectionHandleIn,
|
|
||||||
ble_gatt_char_props_t propsIn,
|
|
||||||
GattAttribute::Handle_t declHandleIn,
|
|
||||||
GattAttribute::Handle_t valueHandleIn)
|
|
||||||
{
|
|
||||||
gattc = gattcIn;
|
|
||||||
connHandle = connectionHandleIn;
|
|
||||||
declHandle = declHandleIn;
|
|
||||||
valueHandle = valueHandleIn;
|
|
||||||
|
|
||||||
props._broadcast = propsIn.broadcast;
|
|
||||||
props._read = propsIn.read;
|
|
||||||
props._writeWoResp = propsIn.write_wo_resp;
|
|
||||||
props._write = propsIn.write;
|
|
||||||
props._notify = propsIn.notify;
|
|
||||||
props._indicate = propsIn.indicate;
|
|
||||||
props._authSignedWrite = propsIn.auth_signed_wr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nRF5xDiscoveredCharacteristic::setup(nRF5xGattClient *gattcIn,
|
|
||||||
Gap::Handle_t connectionHandleIn,
|
|
||||||
UUID::ShortUUIDBytes_t uuidIn,
|
|
||||||
ble_gatt_char_props_t propsIn,
|
|
||||||
GattAttribute::Handle_t declHandleIn,
|
|
||||||
GattAttribute::Handle_t valueHandleIn)
|
|
||||||
{
|
|
||||||
gattc = gattcIn;
|
|
||||||
connHandle = connectionHandleIn;
|
|
||||||
uuid = uuidIn;
|
|
||||||
declHandle = declHandleIn;
|
|
||||||
valueHandle = valueHandleIn;
|
|
||||||
|
|
||||||
props._broadcast = propsIn.broadcast;
|
|
||||||
props._read = propsIn.read;
|
|
||||||
props._writeWoResp = propsIn.write_wo_resp;
|
|
||||||
props._write = propsIn.write;
|
|
||||||
props._notify = propsIn.notify;
|
|
||||||
props._indicate = propsIn.indicate;
|
|
||||||
props._authSignedWrite = propsIn.auth_signed_wr;
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
/* mbed Microcontroller Library
|
|
||||||
* Copyright (c) 2006-2013 ARM Limited
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __NRF_DISCOVERED_CHARACTERISTIC_H__
|
|
||||||
#define __NRF_DISCOVERED_CHARACTERISTIC_H__
|
|
||||||
|
|
||||||
#include "ble/DiscoveredCharacteristic.h"
|
|
||||||
#include "headers/nrf_ble_gatt.h"
|
|
||||||
|
|
||||||
class nRF5xGattClient; /* forward declaration */
|
|
||||||
|
|
||||||
class nRF5xDiscoveredCharacteristic : public DiscoveredCharacteristic {
|
|
||||||
public:
|
|
||||||
void setup(nRF5xGattClient *gattcIn,
|
|
||||||
Gap::Handle_t connectionHandleIn,
|
|
||||||
ble_gatt_char_props_t propsIn,
|
|
||||||
GattAttribute::Handle_t declHandleIn,
|
|
||||||
GattAttribute::Handle_t valueHandleIn);
|
|
||||||
|
|
||||||
void setup(nRF5xGattClient *gattcIn,
|
|
||||||
Gap::Handle_t connectionHandleIn,
|
|
||||||
UUID::ShortUUIDBytes_t uuidIn,
|
|
||||||
ble_gatt_char_props_t propsIn,
|
|
||||||
GattAttribute::Handle_t declHandleIn,
|
|
||||||
GattAttribute::Handle_t valueHandleIn);
|
|
||||||
|
|
||||||
void setLastHandle(GattAttribute::Handle_t last) {
|
|
||||||
lastHandle = last;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* __NRF_DISCOVERED_CHARACTERISTIC_H__ */
|
|
|
@ -1,50 +0,0 @@
|
||||||
/* mbed Microcontroller Library
|
|
||||||
* Copyright (c) 2006-2013 ARM Limited
|
|
||||||
*
|
|
||||||
* 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 "nRF5xGattClient.h"
|
|
||||||
|
|
||||||
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
|
|
||||||
ble_error_t
|
|
||||||
nRF5xGattClient::launchServiceDiscovery(Gap::Handle_t connectionHandle,
|
|
||||||
ServiceDiscovery::ServiceCallback_t sc,
|
|
||||||
ServiceDiscovery::CharacteristicCallback_t cc,
|
|
||||||
const UUID &matchingServiceUUIDIn,
|
|
||||||
const UUID &matchingCharacteristicUUIDIn)
|
|
||||||
{
|
|
||||||
return _discovery.launch(connectionHandle, sc, cc, matchingServiceUUIDIn, matchingCharacteristicUUIDIn);
|
|
||||||
}
|
|
||||||
|
|
||||||
ble_error_t nRF5xGattClient::discoverCharacteristicDescriptors(
|
|
||||||
const DiscoveredCharacteristic& characteristic,
|
|
||||||
const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback,
|
|
||||||
const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback)
|
|
||||||
{
|
|
||||||
return _characteristicDescriptorDiscoverer.launch(
|
|
||||||
characteristic,
|
|
||||||
discoveryCallback,
|
|
||||||
terminationCallback
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool nRF5xGattClient::isCharacteristicDescriptorsDiscoveryActive(const DiscoveredCharacteristic& characteristic) const {
|
|
||||||
return _characteristicDescriptorDiscoverer.isActive(characteristic);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nRF5xGattClient::terminateCharacteristicDescriptorsDiscovery(const DiscoveredCharacteristic& characteristic) {
|
|
||||||
return _characteristicDescriptorDiscoverer.requestTerminate(characteristic);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,218 +0,0 @@
|
||||||
/* mbed Microcontroller Library
|
|
||||||
* Copyright (c) 2006-2013 ARM Limited
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __NRF51822_GATT_CLIENT_H__
|
|
||||||
#define __NRF51822_GATT_CLIENT_H__
|
|
||||||
|
|
||||||
#include "ble/GattClient.h"
|
|
||||||
#include "nRF5xServiceDiscovery.h"
|
|
||||||
#include "nRF5xCharacteristicDescriptorDiscoverer.h"
|
|
||||||
|
|
||||||
class nRF5xGattClient : public GattClient
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* When using S110, all Gatt client features will return
|
|
||||||
* BLE_ERROR_NOT_IMPLEMENTED
|
|
||||||
*/
|
|
||||||
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Launch service discovery. Once launched, service discovery will remain
|
|
||||||
* active with callbacks being issued back into the application for matching
|
|
||||||
* services/characteristics. isActive() can be used to determine status; and
|
|
||||||
* a termination callback (if setup) will be invoked at the end. Service
|
|
||||||
* discovery can be terminated prematurely if needed using terminate().
|
|
||||||
*
|
|
||||||
* @param connectionHandle
|
|
||||||
* Handle for the connection with the peer.
|
|
||||||
* @param sc
|
|
||||||
* This is the application callback for matching service. Taken as
|
|
||||||
* NULL by default. Note: service discovery may still be active
|
|
||||||
* when this callback is issued; calling asynchronous BLE-stack
|
|
||||||
* APIs from within this application callback might cause the
|
|
||||||
* stack to abort service discovery. If this becomes an issue, it
|
|
||||||
* may be better to make local copy of the discoveredService and
|
|
||||||
* wait for service discovery to terminate before operating on the
|
|
||||||
* service.
|
|
||||||
* @param cc
|
|
||||||
* This is the application callback for matching characteristic.
|
|
||||||
* Taken as NULL by default. Note: service discovery may still be
|
|
||||||
* active when this callback is issued; calling asynchronous
|
|
||||||
* BLE-stack APIs from within this application callback might cause
|
|
||||||
* the stack to abort service discovery. If this becomes an issue,
|
|
||||||
* it may be better to make local copy of the discoveredCharacteristic
|
|
||||||
* and wait for service discovery to terminate before operating on the
|
|
||||||
* characteristic.
|
|
||||||
* @param matchingServiceUUID
|
|
||||||
* UUID based filter for specifying a service in which the application is
|
|
||||||
* interested. By default it is set as the wildcard UUID_UNKNOWN,
|
|
||||||
* in which case it matches all services. If characteristic-UUID
|
|
||||||
* filter (below) is set to the wildcard value, then a service
|
|
||||||
* callback will be invoked for the matching service (or for every
|
|
||||||
* service if the service filter is a wildcard).
|
|
||||||
* @param matchingCharacteristicUUIDIn
|
|
||||||
* UUID based filter for specifying characteristic in which the application
|
|
||||||
* is interested. By default it is set as the wildcard UUID_UKNOWN
|
|
||||||
* to match against any characteristic. If both service-UUID
|
|
||||||
* filter and characteristic-UUID filter are used with non- wildcard
|
|
||||||
* values, then only a single characteristic callback is
|
|
||||||
* invoked for the matching characteristic.
|
|
||||||
*
|
|
||||||
* @Note Using wildcard values for both service-UUID and characteristic-
|
|
||||||
* UUID will result in complete service discovery--callbacks being
|
|
||||||
* called for every service and characteristic.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* BLE_ERROR_NONE if service discovery is launched successfully; else an appropriate error.
|
|
||||||
*/
|
|
||||||
virtual ble_error_t launchServiceDiscovery(Gap::Handle_t connectionHandle,
|
|
||||||
ServiceDiscovery::ServiceCallback_t sc = NULL,
|
|
||||||
ServiceDiscovery::CharacteristicCallback_t cc = NULL,
|
|
||||||
const UUID &matchingServiceUUID = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN),
|
|
||||||
const UUID &matchingCharacteristicUUIDIn = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN));
|
|
||||||
|
|
||||||
virtual void onServiceDiscoveryTermination(ServiceDiscovery::TerminationCallback_t callback) {
|
|
||||||
_discovery.onTermination(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is service-discovery currently active?
|
|
||||||
*/
|
|
||||||
virtual bool isServiceDiscoveryActive(void) const {
|
|
||||||
return _discovery.isActive();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Terminate an ongoing service-discovery. This should result in an
|
|
||||||
* invocation of the TerminationCallback if service-discovery is active.
|
|
||||||
*/
|
|
||||||
virtual void terminateServiceDiscovery(void) {
|
|
||||||
_discovery.terminate();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Implementation of GattClient::discoverCharacteristicDescriptors
|
|
||||||
* @see GattClient::discoverCharacteristicDescriptors
|
|
||||||
*/
|
|
||||||
virtual ble_error_t discoverCharacteristicDescriptors(
|
|
||||||
const DiscoveredCharacteristic& characteristic,
|
|
||||||
const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback,
|
|
||||||
const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Implementation of GattClient::isCharacteristicDiscoveryActive
|
|
||||||
* @see GattClient::isCharacteristicDiscoveryActive
|
|
||||||
*/
|
|
||||||
virtual bool isCharacteristicDescriptorsDiscoveryActive(const DiscoveredCharacteristic& characteristic) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Implementation of GattClient::terminateCharacteristicDiscovery
|
|
||||||
* @see GattClient::terminateCharacteristicDiscovery
|
|
||||||
*/
|
|
||||||
virtual void terminateCharacteristicDescriptorsDiscovery(const DiscoveredCharacteristic& characteristic);
|
|
||||||
|
|
||||||
virtual ble_error_t read(Gap::Handle_t connHandle, GattAttribute::Handle_t attributeHandle, uint16_t offset) const {
|
|
||||||
uint32_t rc = sd_ble_gattc_read(connHandle, attributeHandle, offset);
|
|
||||||
if (rc == NRF_SUCCESS) {
|
|
||||||
return BLE_ERROR_NONE;
|
|
||||||
}
|
|
||||||
switch (rc) {
|
|
||||||
case NRF_ERROR_BUSY:
|
|
||||||
return BLE_STACK_BUSY;
|
|
||||||
case BLE_ERROR_INVALID_CONN_HANDLE:
|
|
||||||
case NRF_ERROR_INVALID_STATE:
|
|
||||||
case NRF_ERROR_INVALID_ADDR:
|
|
||||||
default:
|
|
||||||
return BLE_ERROR_INVALID_STATE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ble_error_t write(GattClient::WriteOp_t cmd, Gap::Handle_t connHandle, GattAttribute::Handle_t attributeHandle, size_t length, const uint8_t *value) const {
|
|
||||||
ble_gattc_write_params_t writeParams;
|
|
||||||
writeParams.write_op = cmd;
|
|
||||||
writeParams.flags = 0; /* this is inconsequential */
|
|
||||||
writeParams.handle = attributeHandle;
|
|
||||||
writeParams.offset = 0;
|
|
||||||
writeParams.len = length;
|
|
||||||
writeParams.p_value = const_cast<uint8_t *>(value);
|
|
||||||
|
|
||||||
uint32_t rc = sd_ble_gattc_write(connHandle, &writeParams);
|
|
||||||
if (rc == NRF_SUCCESS) {
|
|
||||||
return BLE_ERROR_NONE;
|
|
||||||
}
|
|
||||||
switch (rc) {
|
|
||||||
case NRF_ERROR_BUSY:
|
|
||||||
return BLE_STACK_BUSY;
|
|
||||||
case BLE_ERROR_NO_TX_PACKETS:
|
|
||||||
return BLE_ERROR_NO_MEM;
|
|
||||||
case BLE_ERROR_INVALID_CONN_HANDLE:
|
|
||||||
case NRF_ERROR_INVALID_STATE:
|
|
||||||
case NRF_ERROR_INVALID_ADDR:
|
|
||||||
default:
|
|
||||||
return BLE_ERROR_INVALID_STATE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Clear nRF5xGattClient's state.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* BLE_ERROR_NONE if successful.
|
|
||||||
*/
|
|
||||||
virtual ble_error_t reset(void) {
|
|
||||||
/* Clear all state that is from the parent, including private members */
|
|
||||||
if (GattClient::reset() != BLE_ERROR_NONE) {
|
|
||||||
return BLE_ERROR_INVALID_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear derived class members */
|
|
||||||
_discovery.reset();
|
|
||||||
|
|
||||||
return BLE_ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/*
|
|
||||||
* Allow instantiation from nRF5xn when required.
|
|
||||||
*/
|
|
||||||
friend class nRF5xn;
|
|
||||||
|
|
||||||
nRF5xGattClient() : _discovery(this) {
|
|
||||||
/* empty */
|
|
||||||
}
|
|
||||||
|
|
||||||
nRF5xServiceDiscovery& discovery() {
|
|
||||||
return _discovery;
|
|
||||||
}
|
|
||||||
|
|
||||||
nRF5xCharacteristicDescriptorDiscoverer& characteristicDescriptorDiscoverer() {
|
|
||||||
return _characteristicDescriptorDiscoverer;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
nRF5xGattClient(const nRF5xGattClient &);
|
|
||||||
const nRF5xGattClient& operator=(const nRF5xGattClient &);
|
|
||||||
|
|
||||||
private:
|
|
||||||
nRF5xServiceDiscovery _discovery;
|
|
||||||
nRF5xCharacteristicDescriptorDiscoverer _characteristicDescriptorDiscoverer;
|
|
||||||
|
|
||||||
#endif // if !S110
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // ifndef __NRF51822_GATT_CLIENT_H__
|
|
|
@ -1,329 +0,0 @@
|
||||||
/* mbed Microcontroller Library
|
|
||||||
* Copyright (c) 2006-2013 ARM Limited
|
|
||||||
*
|
|
||||||
* 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 "nRF5xServiceDiscovery.h"
|
|
||||||
|
|
||||||
ble_error_t
|
|
||||||
nRF5xServiceDiscovery::launchCharacteristicDiscovery(Gap::Handle_t connectionHandle,
|
|
||||||
Gap::Handle_t startHandle,
|
|
||||||
Gap::Handle_t endHandle)
|
|
||||||
{
|
|
||||||
characteristicDiscoveryStarted(connectionHandle);
|
|
||||||
|
|
||||||
ble_gattc_handle_range_t handleRange = {
|
|
||||||
(uint16_t) startHandle,
|
|
||||||
(uint16_t) endHandle
|
|
||||||
};
|
|
||||||
uint32_t rc = sd_ble_gattc_characteristics_discover(connectionHandle, &handleRange);
|
|
||||||
ble_error_t err = BLE_ERROR_NONE;
|
|
||||||
|
|
||||||
switch (rc) {
|
|
||||||
case NRF_SUCCESS:
|
|
||||||
err = BLE_ERROR_NONE;
|
|
||||||
break;
|
|
||||||
case BLE_ERROR_INVALID_CONN_HANDLE:
|
|
||||||
case NRF_ERROR_INVALID_ADDR:
|
|
||||||
err = BLE_ERROR_INVALID_PARAM;
|
|
||||||
break;
|
|
||||||
case NRF_ERROR_BUSY:
|
|
||||||
err = BLE_STACK_BUSY;
|
|
||||||
break;
|
|
||||||
case NRF_ERROR_INVALID_STATE:
|
|
||||||
err = BLE_ERROR_INVALID_STATE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
err = BLE_ERROR_UNSPECIFIED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err) {
|
|
||||||
terminateCharacteristicDiscovery(err);
|
|
||||||
}
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nRF5xServiceDiscovery::setupDiscoveredServices(const ble_gattc_evt_prim_srvc_disc_rsp_t *response)
|
|
||||||
{
|
|
||||||
serviceIndex = 0;
|
|
||||||
numServices = response->count;
|
|
||||||
|
|
||||||
/* Account for the limitation on the number of discovered services we can handle at a time. */
|
|
||||||
if (numServices > BLE_DB_DISCOVERY_MAX_SRV) {
|
|
||||||
numServices = BLE_DB_DISCOVERY_MAX_SRV;
|
|
||||||
}
|
|
||||||
|
|
||||||
serviceUUIDDiscoveryQueue.reset();
|
|
||||||
for (unsigned i = 0; i < numServices; ++i) {
|
|
||||||
if (response->services[i].uuid.type == BLE_UUID_TYPE_UNKNOWN) {
|
|
||||||
serviceUUIDDiscoveryQueue.enqueue(i);
|
|
||||||
services[i].setup(response->services[i].handle_range.start_handle,
|
|
||||||
response->services[i].handle_range.end_handle);
|
|
||||||
} else {
|
|
||||||
services[i].setup(response->services[i].uuid.uuid,
|
|
||||||
response->services[i].handle_range.start_handle,
|
|
||||||
response->services[i].handle_range.end_handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Trigger discovery of service UUID if necessary. */
|
|
||||||
if (serviceUUIDDiscoveryQueue.getCount()) {
|
|
||||||
serviceUUIDDiscoveryQueue.triggerFirst();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nRF5xServiceDiscovery::setupDiscoveredCharacteristics(const ble_gattc_evt_char_disc_rsp_t *response)
|
|
||||||
{
|
|
||||||
numCharacteristics = response->count;
|
|
||||||
|
|
||||||
/* Account for the limitation on the number of discovered characteristics we can handle at a time. */
|
|
||||||
if (numCharacteristics > BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV) {
|
|
||||||
numCharacteristics = BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV;
|
|
||||||
}
|
|
||||||
|
|
||||||
charUUIDDiscoveryQueue.reset();
|
|
||||||
for (unsigned charIndex = 0; charIndex < numCharacteristics; charIndex++) {
|
|
||||||
if (response->chars[charIndex].uuid.type == BLE_UUID_TYPE_UNKNOWN) {
|
|
||||||
charUUIDDiscoveryQueue.enqueue(charIndex);
|
|
||||||
characteristics[charIndex].setup(gattc,
|
|
||||||
connHandle,
|
|
||||||
response->chars[charIndex].char_props,
|
|
||||||
response->chars[charIndex].handle_decl,
|
|
||||||
response->chars[charIndex].handle_value);
|
|
||||||
} else {
|
|
||||||
characteristics[charIndex].setup(gattc,
|
|
||||||
connHandle,
|
|
||||||
response->chars[charIndex].uuid.uuid,
|
|
||||||
response->chars[charIndex].char_props,
|
|
||||||
response->chars[charIndex].handle_decl,
|
|
||||||
response->chars[charIndex].handle_value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Trigger discovery of char UUID if necessary. */
|
|
||||||
if (charUUIDDiscoveryQueue.getCount()) {
|
|
||||||
charUUIDDiscoveryQueue.triggerFirst();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nRF5xServiceDiscovery::progressCharacteristicDiscovery(void)
|
|
||||||
{
|
|
||||||
if (state != CHARACTERISTIC_DISCOVERY_ACTIVE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((discoveredCharacteristic != nRF5xDiscoveredCharacteristic()) && (numCharacteristics > 0)) {
|
|
||||||
discoveredCharacteristic.setLastHandle(characteristics[0].getDeclHandle() - 1);
|
|
||||||
|
|
||||||
if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) ||
|
|
||||||
((matchingCharacteristicUUID == discoveredCharacteristic.getUUID()) &&
|
|
||||||
(matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) {
|
|
||||||
if (characteristicCallback) {
|
|
||||||
characteristicCallback(&discoveredCharacteristic);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < numCharacteristics; ++i) {
|
|
||||||
if (state != CHARACTERISTIC_DISCOVERY_ACTIVE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == (numCharacteristics - 1)) {
|
|
||||||
discoveredCharacteristic = characteristics[i];
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
characteristics[i].setLastHandle(characteristics[i + 1].getDeclHandle() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) ||
|
|
||||||
((matchingCharacteristicUUID == characteristics[i].getUUID()) &&
|
|
||||||
(matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) {
|
|
||||||
if (characteristicCallback) {
|
|
||||||
characteristicCallback(&characteristics[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state != CHARACTERISTIC_DISCOVERY_ACTIVE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Gap::Handle_t startHandle = (numCharacteristics > 0) ? characteristics[numCharacteristics - 1].getValueHandle() + 1 : SRV_DISC_END_HANDLE;
|
|
||||||
Gap::Handle_t endHandle = services[serviceIndex].getEndHandle();
|
|
||||||
resetDiscoveredCharacteristics(); /* Note: resetDiscoveredCharacteristics() must come after fetching start and end Handles. */
|
|
||||||
|
|
||||||
if (startHandle < endHandle) {
|
|
||||||
ble_gattc_handle_range_t handleRange = {
|
|
||||||
(uint16_t) startHandle,
|
|
||||||
(uint16_t) endHandle
|
|
||||||
};
|
|
||||||
if (sd_ble_gattc_characteristics_discover(connHandle, &handleRange) != NRF_SUCCESS) {
|
|
||||||
terminateCharacteristicDiscovery(BLE_ERROR_UNSPECIFIED);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
terminateCharacteristicDiscovery(BLE_ERROR_NONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nRF5xServiceDiscovery::progressServiceDiscovery(void)
|
|
||||||
{
|
|
||||||
/* Iterate through the previously discovered services cached in services[]. */
|
|
||||||
while ((state == SERVICE_DISCOVERY_ACTIVE) && (serviceIndex < numServices)) {
|
|
||||||
if ((matchingServiceUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) ||
|
|
||||||
(matchingServiceUUID == services[serviceIndex].getUUID())) {
|
|
||||||
|
|
||||||
if (serviceCallback && (matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN))) {
|
|
||||||
serviceCallback(&services[serviceIndex]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((state == SERVICE_DISCOVERY_ACTIVE) && characteristicCallback) {
|
|
||||||
launchCharacteristicDiscovery(connHandle, services[serviceIndex].getStartHandle(), services[serviceIndex].getEndHandle());
|
|
||||||
} else {
|
|
||||||
serviceIndex++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
serviceIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Relaunch discovery of new services beyond the last entry cached in services[]. */
|
|
||||||
if ((state == SERVICE_DISCOVERY_ACTIVE) && (numServices > 0) && (serviceIndex > 0)) {
|
|
||||||
/* Determine the ending handle of the last cached service. */
|
|
||||||
Gap::Handle_t endHandle = services[serviceIndex - 1].getEndHandle();
|
|
||||||
resetDiscoveredServices(); /* Note: resetDiscoveredServices() must come after fetching endHandle. */
|
|
||||||
|
|
||||||
if (endHandle == SRV_DISC_END_HANDLE) {
|
|
||||||
terminateServiceDiscovery();
|
|
||||||
} else {
|
|
||||||
// the next service is located after the last handle discovered
|
|
||||||
// Launch a new discovery from [endHandle + 1 : 0xFFFF]
|
|
||||||
if (sd_ble_gattc_primary_services_discover(connHandle, endHandle + 1, NULL) != NRF_SUCCESS) {
|
|
||||||
terminateServiceDiscovery();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nRF5xServiceDiscovery::ServiceUUIDDiscoveryQueue::triggerFirst(void)
|
|
||||||
{
|
|
||||||
while (numIndices) { /* loop until a call to char_value_by_uuid_read() succeeds or we run out of pending indices. */
|
|
||||||
parentDiscoveryObject->state = DISCOVER_SERVICE_UUIDS;
|
|
||||||
|
|
||||||
unsigned serviceIndex = getFirst();
|
|
||||||
ble_uuid_t uuid = {
|
|
||||||
.uuid = BLE_UUID_SERVICE_PRIMARY,
|
|
||||||
.type = BLE_UUID_TYPE_BLE,
|
|
||||||
};
|
|
||||||
ble_gattc_handle_range_t handleRange = {
|
|
||||||
.start_handle = parentDiscoveryObject->services[serviceIndex].getStartHandle(),
|
|
||||||
.end_handle = parentDiscoveryObject->services[serviceIndex].getEndHandle(),
|
|
||||||
};
|
|
||||||
if (sd_ble_gattc_char_value_by_uuid_read(parentDiscoveryObject->connHandle, &uuid, &handleRange) == NRF_SUCCESS) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skip this service if we fail to launch a read for its service-declaration
|
|
||||||
* attribute. Its UUID will remain INVALID, and it may not match any filters. */
|
|
||||||
dequeue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Switch back to service discovery upon exhausting the service-indices pending UUID discovery. */
|
|
||||||
if (parentDiscoveryObject->state == DISCOVER_SERVICE_UUIDS) {
|
|
||||||
parentDiscoveryObject->state = SERVICE_DISCOVERY_ACTIVE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nRF5xServiceDiscovery::CharUUIDDiscoveryQueue::triggerFirst(void)
|
|
||||||
{
|
|
||||||
while (numIndices) { /* loop until a call to char_value_by_uuid_read() succeeds or we run out of pending indices. */
|
|
||||||
parentDiscoveryObject->state = DISCOVER_CHARACTERISTIC_UUIDS;
|
|
||||||
|
|
||||||
unsigned charIndex = getFirst();
|
|
||||||
ble_uuid_t uuid = {
|
|
||||||
.uuid = BLE_UUID_CHARACTERISTIC,
|
|
||||||
.type = BLE_UUID_TYPE_BLE,
|
|
||||||
};
|
|
||||||
ble_gattc_handle_range_t handleRange = { };
|
|
||||||
handleRange.start_handle = parentDiscoveryObject->characteristics[charIndex].getDeclHandle();
|
|
||||||
handleRange.end_handle = parentDiscoveryObject->characteristics[charIndex].getDeclHandle() + 1;
|
|
||||||
if (sd_ble_gattc_char_value_by_uuid_read(parentDiscoveryObject->connHandle, &uuid, &handleRange) == NRF_SUCCESS) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skip this service if we fail to launch a read for its service-declaration
|
|
||||||
* attribute. Its UUID will remain INVALID, and it may not match any filters. */
|
|
||||||
dequeue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Switch back to service discovery upon exhausting the service-indices pending UUID discovery. */
|
|
||||||
if (parentDiscoveryObject->state == DISCOVER_CHARACTERISTIC_UUIDS) {
|
|
||||||
parentDiscoveryObject->state = CHARACTERISTIC_DISCOVERY_ACTIVE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nRF5xServiceDiscovery::processDiscoverUUIDResponse(const ble_gattc_evt_t *p_gattc_evt)
|
|
||||||
{
|
|
||||||
const ble_gattc_evt_char_val_by_uuid_read_rsp_t * response = &p_gattc_evt->params.char_val_by_uuid_read_rsp;
|
|
||||||
|
|
||||||
if (state == DISCOVER_SERVICE_UUIDS) {
|
|
||||||
if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID)) {
|
|
||||||
UUID::LongUUIDBytes_t uuid;
|
|
||||||
|
|
||||||
#if (NRF_SD_BLE_API_VERSION >= 3)
|
|
||||||
ble_gattc_handle_value_t iter;
|
|
||||||
memset(&iter, 0, sizeof(ble_gattc_handle_value_t));
|
|
||||||
(void) sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter(const_cast<ble_gattc_evt_t*>(p_gattc_evt), &iter);
|
|
||||||
memcpy(uuid, iter.p_value, UUID::LENGTH_OF_LONG_UUID);
|
|
||||||
#else
|
|
||||||
memcpy(uuid, &(response->handle_value[0].p_value[0]), UUID::LENGTH_OF_LONG_UUID);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
unsigned serviceIndex = serviceUUIDDiscoveryQueue.dequeue();
|
|
||||||
services[serviceIndex].setupLongUUID(uuid, UUID::LSB);
|
|
||||||
|
|
||||||
serviceUUIDDiscoveryQueue.triggerFirst();
|
|
||||||
} else {
|
|
||||||
serviceUUIDDiscoveryQueue.dequeue();
|
|
||||||
}
|
|
||||||
} else if (state == DISCOVER_CHARACTERISTIC_UUIDS) {
|
|
||||||
if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID + 1 /* props */ + 2 /* value handle */)) {
|
|
||||||
UUID::LongUUIDBytes_t uuid;
|
|
||||||
|
|
||||||
#if (NRF_SD_BLE_API_VERSION >= 3)
|
|
||||||
ble_gattc_handle_value_t iter;
|
|
||||||
memset(&iter, 0, sizeof(ble_gattc_handle_value_t));
|
|
||||||
(void) sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter(const_cast<ble_gattc_evt_t*>(p_gattc_evt), &iter);
|
|
||||||
memcpy(uuid, &(iter.p_value[3]), UUID::LENGTH_OF_LONG_UUID);
|
|
||||||
#else
|
|
||||||
memcpy(uuid, &(response->handle_value[0].p_value[3]), UUID::LENGTH_OF_LONG_UUID);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
unsigned charIndex = charUUIDDiscoveryQueue.dequeue();
|
|
||||||
characteristics[charIndex].setupLongUUID(uuid, UUID::LSB);
|
|
||||||
|
|
||||||
charUUIDDiscoveryQueue.triggerFirst();
|
|
||||||
} else {
|
|
||||||
charUUIDDiscoveryQueue.dequeue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,366 +0,0 @@
|
||||||
/* mbed Microcontroller Library
|
|
||||||
* Copyright (c) 2006-2013 ARM Limited
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __NRF_SERVICE_DISCOVERY_H__
|
|
||||||
#define __NRF_SERVICE_DISCOVERY_H__
|
|
||||||
|
|
||||||
#include "ble/ServiceDiscovery.h"
|
|
||||||
#include "ble/DiscoveredService.h"
|
|
||||||
#include "nRF5xDiscoveredCharacteristic.h"
|
|
||||||
|
|
||||||
#include "headers/nrf_ble.h"
|
|
||||||
#include "headers/nrf_ble_gattc.h"
|
|
||||||
|
|
||||||
class nRF5xGattClient; /* forward declaration */
|
|
||||||
|
|
||||||
class nRF5xServiceDiscovery : public ServiceDiscovery
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const uint16_t SRV_DISC_START_HANDLE = 0x0001; /**< The start handle value used during service discovery. */
|
|
||||||
static const uint16_t SRV_DISC_END_HANDLE = 0xFFFF; /**< The end handle value used during service discovery. */
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const unsigned BLE_DB_DISCOVERY_MAX_SRV = 4; /**< Maximum number of services we can retain information for after a single discovery. */
|
|
||||||
static const unsigned BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV = 4; /**< Maximum number of characteristics per service we can retain information for. */
|
|
||||||
|
|
||||||
public:
|
|
||||||
nRF5xServiceDiscovery(nRF5xGattClient *gattcIn) :
|
|
||||||
gattc(gattcIn),
|
|
||||||
serviceIndex(0),
|
|
||||||
numServices(0),
|
|
||||||
numCharacteristics(0),
|
|
||||||
state(INACTIVE),
|
|
||||||
services(),
|
|
||||||
characteristics(),
|
|
||||||
serviceUUIDDiscoveryQueue(this),
|
|
||||||
charUUIDDiscoveryQueue(this),
|
|
||||||
onTerminationCallback(NULL) {
|
|
||||||
/* empty */
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ble_error_t launch(Gap::Handle_t connectionHandle,
|
|
||||||
ServiceDiscovery::ServiceCallback_t sc,
|
|
||||||
ServiceDiscovery::CharacteristicCallback_t cc,
|
|
||||||
const UUID &matchingServiceUUIDIn,
|
|
||||||
const UUID &matchingCharacteristicUUIDIn)
|
|
||||||
{
|
|
||||||
if (isActive()) {
|
|
||||||
return BLE_ERROR_INVALID_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
serviceCallback = sc;
|
|
||||||
characteristicCallback = cc;
|
|
||||||
matchingServiceUUID = matchingServiceUUIDIn;
|
|
||||||
matchingCharacteristicUUID = matchingCharacteristicUUIDIn;
|
|
||||||
|
|
||||||
serviceDiscoveryStarted(connectionHandle);
|
|
||||||
|
|
||||||
uint32_t rc;
|
|
||||||
if ((rc = sd_ble_gattc_primary_services_discover(connectionHandle, SRV_DISC_START_HANDLE, NULL)) != NRF_SUCCESS) {
|
|
||||||
terminate();
|
|
||||||
switch (rc) {
|
|
||||||
case NRF_ERROR_INVALID_PARAM:
|
|
||||||
case BLE_ERROR_INVALID_CONN_HANDLE:
|
|
||||||
return BLE_ERROR_INVALID_PARAM;
|
|
||||||
case NRF_ERROR_BUSY:
|
|
||||||
return BLE_STACK_BUSY;
|
|
||||||
default:
|
|
||||||
case NRF_ERROR_INVALID_STATE:
|
|
||||||
return BLE_ERROR_INVALID_STATE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return BLE_ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool isActive(void) const {
|
|
||||||
return state != INACTIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void terminate(void) {
|
|
||||||
terminateServiceDiscovery();
|
|
||||||
}
|
|
||||||
|
|
||||||
void terminate(Gap::Handle_t connectionHandle) {
|
|
||||||
if(connHandle == connectionHandle) {
|
|
||||||
terminate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void onTermination(ServiceDiscovery::TerminationCallback_t callback) {
|
|
||||||
onTerminationCallback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Clear nRF5xServiceDiscovery's state.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* BLE_ERROR_NONE if successful.
|
|
||||||
*/
|
|
||||||
virtual ble_error_t reset(void) {
|
|
||||||
/* Clear all state that is from the parent, including private members */
|
|
||||||
if (ServiceDiscovery::reset() != BLE_ERROR_NONE) {
|
|
||||||
return BLE_ERROR_INVALID_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear derived class members */
|
|
||||||
serviceIndex = 0;
|
|
||||||
numServices = 0;
|
|
||||||
numCharacteristics = 0;
|
|
||||||
|
|
||||||
state = INACTIVE;
|
|
||||||
|
|
||||||
serviceUUIDDiscoveryQueue.reset();
|
|
||||||
charUUIDDiscoveryQueue.reset();
|
|
||||||
|
|
||||||
onTerminationCallback = NULL;
|
|
||||||
|
|
||||||
return BLE_ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
ble_error_t launchCharacteristicDiscovery(Gap::Handle_t connectionHandle, Gap::Handle_t startHandle, Gap::Handle_t endHandle);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void setupDiscoveredServices(const ble_gattc_evt_prim_srvc_disc_rsp_t *response);
|
|
||||||
void setupDiscoveredCharacteristics(const ble_gattc_evt_char_disc_rsp_t *response);
|
|
||||||
|
|
||||||
void triggerServiceUUIDDiscovery(void);
|
|
||||||
void processDiscoverUUIDResponse(const ble_gattc_evt_t *p_gattc_evt);
|
|
||||||
void removeFirstServiceNeedingUUIDDiscovery(void);
|
|
||||||
|
|
||||||
void terminateServiceDiscovery(void) {
|
|
||||||
discoveredCharacteristic = nRF5xDiscoveredCharacteristic();
|
|
||||||
|
|
||||||
bool wasActive = isActive();
|
|
||||||
state = INACTIVE;
|
|
||||||
|
|
||||||
if (wasActive && onTerminationCallback) {
|
|
||||||
onTerminationCallback(connHandle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void terminateCharacteristicDiscovery(ble_error_t err) {
|
|
||||||
if (state == CHARACTERISTIC_DISCOVERY_ACTIVE) {
|
|
||||||
if(discoveredCharacteristic != nRF5xDiscoveredCharacteristic()) {
|
|
||||||
if(err == BLE_ERROR_NONE) {
|
|
||||||
// fullfill the last characteristic
|
|
||||||
discoveredCharacteristic.setLastHandle(services[serviceIndex].getEndHandle());
|
|
||||||
|
|
||||||
if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) ||
|
|
||||||
((matchingCharacteristicUUID == discoveredCharacteristic.getUUID()) &&
|
|
||||||
(matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) {
|
|
||||||
if (characteristicCallback) {
|
|
||||||
characteristicCallback(&discoveredCharacteristic);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
discoveredCharacteristic = nRF5xDiscoveredCharacteristic();
|
|
||||||
}
|
|
||||||
|
|
||||||
state = SERVICE_DISCOVERY_ACTIVE;
|
|
||||||
}
|
|
||||||
serviceIndex++; /* Progress service index to keep discovery alive. */
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void resetDiscoveredServices(void) {
|
|
||||||
numServices = 0;
|
|
||||||
serviceIndex = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void resetDiscoveredCharacteristics(void) {
|
|
||||||
numCharacteristics = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void serviceDiscoveryStarted(Gap::Handle_t connectionHandle) {
|
|
||||||
connHandle = connectionHandle;
|
|
||||||
resetDiscoveredServices();
|
|
||||||
state = SERVICE_DISCOVERY_ACTIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void characteristicDiscoveryStarted(Gap::Handle_t connectionHandle) {
|
|
||||||
connHandle = connectionHandle;
|
|
||||||
resetDiscoveredCharacteristics();
|
|
||||||
state = CHARACTERISTIC_DISCOVERY_ACTIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* A datatype to contain service-indices for which long UUIDs need to be
|
|
||||||
* discovered using read_val_by_uuid().
|
|
||||||
*/
|
|
||||||
class ServiceUUIDDiscoveryQueue {
|
|
||||||
public:
|
|
||||||
ServiceUUIDDiscoveryQueue(nRF5xServiceDiscovery *parent) :
|
|
||||||
numIndices(0),
|
|
||||||
serviceIndices(),
|
|
||||||
parentDiscoveryObject(parent) {
|
|
||||||
/* empty */
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
void reset(void) {
|
|
||||||
numIndices = 0;
|
|
||||||
for (unsigned i = 0; i < BLE_DB_DISCOVERY_MAX_SRV; i++) {
|
|
||||||
serviceIndices[i] = INVALID_INDEX;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void enqueue(int serviceIndex) {
|
|
||||||
serviceIndices[numIndices++] = serviceIndex;
|
|
||||||
}
|
|
||||||
int dequeue(void) {
|
|
||||||
if (numIndices == 0) {
|
|
||||||
return INVALID_INDEX;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned valueToReturn = serviceIndices[0];
|
|
||||||
numIndices--;
|
|
||||||
for (unsigned i = 0; i < numIndices; i++) {
|
|
||||||
serviceIndices[i] = serviceIndices[i + 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return valueToReturn;
|
|
||||||
}
|
|
||||||
unsigned getFirst(void) const {
|
|
||||||
return serviceIndices[0];
|
|
||||||
}
|
|
||||||
size_t getCount(void) const {
|
|
||||||
return numIndices;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Trigger UUID discovery for the first of the enqueued ServiceIndices.
|
|
||||||
*/
|
|
||||||
void triggerFirst(void);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static const int INVALID_INDEX = -1;
|
|
||||||
|
|
||||||
private:
|
|
||||||
size_t numIndices;
|
|
||||||
int serviceIndices[BLE_DB_DISCOVERY_MAX_SRV];
|
|
||||||
|
|
||||||
nRF5xServiceDiscovery *parentDiscoveryObject;
|
|
||||||
};
|
|
||||||
friend class ServiceUUIDDiscoveryQueue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A datatype to contain characteristic-indices for which long UUIDs need to
|
|
||||||
* be discovered using read_val_by_uuid().
|
|
||||||
*/
|
|
||||||
class CharUUIDDiscoveryQueue {
|
|
||||||
public:
|
|
||||||
CharUUIDDiscoveryQueue(nRF5xServiceDiscovery *parent) :
|
|
||||||
numIndices(0),
|
|
||||||
charIndices(),
|
|
||||||
parentDiscoveryObject(parent) {
|
|
||||||
/* empty */
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
void reset(void) {
|
|
||||||
numIndices = 0;
|
|
||||||
for (unsigned i = 0; i < BLE_DB_DISCOVERY_MAX_SRV; i++) {
|
|
||||||
charIndices[i] = INVALID_INDEX;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void enqueue(int serviceIndex) {
|
|
||||||
charIndices[numIndices++] = serviceIndex;
|
|
||||||
}
|
|
||||||
int dequeue(void) {
|
|
||||||
if (numIndices == 0) {
|
|
||||||
return INVALID_INDEX;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned valueToReturn = charIndices[0];
|
|
||||||
numIndices--;
|
|
||||||
for (unsigned i = 0; i < numIndices; i++) {
|
|
||||||
charIndices[i] = charIndices[i + 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return valueToReturn;
|
|
||||||
}
|
|
||||||
unsigned getFirst(void) const {
|
|
||||||
return charIndices[0];
|
|
||||||
}
|
|
||||||
size_t getCount(void) const {
|
|
||||||
return numIndices;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Trigger UUID discovery for the first of the enqueued charIndices.
|
|
||||||
*/
|
|
||||||
void triggerFirst(void);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static const int INVALID_INDEX = -1;
|
|
||||||
|
|
||||||
private:
|
|
||||||
size_t numIndices;
|
|
||||||
int charIndices[BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV];
|
|
||||||
|
|
||||||
nRF5xServiceDiscovery *parentDiscoveryObject;
|
|
||||||
};
|
|
||||||
friend class CharUUIDDiscoveryQueue;
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend void bleGattcEventHandler(const ble_evt_t *p_ble_evt);
|
|
||||||
void progressCharacteristicDiscovery(void);
|
|
||||||
void progressServiceDiscovery(void);
|
|
||||||
|
|
||||||
private:
|
|
||||||
nRF5xGattClient *gattc;
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint8_t serviceIndex; /**< Index of the current service being discovered. This is intended for internal use during service discovery.*/
|
|
||||||
uint8_t numServices; /**< Number of services at the peers GATT database.*/
|
|
||||||
uint8_t numCharacteristics; /**< Number of characteristics within the service.*/
|
|
||||||
|
|
||||||
enum State_t {
|
|
||||||
INACTIVE,
|
|
||||||
SERVICE_DISCOVERY_ACTIVE,
|
|
||||||
CHARACTERISTIC_DISCOVERY_ACTIVE,
|
|
||||||
DISCOVER_SERVICE_UUIDS,
|
|
||||||
DISCOVER_CHARACTERISTIC_UUIDS,
|
|
||||||
} state;
|
|
||||||
|
|
||||||
DiscoveredService services[BLE_DB_DISCOVERY_MAX_SRV]; /**< Information related to the current service being discovered.
|
|
||||||
* This is intended for internal use during service discovery. */
|
|
||||||
nRF5xDiscoveredCharacteristic characteristics[BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV];
|
|
||||||
|
|
||||||
ServiceUUIDDiscoveryQueue serviceUUIDDiscoveryQueue;
|
|
||||||
CharUUIDDiscoveryQueue charUUIDDiscoveryQueue;
|
|
||||||
|
|
||||||
TerminationCallback_t onTerminationCallback;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The currently discovered characteristic. Discovery of a characteristic
|
|
||||||
* is a two phase process.
|
|
||||||
* First, declaration handle is fetched, it provide the UUID, the value handle and
|
|
||||||
* the properties of a characteristic.
|
|
||||||
* Second, the next declaration handle is fetched, with its declaration handle, it is
|
|
||||||
* possible to compute the last handle of the discovered characteristic and fill the
|
|
||||||
* missing part of the object.
|
|
||||||
* If there is no remaining characteristic to discover, the last handle of the
|
|
||||||
* discovered characteristic will be set to the last handle of its enclosing service.
|
|
||||||
*/
|
|
||||||
nRF5xDiscoveredCharacteristic discoveredCharacteristic;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /*__NRF_SERVICE_DISCOVERY_H__*/
|
|
|
@ -31,6 +31,8 @@ extern "C" {
|
||||||
#include "softdevice_handler.h"
|
#include "softdevice_handler.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "nRF5XPalGattClient.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The singleton which represents the nRF51822 transport for the BLE.
|
* The singleton which represents the nRF51822 transport for the BLE.
|
||||||
*/
|
*/
|
||||||
|
@ -60,7 +62,7 @@ nRF5xn::nRF5xn(void) :
|
||||||
instanceID(BLE::DEFAULT_INSTANCE),
|
instanceID(BLE::DEFAULT_INSTANCE),
|
||||||
gapInstance(),
|
gapInstance(),
|
||||||
gattServerInstance(NULL),
|
gattServerInstance(NULL),
|
||||||
gattClientInstance(NULL),
|
gattClient(&(ble::pal::vendor::nordic::nRF5XGattClient::get_client())),
|
||||||
securityManagerInstance(NULL)
|
securityManagerInstance(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -189,11 +191,9 @@ ble_error_t nRF5xn::shutdown(void)
|
||||||
|
|
||||||
/* S110 does not support BLE client features, nothing to reset. */
|
/* S110 does not support BLE client features, nothing to reset. */
|
||||||
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
|
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
|
||||||
if (gattClientInstance != NULL) {
|
error = getGattClient().reset();
|
||||||
error = gattClientInstance->reset();
|
if (error != BLE_ERROR_NONE) {
|
||||||
if (error != BLE_ERROR_NONE) {
|
return error;
|
||||||
return error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,10 @@
|
||||||
#include "ble/BLE.h"
|
#include "ble/BLE.h"
|
||||||
#include "ble/blecommon.h"
|
#include "ble/blecommon.h"
|
||||||
#include "ble/BLEInstanceBase.h"
|
#include "ble/BLEInstanceBase.h"
|
||||||
|
#include "ble/generic/GenericGattClient.h"
|
||||||
|
|
||||||
#include "nRF5xGap.h"
|
#include "nRF5xGap.h"
|
||||||
#include "nRF5xGattServer.h"
|
#include "nRF5xGattServer.h"
|
||||||
#include "nRF5xGattClient.h"
|
|
||||||
#include "nRF5xSecurityManager.h"
|
#include "nRF5xSecurityManager.h"
|
||||||
|
|
||||||
#include "btle.h"
|
#include "btle.h"
|
||||||
|
@ -77,11 +77,8 @@ public:
|
||||||
*
|
*
|
||||||
* @return A reference to GattClient.
|
* @return A reference to GattClient.
|
||||||
*/
|
*/
|
||||||
virtual nRF5xGattClient &getGattClient() {
|
virtual GattClient &getGattClient() {
|
||||||
if (gattClientInstance == NULL) {
|
return gattClient;
|
||||||
gattClientInstance = new nRF5xGattClient();
|
|
||||||
}
|
|
||||||
return *gattClientInstance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -171,10 +168,8 @@ private:
|
||||||
* If NULL, then GattServer has not been initialized.
|
* If NULL, then GattServer has not been initialized.
|
||||||
* The pointer has been declared as 'mutable' so that
|
* The pointer has been declared as 'mutable' so that
|
||||||
* it can be assigned inside a 'const' function. */
|
* it can be assigned inside a 'const' function. */
|
||||||
mutable nRF5xGattClient *gattClientInstance; /**< Pointer to the GattClient object instance.
|
ble::generic::GenericGattClient gattClient;
|
||||||
* If NULL, then GattClient has not been initialized.
|
|
||||||
* The pointer has been declared as 'mutable' so that
|
|
||||||
* it can be assigned inside a 'const' function. */
|
|
||||||
mutable nRF5xSecurityManager *securityManagerInstance; /**< Pointer to the SecurityManager object instance.
|
mutable nRF5xSecurityManager *securityManagerInstance; /**< Pointer to the SecurityManager object instance.
|
||||||
* If NULL, then SecurityManager has not been initialized.
|
* If NULL, then SecurityManager has not been initialized.
|
||||||
* The pointer has been declared as 'mutable' so that
|
* The pointer has been declared as 'mutable' so that
|
||||||
|
|
|
@ -0,0 +1,227 @@
|
||||||
|
/* mbed Microcontroller Library
|
||||||
|
* Copyright (c) 2017 ARM Limited
|
||||||
|
*
|
||||||
|
* 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 "fsl_iocon.h"
|
||||||
|
|
||||||
|
#define IOCON_PIO_DIGITAL_EN 0x0100u /*!<@brief Enables digital function */
|
||||||
|
#define IOCON_PIO_FUNC0 0x00u /*!<@brief Selects pin function 0 */
|
||||||
|
#define IOCON_PIO_FUNC1 0x01u /*!<@brief Selects pin function 1 */
|
||||||
|
#define IOCON_PIO_FUNC6 0x06u /*!<@brief Selects pin function 6 */
|
||||||
|
#define IOCON_PIO_FUNC7 0x07u /*!<@brief Selects pin function 7 */
|
||||||
|
#define IOCON_PIO_INPFILT_OFF 0x0200u /*!<@brief Input filter disabled */
|
||||||
|
#define IOCON_PIO_INV_DI 0x00u /*!<@brief Input function is not inverted */
|
||||||
|
#define IOCON_PIO_MODE_INACT 0x00u /*!<@brief No addition pin function */
|
||||||
|
#define IOCON_PIO_MODE_PULLUP 0x20u /*!<@brief Selects pull-up function */
|
||||||
|
#define IOCON_PIO_OPENDRAIN_DI 0x00u /*!<@brief Open drain is disabled */
|
||||||
|
#define IOCON_PIO_SLEW_FAST 0x0400u /*!<@brief Fast mode, slew rate control is disabled */
|
||||||
|
#define IOCON_PIO_SLEW_STANDARD 0x00u /*!<@brief Standard mode, output slew rate control is enabled */
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Code
|
||||||
|
******************************************************************************/
|
||||||
|
void lpc546xx_init_eth_hardware(void)
|
||||||
|
{
|
||||||
|
CLOCK_EnableClock(kCLOCK_InputMux);
|
||||||
|
|
||||||
|
/* Enables the clock for the IOCON block. 0 = Disable; 1 = Enable.: 0x01u */
|
||||||
|
CLOCK_EnableClock(kCLOCK_Iocon);
|
||||||
|
|
||||||
|
const uint32_t port0_pin10_config = (/* Pin is configured as SWO */
|
||||||
|
IOCON_PIO_FUNC6 |
|
||||||
|
/* No addition pin function */
|
||||||
|
IOCON_PIO_MODE_INACT |
|
||||||
|
/* Input function is not inverted */
|
||||||
|
IOCON_PIO_INV_DI |
|
||||||
|
/* Enables digital function */
|
||||||
|
IOCON_PIO_DIGITAL_EN |
|
||||||
|
/* Input filter disabled */
|
||||||
|
IOCON_PIO_INPFILT_OFF |
|
||||||
|
/* Open drain is disabled */
|
||||||
|
IOCON_PIO_OPENDRAIN_DI);
|
||||||
|
/* PORT0 PIN10 (coords: P2) is configured as SWO */
|
||||||
|
IOCON_PinMuxSet(IOCON, 0U, 10U, port0_pin10_config);
|
||||||
|
|
||||||
|
const uint32_t port1_pin10_config = (/* Pin is configured as ENET_TXD1 */
|
||||||
|
IOCON_PIO_FUNC1 /* IOCON_PIO_FUNC1 */ |
|
||||||
|
/* No addition pin function */
|
||||||
|
IOCON_PIO_MODE_INACT |
|
||||||
|
/* Input function is not inverted */
|
||||||
|
IOCON_PIO_INV_DI |
|
||||||
|
/* Enables digital function */
|
||||||
|
IOCON_PIO_DIGITAL_EN |
|
||||||
|
/* Input filter disabled */
|
||||||
|
IOCON_PIO_INPFILT_OFF |
|
||||||
|
/* Standard mode, output slew rate control is enabled */
|
||||||
|
IOCON_PIO_SLEW_STANDARD |
|
||||||
|
/* Open drain is disabled */
|
||||||
|
IOCON_PIO_OPENDRAIN_DI);
|
||||||
|
/* PORT1 PIN10 (coords: E14) is configured as ENET_TXD1 */
|
||||||
|
IOCON_PinMuxSet(IOCON, 1U, 10U, port1_pin10_config);
|
||||||
|
|
||||||
|
|
||||||
|
const uint32_t port1_pin18_config = (/* Pin is configured as ENET_PHY_RST */
|
||||||
|
IOCON_PIO_FUNC0 |
|
||||||
|
/* Selects pull-up function */
|
||||||
|
IOCON_PIO_MODE_PULLUP |
|
||||||
|
/* Input function is not inverted */
|
||||||
|
IOCON_PIO_INV_DI |
|
||||||
|
/* Enables digital function */
|
||||||
|
IOCON_PIO_DIGITAL_EN |
|
||||||
|
/* Input filter disabled */
|
||||||
|
IOCON_PIO_INPFILT_OFF |
|
||||||
|
/* Standard mode, output slew rate control is enabled */
|
||||||
|
IOCON_PIO_SLEW_STANDARD |
|
||||||
|
/* Open drain is disabled */
|
||||||
|
IOCON_PIO_OPENDRAIN_DI);
|
||||||
|
/* PORT1 PIN18 (coords: H11) is configured as ENET_PHY_RST */
|
||||||
|
IOCON_PinMuxSet(IOCON, 1U, 18U, port1_pin18_config);
|
||||||
|
|
||||||
|
const uint32_t port1_pin14_config = (/* Pin is configured as ENET_RX_DV */
|
||||||
|
IOCON_PIO_FUNC1 |
|
||||||
|
/* No addition pin function */
|
||||||
|
IOCON_PIO_MODE_INACT |
|
||||||
|
/* Input function is not inverted */
|
||||||
|
IOCON_PIO_INV_DI |
|
||||||
|
/* Enables digital function */
|
||||||
|
IOCON_PIO_DIGITAL_EN |
|
||||||
|
/* Input filter disabled */
|
||||||
|
IOCON_PIO_INPFILT_OFF |
|
||||||
|
/* Standard mode, output slew rate control is enabled */
|
||||||
|
IOCON_PIO_SLEW_STANDARD |
|
||||||
|
/* Open drain is disabled */
|
||||||
|
IOCON_PIO_OPENDRAIN_DI);
|
||||||
|
/* PORT1 PIN14 (coords: B9) is configured as ENET_RX_DV */
|
||||||
|
IOCON_PinMuxSet(IOCON, 1U, 14U, port1_pin14_config);
|
||||||
|
|
||||||
|
const uint32_t port1_pin12_config = (/* Pin is configured as ENET_RXD0 */
|
||||||
|
IOCON_PIO_FUNC1 |
|
||||||
|
/* No addition pin function */
|
||||||
|
IOCON_PIO_MODE_INACT |
|
||||||
|
/* Input function is not inverted */
|
||||||
|
IOCON_PIO_INV_DI |
|
||||||
|
/* Enables digital function */
|
||||||
|
IOCON_PIO_DIGITAL_EN |
|
||||||
|
/* Input filter disabled */
|
||||||
|
IOCON_PIO_INPFILT_OFF |
|
||||||
|
/* Standard mode, output slew rate control is enabled */
|
||||||
|
IOCON_PIO_SLEW_STANDARD |
|
||||||
|
/* Open drain is disabled */
|
||||||
|
IOCON_PIO_OPENDRAIN_DI);
|
||||||
|
/* PORT1 PIN12 (coords: A9) is configured as ENET_RXD0 */
|
||||||
|
IOCON_PinMuxSet(IOCON, 1U, 12U, port1_pin12_config);
|
||||||
|
|
||||||
|
const uint32_t port1_pin13_config = (/* Pin is configured as ENET_RXD1 */
|
||||||
|
IOCON_PIO_FUNC1 |
|
||||||
|
/* No addition pin function */
|
||||||
|
IOCON_PIO_MODE_INACT |
|
||||||
|
/* Input function is not inverted */
|
||||||
|
IOCON_PIO_INV_DI |
|
||||||
|
/* Enables digital function */
|
||||||
|
IOCON_PIO_DIGITAL_EN |
|
||||||
|
/* Input filter disabled */
|
||||||
|
IOCON_PIO_INPFILT_OFF |
|
||||||
|
/* Standard mode, output slew rate control is enabled */
|
||||||
|
IOCON_PIO_SLEW_STANDARD |
|
||||||
|
/* Open drain is disabled */
|
||||||
|
IOCON_PIO_OPENDRAIN_DI);
|
||||||
|
/* PORT4 PIN12 (coords: A6) is configured as ENET_RXD1 */
|
||||||
|
IOCON_PinMuxSet(IOCON, 1U, 13U, port1_pin13_config);
|
||||||
|
|
||||||
|
const uint32_t port1_pin11_config = (/* Pin is configured as ENET_TX_EN */
|
||||||
|
IOCON_PIO_FUNC1 |
|
||||||
|
/* No addition pin function */
|
||||||
|
IOCON_PIO_MODE_INACT |
|
||||||
|
/* Input function is not inverted */
|
||||||
|
IOCON_PIO_INV_DI |
|
||||||
|
/* Enables digital function */
|
||||||
|
IOCON_PIO_DIGITAL_EN |
|
||||||
|
/* Input filter disabled */
|
||||||
|
IOCON_PIO_INPFILT_OFF |
|
||||||
|
/* Standard mode, output slew rate control is enabled */
|
||||||
|
IOCON_PIO_SLEW_STANDARD |
|
||||||
|
/* Open drain is disabled */
|
||||||
|
IOCON_PIO_OPENDRAIN_DI);
|
||||||
|
/* PORT4 PIN13 (coords: B6) is configured as ENET_TX_EN */
|
||||||
|
IOCON_PinMuxSet(IOCON, 1U, 11U, port1_pin11_config);
|
||||||
|
|
||||||
|
const uint32_t port1_pin15_config = (/* Pin is configured as ENET_RX_CLK */
|
||||||
|
IOCON_PIO_FUNC1 |
|
||||||
|
/* No addition pin function */
|
||||||
|
IOCON_PIO_MODE_INACT |
|
||||||
|
/* Input function is not inverted */
|
||||||
|
IOCON_PIO_INV_DI |
|
||||||
|
/* Enables digital function */
|
||||||
|
IOCON_PIO_DIGITAL_EN |
|
||||||
|
/* Input filter disabled */
|
||||||
|
IOCON_PIO_INPFILT_OFF |
|
||||||
|
/* Standard mode, output slew rate control is enabled */
|
||||||
|
IOCON_PIO_SLEW_STANDARD |
|
||||||
|
/* Open drain is disabled */
|
||||||
|
IOCON_PIO_OPENDRAIN_DI);
|
||||||
|
/* PORT4 PIN14 (coords: B5) is configured as ENET_RX_CLK */
|
||||||
|
IOCON_PinMuxSet(IOCON, 1U, 15U, port1_pin15_config);
|
||||||
|
|
||||||
|
const uint32_t port1_pin16_config = (/* Pin is configured as ENET_MDC */
|
||||||
|
IOCON_PIO_FUNC1 |
|
||||||
|
/* No addition pin function */
|
||||||
|
IOCON_PIO_MODE_INACT |
|
||||||
|
/* Input function is not inverted */
|
||||||
|
IOCON_PIO_INV_DI |
|
||||||
|
/* Enables digital function */
|
||||||
|
IOCON_PIO_DIGITAL_EN |
|
||||||
|
/* Input filter disabled */
|
||||||
|
IOCON_PIO_INPFILT_OFF |
|
||||||
|
/* Standard mode, output slew rate control is enabled */
|
||||||
|
IOCON_PIO_SLEW_STANDARD |
|
||||||
|
/* Open drain is disabled */
|
||||||
|
IOCON_PIO_OPENDRAIN_DI);
|
||||||
|
/* PORT4 PIN15 (coords: A4) is configured as ENET_MDC */
|
||||||
|
IOCON_PinMuxSet(IOCON, 1U, 16U, port1_pin16_config);
|
||||||
|
|
||||||
|
const uint32_t port1_pin17_config = (/* Pin is configured as ENET_MDIO */
|
||||||
|
IOCON_PIO_FUNC1 |
|
||||||
|
/* No addition pin function */
|
||||||
|
IOCON_PIO_MODE_INACT |
|
||||||
|
/* Input function is not inverted */
|
||||||
|
IOCON_PIO_INV_DI |
|
||||||
|
/* Enables digital function */
|
||||||
|
IOCON_PIO_DIGITAL_EN |
|
||||||
|
/* Input filter disabled */
|
||||||
|
IOCON_PIO_INPFILT_OFF |
|
||||||
|
/* Standard mode, output slew rate control is enabled */
|
||||||
|
IOCON_PIO_SLEW_STANDARD |
|
||||||
|
/* Open drain is disabled */
|
||||||
|
IOCON_PIO_OPENDRAIN_DI);
|
||||||
|
/* PORT4 PIN16 (coords: C4) is configured as ENET_MDIO */
|
||||||
|
IOCON_PinMuxSet(IOCON, 1U, 17U, port1_pin17_config);
|
||||||
|
|
||||||
|
const uint32_t port1_pin9_config = (/* Pin is configured as ENET_TXD0 */
|
||||||
|
IOCON_PIO_FUNC1 |
|
||||||
|
/* No addition pin function */
|
||||||
|
IOCON_PIO_MODE_INACT |
|
||||||
|
/* Input function is not inverted */
|
||||||
|
IOCON_PIO_INV_DI |
|
||||||
|
/* Enables digital function */
|
||||||
|
IOCON_PIO_DIGITAL_EN |
|
||||||
|
/* Input filter disabled */
|
||||||
|
IOCON_PIO_INPFILT_OFF |
|
||||||
|
/* Standard mode, output slew rate control is enabled */
|
||||||
|
IOCON_PIO_SLEW_STANDARD |
|
||||||
|
/* Open drain is disabled */
|
||||||
|
IOCON_PIO_OPENDRAIN_DI);
|
||||||
|
/* PORT4 PIN8 (coords: B14) is configured as ENET_TXD0 */
|
||||||
|
IOCON_PinMuxSet(IOCON, 1U, 9U, port1_pin9_config);
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/* mbed Microcontroller Library
|
||||||
|
* Copyright (c) 2017 ARM Limited
|
||||||
|
*
|
||||||
|
* 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 "stm32f4xx_hal.h"
|
||||||
|
|
||||||
|
void _eth_config_mac(ETH_HandleTypeDef *heth)
|
||||||
|
{
|
||||||
|
ETH_MACInitTypeDef macconf =
|
||||||
|
{
|
||||||
|
.Watchdog = ETH_WATCHDOG_ENABLE,
|
||||||
|
.Jabber = ETH_JABBER_ENABLE,
|
||||||
|
.InterFrameGap = ETH_INTERFRAMEGAP_96BIT,
|
||||||
|
.CarrierSense = ETH_CARRIERSENCE_ENABLE,
|
||||||
|
.ReceiveOwn = ETH_RECEIVEOWN_ENABLE,
|
||||||
|
.LoopbackMode = ETH_LOOPBACKMODE_DISABLE,
|
||||||
|
.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE,
|
||||||
|
.RetryTransmission = ETH_RETRYTRANSMISSION_DISABLE,
|
||||||
|
.AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE,
|
||||||
|
.BackOffLimit = ETH_BACKOFFLIMIT_10,
|
||||||
|
.DeferralCheck = ETH_DEFFERRALCHECK_DISABLE,
|
||||||
|
.ReceiveAll = ETH_RECEIVEAll_DISABLE,
|
||||||
|
.SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE,
|
||||||
|
.PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL,
|
||||||
|
.BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE,
|
||||||
|
.DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL,
|
||||||
|
.PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE,
|
||||||
|
.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_NONE, // Disable multicast filter
|
||||||
|
.UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT,
|
||||||
|
.HashTableHigh = 0x0U,
|
||||||
|
.HashTableLow = 0x0U,
|
||||||
|
.PauseTime = 0x0U,
|
||||||
|
.ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE,
|
||||||
|
.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4,
|
||||||
|
.UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE,
|
||||||
|
.ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE,
|
||||||
|
.TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE,
|
||||||
|
.VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT,
|
||||||
|
.VLANTagIdentifier = 0x0U
|
||||||
|
};
|
||||||
|
|
||||||
|
if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE) {
|
||||||
|
macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE;
|
||||||
|
} else {
|
||||||
|
macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void) HAL_ETH_ConfigMAC(heth, &macconf);
|
||||||
|
}
|
|
@ -0,0 +1,159 @@
|
||||||
|
/* Copyright (c) 2017 ARM Limited
|
||||||
|
*
|
||||||
|
* 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 <string.h>
|
||||||
|
#include "stm32f4xx_hal.h"
|
||||||
|
#include "mbed_toolchain.h"
|
||||||
|
|
||||||
|
#define C029_OTP_START_ADDRESS (0x1FFF7800U)
|
||||||
|
#define C029_OTP_END_ADDRESS (C029_OTP_START_ADDRESS + (16*32))
|
||||||
|
#define C029_MAC_ETHERNET_ID (3)
|
||||||
|
|
||||||
|
typedef MBED_PACKED(struct) C029_OTP_Header {
|
||||||
|
uint8_t id;
|
||||||
|
uint8_t len;
|
||||||
|
uint8_t data[];
|
||||||
|
} C029_OTP_Header;
|
||||||
|
|
||||||
|
static int _macRetrieved = 0;
|
||||||
|
static char _macAddr[6] = { 0x02, 0x02, 0xF7, 0xF0, 0x00, 0x00 };
|
||||||
|
|
||||||
|
static C029_OTP_Header *increment(C029_OTP_Header *pTemp)
|
||||||
|
{
|
||||||
|
uint8_t len = 0;
|
||||||
|
uint8_t id = 0;
|
||||||
|
uint8_t *p = (uint8_t*)pTemp;
|
||||||
|
|
||||||
|
memcpy((void*)&id, (void*)pTemp, 1);
|
||||||
|
|
||||||
|
if (id == 0xFF){
|
||||||
|
p++;
|
||||||
|
} else {
|
||||||
|
p++;
|
||||||
|
memcpy((void*)&len, (void*)p++, 1);
|
||||||
|
p += len;
|
||||||
|
}
|
||||||
|
return (C029_OTP_Header*)p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override HAL Eth Init function
|
||||||
|
*/
|
||||||
|
void HAL_ETH_MspInit(ETH_HandleTypeDef* heth)
|
||||||
|
{
|
||||||
|
GPIO_InitTypeDef GPIO_InitStructure;
|
||||||
|
if (heth->Instance == ETH) {
|
||||||
|
|
||||||
|
/* Enable GPIOs clocks */
|
||||||
|
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||||
|
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||||
|
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||||
|
|
||||||
|
/** ETH GPIO Configuration
|
||||||
|
RMII_REF_CLK ----------------------> PA1
|
||||||
|
RMII_MDIO -------------------------> PA2
|
||||||
|
RMII_MDC --------------------------> PC1
|
||||||
|
RMII_MII_CRS_DV -------------------> PA7
|
||||||
|
RMII_MII_RXD0 ---------------------> PC4
|
||||||
|
RMII_MII_RXD1 ---------------------> PC5
|
||||||
|
RMII_MII_RXER ---------------------> PG2
|
||||||
|
RMII_MII_TX_EN --------------------> PB11
|
||||||
|
RMII_MII_TXD0 ---------------------> PB12
|
||||||
|
RMII_MII_TXD1 ---------------------> PB13
|
||||||
|
*/
|
||||||
|
/* Configure PA1, PA2 and PA7 */
|
||||||
|
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
|
||||||
|
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
|
||||||
|
GPIO_InitStructure.Pull = GPIO_PULLUP;
|
||||||
|
GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_7;
|
||||||
|
GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
|
||||||
|
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||||
|
|
||||||
|
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||||
|
GPIO_InitStructure.Pin = GPIO_PIN_1;
|
||||||
|
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||||
|
|
||||||
|
/* Configure PB13 */
|
||||||
|
GPIO_InitStructure.Pin = GPIO_PIN_13 | GPIO_PIN_11 | GPIO_PIN_12;
|
||||||
|
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||||
|
|
||||||
|
/* Configure PC1, PC4 and PC5 */
|
||||||
|
GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
|
||||||
|
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
|
||||||
|
|
||||||
|
/* Enable the Ethernet global Interrupt */
|
||||||
|
HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0);
|
||||||
|
HAL_NVIC_EnableIRQ(ETH_IRQn);
|
||||||
|
|
||||||
|
/* Enable ETHERNET clock */
|
||||||
|
__HAL_RCC_ETH_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override HAL Eth DeInit function
|
||||||
|
*/
|
||||||
|
void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth)
|
||||||
|
{
|
||||||
|
if (heth->Instance == ETH) {
|
||||||
|
/* Peripheral clock disable */
|
||||||
|
__HAL_RCC_ETH_CLK_DISABLE();
|
||||||
|
|
||||||
|
/** ETH GPIO Configuration
|
||||||
|
RMII_REF_CLK ----------------------> PA1
|
||||||
|
RMII_MDIO -------------------------> PA2
|
||||||
|
RMII_MDC --------------------------> PC1
|
||||||
|
RMII_MII_CRS_DV -------------------> PA7
|
||||||
|
RMII_MII_RXD0 ---------------------> PC4
|
||||||
|
RMII_MII_RXD1 ---------------------> PC5
|
||||||
|
RMII_MII_RXER ---------------------> PG2
|
||||||
|
RMII_MII_TX_EN --------------------> PB11
|
||||||
|
RMII_MII_TXD0 ---------------------> PB12
|
||||||
|
RMII_MII_TXD1 ---------------------> PB13
|
||||||
|
*/
|
||||||
|
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7);
|
||||||
|
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13 | GPIO_PIN_11 | GPIO_PIN_12);
|
||||||
|
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5);
|
||||||
|
|
||||||
|
/* Disable the Ethernet global Interrupt */
|
||||||
|
NVIC_DisableIRQ(ETH_IRQn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t mbed_otp_mac_address(char *mac)
|
||||||
|
{
|
||||||
|
C029_OTP_Header *pFound = NULL;
|
||||||
|
C029_OTP_Header *pTemp = (C029_OTP_Header*)C029_OTP_START_ADDRESS;
|
||||||
|
C029_OTP_Header temp;
|
||||||
|
|
||||||
|
if (_macRetrieved == 0) {
|
||||||
|
while ((pTemp >= (C029_OTP_Header*)C029_OTP_START_ADDRESS) && (pTemp < (C029_OTP_Header*)C029_OTP_END_ADDRESS)){
|
||||||
|
memcpy((void*)&temp, (void*)pTemp, sizeof(temp));
|
||||||
|
if (temp.id == C029_MAC_ETHERNET_ID){
|
||||||
|
pFound = pTemp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pTemp = increment(pTemp);
|
||||||
|
}
|
||||||
|
if (pFound != NULL) {
|
||||||
|
memcpy(_macAddr, pFound->data, 6);
|
||||||
|
_macRetrieved = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memcpy(mac, _macAddr, 6);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -1635,13 +1635,13 @@ lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file,
|
||||||
if (whence == LFS_SEEK_SET) {
|
if (whence == LFS_SEEK_SET) {
|
||||||
file->pos = off;
|
file->pos = off;
|
||||||
} else if (whence == LFS_SEEK_CUR) {
|
} else if (whence == LFS_SEEK_CUR) {
|
||||||
if ((lfs_off_t)-off > file->pos) {
|
if (off < 0 && (lfs_off_t)-off > file->pos) {
|
||||||
return LFS_ERR_INVAL;
|
return LFS_ERR_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
file->pos = file->pos + off;
|
file->pos = file->pos + off;
|
||||||
} else if (whence == LFS_SEEK_END) {
|
} else if (whence == LFS_SEEK_END) {
|
||||||
if ((lfs_off_t)-off > file->size) {
|
if (off < 0 && (lfs_off_t)-off > file->size) {
|
||||||
return LFS_ERR_INVAL;
|
return LFS_ERR_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -133,6 +133,14 @@ tests/test.py << TEST
|
||||||
lfs_file_read(&lfs, &file[0], buffer, size) => size;
|
lfs_file_read(&lfs, &file[0], buffer, size) => size;
|
||||||
memcmp(buffer, "kittycatcat", size) => 0;
|
memcmp(buffer, "kittycatcat", size) => 0;
|
||||||
|
|
||||||
|
lfs_file_seek(&lfs, &file[0], 0, LFS_SEEK_CUR) => size;
|
||||||
|
lfs_file_read(&lfs, &file[0], buffer, size) => size;
|
||||||
|
memcmp(buffer, "kittycatcat", size) => 0;
|
||||||
|
|
||||||
|
lfs_file_seek(&lfs, &file[0], size, LFS_SEEK_CUR) => 3*size;
|
||||||
|
lfs_file_read(&lfs, &file[0], buffer, size) => size;
|
||||||
|
memcmp(buffer, "kittycatcat", size) => 0;
|
||||||
|
|
||||||
lfs_file_seek(&lfs, &file[0], pos, LFS_SEEK_SET) => pos;
|
lfs_file_seek(&lfs, &file[0], pos, LFS_SEEK_SET) => pos;
|
||||||
lfs_file_read(&lfs, &file[0], buffer, size) => size;
|
lfs_file_read(&lfs, &file[0], buffer, size) => size;
|
||||||
memcmp(buffer, "kittycatcat", size) => 0;
|
memcmp(buffer, "kittycatcat", size) => 0;
|
||||||
|
@ -174,6 +182,14 @@ tests/test.py << TEST
|
||||||
lfs_file_read(&lfs, &file[0], buffer, size) => size;
|
lfs_file_read(&lfs, &file[0], buffer, size) => size;
|
||||||
memcmp(buffer, "kittycatcat", size) => 0;
|
memcmp(buffer, "kittycatcat", size) => 0;
|
||||||
|
|
||||||
|
lfs_file_seek(&lfs, &file[0], 0, LFS_SEEK_CUR) => size;
|
||||||
|
lfs_file_read(&lfs, &file[0], buffer, size) => size;
|
||||||
|
memcmp(buffer, "kittycatcat", size) => 0;
|
||||||
|
|
||||||
|
lfs_file_seek(&lfs, &file[0], size, LFS_SEEK_CUR) => 3*size;
|
||||||
|
lfs_file_read(&lfs, &file[0], buffer, size) => size;
|
||||||
|
memcmp(buffer, "kittycatcat", size) => 0;
|
||||||
|
|
||||||
lfs_file_seek(&lfs, &file[0], pos, LFS_SEEK_SET) => pos;
|
lfs_file_seek(&lfs, &file[0], pos, LFS_SEEK_SET) => pos;
|
||||||
lfs_file_read(&lfs, &file[0], buffer, size) => size;
|
lfs_file_read(&lfs, &file[0], buffer, size) => size;
|
||||||
memcmp(buffer, "kittycatcat", size) => 0;
|
memcmp(buffer, "kittycatcat", size) => 0;
|
||||||
|
|
|
@ -23,9 +23,5 @@
|
||||||
#define MBEDTLS_SHA512_ALT
|
#define MBEDTLS_SHA512_ALT
|
||||||
|
|
||||||
#define MBEDTLS_AES_ALT
|
#define MBEDTLS_AES_ALT
|
||||||
#define MBEDTLS_AES_SETKEY_ENC_ALT
|
|
||||||
#define MBEDTLS_AES_SETKEY_DEC_ALT
|
|
||||||
#define MBEDTLS_AES_ENCRYPT_ALT
|
|
||||||
#define MBEDTLS_AES_DECRYPT_ALT
|
|
||||||
|
|
||||||
#endif /* MBEDTLS_DEVICE_H */
|
#endif /* MBEDTLS_DEVICE_H */
|
||||||
|
|
|
@ -21,298 +21,229 @@
|
||||||
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/aes.h"
|
||||||
#include "mbedtls/config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_AES_C)
|
#if defined(MBEDTLS_AES_C)
|
||||||
#if defined(MBEDTLS_AES_ALT)
|
#if defined(MBEDTLS_AES_ALT)
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include "mbedtls/aes.h"
|
|
||||||
|
|
||||||
#include "M480.h"
|
#include "M480.h"
|
||||||
#include "mbed_toolchain.h"
|
#include "mbed_toolchain.h"
|
||||||
#include "mbed_assert.h"
|
#include "mbed_assert.h"
|
||||||
|
#include "mbed_error.h"
|
||||||
|
#include "nu_bitutil.h"
|
||||||
|
#include "crypto-misc.h"
|
||||||
#define mbedtls_trace(...) //printf(__VA_ARGS__)
|
|
||||||
|
|
||||||
/* Implementation that should never be optimized out by the compiler */
|
/* Implementation that should never be optimized out by the compiler */
|
||||||
static void mbedtls_zeroize( void *v, size_t n ) {
|
static void mbedtls_zeroize( void *v, size_t n )
|
||||||
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
|
{
|
||||||
|
volatile unsigned char *p = (unsigned char*)v;
|
||||||
|
while( n-- ) *p++ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* AES DMA compatible backup buffer if user buffer doesn't meet requirements
|
||||||
static uint32_t au32MyAESIV[4] = {
|
*
|
||||||
0x00000000, 0x00000000, 0x00000000, 0x00000000
|
* AES DMA buffer location requires to be:
|
||||||
};
|
* (1) Word-aligned
|
||||||
|
* (2) Located in 0x2xxxxxxx region. Check linker files to ensure global variables are placed in this region.
|
||||||
extern volatile int g_AES_done;
|
*
|
||||||
|
* AES DMA buffer size MAX_DMA_CHAIN_SIZE must be a multiple of 16-byte block size.
|
||||||
// Must be a multiple of 16 bytes block size
|
* Its value is estimated to trade memory footprint off against performance.
|
||||||
|
*
|
||||||
|
*/
|
||||||
#define MAX_DMA_CHAIN_SIZE (16*6)
|
#define MAX_DMA_CHAIN_SIZE (16*6)
|
||||||
MBED_ALIGN(4) static uint8_t au8OutputData[MAX_DMA_CHAIN_SIZE];
|
MBED_ALIGN(4) static uint8_t au8OutputData[MAX_DMA_CHAIN_SIZE];
|
||||||
MBED_ALIGN(4) static uint8_t au8InputData[MAX_DMA_CHAIN_SIZE];
|
MBED_ALIGN(4) static uint8_t au8InputData[MAX_DMA_CHAIN_SIZE];
|
||||||
|
|
||||||
static void dumpHex(const unsigned char au8Data[], int len)
|
|
||||||
{
|
|
||||||
int j;
|
|
||||||
for (j = 0; j < len; j++) mbedtls_trace("%02x ", au8Data[j]);
|
|
||||||
mbedtls_trace("\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void swapInitVector(unsigned char iv[16])
|
|
||||||
{
|
|
||||||
unsigned int* piv;
|
|
||||||
int i;
|
|
||||||
// iv SWAP
|
|
||||||
piv = (unsigned int*)iv;
|
|
||||||
for( i=0; i< 4; i++)
|
|
||||||
{
|
|
||||||
*piv = (((*piv) & 0x000000FF) << 24) |
|
|
||||||
(((*piv) & 0x0000FF00) << 8) |
|
|
||||||
(((*piv) & 0x00FF0000) >> 8) |
|
|
||||||
(((*piv) & 0xFF000000) >> 24);
|
|
||||||
piv++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* IRQHandler: To share CRYPTO_IRQHandler() with TRNG & other crypto IPs
|
|
||||||
For ex:
|
|
||||||
volatile void CRYPTO_IRQHandler()
|
|
||||||
{
|
|
||||||
...
|
|
||||||
if (AES_GET_INT_FLAG()) {
|
|
||||||
g_AES_done = 1;
|
|
||||||
AES_CLR_INT_FLAG();
|
|
||||||
}
|
|
||||||
...
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* AES available channel 0~3 */
|
|
||||||
static unsigned char channel_flag[4]={0x00,0x00,0x00,0x00}; // 0: idle, 1: busy
|
|
||||||
static int channel_alloc()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for(i=0; i< (int)sizeof(channel_flag); i++)
|
|
||||||
{
|
|
||||||
if( channel_flag[i] == 0x00 )
|
|
||||||
{
|
|
||||||
channel_flag[i] = 0x01;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void channel_free(int i)
|
|
||||||
{
|
|
||||||
if( i >=0 && i < (int)sizeof(channel_flag) )
|
|
||||||
channel_flag[i] = 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void mbedtls_aes_init( mbedtls_aes_context *ctx )
|
void mbedtls_aes_init( mbedtls_aes_context *ctx )
|
||||||
{
|
{
|
||||||
int i =-1;
|
|
||||||
|
|
||||||
|
|
||||||
mbedtls_trace("=== %s \r\n", __FUNCTION__);
|
|
||||||
memset( ctx, 0, sizeof( mbedtls_aes_context ) );
|
memset( ctx, 0, sizeof( mbedtls_aes_context ) );
|
||||||
|
|
||||||
ctx->swapType = AES_IN_OUT_SWAP;
|
|
||||||
while( (i = channel_alloc()) < 0 )
|
|
||||||
{
|
|
||||||
mbed_assert_internal("No available AES channel", __FILE__, __LINE__);
|
|
||||||
}
|
|
||||||
ctx->channel = i;
|
|
||||||
ctx->iv = au32MyAESIV;
|
|
||||||
|
|
||||||
/* Unlock protected registers */
|
|
||||||
SYS_UnlockReg();
|
|
||||||
CLK_EnableModuleClock(CRPT_MODULE);
|
|
||||||
/* Lock protected registers */
|
|
||||||
SYS_LockReg();
|
|
||||||
|
|
||||||
NVIC_EnableIRQ(CRPT_IRQn);
|
|
||||||
AES_ENABLE_INT();
|
|
||||||
mbedtls_trace("=== %s channel[%d]\r\n", __FUNCTION__, (int)ctx->channel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_aes_free( mbedtls_aes_context *ctx )
|
void mbedtls_aes_free( mbedtls_aes_context *ctx )
|
||||||
{
|
{
|
||||||
|
|
||||||
mbedtls_trace("=== %s channel[%d]\r\n", __FUNCTION__,(int)ctx->channel);
|
|
||||||
|
|
||||||
if( ctx == NULL )
|
if( ctx == NULL )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
channel_free(ctx->channel);
|
|
||||||
mbedtls_zeroize( ctx, sizeof( mbedtls_aes_context ) );
|
mbedtls_zeroize( ctx, sizeof( mbedtls_aes_context ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AES key schedule (encryption)
|
* AES key schedule (encryption)
|
||||||
*/
|
*/
|
||||||
#if defined(MBEDTLS_AES_SETKEY_ENC_ALT)
|
|
||||||
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
|
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
|
||||||
unsigned int keybits )
|
unsigned int keybits )
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
mbedtls_trace("=== %s keybits[%d]\r\n", __FUNCTION__, keybits);
|
|
||||||
dumpHex(key,keybits/8);
|
|
||||||
|
|
||||||
switch( keybits )
|
switch( keybits ) {
|
||||||
{
|
case 128:
|
||||||
case 128:
|
ctx->keySize = AES_KEY_SIZE_128;
|
||||||
ctx->keySize = AES_KEY_SIZE_128;
|
break;
|
||||||
break;
|
case 192:
|
||||||
case 192:
|
ctx->keySize = AES_KEY_SIZE_192;
|
||||||
ctx->keySize = AES_KEY_SIZE_192;
|
break;
|
||||||
break;
|
case 256:
|
||||||
case 256:
|
ctx->keySize = AES_KEY_SIZE_256;
|
||||||
ctx->keySize = AES_KEY_SIZE_256;
|
break;
|
||||||
break;
|
default :
|
||||||
default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
|
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fetch key byte data in big-endian */
|
||||||
|
for( i = 0; i < ( keybits >> 5 ); i++ ) {
|
||||||
// key swap
|
ctx->keys[i] = nu_get32_be(key + i * 4);
|
||||||
for( i = 0; i < ( keybits >> 5 ); i++ )
|
}
|
||||||
{
|
|
||||||
ctx->buf[i] = (*(key+i*4) << 24) |
|
|
||||||
(*(key+1+i*4) << 16) |
|
|
||||||
(*(key+2+i*4) << 8) |
|
|
||||||
(*(key+3+i*4) );
|
|
||||||
}
|
|
||||||
AES_SetKey(ctx->channel, ctx->buf, ctx->keySize);
|
|
||||||
|
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
#endif /* MBEDTLS_AES_SETKEY_ENC_ALT */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AES key schedule (decryption)
|
* AES key schedule (decryption)
|
||||||
*/
|
*/
|
||||||
#if defined(MBEDTLS_AES_SETKEY_DEC_ALT)
|
|
||||||
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
|
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
|
||||||
unsigned int keybits )
|
unsigned int keybits )
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
mbedtls_trace("=== %s keybits[%d]\r\n", __FUNCTION__, keybits);
|
|
||||||
dumpHex((uint8_t *)key,keybits/8);
|
|
||||||
|
|
||||||
/* Also checks keybits */
|
/* Also checks keybits */
|
||||||
if( ( ret = mbedtls_aes_setkey_enc( ctx, key, keybits ) ) != 0 )
|
if( ( ret = mbedtls_aes_setkey_enc( ctx, key, keybits ) ) != 0 )
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
|
||||||
return( ret );
|
return( ret );
|
||||||
}
|
}
|
||||||
#endif /* MBEDTLS_AES_SETKEY_DEC_ALT */
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Do AES encrypt/decrypt with H/W accelerator
|
||||||
|
*
|
||||||
|
* NOTE: As input/output buffer doesn't follow constraint of DMA buffer, static allocated
|
||||||
|
* DMA compatible buffer is used for DMA instead and this needs extra copy.
|
||||||
|
*
|
||||||
|
* NOTE: dataSize requires to be:
|
||||||
|
* 1) Multiple of block size 16
|
||||||
|
* 2) <= MAX_DMA_CHAIN_SIZE
|
||||||
|
*/
|
||||||
static void __nvt_aes_crypt( mbedtls_aes_context *ctx,
|
static void __nvt_aes_crypt( mbedtls_aes_context *ctx,
|
||||||
const unsigned char input[16],
|
const unsigned char *input,
|
||||||
unsigned char output[16], int dataSize)
|
unsigned char *output, size_t dataSize)
|
||||||
{
|
{
|
||||||
unsigned char* pIn;
|
const unsigned char* pIn;
|
||||||
unsigned char* pOut;
|
unsigned char* pOut;
|
||||||
|
|
||||||
// mbedtls_trace("=== %s \r\n", __FUNCTION__);
|
MBED_ASSERT((dataSize % 16 == 0) && (dataSize <= MAX_DMA_CHAIN_SIZE));
|
||||||
dumpHex(input,16);
|
|
||||||
|
/* AES DMA buffer has the following requirements:
|
||||||
AES_Open(ctx->channel, ctx->encDec, ctx->opMode, ctx->keySize, ctx->swapType);
|
* (1) Word-aligned buffer base address
|
||||||
AES_SetInitVect(ctx->channel, ctx->iv);
|
* (2) 16-byte aligned buffer size
|
||||||
if( ((uint32_t)input) & 0x03 )
|
* (3) Located in 0x20000000-0x2FFFFFFF region
|
||||||
{
|
*/
|
||||||
memcpy(au8InputData, input, dataSize);
|
if ((! crypto_dma_buff_compat(au8OutputData, MAX_DMA_CHAIN_SIZE, 16)) ||
|
||||||
pIn = au8InputData;
|
(! crypto_dma_buff_compat(au8InputData, MAX_DMA_CHAIN_SIZE, 16))) {
|
||||||
}else{
|
error("Buffer for AES alter. DMA requires to be word-aligned and located in 0x20000000-0x2FFFFFFF region.");
|
||||||
pIn = (unsigned char*)input;
|
|
||||||
}
|
}
|
||||||
if( (((uint32_t)output) & 0x03) || (dataSize%4)) // HW CFB output byte count must be multiple of word
|
|
||||||
{
|
|
||||||
pOut = au8OutputData;
|
|
||||||
} else {
|
|
||||||
pOut = output;
|
|
||||||
}
|
|
||||||
|
|
||||||
AES_SetDMATransfer(ctx->channel, (uint32_t)pIn, (uint32_t)pOut, dataSize);
|
/* TODO: Change busy-wait to other means to release CPU */
|
||||||
|
/* Acquire ownership of AES H/W */
|
||||||
|
while (! crypto_aes_acquire());
|
||||||
|
|
||||||
|
/* Init crypto module */
|
||||||
|
crypto_init();
|
||||||
|
/* Enable AES interrupt */
|
||||||
|
AES_ENABLE_INT();
|
||||||
|
|
||||||
|
/* We support multiple contexts with context save & restore and so needs just one
|
||||||
|
* H/W channel. Always use H/W channel #0. */
|
||||||
|
|
||||||
g_AES_done = 0;
|
/* AES_IN_OUT_SWAP: Let H/W know both input/output data are arranged in little-endian */
|
||||||
AES_Start(ctx->channel, CRYPTO_DMA_ONE_SHOT);
|
AES_Open(0, ctx->encDec, ctx->opMode, ctx->keySize, AES_IN_OUT_SWAP);
|
||||||
while (!g_AES_done);
|
AES_SetInitVect(0, ctx->iv);
|
||||||
|
AES_SetKey(0, ctx->keys, ctx->keySize);
|
||||||
|
|
||||||
|
/* AES DMA buffer requirements same as above */
|
||||||
|
if (! crypto_dma_buff_compat(input, dataSize, 16)) {
|
||||||
|
memcpy(au8InputData, input, dataSize);
|
||||||
|
pIn = au8InputData;
|
||||||
|
} else {
|
||||||
|
pIn = input;
|
||||||
|
}
|
||||||
|
/* AES DMA buffer requirements same as above */
|
||||||
|
if (! crypto_dma_buff_compat(output, dataSize, 16)) {
|
||||||
|
pOut = au8OutputData;
|
||||||
|
} else {
|
||||||
|
pOut = output;
|
||||||
|
}
|
||||||
|
|
||||||
if( pOut != output ) memcpy(output, au8OutputData, dataSize);
|
/* Even though AES H/W has limited support for overlapped DMA input/output buffers,
|
||||||
dumpHex(output,16);
|
* we still seek to one backup buffer to make them non-overlapped for simplicity. */
|
||||||
|
if (crypto_dma_buffs_overlap(pIn, dataSize, pOut, dataSize)) {
|
||||||
|
memcpy(au8InputData, input, dataSize);
|
||||||
|
pIn = au8InputData;
|
||||||
|
}
|
||||||
|
MBED_ASSERT(! crypto_dma_buffs_overlap(pIn, dataSize, pOut, dataSize));
|
||||||
|
|
||||||
|
AES_SetDMATransfer(0, (uint32_t)pIn, (uint32_t)pOut, dataSize);
|
||||||
|
|
||||||
|
crypto_aes_prestart();
|
||||||
|
AES_Start(0, CRYPTO_DMA_ONE_SHOT);
|
||||||
|
crypto_aes_wait();
|
||||||
|
|
||||||
|
if( pOut != output ) {
|
||||||
|
memcpy(output, au8OutputData, dataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save IV for next block */
|
||||||
|
ctx->iv[0] = CRPT->AES_FDBCK[0];
|
||||||
|
ctx->iv[1] = CRPT->AES_FDBCK[1];
|
||||||
|
ctx->iv[2] = CRPT->AES_FDBCK[2];
|
||||||
|
ctx->iv[3] = CRPT->AES_FDBCK[3];
|
||||||
|
|
||||||
|
/* Disable AES interrupt */
|
||||||
|
AES_DISABLE_INT();
|
||||||
|
/* Uninit crypto module */
|
||||||
|
crypto_uninit();
|
||||||
|
|
||||||
|
/* Release ownership of AES H/W */
|
||||||
|
crypto_aes_release();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AES-ECB block encryption
|
* AES-ECB block encryption
|
||||||
*/
|
*/
|
||||||
#if defined(MBEDTLS_AES_ENCRYPT_ALT)
|
|
||||||
void mbedtls_aes_encrypt( mbedtls_aes_context *ctx,
|
void mbedtls_aes_encrypt( mbedtls_aes_context *ctx,
|
||||||
const unsigned char input[16],
|
const unsigned char input[16],
|
||||||
unsigned char output[16] )
|
unsigned char output[16] )
|
||||||
{
|
{
|
||||||
|
ctx->encDec = 1;
|
||||||
mbedtls_trace("=== %s \r\n", __FUNCTION__);
|
__nvt_aes_crypt(ctx, input, output, 16);
|
||||||
|
|
||||||
ctx->encDec = 1;
|
|
||||||
__nvt_aes_crypt(ctx, input, output, 16);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif /* MBEDTLS_AES_ENCRYPT_ALT */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AES-ECB block decryption
|
* AES-ECB block decryption
|
||||||
*/
|
*/
|
||||||
#if defined(MBEDTLS_AES_DECRYPT_ALT)
|
|
||||||
void mbedtls_aes_decrypt( mbedtls_aes_context *ctx,
|
void mbedtls_aes_decrypt( mbedtls_aes_context *ctx,
|
||||||
const unsigned char input[16],
|
const unsigned char input[16],
|
||||||
unsigned char output[16] )
|
unsigned char output[16] )
|
||||||
{
|
{
|
||||||
|
ctx->encDec = 0;
|
||||||
mbedtls_trace("=== %s \r\n", __FUNCTION__);
|
__nvt_aes_crypt(ctx, input, output, 16);
|
||||||
|
|
||||||
ctx->encDec = 0;
|
|
||||||
__nvt_aes_crypt(ctx, input, output, 16);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif /* MBEDTLS_AES_DECRYPT_ALT */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AES-ECB block encryption/decryption
|
* AES-ECB block encryption/decryption
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
|
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
const unsigned char input[16],
|
const unsigned char input[16],
|
||||||
unsigned char output[16] )
|
unsigned char output[16] )
|
||||||
{
|
{
|
||||||
|
ctx->opMode = AES_MODE_ECB;
|
||||||
mbedtls_trace("=== %s \r\n", __FUNCTION__);
|
|
||||||
|
|
||||||
ctx->opMode = AES_MODE_ECB;
|
|
||||||
if( mode == MBEDTLS_AES_ENCRYPT )
|
if( mode == MBEDTLS_AES_ENCRYPT )
|
||||||
mbedtls_aes_encrypt( ctx, input, output );
|
mbedtls_aes_encrypt( ctx, input, output );
|
||||||
else
|
else
|
||||||
mbedtls_aes_decrypt( ctx, input, output );
|
mbedtls_aes_decrypt( ctx, input, output );
|
||||||
|
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
@ -322,108 +253,135 @@ int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
|
||||||
* AES-CBC buffer encryption/decryption
|
* AES-CBC buffer encryption/decryption
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
|
int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
size_t len,
|
size_t len,
|
||||||
unsigned char iv[16],
|
unsigned char iv[16],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output )
|
unsigned char *output )
|
||||||
{
|
{
|
||||||
unsigned char temp[16];
|
|
||||||
int length = len;
|
int length = len;
|
||||||
int blockChainLen;
|
int blockChainLen;
|
||||||
mbedtls_trace("=== %s [0x%x]\r\n", __FUNCTION__,length);
|
|
||||||
if( length % 16 )
|
if( length % 16 )
|
||||||
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
|
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
|
||||||
|
|
||||||
if( (((uint32_t)input) & 0x03) || (((uint32_t)output) & 0x03) )
|
|
||||||
{
|
|
||||||
blockChainLen = (( length > MAX_DMA_CHAIN_SIZE ) ? MAX_DMA_CHAIN_SIZE : length );
|
|
||||||
} else {
|
|
||||||
blockChainLen = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
while( length > 0 )
|
|
||||||
{
|
|
||||||
ctx->opMode = AES_MODE_CBC;
|
|
||||||
swapInitVector(iv); // iv SWAP
|
|
||||||
ctx->iv = (uint32_t *)iv;
|
|
||||||
|
|
||||||
if( mode == MBEDTLS_AES_ENCRYPT )
|
ctx->opMode = AES_MODE_CBC;
|
||||||
{
|
/* Fetch IV byte data in big-endian */
|
||||||
ctx->encDec = 1;
|
ctx->iv[0] = nu_get32_be(iv);
|
||||||
__nvt_aes_crypt(ctx, input, output, blockChainLen);
|
ctx->iv[1] = nu_get32_be(iv + 4);
|
||||||
// if( blockChainLen == length ) break; // finish last block chain but still need to prepare next iv for mbedtls_aes_self_test()
|
ctx->iv[2] = nu_get32_be(iv + 8);
|
||||||
memcpy( iv, output+blockChainLen-16, 16 );
|
ctx->iv[3] = nu_get32_be(iv + 12);
|
||||||
}else{
|
|
||||||
memcpy( temp, input+blockChainLen-16, 16 );
|
if( mode == MBEDTLS_AES_ENCRYPT ) {
|
||||||
ctx->encDec = 0;
|
ctx->encDec = 1;
|
||||||
__nvt_aes_crypt(ctx, input, output, blockChainLen);
|
}
|
||||||
// if( blockChainLen == length ) break; // finish last block chain but still need to prepare next iv for mbedtls_aes_self_test()
|
else {
|
||||||
memcpy( iv, temp, 16 );
|
ctx->encDec = 0;
|
||||||
}
|
}
|
||||||
length -= blockChainLen;
|
|
||||||
input += blockChainLen;
|
while( length > 0 ) {
|
||||||
output += blockChainLen;
|
blockChainLen = (length > MAX_DMA_CHAIN_SIZE) ? MAX_DMA_CHAIN_SIZE : length;
|
||||||
if(length < MAX_DMA_CHAIN_SIZE ) blockChainLen = length; // For last remainder block chain
|
|
||||||
|
__nvt_aes_crypt(ctx, input, output, blockChainLen);
|
||||||
|
|
||||||
|
length -= blockChainLen;
|
||||||
|
input += blockChainLen;
|
||||||
|
output += blockChainLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Save IV for next block cipher */
|
||||||
|
nu_set32_be(iv, ctx->iv[0]);
|
||||||
|
nu_set32_be(iv + 4, ctx->iv[1]);
|
||||||
|
nu_set32_be(iv + 8, ctx->iv[2]);
|
||||||
|
nu_set32_be(iv + 12, ctx->iv[3]);
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
||||||
|
|
||||||
#if defined(MBEDTLS_CIPHER_MODE_CFB)
|
#if defined(MBEDTLS_CIPHER_MODE_CFB)
|
||||||
/*
|
int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
|
||||||
* AES-CFB128 buffer encryption/decryption
|
int mode,
|
||||||
*/
|
size_t length,
|
||||||
/* Support partial block encryption/decryption */
|
size_t *iv_off,
|
||||||
static int __nvt_aes_crypt_partial_block_cfb128( mbedtls_aes_context *ctx,
|
unsigned char iv[16],
|
||||||
int mode,
|
const unsigned char *input,
|
||||||
size_t length,
|
unsigned char *output )
|
||||||
size_t *iv_off,
|
|
||||||
unsigned char iv[16],
|
|
||||||
const unsigned char *input,
|
|
||||||
unsigned char *output )
|
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
size_t n = *iv_off;
|
size_t n = *iv_off;
|
||||||
unsigned char iv_tmp[16];
|
|
||||||
mbedtls_trace("=== %s \r\n", __FUNCTION__);
|
/* First incomplete block */
|
||||||
if( mode == MBEDTLS_AES_DECRYPT )
|
if (n % 16) {
|
||||||
{
|
while (n && length) {
|
||||||
while( length-- )
|
if (mode == MBEDTLS_AES_DECRYPT) {
|
||||||
{
|
c = *input++;
|
||||||
if( n == 0)
|
*output++ = (unsigned char)( c ^ iv[n] );
|
||||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
|
iv[n] = (unsigned char) c;
|
||||||
else if( ctx->opMode == AES_MODE_CFB) // For previous cryption is CFB mode
|
}
|
||||||
{
|
else {
|
||||||
memcpy(iv_tmp, iv, n);
|
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
|
||||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, ctx->prv_iv, iv );
|
}
|
||||||
memcpy(iv, iv_tmp, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
c = *input++;
|
|
||||||
*output++ = (unsigned char)( c ^ iv[n] );
|
|
||||||
iv[n] = (unsigned char) c;
|
|
||||||
|
|
||||||
n = ( n + 1 ) & 0x0F;
|
n = ( n + 1 ) & 0x0F;
|
||||||
|
length --;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
while( length-- )
|
|
||||||
{
|
|
||||||
if( n == 0 )
|
|
||||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
|
|
||||||
else if( ctx->opMode == AES_MODE_CFB) // For previous cryption is CFB mode
|
|
||||||
{
|
|
||||||
memcpy(iv_tmp, iv, n);
|
|
||||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, ctx->prv_iv, iv );
|
|
||||||
memcpy(iv, iv_tmp, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
|
|
||||||
|
|
||||||
|
/* Middle complete block(s) */
|
||||||
|
size_t block_chain_len = length - (length % 16);
|
||||||
|
|
||||||
|
if (block_chain_len) {
|
||||||
|
ctx->opMode = AES_MODE_CFB;
|
||||||
|
if (mode == MBEDTLS_AES_DECRYPT) {
|
||||||
|
ctx->encDec = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ctx->encDec = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fetch IV byte data in big-endian */
|
||||||
|
ctx->iv[0] = nu_get32_be(iv);
|
||||||
|
ctx->iv[1] = nu_get32_be(iv + 4);
|
||||||
|
ctx->iv[2] = nu_get32_be(iv + 8);
|
||||||
|
ctx->iv[3] = nu_get32_be(iv + 12);
|
||||||
|
|
||||||
|
while (block_chain_len) {
|
||||||
|
size_t block_chain_len2 = (block_chain_len > MAX_DMA_CHAIN_SIZE) ? MAX_DMA_CHAIN_SIZE : block_chain_len;
|
||||||
|
|
||||||
|
__nvt_aes_crypt(ctx, input, output, block_chain_len2);
|
||||||
|
|
||||||
|
input += block_chain_len2;
|
||||||
|
output += block_chain_len2;
|
||||||
|
length -= block_chain_len2;
|
||||||
|
|
||||||
|
block_chain_len -= block_chain_len2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOTE: Buffers input/output could overlap. See ctx->iv rather than input/output
|
||||||
|
* for iv of next block cipher. */
|
||||||
|
/* Fetch IV byte data in big-endian */
|
||||||
|
nu_set32_be(iv, ctx->iv[0]);
|
||||||
|
nu_set32_be(iv + 4, ctx->iv[1]);
|
||||||
|
nu_set32_be(iv + 8, ctx->iv[2]);
|
||||||
|
nu_set32_be(iv + 12, ctx->iv[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Last incomplete block */
|
||||||
|
if (length) {
|
||||||
|
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
|
||||||
|
|
||||||
|
while (length --) {
|
||||||
|
if (mode == MBEDTLS_AES_DECRYPT) {
|
||||||
|
c = *input++;
|
||||||
|
*output++ = (unsigned char)( c ^ iv[n] );
|
||||||
|
iv[n] = (unsigned char) c;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
|
||||||
|
}
|
||||||
|
|
||||||
n = ( n + 1 ) & 0x0F;
|
n = ( n + 1 ) & 0x0F;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -433,96 +391,21 @@ static int __nvt_aes_crypt_partial_block_cfb128( mbedtls_aes_context *ctx,
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
|
|
||||||
int mode,
|
|
||||||
size_t len,
|
|
||||||
size_t *iv_off,
|
|
||||||
unsigned char iv[16],
|
|
||||||
const unsigned char *input,
|
|
||||||
unsigned char *output )
|
|
||||||
{
|
|
||||||
size_t n = *iv_off;
|
|
||||||
unsigned char temp[16];
|
|
||||||
int length=len;
|
|
||||||
int blockChainLen;
|
|
||||||
int remLen=0;
|
|
||||||
int ivLen;
|
|
||||||
|
|
||||||
mbedtls_trace("=== %s \r\n", __FUNCTION__);
|
|
||||||
|
|
||||||
// proceed: start with partial block by ECB mode first
|
|
||||||
if( n !=0 ) {
|
|
||||||
__nvt_aes_crypt_partial_block_cfb128(ctx, mode, 16 - n , iv_off, iv, input, output);
|
|
||||||
input += (16 - n);
|
|
||||||
output += (16 - n);
|
|
||||||
length -= (16 - n);
|
|
||||||
}
|
|
||||||
|
|
||||||
// For address or byte count non-word alignment, go through reserved DMA buffer.
|
|
||||||
if( (((uint32_t)input) & 0x03) || (((uint32_t)output) & 0x03) ) // Must reserved DMA buffer for each block
|
|
||||||
{
|
|
||||||
blockChainLen = (( length > MAX_DMA_CHAIN_SIZE ) ? MAX_DMA_CHAIN_SIZE : length );
|
|
||||||
} else if(length%4) { // Need reserved DMA buffer once for last chain
|
|
||||||
blockChainLen = (( length > MAX_DMA_CHAIN_SIZE ) ? (length - length%16) : length );
|
|
||||||
} else { // Not need reserved DMA buffer
|
|
||||||
blockChainLen = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
// proceed: start with block alignment
|
|
||||||
while( length > 0 )
|
|
||||||
{
|
|
||||||
|
|
||||||
ctx->opMode = AES_MODE_CFB;
|
|
||||||
|
|
||||||
swapInitVector(iv); // iv SWAP
|
|
||||||
|
|
||||||
ctx->iv = (uint32_t *)iv;
|
|
||||||
remLen = blockChainLen%16;
|
|
||||||
ivLen = (( remLen > 0) ? remLen: 16 );
|
|
||||||
|
|
||||||
if( mode == MBEDTLS_AES_DECRYPT )
|
|
||||||
{
|
|
||||||
memcpy(temp, input+blockChainLen - ivLen, ivLen);
|
|
||||||
if(blockChainLen >= 16) memcpy(ctx->prv_iv, input+blockChainLen-remLen-16 , 16);
|
|
||||||
ctx->encDec = 0;
|
|
||||||
__nvt_aes_crypt(ctx, input, output, blockChainLen);
|
|
||||||
memcpy(iv,temp, ivLen);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ctx->encDec = 1;
|
|
||||||
__nvt_aes_crypt(ctx, input, output, blockChainLen);
|
|
||||||
if(blockChainLen >= 16) memcpy(ctx->prv_iv, output+blockChainLen-remLen-16 , 16);
|
|
||||||
memcpy(iv,output+blockChainLen-ivLen,ivLen);
|
|
||||||
}
|
|
||||||
length -= blockChainLen;
|
|
||||||
input += blockChainLen;
|
|
||||||
output += blockChainLen;
|
|
||||||
if(length < MAX_DMA_CHAIN_SIZE ) blockChainLen = length; // For last remainder block chain
|
|
||||||
}
|
|
||||||
|
|
||||||
*iv_off = remLen;
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AES-CFB8 buffer encryption/decryption
|
* AES-CFB8 buffer encryption/decryption
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
|
int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
size_t length,
|
size_t length,
|
||||||
unsigned char iv[16],
|
unsigned char iv[16],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output )
|
unsigned char *output )
|
||||||
{
|
{
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
unsigned char ov[17];
|
unsigned char ov[17];
|
||||||
|
|
||||||
mbedtls_trace("=== %s \r\n", __FUNCTION__);
|
while( length-- ) {
|
||||||
while( length-- )
|
|
||||||
{
|
|
||||||
memcpy( ov, iv, 16 );
|
memcpy( ov, iv, 16 );
|
||||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
|
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
|
||||||
|
|
||||||
|
@ -546,19 +429,17 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
|
||||||
* AES-CTR buffer encryption/decryption
|
* AES-CTR buffer encryption/decryption
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
|
int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
|
||||||
size_t length,
|
size_t length,
|
||||||
size_t *nc_off,
|
size_t *nc_off,
|
||||||
unsigned char nonce_counter[16],
|
unsigned char nonce_counter[16],
|
||||||
unsigned char stream_block[16],
|
unsigned char stream_block[16],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output )
|
unsigned char *output )
|
||||||
{
|
{
|
||||||
int c, i;
|
int c, i;
|
||||||
size_t n = *nc_off;
|
size_t n = *nc_off;
|
||||||
|
|
||||||
mbedtls_trace("=== %s \r\n", __FUNCTION__);
|
while( length-- ) {
|
||||||
while( length-- )
|
|
||||||
{
|
|
||||||
if( n == 0 ) {
|
if( n == 0 ) {
|
||||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block );
|
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block );
|
||||||
|
|
||||||
|
|
|
@ -23,13 +23,8 @@
|
||||||
#ifndef MBEDTLS_AES_ALT_H
|
#ifndef MBEDTLS_AES_ALT_H
|
||||||
#define MBEDTLS_AES_ALT_H
|
#define MBEDTLS_AES_ALT_H
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/aes.h"
|
||||||
#include "mbedtls/config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_AES_C)
|
|
||||||
#if defined(MBEDTLS_AES_ALT)
|
#if defined(MBEDTLS_AES_ALT)
|
||||||
// Regular implementation
|
// Regular implementation
|
||||||
//
|
//
|
||||||
|
@ -39,29 +34,13 @@ extern "C" {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief AES context structure
|
* \brief AES context structure
|
||||||
*
|
|
||||||
* \note buf is able to hold 32 extra bytes, which can be used:
|
|
||||||
* - for alignment purposes if VIA padlock is used, and/or
|
|
||||||
* - to simplify key expansion in the 256-bit case by
|
|
||||||
* generating an extra round key
|
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
uint32_t keySize; /* Key size: AES_KEY_SIZE_128/192/256 */
|
||||||
uint32_t keySize;
|
uint32_t encDec; /* 0: decrypt, 1: encrypt */
|
||||||
uint32_t encDec;
|
uint32_t opMode; /* AES_MODE_ECB/CBC/CFB */
|
||||||
uint32_t opMode;
|
uint32_t iv[4]; /* IV for next block cipher */
|
||||||
uint32_t channel;
|
uint32_t keys[8]; /* Cipher key */
|
||||||
uint32_t swapType;
|
|
||||||
uint32_t *iv;
|
|
||||||
unsigned char prv_iv[16];
|
|
||||||
#if 1
|
|
||||||
uint32_t buf[8];
|
|
||||||
/* For comparsion with software AES for correctness */
|
|
||||||
#else
|
|
||||||
uint32_t buf[68]; /*!< unaligned data */
|
|
||||||
int nr; /*!< number of rounds */
|
|
||||||
uint32_t *rk; /*!< AES round keys */
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
mbedtls_aes_context;
|
mbedtls_aes_context;
|
||||||
|
|
||||||
|
@ -89,7 +68,7 @@ void mbedtls_aes_free( mbedtls_aes_context *ctx );
|
||||||
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
|
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
|
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
|
||||||
unsigned int keybits );
|
unsigned int keybits );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief AES key schedule (decryption)
|
* \brief AES key schedule (decryption)
|
||||||
|
@ -101,7 +80,7 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
|
||||||
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
|
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
|
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
|
||||||
unsigned int keybits );
|
unsigned int keybits );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief AES-ECB block encryption/decryption
|
* \brief AES-ECB block encryption/decryption
|
||||||
|
@ -114,9 +93,9 @@ int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
|
||||||
* \return 0 if successful
|
* \return 0 if successful
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
|
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
const unsigned char input[16],
|
const unsigned char input[16],
|
||||||
unsigned char output[16] );
|
unsigned char output[16] );
|
||||||
|
|
||||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
||||||
/**
|
/**
|
||||||
|
@ -142,11 +121,11 @@ int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
|
||||||
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH
|
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
|
int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
size_t length,
|
size_t length,
|
||||||
unsigned char iv[16],
|
unsigned char iv[16],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output );
|
unsigned char *output );
|
||||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
||||||
|
|
||||||
#if defined(MBEDTLS_CIPHER_MODE_CFB)
|
#if defined(MBEDTLS_CIPHER_MODE_CFB)
|
||||||
|
@ -176,12 +155,12 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
|
||||||
* \return 0 if successful
|
* \return 0 if successful
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
|
int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
size_t length,
|
size_t length,
|
||||||
size_t *iv_off,
|
size_t *iv_off,
|
||||||
unsigned char iv[16],
|
unsigned char iv[16],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output );
|
unsigned char *output );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief AES-CFB8 buffer encryption/decryption.
|
* \brief AES-CFB8 buffer encryption/decryption.
|
||||||
|
@ -208,11 +187,11 @@ int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
|
||||||
* \return 0 if successful
|
* \return 0 if successful
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
|
int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
size_t length,
|
size_t length,
|
||||||
unsigned char iv[16],
|
unsigned char iv[16],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output );
|
unsigned char *output );
|
||||||
#endif /*MBEDTLS_CIPHER_MODE_CFB */
|
#endif /*MBEDTLS_CIPHER_MODE_CFB */
|
||||||
|
|
||||||
#if defined(MBEDTLS_CIPHER_MODE_CTR)
|
#if defined(MBEDTLS_CIPHER_MODE_CTR)
|
||||||
|
@ -239,12 +218,12 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
|
||||||
* \return 0 if successful
|
* \return 0 if successful
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
|
int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
|
||||||
size_t length,
|
size_t length,
|
||||||
size_t *nc_off,
|
size_t *nc_off,
|
||||||
unsigned char nonce_counter[16],
|
unsigned char nonce_counter[16],
|
||||||
unsigned char stream_block[16],
|
unsigned char stream_block[16],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output );
|
unsigned char *output );
|
||||||
#endif /* MBEDTLS_CIPHER_MODE_CTR */
|
#endif /* MBEDTLS_CIPHER_MODE_CTR */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -279,6 +258,5 @@ void mbedtls_aes_decrypt( mbedtls_aes_context *ctx,
|
||||||
|
|
||||||
|
|
||||||
#endif /* MBEDTLS_AES_ALT */
|
#endif /* MBEDTLS_AES_ALT */
|
||||||
#endif /* MBEDTLS_AES_C */
|
|
||||||
|
|
||||||
#endif /* aes_alt.h */
|
#endif /* aes_alt.h */
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
/* mbed Microcontroller Library
|
|
||||||
* Copyright (c) 2015-2016 Nuvoton
|
|
||||||
*
|
|
||||||
* 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 "cmsis.h"
|
|
||||||
#include "mbed_assert.h"
|
|
||||||
#include "nu_modutil.h"
|
|
||||||
#include "nu_bitutil.h"
|
|
||||||
#include "crypto-misc.h"
|
|
||||||
|
|
||||||
static int crypto_inited = 0;
|
|
||||||
static int crypto_sha_avail = 1;
|
|
||||||
|
|
||||||
void crypto_init(void)
|
|
||||||
{
|
|
||||||
if (crypto_inited) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
crypto_inited = 1;
|
|
||||||
|
|
||||||
CLK_EnableModuleClock(CRPT_MODULE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Implementation that should never be optimized out by the compiler */
|
|
||||||
void crypto_zeroize(void *v, size_t n)
|
|
||||||
{
|
|
||||||
volatile unsigned char *p = (unsigned char*) v;
|
|
||||||
while (n--) {
|
|
||||||
*p++ = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int crypto_sha_acquire(void)
|
|
||||||
{
|
|
||||||
if (crypto_sha_avail) {
|
|
||||||
crypto_sha_avail = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void crypto_sha_release(void)
|
|
||||||
{
|
|
||||||
if (! crypto_sha_avail) {
|
|
||||||
crypto_sha_avail = 1;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
/* mbed Microcontroller Library
|
|
||||||
* Copyright (c) 2015-2016 Nuvoton
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MBED_CRYPTO_MISC_H
|
|
||||||
#define MBED_CRYPTO_MISC_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void crypto_init(void);
|
|
||||||
void crypto_zeroize(void *v, size_t n);
|
|
||||||
int crypto_sha_acquire(void);
|
|
||||||
void crypto_sha_release(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -14,33 +14,37 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/des.h"
|
||||||
#include "mbedtls/config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_DES_C)
|
#if defined(MBEDTLS_DES_C)
|
||||||
#if defined(MBEDTLS_DES_ALT)
|
#if defined(MBEDTLS_DES_ALT)
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "mbedtls/des.h"
|
#include <stdbool.h>
|
||||||
#include "des_alt.h"
|
|
||||||
#include "crypto-misc.h"
|
#include "crypto-misc.h"
|
||||||
#include "nu_bitutil.h"
|
#include "nu_bitutil.h"
|
||||||
#include "mbed_toolchain.h"
|
#include "mbed_toolchain.h"
|
||||||
|
#include "mbed_error.h"
|
||||||
|
|
||||||
// Must be a multiple of 64-bit block size
|
/* DES DMA compatible buffer requirements
|
||||||
|
*
|
||||||
|
* DES DMA buffer location requires to be:
|
||||||
|
* (1) Word-aligned
|
||||||
|
* (2) Located in 0x2xxxxxxx region. Check linker files to ensure global variables are placed in this region.
|
||||||
|
*
|
||||||
|
* DES DMA buffer size MAXSIZE_DMABUF must be a multiple of 64-bit block size.
|
||||||
|
* Its value is estimated to trade memory footprint off against performance.
|
||||||
|
*
|
||||||
|
*/
|
||||||
#define MAXSIZE_DMABUF (8 * 5)
|
#define MAXSIZE_DMABUF (8 * 5)
|
||||||
static uint8_t dmabuf_in[MAXSIZE_DMABUF] MBED_ALIGN(4);
|
MBED_ALIGN(4) static uint8_t dmabuf_in[MAXSIZE_DMABUF];
|
||||||
static uint8_t dmabuf_out[MAXSIZE_DMABUF] MBED_ALIGN(4);
|
MBED_ALIGN(4) static uint8_t dmabuf_out[MAXSIZE_DMABUF];
|
||||||
|
|
||||||
static int mbedtls_des_docrypt(uint16_t keyopt, uint8_t key[3][MBEDTLS_DES_KEY_SIZE], int enc, uint32_t tdes_opmode, size_t length,
|
static int mbedtls_des_docrypt(uint16_t keyopt, uint8_t key[3][MBEDTLS_DES_KEY_SIZE], int enc, uint32_t tdes_opmode, size_t length,
|
||||||
unsigned char iv[8], const unsigned char *input, unsigned char *output);
|
unsigned char iv[8], const unsigned char *input, unsigned char *output);
|
||||||
|
|
||||||
void mbedtls_des_init(mbedtls_des_context *ctx)
|
void mbedtls_des_init(mbedtls_des_context *ctx)
|
||||||
{
|
{
|
||||||
crypto_init();
|
|
||||||
memset(ctx, 0, sizeof(mbedtls_des_context));
|
memset(ctx, 0, sizeof(mbedtls_des_context));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +59,6 @@ void mbedtls_des_free( mbedtls_des_context *ctx )
|
||||||
|
|
||||||
void mbedtls_des3_init( mbedtls_des3_context *ctx )
|
void mbedtls_des3_init( mbedtls_des3_context *ctx )
|
||||||
{
|
{
|
||||||
crypto_init();
|
|
||||||
memset(ctx, 0, sizeof(mbedtls_des3_context));
|
memset(ctx, 0, sizeof(mbedtls_des3_context));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,15 +72,16 @@ void mbedtls_des3_free( mbedtls_des3_context *ctx )
|
||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8,
|
static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8,
|
||||||
11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44,
|
11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44,
|
||||||
47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81,
|
47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81,
|
||||||
82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112,
|
82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112,
|
||||||
115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140,
|
115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140,
|
||||||
143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168,
|
143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168,
|
||||||
171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196,
|
171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196,
|
||||||
199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224,
|
199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224,
|
||||||
227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253,
|
227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253,
|
||||||
254 };
|
254
|
||||||
|
};
|
||||||
|
|
||||||
void mbedtls_des_key_set_parity(unsigned char key[MBEDTLS_DES_KEY_SIZE])
|
void mbedtls_des_key_set_parity(unsigned char key[MBEDTLS_DES_KEY_SIZE])
|
||||||
{
|
{
|
||||||
|
@ -125,8 +129,7 @@ int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SI
|
||||||
|
|
||||||
#define WEAK_KEY_COUNT 16
|
#define WEAK_KEY_COUNT 16
|
||||||
|
|
||||||
static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] =
|
static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] = {
|
||||||
{
|
|
||||||
{ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
|
{ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
|
||||||
{ 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },
|
{ 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },
|
||||||
{ 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },
|
{ 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },
|
||||||
|
@ -168,7 +171,7 @@ int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MB
|
||||||
memcpy(ctx->key[0], key, MBEDTLS_DES_KEY_SIZE);
|
memcpy(ctx->key[0], key, MBEDTLS_DES_KEY_SIZE);
|
||||||
memcpy(ctx->key[1], key, MBEDTLS_DES_KEY_SIZE);
|
memcpy(ctx->key[1], key, MBEDTLS_DES_KEY_SIZE);
|
||||||
memcpy(ctx->key[2], key, MBEDTLS_DES_KEY_SIZE);
|
memcpy(ctx->key[2], key, MBEDTLS_DES_KEY_SIZE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,7 +194,7 @@ int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MB
|
||||||
* Triple-DES key schedule (112-bit, encryption)
|
* Triple-DES key schedule (112-bit, encryption)
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx,
|
int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx,
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] )
|
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] )
|
||||||
{
|
{
|
||||||
ctx->enc = 1;
|
ctx->enc = 1;
|
||||||
// Keying option 2: K1 and K2 are independent, and K3 = K1.
|
// Keying option 2: K1 and K2 are independent, and K3 = K1.
|
||||||
|
@ -207,7 +210,7 @@ int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx,
|
||||||
* Triple-DES key schedule (112-bit, decryption)
|
* Triple-DES key schedule (112-bit, decryption)
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx,
|
int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx,
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] )
|
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] )
|
||||||
{
|
{
|
||||||
ctx->enc = 0;
|
ctx->enc = 0;
|
||||||
// Keying option 2: K1 and K2 are independent, and K3 = K1.
|
// Keying option 2: K1 and K2 are independent, and K3 = K1.
|
||||||
|
@ -223,7 +226,7 @@ int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx,
|
||||||
* Triple-DES key schedule (168-bit, encryption)
|
* Triple-DES key schedule (168-bit, encryption)
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx,
|
int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx,
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] )
|
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] )
|
||||||
{
|
{
|
||||||
ctx->enc = 1;
|
ctx->enc = 1;
|
||||||
// Keying option 1: All three keys are independent.
|
// Keying option 1: All three keys are independent.
|
||||||
|
@ -239,7 +242,7 @@ int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx,
|
||||||
* Triple-DES key schedule (168-bit, decryption)
|
* Triple-DES key schedule (168-bit, decryption)
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx,
|
int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx,
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] )
|
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] )
|
||||||
{
|
{
|
||||||
ctx->enc = 0;
|
ctx->enc = 0;
|
||||||
// Keying option 1: All three keys are independent.
|
// Keying option 1: All three keys are independent.
|
||||||
|
@ -255,8 +258,8 @@ int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx,
|
||||||
* DES-ECB block encryption/decryption
|
* DES-ECB block encryption/decryption
|
||||||
*/
|
*/
|
||||||
int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx,
|
int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx,
|
||||||
const unsigned char input[8],
|
const unsigned char input[8],
|
||||||
unsigned char output[8] )
|
unsigned char output[8] )
|
||||||
{
|
{
|
||||||
unsigned char iv[8] = {0x00};
|
unsigned char iv[8] = {0x00};
|
||||||
return mbedtls_des_docrypt(ctx->keyopt, ctx->key, ctx->enc, DES_MODE_ECB, 8, iv, input, output);
|
return mbedtls_des_docrypt(ctx->keyopt, ctx->key, ctx->enc, DES_MODE_ECB, 8, iv, input, output);
|
||||||
|
@ -267,11 +270,11 @@ int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx,
|
||||||
* DES-CBC buffer encryption/decryption
|
* DES-CBC buffer encryption/decryption
|
||||||
*/
|
*/
|
||||||
int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx,
|
int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
size_t length,
|
size_t length,
|
||||||
unsigned char iv[8],
|
unsigned char iv[8],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output )
|
unsigned char *output )
|
||||||
{
|
{
|
||||||
return mbedtls_des_docrypt(ctx->keyopt, ctx->key, mode == MBEDTLS_DES_ENCRYPT, DES_MODE_CBC, length, iv, input, output);
|
return mbedtls_des_docrypt(ctx->keyopt, ctx->key, mode == MBEDTLS_DES_ENCRYPT, DES_MODE_CBC, length, iv, input, output);
|
||||||
}
|
}
|
||||||
|
@ -281,8 +284,8 @@ int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx,
|
||||||
* 3DES-ECB block encryption/decryption
|
* 3DES-ECB block encryption/decryption
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx,
|
int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx,
|
||||||
const unsigned char input[8],
|
const unsigned char input[8],
|
||||||
unsigned char output[8] )
|
unsigned char output[8] )
|
||||||
{
|
{
|
||||||
unsigned char iv[8] = {0x00};
|
unsigned char iv[8] = {0x00};
|
||||||
return mbedtls_des_docrypt(ctx->keyopt, ctx->key, ctx->enc, TDES_MODE_ECB, 8, iv, input, output);
|
return mbedtls_des_docrypt(ctx->keyopt, ctx->key, ctx->enc, TDES_MODE_ECB, 8, iv, input, output);
|
||||||
|
@ -293,11 +296,11 @@ int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx,
|
||||||
* 3DES-CBC buffer encryption/decryption
|
* 3DES-CBC buffer encryption/decryption
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx,
|
int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
size_t length,
|
size_t length,
|
||||||
unsigned char iv[8],
|
unsigned char iv[8],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output )
|
unsigned char *output )
|
||||||
{
|
{
|
||||||
return mbedtls_des_docrypt(ctx->keyopt, ctx->key, mode == MBEDTLS_DES_ENCRYPT, TDES_MODE_CBC, length, iv, input, output);
|
return mbedtls_des_docrypt(ctx->keyopt, ctx->key, mode == MBEDTLS_DES_ENCRYPT, TDES_MODE_CBC, length, iv, input, output);
|
||||||
}
|
}
|
||||||
|
@ -305,103 +308,157 @@ int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int mbedtls_des_docrypt(uint16_t keyopt, uint8_t key[3][MBEDTLS_DES_KEY_SIZE], int enc, uint32_t tdes_opmode, size_t length,
|
static int mbedtls_des_docrypt(uint16_t keyopt, uint8_t key[3][MBEDTLS_DES_KEY_SIZE], int enc, uint32_t tdes_opmode, size_t length,
|
||||||
unsigned char iv[8], const unsigned char *input, unsigned char *output)
|
unsigned char iv[8], const unsigned char *input, unsigned char *output)
|
||||||
{
|
{
|
||||||
|
if ((keyopt < 1) || (keyopt > 3)) {
|
||||||
|
error("Key option in DES alter. requires to be 1/2/3.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == NULL) {
|
||||||
|
error("Meet null key pointer in DES alter.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((enc != 0) && (enc != 1)) {
|
||||||
|
error("Enc/dec flag in DES alter. requires to be 0/1.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tdes_opmode & ~(CRPT_TDES_CTL_TMODE_Msk | CRPT_TDES_CTL_OPMODE_Msk)) {
|
||||||
|
error("Invalid TMODE/OPMODE in DES alter.");
|
||||||
|
}
|
||||||
|
|
||||||
if (length % 8) {
|
if (length % 8) {
|
||||||
return MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH;
|
return MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Don't call driver function TDES_Open in BSP because it doesn't support TDES_CTL[3KEYS] setting.
|
|
||||||
CRPT->TDES_CTL = (0 << CRPT_TDES_CTL_CHANNEL_Pos) | (enc << CRPT_TDES_CTL_ENCRPT_Pos) |
|
|
||||||
tdes_opmode | (TDES_IN_OUT_WHL_SWAP << CRPT_TDES_CTL_BLKSWAP_Pos);
|
|
||||||
|
|
||||||
// Keying option 1: All three keys are independent.
|
if (iv == NULL) {
|
||||||
// Keying option 2: K1 and K2 are independent, and K3 = K1.
|
error("Meet null IV pointer in DES alter.");
|
||||||
// Keying option 3: All three keys are identical, i.e. K1 = K2 = K3.
|
|
||||||
if (keyopt == 1) {
|
|
||||||
CRPT->TDES_CTL |= CRPT_TDES_CTL_3KEYS_Msk;
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
CRPT->TDES_CTL &= ~CRPT_TDES_CTL_3KEYS_Msk;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set DES/TDES keys
|
|
||||||
// NOTE: Don't call driver function TDES_SetKey in BSP because it doesn't support endian swap.
|
|
||||||
uint32_t val;
|
|
||||||
volatile uint32_t *tdes_key = (uint32_t *) ((uint32_t) &CRPT->TDES0_KEY1H + (0x40 * 0));
|
|
||||||
val = nu_get32_be(key[0] + 0);
|
|
||||||
*tdes_key ++ = val;
|
|
||||||
val = nu_get32_be(key[0] + 4);
|
|
||||||
*tdes_key ++ = val;
|
|
||||||
val = nu_get32_be(key[1] + 0);
|
|
||||||
*tdes_key ++ = val;
|
|
||||||
val = nu_get32_be(key[1] + 4);
|
|
||||||
*tdes_key ++ = val;
|
|
||||||
val = nu_get32_be(key[2] + 0);
|
|
||||||
*tdes_key ++ = val;
|
|
||||||
val = nu_get32_be(key[2] + 4);
|
|
||||||
*tdes_key ++ = val;
|
|
||||||
|
|
||||||
|
if (input == NULL || output == NULL) {
|
||||||
|
error("Meet null input/output pointer in DES alter.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DES DMA buffer has the following requirements:
|
||||||
|
* (1) Word-aligned buffer base address
|
||||||
|
* (2) 8-byte aligned buffer size
|
||||||
|
* (3) Located in 0x20000000-0x2FFFFFFF region
|
||||||
|
*/
|
||||||
|
if ((! crypto_dma_buff_compat(dmabuf_in, MAXSIZE_DMABUF, 8)) ||
|
||||||
|
(! crypto_dma_buff_compat(dmabuf_out, MAXSIZE_DMABUF, 8))) {
|
||||||
|
error("Buffer for DES alter. DMA requires to be word-aligned and located in 0x20000000-0x2FFFFFFF region.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Change busy-wait to other means to release CPU */
|
||||||
|
/* Acquire ownership of DES H/W */
|
||||||
|
while (! crypto_des_acquire());
|
||||||
|
|
||||||
|
/* Init crypto module */
|
||||||
|
crypto_init();
|
||||||
|
/* Enable DES interrupt */
|
||||||
|
TDES_ENABLE_INT();
|
||||||
|
|
||||||
|
/* Configure TDES_CTL register
|
||||||
|
*
|
||||||
|
* BSP TDES driver supports multiple channels. Just use channel #0.
|
||||||
|
*
|
||||||
|
* Relationship of keying option and TDES H/W mode configuration
|
||||||
|
* 1: All three keys are independent ==> TDES 3-key mode (TMODE=1, 3KEYS=1)
|
||||||
|
* 2: K1 and K2 are independent, and K3 = K1 ==> TDES 2-key mode (TMODE=1, 3KEYS=0)
|
||||||
|
* 3: All three keys are identical, i.e. K1 = K2 = K3 ==> DES mode (TMODE=0)
|
||||||
|
*
|
||||||
|
* tdes_opmode is combination of TMODE/OPMODE, but TDES_Open I/F requires TMODE/OPMODE to be separate.
|
||||||
|
* We need to divide tdes_opmode to TMODE and OPMODE.
|
||||||
|
*
|
||||||
|
* TDES_IN_OUT_WHL_SWAP lets TDES H/W know input/output data are arranged in below for DMA transfer:
|
||||||
|
* 1. BE for byte sequence in word
|
||||||
|
* 2. BE for word sequence in double-word
|
||||||
|
*/
|
||||||
|
TDES_Open(0, // Channel number (0~4)
|
||||||
|
enc, // 0: decode, 1: encode
|
||||||
|
(tdes_opmode & CRPT_TDES_CTL_TMODE_Msk) ? 1 : 0, // 0: DES, 1: TDES
|
||||||
|
(keyopt == 1) ? 1 : 0, // 0: TDES 2-key mode, 1: TDES 3-key mode
|
||||||
|
tdes_opmode & CRPT_TDES_CTL_OPMODE_Msk, // ECB/CBC/CFB/OFB/CTR
|
||||||
|
TDES_IN_OUT_WHL_SWAP); // TDES_NO_SWAP~TDES_IN_OUT_WHL_SWAP
|
||||||
|
|
||||||
|
/* Set DES/TDES keys
|
||||||
|
*
|
||||||
|
* TDES_SetKey requires 3x2 word array. Change 3x8 byte array to 3x2 word array.
|
||||||
|
*/
|
||||||
|
unsigned i;
|
||||||
|
uint32_t keys3x2[3][2];
|
||||||
|
for (i = 0; i < 3; i ++ ) {
|
||||||
|
keys3x2[i][0] = nu_get32_be(key[i] + 0);
|
||||||
|
keys3x2[i][1] = nu_get32_be(key[i] + 4);
|
||||||
|
}
|
||||||
|
TDES_SetKey(0, keys3x2);
|
||||||
|
|
||||||
uint32_t rmn = length;
|
uint32_t rmn = length;
|
||||||
const unsigned char *in_pos = input;
|
const unsigned char *in_pos = input;
|
||||||
unsigned char *out_pos = output;
|
unsigned char *out_pos = output;
|
||||||
|
|
||||||
while (rmn) {
|
while (rmn > 0) {
|
||||||
uint32_t data_len = (rmn <= MAXSIZE_DMABUF) ? rmn : MAXSIZE_DMABUF;
|
uint32_t data_len = (rmn <= MAXSIZE_DMABUF) ? rmn : MAXSIZE_DMABUF;
|
||||||
|
|
||||||
uint32_t ivh, ivl;
|
uint32_t ivh, ivl;
|
||||||
ivh = nu_get32_be(iv);
|
ivh = nu_get32_be(iv);
|
||||||
ivl = nu_get32_be(iv + 4);
|
ivl = nu_get32_be(iv + 4);
|
||||||
TDES_SetInitVect(0, ivh, ivl);
|
TDES_SetInitVect(0, ivh, ivl);
|
||||||
|
|
||||||
memcpy(dmabuf_in, in_pos, data_len);
|
memcpy(dmabuf_in, in_pos, data_len);
|
||||||
|
|
||||||
|
/* We always use DMA backup buffers, which are guaranteed to be non-overlapped. */
|
||||||
TDES_SetDMATransfer(0, (uint32_t) dmabuf_in, (uint32_t) dmabuf_out, data_len);
|
TDES_SetDMATransfer(0, (uint32_t) dmabuf_in, (uint32_t) dmabuf_out, data_len);
|
||||||
|
|
||||||
// Start enc/dec.
|
crypto_des_prestart();
|
||||||
// NOTE: Don't call driver function TDES_Start in BSP because it will override TDES_CTL[3KEYS] setting.
|
TDES_Start(0, CRYPTO_DMA_ONE_SHOT);
|
||||||
CRPT->TDES_CTL |= CRPT_TDES_CTL_START_Msk | (CRYPTO_DMA_ONE_SHOT << CRPT_TDES_CTL_DMALAST_Pos);
|
crypto_des_wait();
|
||||||
while (CRPT->TDES_STS & CRPT_TDES_STS_BUSY_Msk);
|
|
||||||
|
|
||||||
memcpy(out_pos, dmabuf_out, data_len);
|
memcpy(out_pos, dmabuf_out, data_len);
|
||||||
in_pos += data_len;
|
in_pos += data_len;
|
||||||
out_pos += data_len;
|
out_pos += data_len;
|
||||||
rmn -= data_len;
|
rmn -= data_len;
|
||||||
|
|
||||||
// Update IV for next block enc/dec in next function call
|
// Update IV for next block enc/dec in next function call
|
||||||
switch (tdes_opmode) {
|
switch (tdes_opmode) {
|
||||||
case DES_MODE_OFB:
|
case DES_MODE_OFB:
|
||||||
case TDES_MODE_OFB: {
|
case TDES_MODE_OFB: {
|
||||||
// OFB: IV (enc/dec) = output block XOR input block
|
// OFB: IV (enc/dec) = output block XOR input block
|
||||||
uint32_t lbh, lbl;
|
uint32_t lbh, lbl;
|
||||||
// Last block of input data
|
// Last block of input data
|
||||||
lbh = nu_get32_be(dmabuf_in + data_len - 8 + 4);
|
lbh = nu_get32_be(dmabuf_in + data_len - 8 + 4);
|
||||||
lbl = nu_get32_be(dmabuf_in + data_len - 8 + 0);
|
lbl = nu_get32_be(dmabuf_in + data_len - 8 + 0);
|
||||||
// Last block of output data
|
// Last block of output data
|
||||||
ivh = nu_get32_be(dmabuf_out + 4);
|
ivh = nu_get32_be(dmabuf_out + 4);
|
||||||
ivl = nu_get32_be(dmabuf_out + 0);
|
ivl = nu_get32_be(dmabuf_out + 0);
|
||||||
ivh = ivh ^ lbh;
|
ivh = ivh ^ lbh;
|
||||||
ivl = ivl ^ lbl;
|
ivl = ivl ^ lbl;
|
||||||
nu_set32_be(iv + 4, ivh);
|
nu_set32_be(iv + 4, ivh);
|
||||||
nu_set32_be(iv, ivl);
|
nu_set32_be(iv, ivl);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DES_MODE_CBC:
|
case DES_MODE_CBC:
|
||||||
case DES_MODE_CFB:
|
case DES_MODE_CFB:
|
||||||
case TDES_MODE_CBC:
|
case TDES_MODE_CBC:
|
||||||
case TDES_MODE_CFB: {
|
case TDES_MODE_CFB: {
|
||||||
// CBC/CFB: IV (enc) = output block
|
// CBC/CFB: IV (enc) = output block
|
||||||
// IV (dec) = input block
|
// IV (dec) = input block
|
||||||
if (enc) {
|
if (enc) {
|
||||||
memcpy(iv, dmabuf_out + data_len - 8, 8);
|
memcpy(iv, dmabuf_out + data_len - 8, 8);
|
||||||
}
|
} else {
|
||||||
else {
|
memcpy(iv, dmabuf_in + data_len - 8, 8);
|
||||||
memcpy(iv, dmabuf_in + data_len - 8, 8);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Disable DES interrupt */
|
||||||
|
TDES_DISABLE_INT();
|
||||||
|
/* Uninit crypto module */
|
||||||
|
crypto_uninit();
|
||||||
|
|
||||||
|
/* Release ownership of DES H/W */
|
||||||
|
crypto_des_release();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,23 +13,16 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MBEDTLS_DES_ALT_H
|
#ifndef MBEDTLS_DES_ALT_H
|
||||||
#define MBEDTLS_DES_ALT_H
|
#define MBEDTLS_DES_ALT_H
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/des.h"
|
||||||
#include "mbedtls/config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_DES_C)
|
|
||||||
#if defined(MBEDTLS_DES_ALT)
|
#if defined(MBEDTLS_DES_ALT)
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "des.h"
|
|
||||||
#include "des_alt_sw.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -38,19 +31,19 @@ extern "C" {
|
||||||
/**
|
/**
|
||||||
* \brief DES context structure
|
* \brief DES context structure
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
int enc; /* 0: dec, 1: enc */
|
||||||
int enc; /*!< 0: dec, 1: enc */
|
uint16_t keyopt; /* 1: All three keys are independent.
|
||||||
uint16_t keyopt;
|
* 2: K1 and K2 are independent, and K3 = K1.
|
||||||
uint8_t key[3][MBEDTLS_DES_KEY_SIZE]; /*!< 3DES keys */
|
* 3: All three keys are identical, i.e. K1 = K2 = K3. */
|
||||||
|
uint8_t key[3][MBEDTLS_DES_KEY_SIZE]; /* 3DES keys */
|
||||||
}
|
}
|
||||||
mbedtls_des_context;
|
mbedtls_des_context;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Triple-DES context structure
|
* \brief Triple-DES context structure
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
int enc; /*!< 0: dec, 1: enc */
|
int enc; /*!< 0: dec, 1: enc */
|
||||||
uint16_t keyopt;
|
uint16_t keyopt;
|
||||||
uint8_t key[3][MBEDTLS_DES_KEY_SIZE]; /*!< 3DES keys */
|
uint8_t key[3][MBEDTLS_DES_KEY_SIZE]; /*!< 3DES keys */
|
||||||
|
@ -145,7 +138,7 @@ int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MB
|
||||||
* \return 0
|
* \return 0
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx,
|
int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx,
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
|
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Triple-DES key schedule (112-bit, decryption)
|
* \brief Triple-DES key schedule (112-bit, decryption)
|
||||||
|
@ -156,7 +149,7 @@ int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx,
|
||||||
* \return 0
|
* \return 0
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx,
|
int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx,
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
|
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Triple-DES key schedule (168-bit, encryption)
|
* \brief Triple-DES key schedule (168-bit, encryption)
|
||||||
|
@ -167,7 +160,7 @@ int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx,
|
||||||
* \return 0
|
* \return 0
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx,
|
int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx,
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
|
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Triple-DES key schedule (168-bit, decryption)
|
* \brief Triple-DES key schedule (168-bit, decryption)
|
||||||
|
@ -178,7 +171,7 @@ int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx,
|
||||||
* \return 0
|
* \return 0
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx,
|
int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx,
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
|
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief DES-ECB block encryption/decryption
|
* \brief DES-ECB block encryption/decryption
|
||||||
|
@ -190,8 +183,8 @@ int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx,
|
||||||
* \return 0 if successful
|
* \return 0 if successful
|
||||||
*/
|
*/
|
||||||
int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx,
|
int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx,
|
||||||
const unsigned char input[8],
|
const unsigned char input[8],
|
||||||
unsigned char output[8] );
|
unsigned char output[8] );
|
||||||
|
|
||||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
||||||
/**
|
/**
|
||||||
|
@ -213,11 +206,11 @@ int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx,
|
||||||
* \param output buffer holding the output data
|
* \param output buffer holding the output data
|
||||||
*/
|
*/
|
||||||
int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx,
|
int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
size_t length,
|
size_t length,
|
||||||
unsigned char iv[8],
|
unsigned char iv[8],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output );
|
unsigned char *output );
|
||||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -230,8 +223,8 @@ int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx,
|
||||||
* \return 0 if successful
|
* \return 0 if successful
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx,
|
int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx,
|
||||||
const unsigned char input[8],
|
const unsigned char input[8],
|
||||||
unsigned char output[8] );
|
unsigned char output[8] );
|
||||||
|
|
||||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
||||||
/**
|
/**
|
||||||
|
@ -255,11 +248,11 @@ int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx,
|
||||||
* \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH
|
* \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx,
|
int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
size_t length,
|
size_t length,
|
||||||
unsigned char iv[8],
|
unsigned char iv[8],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output );
|
unsigned char *output );
|
||||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -277,6 +270,5 @@ void mbedtls_des_setkey( uint32_t SK[32],
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* MBEDTLS_DES_ALT */
|
#endif /* MBEDTLS_DES_ALT */
|
||||||
#endif /* MBEDTLS_DES_C */
|
|
||||||
|
|
||||||
#endif /* des_alt.h */
|
#endif /* des_alt.h */
|
||||||
|
|
|
@ -1,797 +0,0 @@
|
||||||
/*
|
|
||||||
* FIPS-46-3 compliant Triple-DES implementation
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*
|
|
||||||
* 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 is part of mbed TLS (https://tls.mbed.org)
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* DES, on which TDES is based, was originally designed by Horst Feistel
|
|
||||||
* at IBM in 1974, and was adopted as a standard by NIST (formerly NBS).
|
|
||||||
*
|
|
||||||
* http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
|
||||||
#include "mbedtls/config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_DES_C)
|
|
||||||
#if defined(MBEDTLS_DES_ALT)
|
|
||||||
|
|
||||||
#include "mbedtls/des.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/* Implementation that should never be optimized out by the compiler */
|
|
||||||
static void mbedtls_zeroize( void *v, size_t n ) {
|
|
||||||
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 32-bit integer manipulation macros (big endian)
|
|
||||||
*/
|
|
||||||
#ifndef GET_UINT32_BE
|
|
||||||
#define GET_UINT32_BE(n,b,i) \
|
|
||||||
{ \
|
|
||||||
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
|
|
||||||
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
|
|
||||||
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
|
|
||||||
| ( (uint32_t) (b)[(i) + 3] ); \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PUT_UINT32_BE
|
|
||||||
#define PUT_UINT32_BE(n,b,i) \
|
|
||||||
{ \
|
|
||||||
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
|
|
||||||
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
|
|
||||||
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
|
|
||||||
(b)[(i) + 3] = (unsigned char) ( (n) ); \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Expanded DES S-boxes
|
|
||||||
*/
|
|
||||||
static const uint32_t SB1[64] =
|
|
||||||
{
|
|
||||||
0x01010400, 0x00000000, 0x00010000, 0x01010404,
|
|
||||||
0x01010004, 0x00010404, 0x00000004, 0x00010000,
|
|
||||||
0x00000400, 0x01010400, 0x01010404, 0x00000400,
|
|
||||||
0x01000404, 0x01010004, 0x01000000, 0x00000004,
|
|
||||||
0x00000404, 0x01000400, 0x01000400, 0x00010400,
|
|
||||||
0x00010400, 0x01010000, 0x01010000, 0x01000404,
|
|
||||||
0x00010004, 0x01000004, 0x01000004, 0x00010004,
|
|
||||||
0x00000000, 0x00000404, 0x00010404, 0x01000000,
|
|
||||||
0x00010000, 0x01010404, 0x00000004, 0x01010000,
|
|
||||||
0x01010400, 0x01000000, 0x01000000, 0x00000400,
|
|
||||||
0x01010004, 0x00010000, 0x00010400, 0x01000004,
|
|
||||||
0x00000400, 0x00000004, 0x01000404, 0x00010404,
|
|
||||||
0x01010404, 0x00010004, 0x01010000, 0x01000404,
|
|
||||||
0x01000004, 0x00000404, 0x00010404, 0x01010400,
|
|
||||||
0x00000404, 0x01000400, 0x01000400, 0x00000000,
|
|
||||||
0x00010004, 0x00010400, 0x00000000, 0x01010004
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32_t SB2[64] =
|
|
||||||
{
|
|
||||||
0x80108020, 0x80008000, 0x00008000, 0x00108020,
|
|
||||||
0x00100000, 0x00000020, 0x80100020, 0x80008020,
|
|
||||||
0x80000020, 0x80108020, 0x80108000, 0x80000000,
|
|
||||||
0x80008000, 0x00100000, 0x00000020, 0x80100020,
|
|
||||||
0x00108000, 0x00100020, 0x80008020, 0x00000000,
|
|
||||||
0x80000000, 0x00008000, 0x00108020, 0x80100000,
|
|
||||||
0x00100020, 0x80000020, 0x00000000, 0x00108000,
|
|
||||||
0x00008020, 0x80108000, 0x80100000, 0x00008020,
|
|
||||||
0x00000000, 0x00108020, 0x80100020, 0x00100000,
|
|
||||||
0x80008020, 0x80100000, 0x80108000, 0x00008000,
|
|
||||||
0x80100000, 0x80008000, 0x00000020, 0x80108020,
|
|
||||||
0x00108020, 0x00000020, 0x00008000, 0x80000000,
|
|
||||||
0x00008020, 0x80108000, 0x00100000, 0x80000020,
|
|
||||||
0x00100020, 0x80008020, 0x80000020, 0x00100020,
|
|
||||||
0x00108000, 0x00000000, 0x80008000, 0x00008020,
|
|
||||||
0x80000000, 0x80100020, 0x80108020, 0x00108000
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32_t SB3[64] =
|
|
||||||
{
|
|
||||||
0x00000208, 0x08020200, 0x00000000, 0x08020008,
|
|
||||||
0x08000200, 0x00000000, 0x00020208, 0x08000200,
|
|
||||||
0x00020008, 0x08000008, 0x08000008, 0x00020000,
|
|
||||||
0x08020208, 0x00020008, 0x08020000, 0x00000208,
|
|
||||||
0x08000000, 0x00000008, 0x08020200, 0x00000200,
|
|
||||||
0x00020200, 0x08020000, 0x08020008, 0x00020208,
|
|
||||||
0x08000208, 0x00020200, 0x00020000, 0x08000208,
|
|
||||||
0x00000008, 0x08020208, 0x00000200, 0x08000000,
|
|
||||||
0x08020200, 0x08000000, 0x00020008, 0x00000208,
|
|
||||||
0x00020000, 0x08020200, 0x08000200, 0x00000000,
|
|
||||||
0x00000200, 0x00020008, 0x08020208, 0x08000200,
|
|
||||||
0x08000008, 0x00000200, 0x00000000, 0x08020008,
|
|
||||||
0x08000208, 0x00020000, 0x08000000, 0x08020208,
|
|
||||||
0x00000008, 0x00020208, 0x00020200, 0x08000008,
|
|
||||||
0x08020000, 0x08000208, 0x00000208, 0x08020000,
|
|
||||||
0x00020208, 0x00000008, 0x08020008, 0x00020200
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32_t SB4[64] =
|
|
||||||
{
|
|
||||||
0x00802001, 0x00002081, 0x00002081, 0x00000080,
|
|
||||||
0x00802080, 0x00800081, 0x00800001, 0x00002001,
|
|
||||||
0x00000000, 0x00802000, 0x00802000, 0x00802081,
|
|
||||||
0x00000081, 0x00000000, 0x00800080, 0x00800001,
|
|
||||||
0x00000001, 0x00002000, 0x00800000, 0x00802001,
|
|
||||||
0x00000080, 0x00800000, 0x00002001, 0x00002080,
|
|
||||||
0x00800081, 0x00000001, 0x00002080, 0x00800080,
|
|
||||||
0x00002000, 0x00802080, 0x00802081, 0x00000081,
|
|
||||||
0x00800080, 0x00800001, 0x00802000, 0x00802081,
|
|
||||||
0x00000081, 0x00000000, 0x00000000, 0x00802000,
|
|
||||||
0x00002080, 0x00800080, 0x00800081, 0x00000001,
|
|
||||||
0x00802001, 0x00002081, 0x00002081, 0x00000080,
|
|
||||||
0x00802081, 0x00000081, 0x00000001, 0x00002000,
|
|
||||||
0x00800001, 0x00002001, 0x00802080, 0x00800081,
|
|
||||||
0x00002001, 0x00002080, 0x00800000, 0x00802001,
|
|
||||||
0x00000080, 0x00800000, 0x00002000, 0x00802080
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32_t SB5[64] =
|
|
||||||
{
|
|
||||||
0x00000100, 0x02080100, 0x02080000, 0x42000100,
|
|
||||||
0x00080000, 0x00000100, 0x40000000, 0x02080000,
|
|
||||||
0x40080100, 0x00080000, 0x02000100, 0x40080100,
|
|
||||||
0x42000100, 0x42080000, 0x00080100, 0x40000000,
|
|
||||||
0x02000000, 0x40080000, 0x40080000, 0x00000000,
|
|
||||||
0x40000100, 0x42080100, 0x42080100, 0x02000100,
|
|
||||||
0x42080000, 0x40000100, 0x00000000, 0x42000000,
|
|
||||||
0x02080100, 0x02000000, 0x42000000, 0x00080100,
|
|
||||||
0x00080000, 0x42000100, 0x00000100, 0x02000000,
|
|
||||||
0x40000000, 0x02080000, 0x42000100, 0x40080100,
|
|
||||||
0x02000100, 0x40000000, 0x42080000, 0x02080100,
|
|
||||||
0x40080100, 0x00000100, 0x02000000, 0x42080000,
|
|
||||||
0x42080100, 0x00080100, 0x42000000, 0x42080100,
|
|
||||||
0x02080000, 0x00000000, 0x40080000, 0x42000000,
|
|
||||||
0x00080100, 0x02000100, 0x40000100, 0x00080000,
|
|
||||||
0x00000000, 0x40080000, 0x02080100, 0x40000100
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32_t SB6[64] =
|
|
||||||
{
|
|
||||||
0x20000010, 0x20400000, 0x00004000, 0x20404010,
|
|
||||||
0x20400000, 0x00000010, 0x20404010, 0x00400000,
|
|
||||||
0x20004000, 0x00404010, 0x00400000, 0x20000010,
|
|
||||||
0x00400010, 0x20004000, 0x20000000, 0x00004010,
|
|
||||||
0x00000000, 0x00400010, 0x20004010, 0x00004000,
|
|
||||||
0x00404000, 0x20004010, 0x00000010, 0x20400010,
|
|
||||||
0x20400010, 0x00000000, 0x00404010, 0x20404000,
|
|
||||||
0x00004010, 0x00404000, 0x20404000, 0x20000000,
|
|
||||||
0x20004000, 0x00000010, 0x20400010, 0x00404000,
|
|
||||||
0x20404010, 0x00400000, 0x00004010, 0x20000010,
|
|
||||||
0x00400000, 0x20004000, 0x20000000, 0x00004010,
|
|
||||||
0x20000010, 0x20404010, 0x00404000, 0x20400000,
|
|
||||||
0x00404010, 0x20404000, 0x00000000, 0x20400010,
|
|
||||||
0x00000010, 0x00004000, 0x20400000, 0x00404010,
|
|
||||||
0x00004000, 0x00400010, 0x20004010, 0x00000000,
|
|
||||||
0x20404000, 0x20000000, 0x00400010, 0x20004010
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32_t SB7[64] =
|
|
||||||
{
|
|
||||||
0x00200000, 0x04200002, 0x04000802, 0x00000000,
|
|
||||||
0x00000800, 0x04000802, 0x00200802, 0x04200800,
|
|
||||||
0x04200802, 0x00200000, 0x00000000, 0x04000002,
|
|
||||||
0x00000002, 0x04000000, 0x04200002, 0x00000802,
|
|
||||||
0x04000800, 0x00200802, 0x00200002, 0x04000800,
|
|
||||||
0x04000002, 0x04200000, 0x04200800, 0x00200002,
|
|
||||||
0x04200000, 0x00000800, 0x00000802, 0x04200802,
|
|
||||||
0x00200800, 0x00000002, 0x04000000, 0x00200800,
|
|
||||||
0x04000000, 0x00200800, 0x00200000, 0x04000802,
|
|
||||||
0x04000802, 0x04200002, 0x04200002, 0x00000002,
|
|
||||||
0x00200002, 0x04000000, 0x04000800, 0x00200000,
|
|
||||||
0x04200800, 0x00000802, 0x00200802, 0x04200800,
|
|
||||||
0x00000802, 0x04000002, 0x04200802, 0x04200000,
|
|
||||||
0x00200800, 0x00000000, 0x00000002, 0x04200802,
|
|
||||||
0x00000000, 0x00200802, 0x04200000, 0x00000800,
|
|
||||||
0x04000002, 0x04000800, 0x00000800, 0x00200002
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32_t SB8[64] =
|
|
||||||
{
|
|
||||||
0x10001040, 0x00001000, 0x00040000, 0x10041040,
|
|
||||||
0x10000000, 0x10001040, 0x00000040, 0x10000000,
|
|
||||||
0x00040040, 0x10040000, 0x10041040, 0x00041000,
|
|
||||||
0x10041000, 0x00041040, 0x00001000, 0x00000040,
|
|
||||||
0x10040000, 0x10000040, 0x10001000, 0x00001040,
|
|
||||||
0x00041000, 0x00040040, 0x10040040, 0x10041000,
|
|
||||||
0x00001040, 0x00000000, 0x00000000, 0x10040040,
|
|
||||||
0x10000040, 0x10001000, 0x00041040, 0x00040000,
|
|
||||||
0x00041040, 0x00040000, 0x10041000, 0x00001000,
|
|
||||||
0x00000040, 0x10040040, 0x00001000, 0x00041040,
|
|
||||||
0x10001000, 0x00000040, 0x10000040, 0x10040000,
|
|
||||||
0x10040040, 0x10000000, 0x00040000, 0x10001040,
|
|
||||||
0x00000000, 0x10041040, 0x00040040, 0x10000040,
|
|
||||||
0x10040000, 0x10001000, 0x10001040, 0x00000000,
|
|
||||||
0x10041040, 0x00041000, 0x00041000, 0x00001040,
|
|
||||||
0x00001040, 0x00040040, 0x10000000, 0x10041000
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PC1: left and right halves bit-swap
|
|
||||||
*/
|
|
||||||
static const uint32_t LHs[16] =
|
|
||||||
{
|
|
||||||
0x00000000, 0x00000001, 0x00000100, 0x00000101,
|
|
||||||
0x00010000, 0x00010001, 0x00010100, 0x00010101,
|
|
||||||
0x01000000, 0x01000001, 0x01000100, 0x01000101,
|
|
||||||
0x01010000, 0x01010001, 0x01010100, 0x01010101
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32_t RHs[16] =
|
|
||||||
{
|
|
||||||
0x00000000, 0x01000000, 0x00010000, 0x01010000,
|
|
||||||
0x00000100, 0x01000100, 0x00010100, 0x01010100,
|
|
||||||
0x00000001, 0x01000001, 0x00010001, 0x01010001,
|
|
||||||
0x00000101, 0x01000101, 0x00010101, 0x01010101,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Initial Permutation macro
|
|
||||||
*/
|
|
||||||
#define DES_IP(X,Y) \
|
|
||||||
{ \
|
|
||||||
T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \
|
|
||||||
T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \
|
|
||||||
T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \
|
|
||||||
T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \
|
|
||||||
Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \
|
|
||||||
T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \
|
|
||||||
X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Final Permutation macro
|
|
||||||
*/
|
|
||||||
#define DES_FP(X,Y) \
|
|
||||||
{ \
|
|
||||||
X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \
|
|
||||||
T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \
|
|
||||||
Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \
|
|
||||||
T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \
|
|
||||||
T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \
|
|
||||||
T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \
|
|
||||||
T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* DES round macro
|
|
||||||
*/
|
|
||||||
#define DES_ROUND(X,Y) \
|
|
||||||
{ \
|
|
||||||
T = *SK++ ^ X; \
|
|
||||||
Y ^= SB8[ (T ) & 0x3F ] ^ \
|
|
||||||
SB6[ (T >> 8) & 0x3F ] ^ \
|
|
||||||
SB4[ (T >> 16) & 0x3F ] ^ \
|
|
||||||
SB2[ (T >> 24) & 0x3F ]; \
|
|
||||||
\
|
|
||||||
T = *SK++ ^ ((X << 28) | (X >> 4)); \
|
|
||||||
Y ^= SB7[ (T ) & 0x3F ] ^ \
|
|
||||||
SB5[ (T >> 8) & 0x3F ] ^ \
|
|
||||||
SB3[ (T >> 16) & 0x3F ] ^ \
|
|
||||||
SB1[ (T >> 24) & 0x3F ]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SWAP(a,b) { uint32_t t = a; a = b; b = t; t = 0; }
|
|
||||||
|
|
||||||
void mbedtls_des_sw_init( mbedtls_des_sw_context *ctx )
|
|
||||||
{
|
|
||||||
memset( ctx, 0, sizeof( mbedtls_des_sw_context ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void mbedtls_des_sw_free( mbedtls_des_sw_context *ctx )
|
|
||||||
{
|
|
||||||
if( ctx == NULL )
|
|
||||||
return;
|
|
||||||
|
|
||||||
mbedtls_zeroize( ctx, sizeof( mbedtls_des_sw_context ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void mbedtls_des3_sw_init( mbedtls_des3_sw_context *ctx )
|
|
||||||
{
|
|
||||||
memset( ctx, 0, sizeof( mbedtls_des3_sw_context ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void mbedtls_des3_sw_free( mbedtls_des3_sw_context *ctx )
|
|
||||||
{
|
|
||||||
if( ctx == NULL )
|
|
||||||
return;
|
|
||||||
|
|
||||||
mbedtls_zeroize( ctx, sizeof( mbedtls_des3_sw_context ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8,
|
|
||||||
11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44,
|
|
||||||
47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81,
|
|
||||||
82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112,
|
|
||||||
115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140,
|
|
||||||
143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168,
|
|
||||||
171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196,
|
|
||||||
199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224,
|
|
||||||
227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253,
|
|
||||||
254 };
|
|
||||||
|
|
||||||
void mbedtls_des_sw_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ )
|
|
||||||
key[i] = odd_parity_table[key[i] / 2];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check the given key's parity, returns 1 on failure, 0 on SUCCESS
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ )
|
|
||||||
if( key[i] != odd_parity_table[key[i] / 2] )
|
|
||||||
return( 1 );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Table of weak and semi-weak keys
|
|
||||||
*
|
|
||||||
* Source: http://en.wikipedia.org/wiki/Weak_key
|
|
||||||
*
|
|
||||||
* Weak:
|
|
||||||
* Alternating ones + zeros (0x0101010101010101)
|
|
||||||
* Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE)
|
|
||||||
* '0xE0E0E0E0F1F1F1F1'
|
|
||||||
* '0x1F1F1F1F0E0E0E0E'
|
|
||||||
*
|
|
||||||
* Semi-weak:
|
|
||||||
* 0x011F011F010E010E and 0x1F011F010E010E01
|
|
||||||
* 0x01E001E001F101F1 and 0xE001E001F101F101
|
|
||||||
* 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01
|
|
||||||
* 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E
|
|
||||||
* 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E
|
|
||||||
* 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define WEAK_KEY_COUNT 16
|
|
||||||
|
|
||||||
static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] =
|
|
||||||
{
|
|
||||||
{ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
|
|
||||||
{ 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },
|
|
||||||
{ 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },
|
|
||||||
{ 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 },
|
|
||||||
|
|
||||||
{ 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E },
|
|
||||||
{ 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 },
|
|
||||||
{ 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 },
|
|
||||||
{ 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 },
|
|
||||||
{ 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE },
|
|
||||||
{ 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 },
|
|
||||||
{ 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 },
|
|
||||||
{ 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E },
|
|
||||||
{ 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE },
|
|
||||||
{ 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E },
|
|
||||||
{ 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE },
|
|
||||||
{ 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 }
|
|
||||||
};
|
|
||||||
|
|
||||||
int mbedtls_des_sw_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for( i = 0; i < WEAK_KEY_COUNT; i++ )
|
|
||||||
if( memcmp( weak_key_table[i], key, MBEDTLS_DES_KEY_SIZE) == 0 )
|
|
||||||
return( 1 );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void mbedtls_des_setkey( uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
uint32_t X, Y, T;
|
|
||||||
|
|
||||||
GET_UINT32_BE( X, key, 0 );
|
|
||||||
GET_UINT32_BE( Y, key, 4 );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Permuted Choice 1
|
|
||||||
*/
|
|
||||||
T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4);
|
|
||||||
T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T );
|
|
||||||
|
|
||||||
X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2)
|
|
||||||
| (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] )
|
|
||||||
| (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6)
|
|
||||||
| (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4);
|
|
||||||
|
|
||||||
Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2)
|
|
||||||
| (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] )
|
|
||||||
| (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6)
|
|
||||||
| (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4);
|
|
||||||
|
|
||||||
X &= 0x0FFFFFFF;
|
|
||||||
Y &= 0x0FFFFFFF;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* calculate subkeys
|
|
||||||
*/
|
|
||||||
for( i = 0; i < 16; i++ )
|
|
||||||
{
|
|
||||||
if( i < 2 || i == 8 || i == 15 )
|
|
||||||
{
|
|
||||||
X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF;
|
|
||||||
Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF;
|
|
||||||
Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
*SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000)
|
|
||||||
| ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000)
|
|
||||||
| ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000)
|
|
||||||
| ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000)
|
|
||||||
| ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000)
|
|
||||||
| ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000)
|
|
||||||
| ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400)
|
|
||||||
| ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100)
|
|
||||||
| ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010)
|
|
||||||
| ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004)
|
|
||||||
| ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001);
|
|
||||||
|
|
||||||
*SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000)
|
|
||||||
| ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000)
|
|
||||||
| ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000)
|
|
||||||
| ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000)
|
|
||||||
| ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000)
|
|
||||||
| ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000)
|
|
||||||
| ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000)
|
|
||||||
| ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400)
|
|
||||||
| ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100)
|
|
||||||
| ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011)
|
|
||||||
| ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* DES key schedule (56-bit, encryption)
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_setkey_enc( mbedtls_des_sw_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
|
|
||||||
{
|
|
||||||
mbedtls_des_setkey( ctx->sk, key );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* DES key schedule (56-bit, decryption)
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_setkey_dec( mbedtls_des_sw_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
mbedtls_des_setkey( ctx->sk, key );
|
|
||||||
|
|
||||||
for( i = 0; i < 16; i += 2 )
|
|
||||||
{
|
|
||||||
SWAP( ctx->sk[i ], ctx->sk[30 - i] );
|
|
||||||
SWAP( ctx->sk[i + 1], ctx->sk[31 - i] );
|
|
||||||
}
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void des3_set2key( uint32_t esk[96],
|
|
||||||
uint32_t dsk[96],
|
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE*2] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
mbedtls_des_setkey( esk, key );
|
|
||||||
mbedtls_des_setkey( dsk + 32, key + 8 );
|
|
||||||
|
|
||||||
for( i = 0; i < 32; i += 2 )
|
|
||||||
{
|
|
||||||
dsk[i ] = esk[30 - i];
|
|
||||||
dsk[i + 1] = esk[31 - i];
|
|
||||||
|
|
||||||
esk[i + 32] = dsk[62 - i];
|
|
||||||
esk[i + 33] = dsk[63 - i];
|
|
||||||
|
|
||||||
esk[i + 64] = esk[i ];
|
|
||||||
esk[i + 65] = esk[i + 1];
|
|
||||||
|
|
||||||
dsk[i + 64] = dsk[i ];
|
|
||||||
dsk[i + 65] = dsk[i + 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Triple-DES key schedule (112-bit, encryption)
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_set2key_enc( mbedtls_des3_sw_context *ctx,
|
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] )
|
|
||||||
{
|
|
||||||
uint32_t sk[96];
|
|
||||||
|
|
||||||
des3_set2key( ctx->sk, sk, key );
|
|
||||||
mbedtls_zeroize( sk, sizeof( sk ) );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Triple-DES key schedule (112-bit, decryption)
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_set2key_dec( mbedtls_des3_sw_context *ctx,
|
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] )
|
|
||||||
{
|
|
||||||
uint32_t sk[96];
|
|
||||||
|
|
||||||
des3_set2key( sk, ctx->sk, key );
|
|
||||||
mbedtls_zeroize( sk, sizeof( sk ) );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void des3_set3key( uint32_t esk[96],
|
|
||||||
uint32_t dsk[96],
|
|
||||||
const unsigned char key[24] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
mbedtls_des_setkey( esk, key );
|
|
||||||
mbedtls_des_setkey( dsk + 32, key + 8 );
|
|
||||||
mbedtls_des_setkey( esk + 64, key + 16 );
|
|
||||||
|
|
||||||
for( i = 0; i < 32; i += 2 )
|
|
||||||
{
|
|
||||||
dsk[i ] = esk[94 - i];
|
|
||||||
dsk[i + 1] = esk[95 - i];
|
|
||||||
|
|
||||||
esk[i + 32] = dsk[62 - i];
|
|
||||||
esk[i + 33] = dsk[63 - i];
|
|
||||||
|
|
||||||
dsk[i + 64] = esk[30 - i];
|
|
||||||
dsk[i + 65] = esk[31 - i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Triple-DES key schedule (168-bit, encryption)
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_set3key_enc( mbedtls_des3_sw_context *ctx,
|
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] )
|
|
||||||
{
|
|
||||||
uint32_t sk[96];
|
|
||||||
|
|
||||||
des3_set3key( ctx->sk, sk, key );
|
|
||||||
mbedtls_zeroize( sk, sizeof( sk ) );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Triple-DES key schedule (168-bit, decryption)
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_set3key_dec( mbedtls_des3_sw_context *ctx,
|
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] )
|
|
||||||
{
|
|
||||||
uint32_t sk[96];
|
|
||||||
|
|
||||||
des3_set3key( sk, ctx->sk, key );
|
|
||||||
mbedtls_zeroize( sk, sizeof( sk ) );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* DES-ECB block encryption/decryption
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_crypt_ecb( mbedtls_des_sw_context *ctx,
|
|
||||||
const unsigned char input[8],
|
|
||||||
unsigned char output[8] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
uint32_t X, Y, T, *SK;
|
|
||||||
|
|
||||||
SK = ctx->sk;
|
|
||||||
|
|
||||||
GET_UINT32_BE( X, input, 0 );
|
|
||||||
GET_UINT32_BE( Y, input, 4 );
|
|
||||||
|
|
||||||
DES_IP( X, Y );
|
|
||||||
|
|
||||||
for( i = 0; i < 8; i++ )
|
|
||||||
{
|
|
||||||
DES_ROUND( Y, X );
|
|
||||||
DES_ROUND( X, Y );
|
|
||||||
}
|
|
||||||
|
|
||||||
DES_FP( Y, X );
|
|
||||||
|
|
||||||
PUT_UINT32_BE( Y, output, 0 );
|
|
||||||
PUT_UINT32_BE( X, output, 4 );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
|
||||||
/*
|
|
||||||
* DES-CBC buffer encryption/decryption
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_crypt_cbc( mbedtls_des_sw_context *ctx,
|
|
||||||
int mode,
|
|
||||||
size_t length,
|
|
||||||
unsigned char iv[8],
|
|
||||||
const unsigned char *input,
|
|
||||||
unsigned char *output )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
unsigned char temp[8];
|
|
||||||
|
|
||||||
if( length % 8 )
|
|
||||||
return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH );
|
|
||||||
|
|
||||||
if( mode == MBEDTLS_DES_ENCRYPT )
|
|
||||||
{
|
|
||||||
while( length > 0 )
|
|
||||||
{
|
|
||||||
for( i = 0; i < 8; i++ )
|
|
||||||
output[i] = (unsigned char)( input[i] ^ iv[i] );
|
|
||||||
|
|
||||||
mbedtls_des_sw_crypt_ecb( ctx, output, output );
|
|
||||||
memcpy( iv, output, 8 );
|
|
||||||
|
|
||||||
input += 8;
|
|
||||||
output += 8;
|
|
||||||
length -= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* MBEDTLS_DES_DECRYPT */
|
|
||||||
{
|
|
||||||
while( length > 0 )
|
|
||||||
{
|
|
||||||
memcpy( temp, input, 8 );
|
|
||||||
mbedtls_des_sw_crypt_ecb( ctx, input, output );
|
|
||||||
|
|
||||||
for( i = 0; i < 8; i++ )
|
|
||||||
output[i] = (unsigned char)( output[i] ^ iv[i] );
|
|
||||||
|
|
||||||
memcpy( iv, temp, 8 );
|
|
||||||
|
|
||||||
input += 8;
|
|
||||||
output += 8;
|
|
||||||
length -= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 3DES-ECB block encryption/decryption
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_crypt_ecb( mbedtls_des3_sw_context *ctx,
|
|
||||||
const unsigned char input[8],
|
|
||||||
unsigned char output[8] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
uint32_t X, Y, T, *SK;
|
|
||||||
|
|
||||||
SK = ctx->sk;
|
|
||||||
|
|
||||||
GET_UINT32_BE( X, input, 0 );
|
|
||||||
GET_UINT32_BE( Y, input, 4 );
|
|
||||||
|
|
||||||
DES_IP( X, Y );
|
|
||||||
|
|
||||||
for( i = 0; i < 8; i++ )
|
|
||||||
{
|
|
||||||
DES_ROUND( Y, X );
|
|
||||||
DES_ROUND( X, Y );
|
|
||||||
}
|
|
||||||
|
|
||||||
for( i = 0; i < 8; i++ )
|
|
||||||
{
|
|
||||||
DES_ROUND( X, Y );
|
|
||||||
DES_ROUND( Y, X );
|
|
||||||
}
|
|
||||||
|
|
||||||
for( i = 0; i < 8; i++ )
|
|
||||||
{
|
|
||||||
DES_ROUND( Y, X );
|
|
||||||
DES_ROUND( X, Y );
|
|
||||||
}
|
|
||||||
|
|
||||||
DES_FP( Y, X );
|
|
||||||
|
|
||||||
PUT_UINT32_BE( Y, output, 0 );
|
|
||||||
PUT_UINT32_BE( X, output, 4 );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
|
||||||
/*
|
|
||||||
* 3DES-CBC buffer encryption/decryption
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_crypt_cbc( mbedtls_des3_sw_context *ctx,
|
|
||||||
int mode,
|
|
||||||
size_t length,
|
|
||||||
unsigned char iv[8],
|
|
||||||
const unsigned char *input,
|
|
||||||
unsigned char *output )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
unsigned char temp[8];
|
|
||||||
|
|
||||||
if( length % 8 )
|
|
||||||
return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH );
|
|
||||||
|
|
||||||
if( mode == MBEDTLS_DES_ENCRYPT )
|
|
||||||
{
|
|
||||||
while( length > 0 )
|
|
||||||
{
|
|
||||||
for( i = 0; i < 8; i++ )
|
|
||||||
output[i] = (unsigned char)( input[i] ^ iv[i] );
|
|
||||||
|
|
||||||
mbedtls_des3_sw_crypt_ecb( ctx, output, output );
|
|
||||||
memcpy( iv, output, 8 );
|
|
||||||
|
|
||||||
input += 8;
|
|
||||||
output += 8;
|
|
||||||
length -= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* MBEDTLS_DES_DECRYPT */
|
|
||||||
{
|
|
||||||
while( length > 0 )
|
|
||||||
{
|
|
||||||
memcpy( temp, input, 8 );
|
|
||||||
mbedtls_des3_sw_crypt_ecb( ctx, input, output );
|
|
||||||
|
|
||||||
for( i = 0; i < 8; i++ )
|
|
||||||
output[i] = (unsigned char)( output[i] ^ iv[i] );
|
|
||||||
|
|
||||||
memcpy( iv, temp, 8 );
|
|
||||||
|
|
||||||
input += 8;
|
|
||||||
output += 8;
|
|
||||||
length -= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
|
||||||
|
|
||||||
#endif /* MBEDTLS_DES_ALT */
|
|
||||||
#endif /* MBEDTLS_DES_C */
|
|
|
@ -1,283 +0,0 @@
|
||||||
/**
|
|
||||||
* \file des.h
|
|
||||||
*
|
|
||||||
* \brief DES block cipher
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*
|
|
||||||
* 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 is part of mbed TLS (https://tls.mbed.org)
|
|
||||||
*/
|
|
||||||
#ifndef MBEDTLS_DES_ALT_SW_H
|
|
||||||
#define MBEDTLS_DES_ALT_SW_H
|
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
|
||||||
#include "config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_DES_C)
|
|
||||||
#if defined(MBEDTLS_DES_ALT)
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief DES context structure
|
|
||||||
*/
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint32_t sk[32]; /*!< DES subkeys */
|
|
||||||
}
|
|
||||||
mbedtls_des_sw_context;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Triple-DES context structure
|
|
||||||
*/
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint32_t sk[96]; /*!< 3DES subkeys */
|
|
||||||
}
|
|
||||||
mbedtls_des3_sw_context;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Initialize DES context
|
|
||||||
*
|
|
||||||
* \param ctx DES context to be initialized
|
|
||||||
*/
|
|
||||||
void mbedtls_des_sw_init( mbedtls_des_sw_context *ctx );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Clear DES context
|
|
||||||
*
|
|
||||||
* \param ctx DES context to be cleared
|
|
||||||
*/
|
|
||||||
void mbedtls_des_sw_free( mbedtls_des_sw_context *ctx );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Initialize Triple-DES context
|
|
||||||
*
|
|
||||||
* \param ctx DES3 context to be initialized
|
|
||||||
*/
|
|
||||||
void mbedtls_des3_sw_init( mbedtls_des3_sw_context *ctx );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Clear Triple-DES context
|
|
||||||
*
|
|
||||||
* \param ctx DES3 context to be cleared
|
|
||||||
*/
|
|
||||||
void mbedtls_des3_sw_free( mbedtls_des3_sw_context *ctx );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Set key parity on the given key to odd.
|
|
||||||
*
|
|
||||||
* DES keys are 56 bits long, but each byte is padded with
|
|
||||||
* a parity bit to allow verification.
|
|
||||||
*
|
|
||||||
* \param key 8-byte secret key
|
|
||||||
*/
|
|
||||||
void mbedtls_des_sw_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Check that key parity on the given key is odd.
|
|
||||||
*
|
|
||||||
* DES keys are 56 bits long, but each byte is padded with
|
|
||||||
* a parity bit to allow verification.
|
|
||||||
*
|
|
||||||
* \param key 8-byte secret key
|
|
||||||
*
|
|
||||||
* \return 0 is parity was ok, 1 if parity was not correct.
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Check that key is not a weak or semi-weak DES key
|
|
||||||
*
|
|
||||||
* \param key 8-byte secret key
|
|
||||||
*
|
|
||||||
* \return 0 if no weak key was found, 1 if a weak key was identified.
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief DES key schedule (56-bit, encryption)
|
|
||||||
*
|
|
||||||
* \param ctx DES context to be initialized
|
|
||||||
* \param key 8-byte secret key
|
|
||||||
*
|
|
||||||
* \return 0
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_setkey_enc( mbedtls_des_sw_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief DES key schedule (56-bit, decryption)
|
|
||||||
*
|
|
||||||
* \param ctx DES context to be initialized
|
|
||||||
* \param key 8-byte secret key
|
|
||||||
*
|
|
||||||
* \return 0
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_setkey_dec( mbedtls_des_sw_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Triple-DES key schedule (112-bit, encryption)
|
|
||||||
*
|
|
||||||
* \param ctx 3DES context to be initialized
|
|
||||||
* \param key 16-byte secret key
|
|
||||||
*
|
|
||||||
* \return 0
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_set2key_enc( mbedtls_des3_sw_context *ctx,
|
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Triple-DES key schedule (112-bit, decryption)
|
|
||||||
*
|
|
||||||
* \param ctx 3DES context to be initialized
|
|
||||||
* \param key 16-byte secret key
|
|
||||||
*
|
|
||||||
* \return 0
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_set2key_dec( mbedtls_des3_sw_context *ctx,
|
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Triple-DES key schedule (168-bit, encryption)
|
|
||||||
*
|
|
||||||
* \param ctx 3DES context to be initialized
|
|
||||||
* \param key 24-byte secret key
|
|
||||||
*
|
|
||||||
* \return 0
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_set3key_enc( mbedtls_des3_sw_context *ctx,
|
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Triple-DES key schedule (168-bit, decryption)
|
|
||||||
*
|
|
||||||
* \param ctx 3DES context to be initialized
|
|
||||||
* \param key 24-byte secret key
|
|
||||||
*
|
|
||||||
* \return 0
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_set3key_dec( mbedtls_des3_sw_context *ctx,
|
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief DES-ECB block encryption/decryption
|
|
||||||
*
|
|
||||||
* \param ctx DES context
|
|
||||||
* \param input 64-bit input block
|
|
||||||
* \param output 64-bit output block
|
|
||||||
*
|
|
||||||
* \return 0 if successful
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_crypt_ecb( mbedtls_des_sw_context *ctx,
|
|
||||||
const unsigned char input[8],
|
|
||||||
unsigned char output[8] );
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
|
||||||
/**
|
|
||||||
* \brief DES-CBC buffer encryption/decryption
|
|
||||||
*
|
|
||||||
* \note Upon exit, the content of the IV is updated so that you can
|
|
||||||
* call the function same function again on the following
|
|
||||||
* block(s) of data and get the same result as if it was
|
|
||||||
* encrypted in one call. This allows a "streaming" usage.
|
|
||||||
* If on the other hand you need to retain the contents of the
|
|
||||||
* IV, you should either save it manually or use the cipher
|
|
||||||
* module instead.
|
|
||||||
*
|
|
||||||
* \param ctx DES context
|
|
||||||
* \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT
|
|
||||||
* \param length length of the input data
|
|
||||||
* \param iv initialization vector (updated after use)
|
|
||||||
* \param input buffer holding the input data
|
|
||||||
* \param output buffer holding the output data
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_crypt_cbc( mbedtls_des_sw_context *ctx,
|
|
||||||
int mode,
|
|
||||||
size_t length,
|
|
||||||
unsigned char iv[8],
|
|
||||||
const unsigned char *input,
|
|
||||||
unsigned char *output );
|
|
||||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief 3DES-ECB block encryption/decryption
|
|
||||||
*
|
|
||||||
* \param ctx 3DES context
|
|
||||||
* \param input 64-bit input block
|
|
||||||
* \param output 64-bit output block
|
|
||||||
*
|
|
||||||
* \return 0 if successful
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_crypt_ecb( mbedtls_des3_sw_context *ctx,
|
|
||||||
const unsigned char input[8],
|
|
||||||
unsigned char output[8] );
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
|
||||||
/**
|
|
||||||
* \brief 3DES-CBC buffer encryption/decryption
|
|
||||||
*
|
|
||||||
* \note Upon exit, the content of the IV is updated so that you can
|
|
||||||
* call the function same function again on the following
|
|
||||||
* block(s) of data and get the same result as if it was
|
|
||||||
* encrypted in one call. This allows a "streaming" usage.
|
|
||||||
* If on the other hand you need to retain the contents of the
|
|
||||||
* IV, you should either save it manually or use the cipher
|
|
||||||
* module instead.
|
|
||||||
*
|
|
||||||
* \param ctx 3DES context
|
|
||||||
* \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT
|
|
||||||
* \param length length of the input data
|
|
||||||
* \param iv initialization vector (updated after use)
|
|
||||||
* \param input buffer holding the input data
|
|
||||||
* \param output buffer holding the output data
|
|
||||||
*
|
|
||||||
* \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_crypt_cbc( mbedtls_des3_sw_context *ctx,
|
|
||||||
int mode,
|
|
||||||
size_t length,
|
|
||||||
unsigned char iv[8],
|
|
||||||
const unsigned char *input,
|
|
||||||
unsigned char *output );
|
|
||||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Internal function for key expansion.
|
|
||||||
* (Only exposed to allow overriding it,
|
|
||||||
* see MBEDTLS_DES_SETKEY_ALT)
|
|
||||||
*
|
|
||||||
* \param SK Round keys
|
|
||||||
* \param key Base key
|
|
||||||
*/
|
|
||||||
void mbedtls_des_sw_setkey( uint32_t SK[32],
|
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* MBEDTLS_DES_ALT */
|
|
||||||
#endif /* MBEDTLS_DES_C */
|
|
||||||
|
|
||||||
#endif /* des.h */
|
|
|
@ -14,53 +14,69 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/sha1.h"
|
||||||
#include "mbedtls/config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA1_C)
|
#if defined(MBEDTLS_SHA1_C)
|
||||||
#if defined(MBEDTLS_SHA1_ALT)
|
#if defined(MBEDTLS_SHA1_ALT)
|
||||||
|
|
||||||
#include "sha1_alt.h"
|
|
||||||
#include "crypto-misc.h"
|
#include "crypto-misc.h"
|
||||||
#include "nu_bitutil.h"
|
#include "nu_bitutil.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
void mbedtls_sha1_init(mbedtls_sha1_context *ctx)
|
/* Choose SHA S/W or H/W context and initialize it
|
||||||
|
*
|
||||||
|
* try_hw:
|
||||||
|
* 0: Initialize S/W context
|
||||||
|
* 1: Try acquiring SHA H/W resource first and initialize its H/W context if successful. If failed, initialize S/W context.
|
||||||
|
*/
|
||||||
|
static void mbedtls_sha1_init_internal(mbedtls_sha1_context *ctx, int try_hw)
|
||||||
{
|
{
|
||||||
if (crypto_sha_acquire()) {
|
if (try_hw && crypto_sha_acquire()) {
|
||||||
ctx->ishw = 1;
|
ctx->active_ctx = &ctx->hw_ctx;
|
||||||
mbedtls_sha1_hw_init(&ctx->hw_ctx);
|
mbedtls_sha1_hw_init(&ctx->hw_ctx);
|
||||||
}
|
} else {
|
||||||
else {
|
ctx->active_ctx = &ctx->sw_ctx;
|
||||||
ctx->ishw = 0;
|
|
||||||
mbedtls_sha1_sw_init(&ctx->sw_ctx);
|
mbedtls_sha1_sw_init(&ctx->sw_ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mbedtls_sha1_init(mbedtls_sha1_context *ctx)
|
||||||
|
{
|
||||||
|
mbedtls_sha1_init_internal(ctx, 1);
|
||||||
|
}
|
||||||
|
|
||||||
void mbedtls_sha1_free(mbedtls_sha1_context *ctx)
|
void mbedtls_sha1_free(mbedtls_sha1_context *ctx)
|
||||||
{
|
{
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha1_hw_free(&ctx->hw_ctx);
|
mbedtls_sha1_hw_free(&ctx->hw_ctx);
|
||||||
crypto_sha_release();
|
crypto_sha_release();
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha1_sw_free(&ctx->sw_ctx);
|
mbedtls_sha1_sw_free(&ctx->sw_ctx);
|
||||||
}
|
}
|
||||||
|
ctx->active_ctx = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha1_clone(mbedtls_sha1_context *dst,
|
void mbedtls_sha1_clone(mbedtls_sha1_context *dst,
|
||||||
const mbedtls_sha1_context *src)
|
const mbedtls_sha1_context *src)
|
||||||
{
|
{
|
||||||
if (src->ishw) {
|
// Corner case: Destination/source contexts are the same
|
||||||
|
if (dst == src) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If dst is H/W context, we need to change it to S/W context first before cloning to.
|
||||||
|
if (dst->active_ctx == &dst->hw_ctx) {
|
||||||
|
mbedtls_sha1_free(dst);
|
||||||
|
// Force S/W context
|
||||||
|
mbedtls_sha1_init_internal(dst, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src->active_ctx == &src->hw_ctx) {
|
||||||
// Clone S/W ctx from H/W ctx
|
// Clone S/W ctx from H/W ctx
|
||||||
dst->ishw = 0;
|
|
||||||
dst->sw_ctx.total[0] = src->hw_ctx.total;
|
dst->sw_ctx.total[0] = src->hw_ctx.total;
|
||||||
dst->sw_ctx.total[1] = 0;
|
dst->sw_ctx.total[1] = 0;
|
||||||
{
|
{
|
||||||
|
@ -78,8 +94,7 @@ void mbedtls_sha1_clone(mbedtls_sha1_context *dst,
|
||||||
if (src->hw_ctx.buffer_left == src->hw_ctx.blocksize) {
|
if (src->hw_ctx.buffer_left == src->hw_ctx.blocksize) {
|
||||||
mbedtls_sha1_sw_process(&dst->sw_ctx, dst->sw_ctx.buffer);
|
mbedtls_sha1_sw_process(&dst->sw_ctx, dst->sw_ctx.buffer);
|
||||||
}
|
}
|
||||||
}
|
} else if (src->active_ctx == &src->sw_ctx) {
|
||||||
else {
|
|
||||||
// Clone S/W ctx from S/W ctx
|
// Clone S/W ctx from S/W ctx
|
||||||
dst->sw_ctx = src->sw_ctx;
|
dst->sw_ctx = src->sw_ctx;
|
||||||
}
|
}
|
||||||
|
@ -90,10 +105,9 @@ void mbedtls_sha1_clone(mbedtls_sha1_context *dst,
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha1_starts(mbedtls_sha1_context *ctx)
|
void mbedtls_sha1_starts(mbedtls_sha1_context *ctx)
|
||||||
{
|
{
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha1_hw_starts(&ctx->hw_ctx);
|
mbedtls_sha1_hw_starts(&ctx->hw_ctx);
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha1_sw_starts(&ctx->sw_ctx);
|
mbedtls_sha1_sw_starts(&ctx->sw_ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,10 +117,9 @@ void mbedtls_sha1_starts(mbedtls_sha1_context *ctx)
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha1_update(mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen)
|
void mbedtls_sha1_update(mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen)
|
||||||
{
|
{
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha1_hw_update(&ctx->hw_ctx, input, ilen);
|
mbedtls_sha1_hw_update(&ctx->hw_ctx, input, ilen);
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha1_sw_update(&ctx->sw_ctx, input, ilen);
|
mbedtls_sha1_sw_update(&ctx->sw_ctx, input, ilen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,20 +129,18 @@ void mbedtls_sha1_update(mbedtls_sha1_context *ctx, const unsigned char *input,
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha1_finish(mbedtls_sha1_context *ctx, unsigned char output[20])
|
void mbedtls_sha1_finish(mbedtls_sha1_context *ctx, unsigned char output[20])
|
||||||
{
|
{
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha1_hw_finish(&ctx->hw_ctx, output);
|
mbedtls_sha1_hw_finish(&ctx->hw_ctx, output);
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha1_sw_finish(&ctx->sw_ctx, output);
|
mbedtls_sha1_sw_finish(&ctx->sw_ctx, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha1_process(mbedtls_sha1_context *ctx, const unsigned char data[64])
|
void mbedtls_sha1_process(mbedtls_sha1_context *ctx, const unsigned char data[64])
|
||||||
{
|
{
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha1_hw_process(&ctx->hw_ctx, data);
|
mbedtls_sha1_hw_process(&ctx->hw_ctx, data);
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha1_sw_process(&ctx->sw_ctx, data);
|
mbedtls_sha1_sw_process(&ctx->sw_ctx, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,13 +16,8 @@
|
||||||
#ifndef MBEDTLS_SHA1_ALT_H
|
#ifndef MBEDTLS_SHA1_ALT_H
|
||||||
#define MBEDTLS_SHA1_ALT_H
|
#define MBEDTLS_SHA1_ALT_H
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/sha1.h"
|
||||||
#include "config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA1_C)
|
|
||||||
#if defined(MBEDTLS_SHA1_ALT)
|
#if defined(MBEDTLS_SHA1_ALT)
|
||||||
|
|
||||||
#include "sha_alt_hw.h"
|
#include "sha_alt_hw.h"
|
||||||
|
@ -37,9 +32,8 @@ struct mbedtls_sha1_context_s;
|
||||||
/**
|
/**
|
||||||
* \brief SHA-1 context structure
|
* \brief SHA-1 context structure
|
||||||
*/
|
*/
|
||||||
typedef struct mbedtls_sha1_context_s
|
typedef struct mbedtls_sha1_context_s {
|
||||||
{
|
void *active_ctx;
|
||||||
int ishw;
|
|
||||||
crypto_sha_context hw_ctx;
|
crypto_sha_context hw_ctx;
|
||||||
mbedtls_sha1_sw_context sw_ctx;
|
mbedtls_sha1_sw_context sw_ctx;
|
||||||
}
|
}
|
||||||
|
@ -100,6 +94,5 @@ void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[6
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* MBEDTLS_SHA1_ALT */
|
#endif /* MBEDTLS_SHA1_ALT */
|
||||||
#endif /* MBEDTLS_SHA1_C */
|
|
||||||
|
|
||||||
#endif /* sha1_alt.h */
|
#endif /* sha1_alt.h */
|
||||||
|
|
|
@ -24,17 +24,10 @@
|
||||||
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
|
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/sha1.h"
|
||||||
#include "mbedtls/config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA1_C)
|
#if defined(MBEDTLS_SHA1_C)
|
||||||
#if defined(MBEDTLS_SHA1_ALT)
|
#if defined(MBEDTLS_SHA1_ALT)
|
||||||
|
|
||||||
#include "mbedtls/sha1.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#if defined(MBEDTLS_SELF_TEST)
|
#if defined(MBEDTLS_SELF_TEST)
|
||||||
#if defined(MBEDTLS_PLATFORM_C)
|
#if defined(MBEDTLS_PLATFORM_C)
|
||||||
|
@ -46,8 +39,10 @@
|
||||||
#endif /* MBEDTLS_SELF_TEST */
|
#endif /* MBEDTLS_SELF_TEST */
|
||||||
|
|
||||||
/* Implementation that should never be optimized out by the compiler */
|
/* Implementation that should never be optimized out by the compiler */
|
||||||
static void mbedtls_zeroize( void *v, size_t n ) {
|
static void mbedtls_zeroize( void *v, size_t n )
|
||||||
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
|
{
|
||||||
|
volatile unsigned char *p = (unsigned char*)v;
|
||||||
|
while( n-- ) *p++ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -87,7 +82,7 @@ void mbedtls_sha1_sw_free( mbedtls_sha1_sw_context *ctx )
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha1_sw_clone( mbedtls_sha1_sw_context *dst,
|
void mbedtls_sha1_sw_clone( mbedtls_sha1_sw_context *dst,
|
||||||
const mbedtls_sha1_sw_context *src )
|
const mbedtls_sha1_sw_context *src )
|
||||||
{
|
{
|
||||||
*dst = *src;
|
*dst = *src;
|
||||||
}
|
}
|
||||||
|
@ -283,8 +278,7 @@ void mbedtls_sha1_sw_update( mbedtls_sha1_sw_context *ctx, const unsigned char *
|
||||||
if( ctx->total[0] < (uint32_t) ilen )
|
if( ctx->total[0] < (uint32_t) ilen )
|
||||||
ctx->total[1]++;
|
ctx->total[1]++;
|
||||||
|
|
||||||
if( left && ilen >= fill )
|
if( left && ilen >= fill ) {
|
||||||
{
|
|
||||||
memcpy( (void *) (ctx->buffer + left), input, fill );
|
memcpy( (void *) (ctx->buffer + left), input, fill );
|
||||||
mbedtls_sha1_sw_process( ctx, ctx->buffer );
|
mbedtls_sha1_sw_process( ctx, ctx->buffer );
|
||||||
input += fill;
|
input += fill;
|
||||||
|
@ -292,8 +286,7 @@ void mbedtls_sha1_sw_update( mbedtls_sha1_sw_context *ctx, const unsigned char *
|
||||||
left = 0;
|
left = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while( ilen >= 64 )
|
while( ilen >= 64 ) {
|
||||||
{
|
|
||||||
mbedtls_sha1_sw_process( ctx, input );
|
mbedtls_sha1_sw_process( ctx, input );
|
||||||
input += 64;
|
input += 64;
|
||||||
ilen -= 64;
|
ilen -= 64;
|
||||||
|
@ -303,9 +296,8 @@ void mbedtls_sha1_sw_update( mbedtls_sha1_sw_context *ctx, const unsigned char *
|
||||||
memcpy( (void *) (ctx->buffer + left), input, ilen );
|
memcpy( (void *) (ctx->buffer + left), input, ilen );
|
||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned char sha1_padding[64] =
|
static const unsigned char sha1_padding[64] = {
|
||||||
{
|
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
@ -321,7 +313,7 @@ void mbedtls_sha1_sw_finish( mbedtls_sha1_sw_context *ctx, unsigned char output[
|
||||||
unsigned char msglen[8];
|
unsigned char msglen[8];
|
||||||
|
|
||||||
high = ( ctx->total[0] >> 29 )
|
high = ( ctx->total[0] >> 29 )
|
||||||
| ( ctx->total[1] << 3 );
|
| ( ctx->total[1] << 3 );
|
||||||
low = ( ctx->total[0] << 3 );
|
low = ( ctx->total[0] << 3 );
|
||||||
|
|
||||||
PUT_UINT32_BE( high, msglen, 0 );
|
PUT_UINT32_BE( high, msglen, 0 );
|
||||||
|
|
|
@ -23,13 +23,6 @@
|
||||||
#ifndef MBEDTLS_SHA1_ALT_SW_H
|
#ifndef MBEDTLS_SHA1_ALT_SW_H
|
||||||
#define MBEDTLS_SHA1_ALT_SW_H
|
#define MBEDTLS_SHA1_ALT_SW_H
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
|
||||||
#include "config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA1_C)
|
|
||||||
#if defined(MBEDTLS_SHA1_ALT)
|
#if defined(MBEDTLS_SHA1_ALT)
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
@ -42,8 +35,7 @@ extern "C" {
|
||||||
/**
|
/**
|
||||||
* \brief SHA-1 context structure
|
* \brief SHA-1 context structure
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
uint32_t total[2]; /*!< number of bytes processed */
|
uint32_t total[2]; /*!< number of bytes processed */
|
||||||
uint32_t state[5]; /*!< intermediate digest state */
|
uint32_t state[5]; /*!< intermediate digest state */
|
||||||
unsigned char buffer[64]; /*!< data block being processed */
|
unsigned char buffer[64]; /*!< data block being processed */
|
||||||
|
@ -71,7 +63,7 @@ void mbedtls_sha1_sw_free( mbedtls_sha1_sw_context *ctx );
|
||||||
* \param src The context to be cloned
|
* \param src The context to be cloned
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha1_sw_clone( mbedtls_sha1_sw_context *dst,
|
void mbedtls_sha1_sw_clone( mbedtls_sha1_sw_context *dst,
|
||||||
const mbedtls_sha1_sw_context *src );
|
const mbedtls_sha1_sw_context *src );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief SHA-1 context setup
|
* \brief SHA-1 context setup
|
||||||
|
@ -105,6 +97,5 @@ void mbedtls_sha1_sw_process( mbedtls_sha1_sw_context *ctx, const unsigned char
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* MBEDTLS_SHA1_ALT */
|
#endif /* MBEDTLS_SHA1_ALT */
|
||||||
#endif /* MBEDTLS_SHA1_C */
|
|
||||||
|
|
||||||
#endif /* sha1_alt_sw.h */
|
#endif /* sha1_alt_sw.h */
|
||||||
|
|
|
@ -14,53 +14,69 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/sha256.h"
|
||||||
#include "mbedtls/config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA256_C)
|
#if defined(MBEDTLS_SHA256_C)
|
||||||
#if defined(MBEDTLS_SHA256_ALT)
|
#if defined(MBEDTLS_SHA256_ALT)
|
||||||
|
|
||||||
#include "sha256_alt.h"
|
|
||||||
#include "crypto-misc.h"
|
#include "crypto-misc.h"
|
||||||
#include "nu_bitutil.h"
|
#include "nu_bitutil.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
void mbedtls_sha256_init(mbedtls_sha256_context *ctx)
|
/* Choose SHA S/W or H/W context and initialize it
|
||||||
|
*
|
||||||
|
* try_hw:
|
||||||
|
* 0: Initialize S/W context
|
||||||
|
* 1: Try acquiring SHA H/W resource first and initialize its H/W context if successful. If failed, initialize S/W context.
|
||||||
|
*/
|
||||||
|
static void mbedtls_sha256_init_internal(mbedtls_sha256_context *ctx, int try_hw)
|
||||||
{
|
{
|
||||||
if (crypto_sha_acquire()) {
|
if (try_hw && crypto_sha_acquire()) {
|
||||||
ctx->ishw = 1;
|
ctx->active_ctx = &ctx->hw_ctx;
|
||||||
mbedtls_sha256_hw_init(&ctx->hw_ctx);
|
mbedtls_sha256_hw_init(&ctx->hw_ctx);
|
||||||
}
|
} else {
|
||||||
else {
|
ctx->active_ctx = &ctx->sw_ctx;
|
||||||
ctx->ishw = 0;
|
|
||||||
mbedtls_sha256_sw_init(&ctx->sw_ctx);
|
mbedtls_sha256_sw_init(&ctx->sw_ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mbedtls_sha256_init(mbedtls_sha256_context *ctx)
|
||||||
|
{
|
||||||
|
mbedtls_sha256_init_internal(ctx, 1);
|
||||||
|
}
|
||||||
|
|
||||||
void mbedtls_sha256_free(mbedtls_sha256_context *ctx)
|
void mbedtls_sha256_free(mbedtls_sha256_context *ctx)
|
||||||
{
|
{
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha256_hw_free(&ctx->hw_ctx);
|
mbedtls_sha256_hw_free(&ctx->hw_ctx);
|
||||||
crypto_sha_release();
|
crypto_sha_release();
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha256_sw_free(&ctx->sw_ctx);
|
mbedtls_sha256_sw_free(&ctx->sw_ctx);
|
||||||
}
|
}
|
||||||
|
ctx->active_ctx = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha256_clone(mbedtls_sha256_context *dst,
|
void mbedtls_sha256_clone(mbedtls_sha256_context *dst,
|
||||||
const mbedtls_sha256_context *src)
|
const mbedtls_sha256_context *src)
|
||||||
{
|
{
|
||||||
if (src->ishw) {
|
// Corner case: Destination/source contexts are the same
|
||||||
|
if (dst == src) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If dst is H/W context, we need to change it to S/W context first before cloning to.
|
||||||
|
if (dst->active_ctx == &dst->hw_ctx) {
|
||||||
|
mbedtls_sha256_free(dst);
|
||||||
|
// Force S/W context
|
||||||
|
mbedtls_sha256_init_internal(dst, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src->active_ctx == &src->hw_ctx) {
|
||||||
// Clone S/W ctx from H/W ctx
|
// Clone S/W ctx from H/W ctx
|
||||||
dst->ishw = 0;
|
|
||||||
dst->sw_ctx.total[0] = src->hw_ctx.total;
|
dst->sw_ctx.total[0] = src->hw_ctx.total;
|
||||||
dst->sw_ctx.total[1] = 0;
|
dst->sw_ctx.total[1] = 0;
|
||||||
{
|
{
|
||||||
|
@ -79,8 +95,7 @@ void mbedtls_sha256_clone(mbedtls_sha256_context *dst,
|
||||||
if (src->hw_ctx.buffer_left == src->hw_ctx.blocksize) {
|
if (src->hw_ctx.buffer_left == src->hw_ctx.blocksize) {
|
||||||
mbedtls_sha256_sw_process(&dst->sw_ctx, dst->sw_ctx.buffer);
|
mbedtls_sha256_sw_process(&dst->sw_ctx, dst->sw_ctx.buffer);
|
||||||
}
|
}
|
||||||
}
|
} else if (src->active_ctx == &src->sw_ctx) {
|
||||||
else {
|
|
||||||
// Clone S/W ctx from S/W ctx
|
// Clone S/W ctx from S/W ctx
|
||||||
dst->sw_ctx = src->sw_ctx;
|
dst->sw_ctx = src->sw_ctx;
|
||||||
}
|
}
|
||||||
|
@ -90,11 +105,10 @@ void mbedtls_sha256_clone(mbedtls_sha256_context *dst,
|
||||||
* SHA-256 context setup
|
* SHA-256 context setup
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224)
|
void mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224)
|
||||||
{
|
{
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha256_hw_starts(&ctx->hw_ctx, is224);
|
mbedtls_sha256_hw_starts(&ctx->hw_ctx, is224);
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha256_sw_starts(&ctx->sw_ctx, is224);
|
mbedtls_sha256_sw_starts(&ctx->sw_ctx, is224);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,10 +118,9 @@ void mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224)
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha256_update(mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen)
|
void mbedtls_sha256_update(mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen)
|
||||||
{
|
{
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha256_hw_update(&ctx->hw_ctx, input, ilen);
|
mbedtls_sha256_hw_update(&ctx->hw_ctx, input, ilen);
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha256_sw_update(&ctx->sw_ctx, input, ilen);
|
mbedtls_sha256_sw_update(&ctx->sw_ctx, input, ilen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,20 +130,18 @@ void mbedtls_sha256_update(mbedtls_sha256_context *ctx, const unsigned char *inp
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha256_finish(mbedtls_sha256_context *ctx, unsigned char output[32])
|
void mbedtls_sha256_finish(mbedtls_sha256_context *ctx, unsigned char output[32])
|
||||||
{
|
{
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha256_hw_finish(&ctx->hw_ctx, output);
|
mbedtls_sha256_hw_finish(&ctx->hw_ctx, output);
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha256_sw_finish(&ctx->sw_ctx, output);
|
mbedtls_sha256_sw_finish(&ctx->sw_ctx, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha256_process(mbedtls_sha256_context *ctx, const unsigned char data[64])
|
void mbedtls_sha256_process(mbedtls_sha256_context *ctx, const unsigned char data[64])
|
||||||
{
|
{
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha256_hw_process(&ctx->hw_ctx, data);
|
mbedtls_sha256_hw_process(&ctx->hw_ctx, data);
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha256_sw_process(&ctx->sw_ctx, data);
|
mbedtls_sha256_sw_process(&ctx->sw_ctx, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,13 +16,8 @@
|
||||||
#ifndef MBEDTLS_SHA256_ALT_H
|
#ifndef MBEDTLS_SHA256_ALT_H
|
||||||
#define MBEDTLS_SHA256_ALT_H
|
#define MBEDTLS_SHA256_ALT_H
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/sha256.h"
|
||||||
#include "config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA256_C)
|
|
||||||
#if defined(MBEDTLS_SHA256_ALT)
|
#if defined(MBEDTLS_SHA256_ALT)
|
||||||
|
|
||||||
#include "sha_alt_hw.h"
|
#include "sha_alt_hw.h"
|
||||||
|
@ -37,9 +32,8 @@ struct mbedtls_sha256_context_s;
|
||||||
/**
|
/**
|
||||||
* \brief SHA-256 context structure
|
* \brief SHA-256 context structure
|
||||||
*/
|
*/
|
||||||
typedef struct mbedtls_sha256_context_s
|
typedef struct mbedtls_sha256_context_s {
|
||||||
{
|
void *active_ctx;
|
||||||
int ishw;
|
|
||||||
crypto_sha_context hw_ctx;
|
crypto_sha_context hw_ctx;
|
||||||
mbedtls_sha256_sw_context sw_ctx;
|
mbedtls_sha256_sw_context sw_ctx;
|
||||||
}
|
}
|
||||||
|
@ -84,7 +78,7 @@ void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 );
|
||||||
* \param ilen length of the input data
|
* \param ilen length of the input data
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input,
|
void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input,
|
||||||
size_t ilen );
|
size_t ilen );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief SHA-256 final digest
|
* \brief SHA-256 final digest
|
||||||
|
@ -102,6 +96,5 @@ void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char da
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* MBEDTLS_SHA256_ALT */
|
#endif /* MBEDTLS_SHA256_ALT */
|
||||||
#endif /* MBEDTLS_SHA256_C */
|
|
||||||
|
|
||||||
#endif /* sha256_alt.h */
|
#endif /* sha256_alt.h */
|
||||||
|
|
|
@ -24,17 +24,11 @@
|
||||||
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/sha256.h"
|
||||||
#include "mbedtls/config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA256_C)
|
#if defined(MBEDTLS_SHA256_C)
|
||||||
#if defined(MBEDTLS_SHA256_ALT)
|
#if defined(MBEDTLS_SHA256_ALT)
|
||||||
|
|
||||||
#include "mbedtls/sha256.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#if defined(MBEDTLS_SELF_TEST)
|
#if defined(MBEDTLS_SELF_TEST)
|
||||||
#if defined(MBEDTLS_PLATFORM_C)
|
#if defined(MBEDTLS_PLATFORM_C)
|
||||||
|
@ -49,8 +43,10 @@
|
||||||
#endif /* MBEDTLS_SELF_TEST */
|
#endif /* MBEDTLS_SELF_TEST */
|
||||||
|
|
||||||
/* Implementation that should never be optimized out by the compiler */
|
/* Implementation that should never be optimized out by the compiler */
|
||||||
static void mbedtls_zeroize( void *v, size_t n ) {
|
static void mbedtls_zeroize( void *v, size_t n )
|
||||||
volatile unsigned char *p = v; while( n-- ) *p++ = 0;
|
{
|
||||||
|
volatile unsigned char *p = v;
|
||||||
|
while( n-- ) *p++ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -90,7 +86,7 @@ void mbedtls_sha256_sw_free( mbedtls_sha256_sw_context *ctx )
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha256_sw_clone( mbedtls_sha256_sw_context *dst,
|
void mbedtls_sha256_sw_clone( mbedtls_sha256_sw_context *dst,
|
||||||
const mbedtls_sha256_sw_context *src )
|
const mbedtls_sha256_sw_context *src )
|
||||||
{
|
{
|
||||||
*dst = *src;
|
*dst = *src;
|
||||||
}
|
}
|
||||||
|
@ -103,8 +99,7 @@ void mbedtls_sha256_sw_starts( mbedtls_sha256_sw_context *ctx, int is224 )
|
||||||
ctx->total[0] = 0;
|
ctx->total[0] = 0;
|
||||||
ctx->total[1] = 0;
|
ctx->total[1] = 0;
|
||||||
|
|
||||||
if( is224 == 0 )
|
if( is224 == 0 ) {
|
||||||
{
|
|
||||||
/* SHA-256 */
|
/* SHA-256 */
|
||||||
ctx->state[0] = 0x6A09E667;
|
ctx->state[0] = 0x6A09E667;
|
||||||
ctx->state[1] = 0xBB67AE85;
|
ctx->state[1] = 0xBB67AE85;
|
||||||
|
@ -114,9 +109,7 @@ void mbedtls_sha256_sw_starts( mbedtls_sha256_sw_context *ctx, int is224 )
|
||||||
ctx->state[5] = 0x9B05688C;
|
ctx->state[5] = 0x9B05688C;
|
||||||
ctx->state[6] = 0x1F83D9AB;
|
ctx->state[6] = 0x1F83D9AB;
|
||||||
ctx->state[7] = 0x5BE0CD19;
|
ctx->state[7] = 0x5BE0CD19;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* SHA-224 */
|
/* SHA-224 */
|
||||||
ctx->state[0] = 0xC1059ED8;
|
ctx->state[0] = 0xC1059ED8;
|
||||||
ctx->state[1] = 0x367CD507;
|
ctx->state[1] = 0x367CD507;
|
||||||
|
@ -131,8 +124,7 @@ void mbedtls_sha256_sw_starts( mbedtls_sha256_sw_context *ctx, int is224 )
|
||||||
ctx->is224 = is224;
|
ctx->is224 = is224;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint32_t K[] =
|
static const uint32_t K[] = {
|
||||||
{
|
|
||||||
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
|
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
|
||||||
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
|
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
|
||||||
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
|
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
|
||||||
|
@ -186,8 +178,7 @@ void mbedtls_sha256_sw_process( mbedtls_sha256_sw_context *ctx, const unsigned c
|
||||||
A[i] = ctx->state[i];
|
A[i] = ctx->state[i];
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA256_SMALLER)
|
#if defined(MBEDTLS_SHA256_SMALLER)
|
||||||
for( i = 0; i < 64; i++ )
|
for( i = 0; i < 64; i++ ) {
|
||||||
{
|
|
||||||
if( i < 16 )
|
if( i < 16 )
|
||||||
GET_UINT32_BE( W[i], data, 4 * i );
|
GET_UINT32_BE( W[i], data, 4 * i );
|
||||||
else
|
else
|
||||||
|
@ -195,15 +186,21 @@ void mbedtls_sha256_sw_process( mbedtls_sha256_sw_context *ctx, const unsigned c
|
||||||
|
|
||||||
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] );
|
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] );
|
||||||
|
|
||||||
temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3];
|
temp1 = A[7];
|
||||||
A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1;
|
A[7] = A[6];
|
||||||
|
A[6] = A[5];
|
||||||
|
A[5] = A[4];
|
||||||
|
A[4] = A[3];
|
||||||
|
A[3] = A[2];
|
||||||
|
A[2] = A[1];
|
||||||
|
A[1] = A[0];
|
||||||
|
A[0] = temp1;
|
||||||
}
|
}
|
||||||
#else /* MBEDTLS_SHA256_SMALLER */
|
#else /* MBEDTLS_SHA256_SMALLER */
|
||||||
for( i = 0; i < 16; i++ )
|
for( i = 0; i < 16; i++ )
|
||||||
GET_UINT32_BE( W[i], data, 4 * i );
|
GET_UINT32_BE( W[i], data, 4 * i );
|
||||||
|
|
||||||
for( i = 0; i < 16; i += 8 )
|
for( i = 0; i < 16; i += 8 ) {
|
||||||
{
|
|
||||||
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] );
|
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] );
|
||||||
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] );
|
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] );
|
||||||
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] );
|
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] );
|
||||||
|
@ -214,8 +211,7 @@ void mbedtls_sha256_sw_process( mbedtls_sha256_sw_context *ctx, const unsigned c
|
||||||
P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] );
|
P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] );
|
||||||
}
|
}
|
||||||
|
|
||||||
for( i = 16; i < 64; i += 8 )
|
for( i = 16; i < 64; i += 8 ) {
|
||||||
{
|
|
||||||
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] );
|
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] );
|
||||||
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] );
|
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] );
|
||||||
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] );
|
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] );
|
||||||
|
@ -235,7 +231,7 @@ void mbedtls_sha256_sw_process( mbedtls_sha256_sw_context *ctx, const unsigned c
|
||||||
* SHA-256 process buffer
|
* SHA-256 process buffer
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha256_sw_update( mbedtls_sha256_sw_context *ctx, const unsigned char *input,
|
void mbedtls_sha256_sw_update( mbedtls_sha256_sw_context *ctx, const unsigned char *input,
|
||||||
size_t ilen )
|
size_t ilen )
|
||||||
{
|
{
|
||||||
size_t fill;
|
size_t fill;
|
||||||
uint32_t left;
|
uint32_t left;
|
||||||
|
@ -252,8 +248,7 @@ void mbedtls_sha256_sw_update( mbedtls_sha256_sw_context *ctx, const unsigned ch
|
||||||
if( ctx->total[0] < (uint32_t) ilen )
|
if( ctx->total[0] < (uint32_t) ilen )
|
||||||
ctx->total[1]++;
|
ctx->total[1]++;
|
||||||
|
|
||||||
if( left && ilen >= fill )
|
if( left && ilen >= fill ) {
|
||||||
{
|
|
||||||
memcpy( (void *) (ctx->buffer + left), input, fill );
|
memcpy( (void *) (ctx->buffer + left), input, fill );
|
||||||
mbedtls_sha256_sw_process( ctx, ctx->buffer );
|
mbedtls_sha256_sw_process( ctx, ctx->buffer );
|
||||||
input += fill;
|
input += fill;
|
||||||
|
@ -261,8 +256,7 @@ void mbedtls_sha256_sw_update( mbedtls_sha256_sw_context *ctx, const unsigned ch
|
||||||
left = 0;
|
left = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while( ilen >= 64 )
|
while( ilen >= 64 ) {
|
||||||
{
|
|
||||||
mbedtls_sha256_sw_process( ctx, input );
|
mbedtls_sha256_sw_process( ctx, input );
|
||||||
input += 64;
|
input += 64;
|
||||||
ilen -= 64;
|
ilen -= 64;
|
||||||
|
@ -272,9 +266,8 @@ void mbedtls_sha256_sw_update( mbedtls_sha256_sw_context *ctx, const unsigned ch
|
||||||
memcpy( (void *) (ctx->buffer + left), input, ilen );
|
memcpy( (void *) (ctx->buffer + left), input, ilen );
|
||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned char sha256_padding[64] =
|
static const unsigned char sha256_padding[64] = {
|
||||||
{
|
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
@ -290,7 +283,7 @@ void mbedtls_sha256_sw_finish( mbedtls_sha256_sw_context *ctx, unsigned char out
|
||||||
unsigned char msglen[8];
|
unsigned char msglen[8];
|
||||||
|
|
||||||
high = ( ctx->total[0] >> 29 )
|
high = ( ctx->total[0] >> 29 )
|
||||||
| ( ctx->total[1] << 3 );
|
| ( ctx->total[1] << 3 );
|
||||||
low = ( ctx->total[0] << 3 );
|
low = ( ctx->total[0] << 3 );
|
||||||
|
|
||||||
PUT_UINT32_BE( high, msglen, 0 );
|
PUT_UINT32_BE( high, msglen, 0 );
|
||||||
|
|
|
@ -23,13 +23,6 @@
|
||||||
#ifndef MBEDTLS_SHA256_ALT_SW_H
|
#ifndef MBEDTLS_SHA256_ALT_SW_H
|
||||||
#define MBEDTLS_SHA256_ALT_SW_H
|
#define MBEDTLS_SHA256_ALT_SW_H
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
|
||||||
#include "config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA256_C)
|
|
||||||
#if defined(MBEDTLS_SHA256_ALT)
|
#if defined(MBEDTLS_SHA256_ALT)
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
@ -42,8 +35,7 @@ extern "C" {
|
||||||
/**
|
/**
|
||||||
* \brief SHA-256 context structure
|
* \brief SHA-256 context structure
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
uint32_t total[2]; /*!< number of bytes processed */
|
uint32_t total[2]; /*!< number of bytes processed */
|
||||||
uint32_t state[8]; /*!< intermediate digest state */
|
uint32_t state[8]; /*!< intermediate digest state */
|
||||||
unsigned char buffer[64]; /*!< data block being processed */
|
unsigned char buffer[64]; /*!< data block being processed */
|
||||||
|
@ -72,7 +64,7 @@ void mbedtls_sha256_sw_free( mbedtls_sha256_sw_context *ctx );
|
||||||
* \param src The context to be cloned
|
* \param src The context to be cloned
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha256_sw_clone( mbedtls_sha256_sw_context *dst,
|
void mbedtls_sha256_sw_clone( mbedtls_sha256_sw_context *dst,
|
||||||
const mbedtls_sha256_sw_context *src );
|
const mbedtls_sha256_sw_context *src );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief SHA-256 context setup
|
* \brief SHA-256 context setup
|
||||||
|
@ -90,7 +82,7 @@ void mbedtls_sha256_sw_starts( mbedtls_sha256_sw_context *ctx, int is224 );
|
||||||
* \param ilen length of the input data
|
* \param ilen length of the input data
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha256_sw_update( mbedtls_sha256_sw_context *ctx, const unsigned char *input,
|
void mbedtls_sha256_sw_update( mbedtls_sha256_sw_context *ctx, const unsigned char *input,
|
||||||
size_t ilen );
|
size_t ilen );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief SHA-256 final digest
|
* \brief SHA-256 final digest
|
||||||
|
@ -108,6 +100,5 @@ void mbedtls_sha256_sw_process( mbedtls_sha256_sw_context *ctx, const unsigned c
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* MBEDTLS_SHA256_ALT */
|
#endif /* MBEDTLS_SHA256_ALT */
|
||||||
#endif /* MBEDTLS_SHA256_C */
|
|
||||||
|
|
||||||
#endif /* sha256_alt_sw.h */
|
#endif /* sha256_alt_sw.h */
|
||||||
|
|
|
@ -14,53 +14,69 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/sha512.h"
|
||||||
#include "mbedtls/config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA512_C)
|
#if defined(MBEDTLS_SHA512_C)
|
||||||
#if defined(MBEDTLS_SHA512_ALT)
|
#if defined(MBEDTLS_SHA512_ALT)
|
||||||
|
|
||||||
#include "sha512_alt.h"
|
|
||||||
#include "crypto-misc.h"
|
#include "crypto-misc.h"
|
||||||
#include "nu_bitutil.h"
|
#include "nu_bitutil.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
void mbedtls_sha512_init(mbedtls_sha512_context *ctx)
|
/* Choose SHA S/W or H/W context and initialize it
|
||||||
|
*
|
||||||
|
* try_hw:
|
||||||
|
* 0: Initialize S/W context
|
||||||
|
* 1: Try acquiring SHA H/W resource first and initialize its H/W context if successful. If failed, initialize S/W context.
|
||||||
|
*/
|
||||||
|
static void mbedtls_sha512_init_internal(mbedtls_sha512_context *ctx, int try_hw)
|
||||||
{
|
{
|
||||||
if (crypto_sha_acquire()) {
|
if (try_hw && crypto_sha_acquire()) {
|
||||||
ctx->ishw = 1;
|
ctx->active_ctx = &ctx->hw_ctx;
|
||||||
mbedtls_sha512_hw_init(&ctx->hw_ctx);
|
mbedtls_sha512_hw_init(&ctx->hw_ctx);
|
||||||
}
|
} else {
|
||||||
else {
|
ctx->active_ctx = &ctx->sw_ctx;
|
||||||
ctx->ishw = 0;
|
|
||||||
mbedtls_sha512_sw_init(&ctx->sw_ctx);
|
mbedtls_sha512_sw_init(&ctx->sw_ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mbedtls_sha512_init(mbedtls_sha512_context *ctx)
|
||||||
|
{
|
||||||
|
mbedtls_sha512_init_internal(ctx, 1);
|
||||||
|
}
|
||||||
|
|
||||||
void mbedtls_sha512_free(mbedtls_sha512_context *ctx)
|
void mbedtls_sha512_free(mbedtls_sha512_context *ctx)
|
||||||
{
|
{
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha512_hw_free(&ctx->hw_ctx);
|
mbedtls_sha512_hw_free(&ctx->hw_ctx);
|
||||||
crypto_sha_release();
|
crypto_sha_release();
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha512_sw_free(&ctx->sw_ctx);
|
mbedtls_sha512_sw_free(&ctx->sw_ctx);
|
||||||
}
|
}
|
||||||
|
ctx->active_ctx = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha512_clone(mbedtls_sha512_context *dst,
|
void mbedtls_sha512_clone(mbedtls_sha512_context *dst,
|
||||||
const mbedtls_sha512_context *src)
|
const mbedtls_sha512_context *src)
|
||||||
{
|
{
|
||||||
if (src->ishw) {
|
// Corner case: Destination/source contexts are the same
|
||||||
|
if (dst == src) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If dst is H/W context, we need to change it to S/W context first before cloning to.
|
||||||
|
if (dst->active_ctx == &dst->hw_ctx) {
|
||||||
|
mbedtls_sha512_free(dst);
|
||||||
|
// Force S/W context
|
||||||
|
mbedtls_sha512_init_internal(dst, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src->active_ctx == &src->hw_ctx) {
|
||||||
// Clone S/W ctx from H/W ctx
|
// Clone S/W ctx from H/W ctx
|
||||||
dst->ishw = 0;
|
|
||||||
dst->sw_ctx.total[0] = src->hw_ctx.total;
|
dst->sw_ctx.total[0] = src->hw_ctx.total;
|
||||||
dst->sw_ctx.total[1] = 0;
|
dst->sw_ctx.total[1] = 0;
|
||||||
{
|
{
|
||||||
|
@ -80,8 +96,7 @@ void mbedtls_sha512_clone(mbedtls_sha512_context *dst,
|
||||||
if (src->hw_ctx.buffer_left == src->hw_ctx.blocksize) {
|
if (src->hw_ctx.buffer_left == src->hw_ctx.blocksize) {
|
||||||
mbedtls_sha512_sw_process(&dst->sw_ctx, dst->sw_ctx.buffer);
|
mbedtls_sha512_sw_process(&dst->sw_ctx, dst->sw_ctx.buffer);
|
||||||
}
|
}
|
||||||
}
|
} else if (src->active_ctx == &src->sw_ctx) {
|
||||||
else {
|
|
||||||
// Clone S/W ctx from S/W ctx
|
// Clone S/W ctx from S/W ctx
|
||||||
dst->sw_ctx = src->sw_ctx;
|
dst->sw_ctx = src->sw_ctx;
|
||||||
}
|
}
|
||||||
|
@ -91,11 +106,10 @@ void mbedtls_sha512_clone(mbedtls_sha512_context *dst,
|
||||||
* SHA-512 context setup
|
* SHA-512 context setup
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha512_starts(mbedtls_sha512_context *ctx, int is384)
|
void mbedtls_sha512_starts(mbedtls_sha512_context *ctx, int is384)
|
||||||
{
|
{
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha512_hw_starts(&ctx->hw_ctx, is384);
|
mbedtls_sha512_hw_starts(&ctx->hw_ctx, is384);
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha512_sw_starts(&ctx->sw_ctx, is384);
|
mbedtls_sha512_sw_starts(&ctx->sw_ctx, is384);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,10 +119,9 @@ void mbedtls_sha512_starts(mbedtls_sha512_context *ctx, int is384)
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha512_update(mbedtls_sha512_context *ctx, const unsigned char *input, size_t ilen)
|
void mbedtls_sha512_update(mbedtls_sha512_context *ctx, const unsigned char *input, size_t ilen)
|
||||||
{
|
{
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha512_hw_update(&ctx->hw_ctx, input, ilen);
|
mbedtls_sha512_hw_update(&ctx->hw_ctx, input, ilen);
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha512_sw_update(&ctx->sw_ctx, input, ilen);
|
mbedtls_sha512_sw_update(&ctx->sw_ctx, input, ilen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,20 +131,18 @@ void mbedtls_sha512_update(mbedtls_sha512_context *ctx, const unsigned char *inp
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha512_finish(mbedtls_sha512_context *ctx, unsigned char output[64])
|
void mbedtls_sha512_finish(mbedtls_sha512_context *ctx, unsigned char output[64])
|
||||||
{
|
{
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha512_hw_finish(&ctx->hw_ctx, output);
|
mbedtls_sha512_hw_finish(&ctx->hw_ctx, output);
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha512_sw_finish(&ctx->sw_ctx, output);
|
mbedtls_sha512_sw_finish(&ctx->sw_ctx, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha512_process(mbedtls_sha512_context *ctx, const unsigned char data[128])
|
void mbedtls_sha512_process(mbedtls_sha512_context *ctx, const unsigned char data[128])
|
||||||
{
|
{
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha512_hw_process(&ctx->hw_ctx, data);
|
mbedtls_sha512_hw_process(&ctx->hw_ctx, data);
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha512_sw_process(&ctx->sw_ctx, data);
|
mbedtls_sha512_sw_process(&ctx->sw_ctx, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,13 +16,8 @@
|
||||||
#ifndef MBEDTLS_SHA512_ALT_H
|
#ifndef MBEDTLS_SHA512_ALT_H
|
||||||
#define MBEDTLS_SHA512_ALT_H
|
#define MBEDTLS_SHA512_ALT_H
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/sha512.h"
|
||||||
#include "config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA512_C)
|
|
||||||
#if defined(MBEDTLS_SHA512_ALT)
|
#if defined(MBEDTLS_SHA512_ALT)
|
||||||
|
|
||||||
#include "sha_alt_hw.h"
|
#include "sha_alt_hw.h"
|
||||||
|
@ -37,9 +32,8 @@ struct mbedtls_sha512_context_s;
|
||||||
/**
|
/**
|
||||||
* \brief SHA-512 context structure
|
* \brief SHA-512 context structure
|
||||||
*/
|
*/
|
||||||
typedef struct mbedtls_sha512_context_s
|
typedef struct mbedtls_sha512_context_s {
|
||||||
{
|
void *active_ctx;
|
||||||
int ishw;
|
|
||||||
crypto_sha_context hw_ctx;
|
crypto_sha_context hw_ctx;
|
||||||
mbedtls_sha512_sw_context sw_ctx;
|
mbedtls_sha512_sw_context sw_ctx;
|
||||||
}
|
}
|
||||||
|
@ -84,7 +78,7 @@ void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 );
|
||||||
* \param ilen length of the input data
|
* \param ilen length of the input data
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input,
|
void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input,
|
||||||
size_t ilen );
|
size_t ilen );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief SHA-512 final digest
|
* \brief SHA-512 final digest
|
||||||
|
@ -102,6 +96,5 @@ void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char da
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* MBEDTLS_SHA512_ALT */
|
#endif /* MBEDTLS_SHA512_ALT */
|
||||||
#endif /* MBEDTLS_SHA512_C */
|
|
||||||
|
|
||||||
#endif /* sha512_alt.h */
|
#endif /* sha512_alt.h */
|
||||||
|
|
|
@ -24,21 +24,15 @@
|
||||||
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/sha512.h"
|
||||||
#include "mbedtls/config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA512_C)
|
#if defined(MBEDTLS_SHA512_C)
|
||||||
#if defined(MBEDTLS_SHA512_ALT)
|
#if defined(MBEDTLS_SHA512_ALT)
|
||||||
|
|
||||||
#include "mbedtls/sha512.h"
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) || defined(__WATCOMC__)
|
#if defined(_MSC_VER) || defined(__WATCOMC__)
|
||||||
#define UL64(x) x##ui64
|
#define UL64(x) x##ui64
|
||||||
#else
|
#else
|
||||||
#define UL64(x) x##ULL
|
#define UL64(x) x##ULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -56,8 +50,10 @@
|
||||||
#endif /* MBEDTLS_SELF_TEST */
|
#endif /* MBEDTLS_SELF_TEST */
|
||||||
|
|
||||||
/* Implementation that should never be optimized out by the compiler */
|
/* Implementation that should never be optimized out by the compiler */
|
||||||
static void mbedtls_zeroize( void *v, size_t n ) {
|
static void mbedtls_zeroize( void *v, size_t n )
|
||||||
volatile unsigned char *p = v; while( n-- ) *p++ = 0;
|
{
|
||||||
|
volatile unsigned char *p = v;
|
||||||
|
while( n-- ) *p++ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -105,7 +101,7 @@ void mbedtls_sha512_sw_free( mbedtls_sha512_sw_context *ctx )
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha512_sw_clone( mbedtls_sha512_sw_context *dst,
|
void mbedtls_sha512_sw_clone( mbedtls_sha512_sw_context *dst,
|
||||||
const mbedtls_sha512_sw_context *src )
|
const mbedtls_sha512_sw_context *src )
|
||||||
{
|
{
|
||||||
*dst = *src;
|
*dst = *src;
|
||||||
}
|
}
|
||||||
|
@ -118,8 +114,7 @@ void mbedtls_sha512_sw_starts( mbedtls_sha512_sw_context *ctx, int is384 )
|
||||||
ctx->total[0] = 0;
|
ctx->total[0] = 0;
|
||||||
ctx->total[1] = 0;
|
ctx->total[1] = 0;
|
||||||
|
|
||||||
if( is384 == 0 )
|
if( is384 == 0 ) {
|
||||||
{
|
|
||||||
/* SHA-512 */
|
/* SHA-512 */
|
||||||
ctx->state[0] = UL64(0x6A09E667F3BCC908);
|
ctx->state[0] = UL64(0x6A09E667F3BCC908);
|
||||||
ctx->state[1] = UL64(0xBB67AE8584CAA73B);
|
ctx->state[1] = UL64(0xBB67AE8584CAA73B);
|
||||||
|
@ -129,9 +124,7 @@ void mbedtls_sha512_sw_starts( mbedtls_sha512_sw_context *ctx, int is384 )
|
||||||
ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
|
ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
|
||||||
ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
|
ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
|
||||||
ctx->state[7] = UL64(0x5BE0CD19137E2179);
|
ctx->state[7] = UL64(0x5BE0CD19137E2179);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* SHA-384 */
|
/* SHA-384 */
|
||||||
ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
|
ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
|
||||||
ctx->state[1] = UL64(0x629A292A367CD507);
|
ctx->state[1] = UL64(0x629A292A367CD507);
|
||||||
|
@ -151,8 +144,7 @@ void mbedtls_sha512_sw_starts( mbedtls_sha512_sw_context *ctx, int is384 )
|
||||||
/*
|
/*
|
||||||
* Round constants
|
* Round constants
|
||||||
*/
|
*/
|
||||||
static const uint64_t K[80] =
|
static const uint64_t K[80] = {
|
||||||
{
|
|
||||||
UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
|
UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
|
||||||
UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
|
UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
|
||||||
UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
|
UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
|
||||||
|
@ -220,13 +212,11 @@ void mbedtls_sha512_sw_process( mbedtls_sha512_sw_context *ctx, const unsigned c
|
||||||
d += temp1; h = temp1 + temp2; \
|
d += temp1; h = temp1 + temp2; \
|
||||||
}
|
}
|
||||||
|
|
||||||
for( i = 0; i < 16; i++ )
|
for( i = 0; i < 16; i++ ) {
|
||||||
{
|
|
||||||
GET_UINT64_BE( W[i], data, i << 3 );
|
GET_UINT64_BE( W[i], data, i << 3 );
|
||||||
}
|
}
|
||||||
|
|
||||||
for( ; i < 80; i++ )
|
for( ; i < 80; i++ ) {
|
||||||
{
|
|
||||||
W[i] = S1(W[i - 2]) + W[i - 7] +
|
W[i] = S1(W[i - 2]) + W[i - 7] +
|
||||||
S0(W[i - 15]) + W[i - 16];
|
S0(W[i - 15]) + W[i - 16];
|
||||||
}
|
}
|
||||||
|
@ -241,18 +231,24 @@ void mbedtls_sha512_sw_process( mbedtls_sha512_sw_context *ctx, const unsigned c
|
||||||
H = ctx->state[7];
|
H = ctx->state[7];
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
do
|
do {
|
||||||
{
|
P( A, B, C, D, E, F, G, H, W[i], K[i] );
|
||||||
P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++;
|
i++;
|
||||||
P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++;
|
P( H, A, B, C, D, E, F, G, W[i], K[i] );
|
||||||
P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++;
|
i++;
|
||||||
P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++;
|
P( G, H, A, B, C, D, E, F, W[i], K[i] );
|
||||||
P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++;
|
i++;
|
||||||
P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++;
|
P( F, G, H, A, B, C, D, E, W[i], K[i] );
|
||||||
P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++;
|
i++;
|
||||||
P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++;
|
P( E, F, G, H, A, B, C, D, W[i], K[i] );
|
||||||
}
|
i++;
|
||||||
while( i < 80 );
|
P( D, E, F, G, H, A, B, C, W[i], K[i] );
|
||||||
|
i++;
|
||||||
|
P( C, D, E, F, G, H, A, B, W[i], K[i] );
|
||||||
|
i++;
|
||||||
|
P( B, C, D, E, F, G, H, A, W[i], K[i] );
|
||||||
|
i++;
|
||||||
|
} while( i < 80 );
|
||||||
|
|
||||||
ctx->state[0] += A;
|
ctx->state[0] += A;
|
||||||
ctx->state[1] += B;
|
ctx->state[1] += B;
|
||||||
|
@ -269,7 +265,7 @@ void mbedtls_sha512_sw_process( mbedtls_sha512_sw_context *ctx, const unsigned c
|
||||||
* SHA-512 process buffer
|
* SHA-512 process buffer
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha512_sw_update( mbedtls_sha512_sw_context *ctx, const unsigned char *input,
|
void mbedtls_sha512_sw_update( mbedtls_sha512_sw_context *ctx, const unsigned char *input,
|
||||||
size_t ilen )
|
size_t ilen )
|
||||||
{
|
{
|
||||||
size_t fill;
|
size_t fill;
|
||||||
unsigned int left;
|
unsigned int left;
|
||||||
|
@ -285,8 +281,7 @@ void mbedtls_sha512_sw_update( mbedtls_sha512_sw_context *ctx, const unsigned ch
|
||||||
if( ctx->total[0] < (uint64_t) ilen )
|
if( ctx->total[0] < (uint64_t) ilen )
|
||||||
ctx->total[1]++;
|
ctx->total[1]++;
|
||||||
|
|
||||||
if( left && ilen >= fill )
|
if( left && ilen >= fill ) {
|
||||||
{
|
|
||||||
memcpy( (void *) (ctx->buffer + left), input, fill );
|
memcpy( (void *) (ctx->buffer + left), input, fill );
|
||||||
mbedtls_sha512_sw_process( ctx, ctx->buffer );
|
mbedtls_sha512_sw_process( ctx, ctx->buffer );
|
||||||
input += fill;
|
input += fill;
|
||||||
|
@ -294,8 +289,7 @@ void mbedtls_sha512_sw_update( mbedtls_sha512_sw_context *ctx, const unsigned ch
|
||||||
left = 0;
|
left = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while( ilen >= 128 )
|
while( ilen >= 128 ) {
|
||||||
{
|
|
||||||
mbedtls_sha512_sw_process( ctx, input );
|
mbedtls_sha512_sw_process( ctx, input );
|
||||||
input += 128;
|
input += 128;
|
||||||
ilen -= 128;
|
ilen -= 128;
|
||||||
|
@ -305,9 +299,8 @@ void mbedtls_sha512_sw_update( mbedtls_sha512_sw_context *ctx, const unsigned ch
|
||||||
memcpy( (void *) (ctx->buffer + left), input, ilen );
|
memcpy( (void *) (ctx->buffer + left), input, ilen );
|
||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned char sha512_padding[128] =
|
static const unsigned char sha512_padding[128] = {
|
||||||
{
|
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
@ -327,7 +320,7 @@ void mbedtls_sha512_sw_finish( mbedtls_sha512_sw_context *ctx, unsigned char out
|
||||||
unsigned char msglen[16];
|
unsigned char msglen[16];
|
||||||
|
|
||||||
high = ( ctx->total[0] >> 61 )
|
high = ( ctx->total[0] >> 61 )
|
||||||
| ( ctx->total[1] << 3 );
|
| ( ctx->total[1] << 3 );
|
||||||
low = ( ctx->total[0] << 3 );
|
low = ( ctx->total[0] << 3 );
|
||||||
|
|
||||||
PUT_UINT64_BE( high, msglen, 0 );
|
PUT_UINT64_BE( high, msglen, 0 );
|
||||||
|
@ -346,8 +339,7 @@ void mbedtls_sha512_sw_finish( mbedtls_sha512_sw_context *ctx, unsigned char out
|
||||||
PUT_UINT64_BE( ctx->state[4], output, 32 );
|
PUT_UINT64_BE( ctx->state[4], output, 32 );
|
||||||
PUT_UINT64_BE( ctx->state[5], output, 40 );
|
PUT_UINT64_BE( ctx->state[5], output, 40 );
|
||||||
|
|
||||||
if( ctx->is384 == 0 )
|
if( ctx->is384 == 0 ) {
|
||||||
{
|
|
||||||
PUT_UINT64_BE( ctx->state[6], output, 48 );
|
PUT_UINT64_BE( ctx->state[6], output, 48 );
|
||||||
PUT_UINT64_BE( ctx->state[7], output, 56 );
|
PUT_UINT64_BE( ctx->state[7], output, 56 );
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,13 +23,6 @@
|
||||||
#ifndef MBEDTLS_SHA512_ALT_SW_H
|
#ifndef MBEDTLS_SHA512_ALT_SW_H
|
||||||
#define MBEDTLS_SHA512_ALT_SW_H
|
#define MBEDTLS_SHA512_ALT_SW_H
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
|
||||||
#include "config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA512_C)
|
|
||||||
#if defined(MBEDTLS_SHA512_ALT)
|
#if defined(MBEDTLS_SHA512_ALT)
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
@ -42,8 +35,7 @@ extern "C" {
|
||||||
/**
|
/**
|
||||||
* \brief SHA-512 context structure
|
* \brief SHA-512 context structure
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
uint64_t total[2]; /*!< number of bytes processed */
|
uint64_t total[2]; /*!< number of bytes processed */
|
||||||
uint64_t state[8]; /*!< intermediate digest state */
|
uint64_t state[8]; /*!< intermediate digest state */
|
||||||
unsigned char buffer[128]; /*!< data block being processed */
|
unsigned char buffer[128]; /*!< data block being processed */
|
||||||
|
@ -72,7 +64,7 @@ void mbedtls_sha512_sw_free( mbedtls_sha512_sw_context *ctx );
|
||||||
* \param src The context to be cloned
|
* \param src The context to be cloned
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha512_sw_clone( mbedtls_sha512_sw_context *dst,
|
void mbedtls_sha512_sw_clone( mbedtls_sha512_sw_context *dst,
|
||||||
const mbedtls_sha512_sw_context *src );
|
const mbedtls_sha512_sw_context *src );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief SHA-512 context setup
|
* \brief SHA-512 context setup
|
||||||
|
@ -90,7 +82,7 @@ void mbedtls_sha512_sw_starts( mbedtls_sha512_sw_context *ctx, int is384 );
|
||||||
* \param ilen length of the input data
|
* \param ilen length of the input data
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha512_sw_update( mbedtls_sha512_sw_context *ctx, const unsigned char *input,
|
void mbedtls_sha512_sw_update( mbedtls_sha512_sw_context *ctx, const unsigned char *input,
|
||||||
size_t ilen );
|
size_t ilen );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief SHA-512 final digest
|
* \brief SHA-512 final digest
|
||||||
|
@ -108,6 +100,5 @@ void mbedtls_sha512_sw_process( mbedtls_sha512_sw_context *ctx, const unsigned c
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* MBEDTLS_SHA512_ALT */
|
#endif /* MBEDTLS_SHA512_ALT */
|
||||||
#endif /* MBEDTLS_SHA512_C */
|
|
||||||
|
|
||||||
#endif /* sha512_alt_sw.h */
|
#endif /* sha512_alt_sw.h */
|
||||||
|
|
|
@ -14,30 +14,18 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/sha1.h"
|
||||||
#include "mbedtls/config.h"
|
#include "mbedtls/sha256.h"
|
||||||
#else
|
#include "mbedtls/sha512.h"
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA1_C) || defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C)
|
#if defined(MBEDTLS_SHA1_C) || defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C)
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA1_ALT) || defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA512_ALT)
|
#if defined(MBEDTLS_SHA1_ALT) || defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA512_ALT)
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA1_ALT)
|
|
||||||
#include "sha1_alt.h"
|
|
||||||
#endif /* MBEDTLS_SHA1_ALT */
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA256_ALT)
|
|
||||||
#include "sha256_alt.h"
|
|
||||||
#endif /* MBEDTLS_SHA256_ALT */
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA512_ALT)
|
|
||||||
#include "sha512_alt.h"
|
|
||||||
#endif /* MBEDTLS_SHA512_ALT */
|
|
||||||
|
|
||||||
#include "nu_bitutil.h"
|
#include "nu_bitutil.h"
|
||||||
|
#include "nu_timer.h"
|
||||||
#include "mbed_assert.h"
|
#include "mbed_assert.h"
|
||||||
|
#include "mbed_error.h"
|
||||||
#include "crypto-misc.h"
|
#include "crypto-misc.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -53,8 +41,9 @@ void crypto_sha_getinternstate(unsigned char output[], size_t olen);
|
||||||
|
|
||||||
void mbedtls_sha1_hw_init(crypto_sha_context *ctx)
|
void mbedtls_sha1_hw_init(crypto_sha_context *ctx)
|
||||||
{
|
{
|
||||||
|
/* Init crypto module */
|
||||||
crypto_init();
|
crypto_init();
|
||||||
memset(ctx, 0, sizeof(crypto_sha_context));
|
memset(ctx, 0, sizeof(*ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha1_hw_free(crypto_sha_context *ctx)
|
void mbedtls_sha1_hw_free(crypto_sha_context *ctx)
|
||||||
|
@ -63,30 +52,28 @@ void mbedtls_sha1_hw_free(crypto_sha_context *ctx)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
crypto_zeroize(ctx, sizeof(crypto_sha_context));
|
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
|
||||||
}
|
|
||||||
|
|
||||||
void mbedtls_sha1_hw_clone(crypto_sha_context *dst,
|
/* Uninit crypto module */
|
||||||
const crypto_sha_context *src)
|
crypto_uninit();
|
||||||
{
|
crypto_zeroize(ctx, sizeof(*ctx));
|
||||||
*dst = *src;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha1_hw_starts(crypto_sha_context *ctx)
|
void mbedtls_sha1_hw_starts(crypto_sha_context *ctx)
|
||||||
{
|
{
|
||||||
// NOTE: mbedtls may call mbedtls_shaXXX_starts multiple times and then call the ending mbedtls_shaXXX_finish. Guard from it.
|
// NOTE: mbedtls may call mbedtls_shaXXX_starts multiple times and then call the ending mbedtls_shaXXX_finish. Guard from it.
|
||||||
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
|
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
|
||||||
|
|
||||||
ctx->total = 0;
|
ctx->total = 0;
|
||||||
ctx->buffer_left = 0;
|
ctx->buffer_left = 0;
|
||||||
ctx->blocksize = 64;
|
ctx->blocksize = 64;
|
||||||
ctx->blocksize_mask = 0x3F;
|
ctx->blocksize_mask = 0x3F;
|
||||||
|
|
||||||
SHA_Open(SHA_MODE_SHA1, SHA_NO_SWAP, 0);
|
SHA_Open(SHA_MODE_SHA1, SHA_NO_SWAP, 0);
|
||||||
|
|
||||||
// Ensure we have correct initial internal states in SHA_DGST registers even though SHA H/W is not actually started.
|
// Ensure we have correct initial internal states in SHA_DGST registers even though SHA H/W is not actually started.
|
||||||
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_START_Msk;
|
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_START_Msk;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,17 +89,16 @@ void mbedtls_sha1_hw_finish(crypto_sha_context *ctx, unsigned char output[20])
|
||||||
crypto_sha_update_nobuf(ctx, ctx->buffer, ctx->buffer_left, 1);
|
crypto_sha_update_nobuf(ctx, ctx->buffer, ctx->buffer_left, 1);
|
||||||
ctx->buffer_left = 0;
|
ctx->buffer_left = 0;
|
||||||
crypto_sha_getinternstate(output, 20);
|
crypto_sha_getinternstate(output, 20);
|
||||||
|
} else {
|
||||||
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mbedtls_sha1_sw_context ctx_sw;
|
mbedtls_sha1_sw_context ctx_sw;
|
||||||
|
|
||||||
mbedtls_sha1_sw_init(&ctx_sw);
|
mbedtls_sha1_sw_init(&ctx_sw);
|
||||||
mbedtls_sha1_sw_starts(&ctx_sw);
|
mbedtls_sha1_sw_starts(&ctx_sw);
|
||||||
mbedtls_sha1_sw_finish(&ctx_sw, output);
|
mbedtls_sha1_sw_finish(&ctx_sw, output);
|
||||||
mbedtls_sha1_sw_free(&ctx_sw);
|
mbedtls_sha1_sw_free(&ctx_sw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha1_hw_process(crypto_sha_context *ctx, const unsigned char data[64])
|
void mbedtls_sha1_hw_process(crypto_sha_context *ctx, const unsigned char data[64])
|
||||||
|
@ -128,8 +114,9 @@ void mbedtls_sha1_hw_process(crypto_sha_context *ctx, const unsigned char data[6
|
||||||
|
|
||||||
void mbedtls_sha256_hw_init(crypto_sha_context *ctx)
|
void mbedtls_sha256_hw_init(crypto_sha_context *ctx)
|
||||||
{
|
{
|
||||||
|
/* Init crypto module */
|
||||||
crypto_init();
|
crypto_init();
|
||||||
memset(ctx, 0, sizeof(crypto_sha_context));
|
memset(ctx, 0, sizeof(*ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha256_hw_free(crypto_sha_context *ctx)
|
void mbedtls_sha256_hw_free(crypto_sha_context *ctx)
|
||||||
|
@ -138,20 +125,18 @@ void mbedtls_sha256_hw_free(crypto_sha_context *ctx)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
crypto_zeroize(ctx, sizeof(crypto_sha_context));
|
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
|
||||||
}
|
|
||||||
|
|
||||||
void mbedtls_sha256_hw_clone(crypto_sha_context *dst,
|
/* Uninit crypto module */
|
||||||
const crypto_sha_context *src)
|
crypto_uninit();
|
||||||
{
|
crypto_zeroize(ctx, sizeof(*ctx));
|
||||||
*dst = *src;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha256_hw_starts( crypto_sha_context *ctx, int is224)
|
void mbedtls_sha256_hw_starts( crypto_sha_context *ctx, int is224)
|
||||||
{
|
{
|
||||||
// NOTE: mbedtls may call mbedtls_shaXXX_starts multiple times and then call the ending mbedtls_shaXXX_finish. Guard from it.
|
// NOTE: mbedtls may call mbedtls_shaXXX_starts multiple times and then call the ending mbedtls_shaXXX_finish. Guard from it.
|
||||||
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
|
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
|
||||||
|
|
||||||
ctx->total = 0;
|
ctx->total = 0;
|
||||||
ctx->buffer_left = 0;
|
ctx->buffer_left = 0;
|
||||||
ctx->blocksize = 64;
|
ctx->blocksize = 64;
|
||||||
|
@ -159,10 +144,10 @@ void mbedtls_sha256_hw_starts( crypto_sha_context *ctx, int is224)
|
||||||
ctx->is224_384 = is224;
|
ctx->is224_384 = is224;
|
||||||
|
|
||||||
SHA_Open(is224 ? SHA_MODE_SHA224 : SHA_MODE_SHA256, SHA_NO_SWAP, 0);
|
SHA_Open(is224 ? SHA_MODE_SHA224 : SHA_MODE_SHA256, SHA_NO_SWAP, 0);
|
||||||
|
|
||||||
// Ensure we have correct initial inernal states in SHA_DGST registers even though SHA H/W is not actually started.
|
// Ensure we have correct initial internal states in SHA_DGST registers even though SHA H/W is not actually started.
|
||||||
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_START_Msk;
|
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_START_Msk;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,17 +163,16 @@ void mbedtls_sha256_hw_finish(crypto_sha_context *ctx, unsigned char output[32])
|
||||||
crypto_sha_update_nobuf(ctx, ctx->buffer, ctx->buffer_left, 1);
|
crypto_sha_update_nobuf(ctx, ctx->buffer, ctx->buffer_left, 1);
|
||||||
ctx->buffer_left = 0;
|
ctx->buffer_left = 0;
|
||||||
crypto_sha_getinternstate(output, ctx->is224_384 ? 28 : 32);
|
crypto_sha_getinternstate(output, ctx->is224_384 ? 28 : 32);
|
||||||
|
} else {
|
||||||
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mbedtls_sha256_sw_context ctx_sw;
|
mbedtls_sha256_sw_context ctx_sw;
|
||||||
|
|
||||||
mbedtls_sha256_sw_init(&ctx_sw);
|
mbedtls_sha256_sw_init(&ctx_sw);
|
||||||
mbedtls_sha256_sw_starts(&ctx_sw, ctx->is224_384);
|
mbedtls_sha256_sw_starts(&ctx_sw, ctx->is224_384);
|
||||||
mbedtls_sha256_sw_finish(&ctx_sw, output);
|
mbedtls_sha256_sw_finish(&ctx_sw, output);
|
||||||
mbedtls_sha256_sw_free(&ctx_sw);
|
mbedtls_sha256_sw_free(&ctx_sw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha256_hw_process(crypto_sha_context *ctx, const unsigned char data[64])
|
void mbedtls_sha256_hw_process(crypto_sha_context *ctx, const unsigned char data[64])
|
||||||
|
@ -205,8 +189,9 @@ void mbedtls_sha256_hw_process(crypto_sha_context *ctx, const unsigned char data
|
||||||
|
|
||||||
void mbedtls_sha512_hw_init(crypto_sha_context *ctx)
|
void mbedtls_sha512_hw_init(crypto_sha_context *ctx)
|
||||||
{
|
{
|
||||||
|
/* Init crypto module */
|
||||||
crypto_init();
|
crypto_init();
|
||||||
memset(ctx, 0, sizeof(crypto_sha_context));
|
memset(ctx, 0, sizeof(*ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha512_hw_free(crypto_sha_context *ctx)
|
void mbedtls_sha512_hw_free(crypto_sha_context *ctx)
|
||||||
|
@ -215,20 +200,18 @@ void mbedtls_sha512_hw_free(crypto_sha_context *ctx)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
crypto_zeroize(ctx, sizeof(crypto_sha_context));
|
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
|
||||||
}
|
|
||||||
|
/* Uninit crypto module */
|
||||||
void mbedtls_sha512_hw_clone(crypto_sha_context *dst,
|
crypto_uninit();
|
||||||
const crypto_sha_context *src)
|
crypto_zeroize(ctx, sizeof(*ctx));
|
||||||
{
|
|
||||||
*dst = *src;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha512_hw_starts( crypto_sha_context *ctx, int is384)
|
void mbedtls_sha512_hw_starts( crypto_sha_context *ctx, int is384)
|
||||||
{
|
{
|
||||||
// NOTE: mbedtls may call mbedtls_shaXXX_starts multiple times and then call the ending mbedtls_shaXXX_finish. Guard from it.
|
// NOTE: mbedtls may call mbedtls_shaXXX_starts multiple times and then call the ending mbedtls_shaXXX_finish. Guard from it.
|
||||||
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
|
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
|
||||||
|
|
||||||
ctx->total = 0;
|
ctx->total = 0;
|
||||||
ctx->buffer_left = 0;
|
ctx->buffer_left = 0;
|
||||||
ctx->blocksize = 128;
|
ctx->blocksize = 128;
|
||||||
|
@ -236,10 +219,10 @@ void mbedtls_sha512_hw_starts( crypto_sha_context *ctx, int is384)
|
||||||
ctx->is224_384 = is384;
|
ctx->is224_384 = is384;
|
||||||
|
|
||||||
SHA_Open(is384 ? SHA_MODE_SHA384 : SHA_MODE_SHA512, SHA_NO_SWAP, 0);
|
SHA_Open(is384 ? SHA_MODE_SHA384 : SHA_MODE_SHA512, SHA_NO_SWAP, 0);
|
||||||
|
|
||||||
// Ensure we have correct initial inernal states in SHA_DGST registers even though SHA H/W is not actually started.
|
// Ensure we have correct initial internal states in SHA_DGST registers even though SHA H/W is not actually started.
|
||||||
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_START_Msk;
|
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_START_Msk;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,17 +238,16 @@ void mbedtls_sha512_hw_finish(crypto_sha_context *ctx, unsigned char output[64])
|
||||||
crypto_sha_update_nobuf(ctx, ctx->buffer, ctx->buffer_left, 1);
|
crypto_sha_update_nobuf(ctx, ctx->buffer, ctx->buffer_left, 1);
|
||||||
ctx->buffer_left = 0;
|
ctx->buffer_left = 0;
|
||||||
crypto_sha_getinternstate(output, ctx->is224_384 ? 48 : 64);
|
crypto_sha_getinternstate(output, ctx->is224_384 ? 48 : 64);
|
||||||
|
} else {
|
||||||
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mbedtls_sha512_sw_context ctx_sw;
|
mbedtls_sha512_sw_context ctx_sw;
|
||||||
|
|
||||||
mbedtls_sha512_sw_init(&ctx_sw);
|
mbedtls_sha512_sw_init(&ctx_sw);
|
||||||
mbedtls_sha512_sw_starts(&ctx_sw, ctx->is224_384);
|
mbedtls_sha512_sw_starts(&ctx_sw, ctx->is224_384);
|
||||||
mbedtls_sha512_sw_finish(&ctx_sw, output);
|
mbedtls_sha512_sw_finish(&ctx_sw, output);
|
||||||
mbedtls_sha512_sw_free(&ctx_sw);
|
mbedtls_sha512_sw_free(&ctx_sw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha512_hw_process(crypto_sha_context *ctx, const unsigned char data[128])
|
void mbedtls_sha512_hw_process(crypto_sha_context *ctx, const unsigned char data[128])
|
||||||
|
@ -284,7 +266,7 @@ void crypto_sha_update(crypto_sha_context *ctx, const unsigned char *input, size
|
||||||
if (ilen == 0) {
|
if (ilen == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t fill = ctx->blocksize - ctx->buffer_left;
|
size_t fill = ctx->blocksize - ctx->buffer_left;
|
||||||
|
|
||||||
ctx->total += (uint32_t) ilen;
|
ctx->total += (uint32_t) ilen;
|
||||||
|
@ -299,7 +281,7 @@ void crypto_sha_update(crypto_sha_context *ctx, const unsigned char *input, size
|
||||||
ctx->buffer_left = 0;
|
ctx->buffer_left = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (ilen > ctx->blocksize) {
|
while (ilen > ctx->blocksize) {
|
||||||
crypto_sha_update_nobuf(ctx, input, ctx->blocksize, 0);
|
crypto_sha_update_nobuf(ctx, input, ctx->blocksize, 0);
|
||||||
input += ctx->blocksize;
|
input += ctx->blocksize;
|
||||||
|
@ -318,17 +300,14 @@ void crypto_sha_update_nobuf(crypto_sha_context *ctx, const unsigned char *input
|
||||||
// 1. Last block which may be incomplete
|
// 1. Last block which may be incomplete
|
||||||
// 2. Non-last block which is complete
|
// 2. Non-last block which is complete
|
||||||
MBED_ASSERT(islast || ilen == ctx->blocksize);
|
MBED_ASSERT(islast || ilen == ctx->blocksize);
|
||||||
|
|
||||||
const unsigned char *in_pos = input;
|
const unsigned char *in_pos = input;
|
||||||
int rmn = ilen;
|
int rmn = ilen;
|
||||||
uint32_t sha_ctl_start = (CRPT->HMAC_CTL & ~(CRPT_HMAC_CTL_DMALAST_Msk | CRPT_HMAC_CTL_DMAEN_Msk | CRPT_HMAC_CTL_HMACEN_Msk)) | CRPT_HMAC_CTL_START_Msk;
|
uint32_t sha_ctl_start = (CRPT->HMAC_CTL & ~(CRPT_HMAC_CTL_DMALAST_Msk | CRPT_HMAC_CTL_DMAEN_Msk | CRPT_HMAC_CTL_HMACEN_Msk)) | CRPT_HMAC_CTL_START_Msk;
|
||||||
uint32_t sha_opmode = (CRPT->HMAC_CTL & CRPT_HMAC_CTL_OPMODE_Msk) >> CRPT_HMAC_CTL_OPMODE_Pos;
|
uint32_t sha_opmode = (CRPT->HMAC_CTL & CRPT_HMAC_CTL_OPMODE_Msk) >> CRPT_HMAC_CTL_OPMODE_Pos;
|
||||||
uint32_t DGST0_old = 0, DGST1_old = 0, DGST2_old = 0, DGST3_old = 0, DGST4_old = 0, DGST5_old = 0, DGST6_old = 0, DGST7_old = 0,
|
uint32_t DGSTs[16] = { 0 };
|
||||||
DGST8_old = 0, DGST9_old = 0, DGST10_old = 0, DGST11_old = 0, DGST12_old = 0, DGST13_old = 0, DGST14_old = 0, DGST15_old = 0;
|
|
||||||
|
|
||||||
while (rmn > 0) {
|
while (rmn > 0) {
|
||||||
CRPT->HMAC_CTL = sha_ctl_start;
|
|
||||||
|
|
||||||
uint32_t data = nu_get32_be(in_pos);
|
uint32_t data = nu_get32_be(in_pos);
|
||||||
if (rmn <= 4) { // Last word of a (in)complete block
|
if (rmn <= 4) { // Last word of a (in)complete block
|
||||||
if (islast) {
|
if (islast) {
|
||||||
|
@ -338,93 +317,112 @@ void crypto_sha_update_nobuf(crypto_sha_context *ctx, const unsigned char *input
|
||||||
}
|
}
|
||||||
CRPT->HMAC_DMACNT = lastblock_size;
|
CRPT->HMAC_DMACNT = lastblock_size;
|
||||||
CRPT->HMAC_CTL = sha_ctl_start | CRPT_HMAC_CTL_DMALAST_Msk;
|
CRPT->HMAC_CTL = sha_ctl_start | CRPT_HMAC_CTL_DMALAST_Msk;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
switch (sha_opmode) {
|
switch (sha_opmode) {
|
||||||
case SHA_MODE_SHA512:
|
case SHA_MODE_SHA512:
|
||||||
DGST15_old = CRPT->HMAC_DGST[15];
|
DGSTs[12] = CRPT->HMAC_DGST[12];
|
||||||
DGST14_old = CRPT->HMAC_DGST[14];
|
DGSTs[13] = CRPT->HMAC_DGST[13];
|
||||||
DGST13_old = CRPT->HMAC_DGST[13];
|
DGSTs[14] = CRPT->HMAC_DGST[14];
|
||||||
DGST12_old = CRPT->HMAC_DGST[12];
|
DGSTs[15] = CRPT->HMAC_DGST[15];
|
||||||
case SHA_MODE_SHA384:
|
case SHA_MODE_SHA384:
|
||||||
DGST11_old = CRPT->HMAC_DGST[11];
|
DGSTs[8] = CRPT->HMAC_DGST[8];
|
||||||
DGST10_old = CRPT->HMAC_DGST[10];
|
DGSTs[9] = CRPT->HMAC_DGST[9];
|
||||||
DGST9_old = CRPT->HMAC_DGST[9];
|
DGSTs[10] = CRPT->HMAC_DGST[10];
|
||||||
DGST8_old = CRPT->HMAC_DGST[8];
|
DGSTs[11] = CRPT->HMAC_DGST[11];
|
||||||
case SHA_MODE_SHA256:
|
case SHA_MODE_SHA256:
|
||||||
DGST7_old = CRPT->HMAC_DGST[7];
|
DGSTs[7] = CRPT->HMAC_DGST[7];
|
||||||
case SHA_MODE_SHA224:
|
case SHA_MODE_SHA224:
|
||||||
DGST5_old = CRPT->HMAC_DGST[5];
|
DGSTs[5] = CRPT->HMAC_DGST[5];
|
||||||
DGST6_old = CRPT->HMAC_DGST[6];
|
DGSTs[6] = CRPT->HMAC_DGST[6];
|
||||||
case SHA_MODE_SHA1:
|
case SHA_MODE_SHA1:
|
||||||
DGST0_old = CRPT->HMAC_DGST[0];
|
DGSTs[0] = CRPT->HMAC_DGST[0];
|
||||||
DGST1_old = CRPT->HMAC_DGST[1];
|
DGSTs[1] = CRPT->HMAC_DGST[1];
|
||||||
DGST2_old = CRPT->HMAC_DGST[2];
|
DGSTs[2] = CRPT->HMAC_DGST[2];
|
||||||
DGST3_old = CRPT->HMAC_DGST[3];
|
DGSTs[3] = CRPT->HMAC_DGST[3];
|
||||||
DGST4_old = CRPT->HMAC_DGST[4];
|
DGSTs[4] = CRPT->HMAC_DGST[4];
|
||||||
}
|
}
|
||||||
|
|
||||||
CRPT->HMAC_CTL = sha_ctl_start;
|
CRPT->HMAC_CTL = sha_ctl_start;
|
||||||
}
|
}
|
||||||
}
|
} else { // Non-last word of a complete block
|
||||||
else { // Non-last word of a complete block
|
|
||||||
CRPT->HMAC_CTL = sha_ctl_start;
|
CRPT->HMAC_CTL = sha_ctl_start;
|
||||||
}
|
}
|
||||||
while (! (CRPT->HMAC_STS & CRPT_HMAC_STS_DATINREQ_Msk));
|
while (! (CRPT->HMAC_STS & CRPT_HMAC_STS_DATINREQ_Msk));
|
||||||
CRPT->HMAC_DATIN = data;
|
CRPT->HMAC_DATIN = data;
|
||||||
|
|
||||||
in_pos += 4;
|
in_pos += 4;
|
||||||
rmn -= 4;
|
rmn -= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (islast) { // Finish of last block
|
if (islast) { // Finish of last block
|
||||||
while (CRPT->HMAC_STS & CRPT_HMAC_STS_BUSY_Msk);
|
while (CRPT->HMAC_STS & CRPT_HMAC_STS_BUSY_Msk);
|
||||||
}
|
} else { // Finish of non-last block
|
||||||
else { // Finish of non-last block
|
/* SHA accelerator doesn't export a flag to indicate non-last block process has finished.
|
||||||
// No H/W flag to indicate finish of non-last block process.
|
* Per designer, if the digest (SHA_DGSTx) code changes after the last word of the block is input,
|
||||||
// Values of SHA_DGSTx registers will change as last word of the block is input, so use it for judgement.
|
* this indicates the non-last block process has finished.
|
||||||
|
*
|
||||||
|
* There is a rare case that two digest codes are the same for
|
||||||
|
* two non-last block processes in a row.
|
||||||
|
* To address it, we use a count-down timer to detect it.
|
||||||
|
* As the count-down timer expires, we see it as finished.
|
||||||
|
*/
|
||||||
int isfinish = 0;
|
int isfinish = 0;
|
||||||
|
struct nu_countdown_ctx_s ctx;
|
||||||
|
|
||||||
|
// Set up 2s timeout
|
||||||
|
nu_countdown_init(&ctx, 2000*1000);
|
||||||
while (! isfinish) {
|
while (! isfinish) {
|
||||||
switch (sha_opmode) {
|
switch (sha_opmode) {
|
||||||
case SHA_MODE_SHA512:
|
case SHA_MODE_SHA512:
|
||||||
if (DGST12_old != CRPT->HMAC_DGST[12] || DGST13_old != CRPT->HMAC_DGST[13] || DGST14_old != CRPT->HMAC_DGST[14] ||
|
if (DGSTs[12] != CRPT->HMAC_DGST[12] || DGSTs[13] != CRPT->HMAC_DGST[13] || DGSTs[14] != CRPT->HMAC_DGST[14] ||
|
||||||
DGST15_old != CRPT->HMAC_DGST[15]) {
|
DGSTs[15] != CRPT->HMAC_DGST[15]) {
|
||||||
isfinish = 1;
|
isfinish = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SHA_MODE_SHA384:
|
case SHA_MODE_SHA384:
|
||||||
if (DGST8_old != CRPT->HMAC_DGST[8] || DGST9_old != CRPT->HMAC_DGST[9] || DGST10_old != CRPT->HMAC_DGST[10] ||
|
if (DGSTs[8] != CRPT->HMAC_DGST[8] || DGSTs[9] != CRPT->HMAC_DGST[9] || DGSTs[10] != CRPT->HMAC_DGST[10] ||
|
||||||
DGST11_old != CRPT->HMAC_DGST[11]) {
|
DGSTs[11] != CRPT->HMAC_DGST[11]) {
|
||||||
isfinish = 1;
|
isfinish = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SHA_MODE_SHA256:
|
case SHA_MODE_SHA256:
|
||||||
if (DGST7_old != CRPT->HMAC_DGST[7]) {
|
if (DGSTs[7] != CRPT->HMAC_DGST[7]) {
|
||||||
isfinish = 1;
|
isfinish = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SHA_MODE_SHA224:
|
case SHA_MODE_SHA224:
|
||||||
if (DGST5_old != CRPT->HMAC_DGST[5] || DGST6_old != CRPT->HMAC_DGST[6]) {
|
if (DGSTs[5] != CRPT->HMAC_DGST[5] || DGSTs[6] != CRPT->HMAC_DGST[6]) {
|
||||||
isfinish = 1;
|
isfinish = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SHA_MODE_SHA1:
|
case SHA_MODE_SHA1:
|
||||||
if (DGST0_old != CRPT->HMAC_DGST[0] || DGST1_old != CRPT->HMAC_DGST[1] || DGST2_old != CRPT->HMAC_DGST[2] ||
|
if (DGSTs[0] != CRPT->HMAC_DGST[0] || DGSTs[1] != CRPT->HMAC_DGST[1] || DGSTs[2] != CRPT->HMAC_DGST[2] ||
|
||||||
DGST3_old != CRPT->HMAC_DGST[3] || DGST4_old != CRPT->HMAC_DGST[4]) {
|
DGSTs[3] != CRPT->HMAC_DGST[3] || DGSTs[4] != CRPT->HMAC_DGST[4]) {
|
||||||
isfinish = 1;
|
isfinish = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nu_countdown_expired(&ctx)) {
|
||||||
|
// We may meet a rare case that the current digest code and the previous one are the same.
|
||||||
|
isfinish = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Must pair nu_countdown_init with nu_countdown_free in the end
|
||||||
|
nu_countdown_free(&ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void crypto_sha_getinternstate(unsigned char output[], size_t olen)
|
void crypto_sha_getinternstate(unsigned char output[], size_t olen)
|
||||||
{
|
{
|
||||||
|
if (olen & 0x3) {
|
||||||
|
error("Internal error in SHA alter. SHA internal state size requires to be a multiple of 4 bytes.");
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t *in_pos = (uint32_t *) &CRPT->HMAC_DGST[0];
|
uint32_t *in_pos = (uint32_t *) &CRPT->HMAC_DGST[0];
|
||||||
unsigned char *out_pos = output;
|
unsigned char *out_pos = output;
|
||||||
uint32_t rmn = olen;
|
uint32_t rmn = olen;
|
||||||
|
|
||||||
while (rmn) {
|
while (rmn) {
|
||||||
uint32_t val = *in_pos ++;
|
uint32_t val = *in_pos ++;
|
||||||
nu_set32_be(out_pos, val);
|
nu_set32_be(out_pos, val);
|
||||||
|
|
|
@ -16,13 +16,6 @@
|
||||||
#ifndef MBEDTLS_SHA_ALT_HW_H
|
#ifndef MBEDTLS_SHA_ALT_HW_H
|
||||||
#define MBEDTLS_SHA_ALT_HW_H
|
#define MBEDTLS_SHA_ALT_HW_H
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
|
||||||
#include "config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA1_C) || defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C)
|
|
||||||
#if defined(MBEDTLS_SHA1_ALT) || defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA512_ALT)
|
#if defined(MBEDTLS_SHA1_ALT) || defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA512_ALT)
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
@ -35,14 +28,13 @@ extern "C" {
|
||||||
/**
|
/**
|
||||||
* \brief SHA context structure
|
* \brief SHA context structure
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
uint32_t total; /*!< number of bytes processed */
|
uint32_t total; /*!< number of bytes processed */
|
||||||
unsigned char buffer[128]; /*!< data block being processed. Max of SHA-1/SHA-256/SHA-512 */
|
uint8_t buffer[128]; /*!< data block being processed. Max of SHA-1/SHA-256/SHA-512 */
|
||||||
uint16_t buffer_left;
|
uint16_t buffer_left;
|
||||||
uint16_t blocksize; /*!< block size */
|
uint16_t blocksize; /*!< block size */
|
||||||
uint32_t blocksize_mask; /*!< block size mask */
|
uint32_t blocksize_mask; /*!< block size mask */
|
||||||
|
|
||||||
int is224_384; /*!< 0 => SHA-256/SHA-512, else SHA-224/384 */
|
int is224_384; /*!< 0 => SHA-256/SHA-512, else SHA-224/384 */
|
||||||
}
|
}
|
||||||
crypto_sha_context;
|
crypto_sha_context;
|
||||||
|
@ -51,58 +43,45 @@ void crypto_sha_update(crypto_sha_context *ctx, const unsigned char *input, size
|
||||||
void crypto_sha_update_nobuf(crypto_sha_context *ctx, const unsigned char *input, size_t ilen, int islast);
|
void crypto_sha_update_nobuf(crypto_sha_context *ctx, const unsigned char *input, size_t ilen, int islast);
|
||||||
void crypto_sha_getinternstate(unsigned char output[], size_t olen);
|
void crypto_sha_getinternstate(unsigned char output[], size_t olen);
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA1_C)
|
|
||||||
#if defined(MBEDTLS_SHA1_ALT)
|
#if defined(MBEDTLS_SHA1_ALT)
|
||||||
|
|
||||||
void mbedtls_sha1_hw_init( crypto_sha_context *ctx );
|
void mbedtls_sha1_hw_init( crypto_sha_context *ctx );
|
||||||
void mbedtls_sha1_hw_free( crypto_sha_context *ctx );
|
void mbedtls_sha1_hw_free( crypto_sha_context *ctx );
|
||||||
void mbedtls_sha1_hw_clone( crypto_sha_context *dst,
|
|
||||||
const crypto_sha_context *src );
|
|
||||||
void mbedtls_sha1_hw_starts( crypto_sha_context *ctx );
|
void mbedtls_sha1_hw_starts( crypto_sha_context *ctx );
|
||||||
void mbedtls_sha1_hw_update( crypto_sha_context *ctx, const unsigned char *input, size_t ilen );
|
void mbedtls_sha1_hw_update( crypto_sha_context *ctx, const unsigned char *input, size_t ilen );
|
||||||
void mbedtls_sha1_hw_finish( crypto_sha_context *ctx, unsigned char output[20] );
|
void mbedtls_sha1_hw_finish( crypto_sha_context *ctx, unsigned char output[20] );
|
||||||
void mbedtls_sha1_hw_process( crypto_sha_context *ctx, const unsigned char data[64] );
|
void mbedtls_sha1_hw_process( crypto_sha_context *ctx, const unsigned char data[64] );
|
||||||
|
|
||||||
#endif /* MBEDTLS_SHA1_ALT */
|
#endif /* MBEDTLS_SHA1_ALT */
|
||||||
#endif /* MBEDTLS_SHA1_C */
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA256_C)
|
|
||||||
#if defined(MBEDTLS_SHA256_ALT)
|
#if defined(MBEDTLS_SHA256_ALT)
|
||||||
|
|
||||||
void mbedtls_sha256_hw_init( crypto_sha_context *ctx );
|
void mbedtls_sha256_hw_init( crypto_sha_context *ctx );
|
||||||
void mbedtls_sha256_hw_free( crypto_sha_context *ctx );
|
void mbedtls_sha256_hw_free( crypto_sha_context *ctx );
|
||||||
void mbedtls_sha256_hw_clone( crypto_sha_context *dst,
|
|
||||||
const crypto_sha_context *src );
|
|
||||||
void mbedtls_sha256_hw_starts( crypto_sha_context *ctx, int is224 );
|
void mbedtls_sha256_hw_starts( crypto_sha_context *ctx, int is224 );
|
||||||
void mbedtls_sha256_hw_update( crypto_sha_context *ctx, const unsigned char *input,
|
void mbedtls_sha256_hw_update( crypto_sha_context *ctx, const unsigned char *input,
|
||||||
size_t ilen );
|
size_t ilen );
|
||||||
void mbedtls_sha256_hw_finish( crypto_sha_context *ctx, unsigned char output[32] );
|
void mbedtls_sha256_hw_finish( crypto_sha_context *ctx, unsigned char output[32] );
|
||||||
void mbedtls_sha256_hw_process( crypto_sha_context *ctx, const unsigned char data[64] );
|
void mbedtls_sha256_hw_process( crypto_sha_context *ctx, const unsigned char data[64] );
|
||||||
|
|
||||||
#endif /* MBEDTLS_SHA256_ALT */
|
#endif /* MBEDTLS_SHA256_ALT */
|
||||||
#endif /* MBEDTLS_SHA256_C */
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA512_C)
|
|
||||||
#if defined(MBEDTLS_SHA512_ALT)
|
#if defined(MBEDTLS_SHA512_ALT)
|
||||||
|
|
||||||
void mbedtls_sha512_hw_init( crypto_sha_context *ctx );
|
void mbedtls_sha512_hw_init( crypto_sha_context *ctx );
|
||||||
void mbedtls_sha512_hw_free( crypto_sha_context *ctx );
|
void mbedtls_sha512_hw_free( crypto_sha_context *ctx );
|
||||||
void mbedtls_sha512_hw_clone( crypto_sha_context *dst,
|
|
||||||
const crypto_sha_context *src );
|
|
||||||
void mbedtls_sha512_hw_starts( crypto_sha_context *ctx, int is384 );
|
void mbedtls_sha512_hw_starts( crypto_sha_context *ctx, int is384 );
|
||||||
void mbedtls_sha512_hw_update( crypto_sha_context *ctx, const unsigned char *input,
|
void mbedtls_sha512_hw_update( crypto_sha_context *ctx, const unsigned char *input,
|
||||||
size_t ilen );
|
size_t ilen );
|
||||||
void mbedtls_sha512_hw_finish( crypto_sha_context *ctx, unsigned char output[64] );
|
void mbedtls_sha512_hw_finish( crypto_sha_context *ctx, unsigned char output[64] );
|
||||||
void mbedtls_sha512_hw_process( crypto_sha_context *ctx, const unsigned char data[128] );
|
void mbedtls_sha512_hw_process( crypto_sha_context *ctx, const unsigned char data[128] );
|
||||||
|
|
||||||
#endif /* MBEDTLS_SHA512_ALT */
|
#endif /* MBEDTLS_SHA512_ALT */
|
||||||
#endif /* MBEDTLS_SHA512_C */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* MBEDTLS_SHA1_ALT || MBEDTLS_SHA256_ALT || MBEDTLS_SHA512_ALT */
|
#endif /* MBEDTLS_SHA1_ALT || MBEDTLS_SHA256_ALT || MBEDTLS_SHA512_ALT */
|
||||||
#endif /* MBEDTLS_SHA1_C || MBEDTLS_SHA256_C || MBEDTLS_SHA512_C*/
|
|
||||||
|
|
||||||
#endif /* sha_alt.h */
|
#endif /* sha_alt.h */
|
||||||
|
|
|
@ -22,9 +22,5 @@
|
||||||
#define MBEDTLS_SHA256_ALT
|
#define MBEDTLS_SHA256_ALT
|
||||||
|
|
||||||
#define MBEDTLS_AES_ALT
|
#define MBEDTLS_AES_ALT
|
||||||
#define MBEDTLS_AES_SETKEY_ENC_ALT
|
|
||||||
#define MBEDTLS_AES_SETKEY_DEC_ALT
|
|
||||||
#define MBEDTLS_AES_ENCRYPT_ALT
|
|
||||||
#define MBEDTLS_AES_DECRYPT_ALT
|
|
||||||
|
|
||||||
#endif /* MBEDTLS_DEVICE_H */
|
#endif /* MBEDTLS_DEVICE_H */
|
||||||
|
|
|
@ -21,304 +21,229 @@
|
||||||
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/aes.h"
|
||||||
#include "mbedtls/config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_AES_C)
|
#if defined(MBEDTLS_AES_C)
|
||||||
#if defined(MBEDTLS_AES_ALT)
|
#if defined(MBEDTLS_AES_ALT)
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include "mbedtls/aes.h"
|
|
||||||
|
|
||||||
#include "NUC472_442.h"
|
#include "NUC472_442.h"
|
||||||
#include "mbed_toolchain.h"
|
#include "mbed_toolchain.h"
|
||||||
#include "mbed_assert.h"
|
#include "mbed_assert.h"
|
||||||
|
#include "mbed_error.h"
|
||||||
//static int aes_init_done = 0;
|
#include "nu_bitutil.h"
|
||||||
|
#include "crypto-misc.h"
|
||||||
|
|
||||||
#define mbedtls_trace(...) //printf(__VA_ARGS__)
|
|
||||||
|
|
||||||
/* Implementation that should never be optimized out by the compiler */
|
/* Implementation that should never be optimized out by the compiler */
|
||||||
static void mbedtls_zeroize( void *v, size_t n ) {
|
static void mbedtls_zeroize( void *v, size_t n )
|
||||||
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
|
{
|
||||||
|
volatile unsigned char *p = (unsigned char*)v;
|
||||||
|
while( n-- ) *p++ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* AES DMA compatible backup buffer if user buffer doesn't meet requirements
|
||||||
static uint32_t au32MyAESIV[4] = {
|
*
|
||||||
0x00000000, 0x00000000, 0x00000000, 0x00000000
|
* AES DMA buffer location requires to be:
|
||||||
};
|
* (1) Word-aligned
|
||||||
|
* (2) Located in 0x2xxxxxxx region. Check linker files to ensure global variables are placed in this region.
|
||||||
extern volatile int g_AES_done;
|
*
|
||||||
|
* AES DMA buffer size MAX_DMA_CHAIN_SIZE must be a multiple of 16-byte block size.
|
||||||
// Must be a multiple of 16 bytes block size
|
* Its value is estimated to trade memory footprint off against performance.
|
||||||
|
*
|
||||||
|
*/
|
||||||
#define MAX_DMA_CHAIN_SIZE (16*6)
|
#define MAX_DMA_CHAIN_SIZE (16*6)
|
||||||
static uint8_t au8OutputData[MAX_DMA_CHAIN_SIZE] MBED_ALIGN(4);
|
MBED_ALIGN(4) static uint8_t au8OutputData[MAX_DMA_CHAIN_SIZE];
|
||||||
static uint8_t au8InputData[MAX_DMA_CHAIN_SIZE] MBED_ALIGN(4);
|
MBED_ALIGN(4) static uint8_t au8InputData[MAX_DMA_CHAIN_SIZE];
|
||||||
|
|
||||||
static void dumpHex(const unsigned char au8Data[], int len)
|
|
||||||
{
|
|
||||||
int j;
|
|
||||||
for (j = 0; j < len; j++) mbedtls_trace("%02x ", au8Data[j]);
|
|
||||||
mbedtls_trace("\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void swapInitVector(unsigned char iv[16])
|
|
||||||
{
|
|
||||||
unsigned int* piv;
|
|
||||||
int i;
|
|
||||||
// iv SWAP
|
|
||||||
piv = (unsigned int*)iv;
|
|
||||||
for( i=0; i< 4; i++)
|
|
||||||
{
|
|
||||||
*piv = (((*piv) & 0x000000FF) << 24) |
|
|
||||||
(((*piv) & 0x0000FF00) << 8) |
|
|
||||||
(((*piv) & 0x00FF0000) >> 8) |
|
|
||||||
(((*piv) & 0xFF000000) >> 24);
|
|
||||||
piv++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//volatile void CRYPTO_IRQHandler()
|
|
||||||
//{
|
|
||||||
// if (AES_GET_INT_FLAG()) {
|
|
||||||
// g_AES_done = 1;
|
|
||||||
// AES_CLR_INT_FLAG();
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
// AES available channel 0~3
|
|
||||||
static unsigned char channel_flag[4]={0x00,0x00,0x00,0x00}; // 0: idle, 1: busy
|
|
||||||
static int channel_alloc()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for(i=0; i< (int)sizeof(channel_flag); i++)
|
|
||||||
{
|
|
||||||
if( channel_flag[i] == 0x00 )
|
|
||||||
{
|
|
||||||
channel_flag[i] = 0x01;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void channel_free(int i)
|
|
||||||
{
|
|
||||||
if( i >=0 && i < (int)sizeof(channel_flag) )
|
|
||||||
channel_flag[i] = 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void mbedtls_aes_init( mbedtls_aes_context *ctx )
|
void mbedtls_aes_init( mbedtls_aes_context *ctx )
|
||||||
{
|
{
|
||||||
int i =-1;
|
|
||||||
|
|
||||||
// sw_mbedtls_aes_init(ctx);
|
|
||||||
// return;
|
|
||||||
|
|
||||||
mbedtls_trace("=== %s \r\n", __FUNCTION__);
|
|
||||||
memset( ctx, 0, sizeof( mbedtls_aes_context ) );
|
memset( ctx, 0, sizeof( mbedtls_aes_context ) );
|
||||||
|
|
||||||
ctx->swapType = AES_IN_OUT_SWAP;
|
|
||||||
while( (i = channel_alloc()) < 0 )
|
|
||||||
{
|
|
||||||
mbed_assert_internal("No available AES channel", __FILE__, __LINE__);
|
|
||||||
//osDelay(300);
|
|
||||||
}
|
|
||||||
ctx->channel = i;
|
|
||||||
ctx->iv = au32MyAESIV;
|
|
||||||
|
|
||||||
/* Unlock protected registers */
|
|
||||||
SYS_UnlockReg();
|
|
||||||
CLK_EnableModuleClock(CRPT_MODULE);
|
|
||||||
/* Lock protected registers */
|
|
||||||
SYS_LockReg();
|
|
||||||
|
|
||||||
NVIC_EnableIRQ(CRPT_IRQn);
|
|
||||||
AES_ENABLE_INT();
|
|
||||||
mbedtls_trace("=== %s channel[%d]\r\n", __FUNCTION__, (int)ctx->channel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_aes_free( mbedtls_aes_context *ctx )
|
void mbedtls_aes_free( mbedtls_aes_context *ctx )
|
||||||
{
|
{
|
||||||
|
|
||||||
mbedtls_trace("=== %s channel[%d]\r\n", __FUNCTION__,(int)ctx->channel);
|
|
||||||
|
|
||||||
if( ctx == NULL )
|
if( ctx == NULL )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Unlock protected registers */
|
|
||||||
// SYS_UnlockReg();
|
|
||||||
// CLK_DisableModuleClock(CRPT_MODULE);
|
|
||||||
/* Lock protected registers */
|
|
||||||
// SYS_LockReg();
|
|
||||||
|
|
||||||
// NVIC_DisableIRQ(CRPT_IRQn);
|
|
||||||
// AES_DISABLE_INT();
|
|
||||||
channel_free(ctx->channel);
|
|
||||||
mbedtls_zeroize( ctx, sizeof( mbedtls_aes_context ) );
|
mbedtls_zeroize( ctx, sizeof( mbedtls_aes_context ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AES key schedule (encryption)
|
* AES key schedule (encryption)
|
||||||
*/
|
*/
|
||||||
#if defined(MBEDTLS_AES_SETKEY_ENC_ALT)
|
|
||||||
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
|
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
|
||||||
unsigned int keybits )
|
unsigned int keybits )
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
mbedtls_trace("=== %s keybits[%d]\r\n", __FUNCTION__, keybits);
|
|
||||||
dumpHex(key,keybits/8);
|
|
||||||
|
|
||||||
switch( keybits )
|
switch( keybits ) {
|
||||||
{
|
case 128:
|
||||||
case 128:
|
ctx->keySize = AES_KEY_SIZE_128;
|
||||||
ctx->keySize = AES_KEY_SIZE_128;
|
break;
|
||||||
break;
|
case 192:
|
||||||
case 192:
|
ctx->keySize = AES_KEY_SIZE_192;
|
||||||
ctx->keySize = AES_KEY_SIZE_192;
|
break;
|
||||||
break;
|
case 256:
|
||||||
case 256:
|
ctx->keySize = AES_KEY_SIZE_256;
|
||||||
ctx->keySize = AES_KEY_SIZE_256;
|
break;
|
||||||
break;
|
default :
|
||||||
default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
|
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fetch key byte data in big-endian */
|
||||||
|
for( i = 0; i < ( keybits >> 5 ); i++ ) {
|
||||||
// key swap
|
ctx->keys[i] = nu_get32_be(key + i * 4);
|
||||||
for( i = 0; i < ( keybits >> 5 ); i++ )
|
}
|
||||||
{
|
|
||||||
ctx->buf[i] = (*(key+i*4) << 24) |
|
|
||||||
(*(key+1+i*4) << 16) |
|
|
||||||
(*(key+2+i*4) << 8) |
|
|
||||||
(*(key+3+i*4) );
|
|
||||||
}
|
|
||||||
AES_SetKey(ctx->channel, ctx->buf, ctx->keySize);
|
|
||||||
|
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
#endif /* MBEDTLS_AES_SETKEY_ENC_ALT */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AES key schedule (decryption)
|
* AES key schedule (decryption)
|
||||||
*/
|
*/
|
||||||
#if defined(MBEDTLS_AES_SETKEY_DEC_ALT)
|
|
||||||
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
|
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
|
||||||
unsigned int keybits )
|
unsigned int keybits )
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
mbedtls_trace("=== %s keybits[%d]\r\n", __FUNCTION__, keybits);
|
|
||||||
dumpHex((uint8_t *)key,keybits/8);
|
|
||||||
|
|
||||||
/* Also checks keybits */
|
/* Also checks keybits */
|
||||||
if( ( ret = mbedtls_aes_setkey_enc( ctx, key, keybits ) ) != 0 )
|
if( ( ret = mbedtls_aes_setkey_enc( ctx, key, keybits ) ) != 0 )
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
|
||||||
return( ret );
|
return( ret );
|
||||||
}
|
}
|
||||||
#endif /* MBEDTLS_AES_SETKEY_DEC_ALT */
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Do AES encrypt/decrypt with H/W accelerator
|
||||||
|
*
|
||||||
|
* NOTE: As input/output buffer doesn't follow constraint of DMA buffer, static allocated
|
||||||
|
* DMA compatible buffer is used for DMA instead and this needs extra copy.
|
||||||
|
*
|
||||||
|
* NOTE: dataSize requires to be:
|
||||||
|
* 1) Multiple of block size 16
|
||||||
|
* 2) <= MAX_DMA_CHAIN_SIZE
|
||||||
|
*/
|
||||||
static void __nvt_aes_crypt( mbedtls_aes_context *ctx,
|
static void __nvt_aes_crypt( mbedtls_aes_context *ctx,
|
||||||
const unsigned char input[16],
|
const unsigned char *input,
|
||||||
unsigned char output[16], int dataSize)
|
unsigned char *output, size_t dataSize)
|
||||||
{
|
{
|
||||||
unsigned char* pIn;
|
const unsigned char* pIn;
|
||||||
unsigned char* pOut;
|
unsigned char* pOut;
|
||||||
|
|
||||||
// mbedtls_trace("=== %s \r\n", __FUNCTION__);
|
MBED_ASSERT((dataSize % 16 == 0) && (dataSize <= MAX_DMA_CHAIN_SIZE));
|
||||||
dumpHex(input,16);
|
|
||||||
|
/* AES DMA buffer has the following requirements:
|
||||||
AES_Open(ctx->channel, ctx->encDec, ctx->opMode, ctx->keySize, ctx->swapType);
|
* (1) Word-aligned buffer base address
|
||||||
AES_SetInitVect(ctx->channel, ctx->iv);
|
* (2) 16-byte aligned buffer size
|
||||||
if( ((uint32_t)input) & 0x03 )
|
* (3) Located in 0x20000000-0x2FFFFFFF region
|
||||||
{
|
*/
|
||||||
memcpy(au8InputData, input, dataSize);
|
if ((! crypto_dma_buff_compat(au8OutputData, MAX_DMA_CHAIN_SIZE, 16)) ||
|
||||||
pIn = au8InputData;
|
(! crypto_dma_buff_compat(au8InputData, MAX_DMA_CHAIN_SIZE, 16))) {
|
||||||
}else{
|
error("Buffer for AES alter. DMA requires to be word-aligned and located in 0x20000000-0x2FFFFFFF region.");
|
||||||
pIn = (unsigned char*)input;
|
|
||||||
}
|
}
|
||||||
if( (((uint32_t)output) & 0x03) || (dataSize%4)) // HW CFB output byte count must be multiple of word
|
|
||||||
{
|
|
||||||
pOut = au8OutputData;
|
|
||||||
} else {
|
|
||||||
pOut = output;
|
|
||||||
}
|
|
||||||
|
|
||||||
AES_SetDMATransfer(ctx->channel, (uint32_t)pIn, (uint32_t)pOut, dataSize);
|
/* TODO: Change busy-wait to other means to release CPU */
|
||||||
|
/* Acquire ownership of AES H/W */
|
||||||
|
while (! crypto_aes_acquire());
|
||||||
|
|
||||||
|
/* Init crypto module */
|
||||||
|
crypto_init();
|
||||||
|
/* Enable AES interrupt */
|
||||||
|
AES_ENABLE_INT();
|
||||||
|
|
||||||
|
/* We support multiple contexts with context save & restore and so needs just one
|
||||||
|
* H/W channel. Always use H/W channel #0. */
|
||||||
|
|
||||||
g_AES_done = 0;
|
/* AES_IN_OUT_SWAP: Let H/W know both input/output data are arranged in little-endian */
|
||||||
AES_Start(ctx->channel, CRYPTO_DMA_ONE_SHOT);
|
AES_Open(0, ctx->encDec, ctx->opMode, ctx->keySize, AES_IN_OUT_SWAP);
|
||||||
while (!g_AES_done);
|
AES_SetInitVect(0, ctx->iv);
|
||||||
|
AES_SetKey(0, ctx->keys, ctx->keySize);
|
||||||
|
|
||||||
|
/* AES DMA buffer requirements same as above */
|
||||||
|
if (! crypto_dma_buff_compat(input, dataSize, 16)) {
|
||||||
|
memcpy(au8InputData, input, dataSize);
|
||||||
|
pIn = au8InputData;
|
||||||
|
} else {
|
||||||
|
pIn = input;
|
||||||
|
}
|
||||||
|
/* AES DMA buffer requirements same as above */
|
||||||
|
if (! crypto_dma_buff_compat(output, dataSize, 16)) {
|
||||||
|
pOut = au8OutputData;
|
||||||
|
} else {
|
||||||
|
pOut = output;
|
||||||
|
}
|
||||||
|
|
||||||
if( pOut != output ) memcpy(output, au8OutputData, dataSize);
|
/* Even though AES H/W has limited support for overlapped DMA input/output buffers,
|
||||||
dumpHex(output,16);
|
* we still seek to one backup buffer to make them non-overlapped for simplicity. */
|
||||||
|
if (crypto_dma_buffs_overlap(pIn, dataSize, pOut, dataSize)) {
|
||||||
|
memcpy(au8InputData, input, dataSize);
|
||||||
|
pIn = au8InputData;
|
||||||
|
}
|
||||||
|
MBED_ASSERT(! crypto_dma_buffs_overlap(pIn, dataSize, pOut, dataSize));
|
||||||
|
|
||||||
|
AES_SetDMATransfer(0, (uint32_t)pIn, (uint32_t)pOut, dataSize);
|
||||||
|
|
||||||
|
crypto_aes_prestart();
|
||||||
|
AES_Start(0, CRYPTO_DMA_ONE_SHOT);
|
||||||
|
crypto_aes_wait();
|
||||||
|
|
||||||
|
if( pOut != output ) {
|
||||||
|
memcpy(output, au8OutputData, dataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save IV for next block */
|
||||||
|
ctx->iv[0] = CRPT->AES_FDBCK0;
|
||||||
|
ctx->iv[1] = CRPT->AES_FDBCK1;
|
||||||
|
ctx->iv[2] = CRPT->AES_FDBCK2;
|
||||||
|
ctx->iv[3] = CRPT->AES_FDBCK3;
|
||||||
|
|
||||||
|
/* Disable AES interrupt */
|
||||||
|
AES_DISABLE_INT();
|
||||||
|
/* Uninit crypto module */
|
||||||
|
crypto_uninit();
|
||||||
|
|
||||||
|
/* Release ownership of AES H/W */
|
||||||
|
crypto_aes_release();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AES-ECB block encryption
|
* AES-ECB block encryption
|
||||||
*/
|
*/
|
||||||
#if defined(MBEDTLS_AES_ENCRYPT_ALT)
|
|
||||||
void mbedtls_aes_encrypt( mbedtls_aes_context *ctx,
|
void mbedtls_aes_encrypt( mbedtls_aes_context *ctx,
|
||||||
const unsigned char input[16],
|
const unsigned char input[16],
|
||||||
unsigned char output[16] )
|
unsigned char output[16] )
|
||||||
{
|
{
|
||||||
|
ctx->encDec = 1;
|
||||||
mbedtls_trace("=== %s \r\n", __FUNCTION__);
|
__nvt_aes_crypt(ctx, input, output, 16);
|
||||||
|
|
||||||
ctx->encDec = 1;
|
|
||||||
__nvt_aes_crypt(ctx, input, output, 16);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif /* MBEDTLS_AES_ENCRYPT_ALT */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AES-ECB block decryption
|
* AES-ECB block decryption
|
||||||
*/
|
*/
|
||||||
#if defined(MBEDTLS_AES_DECRYPT_ALT)
|
|
||||||
void mbedtls_aes_decrypt( mbedtls_aes_context *ctx,
|
void mbedtls_aes_decrypt( mbedtls_aes_context *ctx,
|
||||||
const unsigned char input[16],
|
const unsigned char input[16],
|
||||||
unsigned char output[16] )
|
unsigned char output[16] )
|
||||||
{
|
{
|
||||||
|
ctx->encDec = 0;
|
||||||
mbedtls_trace("=== %s \r\n", __FUNCTION__);
|
__nvt_aes_crypt(ctx, input, output, 16);
|
||||||
|
|
||||||
ctx->encDec = 0;
|
|
||||||
__nvt_aes_crypt(ctx, input, output, 16);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif /* MBEDTLS_AES_DECRYPT_ALT */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AES-ECB block encryption/decryption
|
* AES-ECB block encryption/decryption
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
|
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
const unsigned char input[16],
|
const unsigned char input[16],
|
||||||
unsigned char output[16] )
|
unsigned char output[16] )
|
||||||
{
|
{
|
||||||
|
ctx->opMode = AES_MODE_ECB;
|
||||||
mbedtls_trace("=== %s \r\n", __FUNCTION__);
|
|
||||||
|
|
||||||
ctx->opMode = AES_MODE_ECB;
|
|
||||||
if( mode == MBEDTLS_AES_ENCRYPT )
|
if( mode == MBEDTLS_AES_ENCRYPT )
|
||||||
mbedtls_aes_encrypt( ctx, input, output );
|
mbedtls_aes_encrypt( ctx, input, output );
|
||||||
else
|
else
|
||||||
mbedtls_aes_decrypt( ctx, input, output );
|
mbedtls_aes_decrypt( ctx, input, output );
|
||||||
|
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
@ -328,108 +253,135 @@ int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
|
||||||
* AES-CBC buffer encryption/decryption
|
* AES-CBC buffer encryption/decryption
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
|
int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
size_t len,
|
size_t len,
|
||||||
unsigned char iv[16],
|
unsigned char iv[16],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output )
|
unsigned char *output )
|
||||||
{
|
{
|
||||||
unsigned char temp[16];
|
|
||||||
int length = len;
|
int length = len;
|
||||||
int blockChainLen;
|
int blockChainLen;
|
||||||
mbedtls_trace("=== %s [0x%x]\r\n", __FUNCTION__,length);
|
|
||||||
if( length % 16 )
|
if( length % 16 )
|
||||||
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
|
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
|
||||||
|
|
||||||
if( (((uint32_t)input) & 0x03) || (((uint32_t)output) & 0x03) )
|
|
||||||
{
|
|
||||||
blockChainLen = (( length > MAX_DMA_CHAIN_SIZE ) ? MAX_DMA_CHAIN_SIZE : length );
|
|
||||||
} else {
|
|
||||||
blockChainLen = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
while( length > 0 )
|
|
||||||
{
|
|
||||||
ctx->opMode = AES_MODE_CBC;
|
|
||||||
swapInitVector(iv); // iv SWAP
|
|
||||||
ctx->iv = (uint32_t *)iv;
|
|
||||||
|
|
||||||
if( mode == MBEDTLS_AES_ENCRYPT )
|
ctx->opMode = AES_MODE_CBC;
|
||||||
{
|
/* Fetch IV byte data in big-endian */
|
||||||
ctx->encDec = 1;
|
ctx->iv[0] = nu_get32_be(iv);
|
||||||
__nvt_aes_crypt(ctx, input, output, blockChainLen);
|
ctx->iv[1] = nu_get32_be(iv + 4);
|
||||||
// if( blockChainLen == length ) break; // finish last block chain but still need to prepare next iv for mbedtls_aes_self_test()
|
ctx->iv[2] = nu_get32_be(iv + 8);
|
||||||
memcpy( iv, output+blockChainLen-16, 16 );
|
ctx->iv[3] = nu_get32_be(iv + 12);
|
||||||
}else{
|
|
||||||
memcpy( temp, input+blockChainLen-16, 16 );
|
if( mode == MBEDTLS_AES_ENCRYPT ) {
|
||||||
ctx->encDec = 0;
|
ctx->encDec = 1;
|
||||||
__nvt_aes_crypt(ctx, input, output, blockChainLen);
|
}
|
||||||
// if( blockChainLen == length ) break; // finish last block chain but still need to prepare next iv for mbedtls_aes_self_test()
|
else {
|
||||||
memcpy( iv, temp, 16 );
|
ctx->encDec = 0;
|
||||||
}
|
}
|
||||||
length -= blockChainLen;
|
|
||||||
input += blockChainLen;
|
while( length > 0 ) {
|
||||||
output += blockChainLen;
|
blockChainLen = (length > MAX_DMA_CHAIN_SIZE) ? MAX_DMA_CHAIN_SIZE : length;
|
||||||
if(length < MAX_DMA_CHAIN_SIZE ) blockChainLen = length; // For last remainder block chain
|
|
||||||
|
__nvt_aes_crypt(ctx, input, output, blockChainLen);
|
||||||
|
|
||||||
|
length -= blockChainLen;
|
||||||
|
input += blockChainLen;
|
||||||
|
output += blockChainLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Save IV for next block cipher */
|
||||||
|
nu_set32_be(iv, ctx->iv[0]);
|
||||||
|
nu_set32_be(iv + 4, ctx->iv[1]);
|
||||||
|
nu_set32_be(iv + 8, ctx->iv[2]);
|
||||||
|
nu_set32_be(iv + 12, ctx->iv[3]);
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
||||||
|
|
||||||
#if defined(MBEDTLS_CIPHER_MODE_CFB)
|
#if defined(MBEDTLS_CIPHER_MODE_CFB)
|
||||||
/*
|
int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
|
||||||
* AES-CFB128 buffer encryption/decryption
|
int mode,
|
||||||
*/
|
size_t length,
|
||||||
/* Support partial block encryption/decryption */
|
size_t *iv_off,
|
||||||
static int __nvt_aes_crypt_partial_block_cfb128( mbedtls_aes_context *ctx,
|
unsigned char iv[16],
|
||||||
int mode,
|
const unsigned char *input,
|
||||||
size_t length,
|
unsigned char *output )
|
||||||
size_t *iv_off,
|
|
||||||
unsigned char iv[16],
|
|
||||||
const unsigned char *input,
|
|
||||||
unsigned char *output )
|
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
size_t n = *iv_off;
|
size_t n = *iv_off;
|
||||||
unsigned char iv_tmp[16];
|
|
||||||
mbedtls_trace("=== %s \r\n", __FUNCTION__);
|
/* First incomplete block */
|
||||||
if( mode == MBEDTLS_AES_DECRYPT )
|
if (n % 16) {
|
||||||
{
|
while (n && length) {
|
||||||
while( length-- )
|
if (mode == MBEDTLS_AES_DECRYPT) {
|
||||||
{
|
c = *input++;
|
||||||
if( n == 0)
|
*output++ = (unsigned char)( c ^ iv[n] );
|
||||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
|
iv[n] = (unsigned char) c;
|
||||||
else if( ctx->opMode == AES_MODE_CFB) // For previous cryption is CFB mode
|
}
|
||||||
{
|
else {
|
||||||
memcpy(iv_tmp, iv, n);
|
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
|
||||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, ctx->prv_iv, iv );
|
}
|
||||||
memcpy(iv, iv_tmp, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
c = *input++;
|
|
||||||
*output++ = (unsigned char)( c ^ iv[n] );
|
|
||||||
iv[n] = (unsigned char) c;
|
|
||||||
|
|
||||||
n = ( n + 1 ) & 0x0F;
|
n = ( n + 1 ) & 0x0F;
|
||||||
|
length --;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
while( length-- )
|
|
||||||
{
|
|
||||||
if( n == 0 )
|
|
||||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
|
|
||||||
else if( ctx->opMode == AES_MODE_CFB) // For previous cryption is CFB mode
|
|
||||||
{
|
|
||||||
memcpy(iv_tmp, iv, n);
|
|
||||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, ctx->prv_iv, iv );
|
|
||||||
memcpy(iv, iv_tmp, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
|
|
||||||
|
|
||||||
|
/* Middle complete block(s) */
|
||||||
|
size_t block_chain_len = length - (length % 16);
|
||||||
|
|
||||||
|
if (block_chain_len) {
|
||||||
|
ctx->opMode = AES_MODE_CFB;
|
||||||
|
if (mode == MBEDTLS_AES_DECRYPT) {
|
||||||
|
ctx->encDec = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ctx->encDec = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fetch IV byte data in big-endian */
|
||||||
|
ctx->iv[0] = nu_get32_be(iv);
|
||||||
|
ctx->iv[1] = nu_get32_be(iv + 4);
|
||||||
|
ctx->iv[2] = nu_get32_be(iv + 8);
|
||||||
|
ctx->iv[3] = nu_get32_be(iv + 12);
|
||||||
|
|
||||||
|
while (block_chain_len) {
|
||||||
|
size_t block_chain_len2 = (block_chain_len > MAX_DMA_CHAIN_SIZE) ? MAX_DMA_CHAIN_SIZE : block_chain_len;
|
||||||
|
|
||||||
|
__nvt_aes_crypt(ctx, input, output, block_chain_len2);
|
||||||
|
|
||||||
|
input += block_chain_len2;
|
||||||
|
output += block_chain_len2;
|
||||||
|
length -= block_chain_len2;
|
||||||
|
|
||||||
|
block_chain_len -= block_chain_len2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOTE: Buffers input/output could overlap. See ctx->iv rather than input/output
|
||||||
|
* for iv of next block cipher. */
|
||||||
|
/* Fetch IV byte data in big-endian */
|
||||||
|
nu_set32_be(iv, ctx->iv[0]);
|
||||||
|
nu_set32_be(iv + 4, ctx->iv[1]);
|
||||||
|
nu_set32_be(iv + 8, ctx->iv[2]);
|
||||||
|
nu_set32_be(iv + 12, ctx->iv[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Last incomplete block */
|
||||||
|
if (length) {
|
||||||
|
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
|
||||||
|
|
||||||
|
while (length --) {
|
||||||
|
if (mode == MBEDTLS_AES_DECRYPT) {
|
||||||
|
c = *input++;
|
||||||
|
*output++ = (unsigned char)( c ^ iv[n] );
|
||||||
|
iv[n] = (unsigned char) c;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
|
||||||
|
}
|
||||||
|
|
||||||
n = ( n + 1 ) & 0x0F;
|
n = ( n + 1 ) & 0x0F;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -439,96 +391,21 @@ static int __nvt_aes_crypt_partial_block_cfb128( mbedtls_aes_context *ctx,
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
|
|
||||||
int mode,
|
|
||||||
size_t len,
|
|
||||||
size_t *iv_off,
|
|
||||||
unsigned char iv[16],
|
|
||||||
const unsigned char *input,
|
|
||||||
unsigned char *output )
|
|
||||||
{
|
|
||||||
size_t n = *iv_off;
|
|
||||||
unsigned char temp[16];
|
|
||||||
int length=len;
|
|
||||||
int blockChainLen;
|
|
||||||
int remLen=0;
|
|
||||||
int ivLen;
|
|
||||||
|
|
||||||
mbedtls_trace("=== %s \r\n", __FUNCTION__);
|
|
||||||
|
|
||||||
// proceed: start with partial block by ECB mode first
|
|
||||||
if( n !=0 ) {
|
|
||||||
__nvt_aes_crypt_partial_block_cfb128(ctx, mode, 16 - n , iv_off, iv, input, output);
|
|
||||||
input += (16 - n);
|
|
||||||
output += (16 - n);
|
|
||||||
length -= (16 - n);
|
|
||||||
}
|
|
||||||
|
|
||||||
// For address or byte count non-word alignment, go through reserved DMA buffer.
|
|
||||||
if( (((uint32_t)input) & 0x03) || (((uint32_t)output) & 0x03) ) // Must reserved DMA buffer for each block
|
|
||||||
{
|
|
||||||
blockChainLen = (( length > MAX_DMA_CHAIN_SIZE ) ? MAX_DMA_CHAIN_SIZE : length );
|
|
||||||
} else if(length%4) { // Need reserved DMA buffer once for last chain
|
|
||||||
blockChainLen = (( length > MAX_DMA_CHAIN_SIZE ) ? (length - length%16) : length );
|
|
||||||
} else { // Not need reserved DMA buffer
|
|
||||||
blockChainLen = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
// proceed: start with block alignment
|
|
||||||
while( length > 0 )
|
|
||||||
{
|
|
||||||
|
|
||||||
ctx->opMode = AES_MODE_CFB;
|
|
||||||
|
|
||||||
swapInitVector(iv); // iv SWAP
|
|
||||||
|
|
||||||
ctx->iv = (uint32_t *)iv;
|
|
||||||
remLen = blockChainLen%16;
|
|
||||||
ivLen = (( remLen > 0) ? remLen: 16 );
|
|
||||||
|
|
||||||
if( mode == MBEDTLS_AES_DECRYPT )
|
|
||||||
{
|
|
||||||
memcpy(temp, input+blockChainLen - ivLen, ivLen);
|
|
||||||
if(blockChainLen >= 16) memcpy(ctx->prv_iv, input+blockChainLen-remLen-16 , 16);
|
|
||||||
ctx->encDec = 0;
|
|
||||||
__nvt_aes_crypt(ctx, input, output, blockChainLen);
|
|
||||||
memcpy(iv,temp, ivLen);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ctx->encDec = 1;
|
|
||||||
__nvt_aes_crypt(ctx, input, output, blockChainLen);
|
|
||||||
if(blockChainLen >= 16) memcpy(ctx->prv_iv, output+blockChainLen-remLen-16 , 16);
|
|
||||||
memcpy(iv,output+blockChainLen-ivLen,ivLen);
|
|
||||||
}
|
|
||||||
length -= blockChainLen;
|
|
||||||
input += blockChainLen;
|
|
||||||
output += blockChainLen;
|
|
||||||
if(length < MAX_DMA_CHAIN_SIZE ) blockChainLen = length; // For last remainder block chain
|
|
||||||
}
|
|
||||||
|
|
||||||
*iv_off = remLen;
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AES-CFB8 buffer encryption/decryption
|
* AES-CFB8 buffer encryption/decryption
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
|
int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
size_t length,
|
size_t length,
|
||||||
unsigned char iv[16],
|
unsigned char iv[16],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output )
|
unsigned char *output )
|
||||||
{
|
{
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
unsigned char ov[17];
|
unsigned char ov[17];
|
||||||
|
|
||||||
mbedtls_trace("=== %s \r\n", __FUNCTION__);
|
while( length-- ) {
|
||||||
while( length-- )
|
|
||||||
{
|
|
||||||
memcpy( ov, iv, 16 );
|
memcpy( ov, iv, 16 );
|
||||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
|
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
|
||||||
|
|
||||||
|
@ -552,19 +429,17 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
|
||||||
* AES-CTR buffer encryption/decryption
|
* AES-CTR buffer encryption/decryption
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
|
int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
|
||||||
size_t length,
|
size_t length,
|
||||||
size_t *nc_off,
|
size_t *nc_off,
|
||||||
unsigned char nonce_counter[16],
|
unsigned char nonce_counter[16],
|
||||||
unsigned char stream_block[16],
|
unsigned char stream_block[16],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output )
|
unsigned char *output )
|
||||||
{
|
{
|
||||||
int c, i;
|
int c, i;
|
||||||
size_t n = *nc_off;
|
size_t n = *nc_off;
|
||||||
|
|
||||||
mbedtls_trace("=== %s \r\n", __FUNCTION__);
|
while( length-- ) {
|
||||||
while( length-- )
|
|
||||||
{
|
|
||||||
if( n == 0 ) {
|
if( n == 0 ) {
|
||||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block );
|
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block );
|
||||||
|
|
||||||
|
|
|
@ -20,17 +20,11 @@
|
||||||
*
|
*
|
||||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MBEDTLS_AES_ALT_H
|
#ifndef MBEDTLS_AES_ALT_H
|
||||||
#define MBEDTLS_AES_ALT_H
|
#define MBEDTLS_AES_ALT_H
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/aes.h"
|
||||||
#include "mbedtls/config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_AES_C)
|
|
||||||
#if defined(MBEDTLS_AES_ALT)
|
#if defined(MBEDTLS_AES_ALT)
|
||||||
// Regular implementation
|
// Regular implementation
|
||||||
//
|
//
|
||||||
|
@ -40,29 +34,13 @@ extern "C" {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief AES context structure
|
* \brief AES context structure
|
||||||
*
|
|
||||||
* \note buf is able to hold 32 extra bytes, which can be used:
|
|
||||||
* - for alignment purposes if VIA padlock is used, and/or
|
|
||||||
* - to simplify key expansion in the 256-bit case by
|
|
||||||
* generating an extra round key
|
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
uint32_t keySize; /* Key size: AES_KEY_SIZE_128/192/256 */
|
||||||
uint32_t keySize;
|
uint32_t encDec; /* 0: decrypt, 1: encrypt */
|
||||||
uint32_t encDec;
|
uint32_t opMode; /* AES_MODE_ECB/CBC/CFB */
|
||||||
uint32_t opMode;
|
uint32_t iv[4]; /* IV for next block cipher */
|
||||||
uint32_t channel;
|
uint32_t keys[8]; /* Cipher key */
|
||||||
uint32_t swapType;
|
|
||||||
uint32_t *iv;
|
|
||||||
unsigned char prv_iv[16];
|
|
||||||
#if 1
|
|
||||||
uint32_t buf[8];
|
|
||||||
/* For comparsion with software AES for correctness */
|
|
||||||
#else
|
|
||||||
uint32_t buf[68]; /*!< unaligned data */
|
|
||||||
int nr; /*!< number of rounds */
|
|
||||||
uint32_t *rk; /*!< AES round keys */
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
mbedtls_aes_context;
|
mbedtls_aes_context;
|
||||||
|
|
||||||
|
@ -90,7 +68,7 @@ void mbedtls_aes_free( mbedtls_aes_context *ctx );
|
||||||
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
|
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
|
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
|
||||||
unsigned int keybits );
|
unsigned int keybits );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief AES key schedule (decryption)
|
* \brief AES key schedule (decryption)
|
||||||
|
@ -102,7 +80,7 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
|
||||||
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
|
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
|
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
|
||||||
unsigned int keybits );
|
unsigned int keybits );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief AES-ECB block encryption/decryption
|
* \brief AES-ECB block encryption/decryption
|
||||||
|
@ -115,9 +93,9 @@ int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
|
||||||
* \return 0 if successful
|
* \return 0 if successful
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
|
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
const unsigned char input[16],
|
const unsigned char input[16],
|
||||||
unsigned char output[16] );
|
unsigned char output[16] );
|
||||||
|
|
||||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
||||||
/**
|
/**
|
||||||
|
@ -143,11 +121,11 @@ int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
|
||||||
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH
|
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
|
int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
size_t length,
|
size_t length,
|
||||||
unsigned char iv[16],
|
unsigned char iv[16],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output );
|
unsigned char *output );
|
||||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
||||||
|
|
||||||
#if defined(MBEDTLS_CIPHER_MODE_CFB)
|
#if defined(MBEDTLS_CIPHER_MODE_CFB)
|
||||||
|
@ -177,12 +155,12 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
|
||||||
* \return 0 if successful
|
* \return 0 if successful
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
|
int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
size_t length,
|
size_t length,
|
||||||
size_t *iv_off,
|
size_t *iv_off,
|
||||||
unsigned char iv[16],
|
unsigned char iv[16],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output );
|
unsigned char *output );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief AES-CFB8 buffer encryption/decryption.
|
* \brief AES-CFB8 buffer encryption/decryption.
|
||||||
|
@ -209,11 +187,11 @@ int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
|
||||||
* \return 0 if successful
|
* \return 0 if successful
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
|
int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
size_t length,
|
size_t length,
|
||||||
unsigned char iv[16],
|
unsigned char iv[16],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output );
|
unsigned char *output );
|
||||||
#endif /*MBEDTLS_CIPHER_MODE_CFB */
|
#endif /*MBEDTLS_CIPHER_MODE_CFB */
|
||||||
|
|
||||||
#if defined(MBEDTLS_CIPHER_MODE_CTR)
|
#if defined(MBEDTLS_CIPHER_MODE_CTR)
|
||||||
|
@ -240,12 +218,12 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
|
||||||
* \return 0 if successful
|
* \return 0 if successful
|
||||||
*/
|
*/
|
||||||
int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
|
int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
|
||||||
size_t length,
|
size_t length,
|
||||||
size_t *nc_off,
|
size_t *nc_off,
|
||||||
unsigned char nonce_counter[16],
|
unsigned char nonce_counter[16],
|
||||||
unsigned char stream_block[16],
|
unsigned char stream_block[16],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output );
|
unsigned char *output );
|
||||||
#endif /* MBEDTLS_CIPHER_MODE_CTR */
|
#endif /* MBEDTLS_CIPHER_MODE_CTR */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -280,6 +258,5 @@ void mbedtls_aes_decrypt( mbedtls_aes_context *ctx,
|
||||||
|
|
||||||
|
|
||||||
#endif /* MBEDTLS_AES_ALT */
|
#endif /* MBEDTLS_AES_ALT */
|
||||||
#endif /* MBEDTLS_AES_C */
|
|
||||||
|
|
||||||
#endif /* aes_alt.h */
|
#endif /* aes_alt.h */
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
/* mbed Microcontroller Library
|
|
||||||
* Copyright (c) 2015-2016 Nuvoton
|
|
||||||
*
|
|
||||||
* 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 "cmsis.h"
|
|
||||||
#include "mbed_assert.h"
|
|
||||||
#include "nu_modutil.h"
|
|
||||||
#include "nu_bitutil.h"
|
|
||||||
#include "crypto-misc.h"
|
|
||||||
|
|
||||||
static int crypto_inited = 0;
|
|
||||||
static int crypto_sha_avail = 1;
|
|
||||||
|
|
||||||
void crypto_init(void)
|
|
||||||
{
|
|
||||||
if (crypto_inited) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
crypto_inited = 1;
|
|
||||||
|
|
||||||
CLK_EnableModuleClock(CRPT_MODULE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Implementation that should never be optimized out by the compiler */
|
|
||||||
void crypto_zeroize(void *v, size_t n)
|
|
||||||
{
|
|
||||||
volatile unsigned char *p = (unsigned char*) v;
|
|
||||||
while (n--) {
|
|
||||||
*p++ = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int crypto_sha_acquire(void)
|
|
||||||
{
|
|
||||||
if (crypto_sha_avail) {
|
|
||||||
crypto_sha_avail = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void crypto_sha_release(void)
|
|
||||||
{
|
|
||||||
if (! crypto_sha_avail) {
|
|
||||||
crypto_sha_avail = 1;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
/* mbed Microcontroller Library
|
|
||||||
* Copyright (c) 2015-2016 Nuvoton
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MBED_CRYPTO_MISC_H
|
|
||||||
#define MBED_CRYPTO_MISC_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void crypto_init(void);
|
|
||||||
void crypto_zeroize(void *v, size_t n);
|
|
||||||
int crypto_sha_acquire(void);
|
|
||||||
void crypto_sha_release(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -14,33 +14,37 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/des.h"
|
||||||
#include "mbedtls/config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_DES_C)
|
#if defined(MBEDTLS_DES_C)
|
||||||
#if defined(MBEDTLS_DES_ALT)
|
#if defined(MBEDTLS_DES_ALT)
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "mbedtls/des.h"
|
#include <stdbool.h>
|
||||||
#include "des_alt.h"
|
|
||||||
#include "crypto-misc.h"
|
#include "crypto-misc.h"
|
||||||
#include "nu_bitutil.h"
|
#include "nu_bitutil.h"
|
||||||
#include "mbed_toolchain.h"
|
#include "mbed_toolchain.h"
|
||||||
|
#include "mbed_error.h"
|
||||||
|
|
||||||
// Must be a multiple of 64-bit block size
|
/* DES DMA compatible buffer requirements
|
||||||
|
*
|
||||||
|
* DES DMA buffer location requires to be:
|
||||||
|
* (1) Word-aligned
|
||||||
|
* (2) Located in 0x2xxxxxxx region. Check linker files to ensure global variables are placed in this region.
|
||||||
|
*
|
||||||
|
* DES DMA buffer size MAXSIZE_DMABUF must be a multiple of 64-bit block size.
|
||||||
|
* Its value is estimated to trade memory footprint off against performance.
|
||||||
|
*
|
||||||
|
*/
|
||||||
#define MAXSIZE_DMABUF (8 * 5)
|
#define MAXSIZE_DMABUF (8 * 5)
|
||||||
static uint8_t dmabuf_in[MAXSIZE_DMABUF] MBED_ALIGN(4);
|
MBED_ALIGN(4) static uint8_t dmabuf_in[MAXSIZE_DMABUF];
|
||||||
static uint8_t dmabuf_out[MAXSIZE_DMABUF] MBED_ALIGN(4);
|
MBED_ALIGN(4) static uint8_t dmabuf_out[MAXSIZE_DMABUF];
|
||||||
|
|
||||||
static int mbedtls_des_docrypt(uint16_t keyopt, uint8_t key[3][MBEDTLS_DES_KEY_SIZE], int enc, uint32_t tdes_opmode, size_t length,
|
static int mbedtls_des_docrypt(uint16_t keyopt, uint8_t key[3][MBEDTLS_DES_KEY_SIZE], int enc, uint32_t tdes_opmode, size_t length,
|
||||||
unsigned char iv[8], const unsigned char *input, unsigned char *output);
|
unsigned char iv[8], const unsigned char *input, unsigned char *output);
|
||||||
|
|
||||||
void mbedtls_des_init(mbedtls_des_context *ctx)
|
void mbedtls_des_init(mbedtls_des_context *ctx)
|
||||||
{
|
{
|
||||||
crypto_init();
|
|
||||||
memset(ctx, 0, sizeof(mbedtls_des_context));
|
memset(ctx, 0, sizeof(mbedtls_des_context));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +59,6 @@ void mbedtls_des_free( mbedtls_des_context *ctx )
|
||||||
|
|
||||||
void mbedtls_des3_init( mbedtls_des3_context *ctx )
|
void mbedtls_des3_init( mbedtls_des3_context *ctx )
|
||||||
{
|
{
|
||||||
crypto_init();
|
|
||||||
memset(ctx, 0, sizeof(mbedtls_des3_context));
|
memset(ctx, 0, sizeof(mbedtls_des3_context));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,15 +72,16 @@ void mbedtls_des3_free( mbedtls_des3_context *ctx )
|
||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8,
|
static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8,
|
||||||
11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44,
|
11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44,
|
||||||
47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81,
|
47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81,
|
||||||
82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112,
|
82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112,
|
||||||
115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140,
|
115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140,
|
||||||
143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168,
|
143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168,
|
||||||
171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196,
|
171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196,
|
||||||
199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224,
|
199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224,
|
||||||
227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253,
|
227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253,
|
||||||
254 };
|
254
|
||||||
|
};
|
||||||
|
|
||||||
void mbedtls_des_key_set_parity(unsigned char key[MBEDTLS_DES_KEY_SIZE])
|
void mbedtls_des_key_set_parity(unsigned char key[MBEDTLS_DES_KEY_SIZE])
|
||||||
{
|
{
|
||||||
|
@ -125,8 +129,7 @@ int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SI
|
||||||
|
|
||||||
#define WEAK_KEY_COUNT 16
|
#define WEAK_KEY_COUNT 16
|
||||||
|
|
||||||
static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] =
|
static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] = {
|
||||||
{
|
|
||||||
{ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
|
{ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
|
||||||
{ 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },
|
{ 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },
|
||||||
{ 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },
|
{ 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },
|
||||||
|
@ -168,7 +171,7 @@ int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MB
|
||||||
memcpy(ctx->key[0], key, MBEDTLS_DES_KEY_SIZE);
|
memcpy(ctx->key[0], key, MBEDTLS_DES_KEY_SIZE);
|
||||||
memcpy(ctx->key[1], key, MBEDTLS_DES_KEY_SIZE);
|
memcpy(ctx->key[1], key, MBEDTLS_DES_KEY_SIZE);
|
||||||
memcpy(ctx->key[2], key, MBEDTLS_DES_KEY_SIZE);
|
memcpy(ctx->key[2], key, MBEDTLS_DES_KEY_SIZE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,7 +194,7 @@ int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MB
|
||||||
* Triple-DES key schedule (112-bit, encryption)
|
* Triple-DES key schedule (112-bit, encryption)
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx,
|
int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx,
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] )
|
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] )
|
||||||
{
|
{
|
||||||
ctx->enc = 1;
|
ctx->enc = 1;
|
||||||
// Keying option 2: K1 and K2 are independent, and K3 = K1.
|
// Keying option 2: K1 and K2 are independent, and K3 = K1.
|
||||||
|
@ -207,7 +210,7 @@ int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx,
|
||||||
* Triple-DES key schedule (112-bit, decryption)
|
* Triple-DES key schedule (112-bit, decryption)
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx,
|
int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx,
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] )
|
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] )
|
||||||
{
|
{
|
||||||
ctx->enc = 0;
|
ctx->enc = 0;
|
||||||
// Keying option 2: K1 and K2 are independent, and K3 = K1.
|
// Keying option 2: K1 and K2 are independent, and K3 = K1.
|
||||||
|
@ -223,7 +226,7 @@ int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx,
|
||||||
* Triple-DES key schedule (168-bit, encryption)
|
* Triple-DES key schedule (168-bit, encryption)
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx,
|
int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx,
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] )
|
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] )
|
||||||
{
|
{
|
||||||
ctx->enc = 1;
|
ctx->enc = 1;
|
||||||
// Keying option 1: All three keys are independent.
|
// Keying option 1: All three keys are independent.
|
||||||
|
@ -239,7 +242,7 @@ int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx,
|
||||||
* Triple-DES key schedule (168-bit, decryption)
|
* Triple-DES key schedule (168-bit, decryption)
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx,
|
int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx,
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] )
|
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] )
|
||||||
{
|
{
|
||||||
ctx->enc = 0;
|
ctx->enc = 0;
|
||||||
// Keying option 1: All three keys are independent.
|
// Keying option 1: All three keys are independent.
|
||||||
|
@ -255,8 +258,8 @@ int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx,
|
||||||
* DES-ECB block encryption/decryption
|
* DES-ECB block encryption/decryption
|
||||||
*/
|
*/
|
||||||
int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx,
|
int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx,
|
||||||
const unsigned char input[8],
|
const unsigned char input[8],
|
||||||
unsigned char output[8] )
|
unsigned char output[8] )
|
||||||
{
|
{
|
||||||
unsigned char iv[8] = {0x00};
|
unsigned char iv[8] = {0x00};
|
||||||
return mbedtls_des_docrypt(ctx->keyopt, ctx->key, ctx->enc, DES_MODE_ECB, 8, iv, input, output);
|
return mbedtls_des_docrypt(ctx->keyopt, ctx->key, ctx->enc, DES_MODE_ECB, 8, iv, input, output);
|
||||||
|
@ -267,11 +270,11 @@ int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx,
|
||||||
* DES-CBC buffer encryption/decryption
|
* DES-CBC buffer encryption/decryption
|
||||||
*/
|
*/
|
||||||
int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx,
|
int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
size_t length,
|
size_t length,
|
||||||
unsigned char iv[8],
|
unsigned char iv[8],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output )
|
unsigned char *output )
|
||||||
{
|
{
|
||||||
return mbedtls_des_docrypt(ctx->keyopt, ctx->key, mode == MBEDTLS_DES_ENCRYPT, DES_MODE_CBC, length, iv, input, output);
|
return mbedtls_des_docrypt(ctx->keyopt, ctx->key, mode == MBEDTLS_DES_ENCRYPT, DES_MODE_CBC, length, iv, input, output);
|
||||||
}
|
}
|
||||||
|
@ -281,8 +284,8 @@ int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx,
|
||||||
* 3DES-ECB block encryption/decryption
|
* 3DES-ECB block encryption/decryption
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx,
|
int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx,
|
||||||
const unsigned char input[8],
|
const unsigned char input[8],
|
||||||
unsigned char output[8] )
|
unsigned char output[8] )
|
||||||
{
|
{
|
||||||
unsigned char iv[8] = {0x00};
|
unsigned char iv[8] = {0x00};
|
||||||
return mbedtls_des_docrypt(ctx->keyopt, ctx->key, ctx->enc, TDES_MODE_ECB, 8, iv, input, output);
|
return mbedtls_des_docrypt(ctx->keyopt, ctx->key, ctx->enc, TDES_MODE_ECB, 8, iv, input, output);
|
||||||
|
@ -293,11 +296,11 @@ int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx,
|
||||||
* 3DES-CBC buffer encryption/decryption
|
* 3DES-CBC buffer encryption/decryption
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx,
|
int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
size_t length,
|
size_t length,
|
||||||
unsigned char iv[8],
|
unsigned char iv[8],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output )
|
unsigned char *output )
|
||||||
{
|
{
|
||||||
return mbedtls_des_docrypt(ctx->keyopt, ctx->key, mode == MBEDTLS_DES_ENCRYPT, TDES_MODE_CBC, length, iv, input, output);
|
return mbedtls_des_docrypt(ctx->keyopt, ctx->key, mode == MBEDTLS_DES_ENCRYPT, TDES_MODE_CBC, length, iv, input, output);
|
||||||
}
|
}
|
||||||
|
@ -305,103 +308,157 @@ int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int mbedtls_des_docrypt(uint16_t keyopt, uint8_t key[3][MBEDTLS_DES_KEY_SIZE], int enc, uint32_t tdes_opmode, size_t length,
|
static int mbedtls_des_docrypt(uint16_t keyopt, uint8_t key[3][MBEDTLS_DES_KEY_SIZE], int enc, uint32_t tdes_opmode, size_t length,
|
||||||
unsigned char iv[8], const unsigned char *input, unsigned char *output)
|
unsigned char iv[8], const unsigned char *input, unsigned char *output)
|
||||||
{
|
{
|
||||||
|
if ((keyopt < 1) || (keyopt > 3)) {
|
||||||
|
error("Key option in DES alter. requires to be 1/2/3.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == NULL) {
|
||||||
|
error("Meet null key pointer in DES alter.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((enc != 0) && (enc != 1)) {
|
||||||
|
error("Enc/dec flag in DES alter. requires to be 0/1.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tdes_opmode & ~(CRPT_TDES_CTL_TMODE_Msk | CRPT_TDES_CTL_OPMODE_Msk)) {
|
||||||
|
error("Invalid TMODE/OPMODE in DES alter.");
|
||||||
|
}
|
||||||
|
|
||||||
if (length % 8) {
|
if (length % 8) {
|
||||||
return MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH;
|
return MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Don't call driver function TDES_Open in BSP because it doesn't support TDES_CTL[3KEYS] setting.
|
|
||||||
CRPT->TDES_CTL = (0 << CRPT_TDES_CTL_CHANNEL_Pos) | (enc << CRPT_TDES_CTL_ENCRPT_Pos) |
|
|
||||||
tdes_opmode | (TDES_IN_OUT_WHL_SWAP << CRPT_TDES_CTL_BLKSWAP_Pos);
|
|
||||||
|
|
||||||
// Keying option 1: All three keys are independent.
|
if (iv == NULL) {
|
||||||
// Keying option 2: K1 and K2 are independent, and K3 = K1.
|
error("Meet null IV pointer in DES alter.");
|
||||||
// Keying option 3: All three keys are identical, i.e. K1 = K2 = K3.
|
|
||||||
if (keyopt == 1) {
|
|
||||||
CRPT->TDES_CTL |= CRPT_TDES_CTL_3KEYS_Msk;
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
CRPT->TDES_CTL &= ~CRPT_TDES_CTL_3KEYS_Msk;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set DES/TDES keys
|
|
||||||
// NOTE: Don't call driver function TDES_SetKey in BSP because it doesn't support endian swap.
|
|
||||||
uint32_t val;
|
|
||||||
volatile uint32_t *tdes_key = (uint32_t *) ((uint32_t) &CRPT->TDES0_KEY1H + (0x40 * 0));
|
|
||||||
val = nu_get32_be(key[0] + 0);
|
|
||||||
*tdes_key ++ = val;
|
|
||||||
val = nu_get32_be(key[0] + 4);
|
|
||||||
*tdes_key ++ = val;
|
|
||||||
val = nu_get32_be(key[1] + 0);
|
|
||||||
*tdes_key ++ = val;
|
|
||||||
val = nu_get32_be(key[1] + 4);
|
|
||||||
*tdes_key ++ = val;
|
|
||||||
val = nu_get32_be(key[2] + 0);
|
|
||||||
*tdes_key ++ = val;
|
|
||||||
val = nu_get32_be(key[2] + 4);
|
|
||||||
*tdes_key ++ = val;
|
|
||||||
|
|
||||||
|
if (input == NULL || output == NULL) {
|
||||||
|
error("Meet null input/output pointer in DES alter.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DES DMA buffer has the following requirements:
|
||||||
|
* (1) Word-aligned buffer base address
|
||||||
|
* (2) 8-byte aligned buffer size
|
||||||
|
* (3) Located in 0x20000000-0x2FFFFFFF region
|
||||||
|
*/
|
||||||
|
if ((! crypto_dma_buff_compat(dmabuf_in, MAXSIZE_DMABUF, 8)) ||
|
||||||
|
(! crypto_dma_buff_compat(dmabuf_out, MAXSIZE_DMABUF, 8))) {
|
||||||
|
error("Buffer for DES alter. DMA requires to be word-aligned and located in 0x20000000-0x2FFFFFFF region.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Change busy-wait to other means to release CPU */
|
||||||
|
/* Acquire ownership of DES H/W */
|
||||||
|
while (! crypto_des_acquire());
|
||||||
|
|
||||||
|
/* Init crypto module */
|
||||||
|
crypto_init();
|
||||||
|
/* Enable DES interrupt */
|
||||||
|
TDES_ENABLE_INT();
|
||||||
|
|
||||||
|
/* Configure TDES_CTL register
|
||||||
|
*
|
||||||
|
* BSP TDES driver supports multiple channels. Just use channel #0.
|
||||||
|
*
|
||||||
|
* Relationship of keying option and TDES H/W mode configuration
|
||||||
|
* 1: All three keys are independent ==> TDES 3-key mode (TMODE=1, 3KEYS=1)
|
||||||
|
* 2: K1 and K2 are independent, and K3 = K1 ==> TDES 2-key mode (TMODE=1, 3KEYS=0)
|
||||||
|
* 3: All three keys are identical, i.e. K1 = K2 = K3 ==> DES mode (TMODE=0)
|
||||||
|
*
|
||||||
|
* tdes_opmode is combination of TMODE/OPMODE, but TDES_Open I/F requires TMODE/OPMODE to be separate.
|
||||||
|
* We need to divide tdes_opmode to TMODE and OPMODE.
|
||||||
|
*
|
||||||
|
* TDES_IN_OUT_WHL_SWAP lets TDES H/W know input/output data are arranged in below for DMA transfer:
|
||||||
|
* 1. BE for byte sequence in word
|
||||||
|
* 2. BE for word sequence in double-word
|
||||||
|
*/
|
||||||
|
TDES_Open(0, // Channel number (0~4)
|
||||||
|
enc, // 0: decode, 1: encode
|
||||||
|
(tdes_opmode & CRPT_TDES_CTL_TMODE_Msk) ? 1 : 0, // 0: DES, 1: TDES
|
||||||
|
(keyopt == 1) ? 1 : 0, // 0: TDES 2-key mode, 1: TDES 3-key mode
|
||||||
|
tdes_opmode & CRPT_TDES_CTL_OPMODE_Msk, // ECB/CBC/CFB/OFB/CTR
|
||||||
|
TDES_IN_OUT_WHL_SWAP); // TDES_NO_SWAP~TDES_IN_OUT_WHL_SWAP
|
||||||
|
|
||||||
|
/* Set DES/TDES keys
|
||||||
|
*
|
||||||
|
* TDES_SetKey requires 3x2 word array. Change 3x8 byte array to 3x2 word array.
|
||||||
|
*/
|
||||||
|
unsigned i;
|
||||||
|
uint32_t keys3x2[3][2];
|
||||||
|
for (i = 0; i < 3; i ++ ) {
|
||||||
|
keys3x2[i][0] = nu_get32_be(key[i] + 0);
|
||||||
|
keys3x2[i][1] = nu_get32_be(key[i] + 4);
|
||||||
|
}
|
||||||
|
TDES_SetKey(0, keys3x2);
|
||||||
|
|
||||||
uint32_t rmn = length;
|
uint32_t rmn = length;
|
||||||
const unsigned char *in_pos = input;
|
const unsigned char *in_pos = input;
|
||||||
unsigned char *out_pos = output;
|
unsigned char *out_pos = output;
|
||||||
|
|
||||||
while (rmn) {
|
while (rmn > 0) {
|
||||||
uint32_t data_len = (rmn <= MAXSIZE_DMABUF) ? rmn : MAXSIZE_DMABUF;
|
uint32_t data_len = (rmn <= MAXSIZE_DMABUF) ? rmn : MAXSIZE_DMABUF;
|
||||||
|
|
||||||
uint32_t ivh, ivl;
|
uint32_t ivh, ivl;
|
||||||
ivh = nu_get32_be(iv);
|
ivh = nu_get32_be(iv);
|
||||||
ivl = nu_get32_be(iv + 4);
|
ivl = nu_get32_be(iv + 4);
|
||||||
TDES_SetInitVect(0, ivh, ivl);
|
TDES_SetInitVect(0, ivh, ivl);
|
||||||
|
|
||||||
memcpy(dmabuf_in, in_pos, data_len);
|
memcpy(dmabuf_in, in_pos, data_len);
|
||||||
|
|
||||||
|
/* We always use DMA backup buffers, which are guaranteed to be non-overlapped. */
|
||||||
TDES_SetDMATransfer(0, (uint32_t) dmabuf_in, (uint32_t) dmabuf_out, data_len);
|
TDES_SetDMATransfer(0, (uint32_t) dmabuf_in, (uint32_t) dmabuf_out, data_len);
|
||||||
|
|
||||||
// Start enc/dec.
|
crypto_des_prestart();
|
||||||
// NOTE: Don't call driver function TDES_Start in BSP because it will override TDES_CTL[3KEYS] setting.
|
TDES_Start(0, CRYPTO_DMA_ONE_SHOT);
|
||||||
CRPT->TDES_CTL |= CRPT_TDES_CTL_START_Msk | (CRYPTO_DMA_ONE_SHOT << CRPT_TDES_CTL_DMALAST_Pos);
|
crypto_des_wait();
|
||||||
while (CRPT->TDES_STS & CRPT_TDES_STS_BUSY_Msk);
|
|
||||||
|
|
||||||
memcpy(out_pos, dmabuf_out, data_len);
|
memcpy(out_pos, dmabuf_out, data_len);
|
||||||
in_pos += data_len;
|
in_pos += data_len;
|
||||||
out_pos += data_len;
|
out_pos += data_len;
|
||||||
rmn -= data_len;
|
rmn -= data_len;
|
||||||
|
|
||||||
// Update IV for next block enc/dec in next function call
|
// Update IV for next block enc/dec in next function call
|
||||||
switch (tdes_opmode) {
|
switch (tdes_opmode) {
|
||||||
case DES_MODE_OFB:
|
case DES_MODE_OFB:
|
||||||
case TDES_MODE_OFB: {
|
case TDES_MODE_OFB: {
|
||||||
// OFB: IV (enc/dec) = output block XOR input block
|
// OFB: IV (enc/dec) = output block XOR input block
|
||||||
uint32_t lbh, lbl;
|
uint32_t lbh, lbl;
|
||||||
// Last block of input data
|
// Last block of input data
|
||||||
lbh = nu_get32_be(dmabuf_in + data_len - 8 + 4);
|
lbh = nu_get32_be(dmabuf_in + data_len - 8 + 4);
|
||||||
lbl = nu_get32_be(dmabuf_in + data_len - 8 + 0);
|
lbl = nu_get32_be(dmabuf_in + data_len - 8 + 0);
|
||||||
// Last block of output data
|
// Last block of output data
|
||||||
ivh = nu_get32_be(dmabuf_out + 4);
|
ivh = nu_get32_be(dmabuf_out + 4);
|
||||||
ivl = nu_get32_be(dmabuf_out + 0);
|
ivl = nu_get32_be(dmabuf_out + 0);
|
||||||
ivh = ivh ^ lbh;
|
ivh = ivh ^ lbh;
|
||||||
ivl = ivl ^ lbl;
|
ivl = ivl ^ lbl;
|
||||||
nu_set32_be(iv + 4, ivh);
|
nu_set32_be(iv + 4, ivh);
|
||||||
nu_set32_be(iv, ivl);
|
nu_set32_be(iv, ivl);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DES_MODE_CBC:
|
case DES_MODE_CBC:
|
||||||
case DES_MODE_CFB:
|
case DES_MODE_CFB:
|
||||||
case TDES_MODE_CBC:
|
case TDES_MODE_CBC:
|
||||||
case TDES_MODE_CFB: {
|
case TDES_MODE_CFB: {
|
||||||
// CBC/CFB: IV (enc) = output block
|
// CBC/CFB: IV (enc) = output block
|
||||||
// IV (dec) = input block
|
// IV (dec) = input block
|
||||||
if (enc) {
|
if (enc) {
|
||||||
memcpy(iv, dmabuf_out + data_len - 8, 8);
|
memcpy(iv, dmabuf_out + data_len - 8, 8);
|
||||||
}
|
} else {
|
||||||
else {
|
memcpy(iv, dmabuf_in + data_len - 8, 8);
|
||||||
memcpy(iv, dmabuf_in + data_len - 8, 8);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Disable DES interrupt */
|
||||||
|
TDES_DISABLE_INT();
|
||||||
|
/* Uninit crypto module */
|
||||||
|
crypto_uninit();
|
||||||
|
|
||||||
|
/* Release ownership of DES H/W */
|
||||||
|
crypto_des_release();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,23 +13,16 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MBEDTLS_DES_ALT_H
|
#ifndef MBEDTLS_DES_ALT_H
|
||||||
#define MBEDTLS_DES_ALT_H
|
#define MBEDTLS_DES_ALT_H
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/des.h"
|
||||||
#include "mbedtls/config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_DES_C)
|
|
||||||
#if defined(MBEDTLS_DES_ALT)
|
#if defined(MBEDTLS_DES_ALT)
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "des.h"
|
|
||||||
#include "des_alt_sw.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -38,19 +31,19 @@ extern "C" {
|
||||||
/**
|
/**
|
||||||
* \brief DES context structure
|
* \brief DES context structure
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
int enc; /* 0: dec, 1: enc */
|
||||||
int enc; /*!< 0: dec, 1: enc */
|
uint16_t keyopt; /* 1: All three keys are independent.
|
||||||
uint16_t keyopt;
|
* 2: K1 and K2 are independent, and K3 = K1.
|
||||||
uint8_t key[3][MBEDTLS_DES_KEY_SIZE]; /*!< 3DES keys */
|
* 3: All three keys are identical, i.e. K1 = K2 = K3. */
|
||||||
|
uint8_t key[3][MBEDTLS_DES_KEY_SIZE]; /* 3DES keys */
|
||||||
}
|
}
|
||||||
mbedtls_des_context;
|
mbedtls_des_context;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Triple-DES context structure
|
* \brief Triple-DES context structure
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
int enc; /*!< 0: dec, 1: enc */
|
int enc; /*!< 0: dec, 1: enc */
|
||||||
uint16_t keyopt;
|
uint16_t keyopt;
|
||||||
uint8_t key[3][MBEDTLS_DES_KEY_SIZE]; /*!< 3DES keys */
|
uint8_t key[3][MBEDTLS_DES_KEY_SIZE]; /*!< 3DES keys */
|
||||||
|
@ -145,7 +138,7 @@ int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MB
|
||||||
* \return 0
|
* \return 0
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx,
|
int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx,
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
|
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Triple-DES key schedule (112-bit, decryption)
|
* \brief Triple-DES key schedule (112-bit, decryption)
|
||||||
|
@ -156,7 +149,7 @@ int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx,
|
||||||
* \return 0
|
* \return 0
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx,
|
int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx,
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
|
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Triple-DES key schedule (168-bit, encryption)
|
* \brief Triple-DES key schedule (168-bit, encryption)
|
||||||
|
@ -167,7 +160,7 @@ int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx,
|
||||||
* \return 0
|
* \return 0
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx,
|
int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx,
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
|
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Triple-DES key schedule (168-bit, decryption)
|
* \brief Triple-DES key schedule (168-bit, decryption)
|
||||||
|
@ -178,7 +171,7 @@ int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx,
|
||||||
* \return 0
|
* \return 0
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx,
|
int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx,
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
|
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief DES-ECB block encryption/decryption
|
* \brief DES-ECB block encryption/decryption
|
||||||
|
@ -190,8 +183,8 @@ int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx,
|
||||||
* \return 0 if successful
|
* \return 0 if successful
|
||||||
*/
|
*/
|
||||||
int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx,
|
int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx,
|
||||||
const unsigned char input[8],
|
const unsigned char input[8],
|
||||||
unsigned char output[8] );
|
unsigned char output[8] );
|
||||||
|
|
||||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
||||||
/**
|
/**
|
||||||
|
@ -213,11 +206,11 @@ int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx,
|
||||||
* \param output buffer holding the output data
|
* \param output buffer holding the output data
|
||||||
*/
|
*/
|
||||||
int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx,
|
int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
size_t length,
|
size_t length,
|
||||||
unsigned char iv[8],
|
unsigned char iv[8],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output );
|
unsigned char *output );
|
||||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -230,8 +223,8 @@ int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx,
|
||||||
* \return 0 if successful
|
* \return 0 if successful
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx,
|
int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx,
|
||||||
const unsigned char input[8],
|
const unsigned char input[8],
|
||||||
unsigned char output[8] );
|
unsigned char output[8] );
|
||||||
|
|
||||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
||||||
/**
|
/**
|
||||||
|
@ -255,11 +248,11 @@ int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx,
|
||||||
* \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH
|
* \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH
|
||||||
*/
|
*/
|
||||||
int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx,
|
int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx,
|
||||||
int mode,
|
int mode,
|
||||||
size_t length,
|
size_t length,
|
||||||
unsigned char iv[8],
|
unsigned char iv[8],
|
||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output );
|
unsigned char *output );
|
||||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -277,6 +270,5 @@ void mbedtls_des_setkey( uint32_t SK[32],
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* MBEDTLS_DES_ALT */
|
#endif /* MBEDTLS_DES_ALT */
|
||||||
#endif /* MBEDTLS_DES_C */
|
|
||||||
|
|
||||||
#endif /* des_alt.h */
|
#endif /* des_alt.h */
|
||||||
|
|
|
@ -1,797 +0,0 @@
|
||||||
/*
|
|
||||||
* FIPS-46-3 compliant Triple-DES implementation
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*
|
|
||||||
* 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 is part of mbed TLS (https://tls.mbed.org)
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* DES, on which TDES is based, was originally designed by Horst Feistel
|
|
||||||
* at IBM in 1974, and was adopted as a standard by NIST (formerly NBS).
|
|
||||||
*
|
|
||||||
* http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
|
||||||
#include "mbedtls/config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_DES_C)
|
|
||||||
#if defined(MBEDTLS_DES_ALT)
|
|
||||||
|
|
||||||
#include "mbedtls/des.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/* Implementation that should never be optimized out by the compiler */
|
|
||||||
static void mbedtls_zeroize( void *v, size_t n ) {
|
|
||||||
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 32-bit integer manipulation macros (big endian)
|
|
||||||
*/
|
|
||||||
#ifndef GET_UINT32_BE
|
|
||||||
#define GET_UINT32_BE(n,b,i) \
|
|
||||||
{ \
|
|
||||||
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
|
|
||||||
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
|
|
||||||
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
|
|
||||||
| ( (uint32_t) (b)[(i) + 3] ); \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PUT_UINT32_BE
|
|
||||||
#define PUT_UINT32_BE(n,b,i) \
|
|
||||||
{ \
|
|
||||||
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
|
|
||||||
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
|
|
||||||
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
|
|
||||||
(b)[(i) + 3] = (unsigned char) ( (n) ); \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Expanded DES S-boxes
|
|
||||||
*/
|
|
||||||
static const uint32_t SB1[64] =
|
|
||||||
{
|
|
||||||
0x01010400, 0x00000000, 0x00010000, 0x01010404,
|
|
||||||
0x01010004, 0x00010404, 0x00000004, 0x00010000,
|
|
||||||
0x00000400, 0x01010400, 0x01010404, 0x00000400,
|
|
||||||
0x01000404, 0x01010004, 0x01000000, 0x00000004,
|
|
||||||
0x00000404, 0x01000400, 0x01000400, 0x00010400,
|
|
||||||
0x00010400, 0x01010000, 0x01010000, 0x01000404,
|
|
||||||
0x00010004, 0x01000004, 0x01000004, 0x00010004,
|
|
||||||
0x00000000, 0x00000404, 0x00010404, 0x01000000,
|
|
||||||
0x00010000, 0x01010404, 0x00000004, 0x01010000,
|
|
||||||
0x01010400, 0x01000000, 0x01000000, 0x00000400,
|
|
||||||
0x01010004, 0x00010000, 0x00010400, 0x01000004,
|
|
||||||
0x00000400, 0x00000004, 0x01000404, 0x00010404,
|
|
||||||
0x01010404, 0x00010004, 0x01010000, 0x01000404,
|
|
||||||
0x01000004, 0x00000404, 0x00010404, 0x01010400,
|
|
||||||
0x00000404, 0x01000400, 0x01000400, 0x00000000,
|
|
||||||
0x00010004, 0x00010400, 0x00000000, 0x01010004
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32_t SB2[64] =
|
|
||||||
{
|
|
||||||
0x80108020, 0x80008000, 0x00008000, 0x00108020,
|
|
||||||
0x00100000, 0x00000020, 0x80100020, 0x80008020,
|
|
||||||
0x80000020, 0x80108020, 0x80108000, 0x80000000,
|
|
||||||
0x80008000, 0x00100000, 0x00000020, 0x80100020,
|
|
||||||
0x00108000, 0x00100020, 0x80008020, 0x00000000,
|
|
||||||
0x80000000, 0x00008000, 0x00108020, 0x80100000,
|
|
||||||
0x00100020, 0x80000020, 0x00000000, 0x00108000,
|
|
||||||
0x00008020, 0x80108000, 0x80100000, 0x00008020,
|
|
||||||
0x00000000, 0x00108020, 0x80100020, 0x00100000,
|
|
||||||
0x80008020, 0x80100000, 0x80108000, 0x00008000,
|
|
||||||
0x80100000, 0x80008000, 0x00000020, 0x80108020,
|
|
||||||
0x00108020, 0x00000020, 0x00008000, 0x80000000,
|
|
||||||
0x00008020, 0x80108000, 0x00100000, 0x80000020,
|
|
||||||
0x00100020, 0x80008020, 0x80000020, 0x00100020,
|
|
||||||
0x00108000, 0x00000000, 0x80008000, 0x00008020,
|
|
||||||
0x80000000, 0x80100020, 0x80108020, 0x00108000
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32_t SB3[64] =
|
|
||||||
{
|
|
||||||
0x00000208, 0x08020200, 0x00000000, 0x08020008,
|
|
||||||
0x08000200, 0x00000000, 0x00020208, 0x08000200,
|
|
||||||
0x00020008, 0x08000008, 0x08000008, 0x00020000,
|
|
||||||
0x08020208, 0x00020008, 0x08020000, 0x00000208,
|
|
||||||
0x08000000, 0x00000008, 0x08020200, 0x00000200,
|
|
||||||
0x00020200, 0x08020000, 0x08020008, 0x00020208,
|
|
||||||
0x08000208, 0x00020200, 0x00020000, 0x08000208,
|
|
||||||
0x00000008, 0x08020208, 0x00000200, 0x08000000,
|
|
||||||
0x08020200, 0x08000000, 0x00020008, 0x00000208,
|
|
||||||
0x00020000, 0x08020200, 0x08000200, 0x00000000,
|
|
||||||
0x00000200, 0x00020008, 0x08020208, 0x08000200,
|
|
||||||
0x08000008, 0x00000200, 0x00000000, 0x08020008,
|
|
||||||
0x08000208, 0x00020000, 0x08000000, 0x08020208,
|
|
||||||
0x00000008, 0x00020208, 0x00020200, 0x08000008,
|
|
||||||
0x08020000, 0x08000208, 0x00000208, 0x08020000,
|
|
||||||
0x00020208, 0x00000008, 0x08020008, 0x00020200
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32_t SB4[64] =
|
|
||||||
{
|
|
||||||
0x00802001, 0x00002081, 0x00002081, 0x00000080,
|
|
||||||
0x00802080, 0x00800081, 0x00800001, 0x00002001,
|
|
||||||
0x00000000, 0x00802000, 0x00802000, 0x00802081,
|
|
||||||
0x00000081, 0x00000000, 0x00800080, 0x00800001,
|
|
||||||
0x00000001, 0x00002000, 0x00800000, 0x00802001,
|
|
||||||
0x00000080, 0x00800000, 0x00002001, 0x00002080,
|
|
||||||
0x00800081, 0x00000001, 0x00002080, 0x00800080,
|
|
||||||
0x00002000, 0x00802080, 0x00802081, 0x00000081,
|
|
||||||
0x00800080, 0x00800001, 0x00802000, 0x00802081,
|
|
||||||
0x00000081, 0x00000000, 0x00000000, 0x00802000,
|
|
||||||
0x00002080, 0x00800080, 0x00800081, 0x00000001,
|
|
||||||
0x00802001, 0x00002081, 0x00002081, 0x00000080,
|
|
||||||
0x00802081, 0x00000081, 0x00000001, 0x00002000,
|
|
||||||
0x00800001, 0x00002001, 0x00802080, 0x00800081,
|
|
||||||
0x00002001, 0x00002080, 0x00800000, 0x00802001,
|
|
||||||
0x00000080, 0x00800000, 0x00002000, 0x00802080
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32_t SB5[64] =
|
|
||||||
{
|
|
||||||
0x00000100, 0x02080100, 0x02080000, 0x42000100,
|
|
||||||
0x00080000, 0x00000100, 0x40000000, 0x02080000,
|
|
||||||
0x40080100, 0x00080000, 0x02000100, 0x40080100,
|
|
||||||
0x42000100, 0x42080000, 0x00080100, 0x40000000,
|
|
||||||
0x02000000, 0x40080000, 0x40080000, 0x00000000,
|
|
||||||
0x40000100, 0x42080100, 0x42080100, 0x02000100,
|
|
||||||
0x42080000, 0x40000100, 0x00000000, 0x42000000,
|
|
||||||
0x02080100, 0x02000000, 0x42000000, 0x00080100,
|
|
||||||
0x00080000, 0x42000100, 0x00000100, 0x02000000,
|
|
||||||
0x40000000, 0x02080000, 0x42000100, 0x40080100,
|
|
||||||
0x02000100, 0x40000000, 0x42080000, 0x02080100,
|
|
||||||
0x40080100, 0x00000100, 0x02000000, 0x42080000,
|
|
||||||
0x42080100, 0x00080100, 0x42000000, 0x42080100,
|
|
||||||
0x02080000, 0x00000000, 0x40080000, 0x42000000,
|
|
||||||
0x00080100, 0x02000100, 0x40000100, 0x00080000,
|
|
||||||
0x00000000, 0x40080000, 0x02080100, 0x40000100
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32_t SB6[64] =
|
|
||||||
{
|
|
||||||
0x20000010, 0x20400000, 0x00004000, 0x20404010,
|
|
||||||
0x20400000, 0x00000010, 0x20404010, 0x00400000,
|
|
||||||
0x20004000, 0x00404010, 0x00400000, 0x20000010,
|
|
||||||
0x00400010, 0x20004000, 0x20000000, 0x00004010,
|
|
||||||
0x00000000, 0x00400010, 0x20004010, 0x00004000,
|
|
||||||
0x00404000, 0x20004010, 0x00000010, 0x20400010,
|
|
||||||
0x20400010, 0x00000000, 0x00404010, 0x20404000,
|
|
||||||
0x00004010, 0x00404000, 0x20404000, 0x20000000,
|
|
||||||
0x20004000, 0x00000010, 0x20400010, 0x00404000,
|
|
||||||
0x20404010, 0x00400000, 0x00004010, 0x20000010,
|
|
||||||
0x00400000, 0x20004000, 0x20000000, 0x00004010,
|
|
||||||
0x20000010, 0x20404010, 0x00404000, 0x20400000,
|
|
||||||
0x00404010, 0x20404000, 0x00000000, 0x20400010,
|
|
||||||
0x00000010, 0x00004000, 0x20400000, 0x00404010,
|
|
||||||
0x00004000, 0x00400010, 0x20004010, 0x00000000,
|
|
||||||
0x20404000, 0x20000000, 0x00400010, 0x20004010
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32_t SB7[64] =
|
|
||||||
{
|
|
||||||
0x00200000, 0x04200002, 0x04000802, 0x00000000,
|
|
||||||
0x00000800, 0x04000802, 0x00200802, 0x04200800,
|
|
||||||
0x04200802, 0x00200000, 0x00000000, 0x04000002,
|
|
||||||
0x00000002, 0x04000000, 0x04200002, 0x00000802,
|
|
||||||
0x04000800, 0x00200802, 0x00200002, 0x04000800,
|
|
||||||
0x04000002, 0x04200000, 0x04200800, 0x00200002,
|
|
||||||
0x04200000, 0x00000800, 0x00000802, 0x04200802,
|
|
||||||
0x00200800, 0x00000002, 0x04000000, 0x00200800,
|
|
||||||
0x04000000, 0x00200800, 0x00200000, 0x04000802,
|
|
||||||
0x04000802, 0x04200002, 0x04200002, 0x00000002,
|
|
||||||
0x00200002, 0x04000000, 0x04000800, 0x00200000,
|
|
||||||
0x04200800, 0x00000802, 0x00200802, 0x04200800,
|
|
||||||
0x00000802, 0x04000002, 0x04200802, 0x04200000,
|
|
||||||
0x00200800, 0x00000000, 0x00000002, 0x04200802,
|
|
||||||
0x00000000, 0x00200802, 0x04200000, 0x00000800,
|
|
||||||
0x04000002, 0x04000800, 0x00000800, 0x00200002
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32_t SB8[64] =
|
|
||||||
{
|
|
||||||
0x10001040, 0x00001000, 0x00040000, 0x10041040,
|
|
||||||
0x10000000, 0x10001040, 0x00000040, 0x10000000,
|
|
||||||
0x00040040, 0x10040000, 0x10041040, 0x00041000,
|
|
||||||
0x10041000, 0x00041040, 0x00001000, 0x00000040,
|
|
||||||
0x10040000, 0x10000040, 0x10001000, 0x00001040,
|
|
||||||
0x00041000, 0x00040040, 0x10040040, 0x10041000,
|
|
||||||
0x00001040, 0x00000000, 0x00000000, 0x10040040,
|
|
||||||
0x10000040, 0x10001000, 0x00041040, 0x00040000,
|
|
||||||
0x00041040, 0x00040000, 0x10041000, 0x00001000,
|
|
||||||
0x00000040, 0x10040040, 0x00001000, 0x00041040,
|
|
||||||
0x10001000, 0x00000040, 0x10000040, 0x10040000,
|
|
||||||
0x10040040, 0x10000000, 0x00040000, 0x10001040,
|
|
||||||
0x00000000, 0x10041040, 0x00040040, 0x10000040,
|
|
||||||
0x10040000, 0x10001000, 0x10001040, 0x00000000,
|
|
||||||
0x10041040, 0x00041000, 0x00041000, 0x00001040,
|
|
||||||
0x00001040, 0x00040040, 0x10000000, 0x10041000
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PC1: left and right halves bit-swap
|
|
||||||
*/
|
|
||||||
static const uint32_t LHs[16] =
|
|
||||||
{
|
|
||||||
0x00000000, 0x00000001, 0x00000100, 0x00000101,
|
|
||||||
0x00010000, 0x00010001, 0x00010100, 0x00010101,
|
|
||||||
0x01000000, 0x01000001, 0x01000100, 0x01000101,
|
|
||||||
0x01010000, 0x01010001, 0x01010100, 0x01010101
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32_t RHs[16] =
|
|
||||||
{
|
|
||||||
0x00000000, 0x01000000, 0x00010000, 0x01010000,
|
|
||||||
0x00000100, 0x01000100, 0x00010100, 0x01010100,
|
|
||||||
0x00000001, 0x01000001, 0x00010001, 0x01010001,
|
|
||||||
0x00000101, 0x01000101, 0x00010101, 0x01010101,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Initial Permutation macro
|
|
||||||
*/
|
|
||||||
#define DES_IP(X,Y) \
|
|
||||||
{ \
|
|
||||||
T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \
|
|
||||||
T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \
|
|
||||||
T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \
|
|
||||||
T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \
|
|
||||||
Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \
|
|
||||||
T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \
|
|
||||||
X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Final Permutation macro
|
|
||||||
*/
|
|
||||||
#define DES_FP(X,Y) \
|
|
||||||
{ \
|
|
||||||
X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \
|
|
||||||
T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \
|
|
||||||
Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \
|
|
||||||
T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \
|
|
||||||
T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \
|
|
||||||
T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \
|
|
||||||
T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* DES round macro
|
|
||||||
*/
|
|
||||||
#define DES_ROUND(X,Y) \
|
|
||||||
{ \
|
|
||||||
T = *SK++ ^ X; \
|
|
||||||
Y ^= SB8[ (T ) & 0x3F ] ^ \
|
|
||||||
SB6[ (T >> 8) & 0x3F ] ^ \
|
|
||||||
SB4[ (T >> 16) & 0x3F ] ^ \
|
|
||||||
SB2[ (T >> 24) & 0x3F ]; \
|
|
||||||
\
|
|
||||||
T = *SK++ ^ ((X << 28) | (X >> 4)); \
|
|
||||||
Y ^= SB7[ (T ) & 0x3F ] ^ \
|
|
||||||
SB5[ (T >> 8) & 0x3F ] ^ \
|
|
||||||
SB3[ (T >> 16) & 0x3F ] ^ \
|
|
||||||
SB1[ (T >> 24) & 0x3F ]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SWAP(a,b) { uint32_t t = a; a = b; b = t; t = 0; }
|
|
||||||
|
|
||||||
void mbedtls_des_sw_init( mbedtls_des_sw_context *ctx )
|
|
||||||
{
|
|
||||||
memset( ctx, 0, sizeof( mbedtls_des_sw_context ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void mbedtls_des_sw_free( mbedtls_des_sw_context *ctx )
|
|
||||||
{
|
|
||||||
if( ctx == NULL )
|
|
||||||
return;
|
|
||||||
|
|
||||||
mbedtls_zeroize( ctx, sizeof( mbedtls_des_sw_context ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void mbedtls_des3_sw_init( mbedtls_des3_sw_context *ctx )
|
|
||||||
{
|
|
||||||
memset( ctx, 0, sizeof( mbedtls_des3_sw_context ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void mbedtls_des3_sw_free( mbedtls_des3_sw_context *ctx )
|
|
||||||
{
|
|
||||||
if( ctx == NULL )
|
|
||||||
return;
|
|
||||||
|
|
||||||
mbedtls_zeroize( ctx, sizeof( mbedtls_des3_sw_context ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8,
|
|
||||||
11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44,
|
|
||||||
47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81,
|
|
||||||
82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112,
|
|
||||||
115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140,
|
|
||||||
143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168,
|
|
||||||
171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196,
|
|
||||||
199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224,
|
|
||||||
227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253,
|
|
||||||
254 };
|
|
||||||
|
|
||||||
void mbedtls_des_sw_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ )
|
|
||||||
key[i] = odd_parity_table[key[i] / 2];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check the given key's parity, returns 1 on failure, 0 on SUCCESS
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ )
|
|
||||||
if( key[i] != odd_parity_table[key[i] / 2] )
|
|
||||||
return( 1 );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Table of weak and semi-weak keys
|
|
||||||
*
|
|
||||||
* Source: http://en.wikipedia.org/wiki/Weak_key
|
|
||||||
*
|
|
||||||
* Weak:
|
|
||||||
* Alternating ones + zeros (0x0101010101010101)
|
|
||||||
* Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE)
|
|
||||||
* '0xE0E0E0E0F1F1F1F1'
|
|
||||||
* '0x1F1F1F1F0E0E0E0E'
|
|
||||||
*
|
|
||||||
* Semi-weak:
|
|
||||||
* 0x011F011F010E010E and 0x1F011F010E010E01
|
|
||||||
* 0x01E001E001F101F1 and 0xE001E001F101F101
|
|
||||||
* 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01
|
|
||||||
* 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E
|
|
||||||
* 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E
|
|
||||||
* 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define WEAK_KEY_COUNT 16
|
|
||||||
|
|
||||||
static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] =
|
|
||||||
{
|
|
||||||
{ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
|
|
||||||
{ 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },
|
|
||||||
{ 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },
|
|
||||||
{ 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 },
|
|
||||||
|
|
||||||
{ 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E },
|
|
||||||
{ 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 },
|
|
||||||
{ 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 },
|
|
||||||
{ 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 },
|
|
||||||
{ 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE },
|
|
||||||
{ 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 },
|
|
||||||
{ 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 },
|
|
||||||
{ 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E },
|
|
||||||
{ 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE },
|
|
||||||
{ 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E },
|
|
||||||
{ 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE },
|
|
||||||
{ 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 }
|
|
||||||
};
|
|
||||||
|
|
||||||
int mbedtls_des_sw_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for( i = 0; i < WEAK_KEY_COUNT; i++ )
|
|
||||||
if( memcmp( weak_key_table[i], key, MBEDTLS_DES_KEY_SIZE) == 0 )
|
|
||||||
return( 1 );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void mbedtls_des_setkey( uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
uint32_t X, Y, T;
|
|
||||||
|
|
||||||
GET_UINT32_BE( X, key, 0 );
|
|
||||||
GET_UINT32_BE( Y, key, 4 );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Permuted Choice 1
|
|
||||||
*/
|
|
||||||
T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4);
|
|
||||||
T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T );
|
|
||||||
|
|
||||||
X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2)
|
|
||||||
| (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] )
|
|
||||||
| (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6)
|
|
||||||
| (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4);
|
|
||||||
|
|
||||||
Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2)
|
|
||||||
| (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] )
|
|
||||||
| (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6)
|
|
||||||
| (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4);
|
|
||||||
|
|
||||||
X &= 0x0FFFFFFF;
|
|
||||||
Y &= 0x0FFFFFFF;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* calculate subkeys
|
|
||||||
*/
|
|
||||||
for( i = 0; i < 16; i++ )
|
|
||||||
{
|
|
||||||
if( i < 2 || i == 8 || i == 15 )
|
|
||||||
{
|
|
||||||
X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF;
|
|
||||||
Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF;
|
|
||||||
Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
*SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000)
|
|
||||||
| ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000)
|
|
||||||
| ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000)
|
|
||||||
| ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000)
|
|
||||||
| ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000)
|
|
||||||
| ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000)
|
|
||||||
| ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400)
|
|
||||||
| ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100)
|
|
||||||
| ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010)
|
|
||||||
| ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004)
|
|
||||||
| ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001);
|
|
||||||
|
|
||||||
*SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000)
|
|
||||||
| ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000)
|
|
||||||
| ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000)
|
|
||||||
| ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000)
|
|
||||||
| ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000)
|
|
||||||
| ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000)
|
|
||||||
| ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000)
|
|
||||||
| ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400)
|
|
||||||
| ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100)
|
|
||||||
| ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011)
|
|
||||||
| ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* DES key schedule (56-bit, encryption)
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_setkey_enc( mbedtls_des_sw_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
|
|
||||||
{
|
|
||||||
mbedtls_des_setkey( ctx->sk, key );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* DES key schedule (56-bit, decryption)
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_setkey_dec( mbedtls_des_sw_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
mbedtls_des_setkey( ctx->sk, key );
|
|
||||||
|
|
||||||
for( i = 0; i < 16; i += 2 )
|
|
||||||
{
|
|
||||||
SWAP( ctx->sk[i ], ctx->sk[30 - i] );
|
|
||||||
SWAP( ctx->sk[i + 1], ctx->sk[31 - i] );
|
|
||||||
}
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void des3_set2key( uint32_t esk[96],
|
|
||||||
uint32_t dsk[96],
|
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE*2] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
mbedtls_des_setkey( esk, key );
|
|
||||||
mbedtls_des_setkey( dsk + 32, key + 8 );
|
|
||||||
|
|
||||||
for( i = 0; i < 32; i += 2 )
|
|
||||||
{
|
|
||||||
dsk[i ] = esk[30 - i];
|
|
||||||
dsk[i + 1] = esk[31 - i];
|
|
||||||
|
|
||||||
esk[i + 32] = dsk[62 - i];
|
|
||||||
esk[i + 33] = dsk[63 - i];
|
|
||||||
|
|
||||||
esk[i + 64] = esk[i ];
|
|
||||||
esk[i + 65] = esk[i + 1];
|
|
||||||
|
|
||||||
dsk[i + 64] = dsk[i ];
|
|
||||||
dsk[i + 65] = dsk[i + 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Triple-DES key schedule (112-bit, encryption)
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_set2key_enc( mbedtls_des3_sw_context *ctx,
|
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] )
|
|
||||||
{
|
|
||||||
uint32_t sk[96];
|
|
||||||
|
|
||||||
des3_set2key( ctx->sk, sk, key );
|
|
||||||
mbedtls_zeroize( sk, sizeof( sk ) );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Triple-DES key schedule (112-bit, decryption)
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_set2key_dec( mbedtls_des3_sw_context *ctx,
|
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] )
|
|
||||||
{
|
|
||||||
uint32_t sk[96];
|
|
||||||
|
|
||||||
des3_set2key( sk, ctx->sk, key );
|
|
||||||
mbedtls_zeroize( sk, sizeof( sk ) );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void des3_set3key( uint32_t esk[96],
|
|
||||||
uint32_t dsk[96],
|
|
||||||
const unsigned char key[24] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
mbedtls_des_setkey( esk, key );
|
|
||||||
mbedtls_des_setkey( dsk + 32, key + 8 );
|
|
||||||
mbedtls_des_setkey( esk + 64, key + 16 );
|
|
||||||
|
|
||||||
for( i = 0; i < 32; i += 2 )
|
|
||||||
{
|
|
||||||
dsk[i ] = esk[94 - i];
|
|
||||||
dsk[i + 1] = esk[95 - i];
|
|
||||||
|
|
||||||
esk[i + 32] = dsk[62 - i];
|
|
||||||
esk[i + 33] = dsk[63 - i];
|
|
||||||
|
|
||||||
dsk[i + 64] = esk[30 - i];
|
|
||||||
dsk[i + 65] = esk[31 - i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Triple-DES key schedule (168-bit, encryption)
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_set3key_enc( mbedtls_des3_sw_context *ctx,
|
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] )
|
|
||||||
{
|
|
||||||
uint32_t sk[96];
|
|
||||||
|
|
||||||
des3_set3key( ctx->sk, sk, key );
|
|
||||||
mbedtls_zeroize( sk, sizeof( sk ) );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Triple-DES key schedule (168-bit, decryption)
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_set3key_dec( mbedtls_des3_sw_context *ctx,
|
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] )
|
|
||||||
{
|
|
||||||
uint32_t sk[96];
|
|
||||||
|
|
||||||
des3_set3key( sk, ctx->sk, key );
|
|
||||||
mbedtls_zeroize( sk, sizeof( sk ) );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* DES-ECB block encryption/decryption
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_crypt_ecb( mbedtls_des_sw_context *ctx,
|
|
||||||
const unsigned char input[8],
|
|
||||||
unsigned char output[8] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
uint32_t X, Y, T, *SK;
|
|
||||||
|
|
||||||
SK = ctx->sk;
|
|
||||||
|
|
||||||
GET_UINT32_BE( X, input, 0 );
|
|
||||||
GET_UINT32_BE( Y, input, 4 );
|
|
||||||
|
|
||||||
DES_IP( X, Y );
|
|
||||||
|
|
||||||
for( i = 0; i < 8; i++ )
|
|
||||||
{
|
|
||||||
DES_ROUND( Y, X );
|
|
||||||
DES_ROUND( X, Y );
|
|
||||||
}
|
|
||||||
|
|
||||||
DES_FP( Y, X );
|
|
||||||
|
|
||||||
PUT_UINT32_BE( Y, output, 0 );
|
|
||||||
PUT_UINT32_BE( X, output, 4 );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
|
||||||
/*
|
|
||||||
* DES-CBC buffer encryption/decryption
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_crypt_cbc( mbedtls_des_sw_context *ctx,
|
|
||||||
int mode,
|
|
||||||
size_t length,
|
|
||||||
unsigned char iv[8],
|
|
||||||
const unsigned char *input,
|
|
||||||
unsigned char *output )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
unsigned char temp[8];
|
|
||||||
|
|
||||||
if( length % 8 )
|
|
||||||
return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH );
|
|
||||||
|
|
||||||
if( mode == MBEDTLS_DES_ENCRYPT )
|
|
||||||
{
|
|
||||||
while( length > 0 )
|
|
||||||
{
|
|
||||||
for( i = 0; i < 8; i++ )
|
|
||||||
output[i] = (unsigned char)( input[i] ^ iv[i] );
|
|
||||||
|
|
||||||
mbedtls_des_sw_crypt_ecb( ctx, output, output );
|
|
||||||
memcpy( iv, output, 8 );
|
|
||||||
|
|
||||||
input += 8;
|
|
||||||
output += 8;
|
|
||||||
length -= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* MBEDTLS_DES_DECRYPT */
|
|
||||||
{
|
|
||||||
while( length > 0 )
|
|
||||||
{
|
|
||||||
memcpy( temp, input, 8 );
|
|
||||||
mbedtls_des_sw_crypt_ecb( ctx, input, output );
|
|
||||||
|
|
||||||
for( i = 0; i < 8; i++ )
|
|
||||||
output[i] = (unsigned char)( output[i] ^ iv[i] );
|
|
||||||
|
|
||||||
memcpy( iv, temp, 8 );
|
|
||||||
|
|
||||||
input += 8;
|
|
||||||
output += 8;
|
|
||||||
length -= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 3DES-ECB block encryption/decryption
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_crypt_ecb( mbedtls_des3_sw_context *ctx,
|
|
||||||
const unsigned char input[8],
|
|
||||||
unsigned char output[8] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
uint32_t X, Y, T, *SK;
|
|
||||||
|
|
||||||
SK = ctx->sk;
|
|
||||||
|
|
||||||
GET_UINT32_BE( X, input, 0 );
|
|
||||||
GET_UINT32_BE( Y, input, 4 );
|
|
||||||
|
|
||||||
DES_IP( X, Y );
|
|
||||||
|
|
||||||
for( i = 0; i < 8; i++ )
|
|
||||||
{
|
|
||||||
DES_ROUND( Y, X );
|
|
||||||
DES_ROUND( X, Y );
|
|
||||||
}
|
|
||||||
|
|
||||||
for( i = 0; i < 8; i++ )
|
|
||||||
{
|
|
||||||
DES_ROUND( X, Y );
|
|
||||||
DES_ROUND( Y, X );
|
|
||||||
}
|
|
||||||
|
|
||||||
for( i = 0; i < 8; i++ )
|
|
||||||
{
|
|
||||||
DES_ROUND( Y, X );
|
|
||||||
DES_ROUND( X, Y );
|
|
||||||
}
|
|
||||||
|
|
||||||
DES_FP( Y, X );
|
|
||||||
|
|
||||||
PUT_UINT32_BE( Y, output, 0 );
|
|
||||||
PUT_UINT32_BE( X, output, 4 );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
|
||||||
/*
|
|
||||||
* 3DES-CBC buffer encryption/decryption
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_crypt_cbc( mbedtls_des3_sw_context *ctx,
|
|
||||||
int mode,
|
|
||||||
size_t length,
|
|
||||||
unsigned char iv[8],
|
|
||||||
const unsigned char *input,
|
|
||||||
unsigned char *output )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
unsigned char temp[8];
|
|
||||||
|
|
||||||
if( length % 8 )
|
|
||||||
return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH );
|
|
||||||
|
|
||||||
if( mode == MBEDTLS_DES_ENCRYPT )
|
|
||||||
{
|
|
||||||
while( length > 0 )
|
|
||||||
{
|
|
||||||
for( i = 0; i < 8; i++ )
|
|
||||||
output[i] = (unsigned char)( input[i] ^ iv[i] );
|
|
||||||
|
|
||||||
mbedtls_des3_sw_crypt_ecb( ctx, output, output );
|
|
||||||
memcpy( iv, output, 8 );
|
|
||||||
|
|
||||||
input += 8;
|
|
||||||
output += 8;
|
|
||||||
length -= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* MBEDTLS_DES_DECRYPT */
|
|
||||||
{
|
|
||||||
while( length > 0 )
|
|
||||||
{
|
|
||||||
memcpy( temp, input, 8 );
|
|
||||||
mbedtls_des3_sw_crypt_ecb( ctx, input, output );
|
|
||||||
|
|
||||||
for( i = 0; i < 8; i++ )
|
|
||||||
output[i] = (unsigned char)( output[i] ^ iv[i] );
|
|
||||||
|
|
||||||
memcpy( iv, temp, 8 );
|
|
||||||
|
|
||||||
input += 8;
|
|
||||||
output += 8;
|
|
||||||
length -= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
|
||||||
|
|
||||||
#endif /* MBEDTLS_DES_ALT */
|
|
||||||
#endif /* MBEDTLS_DES_C */
|
|
|
@ -1,283 +0,0 @@
|
||||||
/**
|
|
||||||
* \file des.h
|
|
||||||
*
|
|
||||||
* \brief DES block cipher
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*
|
|
||||||
* 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 is part of mbed TLS (https://tls.mbed.org)
|
|
||||||
*/
|
|
||||||
#ifndef MBEDTLS_DES_ALT_SW_H
|
|
||||||
#define MBEDTLS_DES_ALT_SW_H
|
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
|
||||||
#include "config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_DES_C)
|
|
||||||
#if defined(MBEDTLS_DES_ALT)
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief DES context structure
|
|
||||||
*/
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint32_t sk[32]; /*!< DES subkeys */
|
|
||||||
}
|
|
||||||
mbedtls_des_sw_context;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Triple-DES context structure
|
|
||||||
*/
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint32_t sk[96]; /*!< 3DES subkeys */
|
|
||||||
}
|
|
||||||
mbedtls_des3_sw_context;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Initialize DES context
|
|
||||||
*
|
|
||||||
* \param ctx DES context to be initialized
|
|
||||||
*/
|
|
||||||
void mbedtls_des_sw_init( mbedtls_des_sw_context *ctx );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Clear DES context
|
|
||||||
*
|
|
||||||
* \param ctx DES context to be cleared
|
|
||||||
*/
|
|
||||||
void mbedtls_des_sw_free( mbedtls_des_sw_context *ctx );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Initialize Triple-DES context
|
|
||||||
*
|
|
||||||
* \param ctx DES3 context to be initialized
|
|
||||||
*/
|
|
||||||
void mbedtls_des3_sw_init( mbedtls_des3_sw_context *ctx );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Clear Triple-DES context
|
|
||||||
*
|
|
||||||
* \param ctx DES3 context to be cleared
|
|
||||||
*/
|
|
||||||
void mbedtls_des3_sw_free( mbedtls_des3_sw_context *ctx );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Set key parity on the given key to odd.
|
|
||||||
*
|
|
||||||
* DES keys are 56 bits long, but each byte is padded with
|
|
||||||
* a parity bit to allow verification.
|
|
||||||
*
|
|
||||||
* \param key 8-byte secret key
|
|
||||||
*/
|
|
||||||
void mbedtls_des_sw_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Check that key parity on the given key is odd.
|
|
||||||
*
|
|
||||||
* DES keys are 56 bits long, but each byte is padded with
|
|
||||||
* a parity bit to allow verification.
|
|
||||||
*
|
|
||||||
* \param key 8-byte secret key
|
|
||||||
*
|
|
||||||
* \return 0 is parity was ok, 1 if parity was not correct.
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Check that key is not a weak or semi-weak DES key
|
|
||||||
*
|
|
||||||
* \param key 8-byte secret key
|
|
||||||
*
|
|
||||||
* \return 0 if no weak key was found, 1 if a weak key was identified.
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief DES key schedule (56-bit, encryption)
|
|
||||||
*
|
|
||||||
* \param ctx DES context to be initialized
|
|
||||||
* \param key 8-byte secret key
|
|
||||||
*
|
|
||||||
* \return 0
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_setkey_enc( mbedtls_des_sw_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief DES key schedule (56-bit, decryption)
|
|
||||||
*
|
|
||||||
* \param ctx DES context to be initialized
|
|
||||||
* \param key 8-byte secret key
|
|
||||||
*
|
|
||||||
* \return 0
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_setkey_dec( mbedtls_des_sw_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Triple-DES key schedule (112-bit, encryption)
|
|
||||||
*
|
|
||||||
* \param ctx 3DES context to be initialized
|
|
||||||
* \param key 16-byte secret key
|
|
||||||
*
|
|
||||||
* \return 0
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_set2key_enc( mbedtls_des3_sw_context *ctx,
|
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Triple-DES key schedule (112-bit, decryption)
|
|
||||||
*
|
|
||||||
* \param ctx 3DES context to be initialized
|
|
||||||
* \param key 16-byte secret key
|
|
||||||
*
|
|
||||||
* \return 0
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_set2key_dec( mbedtls_des3_sw_context *ctx,
|
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Triple-DES key schedule (168-bit, encryption)
|
|
||||||
*
|
|
||||||
* \param ctx 3DES context to be initialized
|
|
||||||
* \param key 24-byte secret key
|
|
||||||
*
|
|
||||||
* \return 0
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_set3key_enc( mbedtls_des3_sw_context *ctx,
|
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Triple-DES key schedule (168-bit, decryption)
|
|
||||||
*
|
|
||||||
* \param ctx 3DES context to be initialized
|
|
||||||
* \param key 24-byte secret key
|
|
||||||
*
|
|
||||||
* \return 0
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_set3key_dec( mbedtls_des3_sw_context *ctx,
|
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief DES-ECB block encryption/decryption
|
|
||||||
*
|
|
||||||
* \param ctx DES context
|
|
||||||
* \param input 64-bit input block
|
|
||||||
* \param output 64-bit output block
|
|
||||||
*
|
|
||||||
* \return 0 if successful
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_crypt_ecb( mbedtls_des_sw_context *ctx,
|
|
||||||
const unsigned char input[8],
|
|
||||||
unsigned char output[8] );
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
|
||||||
/**
|
|
||||||
* \brief DES-CBC buffer encryption/decryption
|
|
||||||
*
|
|
||||||
* \note Upon exit, the content of the IV is updated so that you can
|
|
||||||
* call the function same function again on the following
|
|
||||||
* block(s) of data and get the same result as if it was
|
|
||||||
* encrypted in one call. This allows a "streaming" usage.
|
|
||||||
* If on the other hand you need to retain the contents of the
|
|
||||||
* IV, you should either save it manually or use the cipher
|
|
||||||
* module instead.
|
|
||||||
*
|
|
||||||
* \param ctx DES context
|
|
||||||
* \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT
|
|
||||||
* \param length length of the input data
|
|
||||||
* \param iv initialization vector (updated after use)
|
|
||||||
* \param input buffer holding the input data
|
|
||||||
* \param output buffer holding the output data
|
|
||||||
*/
|
|
||||||
int mbedtls_des_sw_crypt_cbc( mbedtls_des_sw_context *ctx,
|
|
||||||
int mode,
|
|
||||||
size_t length,
|
|
||||||
unsigned char iv[8],
|
|
||||||
const unsigned char *input,
|
|
||||||
unsigned char *output );
|
|
||||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief 3DES-ECB block encryption/decryption
|
|
||||||
*
|
|
||||||
* \param ctx 3DES context
|
|
||||||
* \param input 64-bit input block
|
|
||||||
* \param output 64-bit output block
|
|
||||||
*
|
|
||||||
* \return 0 if successful
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_crypt_ecb( mbedtls_des3_sw_context *ctx,
|
|
||||||
const unsigned char input[8],
|
|
||||||
unsigned char output[8] );
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
|
||||||
/**
|
|
||||||
* \brief 3DES-CBC buffer encryption/decryption
|
|
||||||
*
|
|
||||||
* \note Upon exit, the content of the IV is updated so that you can
|
|
||||||
* call the function same function again on the following
|
|
||||||
* block(s) of data and get the same result as if it was
|
|
||||||
* encrypted in one call. This allows a "streaming" usage.
|
|
||||||
* If on the other hand you need to retain the contents of the
|
|
||||||
* IV, you should either save it manually or use the cipher
|
|
||||||
* module instead.
|
|
||||||
*
|
|
||||||
* \param ctx 3DES context
|
|
||||||
* \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT
|
|
||||||
* \param length length of the input data
|
|
||||||
* \param iv initialization vector (updated after use)
|
|
||||||
* \param input buffer holding the input data
|
|
||||||
* \param output buffer holding the output data
|
|
||||||
*
|
|
||||||
* \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH
|
|
||||||
*/
|
|
||||||
int mbedtls_des3_sw_crypt_cbc( mbedtls_des3_sw_context *ctx,
|
|
||||||
int mode,
|
|
||||||
size_t length,
|
|
||||||
unsigned char iv[8],
|
|
||||||
const unsigned char *input,
|
|
||||||
unsigned char *output );
|
|
||||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Internal function for key expansion.
|
|
||||||
* (Only exposed to allow overriding it,
|
|
||||||
* see MBEDTLS_DES_SETKEY_ALT)
|
|
||||||
*
|
|
||||||
* \param SK Round keys
|
|
||||||
* \param key Base key
|
|
||||||
*/
|
|
||||||
void mbedtls_des_sw_setkey( uint32_t SK[32],
|
|
||||||
const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* MBEDTLS_DES_ALT */
|
|
||||||
#endif /* MBEDTLS_DES_C */
|
|
||||||
|
|
||||||
#endif /* des.h */
|
|
|
@ -14,53 +14,69 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/sha1.h"
|
||||||
#include "mbedtls/config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA1_C)
|
#if defined(MBEDTLS_SHA1_C)
|
||||||
#if defined(MBEDTLS_SHA1_ALT)
|
#if defined(MBEDTLS_SHA1_ALT)
|
||||||
|
|
||||||
#include "sha1_alt.h"
|
|
||||||
#include "crypto-misc.h"
|
#include "crypto-misc.h"
|
||||||
#include "nu_bitutil.h"
|
#include "nu_bitutil.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
void mbedtls_sha1_init(mbedtls_sha1_context *ctx)
|
/* Choose SHA S/W or H/W context and initialize it
|
||||||
|
*
|
||||||
|
* try_hw:
|
||||||
|
* 0: Initialize S/W context
|
||||||
|
* 1: Try acquiring SHA H/W resource first and initialize its H/W context if successful. If failed, initialize S/W context.
|
||||||
|
*/
|
||||||
|
static void mbedtls_sha1_init_internal(mbedtls_sha1_context *ctx, int try_hw)
|
||||||
{
|
{
|
||||||
if (crypto_sha_acquire()) {
|
if (try_hw && crypto_sha_acquire()) {
|
||||||
ctx->ishw = 1;
|
ctx->active_ctx = &ctx->hw_ctx;
|
||||||
mbedtls_sha1_hw_init(&ctx->hw_ctx);
|
mbedtls_sha1_hw_init(&ctx->hw_ctx);
|
||||||
}
|
} else {
|
||||||
else {
|
ctx->active_ctx = &ctx->sw_ctx;
|
||||||
ctx->ishw = 0;
|
|
||||||
mbedtls_sha1_sw_init(&ctx->sw_ctx);
|
mbedtls_sha1_sw_init(&ctx->sw_ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mbedtls_sha1_init(mbedtls_sha1_context *ctx)
|
||||||
|
{
|
||||||
|
mbedtls_sha1_init_internal(ctx, 1);
|
||||||
|
}
|
||||||
|
|
||||||
void mbedtls_sha1_free(mbedtls_sha1_context *ctx)
|
void mbedtls_sha1_free(mbedtls_sha1_context *ctx)
|
||||||
{
|
{
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha1_hw_free(&ctx->hw_ctx);
|
mbedtls_sha1_hw_free(&ctx->hw_ctx);
|
||||||
crypto_sha_release();
|
crypto_sha_release();
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha1_sw_free(&ctx->sw_ctx);
|
mbedtls_sha1_sw_free(&ctx->sw_ctx);
|
||||||
}
|
}
|
||||||
|
ctx->active_ctx = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha1_clone(mbedtls_sha1_context *dst,
|
void mbedtls_sha1_clone(mbedtls_sha1_context *dst,
|
||||||
const mbedtls_sha1_context *src)
|
const mbedtls_sha1_context *src)
|
||||||
{
|
{
|
||||||
if (src->ishw) {
|
// Corner case: Destination/source contexts are the same
|
||||||
|
if (dst == src) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If dst is H/W context, we need to change it to S/W context first before cloning to.
|
||||||
|
if (dst->active_ctx == &dst->hw_ctx) {
|
||||||
|
mbedtls_sha1_free(dst);
|
||||||
|
// Force S/W context
|
||||||
|
mbedtls_sha1_init_internal(dst, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src->active_ctx == &src->hw_ctx) {
|
||||||
// Clone S/W ctx from H/W ctx
|
// Clone S/W ctx from H/W ctx
|
||||||
dst->ishw = 0;
|
|
||||||
dst->sw_ctx.total[0] = src->hw_ctx.total;
|
dst->sw_ctx.total[0] = src->hw_ctx.total;
|
||||||
dst->sw_ctx.total[1] = 0;
|
dst->sw_ctx.total[1] = 0;
|
||||||
{
|
{
|
||||||
|
@ -78,8 +94,7 @@ void mbedtls_sha1_clone(mbedtls_sha1_context *dst,
|
||||||
if (src->hw_ctx.buffer_left == src->hw_ctx.blocksize) {
|
if (src->hw_ctx.buffer_left == src->hw_ctx.blocksize) {
|
||||||
mbedtls_sha1_sw_process(&dst->sw_ctx, dst->sw_ctx.buffer);
|
mbedtls_sha1_sw_process(&dst->sw_ctx, dst->sw_ctx.buffer);
|
||||||
}
|
}
|
||||||
}
|
} else if (src->active_ctx == &src->sw_ctx) {
|
||||||
else {
|
|
||||||
// Clone S/W ctx from S/W ctx
|
// Clone S/W ctx from S/W ctx
|
||||||
dst->sw_ctx = src->sw_ctx;
|
dst->sw_ctx = src->sw_ctx;
|
||||||
}
|
}
|
||||||
|
@ -90,10 +105,9 @@ void mbedtls_sha1_clone(mbedtls_sha1_context *dst,
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha1_starts(mbedtls_sha1_context *ctx)
|
void mbedtls_sha1_starts(mbedtls_sha1_context *ctx)
|
||||||
{
|
{
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha1_hw_starts(&ctx->hw_ctx);
|
mbedtls_sha1_hw_starts(&ctx->hw_ctx);
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha1_sw_starts(&ctx->sw_ctx);
|
mbedtls_sha1_sw_starts(&ctx->sw_ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,10 +117,9 @@ void mbedtls_sha1_starts(mbedtls_sha1_context *ctx)
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha1_update(mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen)
|
void mbedtls_sha1_update(mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen)
|
||||||
{
|
{
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha1_hw_update(&ctx->hw_ctx, input, ilen);
|
mbedtls_sha1_hw_update(&ctx->hw_ctx, input, ilen);
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha1_sw_update(&ctx->sw_ctx, input, ilen);
|
mbedtls_sha1_sw_update(&ctx->sw_ctx, input, ilen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,20 +129,18 @@ void mbedtls_sha1_update(mbedtls_sha1_context *ctx, const unsigned char *input,
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha1_finish(mbedtls_sha1_context *ctx, unsigned char output[20])
|
void mbedtls_sha1_finish(mbedtls_sha1_context *ctx, unsigned char output[20])
|
||||||
{
|
{
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha1_hw_finish(&ctx->hw_ctx, output);
|
mbedtls_sha1_hw_finish(&ctx->hw_ctx, output);
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha1_sw_finish(&ctx->sw_ctx, output);
|
mbedtls_sha1_sw_finish(&ctx->sw_ctx, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha1_process(mbedtls_sha1_context *ctx, const unsigned char data[64])
|
void mbedtls_sha1_process(mbedtls_sha1_context *ctx, const unsigned char data[64])
|
||||||
{
|
{
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha1_hw_process(&ctx->hw_ctx, data);
|
mbedtls_sha1_hw_process(&ctx->hw_ctx, data);
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha1_sw_process(&ctx->sw_ctx, data);
|
mbedtls_sha1_sw_process(&ctx->sw_ctx, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,13 +16,8 @@
|
||||||
#ifndef MBEDTLS_SHA1_ALT_H
|
#ifndef MBEDTLS_SHA1_ALT_H
|
||||||
#define MBEDTLS_SHA1_ALT_H
|
#define MBEDTLS_SHA1_ALT_H
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/sha1.h"
|
||||||
#include "config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA1_C)
|
|
||||||
#if defined(MBEDTLS_SHA1_ALT)
|
#if defined(MBEDTLS_SHA1_ALT)
|
||||||
|
|
||||||
#include "sha_alt_hw.h"
|
#include "sha_alt_hw.h"
|
||||||
|
@ -37,9 +32,8 @@ struct mbedtls_sha1_context_s;
|
||||||
/**
|
/**
|
||||||
* \brief SHA-1 context structure
|
* \brief SHA-1 context structure
|
||||||
*/
|
*/
|
||||||
typedef struct mbedtls_sha1_context_s
|
typedef struct mbedtls_sha1_context_s {
|
||||||
{
|
void *active_ctx;
|
||||||
int ishw;
|
|
||||||
crypto_sha_context hw_ctx;
|
crypto_sha_context hw_ctx;
|
||||||
mbedtls_sha1_sw_context sw_ctx;
|
mbedtls_sha1_sw_context sw_ctx;
|
||||||
}
|
}
|
||||||
|
@ -100,6 +94,5 @@ void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[6
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* MBEDTLS_SHA1_ALT */
|
#endif /* MBEDTLS_SHA1_ALT */
|
||||||
#endif /* MBEDTLS_SHA1_C */
|
|
||||||
|
|
||||||
#endif /* sha1_alt.h */
|
#endif /* sha1_alt.h */
|
||||||
|
|
|
@ -24,17 +24,11 @@
|
||||||
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
|
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/sha1.h"
|
||||||
#include "mbedtls/config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA1_C)
|
#if defined(MBEDTLS_SHA1_C)
|
||||||
#if defined(MBEDTLS_SHA1_ALT)
|
#if defined(MBEDTLS_SHA1_ALT)
|
||||||
|
|
||||||
#include "mbedtls/sha1.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#if defined(MBEDTLS_SELF_TEST)
|
#if defined(MBEDTLS_SELF_TEST)
|
||||||
#if defined(MBEDTLS_PLATFORM_C)
|
#if defined(MBEDTLS_PLATFORM_C)
|
||||||
|
@ -46,8 +40,10 @@
|
||||||
#endif /* MBEDTLS_SELF_TEST */
|
#endif /* MBEDTLS_SELF_TEST */
|
||||||
|
|
||||||
/* Implementation that should never be optimized out by the compiler */
|
/* Implementation that should never be optimized out by the compiler */
|
||||||
static void mbedtls_zeroize( void *v, size_t n ) {
|
static void mbedtls_zeroize( void *v, size_t n )
|
||||||
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
|
{
|
||||||
|
volatile unsigned char *p = (unsigned char*)v;
|
||||||
|
while( n-- ) *p++ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -87,7 +83,7 @@ void mbedtls_sha1_sw_free( mbedtls_sha1_sw_context *ctx )
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha1_sw_clone( mbedtls_sha1_sw_context *dst,
|
void mbedtls_sha1_sw_clone( mbedtls_sha1_sw_context *dst,
|
||||||
const mbedtls_sha1_sw_context *src )
|
const mbedtls_sha1_sw_context *src )
|
||||||
{
|
{
|
||||||
*dst = *src;
|
*dst = *src;
|
||||||
}
|
}
|
||||||
|
@ -283,8 +279,7 @@ void mbedtls_sha1_sw_update( mbedtls_sha1_sw_context *ctx, const unsigned char *
|
||||||
if( ctx->total[0] < (uint32_t) ilen )
|
if( ctx->total[0] < (uint32_t) ilen )
|
||||||
ctx->total[1]++;
|
ctx->total[1]++;
|
||||||
|
|
||||||
if( left && ilen >= fill )
|
if( left && ilen >= fill ) {
|
||||||
{
|
|
||||||
memcpy( (void *) (ctx->buffer + left), input, fill );
|
memcpy( (void *) (ctx->buffer + left), input, fill );
|
||||||
mbedtls_sha1_sw_process( ctx, ctx->buffer );
|
mbedtls_sha1_sw_process( ctx, ctx->buffer );
|
||||||
input += fill;
|
input += fill;
|
||||||
|
@ -292,8 +287,7 @@ void mbedtls_sha1_sw_update( mbedtls_sha1_sw_context *ctx, const unsigned char *
|
||||||
left = 0;
|
left = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while( ilen >= 64 )
|
while( ilen >= 64 ) {
|
||||||
{
|
|
||||||
mbedtls_sha1_sw_process( ctx, input );
|
mbedtls_sha1_sw_process( ctx, input );
|
||||||
input += 64;
|
input += 64;
|
||||||
ilen -= 64;
|
ilen -= 64;
|
||||||
|
@ -303,9 +297,8 @@ void mbedtls_sha1_sw_update( mbedtls_sha1_sw_context *ctx, const unsigned char *
|
||||||
memcpy( (void *) (ctx->buffer + left), input, ilen );
|
memcpy( (void *) (ctx->buffer + left), input, ilen );
|
||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned char sha1_padding[64] =
|
static const unsigned char sha1_padding[64] = {
|
||||||
{
|
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
@ -321,7 +314,7 @@ void mbedtls_sha1_sw_finish( mbedtls_sha1_sw_context *ctx, unsigned char output[
|
||||||
unsigned char msglen[8];
|
unsigned char msglen[8];
|
||||||
|
|
||||||
high = ( ctx->total[0] >> 29 )
|
high = ( ctx->total[0] >> 29 )
|
||||||
| ( ctx->total[1] << 3 );
|
| ( ctx->total[1] << 3 );
|
||||||
low = ( ctx->total[0] << 3 );
|
low = ( ctx->total[0] << 3 );
|
||||||
|
|
||||||
PUT_UINT32_BE( high, msglen, 0 );
|
PUT_UINT32_BE( high, msglen, 0 );
|
||||||
|
|
|
@ -23,13 +23,8 @@
|
||||||
#ifndef MBEDTLS_SHA1_ALT_SW_H
|
#ifndef MBEDTLS_SHA1_ALT_SW_H
|
||||||
#define MBEDTLS_SHA1_ALT_SW_H
|
#define MBEDTLS_SHA1_ALT_SW_H
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/sha256.h"
|
||||||
#include "config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA1_C)
|
|
||||||
#if defined(MBEDTLS_SHA1_ALT)
|
#if defined(MBEDTLS_SHA1_ALT)
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
@ -42,8 +37,7 @@ extern "C" {
|
||||||
/**
|
/**
|
||||||
* \brief SHA-1 context structure
|
* \brief SHA-1 context structure
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
uint32_t total[2]; /*!< number of bytes processed */
|
uint32_t total[2]; /*!< number of bytes processed */
|
||||||
uint32_t state[5]; /*!< intermediate digest state */
|
uint32_t state[5]; /*!< intermediate digest state */
|
||||||
unsigned char buffer[64]; /*!< data block being processed */
|
unsigned char buffer[64]; /*!< data block being processed */
|
||||||
|
@ -71,7 +65,7 @@ void mbedtls_sha1_sw_free( mbedtls_sha1_sw_context *ctx );
|
||||||
* \param src The context to be cloned
|
* \param src The context to be cloned
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha1_sw_clone( mbedtls_sha1_sw_context *dst,
|
void mbedtls_sha1_sw_clone( mbedtls_sha1_sw_context *dst,
|
||||||
const mbedtls_sha1_sw_context *src );
|
const mbedtls_sha1_sw_context *src );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief SHA-1 context setup
|
* \brief SHA-1 context setup
|
||||||
|
@ -105,6 +99,5 @@ void mbedtls_sha1_sw_process( mbedtls_sha1_sw_context *ctx, const unsigned char
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* MBEDTLS_SHA1_ALT */
|
#endif /* MBEDTLS_SHA1_ALT */
|
||||||
#endif /* MBEDTLS_SHA1_C */
|
|
||||||
|
|
||||||
#endif /* sha1_alt_sw.h */
|
#endif /* sha1_alt_sw.h */
|
||||||
|
|
|
@ -14,53 +14,69 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/sha256.h"
|
||||||
#include "mbedtls/config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA256_C)
|
#if defined(MBEDTLS_SHA256_C)
|
||||||
#if defined(MBEDTLS_SHA256_ALT)
|
#if defined(MBEDTLS_SHA256_ALT)
|
||||||
|
|
||||||
#include "sha256_alt.h"
|
|
||||||
#include "crypto-misc.h"
|
#include "crypto-misc.h"
|
||||||
#include "nu_bitutil.h"
|
#include "nu_bitutil.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
void mbedtls_sha256_init(mbedtls_sha256_context *ctx)
|
/* Choose SHA S/W or H/W context and initialize it
|
||||||
|
*
|
||||||
|
* try_hw:
|
||||||
|
* 0: Initialize S/W context
|
||||||
|
* 1: Try acquiring SHA H/W resource first and initialize its H/W context if successful. If failed, initialize S/W context.
|
||||||
|
*/
|
||||||
|
static void mbedtls_sha256_init_internal(mbedtls_sha256_context *ctx, int try_hw)
|
||||||
{
|
{
|
||||||
if (crypto_sha_acquire()) {
|
if (try_hw && crypto_sha_acquire()) {
|
||||||
ctx->ishw = 1;
|
ctx->active_ctx = &ctx->hw_ctx;
|
||||||
mbedtls_sha256_hw_init(&ctx->hw_ctx);
|
mbedtls_sha256_hw_init(&ctx->hw_ctx);
|
||||||
}
|
} else {
|
||||||
else {
|
ctx->active_ctx = &ctx->sw_ctx;
|
||||||
ctx->ishw = 0;
|
|
||||||
mbedtls_sha256_sw_init(&ctx->sw_ctx);
|
mbedtls_sha256_sw_init(&ctx->sw_ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mbedtls_sha256_init(mbedtls_sha256_context *ctx)
|
||||||
|
{
|
||||||
|
mbedtls_sha256_init_internal(ctx, 1);
|
||||||
|
}
|
||||||
|
|
||||||
void mbedtls_sha256_free(mbedtls_sha256_context *ctx)
|
void mbedtls_sha256_free(mbedtls_sha256_context *ctx)
|
||||||
{
|
{
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha256_hw_free(&ctx->hw_ctx);
|
mbedtls_sha256_hw_free(&ctx->hw_ctx);
|
||||||
crypto_sha_release();
|
crypto_sha_release();
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha256_sw_free(&ctx->sw_ctx);
|
mbedtls_sha256_sw_free(&ctx->sw_ctx);
|
||||||
}
|
}
|
||||||
|
ctx->active_ctx = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha256_clone(mbedtls_sha256_context *dst,
|
void mbedtls_sha256_clone(mbedtls_sha256_context *dst,
|
||||||
const mbedtls_sha256_context *src)
|
const mbedtls_sha256_context *src)
|
||||||
{
|
{
|
||||||
if (src->ishw) {
|
// Corner case: Destination/source contexts are the same
|
||||||
|
if (dst == src) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If dst is H/W context, we need to change it to S/W context first before cloning to.
|
||||||
|
if (dst->active_ctx == &dst->hw_ctx) {
|
||||||
|
mbedtls_sha256_free(dst);
|
||||||
|
// Force S/W context
|
||||||
|
mbedtls_sha256_init_internal(dst, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src->active_ctx == &src->hw_ctx) {
|
||||||
// Clone S/W ctx from H/W ctx
|
// Clone S/W ctx from H/W ctx
|
||||||
dst->ishw = 0;
|
|
||||||
dst->sw_ctx.total[0] = src->hw_ctx.total;
|
dst->sw_ctx.total[0] = src->hw_ctx.total;
|
||||||
dst->sw_ctx.total[1] = 0;
|
dst->sw_ctx.total[1] = 0;
|
||||||
{
|
{
|
||||||
|
@ -79,8 +95,7 @@ void mbedtls_sha256_clone(mbedtls_sha256_context *dst,
|
||||||
if (src->hw_ctx.buffer_left == src->hw_ctx.blocksize) {
|
if (src->hw_ctx.buffer_left == src->hw_ctx.blocksize) {
|
||||||
mbedtls_sha256_sw_process(&dst->sw_ctx, dst->sw_ctx.buffer);
|
mbedtls_sha256_sw_process(&dst->sw_ctx, dst->sw_ctx.buffer);
|
||||||
}
|
}
|
||||||
}
|
} else if (src->active_ctx == &src->sw_ctx) {
|
||||||
else {
|
|
||||||
// Clone S/W ctx from S/W ctx
|
// Clone S/W ctx from S/W ctx
|
||||||
dst->sw_ctx = src->sw_ctx;
|
dst->sw_ctx = src->sw_ctx;
|
||||||
}
|
}
|
||||||
|
@ -90,11 +105,10 @@ void mbedtls_sha256_clone(mbedtls_sha256_context *dst,
|
||||||
* SHA-256 context setup
|
* SHA-256 context setup
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224)
|
void mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224)
|
||||||
{
|
{
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha256_hw_starts(&ctx->hw_ctx, is224);
|
mbedtls_sha256_hw_starts(&ctx->hw_ctx, is224);
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha256_sw_starts(&ctx->sw_ctx, is224);
|
mbedtls_sha256_sw_starts(&ctx->sw_ctx, is224);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,10 +118,9 @@ void mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224)
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha256_update(mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen)
|
void mbedtls_sha256_update(mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen)
|
||||||
{
|
{
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha256_hw_update(&ctx->hw_ctx, input, ilen);
|
mbedtls_sha256_hw_update(&ctx->hw_ctx, input, ilen);
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha256_sw_update(&ctx->sw_ctx, input, ilen);
|
mbedtls_sha256_sw_update(&ctx->sw_ctx, input, ilen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,20 +130,18 @@ void mbedtls_sha256_update(mbedtls_sha256_context *ctx, const unsigned char *inp
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha256_finish(mbedtls_sha256_context *ctx, unsigned char output[32])
|
void mbedtls_sha256_finish(mbedtls_sha256_context *ctx, unsigned char output[32])
|
||||||
{
|
{
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha256_hw_finish(&ctx->hw_ctx, output);
|
mbedtls_sha256_hw_finish(&ctx->hw_ctx, output);
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha256_sw_finish(&ctx->sw_ctx, output);
|
mbedtls_sha256_sw_finish(&ctx->sw_ctx, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha256_process(mbedtls_sha256_context *ctx, const unsigned char data[64])
|
void mbedtls_sha256_process(mbedtls_sha256_context *ctx, const unsigned char data[64])
|
||||||
{
|
{
|
||||||
if (ctx->ishw) {
|
if (ctx->active_ctx == &ctx->hw_ctx) {
|
||||||
mbedtls_sha256_hw_process(&ctx->hw_ctx, data);
|
mbedtls_sha256_hw_process(&ctx->hw_ctx, data);
|
||||||
}
|
} else if (ctx->active_ctx == &ctx->sw_ctx) {
|
||||||
else {
|
|
||||||
mbedtls_sha256_sw_process(&ctx->sw_ctx, data);
|
mbedtls_sha256_sw_process(&ctx->sw_ctx, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,13 +16,8 @@
|
||||||
#ifndef MBEDTLS_SHA256_ALT_H
|
#ifndef MBEDTLS_SHA256_ALT_H
|
||||||
#define MBEDTLS_SHA256_ALT_H
|
#define MBEDTLS_SHA256_ALT_H
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/sha256.h"
|
||||||
#include "config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA256_C)
|
|
||||||
#if defined(MBEDTLS_SHA256_ALT)
|
#if defined(MBEDTLS_SHA256_ALT)
|
||||||
|
|
||||||
#include "sha_alt_hw.h"
|
#include "sha_alt_hw.h"
|
||||||
|
@ -37,9 +32,8 @@ struct mbedtls_sha256_context_s;
|
||||||
/**
|
/**
|
||||||
* \brief SHA-256 context structure
|
* \brief SHA-256 context structure
|
||||||
*/
|
*/
|
||||||
typedef struct mbedtls_sha256_context_s
|
typedef struct mbedtls_sha256_context_s {
|
||||||
{
|
void *active_ctx;
|
||||||
int ishw;
|
|
||||||
crypto_sha_context hw_ctx;
|
crypto_sha_context hw_ctx;
|
||||||
mbedtls_sha256_sw_context sw_ctx;
|
mbedtls_sha256_sw_context sw_ctx;
|
||||||
}
|
}
|
||||||
|
@ -84,7 +78,7 @@ void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 );
|
||||||
* \param ilen length of the input data
|
* \param ilen length of the input data
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input,
|
void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input,
|
||||||
size_t ilen );
|
size_t ilen );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief SHA-256 final digest
|
* \brief SHA-256 final digest
|
||||||
|
@ -102,6 +96,5 @@ void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char da
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* MBEDTLS_SHA256_ALT */
|
#endif /* MBEDTLS_SHA256_ALT */
|
||||||
#endif /* MBEDTLS_SHA256_C */
|
|
||||||
|
|
||||||
#endif /* sha256_alt.h */
|
#endif /* sha256_alt.h */
|
||||||
|
|
|
@ -24,17 +24,11 @@
|
||||||
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/sha256.h"
|
||||||
#include "mbedtls/config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA256_C)
|
#if defined(MBEDTLS_SHA256_C)
|
||||||
#if defined(MBEDTLS_SHA256_ALT)
|
#if defined(MBEDTLS_SHA256_ALT)
|
||||||
|
|
||||||
#include "mbedtls/sha256.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#if defined(MBEDTLS_SELF_TEST)
|
#if defined(MBEDTLS_SELF_TEST)
|
||||||
#if defined(MBEDTLS_PLATFORM_C)
|
#if defined(MBEDTLS_PLATFORM_C)
|
||||||
|
@ -49,8 +43,10 @@
|
||||||
#endif /* MBEDTLS_SELF_TEST */
|
#endif /* MBEDTLS_SELF_TEST */
|
||||||
|
|
||||||
/* Implementation that should never be optimized out by the compiler */
|
/* Implementation that should never be optimized out by the compiler */
|
||||||
static void mbedtls_zeroize( void *v, size_t n ) {
|
static void mbedtls_zeroize( void *v, size_t n )
|
||||||
volatile unsigned char *p = v; while( n-- ) *p++ = 0;
|
{
|
||||||
|
volatile unsigned char *p = v;
|
||||||
|
while( n-- ) *p++ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -90,7 +86,7 @@ void mbedtls_sha256_sw_free( mbedtls_sha256_sw_context *ctx )
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha256_sw_clone( mbedtls_sha256_sw_context *dst,
|
void mbedtls_sha256_sw_clone( mbedtls_sha256_sw_context *dst,
|
||||||
const mbedtls_sha256_sw_context *src )
|
const mbedtls_sha256_sw_context *src )
|
||||||
{
|
{
|
||||||
*dst = *src;
|
*dst = *src;
|
||||||
}
|
}
|
||||||
|
@ -103,8 +99,7 @@ void mbedtls_sha256_sw_starts( mbedtls_sha256_sw_context *ctx, int is224 )
|
||||||
ctx->total[0] = 0;
|
ctx->total[0] = 0;
|
||||||
ctx->total[1] = 0;
|
ctx->total[1] = 0;
|
||||||
|
|
||||||
if( is224 == 0 )
|
if( is224 == 0 ) {
|
||||||
{
|
|
||||||
/* SHA-256 */
|
/* SHA-256 */
|
||||||
ctx->state[0] = 0x6A09E667;
|
ctx->state[0] = 0x6A09E667;
|
||||||
ctx->state[1] = 0xBB67AE85;
|
ctx->state[1] = 0xBB67AE85;
|
||||||
|
@ -114,9 +109,7 @@ void mbedtls_sha256_sw_starts( mbedtls_sha256_sw_context *ctx, int is224 )
|
||||||
ctx->state[5] = 0x9B05688C;
|
ctx->state[5] = 0x9B05688C;
|
||||||
ctx->state[6] = 0x1F83D9AB;
|
ctx->state[6] = 0x1F83D9AB;
|
||||||
ctx->state[7] = 0x5BE0CD19;
|
ctx->state[7] = 0x5BE0CD19;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* SHA-224 */
|
/* SHA-224 */
|
||||||
ctx->state[0] = 0xC1059ED8;
|
ctx->state[0] = 0xC1059ED8;
|
||||||
ctx->state[1] = 0x367CD507;
|
ctx->state[1] = 0x367CD507;
|
||||||
|
@ -131,8 +124,7 @@ void mbedtls_sha256_sw_starts( mbedtls_sha256_sw_context *ctx, int is224 )
|
||||||
ctx->is224 = is224;
|
ctx->is224 = is224;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint32_t K[] =
|
static const uint32_t K[] = {
|
||||||
{
|
|
||||||
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
|
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
|
||||||
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
|
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
|
||||||
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
|
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
|
||||||
|
@ -186,8 +178,7 @@ void mbedtls_sha256_sw_process( mbedtls_sha256_sw_context *ctx, const unsigned c
|
||||||
A[i] = ctx->state[i];
|
A[i] = ctx->state[i];
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA256_SMALLER)
|
#if defined(MBEDTLS_SHA256_SMALLER)
|
||||||
for( i = 0; i < 64; i++ )
|
for( i = 0; i < 64; i++ ) {
|
||||||
{
|
|
||||||
if( i < 16 )
|
if( i < 16 )
|
||||||
GET_UINT32_BE( W[i], data, 4 * i );
|
GET_UINT32_BE( W[i], data, 4 * i );
|
||||||
else
|
else
|
||||||
|
@ -195,15 +186,21 @@ void mbedtls_sha256_sw_process( mbedtls_sha256_sw_context *ctx, const unsigned c
|
||||||
|
|
||||||
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] );
|
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] );
|
||||||
|
|
||||||
temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3];
|
temp1 = A[7];
|
||||||
A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1;
|
A[7] = A[6];
|
||||||
|
A[6] = A[5];
|
||||||
|
A[5] = A[4];
|
||||||
|
A[4] = A[3];
|
||||||
|
A[3] = A[2];
|
||||||
|
A[2] = A[1];
|
||||||
|
A[1] = A[0];
|
||||||
|
A[0] = temp1;
|
||||||
}
|
}
|
||||||
#else /* MBEDTLS_SHA256_SMALLER */
|
#else /* MBEDTLS_SHA256_SMALLER */
|
||||||
for( i = 0; i < 16; i++ )
|
for( i = 0; i < 16; i++ )
|
||||||
GET_UINT32_BE( W[i], data, 4 * i );
|
GET_UINT32_BE( W[i], data, 4 * i );
|
||||||
|
|
||||||
for( i = 0; i < 16; i += 8 )
|
for( i = 0; i < 16; i += 8 ) {
|
||||||
{
|
|
||||||
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] );
|
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] );
|
||||||
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] );
|
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] );
|
||||||
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] );
|
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] );
|
||||||
|
@ -214,8 +211,7 @@ void mbedtls_sha256_sw_process( mbedtls_sha256_sw_context *ctx, const unsigned c
|
||||||
P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] );
|
P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] );
|
||||||
}
|
}
|
||||||
|
|
||||||
for( i = 16; i < 64; i += 8 )
|
for( i = 16; i < 64; i += 8 ) {
|
||||||
{
|
|
||||||
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] );
|
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] );
|
||||||
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] );
|
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] );
|
||||||
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] );
|
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] );
|
||||||
|
@ -235,7 +231,7 @@ void mbedtls_sha256_sw_process( mbedtls_sha256_sw_context *ctx, const unsigned c
|
||||||
* SHA-256 process buffer
|
* SHA-256 process buffer
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha256_sw_update( mbedtls_sha256_sw_context *ctx, const unsigned char *input,
|
void mbedtls_sha256_sw_update( mbedtls_sha256_sw_context *ctx, const unsigned char *input,
|
||||||
size_t ilen )
|
size_t ilen )
|
||||||
{
|
{
|
||||||
size_t fill;
|
size_t fill;
|
||||||
uint32_t left;
|
uint32_t left;
|
||||||
|
@ -252,8 +248,7 @@ void mbedtls_sha256_sw_update( mbedtls_sha256_sw_context *ctx, const unsigned ch
|
||||||
if( ctx->total[0] < (uint32_t) ilen )
|
if( ctx->total[0] < (uint32_t) ilen )
|
||||||
ctx->total[1]++;
|
ctx->total[1]++;
|
||||||
|
|
||||||
if( left && ilen >= fill )
|
if( left && ilen >= fill ) {
|
||||||
{
|
|
||||||
memcpy( (void *) (ctx->buffer + left), input, fill );
|
memcpy( (void *) (ctx->buffer + left), input, fill );
|
||||||
mbedtls_sha256_sw_process( ctx, ctx->buffer );
|
mbedtls_sha256_sw_process( ctx, ctx->buffer );
|
||||||
input += fill;
|
input += fill;
|
||||||
|
@ -261,8 +256,7 @@ void mbedtls_sha256_sw_update( mbedtls_sha256_sw_context *ctx, const unsigned ch
|
||||||
left = 0;
|
left = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while( ilen >= 64 )
|
while( ilen >= 64 ) {
|
||||||
{
|
|
||||||
mbedtls_sha256_sw_process( ctx, input );
|
mbedtls_sha256_sw_process( ctx, input );
|
||||||
input += 64;
|
input += 64;
|
||||||
ilen -= 64;
|
ilen -= 64;
|
||||||
|
@ -272,9 +266,8 @@ void mbedtls_sha256_sw_update( mbedtls_sha256_sw_context *ctx, const unsigned ch
|
||||||
memcpy( (void *) (ctx->buffer + left), input, ilen );
|
memcpy( (void *) (ctx->buffer + left), input, ilen );
|
||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned char sha256_padding[64] =
|
static const unsigned char sha256_padding[64] = {
|
||||||
{
|
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
@ -290,7 +283,7 @@ void mbedtls_sha256_sw_finish( mbedtls_sha256_sw_context *ctx, unsigned char out
|
||||||
unsigned char msglen[8];
|
unsigned char msglen[8];
|
||||||
|
|
||||||
high = ( ctx->total[0] >> 29 )
|
high = ( ctx->total[0] >> 29 )
|
||||||
| ( ctx->total[1] << 3 );
|
| ( ctx->total[1] << 3 );
|
||||||
low = ( ctx->total[0] << 3 );
|
low = ( ctx->total[0] << 3 );
|
||||||
|
|
||||||
PUT_UINT32_BE( high, msglen, 0 );
|
PUT_UINT32_BE( high, msglen, 0 );
|
||||||
|
|
|
@ -23,13 +23,8 @@
|
||||||
#ifndef MBEDTLS_SHA256_ALT_SW_H
|
#ifndef MBEDTLS_SHA256_ALT_SW_H
|
||||||
#define MBEDTLS_SHA256_ALT_SW_H
|
#define MBEDTLS_SHA256_ALT_SW_H
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/sha256.h"
|
||||||
#include "config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA256_C)
|
|
||||||
#if defined(MBEDTLS_SHA256_ALT)
|
#if defined(MBEDTLS_SHA256_ALT)
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
@ -42,8 +37,7 @@ extern "C" {
|
||||||
/**
|
/**
|
||||||
* \brief SHA-256 context structure
|
* \brief SHA-256 context structure
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
uint32_t total[2]; /*!< number of bytes processed */
|
uint32_t total[2]; /*!< number of bytes processed */
|
||||||
uint32_t state[8]; /*!< intermediate digest state */
|
uint32_t state[8]; /*!< intermediate digest state */
|
||||||
unsigned char buffer[64]; /*!< data block being processed */
|
unsigned char buffer[64]; /*!< data block being processed */
|
||||||
|
@ -72,7 +66,7 @@ void mbedtls_sha256_sw_free( mbedtls_sha256_sw_context *ctx );
|
||||||
* \param src The context to be cloned
|
* \param src The context to be cloned
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha256_sw_clone( mbedtls_sha256_sw_context *dst,
|
void mbedtls_sha256_sw_clone( mbedtls_sha256_sw_context *dst,
|
||||||
const mbedtls_sha256_sw_context *src );
|
const mbedtls_sha256_sw_context *src );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief SHA-256 context setup
|
* \brief SHA-256 context setup
|
||||||
|
@ -90,7 +84,7 @@ void mbedtls_sha256_sw_starts( mbedtls_sha256_sw_context *ctx, int is224 );
|
||||||
* \param ilen length of the input data
|
* \param ilen length of the input data
|
||||||
*/
|
*/
|
||||||
void mbedtls_sha256_sw_update( mbedtls_sha256_sw_context *ctx, const unsigned char *input,
|
void mbedtls_sha256_sw_update( mbedtls_sha256_sw_context *ctx, const unsigned char *input,
|
||||||
size_t ilen );
|
size_t ilen );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief SHA-256 final digest
|
* \brief SHA-256 final digest
|
||||||
|
@ -108,6 +102,5 @@ void mbedtls_sha256_sw_process( mbedtls_sha256_sw_context *ctx, const unsigned c
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* MBEDTLS_SHA256_ALT */
|
#endif /* MBEDTLS_SHA256_ALT */
|
||||||
#endif /* MBEDTLS_SHA256_C */
|
|
||||||
|
|
||||||
#endif /* sha256_alt_sw.h */
|
#endif /* sha256_alt_sw.h */
|
||||||
|
|
|
@ -14,30 +14,18 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
#include "mbedtls/sha1.h"
|
||||||
#include "mbedtls/config.h"
|
#include "mbedtls/sha256.h"
|
||||||
#else
|
#include "mbedtls/sha512.h"
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA1_C) || defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C)
|
#if defined(MBEDTLS_SHA1_C) || defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C)
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA1_ALT) || defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA512_ALT)
|
#if defined(MBEDTLS_SHA1_ALT) || defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA512_ALT)
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA1_ALT)
|
|
||||||
#include "sha1_alt.h"
|
|
||||||
#endif /* MBEDTLS_SHA1_ALT */
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA256_ALT)
|
|
||||||
#include "sha256_alt.h"
|
|
||||||
#endif /* MBEDTLS_SHA256_ALT */
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA512_ALT)
|
|
||||||
#include "sha512_alt.h"
|
|
||||||
#endif /* MBEDTLS_SHA512_ALT */
|
|
||||||
|
|
||||||
#include "nu_bitutil.h"
|
#include "nu_bitutil.h"
|
||||||
|
#include "nu_timer.h"
|
||||||
#include "mbed_assert.h"
|
#include "mbed_assert.h"
|
||||||
|
#include "mbed_error.h"
|
||||||
#include "crypto-misc.h"
|
#include "crypto-misc.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -53,8 +41,9 @@ void crypto_sha_getinternstate(unsigned char output[], size_t olen);
|
||||||
|
|
||||||
void mbedtls_sha1_hw_init(crypto_sha_context *ctx)
|
void mbedtls_sha1_hw_init(crypto_sha_context *ctx)
|
||||||
{
|
{
|
||||||
|
/* Init crypto module */
|
||||||
crypto_init();
|
crypto_init();
|
||||||
memset(ctx, 0, sizeof(crypto_sha_context));
|
memset(ctx, 0, sizeof(*ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha1_hw_free(crypto_sha_context *ctx)
|
void mbedtls_sha1_hw_free(crypto_sha_context *ctx)
|
||||||
|
@ -63,30 +52,28 @@ void mbedtls_sha1_hw_free(crypto_sha_context *ctx)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
crypto_zeroize(ctx, sizeof(crypto_sha_context));
|
CRPT->SHA_CTL |= CRPT_SHA_CTL_STOP_Msk;
|
||||||
}
|
|
||||||
|
|
||||||
void mbedtls_sha1_hw_clone(crypto_sha_context *dst,
|
/* Uninit crypto module */
|
||||||
const crypto_sha_context *src)
|
crypto_uninit();
|
||||||
{
|
crypto_zeroize(ctx, sizeof(*ctx));
|
||||||
*dst = *src;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha1_hw_starts(crypto_sha_context *ctx)
|
void mbedtls_sha1_hw_starts(crypto_sha_context *ctx)
|
||||||
{
|
{
|
||||||
// NOTE: mbedtls may call mbedtls_shaXXX_starts multiple times and then call the ending mbedtls_shaXXX_finish. Guard from it.
|
// NOTE: mbedtls may call mbedtls_shaXXX_starts multiple times and then call the ending mbedtls_shaXXX_finish. Guard from it.
|
||||||
CRPT->SHA_CTL |= CRPT_SHA_CTL_STOP_Msk;
|
CRPT->SHA_CTL |= CRPT_SHA_CTL_STOP_Msk;
|
||||||
|
|
||||||
ctx->total = 0;
|
ctx->total = 0;
|
||||||
ctx->buffer_left = 0;
|
ctx->buffer_left = 0;
|
||||||
ctx->blocksize = 64;
|
ctx->blocksize = 64;
|
||||||
ctx->blocksize_mask = 0x3F;
|
ctx->blocksize_mask = 0x3F;
|
||||||
|
|
||||||
SHA_Open(SHA_MODE_SHA1, SHA_NO_SWAP);
|
SHA_Open(SHA_MODE_SHA1, SHA_NO_SWAP);
|
||||||
|
|
||||||
// Ensure we have correct initial inernal states in SHA_DGST registers even though SHA H/W is not actually started.
|
// Ensure we have correct initial internal states in SHA_DGST registers even though SHA H/W is not actually started.
|
||||||
CRPT->SHA_CTL |= CRPT_SHA_CTL_START_Msk;
|
CRPT->SHA_CTL |= CRPT_SHA_CTL_START_Msk;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,17 +89,16 @@ void mbedtls_sha1_hw_finish(crypto_sha_context *ctx, unsigned char output[20])
|
||||||
crypto_sha_update_nobuf(ctx, ctx->buffer, ctx->buffer_left, 1);
|
crypto_sha_update_nobuf(ctx, ctx->buffer, ctx->buffer_left, 1);
|
||||||
ctx->buffer_left = 0;
|
ctx->buffer_left = 0;
|
||||||
crypto_sha_getinternstate(output, 20);
|
crypto_sha_getinternstate(output, 20);
|
||||||
|
} else {
|
||||||
CRPT->SHA_CTL |= CRPT_SHA_CTL_STOP_Msk;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mbedtls_sha1_sw_context ctx_sw;
|
mbedtls_sha1_sw_context ctx_sw;
|
||||||
|
|
||||||
mbedtls_sha1_sw_init(&ctx_sw);
|
mbedtls_sha1_sw_init(&ctx_sw);
|
||||||
mbedtls_sha1_sw_starts(&ctx_sw);
|
mbedtls_sha1_sw_starts(&ctx_sw);
|
||||||
mbedtls_sha1_sw_finish(&ctx_sw, output);
|
mbedtls_sha1_sw_finish(&ctx_sw, output);
|
||||||
mbedtls_sha1_sw_free(&ctx_sw);
|
mbedtls_sha1_sw_free(&ctx_sw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CRPT->SHA_CTL |= CRPT_SHA_CTL_STOP_Msk;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha1_hw_process(crypto_sha_context *ctx, const unsigned char data[64])
|
void mbedtls_sha1_hw_process(crypto_sha_context *ctx, const unsigned char data[64])
|
||||||
|
@ -128,8 +114,9 @@ void mbedtls_sha1_hw_process(crypto_sha_context *ctx, const unsigned char data[6
|
||||||
|
|
||||||
void mbedtls_sha256_hw_init(crypto_sha_context *ctx)
|
void mbedtls_sha256_hw_init(crypto_sha_context *ctx)
|
||||||
{
|
{
|
||||||
|
/* Init crypto module */
|
||||||
crypto_init();
|
crypto_init();
|
||||||
memset(ctx, 0, sizeof(crypto_sha_context));
|
memset(ctx, 0, sizeof(*ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha256_hw_free(crypto_sha_context *ctx)
|
void mbedtls_sha256_hw_free(crypto_sha_context *ctx)
|
||||||
|
@ -138,20 +125,18 @@ void mbedtls_sha256_hw_free(crypto_sha_context *ctx)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
crypto_zeroize(ctx, sizeof(crypto_sha_context));
|
CRPT->SHA_CTL |= CRPT_SHA_CTL_STOP_Msk;
|
||||||
}
|
|
||||||
|
|
||||||
void mbedtls_sha256_hw_clone(crypto_sha_context *dst,
|
/* Uninit crypto module */
|
||||||
const crypto_sha_context *src)
|
crypto_uninit();
|
||||||
{
|
crypto_zeroize(ctx, sizeof(*ctx));
|
||||||
*dst = *src;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha256_hw_starts( crypto_sha_context *ctx, int is224)
|
void mbedtls_sha256_hw_starts( crypto_sha_context *ctx, int is224)
|
||||||
{
|
{
|
||||||
// NOTE: mbedtls may call mbedtls_shaXXX_starts multiple times and then call the ending mbedtls_shaXXX_finish. Guard from it.
|
// NOTE: mbedtls may call mbedtls_shaXXX_starts multiple times and then call the ending mbedtls_shaXXX_finish. Guard from it.
|
||||||
CRPT->SHA_CTL |= CRPT_SHA_CTL_STOP_Msk;
|
CRPT->SHA_CTL |= CRPT_SHA_CTL_STOP_Msk;
|
||||||
|
|
||||||
ctx->total = 0;
|
ctx->total = 0;
|
||||||
ctx->buffer_left = 0;
|
ctx->buffer_left = 0;
|
||||||
ctx->blocksize = 64;
|
ctx->blocksize = 64;
|
||||||
|
@ -159,10 +144,10 @@ void mbedtls_sha256_hw_starts( crypto_sha_context *ctx, int is224)
|
||||||
ctx->is224 = is224;
|
ctx->is224 = is224;
|
||||||
|
|
||||||
SHA_Open(is224 ? SHA_MODE_SHA224 : SHA_MODE_SHA256, SHA_NO_SWAP);
|
SHA_Open(is224 ? SHA_MODE_SHA224 : SHA_MODE_SHA256, SHA_NO_SWAP);
|
||||||
|
|
||||||
// Ensure we have correct initial inernal states in SHA_DGST registers even though SHA H/W is not actually started.
|
// Ensure we have correct initial internal states in SHA_DGST registers even though SHA H/W is not actually started.
|
||||||
CRPT->SHA_CTL |= CRPT_SHA_CTL_START_Msk;
|
CRPT->SHA_CTL |= CRPT_SHA_CTL_START_Msk;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,17 +163,16 @@ void mbedtls_sha256_hw_finish(crypto_sha_context *ctx, unsigned char output[32])
|
||||||
crypto_sha_update_nobuf(ctx, ctx->buffer, ctx->buffer_left, 1);
|
crypto_sha_update_nobuf(ctx, ctx->buffer, ctx->buffer_left, 1);
|
||||||
ctx->buffer_left = 0;
|
ctx->buffer_left = 0;
|
||||||
crypto_sha_getinternstate(output, ctx->is224 ? 28 : 32);
|
crypto_sha_getinternstate(output, ctx->is224 ? 28 : 32);
|
||||||
|
} else {
|
||||||
CRPT->SHA_CTL |= CRPT_SHA_CTL_STOP_Msk;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mbedtls_sha256_sw_context ctx_sw;
|
mbedtls_sha256_sw_context ctx_sw;
|
||||||
|
|
||||||
mbedtls_sha256_sw_init(&ctx_sw);
|
mbedtls_sha256_sw_init(&ctx_sw);
|
||||||
mbedtls_sha256_sw_starts(&ctx_sw, ctx->is224);
|
mbedtls_sha256_sw_starts(&ctx_sw, ctx->is224);
|
||||||
mbedtls_sha256_sw_finish(&ctx_sw, output);
|
mbedtls_sha256_sw_finish(&ctx_sw, output);
|
||||||
mbedtls_sha256_sw_free(&ctx_sw);
|
mbedtls_sha256_sw_free(&ctx_sw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CRPT->SHA_CTL |= CRPT_SHA_CTL_STOP_Msk;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbedtls_sha256_hw_process(crypto_sha_context *ctx, const unsigned char data[64])
|
void mbedtls_sha256_hw_process(crypto_sha_context *ctx, const unsigned char data[64])
|
||||||
|
@ -207,7 +191,7 @@ void crypto_sha_update(crypto_sha_context *ctx, const unsigned char *input, size
|
||||||
if (ilen == 0) {
|
if (ilen == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t fill = ctx->blocksize - ctx->buffer_left;
|
size_t fill = ctx->blocksize - ctx->buffer_left;
|
||||||
|
|
||||||
ctx->total += (uint32_t) ilen;
|
ctx->total += (uint32_t) ilen;
|
||||||
|
@ -222,7 +206,7 @@ void crypto_sha_update(crypto_sha_context *ctx, const unsigned char *input, size
|
||||||
ctx->buffer_left = 0;
|
ctx->buffer_left = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (ilen > ctx->blocksize) {
|
while (ilen > ctx->blocksize) {
|
||||||
crypto_sha_update_nobuf(ctx, input, ctx->blocksize, 0);
|
crypto_sha_update_nobuf(ctx, input, ctx->blocksize, 0);
|
||||||
input += ctx->blocksize;
|
input += ctx->blocksize;
|
||||||
|
@ -241,16 +225,14 @@ void crypto_sha_update_nobuf(crypto_sha_context *ctx, const unsigned char *input
|
||||||
// 1. Last block which may be incomplete
|
// 1. Last block which may be incomplete
|
||||||
// 2. Non-last block which is complete
|
// 2. Non-last block which is complete
|
||||||
MBED_ASSERT(islast || ilen == ctx->blocksize);
|
MBED_ASSERT(islast || ilen == ctx->blocksize);
|
||||||
|
|
||||||
const unsigned char *in_pos = input;
|
const unsigned char *in_pos = input;
|
||||||
int rmn = ilen;
|
int rmn = ilen;
|
||||||
uint32_t sha_ctl_start = (CRPT->SHA_CTL & ~(CRPT_SHA_CTL_DMALAST_Msk | CRPT_SHA_CTL_DMAEN_Msk)) | CRPT_SHA_CTL_START_Msk;
|
uint32_t sha_ctl_start = (CRPT->SHA_CTL & ~(CRPT_SHA_CTL_DMALAST_Msk | CRPT_SHA_CTL_DMAEN_Msk)) | CRPT_SHA_CTL_START_Msk;
|
||||||
uint32_t sha_opmode = (CRPT->SHA_CTL & CRPT_SHA_CTL_OPMODE_Msk) >> CRPT_SHA_CTL_OPMODE_Pos;
|
uint32_t sha_opmode = (CRPT->SHA_CTL & CRPT_SHA_CTL_OPMODE_Msk) >> CRPT_SHA_CTL_OPMODE_Pos;
|
||||||
uint32_t DGST0_old, DGST1_old, DGST2_old, DGST3_old, DGST4_old, DGST5_old, DGST6_old, DGST7_old;
|
uint32_t DGSTs[8] = { 0 };
|
||||||
|
|
||||||
while (rmn > 0) {
|
while (rmn > 0) {
|
||||||
CRPT->SHA_CTL = sha_ctl_start;
|
|
||||||
|
|
||||||
uint32_t data = nu_get32_be(in_pos);
|
uint32_t data = nu_get32_be(in_pos);
|
||||||
if (rmn <= 4) { // Last word of a (in)complete block
|
if (rmn <= 4) { // Last word of a (in)complete block
|
||||||
if (islast) {
|
if (islast) {
|
||||||
|
@ -260,71 +242,90 @@ void crypto_sha_update_nobuf(crypto_sha_context *ctx, const unsigned char *input
|
||||||
}
|
}
|
||||||
CRPT->SHA_DMACNT = lastblock_size;
|
CRPT->SHA_DMACNT = lastblock_size;
|
||||||
CRPT->SHA_CTL = sha_ctl_start | CRPT_SHA_CTL_DMALAST_Msk;
|
CRPT->SHA_CTL = sha_ctl_start | CRPT_SHA_CTL_DMALAST_Msk;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
switch (sha_opmode) {
|
switch (sha_opmode) {
|
||||||
case SHA_MODE_SHA256:
|
case SHA_MODE_SHA256:
|
||||||
DGST7_old = CRPT->SHA_DGST7;
|
DGSTs[7] = CRPT->SHA_DGST7;
|
||||||
case SHA_MODE_SHA224:
|
case SHA_MODE_SHA224:
|
||||||
DGST5_old = CRPT->SHA_DGST5;
|
DGSTs[5] = CRPT->SHA_DGST5;
|
||||||
DGST6_old = CRPT->SHA_DGST6;
|
DGSTs[6] = CRPT->SHA_DGST6;
|
||||||
case SHA_MODE_SHA1:
|
case SHA_MODE_SHA1:
|
||||||
DGST0_old = CRPT->SHA_DGST0;
|
DGSTs[0] = CRPT->SHA_DGST0;
|
||||||
DGST1_old = CRPT->SHA_DGST1;
|
DGSTs[1] = CRPT->SHA_DGST1;
|
||||||
DGST2_old = CRPT->SHA_DGST2;
|
DGSTs[2] = CRPT->SHA_DGST2;
|
||||||
DGST3_old = CRPT->SHA_DGST3;
|
DGSTs[3] = CRPT->SHA_DGST3;
|
||||||
DGST4_old = CRPT->SHA_DGST4;
|
DGSTs[4] = CRPT->SHA_DGST4;
|
||||||
}
|
}
|
||||||
|
|
||||||
CRPT->SHA_CTL = sha_ctl_start;
|
CRPT->SHA_CTL = sha_ctl_start;
|
||||||
}
|
}
|
||||||
}
|
} else { // Non-last word of a complete block
|
||||||
else { // Non-last word of a complete block
|
|
||||||
CRPT->SHA_CTL = sha_ctl_start;
|
CRPT->SHA_CTL = sha_ctl_start;
|
||||||
}
|
}
|
||||||
while (! (CRPT->SHA_STS & CRPT_SHA_STS_DATINREQ_Msk));
|
while (! (CRPT->SHA_STS & CRPT_SHA_STS_DATINREQ_Msk));
|
||||||
CRPT->SHA_DATIN = data;
|
CRPT->SHA_DATIN = data;
|
||||||
|
|
||||||
in_pos += 4;
|
in_pos += 4;
|
||||||
rmn -= 4;
|
rmn -= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (islast) { // Finish of last block
|
if (islast) { // Finish of last block
|
||||||
while (CRPT->SHA_STS & CRPT_SHA_STS_BUSY_Msk);
|
while (CRPT->SHA_STS & CRPT_SHA_STS_BUSY_Msk);
|
||||||
}
|
} else { // Finish of non-last block
|
||||||
else { // Finish of non-last block
|
/* SHA accelerator doesn't export a flag to indicate non-last block process has finished.
|
||||||
// No H/W flag to indicate finish of non-last block process.
|
* Per designer, if the digest (SHA_DGSTx) code changes after the last word of the block is input,
|
||||||
// Values of SHA_DGSTx registers will change as last word of the block is input, so use it for judgement.
|
* this indicates the non-last block process has finished.
|
||||||
|
*
|
||||||
|
* There is a rare case that two digest codes are the same for
|
||||||
|
* two non-last block processes in a row.
|
||||||
|
* To address it, we use a count-down timer to detect it.
|
||||||
|
* As the count-down timer expires, we see it as finished.
|
||||||
|
*/
|
||||||
int isfinish = 0;
|
int isfinish = 0;
|
||||||
|
struct nu_countdown_ctx_s ctx;
|
||||||
|
|
||||||
|
// Set up 2s timeout
|
||||||
|
nu_countdown_init(&ctx, 2000*1000);
|
||||||
while (! isfinish) {
|
while (! isfinish) {
|
||||||
switch (sha_opmode) {
|
switch (sha_opmode) {
|
||||||
case SHA_MODE_SHA256:
|
case SHA_MODE_SHA256:
|
||||||
if (DGST7_old != CRPT->SHA_DGST7) {
|
if (DGSTs[7] != CRPT->SHA_DGST7) {
|
||||||
isfinish = 1;
|
isfinish = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SHA_MODE_SHA224:
|
case SHA_MODE_SHA224:
|
||||||
if (DGST5_old != CRPT->SHA_DGST5 || DGST6_old != CRPT->SHA_DGST6) {
|
if (DGSTs[5] != CRPT->SHA_DGST5 || DGSTs[6] != CRPT->SHA_DGST6) {
|
||||||
isfinish = 1;
|
isfinish = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SHA_MODE_SHA1:
|
case SHA_MODE_SHA1:
|
||||||
if (DGST0_old != CRPT->SHA_DGST0 || DGST1_old != CRPT->SHA_DGST1 || DGST2_old != CRPT->SHA_DGST2 ||
|
if (DGSTs[0] != CRPT->SHA_DGST0 || DGSTs[1] != CRPT->SHA_DGST1 || DGSTs[2] != CRPT->SHA_DGST2 ||
|
||||||
DGST3_old != CRPT->SHA_DGST3 || DGST4_old != CRPT->SHA_DGST4) {
|
DGSTs[3] != CRPT->SHA_DGST3 || DGSTs[4] != CRPT->SHA_DGST4) {
|
||||||
isfinish = 1;
|
isfinish = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nu_countdown_expired(&ctx)) {
|
||||||
|
// We may meet a rare case that the current digest code and the previous one are the same.
|
||||||
|
isfinish = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Must pair nu_countdown_init with nu_countdown_free in the end
|
||||||
|
nu_countdown_free(&ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void crypto_sha_getinternstate(unsigned char output[], size_t olen)
|
void crypto_sha_getinternstate(unsigned char output[], size_t olen)
|
||||||
{
|
{
|
||||||
|
if (olen & 0x3) {
|
||||||
|
error("Internal error in SHA alter. SHA internal state size requires to be a multiple of 4 bytes.");
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t *in_pos = (uint32_t *) &CRPT->SHA_DGST0;
|
uint32_t *in_pos = (uint32_t *) &CRPT->SHA_DGST0;
|
||||||
unsigned char *out_pos = output;
|
unsigned char *out_pos = output;
|
||||||
uint32_t rmn = olen;
|
uint32_t rmn = olen;
|
||||||
|
|
||||||
while (rmn) {
|
while (rmn) {
|
||||||
uint32_t val = *in_pos ++;
|
uint32_t val = *in_pos ++;
|
||||||
nu_set32_be(out_pos, val);
|
nu_set32_be(out_pos, val);
|
||||||
|
|
|
@ -16,13 +16,6 @@
|
||||||
#ifndef MBEDTLS_SHA_ALT_HW_H
|
#ifndef MBEDTLS_SHA_ALT_HW_H
|
||||||
#define MBEDTLS_SHA_ALT_HW_H
|
#define MBEDTLS_SHA_ALT_HW_H
|
||||||
|
|
||||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
|
||||||
#include "config.h"
|
|
||||||
#else
|
|
||||||
#include MBEDTLS_CONFIG_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA1_C) || defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C)
|
|
||||||
#if defined(MBEDTLS_SHA1_ALT) || defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA512_ALT)
|
#if defined(MBEDTLS_SHA1_ALT) || defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA512_ALT)
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
@ -35,14 +28,13 @@ extern "C" {
|
||||||
/**
|
/**
|
||||||
* \brief SHA context structure
|
* \brief SHA context structure
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
uint32_t total; /*!< number of bytes processed */
|
uint32_t total; /*!< number of bytes processed */
|
||||||
unsigned char buffer[128]; /*!< data block being processed. Max of SHA-1/SHA-256/SHA-512 */
|
uint8_t buffer[128]; /*!< data block being processed. Max of SHA-1/SHA-256/SHA-512 */
|
||||||
uint16_t buffer_left;
|
uint16_t buffer_left;
|
||||||
uint16_t blocksize; /*!< block size */
|
uint16_t blocksize; /*!< block size */
|
||||||
uint32_t blocksize_mask; /*!< block size mask */
|
uint32_t blocksize_mask; /*!< block size mask */
|
||||||
|
|
||||||
int is224; /*!< 0 => SHA-256, else SHA-224 */
|
int is224; /*!< 0 => SHA-256, else SHA-224 */
|
||||||
}
|
}
|
||||||
crypto_sha_context;
|
crypto_sha_context;
|
||||||
|
@ -51,42 +43,33 @@ void crypto_sha_update(crypto_sha_context *ctx, const unsigned char *input, size
|
||||||
void crypto_sha_update_nobuf(crypto_sha_context *ctx, const unsigned char *input, size_t ilen, int islast);
|
void crypto_sha_update_nobuf(crypto_sha_context *ctx, const unsigned char *input, size_t ilen, int islast);
|
||||||
void crypto_sha_getinternstate(unsigned char output[], size_t olen);
|
void crypto_sha_getinternstate(unsigned char output[], size_t olen);
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA1_C)
|
|
||||||
#if defined(MBEDTLS_SHA1_ALT)
|
#if defined(MBEDTLS_SHA1_ALT)
|
||||||
|
|
||||||
void mbedtls_sha1_hw_init( crypto_sha_context *ctx );
|
void mbedtls_sha1_hw_init( crypto_sha_context *ctx );
|
||||||
void mbedtls_sha1_hw_free( crypto_sha_context *ctx );
|
void mbedtls_sha1_hw_free( crypto_sha_context *ctx );
|
||||||
void mbedtls_sha1_hw_clone( crypto_sha_context *dst,
|
|
||||||
const crypto_sha_context *src );
|
|
||||||
void mbedtls_sha1_hw_starts( crypto_sha_context *ctx );
|
void mbedtls_sha1_hw_starts( crypto_sha_context *ctx );
|
||||||
void mbedtls_sha1_hw_update( crypto_sha_context *ctx, const unsigned char *input, size_t ilen );
|
void mbedtls_sha1_hw_update( crypto_sha_context *ctx, const unsigned char *input, size_t ilen );
|
||||||
void mbedtls_sha1_hw_finish( crypto_sha_context *ctx, unsigned char output[20] );
|
void mbedtls_sha1_hw_finish( crypto_sha_context *ctx, unsigned char output[20] );
|
||||||
void mbedtls_sha1_hw_process( crypto_sha_context *ctx, const unsigned char data[64] );
|
void mbedtls_sha1_hw_process( crypto_sha_context *ctx, const unsigned char data[64] );
|
||||||
|
|
||||||
#endif /* MBEDTLS_SHA1_ALT */
|
#endif /* MBEDTLS_SHA1_ALT */
|
||||||
#endif /* MBEDTLS_SHA1_C */
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SHA256_C)
|
|
||||||
#if defined(MBEDTLS_SHA256_ALT)
|
#if defined(MBEDTLS_SHA256_ALT)
|
||||||
|
|
||||||
void mbedtls_sha256_hw_init( crypto_sha_context *ctx );
|
void mbedtls_sha256_hw_init( crypto_sha_context *ctx );
|
||||||
void mbedtls_sha256_hw_free( crypto_sha_context *ctx );
|
void mbedtls_sha256_hw_free( crypto_sha_context *ctx );
|
||||||
void mbedtls_sha256_hw_clone( crypto_sha_context *dst,
|
|
||||||
const crypto_sha_context *src );
|
|
||||||
void mbedtls_sha256_hw_starts( crypto_sha_context *ctx, int is224 );
|
void mbedtls_sha256_hw_starts( crypto_sha_context *ctx, int is224 );
|
||||||
void mbedtls_sha256_hw_update( crypto_sha_context *ctx, const unsigned char *input,
|
void mbedtls_sha256_hw_update( crypto_sha_context *ctx, const unsigned char *input,
|
||||||
size_t ilen );
|
size_t ilen );
|
||||||
void mbedtls_sha256_hw_finish( crypto_sha_context *ctx, unsigned char output[32] );
|
void mbedtls_sha256_hw_finish( crypto_sha_context *ctx, unsigned char output[32] );
|
||||||
void mbedtls_sha256_hw_process( crypto_sha_context *ctx, const unsigned char data[64] );
|
void mbedtls_sha256_hw_process( crypto_sha_context *ctx, const unsigned char data[64] );
|
||||||
|
|
||||||
#endif /* MBEDTLS_SHA256_ALT */
|
#endif /* MBEDTLS_SHA256_ALT */
|
||||||
#endif /* MBEDTLS_SHA256_C */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* MBEDTLS_SHA1_ALT || MBEDTLS_SHA256_ALT || MBEDTLS_SHA512_ALT */
|
#endif /* MBEDTLS_SHA1_ALT || MBEDTLS_SHA256_ALT || MBEDTLS_SHA512_ALT */
|
||||||
#endif /* MBEDTLS_SHA1_C || MBEDTLS_SHA256_C || MBEDTLS_SHA512_C */
|
|
||||||
|
|
||||||
#endif /* sha_alt.h */
|
#endif /* sha_alt_hw.h */
|
||||||
|
|
|
@ -140,6 +140,7 @@ USBHAL::USBHAL(void) {
|
||||||
defined(TARGET_NUCLEO_F401RE) || \
|
defined(TARGET_NUCLEO_F401RE) || \
|
||||||
defined(TARGET_NUCLEO_F411RE) || \
|
defined(TARGET_NUCLEO_F411RE) || \
|
||||||
defined(TARGET_NUCLEO_F412ZG) || \
|
defined(TARGET_NUCLEO_F412ZG) || \
|
||||||
|
defined(TARGET_NUCLEO_F413ZH) || \
|
||||||
defined(TARGET_NUCLEO_F429ZI) || \
|
defined(TARGET_NUCLEO_F429ZI) || \
|
||||||
defined(TARGET_NUCLEO_F446RE) || \
|
defined(TARGET_NUCLEO_F446RE) || \
|
||||||
defined(TARGET_NUCLEO_F446ZE) || \
|
defined(TARGET_NUCLEO_F446ZE) || \
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
defined(TARGET_NUCLEO_F401RE) || \
|
defined(TARGET_NUCLEO_F401RE) || \
|
||||||
defined(TARGET_NUCLEO_F411RE) || \
|
defined(TARGET_NUCLEO_F411RE) || \
|
||||||
defined(TARGET_NUCLEO_F412ZG) || \
|
defined(TARGET_NUCLEO_F412ZG) || \
|
||||||
|
defined(TARGET_NUCLEO_F413ZH) || \
|
||||||
defined(TARGET_NUCLEO_F429ZI) || \
|
defined(TARGET_NUCLEO_F429ZI) || \
|
||||||
defined(TARGET_NUCLEO_F446RE) || \
|
defined(TARGET_NUCLEO_F446RE) || \
|
||||||
defined(TARGET_NUCLEO_F446ZE) || \
|
defined(TARGET_NUCLEO_F446ZE) || \
|
||||||
|
|
|
@ -67,6 +67,7 @@ static gpio_t gpio_powerpin;
|
||||||
// NUCLEO_144 boards
|
// NUCLEO_144 boards
|
||||||
#elif defined(TARGET_NUCLEO_F207ZG) || \
|
#elif defined(TARGET_NUCLEO_F207ZG) || \
|
||||||
defined(TARGET_NUCLEO_F412ZG) || \
|
defined(TARGET_NUCLEO_F412ZG) || \
|
||||||
|
defined(TARGET_NUCLEO_F413ZH) || \
|
||||||
defined(TARGET_NUCLEO_F429ZI) || \
|
defined(TARGET_NUCLEO_F429ZI) || \
|
||||||
defined(TARGET_NUCLEO_F439ZI) || \
|
defined(TARGET_NUCLEO_F439ZI) || \
|
||||||
defined(TARGET_NUCLEO_F446ZE) || \
|
defined(TARGET_NUCLEO_F446ZE) || \
|
||||||
|
@ -189,6 +190,7 @@ USBHALHost::USBHALHost()
|
||||||
defined(TARGET_NUCLEO_L486RG) || \
|
defined(TARGET_NUCLEO_L486RG) || \
|
||||||
defined(TARGET_NUCLEO_F207ZG) || \
|
defined(TARGET_NUCLEO_F207ZG) || \
|
||||||
defined(TARGET_NUCLEO_F412ZG) || \
|
defined(TARGET_NUCLEO_F412ZG) || \
|
||||||
|
defined(TARGET_NUCLEO_F413ZH) || \
|
||||||
defined(TARGET_NUCLEO_F429ZI) || \
|
defined(TARGET_NUCLEO_F429ZI) || \
|
||||||
defined(TARGET_NUCLEO_F439ZI) || \
|
defined(TARGET_NUCLEO_F439ZI) || \
|
||||||
defined(TARGET_NUCLEO_F446ZE) || \
|
defined(TARGET_NUCLEO_F446ZE) || \
|
||||||
|
|
|
@ -21,7 +21,8 @@ CAN can1(PD_0, PD_1);
|
||||||
defined(TARGET_DISCO_F429ZI) || defined(TARGET_NUCLEO_F103RB) || \
|
defined(TARGET_DISCO_F429ZI) || defined(TARGET_NUCLEO_F103RB) || \
|
||||||
defined(TARGET_NUCLEO_F746ZG) || defined(TARGET_NUCLEO_L476RG) || \
|
defined(TARGET_NUCLEO_F746ZG) || defined(TARGET_NUCLEO_L476RG) || \
|
||||||
defined(TARGET_NUCLEO_F412ZG) || defined(TARGET_DISCO_F413ZH) || \
|
defined(TARGET_NUCLEO_F412ZG) || defined(TARGET_DISCO_F413ZH) || \
|
||||||
defined(TARGET_NUCLEO_L432KC) || defined(TARGET_DISCO_F303VC)
|
defined(TARGET_NUCLEO_L432KC) || defined(TARGET_DISCO_F303VC) || \
|
||||||
|
defined(TARGET_NUCLEO_F413ZH)
|
||||||
CAN can1(PA_11, PA_12);
|
CAN can1(PA_11, PA_12);
|
||||||
#elif defined(TARGET_DISCO_F469NI) ||defined(TARGET_DISCO_F746NG)
|
#elif defined(TARGET_DISCO_F469NI) ||defined(TARGET_DISCO_F746NG)
|
||||||
CAN can1(PB_8, PB_9);
|
CAN can1(PB_8, PB_9);
|
||||||
|
@ -36,7 +37,7 @@ CAN can2(p30, p29);
|
||||||
#elif defined(TARGET_NUCLEO_F446RE) || defined(TARGET_DISCO_F469NI) || \
|
#elif defined(TARGET_NUCLEO_F446RE) || defined(TARGET_DISCO_F469NI) || \
|
||||||
defined(TARGET_DISCO_F429ZI) || defined(TARGET_NUCLEO_F746ZG) || \
|
defined(TARGET_DISCO_F429ZI) || defined(TARGET_NUCLEO_F746ZG) || \
|
||||||
defined(TARGET_NUCLEO_F412ZG) || defined(TARGET_DISCO_F413ZH) || \
|
defined(TARGET_NUCLEO_F412ZG) || defined(TARGET_DISCO_F413ZH) || \
|
||||||
defined(TARGET_DISCO_F746NG)
|
defined(TARGET_DISCO_F746NG) || defined(TARGET_NUCLEO_F413ZH)
|
||||||
CAN can2(PB_5, PB_6);
|
CAN can2(PB_5, PB_6);
|
||||||
#endif
|
#endif
|
||||||
char counter = 0;
|
char counter = 0;
|
||||||
|
|
|
@ -21,7 +21,8 @@ CAN can1(PD_0, PD_1);
|
||||||
defined(TARGET_DISCO_F429ZI) || defined(TARGET_NUCLEO_F103RB) || \
|
defined(TARGET_DISCO_F429ZI) || defined(TARGET_NUCLEO_F103RB) || \
|
||||||
defined(TARGET_NUCLEO_F746ZG) || defined(TARGET_NUCLEO_L476RG) || \
|
defined(TARGET_NUCLEO_F746ZG) || defined(TARGET_NUCLEO_L476RG) || \
|
||||||
defined(TARGET_NUCLEO_F412ZG) || defined(TARGET_DISCO_F413ZH) || \
|
defined(TARGET_NUCLEO_F412ZG) || defined(TARGET_DISCO_F413ZH) || \
|
||||||
defined(TARGET_NUCLEO_L432KC) || defined(TARGET_DISCO_F303VC)
|
defined(TARGET_NUCLEO_L432KC) || defined(TARGET_DISCO_F303VC) || \
|
||||||
|
defined(TARGET_NUCLEO_F413ZH)
|
||||||
CAN can1(PA_11, PA_12);
|
CAN can1(PA_11, PA_12);
|
||||||
#elif defined(TARGET_DISCO_F469NI) || defined(TARGET_DISCO_F746NG)
|
#elif defined(TARGET_DISCO_F469NI) || defined(TARGET_DISCO_F746NG)
|
||||||
CAN can1(PB_8, PB_9);
|
CAN can1(PB_8, PB_9);
|
||||||
|
@ -36,7 +37,7 @@ CAN can2(p30, p29);
|
||||||
#elif defined(TARGET_NUCLEO_F446RE) || defined(TARGET_DISCO_F469NI) || \
|
#elif defined(TARGET_NUCLEO_F446RE) || defined(TARGET_DISCO_F469NI) || \
|
||||||
defined(TARGET_DISCO_F429ZI) || defined(TARGET_NUCLEO_F746ZG) || \
|
defined(TARGET_DISCO_F429ZI) || defined(TARGET_NUCLEO_F746ZG) || \
|
||||||
defined(TARGET_NUCLEO_F412ZG) || defined(TARGET_DISCO_F413ZH) || \
|
defined(TARGET_NUCLEO_F412ZG) || defined(TARGET_DISCO_F413ZH) || \
|
||||||
defined(TARGET_DISCO_F746NG)
|
defined(TARGET_DISCO_F746NG) || defined(TARGET_NUCLEO_F413ZH)
|
||||||
CAN can2(PB_5, PB_6);
|
CAN can2(PB_5, PB_6);
|
||||||
#endif
|
#endif
|
||||||
char counter = 0;
|
char counter = 0;
|
||||||
|
|
|
@ -20,7 +20,8 @@ CAN can1(P5_9, P5_10);
|
||||||
defined(TARGET_DISCO_F429ZI) || \
|
defined(TARGET_DISCO_F429ZI) || \
|
||||||
defined(TARGET_NUCLEO_F746ZG) || defined(TARGET_DISCO_L476VG) || defined(TARGET_DISCO_L475VG_IOT01A) || \
|
defined(TARGET_NUCLEO_F746ZG) || defined(TARGET_DISCO_L476VG) || defined(TARGET_DISCO_L475VG_IOT01A) || \
|
||||||
defined(TARGET_NUCLEO_F412ZG) || defined(TARGET_DISCO_F413ZH) || \
|
defined(TARGET_NUCLEO_F412ZG) || defined(TARGET_DISCO_F413ZH) || \
|
||||||
defined(TARGET_NUCLEO_L476RG) || defined(TARGET_NUCLEO_L432KC)
|
defined(TARGET_NUCLEO_L476RG) || defined(TARGET_NUCLEO_L432KC) || \
|
||||||
|
defined(TARGET_NUCLEO_F413ZH)
|
||||||
CAN can1(PA_11, PA_12);
|
CAN can1(PA_11, PA_12);
|
||||||
#elif defined(TARGET_DISCO_F469NI) || defined(TARGET_DISCO_F746NG) || \
|
#elif defined(TARGET_DISCO_F469NI) || defined(TARGET_DISCO_F746NG) || \
|
||||||
defined(TARGET_NUCLEO_F446ZE) || defined(TARGET_NUCLEO_F103RB) || \
|
defined(TARGET_NUCLEO_F446ZE) || defined(TARGET_NUCLEO_F103RB) || \
|
||||||
|
|
2
mbed.h
2
mbed.h
|
@ -22,7 +22,7 @@
|
||||||
// RTOS present, this is valid only for mbed OS 5
|
// RTOS present, this is valid only for mbed OS 5
|
||||||
#define MBED_MAJOR_VERSION 5
|
#define MBED_MAJOR_VERSION 5
|
||||||
#define MBED_MINOR_VERSION 7
|
#define MBED_MINOR_VERSION 7
|
||||||
#define MBED_PATCH_VERSION 2
|
#define MBED_PATCH_VERSION 3
|
||||||
|
|
||||||
#else
|
#else
|
||||||
// mbed 2
|
// mbed 2
|
||||||
|
|
|
@ -47,7 +47,6 @@
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
#include "PeripheralPins.h"
|
#include "PeripheralPins.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -80,7 +79,10 @@ void analogin_init(analogin_t *obj, PinName pin)
|
||||||
ADCName peripheral;
|
ADCName peripheral;
|
||||||
uint32_t function, channel;
|
uint32_t function, channel;
|
||||||
|
|
||||||
peripheral = (ADCName)pinmap_peripheral(pin, &PinMap_ADC[0]); // gives peripheral
|
memset(obj, 0, sizeof(analogin_t) );
|
||||||
|
memset( DeviceMemory, 0, sizeof( DeviceMemory ) );
|
||||||
|
|
||||||
|
peripheral = (ADCName)pinmap_peripheral(pin, &PinMap_ADC[0]); // gives peripheral
|
||||||
MBED_ASSERT(peripheral != (ADCName)NC);
|
MBED_ASSERT(peripheral != (ADCName)NC);
|
||||||
|
|
||||||
/* verify read function */
|
/* verify read function */
|
||||||
|
@ -142,6 +144,7 @@ void analogin_init(analogin_t *obj, PinName pin)
|
||||||
|
|
||||||
/* Set the acquisition time. (Application need to change it based on the impedence) */
|
/* Set the acquisition time. (Application need to change it based on the impedence) */
|
||||||
adi_adc_SetAcquisitionTime(hDevice, obj->SampleCycles);
|
adi_adc_SetAcquisitionTime(hDevice, obj->SampleCycles);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Read the input voltage, represented as a float in the range [0.0, 1.0]
|
/** Read the input voltage, represented as a float in the range [0.0, 1.0]
|
||||||
|
@ -165,6 +168,11 @@ uint16_t analogin_read_u16(analogin_t *obj)
|
||||||
{
|
{
|
||||||
ADI_ADC_HANDLE hDevice = obj->hDevice;
|
ADI_ADC_HANDLE hDevice = obj->hDevice;
|
||||||
ADI_ADC_BUFFER *pAdcBuffer;
|
ADI_ADC_BUFFER *pAdcBuffer;
|
||||||
|
uint32_t ADCsample;
|
||||||
|
|
||||||
|
obj->UserBuffer.pDataBuffer = &ADCsample;
|
||||||
|
obj->UserBuffer.nNumConversionPasses = 1;
|
||||||
|
obj->UserBuffer.nBuffSize = 1;
|
||||||
|
|
||||||
/* Submit the buffer to the driver */
|
/* Submit the buffer to the driver */
|
||||||
adi_adc_SubmitBuffer(hDevice, &obj->UserBuffer);
|
adi_adc_SubmitBuffer(hDevice, &obj->UserBuffer);
|
||||||
|
@ -178,8 +186,9 @@ uint16_t analogin_read_u16(analogin_t *obj)
|
||||||
return( (uint16_t)( ((uint16_t *)pAdcBuffer->pDataBuffer)[(pAdcBuffer->nNumConversionPasses) - 1]) );
|
return( (uint16_t)( ((uint16_t *)pAdcBuffer->pDataBuffer)[(pAdcBuffer->nNumConversionPasses) - 1]) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retrieve te active channel correspondoing to the input pin */
|
/* Retrieve the active channel corresponding to the input pin */
|
||||||
static uint32_t adi_pin2channel(PinName pin) {
|
static uint32_t adi_pin2channel(PinName pin)
|
||||||
|
{
|
||||||
|
|
||||||
uint32_t activech;
|
uint32_t activech;
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,10 @@ void analogin_init(analogin_t *obj, PinName pin)
|
||||||
ADCName peripheral;
|
ADCName peripheral;
|
||||||
uint32_t function, channel;
|
uint32_t function, channel;
|
||||||
|
|
||||||
peripheral = (ADCName)pinmap_peripheral(pin, &PinMap_ADC[0]); // gives peripheral
|
memset(obj, 0, sizeof(analogin_t) );
|
||||||
|
memset( DeviceMemory, 0, sizeof( DeviceMemory ) );
|
||||||
|
|
||||||
|
peripheral = (ADCName)pinmap_peripheral(pin, &PinMap_ADC[0]); // gives peripheral
|
||||||
MBED_ASSERT(peripheral != (ADCName)NC);
|
MBED_ASSERT(peripheral != (ADCName)NC);
|
||||||
|
|
||||||
/* verify read function */
|
/* verify read function */
|
||||||
|
@ -165,6 +168,11 @@ uint16_t analogin_read_u16(analogin_t *obj)
|
||||||
{
|
{
|
||||||
ADI_ADC_HANDLE hDevice = obj->hDevice;
|
ADI_ADC_HANDLE hDevice = obj->hDevice;
|
||||||
ADI_ADC_BUFFER *pAdcBuffer;
|
ADI_ADC_BUFFER *pAdcBuffer;
|
||||||
|
uint32_t ADCsample;
|
||||||
|
|
||||||
|
obj->UserBuffer.pDataBuffer = &ADCsample;
|
||||||
|
obj->UserBuffer.nNumConversionPasses = 1;
|
||||||
|
obj->UserBuffer.nBuffSize = 1;
|
||||||
|
|
||||||
/* Submit the buffer to the driver */
|
/* Submit the buffer to the driver */
|
||||||
adi_adc_SubmitBuffer(hDevice, &obj->UserBuffer);
|
adi_adc_SubmitBuffer(hDevice, &obj->UserBuffer);
|
||||||
|
@ -178,7 +186,7 @@ uint16_t analogin_read_u16(analogin_t *obj)
|
||||||
return( (uint16_t)( ((uint16_t *)pAdcBuffer->pDataBuffer)[(pAdcBuffer->nNumConversionPasses) - 1]) );
|
return( (uint16_t)( ((uint16_t *)pAdcBuffer->pDataBuffer)[(pAdcBuffer->nNumConversionPasses) - 1]) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retrieve te active channel correspondoing to the input pin */
|
/* Retrieve the active channel corresponding to the input pin */
|
||||||
static uint32_t adi_pin2channel(PinName pin)
|
static uint32_t adi_pin2channel(PinName pin)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Nordic Semiconductor ASA
|
* Copyright (c) 2013 Nordic Semiconductor ASA
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||||
* of conditions and the following disclaimer.
|
* of conditions and the following disclaimer.
|
||||||
*
|
*
|
||||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||||
* integrated circuit in a product or a software update for such product, must reproduce
|
* integrated circuit in a product or a software update for such product, must reproduce
|
||||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||||
* the documentation and/or other materials provided with the distribution.
|
* the documentation and/or other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||||
* used to endorse or promote products derived from this software without specific prior
|
* used to endorse or promote products derived from this software without specific prior
|
||||||
* written permission.
|
* written permission.
|
||||||
*
|
*
|
||||||
* 4. This software, with or without modification, must only be used with a
|
* 4. This software, with or without modification, must only be used with a
|
||||||
* Nordic Semiconductor ASA integrated circuit.
|
* Nordic Semiconductor ASA integrated circuit.
|
||||||
*
|
*
|
||||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||||
* engineered, decompiled, modified and/or disassembled.
|
* engineered, decompiled, modified and/or disassembled.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@
|
||||||
#include "app_error.h"
|
#include "app_error.h"
|
||||||
#include "app_util.h"
|
#include "app_util.h"
|
||||||
|
|
||||||
#define BLE_STACK_EVT_MSG_BUF_SIZE (sizeof(ble_evt_t) + (GATT_MTU_SIZE_DEFAULT)) /**< Size of BLE event message buffer. This will be provided to the SoftDevice while fetching an event. */
|
#define BLE_STACK_EVT_MSG_BUF_SIZE (sizeof(ble_evt_t) + (3 * sizeof(ble_gattc_attr_info_t)) + (GATT_MTU_SIZE_DEFAULT)) /**< Size of BLE event message buffer. This will be provided to the SoftDevice while fetching an event. */
|
||||||
#define BLE_STACK_HANDLER_SCHED_EVT_SIZE 0 /**< The size of the scheduler event used by SoftDevice handler when passing BLE events using the @ref app_scheduler. */
|
#define BLE_STACK_HANDLER_SCHED_EVT_SIZE 0 /**< The size of the scheduler event used by SoftDevice handler when passing BLE events using the @ref app_scheduler. */
|
||||||
|
|
||||||
/**@brief Application stack event handler type. */
|
/**@brief Application stack event handler type. */
|
||||||
|
|
|
@ -15,43 +15,88 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h> // uint32_t, UINT32_MAX
|
#include <stdint.h>
|
||||||
#include <assert.h> // uint32_t, UINT32_MAX
|
#include "app_util_platform.h"
|
||||||
#include "cmsis.h"
|
|
||||||
#include "nrf_soc.h"
|
|
||||||
#include "nrf_sdm.h"
|
|
||||||
#include "nrf_nvic.h"
|
|
||||||
|
|
||||||
static uint8_t _sd_state = 0;
|
#if defined(SOFTDEVICE_PRESENT)
|
||||||
static volatile uint32_t _entry_count = 0;
|
static volatile uint32_t nordic_cr_nested = 0;
|
||||||
|
|
||||||
|
static void nordic_nvic_critical_region_enter(void);
|
||||||
|
static void nordic_nvic_critical_region_exit(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
void core_util_critical_section_enter()
|
void core_util_critical_section_enter()
|
||||||
{
|
{
|
||||||
// if a critical section has already been entered, just update the counter
|
#ifdef NRF52
|
||||||
if (_entry_count) {
|
ASSERT(APP_LEVEL_PRIVILEGED == privilege_level_get())
|
||||||
++_entry_count;
|
#endif
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// in this path, a critical section has never been entered
|
#if defined(SOFTDEVICE_PRESENT)
|
||||||
// routine of SD V11 work even if the softdevice is not active
|
/* return value can be safely ignored */
|
||||||
sd_nvic_critical_region_enter(&_sd_state);
|
nordic_nvic_critical_region_enter();
|
||||||
|
#else
|
||||||
assert(_entry_count == 0); // entry count should always be equal to 0 at this point
|
app_util_disable_irq();
|
||||||
++_entry_count;
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_util_critical_section_exit()
|
void core_util_critical_section_exit()
|
||||||
{
|
{
|
||||||
assert(_entry_count > 0);
|
#ifdef NRF52
|
||||||
--_entry_count;
|
ASSERT(APP_LEVEL_PRIVILEGED == privilege_level_get())
|
||||||
|
#endif
|
||||||
|
|
||||||
// If their is other segments which have entered the critical section, just leave
|
#if defined(SOFTDEVICE_PRESENT)
|
||||||
if (_entry_count) {
|
/* return value can be safely ignored */
|
||||||
return;
|
nordic_nvic_critical_region_exit();
|
||||||
|
#else
|
||||||
|
app_util_enable_irq();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(SOFTDEVICE_PRESENT)
|
||||||
|
/**@brief Enters critical region.
|
||||||
|
*
|
||||||
|
* @post Application interrupts will be disabled.
|
||||||
|
* @sa nordic_nvic_critical_region_exit
|
||||||
|
*/
|
||||||
|
static inline void nordic_nvic_critical_region_enter(void)
|
||||||
|
{
|
||||||
|
int was_masked = __sd_nvic_irq_disable();
|
||||||
|
|
||||||
|
if (nordic_cr_nested == 0) {
|
||||||
|
nrf_nvic_state.__irq_masks[0] = ( NVIC->ICER[0] & __NRF_NVIC_APP_IRQS_0 );
|
||||||
|
NVIC->ICER[0] = __NRF_NVIC_APP_IRQS_0;
|
||||||
|
#ifdef NRF52
|
||||||
|
nrf_nvic_state.__irq_masks[1] = ( NVIC->ICER[1] & __NRF_NVIC_APP_IRQS_1 );
|
||||||
|
NVIC->ICER[1] = __NRF_NVIC_APP_IRQS_1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the last segment of the critical section, state should be restored as before entering
|
nordic_cr_nested++;
|
||||||
// the critical section
|
|
||||||
sd_nvic_critical_region_exit(_sd_state);
|
if (!was_masked) {
|
||||||
|
__sd_nvic_irq_enable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**@brief Exit critical region.
|
||||||
|
*
|
||||||
|
* @pre Application has entered a critical region using ::nordic_nvic_critical_region_enter.
|
||||||
|
* @post If not in a nested critical region, the application interrupts will restored to the state before ::nordic_nvic_critical_region_enter was called.
|
||||||
|
*/
|
||||||
|
static inline void nordic_nvic_critical_region_exit(void)
|
||||||
|
{
|
||||||
|
nordic_cr_nested--;
|
||||||
|
|
||||||
|
if (nordic_cr_nested == 0) {
|
||||||
|
int was_masked = __sd_nvic_irq_disable();
|
||||||
|
NVIC->ISER[0] = nrf_nvic_state.__irq_masks[0];
|
||||||
|
#ifdef NRF52
|
||||||
|
NVIC->ISER[1] = nrf_nvic_state.__irq_masks[1];
|
||||||
|
#endif
|
||||||
|
if (!was_masked) {
|
||||||
|
__sd_nvic_irq_enable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue