nvmem: test modifications to support the new scheme

This patch includes changes to support testing of the new nvmem
implementation.

Making fizz compatible required duplicating a lot of functionality
available in the test/ directory (fuzz/nvmem_tpm2_mock.c is very
similar to test/nvmem_tpm2_mock.c), but I could not find an easy way
to avoid it.

BRANCH=cr50, cr50-mp
BUG=b:69907320, b:129710256
CQ-DEPEND=CL:1496607
TEST=with the rest of the patches applied 'make buildall -j' succeeds,
     which confirms both test and fuzz success.

Change-Id: Ife999b04d22f8ddbe9ea5d35f4c3e21f57592754
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1450278
Reviewed-by: Andrey Pronin <apronin@chromium.org>
This commit is contained in:
Vadim Bendebury 2019-02-28 20:05:27 -08:00 committed by chrome-bot
parent 63bf8f8ba8
commit 1d6c7bb977
14 changed files with 3009 additions and 1227 deletions

View File

@ -9,15 +9,21 @@
#define __CROS_EC_CONFIG_CHIP_H
/* Memory mapping */
#if !defined(TEST_NVMEM) && !defined(TEST_CR50_FUZZ)
#define CONFIG_FLASH_SIZE 0x00020000
#define CONFIG_FLASH_BANK_SIZE 0x1000
#else
#define CONFIG_FLASH_SIZE (512 * 1024)
#define CONFIG_FLASH_BANK_SIZE 0x800
#endif
extern char __host_flash[CONFIG_FLASH_SIZE];
#define CONFIG_PROGRAM_MEMORY_BASE ((uintptr_t)__host_flash)
#define CONFIG_FLASH_BANK_SIZE 0x1000
#define CONFIG_FLASH_ERASE_SIZE 0x0010 /* erase bank size */
#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */
#define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x0080 /* ideal write size */
#define CONFIG_RAM_BASE 0x0 /* Not supported */
#define CONFIG_PROGRAM_MEMORY_BASE ((uintptr_t)__host_flash)
#define CONFIG_FLASH_ERASE_SIZE 0x0010 /* erase bank size */
#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */
#define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x0080 /* ideal write size */
#define CONFIG_RAM_BASE 0x0 /* Not supported */
#define CONFIG_RAM_SIZE 0x0 /* Not supported */
#define CONFIG_FPU

View File

@ -25,7 +25,7 @@ endif
# Does your object file need to link against cstdlib?
# Yes -> use <obj_name>-rw
# Otherwise use <obj_name>-y
cr50_fuzz-rw = cr50_fuzz.o pinweaver_model.o mem_hash_tree.o
cr50_fuzz-rw = cr50_fuzz.o pinweaver_model.o mem_hash_tree.o nvmem_tpm2_mock.o
host_command_fuzz-y = host_command_fuzz.o
usb_pd_fuzz-y = usb_pd_fuzz.o
@ -35,6 +35,9 @@ $(out)/RW/fuzz/pinweaver_model.o: ${CR50_PROTO_HEADERS}
$(out)/RW/fuzz/cr50_fuzz.o: ${CR50_PROTO_HEADERS}
$(out)/RW/fuzz/cr50_fuzz.o: CPPFLAGS+=${LIBPROTOBUF_MUTATOR_CFLAGS}
TPM2_LIB_ROOT := $(CROS_WORKON_SRCROOT)/src/third_party/tpm2
$(out)/RW/fuzz/nvmem_tpm2_mock.o: CFLAGS += -I$(TPM2_LIB_ROOT)
$(out)/cr50_fuzz.exe: $(out)/cryptoc/libcryptoc.a \
$(out)/gen/fuzz/cr50_fuzz.pb.o \
$(out)/gen/fuzz/pinweaver/pinweaver.pb.o \

View File

@ -71,7 +71,6 @@ void InitializeFuzzerRun() {
memset(__host_flash, 0xff, sizeof(__host_flash));
nvmem_init();
nvmem_enable_commits();
initvars();
srand(0);
}

View File

@ -17,6 +17,7 @@
#define CONFIG_PINWEAVER
#define CONFIG_UPTO_SHA512
#define SHA512_SUPPORT
#define CONFIG_MALLOC
/******************************************************************************/
/* From chip/g/config_chip.h */
@ -29,6 +30,11 @@
/******************************************************************************/
/* From board/cr50/board.h */
/* Non-volatile counter storage for U2F */
#define CONFIG_CRC8
#define CONFIG_FLASH_ERASED_VALUE32 (-1U)
#define CONFIG_FLASH_LOG
#define CONFIG_FLASH_LOG_BASE CONFIG_PROGRAM_MEMORY_BASE
#define CONFIG_FLASH_LOG_SPACE 0x800
#define CONFIG_FLASH_NVCOUNTER
#define CONFIG_FLASH_NVCTR_SIZE CONFIG_FLASH_BANK_SIZE
#define CONFIG_FLASH_NVCTR_BASE_A (CONFIG_PROGRAM_MEMORY_BASE + \
@ -41,14 +47,23 @@
#define CONFIG_FLASH_NVMEM_OFFSET_A (CFG_TOP_A_OFF + CONFIG_FLASH_NVCTR_SIZE)
#define CONFIG_FLASH_NVMEM_OFFSET_B (CFG_TOP_B_OFF + CONFIG_FLASH_NVCTR_SIZE)
/* Address of start of Nvmem area */
#define CONFIG_FLASH_NVMEM_BASE_A (CONFIG_PROGRAM_MEMORY_BASE + \
CONFIG_FLASH_NVMEM_OFFSET_A)
#define CONFIG_FLASH_NVMEM_BASE_B (CONFIG_PROGRAM_MEMORY_BASE + \
CONFIG_FLASH_NVMEM_OFFSET_B)
#define CONFIG_FLASH_NVMEM_BASE_A \
(CONFIG_PROGRAM_MEMORY_BASE + CONFIG_FLASH_NVMEM_OFFSET_A)
#define CONFIG_FLASH_NVMEM_BASE_B \
(CONFIG_PROGRAM_MEMORY_BASE + CONFIG_FLASH_NVMEM_OFFSET_B)
#define CONFIG_FLASH_NEW_NVMEM_BASE_A \
(CONFIG_FLASH_NVMEM_BASE_A + CONFIG_FLASH_BANK_SIZE)
#define CONFIG_FLASH_NEW_NVMEM_BASE_B \
(CONFIG_FLASH_NVMEM_BASE_B + CONFIG_FLASH_BANK_SIZE)
/* Size partition in NvMem */
#define NVMEM_PARTITION_SIZE (CFG_TOP_SIZE - CONFIG_FLASH_NVCTR_SIZE)
/* Size in bytes of NvMem area */
#define CONFIG_FLASH_NVMEM_SIZE (NVMEM_PARTITION_SIZE * NVMEM_NUM_PARTITIONS)
#define NEW_NVMEM_PARTITION_SIZE (NVMEM_PARTITION_SIZE - CONFIG_FLASH_BANK_SIZE)
#define NEW_NVMEM_TOTAL_PAGES \
(2 * NEW_NVMEM_PARTITION_SIZE / CONFIG_FLASH_BANK_SIZE)
/* Enable <key, value> variable support. */
#define CONFIG_FLASH_NVMEM_VARS
#define NVMEM_CR50_SIZE 272

228
fuzz/nvmem_tpm2_mock.c Normal file
View File

@ -0,0 +1,228 @@
/* Copyright 2019 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* Stuff from tpm2 directory. */
#define NV_C
#include "Global.h"
#undef NV_C
#include "NV_fp.h"
#include "tpm_generated.h"
#include "nvmem.h"
#include "util.h"
#define NVMEM_CR50_SIZE 272
#ifndef TEST_FUZZ
uint32_t nvmem_user_sizes[NVMEM_NUM_USERS] = {MOCK_NV_MEMORY_SIZE,
NVMEM_CR50_SIZE};
#endif
uint32_t s_evictNvStart;
uint32_t s_evictNvEnd;
/* Calculate size of TPM NVMEM. */
#define MOCK_NV_MEMORY_SIZE \
(NVMEM_PARTITION_SIZE - sizeof(struct nvmem_tag) - NVMEM_CR50_SIZE)
/*
* Sizes of the reserved objects stored in the TPM NVMEM. Note that the second
* last object is in fact a variable size field starting with 4 bytes of size
* and then up to 512 bytes of actual index data. The array below assumes that
* the full 512 bytes of the index space are used.
*/
const uint16_t res_sizes[] = {4, 2, 2, 2, 66, 66, 66, 66, 66, 66,
34, 34, 34, 66, 66, 66, 8, 4, 134, 28,
3, 4, 4, 4, 4, 4, 2, 15, 2, 8,
4, 4, 4, 96, 2844, 424, 516, 8};
static uint16_t res_addrs[ARRAY_SIZE(res_sizes)];
BOOL NvEarlyStageFindHandle(TPM_HANDLE handle)
{
size_t i;
res_addrs[0] = 0;
for (i = 1; i < ARRAY_SIZE(res_addrs); i++)
res_addrs[i] = res_addrs[i - 1] + res_sizes[i - 1];
s_evictNvStart = res_addrs[i - 1] + res_sizes[i - 1];
s_evictNvEnd = MOCK_NV_MEMORY_SIZE;
return 0;
}
void NvGetReserved(UINT32 index, NV_RESERVED_ITEM *ri)
{
if (index < ARRAY_SIZE(res_sizes)) {
ri->size = res_sizes[index];
ri->offset = res_addrs[index];
} else {
ri->size = 0;
}
}
UINT16 UINT16_Marshal(UINT16 *source, BYTE **buffer, INT32 *size)
{
uint16_t value;
if (!size || (*size < sizeof(value)))
return 0;
value = htobe16(*source);
memcpy(*buffer, &value, sizeof(value));
*buffer += sizeof(value);
*size -= sizeof(value);
return sizeof(value);
}
UINT16 UINT32_Marshal(UINT32 *source, BYTE **buffer, INT32 *size)
{
uint32_t value;
if (!size || (*size < sizeof(value)))
return 0;
value = htobe32(*source);
memcpy(*buffer, &value, sizeof(value));
*buffer += sizeof(value);
*size -= sizeof(value);
return sizeof(value);
}
UINT16 UINT64_Marshal(UINT64 *source, BYTE **buffer, INT32 *size)
{
uint64_t value;
if (!size || (*size < sizeof(value)))
return 0;
value = htobe64(*source);
memcpy(*buffer, &value, sizeof(value));
*buffer += sizeof(value);
*size -= sizeof(value);
return sizeof(value);
}
UINT16 TPM2B_DIGEST_Marshal(TPM2B_DIGEST *source, BYTE **buffer, INT32 *size)
{
UINT16 total_size;
INT32 i;
uint8_t *p;
total_size = UINT16_Marshal(&source->t.size, buffer, size);
p = *buffer;
for (i = 0; (i < source->t.size) && *size; ++i) {
*p++ = source->t.buffer[i];
*size -= 1;
}
total_size += i;
*buffer = p;
return total_size;
}
uint16_t TPM2B_AUTH_Marshal(TPM2B_AUTH *source, BYTE **buffer, INT32 *size)
{
return TPM2B_DIGEST_Marshal(source, buffer, size);
}
uint16_t TPM2B_NONCE_Marshal(TPM2B_AUTH *source, BYTE **buffer, INT32 *size)
{
return TPM2B_DIGEST_Marshal(source, buffer, size);
}
TPM_RC UINT16_Unmarshal(UINT16 *target, BYTE **buffer, INT32 *size)
{
uint16_t value;
if (!size || *size < sizeof(value))
return TPM_RC_INSUFFICIENT;
memcpy(&value, *buffer, sizeof(value));
*target = be16toh(value);
*buffer += sizeof(value);
*size -= sizeof(value);
return TPM_RC_SUCCESS;
}
TPM_RC UINT32_Unmarshal(UINT32 *target, BYTE **buffer, INT32 *size)
{
uint32_t value;
if (!size || *size < sizeof(value))
return TPM_RC_INSUFFICIENT;
memcpy(&value, *buffer, sizeof(value));
*target = be32toh(value);
*buffer += sizeof(value);
*size -= sizeof(value);
return TPM_RC_SUCCESS;
}
TPM_RC UINT64_Unmarshal(UINT64 *target, BYTE **buffer, INT32 *size)
{
uint64_t value;
if (!size || *size < sizeof(value))
return TPM_RC_INSUFFICIENT;
memcpy(&value, *buffer, sizeof(value));
*target = be64toh(value);
*buffer += sizeof(value);
*size -= sizeof(value);
return TPM_RC_SUCCESS;
}
TPM_RC TPM2B_DIGEST_Unmarshal(TPM2B_DIGEST *target, BYTE **buffer, INT32 *size)
{
TPM_RC result;
INT32 i;
uint8_t *p;
result = UINT16_Unmarshal(&target->t.size, buffer, size);
if (result != TPM_RC_SUCCESS)
return result;
if (target->t.size == 0)
return TPM_RC_SUCCESS;
if ((target->t.size > sizeof(TPMU_HA)) || (target->t.size > *size))
return TPM_RC_SIZE;
p = *buffer;
for (i = 0; i < target->t.size; ++i)
target->t.buffer[i] = *p++;
*buffer = p;
*size -= i;
return TPM_RC_SUCCESS;
}
TPM_RC TPM2B_AUTH_Unmarshal(TPM2B_AUTH *target, BYTE **buffer, INT32 *size)
{
return TPM2B_DIGEST_Unmarshal(target, buffer, size);
}
TPM_RC TPM2B_NONCE_Unmarshal(TPM2B_AUTH *target, BYTE **buffer, INT32 *size)
{
return TPM2B_DIGEST_Unmarshal(target, buffer, size);
}

View File

@ -47,7 +47,6 @@ test-list-host += motion_angle_tablet
test-list-host += motion_lid
test-list-host += mutex
test-list-host += nvmem
test-list-host += nvmem_vars
test-list-host += pingpong
test-list-host += pinweaver
test-list-host += power_button
@ -105,8 +104,7 @@ motion_angle-y=motion_angle.o motion_angle_data_literals.o motion_common.o
motion_angle_tablet-y=motion_angle_tablet.o motion_angle_data_literals_tablet.o motion_common.o
motion_lid-y=motion_lid.o
mutex-y=mutex.o
nvmem-y=nvmem.o
nvmem_vars-y=nvmem_vars.o
nvmem-y=nvmem.o nvmem_tpm2_mock.o
pingpong-y=pingpong.o
pinweaver-y=pinweaver.o
power_button-y=power_button.o
@ -135,3 +133,8 @@ vboot-y=vboot.o
float-y=fp.o
fp-y=fp.o
x25519-y=x25519.o
TPM2_ROOT := $(CROS_WORKON_SRCROOT)/src/third_party/tpm2
$(out)/RO/common/new_nvmem.o: CFLAGS += -I$(TPM2_ROOT)
$(out)/RO/test/nvmem.o: CFLAGS += -I$(TPM2_ROOT)
$(out)/RO/test/nvmem_tpm2_mock.o: CFLAGS += -I$(TPM2_ROOT)

1043
test/legacy_nvmem_dump.h Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

28
test/nvmem_test.h Normal file
View File

@ -0,0 +1,28 @@
/* Copyright 2019 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef __EC_TEST_NVMEM_TEST_H
#define __EC_TEST_NVMEM_TEST_H
#define EMBEDDED_MODE 1
#define NV_C
#include "Global.h"
#undef NV_C
#include "NV_fp.h"
#include "tpm_generated.h"
enum test_failure_mode {
TEST_NO_FAILURE,
TEST_FAIL_WHEN_SAVING,
TEST_FAIL_WHEN_INVALIDATING,
TEST_FAIL_WHEN_COMPACTING
};
extern enum test_failure_mode failure_mode;
size_t add_evictable_obj(void *obj, size_t obj_size);
void drop_evictable_obj(void *obj);
#endif /* ! __EC_TEST_NVMEM_TEST_H */

377
test/nvmem_tpm2_mock.c Normal file
View File

@ -0,0 +1,377 @@
/* Copyright 2019 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* Stuff from tpm2 directory. */
#include "nvmem_test.h"
#include "console.h"
#include "nvmem.h"
#include "util.h"
#define NVMEM_CR50_SIZE 272
uint32_t s_evictNvStart;
uint32_t s_evictNvEnd;
/* Calculate size of TPM NVMEM. */
#define MOCK_NV_MEMORY_SIZE \
(NVMEM_PARTITION_SIZE - sizeof(struct nvmem_tag) - NVMEM_CR50_SIZE)
uint32_t nvmem_user_sizes[NVMEM_NUM_USERS] = {MOCK_NV_MEMORY_SIZE,
NVMEM_CR50_SIZE};
/*
* Sizes of the reserved objects stored in the TPM NVMEM. Note that the second
* last object is in fact a variable size field starting with 4 bytes of size
* and then up to 512 bytes of actual index data. The array below assumes that
* the full 512 bytes of the index space are used.
*/
const uint16_t res_sizes[] = {4, 2, 2, 2, 66, 66, 66, 66, 66, 66,
34, 34, 34, 66, 66, 66, 8, 4, 134, 28,
3, 4, 4, 4, 4, 4, 2, 15, 2, 8,
4, 4, 4, 96, 2844, 424, 516, 8};
static uint16_t res_addrs[ARRAY_SIZE(res_sizes)];
BOOL NvEarlyStageFindHandle(TPM_HANDLE handle)
{
size_t i;
res_addrs[0] = 0;
for (i = 1; i < ARRAY_SIZE(res_addrs); i++)
res_addrs[i] = res_addrs[i - 1] + res_sizes[i - 1];
s_evictNvStart = res_addrs[i - 1] + res_sizes[i - 1];
s_evictNvEnd = MOCK_NV_MEMORY_SIZE;
return 0;
}
void NvGetReserved(UINT32 index, NV_RESERVED_ITEM *ri)
{
uint32_t index_size;
if (index >= ARRAY_SIZE(res_sizes)) {
ri->size = 0;
return;
}
ri->offset = res_addrs[index];
if (index != NV_RAM_INDEX_SPACE) {
ri->size = res_sizes[index];
return;
}
memcpy(&index_size, nvmem_cache_base(NVMEM_TPM) + ri->offset,
sizeof(index_size));
if (index_size == ~0)
/* Must be starting with empty flash memeory. */
index_size = 0;
ri->size = index_size + sizeof(index_size);
}
UINT16 UINT16_Marshal(UINT16 *source, BYTE **buffer, INT32 *size)
{
uint16_t value;
if (!size || (*size < sizeof(value)))
return 0;
value = htobe16(*source);
memcpy(*buffer, &value, sizeof(value));
*buffer += sizeof(value);
*size -= sizeof(value);
return sizeof(value);
}
UINT16 UINT32_Marshal(UINT32 *source, BYTE **buffer, INT32 *size)
{
uint32_t value;
if (!size || (*size < sizeof(value)))
return 0;
value = htobe32(*source);
memcpy(*buffer, &value, sizeof(value));
*buffer += sizeof(value);
*size -= sizeof(value);
return sizeof(value);
}
UINT16 UINT64_Marshal(UINT64 *source, BYTE **buffer, INT32 *size)
{
uint64_t value;
if (!size || (*size < sizeof(value)))
return 0;
value = htobe64(*source);
memcpy(*buffer, &value, sizeof(value));
*buffer += sizeof(value);
*size -= sizeof(value);
return sizeof(value);
}
UINT16 TPM2B_DIGEST_Marshal(TPM2B_DIGEST *source, BYTE **buffer, INT32 *size)
{
UINT16 total_size;
INT32 i;
uint8_t *p;
total_size = UINT16_Marshal(&source->t.size, buffer, size);
p = *buffer;
for (i = 0; (i < source->t.size) && *size; ++i) {
*p++ = source->t.buffer[i];
*size -= 1;
}
total_size += i;
*buffer = p;
return total_size;
}
uint16_t TPM2B_AUTH_Marshal(TPM2B_AUTH *source, BYTE **buffer, INT32 *size)
{
return TPM2B_DIGEST_Marshal(source, buffer, size);
}
uint16_t TPM2B_NONCE_Marshal(TPM2B_AUTH *source, BYTE **buffer, INT32 *size)
{
return TPM2B_DIGEST_Marshal(source, buffer, size);
}
TPM_RC UINT16_Unmarshal(UINT16 *target, BYTE **buffer, INT32 *size)
{
uint16_t value;
if (!size || *size < sizeof(value))
return TPM_RC_INSUFFICIENT;
memcpy(&value, *buffer, sizeof(value));
*target = be16toh(value);
*buffer += sizeof(value);
*size -= sizeof(value);
return TPM_RC_SUCCESS;
}
TPM_RC UINT32_Unmarshal(UINT32 *target, BYTE **buffer, INT32 *size)
{
uint32_t value;
if (!size || *size < sizeof(value))
return TPM_RC_INSUFFICIENT;
memcpy(&value, *buffer, sizeof(value));
*target = be32toh(value);
*buffer += sizeof(value);
*size -= sizeof(value);
return TPM_RC_SUCCESS;
}
TPM_RC UINT64_Unmarshal(UINT64 *target, BYTE **buffer, INT32 *size)
{
uint64_t value;
if (!size || *size < sizeof(value))
return TPM_RC_INSUFFICIENT;
memcpy(&value, *buffer, sizeof(value));
*target = be64toh(value);
*buffer += sizeof(value);
*size -= sizeof(value);
return TPM_RC_SUCCESS;
}
TPM_RC TPM2B_DIGEST_Unmarshal(TPM2B_DIGEST *target, BYTE **buffer, INT32 *size)
{
TPM_RC result;
INT32 i;
uint8_t *p;
result = UINT16_Unmarshal(&target->t.size, buffer, size);
if (result != TPM_RC_SUCCESS)
return result;
if (target->t.size == 0)
return TPM_RC_SUCCESS;
if ((target->t.size > sizeof(TPMU_HA)) || (target->t.size > *size))
return TPM_RC_SIZE;
p = *buffer;
for (i = 0; i < target->t.size; ++i)
target->t.buffer[i] = *p++;
*buffer = p;
*size -= i;
return TPM_RC_SUCCESS;
}
TPM_RC TPM2B_AUTH_Unmarshal(TPM2B_AUTH *target, BYTE **buffer, INT32 *size)
{
return TPM2B_DIGEST_Unmarshal(target, buffer, size);
}
TPM_RC TPM2B_NONCE_Unmarshal(TPM2B_AUTH *target, BYTE **buffer, INT32 *size)
{
return TPM2B_DIGEST_Unmarshal(target, buffer, size);
}
#define ITER_INIT (~0)
static void *get_cache_addr(size_t offset)
{
return (void *)(((uintptr_t)nvmem_cache_base(NVMEM_TPM)) + offset);
}
static void read_from_cache(size_t offset, size_t size, void *dest)
{
nvmem_read(offset, size, dest, NVMEM_TPM);
}
static void write_to_cache(size_t offset, size_t size, void *src)
{
nvmem_write(offset, size, src, NVMEM_TPM);
}
/* Copies of the appropriate functions from NV.c in TPM2 library. */
static uint32_t nv_next(uint32_t *iter)
{
uint32_t currentIter;
if (*iter == ITER_INIT)
*iter = s_evictNvStart;
if ((*iter + sizeof(uint32_t) > s_evictNvEnd) || !*iter)
return 0;
currentIter = *iter;
read_from_cache(*iter, sizeof(uint32_t), iter);
if (!*iter || (*iter == ITER_INIT))
return 0;
return currentIter + sizeof(uint32_t);
}
static uint32_t nv_get_end(void)
{
uint32_t iter = ITER_INIT;
uint32_t endAddr = s_evictNvStart;
uint32_t currentAddr;
while ((currentAddr = nv_next(&iter)) != 0)
endAddr = currentAddr;
if (endAddr != s_evictNvStart) {
/* Read offset. */
endAddr -= sizeof(uint32_t);
read_from_cache(endAddr, sizeof(uint32_t), &endAddr);
}
return endAddr;
}
size_t add_evictable_obj(void *obj, size_t obj_size)
{
uint32_t end_addr;
uint32_t next_addr;
uint32_t list_end = 0;
end_addr = nv_get_end();
next_addr = end_addr + sizeof(uint32_t) + obj_size;
if (next_addr >= s_evictNvEnd) {
ccprintf("%s: could not fit %d bytes!\n", __func__, obj_size);
return 0;
}
/* Write next pointer */
write_to_cache(end_addr, sizeof(uint32_t), &next_addr);
/* Write entity data. */
write_to_cache(end_addr + sizeof(uint32_t), obj_size, obj);
/* Write the end of list if it fits. */
if (next_addr + sizeof(uint32_t) <= s_evictNvEnd)
write_to_cache(next_addr, sizeof(list_end), &list_end);
return obj_size;
}
/*
* It is the responsibility of the caller to pass the proper address of an
* object in the cache.
*/
void drop_evictable_obj(void *obj)
{
uint32_t next_addr;
uint32_t list_end = 0;
uint32_t obj_addr;
obj_addr = (uintptr_t)obj - (uintptr_t)nvmem_cache_base(NVMEM_TPM);
read_from_cache(obj_addr - sizeof(next_addr), sizeof(next_addr),
&next_addr);
ccprintf("%s:%d dropping obj at cache addr %x, offset %x, addr %p next "
"addr %x aka %x (off s_evictNvStart)\n",
__func__, __LINE__, obj_addr - s_evictNvStart, obj_addr, obj,
next_addr, next_addr - s_evictNvStart);
/*
* Now, to make it easier to add objects behind the current one, let's
* pretend there is no more objects.
*/
write_to_cache(obj_addr - sizeof(next_addr), sizeof(list_end),
&list_end);
if (!next_addr || (next_addr == s_evictNvEnd))
return;
/*
* Iterate over objects starting with next_addr, copying them into
* obj_addr.
*/
obj_addr = next_addr;
while (1) {
uint32_t next_next_addr;
uint32_t next_obj_size;
read_from_cache(next_addr, sizeof(next_next_addr),
&next_next_addr);
if (!next_next_addr || (next_next_addr == s_evictNvEnd))
return;
next_obj_size = next_next_addr - obj_addr - sizeof(uint32_t);
add_evictable_obj(
(void *)((uintptr_t)nvmem_cache_base(NVMEM_TPM) +
next_addr + sizeof(uint32_t)),
next_obj_size);
next_addr = next_next_addr;
obj_addr += next_obj_size + sizeof(next_obj_size);
}
}
void *evictable_offs_to_addr(uint16_t offset)
{
return (void *)((uintptr_t)get_cache_addr(s_evictNvStart) + offset);
}

View File

@ -1,538 +0,0 @@
/* Copyright 2016 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* Test of the key=val variable implementation (set, get, delete, etc).
*/
#include "common.h"
#include "compile_time_macros.h"
#include "nvmem.h"
#include "nvmem_vars.h"
#include "printf.h"
#include "shared_mem.h"
#include "test_util.h"
/* Declare the user regions (see test_config.h) */
uint32_t nvmem_user_sizes[] = {
CONFIG_FLASH_NVMEM_VARS_USER_SIZE,
};
BUILD_ASSERT(ARRAY_SIZE(nvmem_user_sizes) == NVMEM_NUM_USERS);
/****************************************************************************/
/* Mock the flash storage */
static uint8_t ram_buffer[CONFIG_FLASH_NVMEM_VARS_USER_SIZE];
static uint8_t flash_buffer[CONFIG_FLASH_NVMEM_VARS_USER_SIZE];
extern char *rbuf;
/* Internal functions exported for test */
void release_local_copy(void)
{
rbuf = NULL;
}
int get_local_copy(void)
{
if (!rbuf) {
memcpy(ram_buffer, flash_buffer, sizeof(ram_buffer));
rbuf = (char *)ram_buffer;
}
return EC_SUCCESS;
}
int nvmem_read(uint32_t startOffset, uint32_t size,
void *data_, enum nvmem_users user)
{
/* Our mocks make some assumptions */
if (startOffset != 0 ||
size > CONFIG_FLASH_NVMEM_VARS_USER_SIZE ||
user != CONFIG_FLASH_NVMEM_VARS_USER_NUM)
return EC_ERROR_UNIMPLEMENTED;
if (!data_)
return EC_ERROR_INVAL;
memcpy(data_, flash_buffer, size);
return EC_SUCCESS;
}
int nvmem_write(uint32_t startOffset, uint32_t size,
void *data_, enum nvmem_users user)
{
/* Our mocks make some assumptions */
if (startOffset != 0 ||
size > CONFIG_FLASH_NVMEM_VARS_USER_SIZE ||
user != CONFIG_FLASH_NVMEM_VARS_USER_NUM)
return EC_ERROR_UNIMPLEMENTED;
if (!data_)
return EC_ERROR_INVAL;
memcpy(ram_buffer, data_, size);
return EC_SUCCESS;
}
int nvmem_commit(void)
{
memcpy(flash_buffer, ram_buffer, CONFIG_FLASH_NVMEM_VARS_USER_SIZE);
return EC_SUCCESS;
}
int nvmem_erase_user_data(enum nvmem_users user)
{
memset(ram_buffer, 0xff, sizeof(ram_buffer));
memset(flash_buffer, 0xff, sizeof(flash_buffer));
return EC_SUCCESS;
}
/****************************************************************************/
/* Helper routines */
static void erase_flash(void)
{
/* Invalidate the RAM cache */
release_local_copy();
/* Zero flash */
memset(flash_buffer, 0xff, sizeof(flash_buffer));
}
/* Erase flash, then copy data_ over it */
static void load_flash(const uint8_t *data_, size_t data_len)
{
erase_flash();
memcpy(flash_buffer, data_, data_len);
}
/* Return true if flash matches data_, and is followed by 0xff to the end */
static int verify_flash(const uint8_t *data_, size_t data_len)
{
size_t i;
/* mismatch means false */
if (memcmp(flash_buffer, data_, data_len))
return 0;
for (i = data_len;
i < CONFIG_FLASH_NVMEM_VARS_USER_SIZE - data_len;
i++)
if (flash_buffer[i] != 0xff)
return 0;
return 1;
}
/*
* Treating both as strings, save the <key, value> pair.
*/
int str_setvar(const char *key, const char *val)
{
/* Only for tests, so assume the length will fit */
uint8_t key_len, val_len;
key_len = strlen(key);
val_len = val ? strlen(val) : 0;
return setvar(key, key_len, val, val_len);
}
/*
* Treating both as strings, lookup the key and compare the result with the
* expected value. Return true if they match.
*/
static int str_matches(const char *key, const char *expected_val)
{
const struct tuple *t = getvar(key, strlen(key));
uint8_t expected_len;
if (!expected_val && !t)
return 1;
if (expected_val && !t)
return 0;
if (!expected_val && t)
return 0;
expected_len = strlen(expected_val);
return !memcmp(tuple_val(t), expected_val, expected_len);
}
/****************************************************************************/
/* Tests */
static int check_init(void)
{
/* Valid entries */
const uint8_t good[] = { 0x01, 0x01, 0x00, 'A', 'a',
0x01, 0x01, 0x00, 'B', 'b',
0x00 };
/* Empty variables are 0x00, followed by all 0xff */
const uint8_t empty[] = { 0x00 };
/*
* This is parsed as though there's only one variable, but it's wrong
* because the rest of the storage isn't 0xff.
*/
const uint8_t bad_key[] = { 0x01, 0x01, 0x00, 'A', 'a',
0x00, 0x01, 0x00, 'B', 'b',
0x00 };
/* Zero-length variables are not allowed */
const uint8_t bad_val[] = { 0x01, 0x01, 0x00, 'A', 'a',
0x01, 0x00, 0x00, 'B', 'b',
0x00 };
/* The next constants use magic numbers based on on the region size */
BUILD_ASSERT(CONFIG_FLASH_NVMEM_VARS_USER_SIZE == 600);
/* This is one byte too large */
const uint8_t too_big[] = { [0] = 0xff, [1] = 0xff, /* 0 - 512 */
[513] = 0x01, [514] = 0x53, /* 513 - 599 */
[599] = 0x00 };
/* This should just barely fit */
const uint8_t just_right[] = { [0] = 0xff, [1] = 0xff, /* 0-512 */
[513] = 0x01, [514] = 0x52, /* 513-598 */
[599] = 0x00 };
/* No end marker */
const uint8_t not_right[] = { [0] = 0xff, [1] = 0xff, /* 0-512 */
[513] = 0x01, [514] = 0x52, /* 513-598 */
[599] = 0xff };
load_flash(good, sizeof(good));
TEST_ASSERT(initvars() == EC_SUCCESS);
TEST_ASSERT(verify_flash(good, sizeof(good)));
load_flash(empty, sizeof(empty));
TEST_ASSERT(initvars() == EC_SUCCESS);
TEST_ASSERT(verify_flash(empty, sizeof(empty)));
/* All 0xff quickly runs off the end of the storage */
erase_flash();
TEST_ASSERT(initvars() == EC_SUCCESS);
TEST_ASSERT(verify_flash(empty, sizeof(empty)));
load_flash(bad_key, sizeof(bad_key));
TEST_ASSERT(initvars() == EC_SUCCESS);
TEST_ASSERT(verify_flash(empty, sizeof(empty)));
load_flash(bad_val, sizeof(bad_val));
TEST_ASSERT(initvars() == EC_SUCCESS);
TEST_ASSERT(verify_flash(empty, sizeof(empty)));
load_flash(too_big, sizeof(too_big));
TEST_ASSERT(initvars() == EC_SUCCESS);
TEST_ASSERT(verify_flash(empty, sizeof(empty)));
load_flash(just_right, sizeof(just_right));
TEST_ASSERT(initvars() == EC_SUCCESS);
TEST_ASSERT(verify_flash(just_right, sizeof(just_right)));
load_flash(not_right, sizeof(not_right));
TEST_ASSERT(initvars() == EC_SUCCESS);
TEST_ASSERT(verify_flash(empty, sizeof(empty)));
return EC_SUCCESS;
}
static int simple_search(void)
{
const uint8_t preload[] = {
0x02, 0x02, 0x00, 'h', 'o', 'y', 'o',
0x02, 0x4, 0x00, 'y', 'o', 'h', 'o', 'y', 'o',
0x02, 0x06, 0x00, 'm', 'o', 'y', 'o', 'h', 'o', 'y', 'o',
0x00 };
load_flash(preload, sizeof(preload));
TEST_ASSERT(initvars() == EC_SUCCESS);
TEST_ASSERT(verify_flash(preload, sizeof(preload)));
TEST_ASSERT(str_matches("no", 0));
TEST_ASSERT(str_matches("ho", "yo"));
TEST_ASSERT(str_matches("yo", "hoyo"));
TEST_ASSERT(str_matches("mo", "yohoyo"));
return EC_SUCCESS;
}
static int simple_write(void)
{
const uint8_t after_one[] = {
0x02, 0x02, 0x00, 'h', 'o', 'y', 'o',
0x00 };
const uint8_t after_two[] = {
0x02, 0x02, 0x00, 'h', 'o', 'y', 'o',
0x02, 0x4, 0x00, 'y', 'o', 'h', 'o', 'y', 'o',
0x00 };
const uint8_t after_three[] = {
0x02, 0x02, 0x00, 'h', 'o', 'y', 'o',
0x02, 0x4, 0x00, 'y', 'o', 'h', 'o', 'y', 'o',
0x02, 0x06, 0x00, 'm', 'o', 'y', 'o', 'h', 'o', 'y', 'o',
0x00 };
erase_flash();
TEST_ASSERT(initvars() == EC_SUCCESS);
TEST_ASSERT(setvar("ho", 2, "yo", 2) == EC_SUCCESS);
TEST_ASSERT(writevars() == EC_SUCCESS);
TEST_ASSERT(verify_flash(after_one, sizeof(after_one)));
TEST_ASSERT(setvar("yo", 2, "hoyo", 4) == EC_SUCCESS);
TEST_ASSERT(writevars() == EC_SUCCESS);
TEST_ASSERT(verify_flash(after_two, sizeof(after_two)));
TEST_ASSERT(setvar("mo", 2, "yohoyo", 6) == EC_SUCCESS);
TEST_ASSERT(writevars() == EC_SUCCESS);
TEST_ASSERT(verify_flash(after_three, sizeof(after_three)));
return EC_SUCCESS;
}
static int simple_delete(void)
{
const char start_with[] = {
0x01, 0x05, 0x00, 'A', 'a', 'a', 'a', 'a', 'a',
0x02, 0x03, 0x00, 'B', 'B', 'b', 'b', 'b',
0x03, 0x06, 0x00, 'C', 'C', 'C', 'x', 'y', 'z', 'p', 'd', 'q',
0x01, 0x03, 0x00, 'M', 'm', '0', 'm',
0x04, 0x01, 0x00, 'N', 'N', 'N', 'N', 'n',
0x00 };
const char after_one[] = {
0x02, 0x03, 0x00, 'B', 'B', 'b', 'b', 'b',
0x03, 0x06, 0x00, 'C', 'C', 'C', 'x', 'y', 'z', 'p', 'd', 'q',
0x01, 0x03, 0x00, 'M', 'm', '0', 'm',
0x04, 0x01, 0x00, 'N', 'N', 'N', 'N', 'n',
0x00 };
const char after_two[] = {
0x02, 0x03, 0x00, 'B', 'B', 'b', 'b', 'b',
0x03, 0x06, 0x00, 'C', 'C', 'C', 'x', 'y', 'z', 'p', 'd', 'q',
0x01, 0x03, 0x00, 'M', 'm', '0', 'm',
0x00 };
const char after_three[] = {
0x02, 0x03, 0x00, 'B', 'B', 'b', 'b', 'b',
0x01, 0x03, 0x00, 'M', 'm', '0', 'm',
0x00 };
const char empty[] = { 0x00 };
erase_flash();
TEST_ASSERT(initvars() == EC_SUCCESS);
TEST_ASSERT(setvar("A", 1, "aaaaa", 5) == EC_SUCCESS);
TEST_ASSERT(setvar("BB", 2, "bbb", 3) == EC_SUCCESS);
TEST_ASSERT(setvar("CCC", 3, "xyzpdq", 6) == EC_SUCCESS);
TEST_ASSERT(setvar("M", 1, "m0m", 3) == EC_SUCCESS);
TEST_ASSERT(setvar("NNNN", 4, "n", 1) == EC_SUCCESS);
TEST_ASSERT(writevars() == EC_SUCCESS);
TEST_ASSERT(verify_flash(start_with, sizeof(start_with)));
/* Zap first variable by setting var_len to 0 */
TEST_ASSERT(setvar("A", 1, "yohoyo", 0) == EC_SUCCESS);
TEST_ASSERT(writevars() == EC_SUCCESS);
TEST_ASSERT(verify_flash(after_one, sizeof(after_one)));
/* Zap last variable by passing null pointer */
TEST_ASSERT(setvar("NNNN", 4, 0, 3) == EC_SUCCESS);
TEST_ASSERT(writevars() == EC_SUCCESS);
TEST_ASSERT(verify_flash(after_two, sizeof(after_two)));
/* Ensure that zapping nonexistant variable does nothing */
TEST_ASSERT(setvar("XXX", 3, 0, 0) == EC_SUCCESS);
TEST_ASSERT(writevars() == EC_SUCCESS);
TEST_ASSERT(verify_flash(after_two, sizeof(after_two)));
/* Zap variable in the middle */
TEST_ASSERT(setvar("CCC", 3, 0, 0) == EC_SUCCESS);
TEST_ASSERT(writevars() == EC_SUCCESS);
TEST_ASSERT(verify_flash(after_three, sizeof(after_three)));
/* Zap the rest */
TEST_ASSERT(setvar("BB", 2, 0, 0) == EC_SUCCESS);
TEST_ASSERT(setvar("M", 1, 0, 0) == EC_SUCCESS);
TEST_ASSERT(writevars() == EC_SUCCESS);
TEST_ASSERT(verify_flash(empty, sizeof(empty)));
/* Zapping a nonexistant variable still does nothing */
TEST_ASSERT(setvar("XXX", 3, 0, 0) == EC_SUCCESS);
TEST_ASSERT(writevars() == EC_SUCCESS);
TEST_ASSERT(verify_flash(empty, sizeof(empty)));
return EC_SUCCESS;
}
static int complex_write(void)
{
erase_flash();
TEST_ASSERT(initvars() == EC_SUCCESS);
/* Do a bunch of writes and erases */
str_setvar("ho", "aa");
str_setvar("zo", "nn");
str_setvar("yo", "CCCCCCCC");
str_setvar("zooo", "yyyyyyy");
str_setvar("yo", "AA");
str_setvar("ho", 0);
str_setvar("yi", "BBB");
str_setvar("yi", "AA");
str_setvar("hixx", 0);
str_setvar("yo", "BBB");
str_setvar("zo", "");
str_setvar("hi", "bbb");
str_setvar("ho", "cccccc");
str_setvar("yo", "");
str_setvar("zo", "ggggg");
/* What do we expect to find? */
TEST_ASSERT(str_matches("hi", "bbb"));
TEST_ASSERT(str_matches("hixx", 0));
TEST_ASSERT(str_matches("ho", "cccccc"));
TEST_ASSERT(str_matches("yi", "AA"));
TEST_ASSERT(str_matches("yo", 0));
TEST_ASSERT(str_matches("zo", "ggggg"));
TEST_ASSERT(str_matches("zooo", "yyyyyyy"));
return EC_SUCCESS;
}
static int weird_keys(void)
{
uint8_t keyA[255];
uint8_t keyB[255];
const char *valA = "this is A";
const char *valB = "THIS IS b";
int i;
const struct tuple *t;
erase_flash();
TEST_ASSERT(initvars() == EC_SUCCESS);
for (i = 0; i < 255; i++) {
keyA[i] = i;
keyB[i] = 255 - i;
}
TEST_ASSERT(setvar(keyA, sizeof(keyA),
valA, strlen(valA)) == EC_SUCCESS);
TEST_ASSERT(setvar(keyB, sizeof(keyB),
valB, strlen(valB)) == EC_SUCCESS);
TEST_ASSERT(writevars() == EC_SUCCESS);
t = getvar(keyA, sizeof(keyA));
TEST_ASSERT(t);
TEST_ASSERT(t->val_len == strlen(valA));
TEST_ASSERT(memcmp(tuple_val(t), valA, strlen(valA)) == 0);
t = getvar(keyB, sizeof(keyB));
TEST_ASSERT(t);
TEST_ASSERT(t->val_len == strlen(valB));
TEST_ASSERT(memcmp(tuple_val(t), valB, strlen(valB)) == 0);
return EC_SUCCESS;
}
static int weird_values(void)
{
const char *keyA = "this is A";
const char *keyB = "THIS IS b";
char valA[255];
char valB[255];
int i;
const struct tuple *t;
erase_flash();
TEST_ASSERT(initvars() == EC_SUCCESS);
for (i = 0; i < 255; i++) {
valA[i] = i;
valB[i] = 255 - i;
}
TEST_ASSERT(setvar(keyA, strlen(keyA),
valA, sizeof(valA)) == EC_SUCCESS);
TEST_ASSERT(str_setvar("c", "CcC") == EC_SUCCESS);
TEST_ASSERT(setvar(keyB, strlen(keyB),
valB, sizeof(valB)) == EC_SUCCESS);
TEST_ASSERT(str_setvar("d", "dDd") == EC_SUCCESS);
TEST_ASSERT(writevars() == EC_SUCCESS);
t = getvar(keyA, strlen(keyA));
TEST_ASSERT(t);
TEST_ASSERT(memcmp(tuple_val(t), valA, sizeof(valA)) == 0);
t = getvar(keyB, strlen(keyB));
TEST_ASSERT(t);
TEST_ASSERT(memcmp(tuple_val(t), valB, sizeof(valB)) == 0);
TEST_ASSERT(str_matches("c", "CcC"));
TEST_ASSERT(str_matches("d", "dDd"));
return EC_SUCCESS;
}
static int fill_it_up(void)
{
int i, n;
char key[20];
erase_flash();
TEST_ASSERT(initvars() == EC_SUCCESS);
/*
* Some magic numbers here, because we want to use up 10 bytes at a
* time and end up with exactly 9 free bytes left.
*/
TEST_ASSERT(CONFIG_FLASH_NVMEM_VARS_USER_SIZE % 10 == 0);
n = CONFIG_FLASH_NVMEM_VARS_USER_SIZE / 10;
TEST_ASSERT(n < 1000);
/* Fill up the storage */
for (i = 0; i < n - 1; i++) {
/* 3-byte header, 5-char key, 2-char val, == 10 chars */
snprintf(key, sizeof(key), "kk%03d", i);
TEST_ASSERT(setvar(key, 5, "aa", 2) == EC_SUCCESS);
}
/*
* Should be nine bytes left in rbuf (because we need one more '\0' at
* the end). This won't fit.
*/
TEST_ASSERT(setvar("kk999", 5, "aa", 2) == EC_ERROR_OVERFLOW);
/* But this will. */
TEST_ASSERT(setvar("kk999", 5, "a", 1) == EC_SUCCESS);
/* And this, because it replaces a previous entry */
TEST_ASSERT(setvar("kk000", 5, "bc", 2) == EC_SUCCESS);
/* But this still won't fit */
TEST_ASSERT(setvar("kk999", 5, "de", 2) == EC_ERROR_OVERFLOW);
return EC_SUCCESS;
}
void run_test(void)
{
test_reset();
RUN_TEST(check_init);
RUN_TEST(simple_write);
RUN_TEST(simple_search);
RUN_TEST(simple_delete);
RUN_TEST(complex_write);
RUN_TEST(weird_keys);
RUN_TEST(weird_values);
RUN_TEST(fill_it_up);
test_print_result();
}

View File

@ -1,17 +0,0 @@
/* Copyright 2016 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/**
* List of enabled tasks in the priority order
*
* The first one has the lowest priority.
*
* For each task, use the macro TASK_TEST(n, r, d, s) where :
* 'n' in the name of the task
* 'r' in the main routine of the task
* 'd' in an opaque parameter passed to the routine at startup
* 's' is the stack size in bytes; must be a multiple of 8
*/
#define CONFIG_TEST_TASK_LIST /* No test task */

View File

@ -16,6 +16,8 @@
#include "test_util.h"
#include <stdlib.h>
struct pw_test_data_t {
union {
struct pw_request_t request;
@ -152,13 +154,10 @@ const uint8_t DEFAULT_PCR_DIGEST[] = {
/* Config Variables and defines for Mocks.
*/
struct tuple MOCK_pw_tuple;
struct pw_long_term_storage_t MOCK_pw_long_term_storage;
struct pw_log_storage_t MOCK_pw_log_storage;
int MOCK_getvar_ret = EC_SUCCESS;
int MOCK_setvar_ret = EC_SUCCESS;
int MOCK_writevars_ret = EC_SUCCESS;
void *MOCK_tuple_val_ret;
const uint8_t *MOCK_rand_bytes_src;
size_t MOCK_rand_bytes_offset;
@ -342,7 +341,6 @@ static void setup_storage(int num_operations)
{
MOCK_getvar_ret = EC_SUCCESS;
MOCK_setvar_ret = EC_SUCCESS;
MOCK_writevars_ret = EC_SUCCESS;
memset(&MOCK_pw_long_term_storage, 0,
sizeof(MOCK_pw_long_term_storage));
@ -470,7 +468,6 @@ static void setup_reset_tree_defaults(struct merkle_tree_t *merkle_tree,
MOCK_rand_bytes_len = sizeof(EMPTY_TREE.key_derivation_nonce);
MOCK_appkey_derive_fail = EC_SUCCESS;
MOCK_setvar_ret = EC_SUCCESS;
MOCK_writevars_ret = EC_SUCCESS;
}
static void setup_insert_leaf_defaults(struct merkle_tree_t *merkle_tree,
@ -513,7 +510,6 @@ static void setup_insert_leaf_defaults(struct merkle_tree_t *merkle_tree,
MOCK_hmac = DEFAULT_HMAC;
MOCK_aes_fail = 0;
MOCK_setvar_ret = EC_SUCCESS;
MOCK_writevars_ret = EC_SUCCESS;
}
static void setup_remove_leaf_defaults(struct merkle_tree_t *merkle_tree,
@ -540,7 +536,6 @@ static void setup_remove_leaf_defaults(struct merkle_tree_t *merkle_tree,
setup_default_empty_path(request->data.remove_leaf.path_hashes);
MOCK_setvar_ret = EC_SUCCESS;
MOCK_writevars_ret = EC_SUCCESS;
}
static void setup_try_auth_defaults_with_leaf(
@ -598,7 +593,6 @@ static void setup_try_auth_defaults_with_leaf(
MOCK_hash_update_cb = auth_hash_update_cb;
MOCK_aes_fail = 0;
MOCK_setvar_ret = EC_SUCCESS;
MOCK_writevars_ret = EC_SUCCESS;
}
static void setup_try_auth_defaults(struct merkle_tree_t *merkle_tree,
@ -645,7 +639,6 @@ static void setup_reset_auth_defaults(struct merkle_tree_t *merkle_tree,
MOCK_hmac = EMPTY_HMAC; /* Gets overwritten by auth_hash_update_cb. */
MOCK_aes_fail = 0;
MOCK_setvar_ret = EC_SUCCESS;
MOCK_writevars_ret = EC_SUCCESS;
}
static void setup_get_log_defaults(struct merkle_tree_t *merkle_tree,
@ -800,35 +793,57 @@ uint8_t get_current_pcr_digest(const uint8_t bitmask[2],
/******************************************************************************/
/* Mock implementations of nvmem_vars functionality.
*/
const struct tuple *getvar(const uint8_t *key, uint8_t key_len)
struct tuple *getvar(const uint8_t *key, uint8_t key_len)
{
struct tuple *var = NULL;
size_t i;
const struct {
size_t key_len;
const void *key;
size_t val_size;
const void *val;
} vars[] = {
{sizeof(PW_TREE_VAR) - 1, PW_TREE_VAR,
sizeof(MOCK_pw_long_term_storage), &MOCK_pw_long_term_storage},
{sizeof(PW_LOG_VAR0) - 1, PW_LOG_VAR0,
sizeof(MOCK_pw_log_storage), &MOCK_pw_log_storage},
};
if (!key || !key_len)
return NULL;
if (MOCK_getvar_ret != EC_SUCCESS)
return NULL;
MOCK_pw_tuple.flags = 0;
MOCK_pw_tuple.key_len = key_len;
for (i = 0; i < ARRAY_SIZE(vars); i++) {
if ((key_len != vars[i].key_len) ||
memcmp(key, vars[i].key, key_len)) {
continue;
}
var = malloc(sizeof(struct tuple) + key_len + vars[i].val_size);
var->flags = 0;
var->val_len = vars[i].val_size;
memcpy(var->data_ + var->key_len, vars[i].val, var->val_len);
break;
}
if (key_len == (sizeof(PW_TREE_VAR) - 1) &&
memcmp(key, PW_TREE_VAR, (sizeof(PW_TREE_VAR) - 1)) == 0) {
MOCK_pw_tuple.val_len = sizeof(MOCK_pw_long_term_storage);
MOCK_tuple_val_ret = &MOCK_pw_long_term_storage;
return &MOCK_pw_tuple;
} else if (key_len == (sizeof(PW_LOG_VAR0) - 1) &&
memcmp(key, PW_LOG_VAR0, (sizeof(PW_LOG_VAR0) - 1)) == 0) {
MOCK_pw_tuple.val_len = sizeof(struct pw_log_storage_t);
MOCK_tuple_val_ret = &MOCK_pw_log_storage;
return &MOCK_pw_tuple;
} else
return NULL;
return var;
}
int freevar(struct tuple *var)
{
free(var);
return EC_SUCCESS;
}
const uint8_t *tuple_val(const struct tuple *tpl)
{
return MOCK_tuple_val_ret;
return tpl->data_ + tpl->key_len;
}
int setvar(const uint8_t *key, uint8_t key_len,
const uint8_t *val, uint8_t val_len)
int setvar(const uint8_t *key, uint8_t key_len, const uint8_t *val,
uint8_t val_len)
{
if (MOCK_setvar_ret != EC_SUCCESS)
return MOCK_setvar_ret;
@ -847,11 +862,6 @@ int setvar(const uint8_t *key, uint8_t key_len,
return EC_ERROR_UNKNOWN;
}
int writevars(void)
{
return MOCK_writevars_ret;
}
/******************************************************************************/
/* Mock implementations of TRNG functionality.
*/
@ -1214,7 +1224,7 @@ static int handle_reset_tree_nv_fail(void)
setup_reset_tree_defaults(&merkle_tree, &buf.request);
MOCK_writevars_ret = PW_ERR_NV_LENGTH_MISMATCH;
MOCK_setvar_ret = PW_ERR_NV_LENGTH_MISMATCH;
TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
PW_ERR_NV_LENGTH_MISMATCH);
@ -1364,7 +1374,7 @@ static int handle_insert_leaf_nv_fail(void)
setup_insert_leaf_defaults(&merkle_tree, &buf.request);
MOCK_writevars_ret = PW_ERR_NV_LENGTH_MISMATCH;
MOCK_setvar_ret = PW_ERR_NV_LENGTH_MISMATCH;
TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
PW_ERR_NV_LENGTH_MISMATCH);
@ -1535,7 +1545,7 @@ static int handle_remove_leaf_nv_fail(void)
setup_remove_leaf_defaults(&merkle_tree, &buf.request);
MOCK_writevars_ret = PW_ERR_NV_LENGTH_MISMATCH;
MOCK_setvar_ret = PW_ERR_NV_LENGTH_MISMATCH;
TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
PW_ERR_NV_LENGTH_MISMATCH);
@ -1789,7 +1799,7 @@ static int handle_try_auth_nv_fail(void)
force_restart_count(0);
force_time((timestamp_t){.val = 65 * SECOND});
MOCK_writevars_ret = PW_ERR_NV_LENGTH_MISMATCH;
MOCK_setvar_ret = PW_ERR_NV_LENGTH_MISMATCH;
TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
PW_ERR_NV_LENGTH_MISMATCH);
@ -2136,7 +2146,7 @@ static int handle_reset_auth_nv_fail(void)
setup_reset_auth_defaults(&merkle_tree, &buf.request);
MOCK_writevars_ret = PW_ERR_NV_LENGTH_MISMATCH;
MOCK_setvar_ret = PW_ERR_NV_LENGTH_MISMATCH;
TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
PW_ERR_NV_LENGTH_MISMATCH);

View File

@ -257,52 +257,36 @@ int ncp15wb_calculate_temp(uint16_t adc);
#define CONFIG_USB_PD_PORT_COUNT 2
#endif
#ifdef TEST_NVMEM
#if defined(TEST_NVMEM) || defined(TEST_NVMEM_VARS)
#define CONFIG_CRC8
#define CONFIG_FLASH_ERASED_VALUE32 (-1U)
#define CONFIG_FLASH_LOG
#define CONFIG_FLASH_LOG_BASE CONFIG_PROGRAM_MEMORY_BASE
#define CONFIG_FLASH_LOG_SPACE 0x800
#define CONFIG_FLASH_NVMEM
#define CONFIG_FLASH_NVMEM_OFFSET_A 0x1000
#define CONFIG_FLASH_NVMEM_OFFSET_B 0x4000
#define CONFIG_FLASH_NVMEM_BASE_A (CONFIG_PROGRAM_MEMORY_BASE + \
CONFIG_FLASH_NVMEM_OFFSET_A)
#define CONFIG_FLASH_NVMEM_BASE_B (CONFIG_PROGRAM_MEMORY_BASE + \
CONFIG_FLASH_NVMEM_OFFSET_B)
#define CONFIG_FLASH_NVMEM_SIZE 0x4000
#define CONFIG_SW_CRC
#define NVMEM_PARTITION_SIZE \
(CONFIG_FLASH_NVMEM_SIZE / NVMEM_NUM_PARTITIONS)
/* User buffer definitions for test purposes */
#define NVMEM_USER_2_SIZE 0x201
#define NVMEM_USER_1_SIZE 0x402
#define NVMEM_USER_0_SIZE (NVMEM_PARTITION_SIZE - \
NVMEM_USER_2_SIZE - NVMEM_USER_1_SIZE - \
sizeof(struct nvmem_tag))
#ifndef __ASSEMBLER__
enum nvmem_users {
NVMEM_USER_0,
NVMEM_USER_1,
NVMEM_USER_2,
NVMEM_NUM_USERS
};
#endif
#endif
#ifdef TEST_NVMEM_VARS
#define CONFIG_FLASH_NVMEM_OFFSET_A 0x3d000
#define CONFIG_FLASH_NVMEM_OFFSET_B 0x7d000
#define CONFIG_FLASH_NVMEM_BASE_A \
(CONFIG_PROGRAM_MEMORY_BASE + CONFIG_FLASH_NVMEM_OFFSET_A)
#define CONFIG_FLASH_NVMEM_BASE_B \
(CONFIG_PROGRAM_MEMORY_BASE + CONFIG_FLASH_NVMEM_OFFSET_B)
#define CONFIG_FLASH_NEW_NVMEM_BASE_A (CONFIG_FLASH_NVMEM_BASE_A + 0x800)
#define CONFIG_FLASH_NEW_NVMEM_BASE_B (CONFIG_FLASH_NVMEM_BASE_B + 0x800)
#define CONFIG_MALLOC
/* This is legacy NVMEM partition size. */
#define NVMEM_PARTITION_SIZE 0x3000
#define NEW_FLASH_HALF_NVMEM_SIZE \
(NVMEM_PARTITION_SIZE - CONFIG_FLASH_BANK_SIZE)
#define NEW_NVMEM_PARTITION_SIZE (NVMEM_PARTITION_SIZE - CONFIG_FLASH_BANK_SIZE)
#define NEW_NVMEM_TOTAL_PAGES \
(2 * NEW_NVMEM_PARTITION_SIZE / CONFIG_FLASH_BANK_SIZE)
#define CONFIG_SW_CRC
#define CONFIG_FLASH_NVMEM_VARS
#ifndef __ASSEMBLER__
/* Define the user region numbers */
enum nvmem_users {
CONFIG_FLASH_NVMEM_VARS_USER_NUM,
NVMEM_NUM_USERS
};
/* Define a test var. */
enum nvmem_vars {
NVMEM_VAR_TEST_VAR,
};
enum nvmem_users { NVMEM_TPM = 0, NVMEM_CR50, NVMEM_NUM_USERS };
#endif
#endif
#define CONFIG_FLASH_NVMEM_VARS_USER_SIZE 600
#endif /* TEST_NVMEM_VARS */
#ifdef TEST_PINWEAVER
#define CONFIG_DCRYPTO_MOCK