mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-09 17:11:42 +00:00
@@ -22,4 +22,10 @@
|
||||
uint8_t* ReadFile(const char* filename, uint64_t* size);
|
||||
|
||||
|
||||
/* Writes [size] bytes of [data] to [filename].
|
||||
*
|
||||
* Returns 0 if success, 1 if error. */
|
||||
int WriteFile(const char* filename, const void *data, uint64_t size);
|
||||
|
||||
|
||||
#endif /* VBOOT_REFERENCE_HOST_MISC_H_ */
|
||||
|
||||
@@ -187,37 +187,20 @@ VbPublicKey* PublicKeyRead(const char* filename) {
|
||||
|
||||
|
||||
int PublicKeyWrite(const char* filename, const VbPublicKey* key) {
|
||||
VbPublicKey* kcopy = NULL;
|
||||
FILE* f = NULL;
|
||||
int rv = 1;
|
||||
VbPublicKey* kcopy;
|
||||
int rv;
|
||||
|
||||
do {
|
||||
f = fopen(filename, "wb");
|
||||
if (!f) {
|
||||
debug("PublicKeyWrite() unable to open file %s\n", filename);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Copy the key, so its data is contiguous with the header */
|
||||
kcopy = PublicKeyAlloc(key->key_size, 0, 0);
|
||||
if (!kcopy || 0 != PublicKeyCopy(kcopy, key))
|
||||
break;
|
||||
|
||||
if (1 != fwrite(kcopy, kcopy->key_offset + kcopy->key_size, 1, f))
|
||||
break;
|
||||
|
||||
/* Success */
|
||||
rv = 0;
|
||||
|
||||
} while(0);
|
||||
|
||||
if (kcopy)
|
||||
/* Copy the key, so its data is contiguous with the header */
|
||||
kcopy = PublicKeyAlloc(key->key_size, 0, 0);
|
||||
if (!kcopy)
|
||||
return 1;
|
||||
if (0 != PublicKeyCopy(kcopy, key)) {
|
||||
Free(kcopy);
|
||||
if (f)
|
||||
fclose(f);
|
||||
|
||||
if (0 != rv)
|
||||
unlink(filename); /* Delete any partial file */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Write the copy, then free it */
|
||||
rv = WriteFile(filename, kcopy, kcopy->key_offset + kcopy->key_size);
|
||||
Free(kcopy);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "host_common.h"
|
||||
|
||||
@@ -47,3 +48,21 @@ uint8_t* ReadFile(const char* filename, uint64_t* size) {
|
||||
fclose(f);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
int WriteFile(const char* filename, const void *data, uint64_t size) {
|
||||
FILE *f = fopen(filename, "wb");
|
||||
if (!f) {
|
||||
debug("Unable to open file %s\n", filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (1 != fwrite(data, size, 1, f)) {
|
||||
debug("Unable to write to file %s\n", filename);
|
||||
fclose(f);
|
||||
unlink(filename); /* Delete any partial file */
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ int main(void)
|
||||
|
||||
/* host_misc.h */
|
||||
ReadFile(0, 0);
|
||||
WriteFile(0, 0, 0);
|
||||
|
||||
/* host_signature.h */
|
||||
SignatureInit(0, 0, 0, 0);
|
||||
|
||||
@@ -115,6 +115,7 @@ runtests:
|
||||
# Crypto tests
|
||||
./run_rsa_tests.sh
|
||||
./sha_tests
|
||||
./run_vbutil_tests.sh
|
||||
./run_vboot_common_tests.sh
|
||||
./run_image_verification_tests.sh
|
||||
# Splicing tests
|
||||
@@ -128,3 +129,5 @@ runtests:
|
||||
|
||||
clean:
|
||||
rm -f $(TEST_BINS)
|
||||
rm -f testkeys/*.vbpubk
|
||||
rm -f testkeys/*.keyblock
|
||||
|
||||
111
tests/run_vbutil_tests.sh
Executable file
111
tests/run_vbutil_tests.sh
Executable file
@@ -0,0 +1,111 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2010 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.
|
||||
|
||||
# Run verified boot firmware and kernel verification tests.
|
||||
|
||||
# Load common constants and variables.
|
||||
. "$(dirname "$0")/common.sh"
|
||||
|
||||
return_code=0
|
||||
|
||||
function test_vbutil_key {
|
||||
algorithmcounter=0
|
||||
for keylen in ${key_lengths[@]}
|
||||
do
|
||||
for hashalgo in ${hash_algos[@]}
|
||||
do
|
||||
echo -e "For signing key ${COL_YELLOW}RSA-$keylen/$hashalgo${COL_STOP}:"
|
||||
# Pack the key
|
||||
${UTIL_DIR}/vbutil_key --pack \
|
||||
--in ${TESTKEY_DIR}/key_rsa${keylen}.keyb \
|
||||
--out ${TESTKEY_DIR}/key_alg${algorithmcounter}.vbpubk \
|
||||
--version 1 \
|
||||
--algorithm $algorithmcounter
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
return_code=255
|
||||
fi
|
||||
|
||||
# Unpack the key
|
||||
# TODO: should verify we get the same key back out?
|
||||
${UTIL_DIR}/vbutil_key --unpack \
|
||||
--in ${TESTKEY_DIR}/key_alg${algorithmcounter}.vbpubk
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
return_code=255
|
||||
fi
|
||||
|
||||
let algorithmcounter=algorithmcounter+1
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
function test_vbutil_keyblock {
|
||||
# Test for various combinations of firmware signing algorithm and
|
||||
# kernel signing algorithm
|
||||
signing_algorithmcounter=0
|
||||
data_algorithmcounter=0
|
||||
for signing_keylen in ${key_lengths[@]}
|
||||
do
|
||||
for signing_hashalgo in ${hash_algos[@]}
|
||||
do
|
||||
let data_algorithmcounter=0
|
||||
for datakeylen in ${key_lengths[@]}
|
||||
do
|
||||
for datahashalgo in ${hash_algos[@]}
|
||||
do
|
||||
echo -e "For ${COL_YELLOW}signing algorithm \
|
||||
RSA-${signing_keylen}/${signing_hashalgo}${COL_STOP} \
|
||||
and ${COL_YELLOW}data key algorithm RSA-${datakeylen}/\
|
||||
${datahashalgo}${COL_STOP}"
|
||||
# Remove old file
|
||||
keyblockfile=${TESTKEY_DIR}/sign${signing_algorithmcounter}_data${data_algorithmcounter}.keyblock
|
||||
rm -f ${keyblockfile}
|
||||
|
||||
# Pack
|
||||
${UTIL_DIR}/vbutil_keyblock --pack ${keyblockfile} \
|
||||
--datapubkey \
|
||||
tests/testkeys/key_alg${data_algorithmcounter}.vbpubk \
|
||||
--signprivate ${TESTKEY_DIR}/key_rsa${signing_keylen}.pem \
|
||||
--algorithm $signing_algorithmcounter
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
return_code=255
|
||||
fi
|
||||
|
||||
# Unpack
|
||||
${UTIL_DIR}/vbutil_keyblock --unpack ${keyblockfile} \
|
||||
--signpubkey \
|
||||
tests/testkeys/key_alg${signing_algorithmcounter}.vbpubk
|
||||
# TODO: check data key against the packed one?
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
return_code=255
|
||||
fi
|
||||
|
||||
let data_algorithmcounter=data_algorithmcounter+1
|
||||
done
|
||||
done
|
||||
let signing_algorithmcounter=signing_algorithmcounter+1
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
check_test_keys
|
||||
|
||||
echo
|
||||
echo "Testing vbutil_key..."
|
||||
test_vbutil_key
|
||||
|
||||
echo
|
||||
echo "Testing vbutil_keyblock..."
|
||||
test_vbutil_keyblock
|
||||
|
||||
|
||||
exit $return_code
|
||||
|
||||
@@ -33,6 +33,7 @@ TARGET_BINS = dumpRSAPublicKey \
|
||||
load_kernel_test \
|
||||
signature_digest_utility \
|
||||
vbutil_key \
|
||||
vbutil_keyblock \
|
||||
verify_data
|
||||
|
||||
all: $(TARGET_BINS) subdirs
|
||||
@@ -61,15 +62,15 @@ kernel_utility: kernel_utility.cc $(LIBS)
|
||||
$(CXX) $(CFLAGS) $(INCLUDES) -ggdb -D__STDC_LIMIT_MACROS $< \
|
||||
-o $@ $(LIBS) -lcrypto
|
||||
|
||||
load_kernel_test: load_kernel_test.c $(LIBS)
|
||||
$(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) -lcrypto
|
||||
|
||||
signature_digest_utility: signature_digest_utility.c $(LIBS)
|
||||
$(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) -lcrypto
|
||||
|
||||
vbutil_key: vbutil_key.c $(LIBS)
|
||||
$(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) -lcrypto
|
||||
|
||||
vbutil_keyblock: vbutil_keyblock.c $(LIBS)
|
||||
$(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) -lcrypto
|
||||
|
||||
verify_data: verify_data.c $(LIBS)
|
||||
$(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) -lcrypto
|
||||
|
||||
|
||||
222
utility/vbutil_keyblock.c
Normal file
222
utility/vbutil_keyblock.c
Normal file
@@ -0,0 +1,222 @@
|
||||
#include <getopt.h>
|
||||
#include <inttypes.h> /* For PRIu64 */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "cryptolib.h"
|
||||
#include "host_common.h"
|
||||
#include "vboot_common.h"
|
||||
|
||||
|
||||
/* Command line options */
|
||||
enum {
|
||||
OPT_MODE_PACK = 1000,
|
||||
OPT_MODE_UNPACK,
|
||||
OPT_DATAPUBKEY,
|
||||
OPT_SIGNPUBKEY,
|
||||
OPT_SIGNPRIVATE,
|
||||
OPT_ALGORITHM,
|
||||
OPT_FLAGS,
|
||||
};
|
||||
|
||||
static struct option long_opts[] = {
|
||||
{"pack", 1, 0, OPT_MODE_PACK },
|
||||
{"unpack", 1, 0, OPT_MODE_UNPACK },
|
||||
{"datapubkey", 1, 0, OPT_DATAPUBKEY },
|
||||
{"signpubkey", 1, 0, OPT_SIGNPUBKEY },
|
||||
{"signprivate", 1, 0, OPT_SIGNPRIVATE },
|
||||
{"algorithm", 1, 0, OPT_ALGORITHM },
|
||||
{"flags", 1, 0, OPT_FLAGS },
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
||||
/* Print help and return error */
|
||||
static int PrintHelp(void) {
|
||||
int i;
|
||||
|
||||
puts("vbutil_keyblock - Verified boot key block utility\n"
|
||||
"\n"
|
||||
"Usage: vbutil_keyblock <--pack|--unpack> <file> [OPTIONS]\n"
|
||||
"\n"
|
||||
"For '--pack <file>', required OPTIONS are:\n"
|
||||
" --datapubkey <file> Data public key in .vbpubk format\n"
|
||||
" --signprivate <file> Signing private key in .pem format\n"
|
||||
" --algorithm <algoid> Signing algorithm for key, one of:");
|
||||
|
||||
for (i = 0; i < kNumAlgorithms; i++)
|
||||
printf(" %d (%s)\n", i, algo_strings[i]);
|
||||
|
||||
puts("\n"
|
||||
"Optional OPTIONS are:\n"
|
||||
" --flags <number> Flags\n"
|
||||
"\n"
|
||||
"For '--unpack <file>', required OPTIONS are:\n"
|
||||
" --signpubkey <file> Signing public key in .vbpubk format\n"
|
||||
"Optional OPTIONS are:\n"
|
||||
" --datapubkey <file> Data public key output file\n"
|
||||
"");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Pack a .keyblock */
|
||||
static int Pack(const char* outfile, const char* datapubkey,
|
||||
const char* signprivate, uint64_t algorithm,
|
||||
uint64_t flags) {
|
||||
VbPublicKey* data_key;
|
||||
VbPrivateKey* signing_key;
|
||||
VbKeyBlockHeader* block;
|
||||
|
||||
if (!outfile) {
|
||||
fprintf(stderr, "vbutil_keyblock: Must specify output filename\n");
|
||||
return 1;
|
||||
}
|
||||
if (!datapubkey || !signprivate) {
|
||||
fprintf(stderr, "vbutil_keyblock: Must specify all keys\n");
|
||||
return 1;
|
||||
}
|
||||
if (algorithm >= kNumAlgorithms) {
|
||||
fprintf(stderr, "Invalid algorithm\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
data_key = PublicKeyRead(datapubkey);
|
||||
if (!data_key) {
|
||||
fprintf(stderr, "vbutil_keyblock: Error reading data key.\n");
|
||||
return 1;
|
||||
}
|
||||
signing_key = PrivateKeyRead(signprivate, algorithm);
|
||||
if (!signing_key) {
|
||||
fprintf(stderr, "vbutil_keyblock: Error reading signing key.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
block = CreateKeyBlock(data_key, signing_key, flags);
|
||||
Free(data_key);
|
||||
Free(signing_key);
|
||||
|
||||
if (0 != WriteFile(outfile, block, block->key_block_size)) {
|
||||
fprintf(stderr, "vbutil_keyblock: Error writing key block.\n");
|
||||
return 1;
|
||||
}
|
||||
Free(block);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int Unpack(const char* infile, const char* datapubkey,
|
||||
const char* signpubkey) {
|
||||
VbPublicKey* data_key;
|
||||
VbPublicKey* sign_key;
|
||||
VbKeyBlockHeader* block;
|
||||
uint64_t block_size;
|
||||
|
||||
if (!infile || !signpubkey) {
|
||||
fprintf(stderr, "vbutil_keyblock: Must specify filename and signpubkey\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
sign_key = PublicKeyRead(signpubkey);
|
||||
if (!sign_key) {
|
||||
fprintf(stderr, "vbutil_keyblock: Error reading signpubkey.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
block = (VbKeyBlockHeader*)ReadFile(infile, &block_size);
|
||||
if (!block) {
|
||||
fprintf(stderr, "vbutil_keyblock: Error reading key block.\n");
|
||||
return 1;
|
||||
}
|
||||
if (0 != VerifyKeyBlock(block, block_size, sign_key)) {
|
||||
fprintf(stderr, "vbutil_keyblock: Error verifying key block.\n");
|
||||
return 1;
|
||||
}
|
||||
Free(sign_key);
|
||||
|
||||
printf("Key block file: %s\n", infile);
|
||||
printf("Flags: %" PRIu64 "\n", block->key_block_flags);
|
||||
|
||||
data_key = &block->data_key;
|
||||
printf("Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm,
|
||||
(data_key->algorithm < kNumAlgorithms ?
|
||||
algo_strings[data_key->algorithm] : "(invalid)"));
|
||||
printf("Data key version: %" PRIu64 "\n", data_key->key_version);
|
||||
|
||||
/* TODO: write key data, if output file specified */
|
||||
|
||||
Free(block);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
|
||||
char* filename = NULL;
|
||||
char* datapubkey = NULL;
|
||||
char* signpubkey = NULL;
|
||||
char* signprivate = NULL;
|
||||
uint64_t flags = 0;
|
||||
uint64_t algorithm = kNumAlgorithms;
|
||||
int mode = 0;
|
||||
int parse_error = 0;
|
||||
char* e;
|
||||
int i;
|
||||
|
||||
while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
|
||||
switch (i) {
|
||||
case '?':
|
||||
/* Unhandled option */
|
||||
printf("Unknown option\n");
|
||||
parse_error = 1;
|
||||
break;
|
||||
|
||||
case OPT_MODE_PACK:
|
||||
case OPT_MODE_UNPACK:
|
||||
mode = i;
|
||||
filename = optarg;
|
||||
break;
|
||||
|
||||
case OPT_DATAPUBKEY:
|
||||
datapubkey = optarg;
|
||||
break;
|
||||
|
||||
case OPT_SIGNPUBKEY:
|
||||
signpubkey = optarg;
|
||||
break;
|
||||
|
||||
case OPT_SIGNPRIVATE:
|
||||
signprivate = optarg;
|
||||
break;
|
||||
|
||||
case OPT_ALGORITHM:
|
||||
algorithm = strtoul(optarg, &e, 0);
|
||||
if (!*optarg || (e && *e)) {
|
||||
printf("Invalid --algorithm\n");
|
||||
parse_error = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPT_FLAGS:
|
||||
flags = strtoul(optarg, &e, 0);
|
||||
if (!*optarg || (e && *e)) {
|
||||
printf("Invalid --flags\n");
|
||||
parse_error = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (parse_error)
|
||||
return PrintHelp();
|
||||
|
||||
switch(mode) {
|
||||
case OPT_MODE_PACK:
|
||||
return Pack(filename, datapubkey, signprivate, algorithm, flags);
|
||||
case OPT_MODE_UNPACK:
|
||||
return Unpack(filename, datapubkey, signpubkey);
|
||||
default:
|
||||
printf("Must specify a mode.\n");
|
||||
return PrintHelp();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user