mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-27 11:44:02 +00:00
vboot2: Add support for kernel version secure data space
Holds kernel rollback information. Will be used by vboot 2.0 kernel verification. BUG=chromium:487699 BRANCH=none TEST=make -j runtests Change-Id: Ib4a70e943ebd79aac06404df09cf4ce62d719201 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/270626 Reviewed-by: Bill Richardson <wfrichar@chromium.org>
This commit is contained in:
committed by
ChromeOS Commit Bot
parent
0140cd2906
commit
bf9c2760d2
3
Makefile
3
Makefile
@@ -330,6 +330,7 @@ FWLIB2X_SRCS = \
|
|||||||
firmware/2lib/2nvstorage.c \
|
firmware/2lib/2nvstorage.c \
|
||||||
firmware/2lib/2rsa.c \
|
firmware/2lib/2rsa.c \
|
||||||
firmware/2lib/2secdata.c \
|
firmware/2lib/2secdata.c \
|
||||||
|
firmware/2lib/2secdatak.c \
|
||||||
firmware/2lib/2sha1.c \
|
firmware/2lib/2sha1.c \
|
||||||
firmware/2lib/2sha256.c \
|
firmware/2lib/2sha256.c \
|
||||||
firmware/2lib/2sha512.c \
|
firmware/2lib/2sha512.c \
|
||||||
@@ -711,6 +712,7 @@ TEST2X_NAMES = \
|
|||||||
tests/vb2_nvstorage_tests \
|
tests/vb2_nvstorage_tests \
|
||||||
tests/vb2_rsa_utility_tests \
|
tests/vb2_rsa_utility_tests \
|
||||||
tests/vb2_secdata_tests \
|
tests/vb2_secdata_tests \
|
||||||
|
tests/vb2_secdatak_tests \
|
||||||
tests/vb2_sha_tests
|
tests/vb2_sha_tests
|
||||||
|
|
||||||
TEST20_NAMES = \
|
TEST20_NAMES = \
|
||||||
@@ -1376,6 +1378,7 @@ run2tests: test_setup
|
|||||||
${RUNTEST} ${BUILD_RUN}/tests/vb2_nvstorage_tests
|
${RUNTEST} ${BUILD_RUN}/tests/vb2_nvstorage_tests
|
||||||
${RUNTEST} ${BUILD_RUN}/tests/vb2_rsa_utility_tests
|
${RUNTEST} ${BUILD_RUN}/tests/vb2_rsa_utility_tests
|
||||||
${RUNTEST} ${BUILD_RUN}/tests/vb2_secdata_tests
|
${RUNTEST} ${BUILD_RUN}/tests/vb2_secdata_tests
|
||||||
|
${RUNTEST} ${BUILD_RUN}/tests/vb2_secdatak_tests
|
||||||
${RUNTEST} ${BUILD_RUN}/tests/vb2_sha_tests
|
${RUNTEST} ${BUILD_RUN}/tests/vb2_sha_tests
|
||||||
${RUNTEST} ${BUILD_RUN}/tests/vb20_api_tests
|
${RUNTEST} ${BUILD_RUN}/tests/vb20_api_tests
|
||||||
${RUNTEST} ${BUILD_RUN}/tests/vb20_common_tests
|
${RUNTEST} ${BUILD_RUN}/tests/vb20_common_tests
|
||||||
|
|||||||
112
firmware/2lib/2secdatak.c
Normal file
112
firmware/2lib/2secdatak.c
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/* Copyright 2015 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.
|
||||||
|
*
|
||||||
|
* Secure storage APIs - kernel version space
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
#include "2common.h"
|
||||||
|
#include "2crc8.h"
|
||||||
|
#include "2misc.h"
|
||||||
|
#include "2secdata.h"
|
||||||
|
|
||||||
|
int vb2_secdatak_check_crc(const struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
const struct vb2_secdatak *sec =
|
||||||
|
(const struct vb2_secdatak *)ctx->secdatak;
|
||||||
|
|
||||||
|
/* Verify CRC */
|
||||||
|
if (sec->crc8 != vb2_crc8(sec, offsetof(struct vb2_secdatak, crc8)))
|
||||||
|
return VB2_ERROR_SECDATAK_CRC;
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_secdatak_create(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
struct vb2_secdatak *sec = (struct vb2_secdatak *)ctx->secdatak;
|
||||||
|
|
||||||
|
/* Clear the entire struct */
|
||||||
|
memset(sec, 0, sizeof(*sec));
|
||||||
|
|
||||||
|
/* Set to current version */
|
||||||
|
sec->struct_version = VB2_SECDATAK_VERSION;
|
||||||
|
|
||||||
|
/* Set UID */
|
||||||
|
sec->uid = VB2_SECDATAK_UID;
|
||||||
|
|
||||||
|
/* Calculate initial CRC */
|
||||||
|
sec->crc8 = vb2_crc8(sec, offsetof(struct vb2_secdatak, crc8));
|
||||||
|
ctx->flags |= VB2_CONTEXT_SECDATAK_CHANGED;
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_secdatak_init(struct vb2_context *ctx)
|
||||||
|
{
|
||||||
|
struct vb2_secdatak *sec = (struct vb2_secdatak *)ctx->secdatak;
|
||||||
|
struct vb2_shared_data *sd = vb2_get_sd(ctx);
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv = vb2_secdatak_check_crc(ctx);
|
||||||
|
if (rv)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
/* Make sure the UID is correct */
|
||||||
|
if (sec->uid != VB2_SECDATAK_UID)
|
||||||
|
return VB2_ERROR_SECDATAK_UID;
|
||||||
|
|
||||||
|
/* Set status flag */
|
||||||
|
sd->status |= VB2_SD_STATUS_SECDATAK_INIT;
|
||||||
|
/* TODO: unit test for that */
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_secdatak_get(struct vb2_context *ctx,
|
||||||
|
enum vb2_secdatak_param param,
|
||||||
|
uint32_t *dest)
|
||||||
|
{
|
||||||
|
struct vb2_secdatak *sec = (struct vb2_secdatak *)ctx->secdatak;
|
||||||
|
|
||||||
|
if (!(vb2_get_sd(ctx)->status & VB2_SD_STATUS_SECDATAK_INIT))
|
||||||
|
return VB2_ERROR_SECDATAK_GET_UNINITIALIZED;
|
||||||
|
|
||||||
|
switch(param) {
|
||||||
|
case VB2_SECDATAK_VERSIONS:
|
||||||
|
*dest = sec->kernel_versions;
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return VB2_ERROR_SECDATAK_GET_PARAM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_secdatak_set(struct vb2_context *ctx,
|
||||||
|
enum vb2_secdatak_param param,
|
||||||
|
uint32_t value)
|
||||||
|
{
|
||||||
|
struct vb2_secdatak *sec = (struct vb2_secdatak *)ctx->secdatak;
|
||||||
|
uint32_t now;
|
||||||
|
|
||||||
|
if (!(vb2_get_sd(ctx)->status & VB2_SD_STATUS_SECDATAK_INIT))
|
||||||
|
return VB2_ERROR_SECDATAK_SET_UNINITIALIZED;
|
||||||
|
|
||||||
|
/* If not changing the value, don't regenerate the CRC. */
|
||||||
|
if (vb2_secdatak_get(ctx, param, &now) == VB2_SUCCESS && now == value)
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
|
||||||
|
switch(param) {
|
||||||
|
case VB2_SECDATAK_VERSIONS:
|
||||||
|
sec->kernel_versions = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return VB2_ERROR_SECDATAK_SET_PARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Regenerate CRC */
|
||||||
|
sec->crc8 = vb2_crc8(sec, offsetof(struct vb2_secdatak, crc8));
|
||||||
|
ctx->flags |= VB2_CONTEXT_SECDATAK_CHANGED;
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
@@ -31,8 +31,9 @@
|
|||||||
/* Size of non-volatile data used by vboot */
|
/* Size of non-volatile data used by vboot */
|
||||||
#define VB2_NVDATA_SIZE 16
|
#define VB2_NVDATA_SIZE 16
|
||||||
|
|
||||||
/* Size of secure data used by vboot */
|
/* Size of secure data spaces used by vboot */
|
||||||
#define VB2_SECDATA_SIZE 10
|
#define VB2_SECDATA_SIZE 10
|
||||||
|
#define VB2_SECDATAK_SIZE 14
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Recommended size of work buffer.
|
* Recommended size of work buffer.
|
||||||
@@ -93,6 +94,12 @@ enum vb2_context_flags {
|
|||||||
|
|
||||||
/* Erase TPM developer mode state if it is enabled. */
|
/* Erase TPM developer mode state if it is enabled. */
|
||||||
VB2_DISABLE_DEVELOPER_MODE = (1 << 9),
|
VB2_DISABLE_DEVELOPER_MODE = (1 << 9),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verified boot has changed secdatak[]. Caller must save secdatak[]
|
||||||
|
* back to its underlying storage, then may clear this flag.
|
||||||
|
*/
|
||||||
|
VB2_CONTEXT_SECDATAK_CHANGED = (1 << 11),
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -128,10 +135,11 @@ struct vb2_context {
|
|||||||
uint8_t nvdata[VB2_NVDATA_SIZE];
|
uint8_t nvdata[VB2_NVDATA_SIZE];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Secure data. Caller must fill this from some secure non-volatile
|
* Secure data for firmware verification stage. Caller must fill this
|
||||||
* location. If the VB2_CONTEXT_SECDATA_CHANGED flag is set when a
|
* from some secure non-volatile location. If the
|
||||||
* function returns, caller must save the data back to the secure
|
* VB2_CONTEXT_SECDATA_CHANGED flag is set when a function returns,
|
||||||
* non-volatile location and then clear the flag.
|
* caller must save the data back to the secure non-volatile location
|
||||||
|
* and then clear the flag.
|
||||||
*/
|
*/
|
||||||
uint8_t secdata[VB2_SECDATA_SIZE];
|
uint8_t secdata[VB2_SECDATA_SIZE];
|
||||||
|
|
||||||
@@ -154,6 +162,19 @@ struct vb2_context {
|
|||||||
* copied when relocating the work buffer.
|
* copied when relocating the work buffer.
|
||||||
*/
|
*/
|
||||||
uint32_t workbuf_used;
|
uint32_t workbuf_used;
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Fields caller must initialize before calling vb2api_kernel_phase1().
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Secure data for kernel verification stage. Caller must fill this
|
||||||
|
* from some secure non-volatile location. If the
|
||||||
|
* VB2_CONTEXT_SECDATAK_CHANGED flag is set when a function returns,
|
||||||
|
* caller must save the data back to the secure non-volatile location
|
||||||
|
* and then clear the flag.
|
||||||
|
*/
|
||||||
|
uint8_t secdatak[VB2_SECDATAK_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
enum vb2_resource_index {
|
enum vb2_resource_index {
|
||||||
@@ -234,8 +255,7 @@ enum vb2_pcr_digest {
|
|||||||
*
|
*
|
||||||
* At this point, firmware verification is done, and vb2_context contains the
|
* At this point, firmware verification is done, and vb2_context contains the
|
||||||
* kernel key needed to verify the kernel. That context should be preserved
|
* kernel key needed to verify the kernel. That context should be preserved
|
||||||
* and passed on to kernel selection. For now, that requires translating it
|
* and passed on to kernel selection.
|
||||||
* into the old VbSharedData format (via a func which does not yet exist...)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -266,6 +286,34 @@ int vb2api_secdata_check(const struct vb2_context *ctx);
|
|||||||
*/
|
*/
|
||||||
int vb2api_secdata_create(struct vb2_context *ctx);
|
int vb2api_secdata_create(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sanity-check the contents of the kernel version secure storage context.
|
||||||
|
*
|
||||||
|
* Use this if reading from secure storage may be flaky, and you want to retry
|
||||||
|
* reading it several times.
|
||||||
|
*
|
||||||
|
* This may be called before vb2api_phase1().
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2api_secdatak_check(const struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create fresh data in the kernel version secure storage context.
|
||||||
|
*
|
||||||
|
* Use this only when initializing the secure storage context on a new machine
|
||||||
|
* the first time it boots. Do NOT simply use this if vb2api_secdatak_check()
|
||||||
|
* (or any other API in this library) fails; that could allow the secure data
|
||||||
|
* to be rolled back to an insecure state.
|
||||||
|
*
|
||||||
|
* This may be called before vb2api_phase1().
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2api_secdatak_create(struct vb2_context *ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Report firmware failure to vboot.
|
* Report firmware failure to vboot.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -111,6 +111,30 @@ enum vb2_return_code {
|
|||||||
/* Called vb2_secdata_set() with uninitialized secdata */
|
/* Called vb2_secdata_set() with uninitialized secdata */
|
||||||
VB2_ERROR_SECDATA_SET_UNINITIALIZED,
|
VB2_ERROR_SECDATA_SET_UNINITIALIZED,
|
||||||
|
|
||||||
|
/* Bad CRC in vb2_secdatak_check_crc() */
|
||||||
|
VB2_ERROR_SECDATAK_CRC,
|
||||||
|
|
||||||
|
/* Bad struct version in vb2_secdatak_init() */
|
||||||
|
VB2_ERROR_SECDATAK_VERSION,
|
||||||
|
|
||||||
|
/* Bad uid in vb2_secdatak_init() */
|
||||||
|
VB2_ERROR_SECDATAK_UID,
|
||||||
|
|
||||||
|
/* Invalid param in vb2_secdatak_get() */
|
||||||
|
VB2_ERROR_SECDATAK_GET_PARAM,
|
||||||
|
|
||||||
|
/* Invalid param in vb2_secdatak_set() */
|
||||||
|
VB2_ERROR_SECDATAK_SET_PARAM,
|
||||||
|
|
||||||
|
/* Invalid flags passed to vb2_secdatak_set() */
|
||||||
|
VB2_ERROR_SECDATAK_SET_FLAGS,
|
||||||
|
|
||||||
|
/* Called vb2_secdatak_get() with uninitialized secdatak */
|
||||||
|
VB2_ERROR_SECDATAK_GET_UNINITIALIZED,
|
||||||
|
|
||||||
|
/* Called vb2_secdatak_set() with uninitialized secdatak */
|
||||||
|
VB2_ERROR_SECDATAK_SET_UNINITIALIZED,
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* Common code errors
|
* Common code errors
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -8,6 +8,9 @@
|
|||||||
#ifndef VBOOT_REFERENCE_VBOOT_SECDATA_H_
|
#ifndef VBOOT_REFERENCE_VBOOT_SECDATA_H_
|
||||||
#define VBOOT_REFERENCE_VBOOT_SECDATA_H_
|
#define VBOOT_REFERENCE_VBOOT_SECDATA_H_
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Firmware version space */
|
||||||
|
|
||||||
/* Expected value of vb2_secdata.version */
|
/* Expected value of vb2_secdata.version */
|
||||||
#define VB2_SECDATA_VERSION 2
|
#define VB2_SECDATA_VERSION 2
|
||||||
|
|
||||||
@@ -28,7 +31,7 @@ enum vb2_secdata_flags {
|
|||||||
VB2_SECDATA_FLAG_DEV_MODE = (1 << 1),
|
VB2_SECDATA_FLAG_DEV_MODE = (1 << 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Secure data area */
|
/* Secure data area (firmware space) */
|
||||||
struct vb2_secdata {
|
struct vb2_secdata {
|
||||||
/* Struct version, for backwards compatibility */
|
/* Struct version, for backwards compatibility */
|
||||||
uint8_t struct_version;
|
uint8_t struct_version;
|
||||||
@@ -55,6 +58,39 @@ enum vb2_secdata_param {
|
|||||||
VB2_SECDATA_VERSIONS,
|
VB2_SECDATA_VERSIONS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Kernel version space */
|
||||||
|
|
||||||
|
/* Kernel space - KERNEL_NV_INDEX, locked with physical presence. */
|
||||||
|
#define VB2_SECDATAK_VERSION 2
|
||||||
|
#define VB2_SECDATAK_UID 0x4752574c /* 'GRWL' */
|
||||||
|
|
||||||
|
struct vb2_secdatak {
|
||||||
|
/* Struct version, for backwards compatibility */
|
||||||
|
uint8_t struct_version;
|
||||||
|
|
||||||
|
/* Unique ID to detect space redefinition */
|
||||||
|
uint32_t uid;
|
||||||
|
|
||||||
|
/* Kernel versions */
|
||||||
|
uint32_t kernel_versions;
|
||||||
|
|
||||||
|
/* Reserved for future expansion */
|
||||||
|
uint8_t reserved[3];
|
||||||
|
|
||||||
|
/* CRC; must be last field in struct */
|
||||||
|
uint8_t crc8;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/* Which param to get/set for vb2_secdatak_get() / vb2_secdatak_set() */
|
||||||
|
enum vb2_secdatak_param {
|
||||||
|
/* Kernel versions */
|
||||||
|
VB2_SECDATAK_VERSIONS = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Firmware version space functions */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the CRC of the secure storage context.
|
* Check the CRC of the secure storage context.
|
||||||
*
|
*
|
||||||
@@ -114,4 +150,70 @@ int vb2_secdata_set(struct vb2_context *ctx,
|
|||||||
enum vb2_secdata_param param,
|
enum vb2_secdata_param param,
|
||||||
uint32_t value);
|
uint32_t value);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Kernel version space functions.
|
||||||
|
*
|
||||||
|
* These are separate functions so that they don't bloat the size of the early
|
||||||
|
* boot code which uses the firmware version space functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the CRC of the kernel version secure storage context.
|
||||||
|
*
|
||||||
|
* Use this if reading from secure storage may be flaky, and you want to retry
|
||||||
|
* reading it several times.
|
||||||
|
*
|
||||||
|
* This may be called before vb2_context_init().
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2_secdatak_check_crc(const struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create fresh data in the secure storage context.
|
||||||
|
*
|
||||||
|
* Use this only when initializing the secure storage context on a new machine
|
||||||
|
* the first time it boots. Do NOT simply use this if vb2_secdatak_check_crc()
|
||||||
|
* (or any other API in this library) fails; that could allow the secure data
|
||||||
|
* to be rolled back to an insecure state.
|
||||||
|
*
|
||||||
|
* This may be called before vb2_context_init().
|
||||||
|
*/
|
||||||
|
int vb2_secdatak_create(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the secure storage context and verify its CRC.
|
||||||
|
*
|
||||||
|
* This must be called before vb2_secdatak_get() or vb2_secdatak_set().
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2_secdatak_init(struct vb2_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a secure storage value.
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @param param Parameter to read
|
||||||
|
* @param dest Destination for value
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2_secdatak_get(struct vb2_context *ctx,
|
||||||
|
enum vb2_secdatak_param param,
|
||||||
|
uint32_t *dest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a secure storage value.
|
||||||
|
*
|
||||||
|
* @param ctx Context pointer
|
||||||
|
* @param param Parameter to write
|
||||||
|
* @param value New value
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2_secdatak_set(struct vb2_context *ctx,
|
||||||
|
enum vb2_secdatak_param param,
|
||||||
|
uint32_t value);
|
||||||
|
|
||||||
#endif /* VBOOT_REFERENCE_VBOOT_2SECDATA_H_ */
|
#endif /* VBOOT_REFERENCE_VBOOT_2SECDATA_H_ */
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ enum vb2_shared_data_status {
|
|||||||
|
|
||||||
/* Chose a firmware slot */
|
/* Chose a firmware slot */
|
||||||
VB2_SD_STATUS_CHOSE_SLOT = (1 << 3),
|
VB2_SD_STATUS_CHOSE_SLOT = (1 << 3),
|
||||||
|
|
||||||
|
/* Secure data kernel version space initialized */
|
||||||
|
VB2_SD_STATUS_SECDATAK_INIT = (1 << 4),
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
114
tests/vb2_secdatak_tests.c
Normal file
114
tests/vb2_secdatak_tests.c
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
/* Copyright 2015 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 kernel secure storage library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "test_common.h"
|
||||||
|
#include "vboot_common.h"
|
||||||
|
|
||||||
|
#include "2common.h"
|
||||||
|
#include "2api.h"
|
||||||
|
#include "2crc8.h"
|
||||||
|
#include "2misc.h"
|
||||||
|
#include "2secdata.h"
|
||||||
|
|
||||||
|
static void test_changed(struct vb2_context *ctx, int changed, const char *why)
|
||||||
|
{
|
||||||
|
if (changed)
|
||||||
|
TEST_NEQ(ctx->flags & VB2_CONTEXT_SECDATAK_CHANGED, 0, why);
|
||||||
|
else
|
||||||
|
TEST_EQ(ctx->flags & VB2_CONTEXT_SECDATAK_CHANGED, 0, why);
|
||||||
|
|
||||||
|
ctx->flags &= ~VB2_CONTEXT_SECDATAK_CHANGED;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void secdatak_test(void)
|
||||||
|
{
|
||||||
|
uint8_t workbuf[VB2_WORKBUF_RECOMMENDED_SIZE]
|
||||||
|
__attribute__ ((aligned (VB2_WORKBUF_ALIGN)));
|
||||||
|
struct vb2_context c = {
|
||||||
|
.flags = 0,
|
||||||
|
.workbuf = workbuf,
|
||||||
|
.workbuf_size = sizeof(workbuf),
|
||||||
|
};
|
||||||
|
uint32_t v = 1;
|
||||||
|
|
||||||
|
/* Blank data is invalid */
|
||||||
|
memset(c.secdatak, 0xa6, sizeof(c.secdatak));
|
||||||
|
TEST_EQ(vb2_secdatak_check_crc(&c),
|
||||||
|
VB2_ERROR_SECDATAK_CRC, "Check blank CRC");
|
||||||
|
TEST_EQ(vb2_secdatak_init(&c),
|
||||||
|
VB2_ERROR_SECDATAK_CRC, "Init blank CRC");
|
||||||
|
|
||||||
|
/* Create good data */
|
||||||
|
TEST_SUCC(vb2_secdatak_create(&c), "Create");
|
||||||
|
TEST_SUCC(vb2_secdatak_check_crc(&c), "Check created CRC");
|
||||||
|
TEST_SUCC(vb2_secdatak_init(&c), "Init created CRC");
|
||||||
|
test_changed(&c, 1, "Create changes data");
|
||||||
|
|
||||||
|
/* Now corrupt it */
|
||||||
|
c.secdatak[2]++;
|
||||||
|
TEST_EQ(vb2_secdatak_check_crc(&c),
|
||||||
|
VB2_ERROR_SECDATAK_CRC, "Check invalid CRC");
|
||||||
|
TEST_EQ(vb2_secdatak_init(&c),
|
||||||
|
VB2_ERROR_SECDATAK_CRC, "Init invalid CRC");
|
||||||
|
|
||||||
|
/* Make sure UID is checked */
|
||||||
|
{
|
||||||
|
struct vb2_secdatak *sec = (struct vb2_secdatak *)c.secdatak;
|
||||||
|
|
||||||
|
vb2_secdatak_create(&c);
|
||||||
|
sec->uid++;
|
||||||
|
sec->crc8 = vb2_crc8(sec, offsetof(struct vb2_secdatak, crc8));
|
||||||
|
|
||||||
|
TEST_EQ(vb2_secdatak_init(&c), VB2_ERROR_SECDATAK_UID,
|
||||||
|
"Init invalid struct UID");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read/write versions */
|
||||||
|
vb2_secdatak_create(&c);
|
||||||
|
c.flags = 0;
|
||||||
|
TEST_SUCC(vb2_secdatak_get(&c, VB2_SECDATAK_VERSIONS, &v),
|
||||||
|
"Get versions");
|
||||||
|
TEST_EQ(v, 0, "Versions created 0");
|
||||||
|
test_changed(&c, 0, "Get doesn't change data");
|
||||||
|
TEST_SUCC(vb2_secdatak_set(&c, VB2_SECDATAK_VERSIONS, 0x123456ff),
|
||||||
|
"Set versions");
|
||||||
|
test_changed(&c, 1, "Set changes data");
|
||||||
|
TEST_SUCC(vb2_secdatak_set(&c, VB2_SECDATAK_VERSIONS, 0x123456ff),
|
||||||
|
"Set versions 2");
|
||||||
|
test_changed(&c, 0, "Set again doesn't change data");
|
||||||
|
TEST_SUCC(vb2_secdatak_get(&c, VB2_SECDATAK_VERSIONS, &v),
|
||||||
|
"Get versions 2");
|
||||||
|
TEST_EQ(v, 0x123456ff, "Versions changed");
|
||||||
|
|
||||||
|
/* Invalid field fails */
|
||||||
|
TEST_EQ(vb2_secdatak_get(&c, -1, &v),
|
||||||
|
VB2_ERROR_SECDATAK_GET_PARAM, "Get invalid");
|
||||||
|
TEST_EQ(vb2_secdatak_set(&c, -1, 456),
|
||||||
|
VB2_ERROR_SECDATAK_SET_PARAM, "Set invalid");
|
||||||
|
test_changed(&c, 0, "Set invalid field doesn't change data");
|
||||||
|
|
||||||
|
/* Read/write uninitialized data fails */
|
||||||
|
vb2_get_sd(&c)->status &= ~VB2_SD_STATUS_SECDATAK_INIT;
|
||||||
|
TEST_EQ(vb2_secdatak_get(&c, VB2_SECDATAK_VERSIONS, &v),
|
||||||
|
VB2_ERROR_SECDATAK_GET_UNINITIALIZED, "Get uninitialized");
|
||||||
|
test_changed(&c, 0, "Get uninitialized doesn't change data");
|
||||||
|
TEST_EQ(vb2_secdatak_set(&c, VB2_SECDATAK_VERSIONS, 0x123456ff),
|
||||||
|
VB2_ERROR_SECDATAK_SET_UNINITIALIZED, "Set uninitialized");
|
||||||
|
test_changed(&c, 0, "Set uninitialized doesn't change data");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
secdatak_test();
|
||||||
|
|
||||||
|
return gTestSuccess ? 0 : 255;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user