mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-23 17:55:01 +00:00
vboot2: Add host library functions to read/write new-format key objects
And unit tests for them. BUG=chromium:423882 BRANCH=none TEST=make runtests && VBOOT2=1 make runtests Change-Id: I720bfb2537bae60f05b5ce28ab196a331a82eedf Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/230931
This commit is contained in:
committed by
chrome-internal-fetch
parent
02e11b323b
commit
59c29202d2
4
Makefile
4
Makefile
@@ -376,6 +376,7 @@ UTILLIB_SRCS = \
|
|||||||
|
|
||||||
ifneq (${VBOOT2},)
|
ifneq (${VBOOT2},)
|
||||||
UTILLIB_SRCS += \
|
UTILLIB_SRCS += \
|
||||||
|
host/lib/host_key2.c \
|
||||||
host/lib/host_misc2.c \
|
host/lib/host_misc2.c \
|
||||||
|
|
||||||
endif
|
endif
|
||||||
@@ -632,6 +633,7 @@ TEST_NAMES += \
|
|||||||
tests/vb2_common_tests \
|
tests/vb2_common_tests \
|
||||||
tests/vb2_common2_tests \
|
tests/vb2_common2_tests \
|
||||||
tests/vb2_common3_tests \
|
tests/vb2_common3_tests \
|
||||||
|
tests/vb2_host_key_tests \
|
||||||
tests/vb2_host_misc_tests \
|
tests/vb2_host_misc_tests \
|
||||||
tests/vb2_misc_tests \
|
tests/vb2_misc_tests \
|
||||||
tests/vb2_misc2_tests \
|
tests/vb2_misc2_tests \
|
||||||
@@ -988,6 +990,7 @@ ${BUILD}/utility/signature_digest_utility: LDLIBS += ${CRYPTO_LIBS}
|
|||||||
${BUILD}/host/linktest/main: LDLIBS += ${CRYPTO_LIBS}
|
${BUILD}/host/linktest/main: LDLIBS += ${CRYPTO_LIBS}
|
||||||
${BUILD}/tests/vb2_common2_tests: LDLIBS += ${CRYPTO_LIBS}
|
${BUILD}/tests/vb2_common2_tests: LDLIBS += ${CRYPTO_LIBS}
|
||||||
${BUILD}/tests/vb2_common3_tests: LDLIBS += ${CRYPTO_LIBS}
|
${BUILD}/tests/vb2_common3_tests: LDLIBS += ${CRYPTO_LIBS}
|
||||||
|
${BUILD}/tests/vb2_host_key_tests: LDLIBS += ${CRYPTO_LIBS}
|
||||||
${BUILD}/tests/vboot_common2_tests: LDLIBS += ${CRYPTO_LIBS}
|
${BUILD}/tests/vboot_common2_tests: LDLIBS += ${CRYPTO_LIBS}
|
||||||
${BUILD}/tests/vboot_common3_tests: LDLIBS += ${CRYPTO_LIBS}
|
${BUILD}/tests/vboot_common3_tests: LDLIBS += ${CRYPTO_LIBS}
|
||||||
|
|
||||||
@@ -1167,6 +1170,7 @@ run2tests: test_setup
|
|||||||
${RUNTEST} ${BUILD_RUN}/tests/vb2_common_tests
|
${RUNTEST} ${BUILD_RUN}/tests/vb2_common_tests
|
||||||
${RUNTEST} ${BUILD_RUN}/tests/vb2_common2_tests ${TEST_KEYS}
|
${RUNTEST} ${BUILD_RUN}/tests/vb2_common2_tests ${TEST_KEYS}
|
||||||
${RUNTEST} ${BUILD_RUN}/tests/vb2_common3_tests ${TEST_KEYS}
|
${RUNTEST} ${BUILD_RUN}/tests/vb2_common3_tests ${TEST_KEYS}
|
||||||
|
${RUNTEST} ${BUILD_RUN}/tests/vb2_host_key_tests ${TEST_KEYS}
|
||||||
${RUNTEST} ${BUILD_RUN}/tests/vb2_host_misc_tests
|
${RUNTEST} ${BUILD_RUN}/tests/vb2_host_misc_tests
|
||||||
${RUNTEST} ${BUILD_RUN}/tests/vb2_misc_tests
|
${RUNTEST} ${BUILD_RUN}/tests/vb2_misc_tests
|
||||||
${RUNTEST} ${BUILD_RUN}/tests/vb2_misc2_tests
|
${RUNTEST} ${BUILD_RUN}/tests/vb2_misc2_tests
|
||||||
|
|||||||
@@ -9,9 +9,36 @@
|
|||||||
#include "2common.h"
|
#include "2common.h"
|
||||||
#include "2rsa.h"
|
#include "2rsa.h"
|
||||||
|
|
||||||
const uint8_t *vb2_packed_key2_data(const struct vb2_packed_key2 *key)
|
int vb2_unpack_key2_data(struct vb2_public_key *key,
|
||||||
|
const uint8_t *key_data,
|
||||||
|
uint32_t key_size)
|
||||||
{
|
{
|
||||||
return (const uint8_t *)key + key->key_offset;
|
const uint32_t *buf32 = (const uint32_t *)key_data;
|
||||||
|
uint32_t expected_key_size = vb2_packed_key_size(key->sig_alg);
|
||||||
|
|
||||||
|
/* Make sure buffer is the correct length */
|
||||||
|
if (!expected_key_size || expected_key_size != key_size) {
|
||||||
|
VB2_DEBUG("Wrong key size for algorithm\n");
|
||||||
|
return VB2_ERROR_UNPACK_KEY_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for alignment */
|
||||||
|
if (!vb2_aligned(buf32, sizeof(uint32_t)))
|
||||||
|
return VB2_ERROR_UNPACK_KEY_ALIGN;
|
||||||
|
|
||||||
|
key->arrsize = buf32[0];
|
||||||
|
|
||||||
|
/* Sanity check key array size */
|
||||||
|
if (key->arrsize * sizeof(uint32_t) != vb2_rsa_sig_size(key->sig_alg))
|
||||||
|
return VB2_ERROR_UNPACK_KEY_ARRAY_SIZE;
|
||||||
|
|
||||||
|
key->n0inv = buf32[1];
|
||||||
|
|
||||||
|
/* Arrays point inside the key data */
|
||||||
|
key->n = buf32 + 2;
|
||||||
|
key->rr = buf32 + 2 + key->arrsize;
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vb2_unpack_key2(struct vb2_public_key *key,
|
int vb2_unpack_key2(struct vb2_public_key *key,
|
||||||
@@ -20,8 +47,6 @@ int vb2_unpack_key2(struct vb2_public_key *key,
|
|||||||
{
|
{
|
||||||
const struct vb2_packed_key2 *pkey =
|
const struct vb2_packed_key2 *pkey =
|
||||||
(const struct vb2_packed_key2 *)buf;
|
(const struct vb2_packed_key2 *)buf;
|
||||||
const uint32_t *buf32;
|
|
||||||
uint32_t expected_key_size;
|
|
||||||
uint32_t sig_size;
|
uint32_t sig_size;
|
||||||
uint32_t min_offset = 0;
|
uint32_t min_offset = 0;
|
||||||
int rv;
|
int rv;
|
||||||
@@ -65,25 +90,11 @@ int vb2_unpack_key2(struct vb2_public_key *key,
|
|||||||
if (!vb2_digest_size(key->hash_alg))
|
if (!vb2_digest_size(key->hash_alg))
|
||||||
return VB2_ERROR_UNPACK_KEY_HASH_ALGORITHM;
|
return VB2_ERROR_UNPACK_KEY_HASH_ALGORITHM;
|
||||||
|
|
||||||
expected_key_size = vb2_packed_key_size(key->sig_alg);
|
rv = vb2_unpack_key2_data(key,
|
||||||
if (!expected_key_size || expected_key_size != pkey->key_size) {
|
(const uint8_t *)pkey + pkey->key_offset,
|
||||||
VB2_DEBUG("Wrong key size for algorithm\n");
|
pkey->key_size);
|
||||||
return VB2_ERROR_UNPACK_KEY_SIZE;
|
if (rv)
|
||||||
}
|
return rv;
|
||||||
|
|
||||||
/* Unpack key data */
|
|
||||||
buf32 = (const uint32_t *)vb2_packed_key2_data(pkey);
|
|
||||||
|
|
||||||
/* Sanity check key array size */
|
|
||||||
key->arrsize = buf32[0];
|
|
||||||
if (key->arrsize * sizeof(uint32_t) != sig_size)
|
|
||||||
return VB2_ERROR_UNPACK_KEY_ARRAY_SIZE;
|
|
||||||
|
|
||||||
key->n0inv = buf32[1];
|
|
||||||
|
|
||||||
/* Arrays point inside the key data */
|
|
||||||
key->n = buf32 + 2;
|
|
||||||
key->rr = buf32 + 2 + key->arrsize;
|
|
||||||
|
|
||||||
/* Key description */
|
/* Key description */
|
||||||
if (pkey->c.desc_size)
|
if (pkey->c.desc_size)
|
||||||
|
|||||||
@@ -288,6 +288,20 @@ int vb2_unpack_key2(struct vb2_public_key *key,
|
|||||||
const uint8_t *buf,
|
const uint8_t *buf,
|
||||||
uint32_t size);
|
uint32_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unpack the RSA data fields for a public key
|
||||||
|
*
|
||||||
|
* This is called by vb2_unpack_key2() to extract the arrays from a packed key.
|
||||||
|
* These elements of *key will point inside the key_data buffer.
|
||||||
|
*
|
||||||
|
* @param key Destination key for RSA data fields
|
||||||
|
* @param key_data Packed key data (from inside a packed key buffer)
|
||||||
|
* @param key_size Size of packed key data in bytes
|
||||||
|
*/
|
||||||
|
int vb2_unpack_key2_data(struct vb2_public_key *key,
|
||||||
|
const uint8_t *key_data,
|
||||||
|
uint32_t key_size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return expected signature size for a signature/hash algorithm pair
|
* Return expected signature size for a signature/hash algorithm pair
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -472,6 +472,83 @@ enum vb2_return_code {
|
|||||||
/* Unable to write data in write_file() */
|
/* Unable to write data in write_file() */
|
||||||
VB2_ERROR_WRITE_FILE_DATA,
|
VB2_ERROR_WRITE_FILE_DATA,
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Errors generated by host library key functions
|
||||||
|
*/
|
||||||
|
VB2_ERROR_HOST_KEY = VB2_ERROR_HOST_BASE + 0x020000,
|
||||||
|
|
||||||
|
/* Unable to allocate key in vb2_private_key_read_pem() */
|
||||||
|
VB2_ERROR_READ_PEM_ALLOC,
|
||||||
|
|
||||||
|
/* Unable to open .pem file in vb2_private_key_read_pem() */
|
||||||
|
VB2_ERROR_READ_PEM_FILE_OPEN,
|
||||||
|
|
||||||
|
/* Bad RSA data from .pem file in vb2_private_key_read_pem() */
|
||||||
|
VB2_ERROR_READ_PEM_RSA,
|
||||||
|
|
||||||
|
/* Unable to set private key description */
|
||||||
|
VB2_ERROR_PRIVATE_KEY_SET_DESC,
|
||||||
|
|
||||||
|
/* Bad magic number in vb2_private_key_unpack() */
|
||||||
|
VB2_ERROR_UNPACK_PRIVATE_KEY_MAGIC,
|
||||||
|
|
||||||
|
/* Bad common header in vb2_private_key_unpack() */
|
||||||
|
VB2_ERROR_UNPACK_PRIVATE_KEY_HEADER,
|
||||||
|
|
||||||
|
/* Bad key data in vb2_private_key_unpack() */
|
||||||
|
VB2_ERROR_UNPACK_PRIVATE_KEY_DATA,
|
||||||
|
|
||||||
|
/* Bad struct version in vb2_private_key_unpack() */
|
||||||
|
VB2_ERROR_UNPACK_PRIVATE_KEY_STRUCT_VERSION,
|
||||||
|
|
||||||
|
/* Unable to allocate buffer in vb2_private_key_unpack() */
|
||||||
|
VB2_ERROR_UNPACK_PRIVATE_KEY_ALLOC,
|
||||||
|
|
||||||
|
/* Unable to unpack RSA key in vb2_private_key_unpack() */
|
||||||
|
VB2_ERROR_UNPACK_PRIVATE_KEY_RSA,
|
||||||
|
|
||||||
|
/* Unable to set description in vb2_private_key_unpack() */
|
||||||
|
VB2_ERROR_UNPACK_PRIVATE_KEY_DESC,
|
||||||
|
|
||||||
|
/* Unable to create RSA data in vb2_private_key_write() */
|
||||||
|
VB2_ERROR_PRIVATE_KEY_WRITE_RSA,
|
||||||
|
|
||||||
|
/* Unable to allocate packed key buffer in vb2_private_key_write() */
|
||||||
|
VB2_ERROR_PRIVATE_KEY_WRITE_ALLOC,
|
||||||
|
|
||||||
|
/* Unable to write file in vb2_private_key_write() */
|
||||||
|
VB2_ERROR_PRIVATE_KEY_WRITE_FILE,
|
||||||
|
|
||||||
|
/* Unable to determine key size in vb2_public_key_alloc() */
|
||||||
|
VB2_ERROR_PUBLIC_KEY_ALLOC_SIZE,
|
||||||
|
|
||||||
|
/* Unable to allocate buffer in vb2_public_key_alloc() */
|
||||||
|
VB2_ERROR_PUBLIC_KEY_ALLOC,
|
||||||
|
|
||||||
|
/* Unable to set public key description */
|
||||||
|
VB2_ERROR_PUBLIC_KEY_SET_DESC,
|
||||||
|
|
||||||
|
/* Unable to read key data in vb2_public_key_read_keyb() */
|
||||||
|
VB2_ERROR_READ_KEYB_DATA,
|
||||||
|
|
||||||
|
/* Wrong amount of data read in vb2_public_key_read_keyb() */
|
||||||
|
VB2_ERROR_READ_KEYB_SIZE,
|
||||||
|
|
||||||
|
/* Unable to allocate key buffer in vb2_public_key_read_keyb() */
|
||||||
|
VB2_ERROR_READ_KEYB_ALLOC,
|
||||||
|
|
||||||
|
/* Error unpacking RSA arrays in vb2_public_key_read_keyb() */
|
||||||
|
VB2_ERROR_READ_KEYB_UNPACK,
|
||||||
|
|
||||||
|
/* Unable to read key data in vb2_packed_key_read() */
|
||||||
|
VB2_ERROR_READ_PACKED_KEY_DATA,
|
||||||
|
|
||||||
|
/* Bad key data in vb2_packed_key_read() */
|
||||||
|
VB2_ERROR_READ_PACKED_KEY,
|
||||||
|
|
||||||
|
/* Unable to determine key size in vb2_public_key_pack() */
|
||||||
|
VB2_ERROR_PUBLIC_KEY_PACK_SIZE,
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* Highest non-zero error generated inside vboot library. Note that
|
* Highest non-zero error generated inside vboot library. Note that
|
||||||
* error codes passed through vboot when it calls external APIs may
|
* error codes passed through vboot when it calls external APIs may
|
||||||
|
|||||||
@@ -213,6 +213,9 @@ enum vb2_struct_common_magic {
|
|||||||
/* "Vb2F" = vb2_fw_preamble.c.magic */
|
/* "Vb2F" = vb2_fw_preamble.c.magic */
|
||||||
VB2_MAGIC_FW_PREAMBLE2 = 0x46326256,
|
VB2_MAGIC_FW_PREAMBLE2 = 0x46326256,
|
||||||
|
|
||||||
|
/* "Vb2I" = vb2_packed_private_key2.c.magic */
|
||||||
|
VB2_MAGIC_PACKED_PRIVATE_KEY2 = 0x49326256,
|
||||||
|
|
||||||
/* "Vb2K" = vb2_kernel_preamble.c.magic */
|
/* "Vb2K" = vb2_kernel_preamble.c.magic */
|
||||||
VB2_MAGIC_KERNEL_PREAMBLE2 = 0x4b326256,
|
VB2_MAGIC_KERNEL_PREAMBLE2 = 0x4b326256,
|
||||||
|
|
||||||
@@ -356,6 +359,45 @@ struct vb2_packed_key2 {
|
|||||||
#define EXPECTED_VB2_PACKED_KEY2_SIZE \
|
#define EXPECTED_VB2_PACKED_KEY2_SIZE \
|
||||||
(EXPECTED_VB2_STRUCT_COMMON_SIZE + EXPECTED_GUID_SIZE + 16)
|
(EXPECTED_VB2_STRUCT_COMMON_SIZE + EXPECTED_GUID_SIZE + 16)
|
||||||
|
|
||||||
|
/* Current version of vb2_packed_private_key2 struct */
|
||||||
|
#define VB2_PACKED_PRIVATE_KEY2_VERSION_MAJOR 3
|
||||||
|
#define VB2_PACKED_PRIVATE_KEY2_VERSION_MINOR 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Packed private key data, version 2
|
||||||
|
*
|
||||||
|
* The key data must be arranged like this:
|
||||||
|
* 1) vb2_packed_private_key2 header struct h
|
||||||
|
* 2) Key description (pointed to by h.c.fixed_size)
|
||||||
|
* 3) Key data key (pointed to by h.key_offset)
|
||||||
|
*/
|
||||||
|
struct vb2_packed_private_key2 {
|
||||||
|
/* Common header fields */
|
||||||
|
struct vb2_struct_common c;
|
||||||
|
|
||||||
|
/* Offset of key data from start of this struct */
|
||||||
|
uint32_t key_offset;
|
||||||
|
|
||||||
|
/* Size of key data in bytes (NOT strength of key in bits) */
|
||||||
|
uint32_t key_size;
|
||||||
|
|
||||||
|
/* Signature algorithm used by the key (enum vb2_signature_algorithm) */
|
||||||
|
uint16_t sig_alg;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hash digest algorithm used with the key (enum vb2_hash_algorithm).
|
||||||
|
* This is explicitly specified as part of the key to prevent use of a
|
||||||
|
* strong key with a weak hash.
|
||||||
|
*/
|
||||||
|
uint16_t hash_alg;
|
||||||
|
|
||||||
|
/* Key GUID */
|
||||||
|
struct vb2_guid guid;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
#define EXPECTED_VB2_PACKED_PRIVATE_KEY2_SIZE \
|
||||||
|
(EXPECTED_VB2_STRUCT_COMMON_SIZE + EXPECTED_GUID_SIZE + 12)
|
||||||
|
|
||||||
/* Current version of vb2_signature2 struct */
|
/* Current version of vb2_signature2 struct */
|
||||||
#define VB2_SIGNATURE2_VERSION_MAJOR 3
|
#define VB2_SIGNATURE2_VERSION_MAJOR 3
|
||||||
#define VB2_SIGNATURE2_VERSION_MINOR 0
|
#define VB2_SIGNATURE2_VERSION_MINOR 0
|
||||||
|
|||||||
419
host/lib/host_key2.c
Normal file
419
host/lib/host_key2.c
Normal file
@@ -0,0 +1,419 @@
|
|||||||
|
/* 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 keys.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define OPENSSL_NO_SHA
|
||||||
|
#include <openssl/engine.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/rsa.h>
|
||||||
|
#include <openssl/x509.h>
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
#include "2common.h"
|
||||||
|
#include "2rsa.h"
|
||||||
|
#include "host_common.h"
|
||||||
|
#include "host_key2.h"
|
||||||
|
#include "host_misc.h"
|
||||||
|
|
||||||
|
void vb2_private_key_free(struct vb2_private_key *key)
|
||||||
|
{
|
||||||
|
if (!key)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (key->rsa_private_key)
|
||||||
|
RSA_free(key->rsa_private_key);
|
||||||
|
|
||||||
|
if (key->desc)
|
||||||
|
free(key->desc);
|
||||||
|
|
||||||
|
free(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_private_key_unpack(struct vb2_private_key **key_ptr,
|
||||||
|
const uint8_t *buf,
|
||||||
|
uint32_t size)
|
||||||
|
{
|
||||||
|
const struct vb2_packed_private_key2 *pkey =
|
||||||
|
(const struct vb2_packed_private_key2 *)buf;
|
||||||
|
struct vb2_private_key *key;
|
||||||
|
const unsigned char *start;
|
||||||
|
uint32_t min_offset = 0;
|
||||||
|
|
||||||
|
*key_ptr = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check magic number.
|
||||||
|
*
|
||||||
|
* TODO: If it doesn't match, pass through to the old packed key format.
|
||||||
|
*/
|
||||||
|
if (pkey->c.magic != VB2_MAGIC_PACKED_PRIVATE_KEY2)
|
||||||
|
return VB2_ERROR_UNPACK_PRIVATE_KEY_MAGIC;
|
||||||
|
|
||||||
|
if (vb2_verify_common_header(buf, size))
|
||||||
|
return VB2_ERROR_UNPACK_PRIVATE_KEY_HEADER;
|
||||||
|
|
||||||
|
/* Make sure key data is inside */
|
||||||
|
if (vb2_verify_common_member(pkey, &min_offset,
|
||||||
|
pkey->key_offset, pkey->key_size))
|
||||||
|
return VB2_ERROR_UNPACK_PRIVATE_KEY_DATA;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for compatible version. No need to check minor version, since
|
||||||
|
* that's compatible across readers matching the major version, and we
|
||||||
|
* haven't added any new fields.
|
||||||
|
*/
|
||||||
|
if (pkey->c.struct_version_major !=
|
||||||
|
VB2_PACKED_PRIVATE_KEY2_VERSION_MAJOR)
|
||||||
|
return VB2_ERROR_UNPACK_PRIVATE_KEY_STRUCT_VERSION;
|
||||||
|
|
||||||
|
/* Allocate the new key */
|
||||||
|
key = malloc(sizeof(*key));
|
||||||
|
if (!key)
|
||||||
|
return VB2_ERROR_UNPACK_PRIVATE_KEY_ALLOC;
|
||||||
|
|
||||||
|
memset(key, 0, sizeof(*key));
|
||||||
|
|
||||||
|
/* Copy key algorithms and guid */
|
||||||
|
key->sig_alg = pkey->sig_alg;
|
||||||
|
key->hash_alg = pkey->hash_alg;
|
||||||
|
key->guid = pkey->guid;
|
||||||
|
|
||||||
|
/* Unpack RSA key */
|
||||||
|
start = (const unsigned char *)(buf + pkey->key_offset);
|
||||||
|
key->rsa_private_key = d2i_RSAPrivateKey(0, &start, pkey->key_size);
|
||||||
|
if (!key->rsa_private_key) {
|
||||||
|
free(key);
|
||||||
|
return VB2_ERROR_UNPACK_PRIVATE_KEY_RSA;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Key description */
|
||||||
|
if (pkey->c.desc_size) {
|
||||||
|
if (vb2_private_key_set_desc(
|
||||||
|
key, (const char *)(buf + pkey->c.fixed_size))) {
|
||||||
|
vb2_private_key_free(key);
|
||||||
|
return VB2_ERROR_UNPACK_PRIVATE_KEY_DESC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*key_ptr = key;
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_private_key_read(struct vb2_private_key **key_ptr,
|
||||||
|
const char *filename)
|
||||||
|
{
|
||||||
|
uint32_t size = 0;
|
||||||
|
uint8_t *buf;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
*key_ptr = NULL;
|
||||||
|
|
||||||
|
rv = vb2_read_file(filename, &buf, &size);
|
||||||
|
if (rv)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
rv = vb2_private_key_unpack(key_ptr, buf, size);
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_private_key_read_pem(struct vb2_private_key **key_ptr,
|
||||||
|
const char *filename)
|
||||||
|
{
|
||||||
|
struct vb2_private_key *key;
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
*key_ptr = NULL;
|
||||||
|
|
||||||
|
/* Allocate the new key */
|
||||||
|
key = malloc(sizeof(*key));
|
||||||
|
if (!key)
|
||||||
|
return VB2_ERROR_READ_PEM_ALLOC;
|
||||||
|
|
||||||
|
memset(key, 0, sizeof(*key));
|
||||||
|
|
||||||
|
/* Read private key */
|
||||||
|
f = fopen(filename, "r");
|
||||||
|
if (!f) {
|
||||||
|
free(key);
|
||||||
|
return VB2_ERROR_READ_PEM_FILE_OPEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
key->rsa_private_key = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL);
|
||||||
|
if (!key->rsa_private_key) {
|
||||||
|
free(key);
|
||||||
|
return VB2_ERROR_READ_PEM_RSA;
|
||||||
|
}
|
||||||
|
|
||||||
|
*key_ptr = key;
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_private_key_set_desc(struct vb2_private_key *key, const char *desc)
|
||||||
|
{
|
||||||
|
if (key->desc)
|
||||||
|
free(key->desc);
|
||||||
|
|
||||||
|
if (desc) {
|
||||||
|
key->desc = strdup(desc);
|
||||||
|
if (!key->desc)
|
||||||
|
return VB2_ERROR_PRIVATE_KEY_SET_DESC;
|
||||||
|
} else {
|
||||||
|
key->desc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_private_key_write(const struct vb2_private_key *key,
|
||||||
|
const char *filename)
|
||||||
|
{
|
||||||
|
struct vb2_packed_private_key2 pkey = {
|
||||||
|
.c.magic = VB2_MAGIC_PACKED_PRIVATE_KEY2,
|
||||||
|
.c.struct_version_major = VB2_PACKED_PRIVATE_KEY2_VERSION_MAJOR,
|
||||||
|
.c.struct_version_minor = VB2_PACKED_PRIVATE_KEY2_VERSION_MINOR,
|
||||||
|
.c.fixed_size = sizeof(pkey),
|
||||||
|
.sig_alg = key->sig_alg,
|
||||||
|
.hash_alg = key->hash_alg,
|
||||||
|
.guid = key->guid,
|
||||||
|
};
|
||||||
|
uint8_t *buf;
|
||||||
|
uint8_t *rsabuf = NULL;
|
||||||
|
int rsalen;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
memcpy(&pkey.guid, &key->guid, sizeof(pkey.guid));
|
||||||
|
|
||||||
|
if (key->desc)
|
||||||
|
pkey.c.desc_size = roundup32(strlen(key->desc) + 1);
|
||||||
|
|
||||||
|
/* Pack RSA key */
|
||||||
|
rsalen = i2d_RSAPrivateKey(key->rsa_private_key, &rsabuf);
|
||||||
|
if (rsalen <= 0)
|
||||||
|
return VB2_ERROR_PRIVATE_KEY_WRITE_RSA;
|
||||||
|
|
||||||
|
pkey.key_offset = pkey.c.fixed_size + pkey.c.desc_size;
|
||||||
|
pkey.key_size = roundup32(rsalen);
|
||||||
|
pkey.c.total_size = pkey.key_offset + pkey.key_size;
|
||||||
|
|
||||||
|
/* Pack private key */
|
||||||
|
buf = malloc(pkey.c.total_size);
|
||||||
|
if (!buf) {
|
||||||
|
free(rsabuf);
|
||||||
|
return VB2_ERROR_PRIVATE_KEY_WRITE_ALLOC;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(buf, 0, pkey.c.total_size);
|
||||||
|
memcpy(buf, &pkey, sizeof(pkey));
|
||||||
|
|
||||||
|
/* strcpy() is ok here because we checked the length above */
|
||||||
|
if (key->desc)
|
||||||
|
strcpy((char *)buf + pkey.c.fixed_size, key->desc);
|
||||||
|
|
||||||
|
memcpy(buf + pkey.key_offset, rsabuf, rsalen);
|
||||||
|
free(rsabuf);
|
||||||
|
|
||||||
|
rv = vb2_write_object(filename, buf);
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
return rv ? VB2_ERROR_PRIVATE_KEY_WRITE_FILE : VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate a public key buffer of sufficient size for the signature algorithm.
|
||||||
|
*
|
||||||
|
* This only initializes the sig_alg field and the guid field to an empty
|
||||||
|
* guid. It does not set any of the other fields in *key_ptr.
|
||||||
|
*
|
||||||
|
* @param key_ptr Destination for newly allocated key; this must be
|
||||||
|
* freed with vb2_public_key_free().
|
||||||
|
* @param sig_alg Signature algorithm for key.
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
static int vb2_public_key_alloc(struct vb2_public_key **key_ptr,
|
||||||
|
enum vb2_signature_algorithm sig_alg)
|
||||||
|
{
|
||||||
|
struct vb2_public_key *key;
|
||||||
|
uint32_t key_data_size = vb2_packed_key_size(sig_alg);
|
||||||
|
|
||||||
|
/* The buffer contains the key, its GUID, and its packed data */
|
||||||
|
uint32_t buf_size = sizeof(*key) + sizeof(struct vb2_guid) +
|
||||||
|
key_data_size;
|
||||||
|
|
||||||
|
if (!key_data_size)
|
||||||
|
return VB2_ERROR_PUBLIC_KEY_ALLOC_SIZE;
|
||||||
|
|
||||||
|
key = malloc(buf_size);
|
||||||
|
if (!key)
|
||||||
|
return VB2_ERROR_PUBLIC_KEY_ALLOC;
|
||||||
|
|
||||||
|
memset(key, 0, buf_size);
|
||||||
|
key->guid = (struct vb2_guid *)(key + 1);
|
||||||
|
key->sig_alg = sig_alg;
|
||||||
|
|
||||||
|
*key_ptr = key;
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vb2_public_key_free(struct vb2_public_key *key)
|
||||||
|
{
|
||||||
|
if (key->desc)
|
||||||
|
free((void *)key->desc);
|
||||||
|
|
||||||
|
free(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the packed data for a key allocated with vb2_public_key_alloc().
|
||||||
|
*
|
||||||
|
* The packed data is in the same buffer, following the key struct and GUID.
|
||||||
|
*/
|
||||||
|
static uint8_t *vb2_public_key_packed_data(struct vb2_public_key *key)
|
||||||
|
{
|
||||||
|
return (uint8_t *)(key->guid + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_public_key_read_keyb(struct vb2_public_key **key_ptr,
|
||||||
|
const char *filename)
|
||||||
|
{
|
||||||
|
struct vb2_public_key *key = NULL;
|
||||||
|
uint8_t *key_data, *key_buf;
|
||||||
|
uint32_t key_size;
|
||||||
|
enum vb2_signature_algorithm sig_alg;
|
||||||
|
|
||||||
|
*key_ptr = NULL;
|
||||||
|
|
||||||
|
if (vb2_read_file(filename, &key_data, &key_size))
|
||||||
|
return VB2_ERROR_READ_KEYB_DATA;
|
||||||
|
|
||||||
|
/* Guess the signature algorithm from the key size */
|
||||||
|
for (sig_alg = VB2_SIG_RSA1024; sig_alg <= VB2_SIG_RSA8192; sig_alg++) {
|
||||||
|
if (key_size == vb2_packed_key_size(sig_alg))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (sig_alg > VB2_SIG_RSA8192) {
|
||||||
|
free(key_data);
|
||||||
|
return VB2_ERROR_READ_KEYB_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vb2_public_key_alloc(&key, sig_alg)) {
|
||||||
|
free(key_data);
|
||||||
|
return VB2_ERROR_READ_KEYB_ALLOC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy data from the file buffer to the public key buffer */
|
||||||
|
key_buf = vb2_public_key_packed_data(key);
|
||||||
|
memcpy(key_buf, key_data, key_size);
|
||||||
|
free(key_data);
|
||||||
|
|
||||||
|
if (vb2_unpack_key2_data(key, key_buf, key_size)) {
|
||||||
|
vb2_public_key_free(key);
|
||||||
|
return VB2_ERROR_READ_KEYB_UNPACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
*key_ptr = key;
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_public_key_set_desc(struct vb2_public_key *key, const char *desc)
|
||||||
|
{
|
||||||
|
if (key->desc)
|
||||||
|
free((void *)key->desc);
|
||||||
|
|
||||||
|
if (desc) {
|
||||||
|
key->desc = strdup(desc);
|
||||||
|
if (!key->desc)
|
||||||
|
return VB2_ERROR_PUBLIC_KEY_SET_DESC;
|
||||||
|
} else {
|
||||||
|
key->desc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_packed_key2_read(struct vb2_packed_key2 **key_ptr,
|
||||||
|
const char *filename)
|
||||||
|
{
|
||||||
|
struct vb2_public_key key;
|
||||||
|
uint8_t *buf;
|
||||||
|
uint32_t size;
|
||||||
|
|
||||||
|
*key_ptr = NULL;
|
||||||
|
|
||||||
|
if (!vb2_read_file(filename, &buf, &size))
|
||||||
|
return VB2_ERROR_READ_PACKED_KEY_DATA;
|
||||||
|
|
||||||
|
/* Sanity check: make sure key unpacks properly */
|
||||||
|
if (!vb2_unpack_key(&key, buf, size))
|
||||||
|
return VB2_ERROR_READ_PACKED_KEY;
|
||||||
|
|
||||||
|
*key_ptr = (struct vb2_packed_key2 *)buf;
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vb2_public_key_pack(struct vb2_packed_key2 **key_ptr,
|
||||||
|
const struct vb2_public_key *pubk)
|
||||||
|
{
|
||||||
|
struct vb2_packed_key2 key = {
|
||||||
|
.c.magic = VB2_MAGIC_PACKED_KEY2,
|
||||||
|
.c.struct_version_major = VB2_PACKED_KEY2_VERSION_MAJOR,
|
||||||
|
.c.struct_version_minor = VB2_PACKED_KEY2_VERSION_MINOR,
|
||||||
|
};
|
||||||
|
uint8_t *buf;
|
||||||
|
uint32_t *buf32;
|
||||||
|
|
||||||
|
*key_ptr = NULL;
|
||||||
|
|
||||||
|
/* Calculate sizes and offsets */
|
||||||
|
key.c.fixed_size = sizeof(key);
|
||||||
|
|
||||||
|
if (pubk->desc)
|
||||||
|
key.c.desc_size = roundup32(strlen(pubk->desc) + 1);
|
||||||
|
|
||||||
|
key.key_offset = key.c.fixed_size + key.c.desc_size;
|
||||||
|
|
||||||
|
key.key_size = vb2_packed_key_size(pubk->sig_alg);
|
||||||
|
if (!key.key_size)
|
||||||
|
return VB2_ERROR_PUBLIC_KEY_PACK_SIZE;
|
||||||
|
|
||||||
|
key.c.total_size = key.key_offset + key.key_size;
|
||||||
|
|
||||||
|
/* Copy/initialize fields */
|
||||||
|
key.key_version = pubk->version;
|
||||||
|
key.sig_alg = pubk->sig_alg;
|
||||||
|
key.hash_alg = pubk->hash_alg;
|
||||||
|
key.guid = *pubk->guid;
|
||||||
|
|
||||||
|
/* Allocate the new buffer */
|
||||||
|
buf = malloc(key.c.total_size);
|
||||||
|
memset(buf, 0, key.c.total_size);
|
||||||
|
|
||||||
|
/* Copy data into the buffer */
|
||||||
|
memcpy(buf, &key, sizeof(key));
|
||||||
|
|
||||||
|
/* strcpy() is safe because we allocated above based on strlen() */
|
||||||
|
if (pubk->desc) {
|
||||||
|
strcpy((char *)(buf + key.c.fixed_size), pubk->desc);
|
||||||
|
buf[key.c.fixed_size + key.c.desc_size - 1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Re-pack the key arrays */
|
||||||
|
buf32 = (uint32_t *)(buf + key.key_offset);
|
||||||
|
buf32[0] = pubk->arrsize;
|
||||||
|
buf32[1] = pubk->n0inv;
|
||||||
|
memcpy(buf32 + 2, pubk->n, pubk->arrsize * sizeof(uint32_t));
|
||||||
|
memcpy(buf32 + 2 + pubk->arrsize, pubk->rr,
|
||||||
|
pubk->arrsize * sizeof(uint32_t));
|
||||||
|
|
||||||
|
*key_ptr = (struct vb2_packed_key2 *)buf;
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
144
host/lib/include/host_key2.h
Normal file
144
host/lib/include/host_key2.h
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
/* 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-side functions for verified boot key structures
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VBOOT_REFERENCE_HOST_KEY2_H_
|
||||||
|
#define VBOOT_REFERENCE_HOST_KEY2_H_
|
||||||
|
|
||||||
|
#include "2struct.h"
|
||||||
|
|
||||||
|
/* Private key data, in-memory format for use in signing calls. */
|
||||||
|
struct vb2_private_key {
|
||||||
|
struct rsa_st *rsa_private_key; /* Private key data */
|
||||||
|
enum vb2_hash_algorithm hash_alg; /* Hash algorithm */
|
||||||
|
enum vb2_signature_algorithm sig_alg; /* Signature algorithm */
|
||||||
|
char *desc; /* Description */
|
||||||
|
struct vb2_guid guid; /* Key GUID */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free a private key.
|
||||||
|
*
|
||||||
|
* @param key Key containing internal data to free.
|
||||||
|
*/
|
||||||
|
void vb2_private_key_free(struct vb2_private_key *key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unpack a private key from vb2_packed_private_key2 format.
|
||||||
|
*
|
||||||
|
* @param key_ptr Destination for newly allocated key; this must be
|
||||||
|
* freed with vb2_private_key_free().
|
||||||
|
* @param buf Source buffer containing packed key
|
||||||
|
* @param size Size of buffer in bytes
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2_private_key_unpack(struct vb2_private_key **key_ptr,
|
||||||
|
const uint8_t *buf,
|
||||||
|
uint32_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a private key from vb2_packed_private_key2 format.
|
||||||
|
*
|
||||||
|
* @param key_ptr Destination for newly allocated key; this must be
|
||||||
|
* freed with vb2_private_key_free().
|
||||||
|
* @param filename File to read key data from.
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2_private_key_read(struct vb2_private_key **key_ptr,
|
||||||
|
const char *filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a private key from a .pem file.
|
||||||
|
*
|
||||||
|
* This only reads the internal data for the key. It does not set any of the
|
||||||
|
* other fields in *key_ptr, since those are not contained in the .pem file.
|
||||||
|
*
|
||||||
|
* @param key_ptr Destination for newly allocated key; this must be
|
||||||
|
* freed with vb2_private_key_free().
|
||||||
|
* @param filename File to read key data from.
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2_private_key_read_pem(struct vb2_private_key **key_ptr,
|
||||||
|
const char *filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the description of a private key.
|
||||||
|
*
|
||||||
|
* @param key Key to set description for
|
||||||
|
* @param desc Description string, or NULL if no description.
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2_private_key_set_desc(struct vb2_private_key *key, const char *desc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a private key to vb2_packed_private_key2 format.
|
||||||
|
*
|
||||||
|
* @param key Key to write
|
||||||
|
* @param filename File to write key data to.
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2_private_key_write(const struct vb2_private_key *key,
|
||||||
|
const char *filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free a public key allocated by one of the functions below.
|
||||||
|
*
|
||||||
|
* Note that this should ONLY be called for public keys allocated via one
|
||||||
|
* of those functions; public keys created or filled in other ways (such as
|
||||||
|
* vb2_unpack_key2()) do not allocate memory for sub-fields in the same way.
|
||||||
|
*
|
||||||
|
* @param key Key to free
|
||||||
|
*/
|
||||||
|
void vb2_public_key_free(struct vb2_public_key *key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a public key from a .keyb file.
|
||||||
|
*
|
||||||
|
* Guesses the signature algorithm based on the size of the .keyb file. Does
|
||||||
|
* not set the hash_alg, guid, or desc fields, since those are not contained in
|
||||||
|
* the .keyb file.
|
||||||
|
*
|
||||||
|
* @param key_ptr Destination for newly allocated key; this must be
|
||||||
|
* freed with vb2_public_key_free().
|
||||||
|
* @param filename File to read key from.
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int vb2_public_key_read_keyb(struct vb2_public_key **key_ptr,
|
||||||
|
const char *filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the description of a public key.
|
||||||
|
*
|
||||||
|
* @param key Key to set description for
|
||||||
|
* @param desc Description string, or NULL if no description.
|
||||||
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
||||||
|
*/
|
||||||
|
int vb2_public_key_set_desc(struct vb2_public_key *key, const char *desc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a public key in vb2_packed_key2 format.
|
||||||
|
*
|
||||||
|
* @param key_ptr On success, points to the newly allocated key buffer.
|
||||||
|
* Caller is responsible for calling free() on this.
|
||||||
|
* @return VB2_SUCCESS, or non-zero if error.
|
||||||
|
*/
|
||||||
|
int vb2_packed_key2_read(struct vb2_packed_key2 **key_ptr,
|
||||||
|
const char *filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pack a public key into vb2_packed_key2 format.
|
||||||
|
*
|
||||||
|
* @param pubk Public key to pack
|
||||||
|
* @param key_ptr On success, points to a newly allocated packed key
|
||||||
|
* buffer. Caller is responsible for calling free() on
|
||||||
|
* this.
|
||||||
|
* @return VB2_SUCCESS, or non-zero if error.
|
||||||
|
*/
|
||||||
|
int vb2_public_key_pack(struct vb2_packed_key2 **key_ptr,
|
||||||
|
const struct vb2_public_key *pubk);
|
||||||
|
|
||||||
|
#endif /* VBOOT_REFERENCE_HOST_KEY2_H_ */
|
||||||
257
tests/vb2_host_key_tests.c
Normal file
257
tests/vb2_host_key_tests.c
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
/* 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 library vboot2 key functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
#include "2common.h"
|
||||||
|
#include "2rsa.h"
|
||||||
|
#include "host_common.h"
|
||||||
|
#include "host_key2.h"
|
||||||
|
|
||||||
|
#include "test_common.h"
|
||||||
|
|
||||||
|
/* Test only the algorithms we use */
|
||||||
|
struct alg_combo {
|
||||||
|
const char *name;
|
||||||
|
enum vb2_signature_algorithm sig_alg;
|
||||||
|
enum vb2_hash_algorithm hash_alg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct alg_combo test_algs[] = {
|
||||||
|
{"RSA2048/SHA-256", VB2_SIG_RSA2048, VB2_HASH_SHA256},
|
||||||
|
{"RSA4096/SHA-256", VB2_SIG_RSA4096, VB2_HASH_SHA256},
|
||||||
|
{"RSA8192/SHA-512", VB2_SIG_RSA8192, VB2_HASH_SHA512},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void private_key_tests(const struct alg_combo *combo,
|
||||||
|
const char *pemfile)
|
||||||
|
{
|
||||||
|
struct vb2_private_key *key, *k2;
|
||||||
|
struct vb2_packed_private_key2 *pkey;
|
||||||
|
const char *testfile = "test.vbprik2";
|
||||||
|
const char *notapem = "not_a_pem";
|
||||||
|
const char *testdesc = "test desc";
|
||||||
|
const struct vb2_guid test_guid = {.raw = {0xaa}};
|
||||||
|
uint8_t *buf, *buf2;
|
||||||
|
uint32_t bufsize;
|
||||||
|
|
||||||
|
TEST_SUCC(vb2_private_key_read_pem(&key, pemfile), "Read pem - good");
|
||||||
|
TEST_PTR_NEQ(key, NULL, " key_ptr");
|
||||||
|
TEST_PTR_NEQ(key->rsa_private_key, NULL, " rsa_private_key");
|
||||||
|
TEST_PTR_EQ(key->desc, NULL, " desc");
|
||||||
|
vb2_private_key_free(key);
|
||||||
|
|
||||||
|
TEST_EQ(vb2_private_key_read_pem(&key, "no_such_key"),
|
||||||
|
VB2_ERROR_READ_PEM_FILE_OPEN, "Read pem - no key");
|
||||||
|
TEST_PTR_EQ(key, NULL, " key_ptr");
|
||||||
|
|
||||||
|
vb2_write_file(testfile, (const uint8_t *)notapem, sizeof(notapem));
|
||||||
|
TEST_EQ(vb2_private_key_read_pem(&key, testfile),
|
||||||
|
VB2_ERROR_READ_PEM_RSA, "Read pem - not a pem");
|
||||||
|
unlink(testfile);
|
||||||
|
|
||||||
|
TEST_SUCC(vb2_private_key_read_pem(&key, pemfile), "Read pem - good2");
|
||||||
|
TEST_SUCC(vb2_private_key_set_desc(key, testdesc), "Set desc");
|
||||||
|
TEST_PTR_NEQ(key->desc, NULL, " desc");
|
||||||
|
TEST_PTR_NEQ(key->desc, testdesc, " made a copy");
|
||||||
|
TEST_EQ(strcmp(key->desc, testdesc), 0, " right contents");
|
||||||
|
TEST_SUCC(vb2_private_key_set_desc(key, NULL), "Clear desc");
|
||||||
|
TEST_PTR_EQ(key->desc, NULL, " desc");
|
||||||
|
TEST_SUCC(vb2_private_key_set_desc(key, testdesc), "Set desc");
|
||||||
|
vb2_private_key_free(key);
|
||||||
|
|
||||||
|
TEST_SUCC(vb2_private_key_read_pem(&key, pemfile), "Read pem - good3");
|
||||||
|
TEST_SUCC(vb2_private_key_set_desc(key, testdesc), "Set desc");
|
||||||
|
key->hash_alg = combo->hash_alg;
|
||||||
|
key->sig_alg = combo->sig_alg;
|
||||||
|
key->guid = test_guid;
|
||||||
|
|
||||||
|
unlink(testfile);
|
||||||
|
|
||||||
|
TEST_EQ(vb2_private_key_read(&k2, testfile),
|
||||||
|
VB2_ERROR_READ_FILE_OPEN, "Read key no file");
|
||||||
|
TEST_EQ(vb2_private_key_write(key, "no/such/dir"),
|
||||||
|
VB2_ERROR_PRIVATE_KEY_WRITE_FILE, "Write key to bad path");
|
||||||
|
|
||||||
|
TEST_SUCC(vb2_private_key_write(key, testfile), "Write key good");
|
||||||
|
TEST_SUCC(vb2_private_key_read(&k2, testfile), "Read key good");
|
||||||
|
TEST_PTR_NEQ(k2, NULL, " key_ptr");
|
||||||
|
TEST_EQ(k2->sig_alg, key->sig_alg, " sig alg");
|
||||||
|
TEST_EQ(k2->hash_alg, key->hash_alg, " hash alg");
|
||||||
|
TEST_EQ(memcmp(&k2->guid, &key->guid, sizeof(k2->guid)), 0, " guid");
|
||||||
|
TEST_EQ(strcmp(k2->desc, testdesc), 0, " desc");
|
||||||
|
vb2_private_key_free(k2);
|
||||||
|
|
||||||
|
TEST_SUCC(vb2_read_file(testfile, &buf, &bufsize), "Read key raw");
|
||||||
|
pkey = (struct vb2_packed_private_key2 *)buf;
|
||||||
|
|
||||||
|
/* Make a backup of the good buffer so we can mangle it */
|
||||||
|
buf2 = malloc(bufsize);
|
||||||
|
memcpy(buf2, buf, bufsize);
|
||||||
|
|
||||||
|
TEST_SUCC(vb2_private_key_unpack(&k2, buf, bufsize),
|
||||||
|
"Unpack private key good");
|
||||||
|
vb2_private_key_free(k2);
|
||||||
|
|
||||||
|
memcpy(buf, buf2, bufsize);
|
||||||
|
pkey->c.magic = VB2_MAGIC_PACKED_KEY2;
|
||||||
|
TEST_EQ(vb2_private_key_unpack(&k2, buf, bufsize),
|
||||||
|
VB2_ERROR_UNPACK_PRIVATE_KEY_MAGIC,
|
||||||
|
"Unpack private key bad magic");
|
||||||
|
TEST_PTR_EQ(k2, NULL, " key_ptr");
|
||||||
|
|
||||||
|
memcpy(buf, buf2, bufsize);
|
||||||
|
pkey->c.desc_size++;
|
||||||
|
TEST_EQ(vb2_private_key_unpack(&k2, buf, bufsize),
|
||||||
|
VB2_ERROR_UNPACK_PRIVATE_KEY_HEADER,
|
||||||
|
"Unpack private key bad header");
|
||||||
|
|
||||||
|
memcpy(buf, buf2, bufsize);
|
||||||
|
pkey->key_size += pkey->c.total_size;
|
||||||
|
TEST_EQ(vb2_private_key_unpack(&k2, buf, bufsize),
|
||||||
|
VB2_ERROR_UNPACK_PRIVATE_KEY_DATA,
|
||||||
|
"Unpack private key bad data size");
|
||||||
|
|
||||||
|
memcpy(buf, buf2, bufsize);
|
||||||
|
pkey->c.struct_version_major++;
|
||||||
|
TEST_EQ(vb2_private_key_unpack(&k2, buf, bufsize),
|
||||||
|
VB2_ERROR_UNPACK_PRIVATE_KEY_STRUCT_VERSION,
|
||||||
|
"Unpack private key bad struct version");
|
||||||
|
|
||||||
|
memcpy(buf, buf2, bufsize);
|
||||||
|
pkey->c.struct_version_minor++;
|
||||||
|
TEST_SUCC(vb2_private_key_unpack(&k2, buf, bufsize),
|
||||||
|
"Unpack private key minor version");
|
||||||
|
vb2_private_key_free(k2);
|
||||||
|
|
||||||
|
memcpy(buf, buf2, bufsize);
|
||||||
|
pkey->key_size -= 32;
|
||||||
|
TEST_EQ(vb2_private_key_unpack(&k2, buf, bufsize),
|
||||||
|
VB2_ERROR_UNPACK_PRIVATE_KEY_RSA,
|
||||||
|
"Unpack private key bad rsa data");
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
free(buf2);
|
||||||
|
unlink(testfile);
|
||||||
|
|
||||||
|
vb2_private_key_free(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void public_key_tests(const struct alg_combo *combo,
|
||||||
|
const char *keybfile)
|
||||||
|
{
|
||||||
|
struct vb2_public_key *key, k2;
|
||||||
|
struct vb2_packed_key2 *pkey;
|
||||||
|
const char *testfile = "test.vbpubk2";
|
||||||
|
const char *testdesc = "test desc";
|
||||||
|
const struct vb2_guid test_guid = {.raw = {0xbb}};
|
||||||
|
const uint32_t test_version = 0xcc01;
|
||||||
|
uint8_t *buf;
|
||||||
|
uint32_t bufsize;
|
||||||
|
|
||||||
|
TEST_EQ(vb2_public_key_read_keyb(&key, "no_such_key"),
|
||||||
|
VB2_ERROR_READ_KEYB_DATA, "Read keyb - no file");
|
||||||
|
TEST_PTR_EQ(key, NULL, " key_ptr");
|
||||||
|
|
||||||
|
TEST_SUCC(vb2_public_key_read_keyb(&key, keybfile), "Read keyb - good");
|
||||||
|
TEST_PTR_NEQ(key, NULL, " key_ptr");
|
||||||
|
TEST_EQ(key->sig_alg, combo->sig_alg, " sig_alg");
|
||||||
|
TEST_PTR_EQ(key->desc, NULL, " desc");
|
||||||
|
vb2_public_key_free(key);
|
||||||
|
|
||||||
|
bufsize = vb2_packed_key_size(combo->sig_alg);
|
||||||
|
buf = malloc(bufsize);
|
||||||
|
memset(buf, 0, bufsize);
|
||||||
|
|
||||||
|
vb2_write_file(testfile, buf, bufsize - 1);
|
||||||
|
TEST_EQ(vb2_public_key_read_keyb(&key, testfile),
|
||||||
|
VB2_ERROR_READ_KEYB_SIZE, "Read keyb - bad size");
|
||||||
|
unlink(testfile);
|
||||||
|
|
||||||
|
vb2_write_file(testfile, buf, bufsize);
|
||||||
|
free(buf);
|
||||||
|
TEST_EQ(vb2_public_key_read_keyb(&key, testfile),
|
||||||
|
VB2_ERROR_READ_KEYB_UNPACK, "Read keyb - unpack");
|
||||||
|
unlink(testfile);
|
||||||
|
|
||||||
|
TEST_SUCC(vb2_public_key_read_keyb(&key, keybfile), "Read keyb 2");
|
||||||
|
TEST_SUCC(vb2_public_key_set_desc(key, testdesc), "Set desc");
|
||||||
|
TEST_PTR_NEQ(key->desc, NULL, " desc");
|
||||||
|
TEST_PTR_NEQ(key->desc, testdesc, " made a copy");
|
||||||
|
TEST_EQ(strcmp(key->desc, testdesc), 0, " right contents");
|
||||||
|
TEST_SUCC(vb2_public_key_set_desc(key, NULL), "Clear desc");
|
||||||
|
TEST_PTR_EQ(key->desc, NULL, " desc");
|
||||||
|
TEST_SUCC(vb2_public_key_set_desc(key, testdesc), "Set desc");
|
||||||
|
vb2_public_key_free(key);
|
||||||
|
|
||||||
|
TEST_SUCC(vb2_public_key_read_keyb(&key, keybfile), "Read keyb 3");
|
||||||
|
TEST_SUCC(vb2_public_key_set_desc(key, testdesc), "Set desc");
|
||||||
|
key->hash_alg = combo->hash_alg;
|
||||||
|
key->guid = &test_guid;
|
||||||
|
key->version = test_version;
|
||||||
|
|
||||||
|
TEST_SUCC(vb2_public_key_pack(&pkey, key), "Pack public key");
|
||||||
|
TEST_PTR_NEQ(pkey, NULL, " key_ptr");
|
||||||
|
TEST_EQ(pkey->hash_alg, key->hash_alg, " hash_alg");
|
||||||
|
TEST_EQ(pkey->sig_alg, key->sig_alg, " sig_alg");
|
||||||
|
TEST_EQ(pkey->key_version, key->version, " version");
|
||||||
|
TEST_EQ(memcmp(&pkey->guid, key->guid, sizeof(pkey->guid)), 0,
|
||||||
|
" guid");
|
||||||
|
TEST_EQ(strcmp((char *)pkey + pkey->c.fixed_size, key->desc), 0,
|
||||||
|
" desc");
|
||||||
|
TEST_SUCC(vb2_unpack_key2(&k2, (uint8_t *)pkey, pkey->c.total_size),
|
||||||
|
"Unpack public key");
|
||||||
|
TEST_EQ(key->arrsize, k2.arrsize, " arrsize");
|
||||||
|
TEST_EQ(key->n0inv, k2.n0inv, " n0inv");
|
||||||
|
TEST_EQ(memcmp(key->n, k2.n, key->arrsize * sizeof(uint32_t)), 0,
|
||||||
|
" n");
|
||||||
|
TEST_EQ(memcmp(key->rr, k2.rr, key->arrsize * sizeof(uint32_t)), 0,
|
||||||
|
" rr");
|
||||||
|
free(pkey);
|
||||||
|
|
||||||
|
key->sig_alg = VB2_SIG_INVALID;
|
||||||
|
TEST_EQ(vb2_public_key_pack(&pkey, key),
|
||||||
|
VB2_ERROR_PUBLIC_KEY_PACK_SIZE,
|
||||||
|
"Pack invalid sig alg");
|
||||||
|
vb2_public_key_free(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_algorithm(const struct alg_combo *combo, const char *keys_dir)
|
||||||
|
{
|
||||||
|
int rsa_bits = vb2_rsa_sig_size(combo->sig_alg) * 8;
|
||||||
|
char pemfile[1024];
|
||||||
|
char keybfile[1024];
|
||||||
|
|
||||||
|
printf("***Testing algorithm: %s\n", combo->name);
|
||||||
|
|
||||||
|
sprintf(pemfile, "%s/key_rsa%d.pem", keys_dir, rsa_bits);
|
||||||
|
sprintf(keybfile, "%s/key_rsa%d.keyb", keys_dir, rsa_bits);
|
||||||
|
|
||||||
|
private_key_tests(combo, pemfile);
|
||||||
|
public_key_tests(combo, keybfile);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
if (argc == 2) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(test_algs); i++) {
|
||||||
|
if (test_algorithm(test_algs + i, argv[1]))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Usage: %s <keys_dir>", argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return gTestSuccess ? 0 : 255;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user