Skip to content

Commit

Permalink
Added unit tests for the nvmem module (#203)
Browse files Browse the repository at this point in the history
* Added unit tests for SGX HAL nvmem module
* Added SGX HAL unit tests to the CI
* Added check to avoid for buffer overrun on nvmem.c
  • Loading branch information
italo-sampaio authored Oct 2, 2024
1 parent 0ab82e4 commit b9fb7ae
Show file tree
Hide file tree
Showing 14 changed files with 615 additions and 9 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ jobs:

- name: Firmware HAL's x86 unit tests
run: firmware/src/hal/x86/test/run-all.sh

- name: Firmware HAL's SGX unit tests
run: firmware/src/hal/sgx/test/run-all.sh

- name: Firmware common lib unit tests
run: firmware/src/common/test/run-all.sh
Expand Down
1 change: 1 addition & 0 deletions firmware/coverage/gen-coverage
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ if [[ $1 == "exec" ]]; then
COVERAGE=y $REPOROOT/firmware/src/ledger/ui/test/run-all.sh
COVERAGE=y $REPOROOT/firmware/src/ledger/signer/test/run-all.sh
COVERAGE=y $REPOROOT/firmware/src/tcpsigner/test/run-all.sh
COVERAGE=y $REPOROOT/firmware/src/hal/sgx/test/run-all.sh

# Run tcpsigner test suite
pushd $REPOROOT/firmware/src/tcpsigner > /dev/null
Expand Down
5 changes: 3 additions & 2 deletions firmware/src/hal/include/hal/nvmem.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
/**
* @brief Write to non volatile memory
*
* @param key The key of the destination in non volatile memory
* @param dst The destination address in (non volatile) memory
* @param src The source address to write from
* @param length The amount of bytes to write
Expand Down Expand Up @@ -73,8 +72,10 @@ void nvmem_init();
* @param key a string key to uniquely identify the block
* @param addr the base address of the block
* @param size the size of the block in bytes
*
* @return whether the block was successfully registered
*/
void nvmem_register_block(char* key, void* addr, size_t size);
bool nvmem_register_block(char* key, void* addr, size_t size);

/**
* @brief Loads registered blocks into memory
Expand Down
9 changes: 8 additions & 1 deletion firmware/src/hal/sgx/src/trusted/nvmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,18 @@ void nvmem_init() {
nvm_blocks_count = 0;
}

void nvmem_register_block(char* key, void* addr, size_t size) {
bool nvmem_register_block(char* key, void* addr, size_t size) {
if (nvm_blocks_count >= MAX_NVM_BLOCKS) {
LOG("Error registering NVM block <%s>: too many blocks\n", key);
return false;
}

nvm_blocks[nvm_blocks_count].key = key;
nvm_blocks[nvm_blocks_count].addr = addr;
nvm_blocks[nvm_blocks_count].size = size;
nvm_blocks_count++;

return true;
}

static void clear_blocks() {
Expand Down
1 change: 1 addition & 0 deletions firmware/src/hal/sgx/test/common/assert_utils.h
37 changes: 37 additions & 0 deletions firmware/src/hal/sgx/test/common/common.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# The MIT License (MIT)
#
# Copyright (c) 2021 RSK Labs Ltd
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
# of the Software, and to permit persons to whom the Software is furnished to do
# so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

SRCDIR = ../../src/trusted
MOCKDIR = ../mock
HALINCDIR = ../../../../hal/include
TESTCOMMONDIR = ../common
CFLAGS = -Wall -Wextra -Werror -Wno-unused-parameter -Wno-unused-function
CFLAGS += -iquote $(SRCDIR) -iquote $(HALINCDIR)
CFLAGS += -iquote $(TESTCOMMONDIR)
CFLAGS += -iquote $(MOCKDIR)
CFLAGS += -DHSM_PLATFORM_SGX

VPATH += $(MOCKDIR):$(SRCDIR)

include ../../../../../coverage/coverage.mk

CFLAGS += $(COVFLAGS)
30 changes: 30 additions & 0 deletions firmware/src/hal/sgx/test/mock/mock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* The MIT License (MIT)
*
* Copyright (c) 2021 RSK Labs Ltd
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/

#ifndef __MOCK_H
#define __MOCK_H

#include "mock_secret_store.h"

#endif // #ifndef __MOCK_H
99 changes: 99 additions & 0 deletions firmware/src/hal/sgx/test/mock/mock_secret_store.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#include "mock_secret_store.h"

typedef struct mock_sest_register {
char *key;
uint8_t *secret;
size_t secret_length;
} mock_sest_register_t;

#define MOCK_SEST_MAX_REGISTERS 10
typedef struct mock_secret_store {
mock_sest_register_t registers[MOCK_SEST_MAX_REGISTERS];
size_t num_registers;
bool fail_next_read;
bool fail_next_write;
} mock_secret_store_t;

static mock_secret_store_t g_mock_secret_store;

bool mock_sest_exists(char *key) {
for (size_t i = 0; i < g_mock_secret_store.num_registers; i++) {
if (strcmp(g_mock_secret_store.registers[i].key, key) == 0) {
return true;
}
}
return false;
}

bool mock_sest_write(char *key, uint8_t *secret, size_t secret_length) {
if (g_mock_secret_store.fail_next_write) {
g_mock_secret_store.fail_next_write = false;
return false;
}
int register_index = -1;
for (size_t i = 0; i < g_mock_secret_store.num_registers; i++) {
if (strcmp(g_mock_secret_store.registers[i].key, key) == 0) {
register_index = i;
break;
}
}
if (register_index == -1) {
assert(g_mock_secret_store.num_registers < MOCK_SEST_MAX_REGISTERS);
register_index = g_mock_secret_store.num_registers;
}

mock_sest_register_t *new_register =
&g_mock_secret_store.registers[register_index];
new_register->key = malloc(strlen(key) + 1);
strcpy(new_register->key, key);
new_register->secret = malloc(secret_length);
memcpy(new_register->secret, secret, secret_length);
new_register->secret_length = secret_length;
g_mock_secret_store.num_registers++;

return true;
}

uint8_t mock_sest_read(char *key, uint8_t *dest, size_t dest_length) {
if (g_mock_secret_store.fail_next_read) {
g_mock_secret_store.fail_next_read = false;
return 0;
}
for (size_t i = 0; i < g_mock_secret_store.num_registers; i++) {
if (strcmp(g_mock_secret_store.registers[i].key, key) == 0) {
assert(dest_length >=
g_mock_secret_store.registers[i].secret_length);
memcpy(dest,
g_mock_secret_store.registers[i].secret,
g_mock_secret_store.registers[i].secret_length);
return g_mock_secret_store.registers[i].secret_length;
}
}
return 0;
}

void mock_sest_init() {
memset(&g_mock_secret_store, 0, sizeof(g_mock_secret_store));
}

void mock_sest_reset() {
for (size_t i = 0; i < g_mock_secret_store.num_registers; i++) {
free(g_mock_secret_store.registers[i].key);
free(g_mock_secret_store.registers[i].secret);
}
memset(&g_mock_secret_store, 0, sizeof(g_mock_secret_store));
}

void mock_sest_fail_next_read(bool fail) {
g_mock_secret_store.fail_next_read = fail;
}

void mock_sest_fail_next_write(bool fail) {
g_mock_secret_store.fail_next_write = fail;
}
93 changes: 93 additions & 0 deletions firmware/src/hal/sgx/test/mock/mock_secret_store.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/**
* The MIT License (MIT)
*
* Copyright (c) 2021 RSK Labs Ltd
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/

#ifndef __MOCK_SECRET_STORE_H
#define __MOCK_SECRET_STORE_H

#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

/**
* @brief Initializes the mock secret store
*/
void mock_sest_init();

/**
* @brief Mock implementation of sest_exists
*
* @param key the key for the secret
*
* @returns whether the provided key corresponds to a secret in the store
*/
bool mock_sest_exists(char *key);

/**
* @brief Mock implementation of sest_write
*
* @param key the key for the secret
* @param secret the secret to write
* @param secret_length the length of the secret
*
* @returns Whether the write was successful.
*
* NOTE: This mock implementation will always return true unless the
* fail_next_write flag is set.
*/
bool mock_sest_write(char *key, uint8_t *secret, size_t secret_length);

/**
* @brief Mock implementation of sest_read
*
* @param key the key for the secret
* @param dest the destination buffer for the read secret
* @param dest_length the length of the destination buffer
*
* @returns the length of the secret read, or ZERO upon error.
*
* NOTE: This mock implementation will fail if the fail_next_read flag is set,
* regardless of the key provided.
*/
uint8_t mock_sest_read(char *key, uint8_t *dest, size_t dest_length);

/**
* @brief Resets the mock secret store to its initial state
*/
void mock_sest_reset();

/**
* @brief Sets the value of the fail_next_read flag
*
* @param fail whether the next call to sest_read should fail
*/
void mock_sest_fail_next_read(bool fail);

/**
* @brief Sets the value of the fail_next_write flag
*
* @param fail whether the next call to sest_write should fail
*/
void mock_sest_fail_next_write(bool fail);

#endif // #ifndef __MOCK_SECRET_STORE_H
38 changes: 38 additions & 0 deletions firmware/src/hal/sgx/test/nvmem/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# The MIT License (MIT)
#
# Copyright (c) 2021 RSK Labs Ltd
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
# of the Software, and to permit persons to whom the Software is furnished to do
# so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

include ../common/common.mk

PROG = test.out
OBJS = nvmem.o test_nvmem.o mock_secret_store.o

all: $(PROG)

$(PROG): $(OBJS)
$(CC) $(COVFLAGS) -o $@ $^

.PHONY: clean test
clean:
rm -f $(PROG) *.o $(COVFILES)

test: all
./$(PROG)
Loading

0 comments on commit b9fb7ae

Please sign in to comment.