vboot2: Add host library functions to read/write files and objects

And unit tests for them.

Move roundup32() into hostlib.

Fix WriteFile() returning success even if it failed to write to the file.

BUG=chromium:423882
BRANCH=none
TEST=VBOOT2=1 make runtests

Change-Id: I8a115335c088dc5c66c88423d1ccbda7eaca1996
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/230844
This commit is contained in:
Randall Spangler
2014-11-19 12:48:36 -08:00
committed by chrome-internal-fetch
parent 8577b5360c
commit 02e11b323b
8 changed files with 238 additions and 10 deletions

View File

@@ -374,6 +374,12 @@ UTILLIB_SRCS = \
host/lib/host_signature.c \
host/lib/signature_digest.c
ifneq (${VBOOT2},)
UTILLIB_SRCS += \
host/lib/host_misc2.c \
endif
UTILLIB_OBJS = ${UTILLIB_SRCS:%.c=${BUILD}/%.o}
ALL_OBJS += ${UTILLIB_OBJS}
@@ -626,6 +632,7 @@ TEST_NAMES += \
tests/vb2_common_tests \
tests/vb2_common2_tests \
tests/vb2_common3_tests \
tests/vb2_host_misc_tests \
tests/vb2_misc_tests \
tests/vb2_misc2_tests \
tests/vb2_misc3_tests \
@@ -1160,6 +1167,7 @@ run2tests: test_setup
${RUNTEST} ${BUILD_RUN}/tests/vb2_common_tests
${RUNTEST} ${BUILD_RUN}/tests/vb2_common2_tests ${TEST_KEYS}
${RUNTEST} ${BUILD_RUN}/tests/vb2_common3_tests ${TEST_KEYS}
${RUNTEST} ${BUILD_RUN}/tests/vb2_host_misc_tests
${RUNTEST} ${BUILD_RUN}/tests/vb2_misc_tests
${RUNTEST} ${BUILD_RUN}/tests/vb2_misc2_tests
${RUNTEST} ${BUILD_RUN}/tests/vb2_misc3_tests

View File

@@ -20,7 +20,7 @@ enum vb2_return_code {
* All vboot2 error codes start at a large offset from zero, to reduce
* the risk of overlap with other error codes (TPM, etc.).
*/
VB2_ERROR_BASE = 0x0100000,
VB2_ERROR_BASE = 0x10000000,
/* Unknown / unspecified error */
VB2_ERROR_UNKNOWN = VB2_ERROR_BASE + 1,
@@ -443,12 +443,41 @@ enum vb2_return_code {
/* TPM clear owner not implemented */
VB2_ERROR_EX_TPM_CLEAR_OWNER_UNIMPLEMENTED,
/**********************************************************************
* Errors generated by host library (non-firmware) start here.
*/
VB2_ERROR_HOST_BASE = 0x20000000,
/**********************************************************************
* Errors generated by host library misc functions
*/
VB2_ERROR_HOST_MISC = VB2_ERROR_HOST_BASE + 0x010000,
/* Unable to open file in read_file() */
VB2_ERROR_READ_FILE_OPEN,
/* Bad size in read_file() */
VB2_ERROR_READ_FILE_SIZE,
/* Unable to allocate buffer in read_file() */
VB2_ERROR_READ_FILE_ALLOC,
/* Unable to read data in read_file() */
VB2_ERROR_READ_FILE_DATA,
/* Unable to open file in write_file() */
VB2_ERROR_WRITE_FILE_OPEN,
/* Unable to write data in write_file() */
VB2_ERROR_WRITE_FILE_DATA,
/**********************************************************************
* Highest non-zero error generated inside vboot library. Note that
* error codes passed through vboot when it calls external APIs may
* still be outside this range.
*/
VB2_ERROR_MAX = VB2_ERROR_BASE + 0xffffff,
VB2_ERROR_MAX = VB2_ERROR_BASE + 0x1fffffff,
};
#endif /* VBOOT_2_RETURN_CODES_H_ */

View File

@@ -108,6 +108,7 @@ int WriteFile(const char* filename, const void *data, uint64_t size) {
VBDEBUG(("Unable to write to file %s\n", filename));
fclose(f);
unlink(filename); /* Delete any partial file */
return 1;
}
fclose(f);

84
host/lib/host_misc2.c Normal file
View File

@@ -0,0 +1,84 @@
/* Copyright (c) 2014 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.
*
* Host functions for verified boot.
*/
#include <stdio.h>
#include <unistd.h>
#include "2sysincludes.h"
#include "2common.h"
#include "host_common.h"
int vb2_read_file(const char *filename, uint8_t **data_ptr, uint32_t *size_ptr)
{
FILE *f;
uint8_t *buf;
long size;
*data_ptr = NULL;
*size_ptr = 0;
f = fopen(filename, "rb");
if (!f) {
VB2_DEBUG("Unable to open file %s\n", filename);
return VB2_ERROR_READ_FILE_OPEN;
}
fseek(f, 0, SEEK_END);
size = ftell(f);
rewind(f);
if (size < 0 || size > UINT32_MAX) {
fclose(f);
return VB2_ERROR_READ_FILE_SIZE;
}
buf = malloc(size);
if (!buf) {
fclose(f);
return VB2_ERROR_READ_FILE_ALLOC;
}
if(1 != fread(buf, size, 1, f)) {
VB2_DEBUG("Unable to read file %s\n", filename);
fclose(f);
free(buf);
return VB2_ERROR_READ_FILE_DATA;
}
fclose(f);
*data_ptr = buf;
*size_ptr = size;
return VB2_SUCCESS;
}
int vb2_write_file(const char *filename, const void *buf, uint32_t size)
{
FILE *f = fopen(filename, "wb");
if (!f) {
VB2_DEBUG("Unable to open file %s\n", filename);
return VB2_ERROR_WRITE_FILE_OPEN;
}
if (1 != fwrite(buf, size, 1, f)) {
VB2_DEBUG("Unable to write to file %s\n", filename);
fclose(f);
unlink(filename); /* Delete any partial file */
return VB2_ERROR_WRITE_FILE_DATA;
}
fclose(f);
return VB2_SUCCESS;
}
int vb2_write_object(const char *filename, const void *buf)
{
const struct vb2_struct_common *cptr = buf;
return vb2_write_file(filename, buf, cptr->total_size);
}

View File

@@ -43,4 +43,45 @@ int ReadFileBit(const char* filename, int bitmask);
* Returns 0 if success, 1 if error. */
int WriteFile(const char* filename, const void *data, uint64_t size);
/**
* Read data from a file into a newly allocated buffer.
*
* @param filename Name of file to read from
* @param data_ptr On exit, pointer to newly allocated buffer with data
* will be stored here. Caller must free() the buffer
* when done with it.
* @param size_ptr On exit, size of data will be stored here.
* @return VB2_SUCCESS, or non-zero if error.
*/
int vb2_read_file(const char *filename, uint8_t **data_ptr, uint32_t *size_ptr);
/**
* Write data to a file from a buffer.
*
* @param filename Name of file to write to
* @param buf Buffer to write
* @param size Number of bytes of data to write
* @return VB2_SUCCESS, or non-zero if error.
*/
int vb2_write_file(const char *filename, const void *buf, uint32_t size);
/**
* Write a buffer which starts with a standard vb2_struct_common header.
*
* Determines the buffer size from the common header total size field.
*
* @param filename Name of file to write to
* @param buf Buffer to write
* @return VB2_SUCCESS, or non-zero if error.
*/
int vb2_write_object(const char *filename, const void *buf);
/**
* Round up a size to a multiple of 32 bits (4 bytes).
*/
static __inline const uint32_t roundup32(uint32_t v)
{
return (v + 3) & ~3;
}
#endif /* VBOOT_REFERENCE_HOST_MISC_H_ */

View File

@@ -8,6 +8,8 @@
#include "2sysincludes.h"
#include "2common.h"
#include "2rsa.h"
#include "host_common.h"
#include "host_misc.h"
#include "vb2_convert_structs.h"
#include "vboot_struct.h" /* For old struct sizes */

View File

@@ -9,14 +9,6 @@
#include "2struct.h"
/**
* Round up a size to a multiple of 32 bits (4 bytes).
*/
static __inline const uint32_t roundup32(uint32_t v)
{
return (v + 3) & ~3;
}
/**
* Convert a packed key from vboot data format to vboot2 data format.
*

View File

@@ -0,0 +1,71 @@
/* Copyright (c) 2014 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.
*
* Tests for host misc library vboot2 functions
*/
#include <unistd.h>
#include "2sysincludes.h"
#include "2common.h"
#include "host_common.h"
#include "host_misc.h"
#include "test_common.h"
static void misc_tests(void)
{
TEST_EQ(roundup32(0), 0, "roundup32(0)");
TEST_EQ(roundup32(15), 16, "roundup32(15)");
TEST_EQ(roundup32(16), 16, "roundup32(16)");
}
static void file_tests(void)
{
const char *testfile = "file_tests.dat";
const uint8_t test_data[] = "Some test data";
uint8_t *read_data;
uint32_t read_size;
uint8_t cbuf[sizeof(struct vb2_struct_common) + 12];
struct vb2_struct_common *c = (struct vb2_struct_common *)cbuf;
unlink(testfile);
TEST_EQ(vb2_read_file(testfile, &read_data, &read_size),
VB2_ERROR_READ_FILE_OPEN, "vb2_read_file() missing");
TEST_EQ(vb2_write_file("no/such/dir", test_data, sizeof(test_data)),
VB2_ERROR_WRITE_FILE_OPEN, "vb2_write_file() open");
TEST_SUCC(vb2_write_file(testfile, test_data, sizeof(test_data)),
"vb2_write_file() good");
TEST_SUCC(vb2_read_file(testfile, &read_data, &read_size),
"vb2_read_file() good");
TEST_EQ(read_size, sizeof(test_data), " data size");
TEST_EQ(memcmp(read_data, test_data, read_size), 0, " data");
free(read_data);
unlink(testfile);
memset(cbuf, 0, sizeof(cbuf));
c->fixed_size = sizeof(*c);
c->total_size = sizeof(cbuf);
c->magic = 0x1234;
cbuf[sizeof(cbuf) - 1] = 0xed; /* Some non-zero data at the end */
TEST_SUCC(vb2_write_object(testfile, c), "vb2_write_object() good");
TEST_SUCC(vb2_read_file(testfile, &read_data, &read_size),
"vb2_read_file() object");
TEST_EQ(read_size, c->total_size, " data size");
/* Compare the entire buffer, including the non-zero data at the end */
TEST_EQ(memcmp(read_data, c, read_size), 0, " data");
free(read_data);
unlink(testfile);
}
int main(int argc, char* argv[])
{
misc_tests();
file_tests();
return gTestSuccess ? 0 : 255;
}