From d46461cec2aa7547b3722623b85dcfb2f298f859 Mon Sep 17 00:00:00 2001 From: Randall Spangler Date: Wed, 22 Jun 2016 16:46:23 -0700 Subject: futility: Use vboot 2.0 APIs for private keys This replaces calls to the vboot 1 host library with their vboot 2.0 equivalents. BUG=chromium:611535 BRANCH=none TEST=make runtests Change-Id: Id061554fd82ea3efe35d0fe1485693b47599a863 Signed-off-by: Randall Spangler Reviewed-on: https://chromium-review.googlesource.com/356540 Reviewed-by: Daisuke Nojiri --- firmware/2lib/include/2return_codes.h | 3 + futility/cmd_create.c | 27 ++++---- futility/cmd_sign.c | 32 +++------ futility/cmd_vbutil_firmware.c | 57 ++++++---------- futility/cmd_vbutil_kernel.c | 6 +- futility/cmd_vbutil_key.c | 36 +++++----- futility/file_type.inc | 4 +- futility/futility_options.h | 1 - futility/vb1_helper.c | 30 ++++---- futility/vb1_helper.h | 2 +- host/lib/host_common.c | 20 +++--- host/lib/host_key.c | 124 ---------------------------------- host/lib/host_key2.c | 67 ++++++++++++++++-- host/lib/host_signature.c | 56 --------------- host/lib/include/host_common.h | 2 +- host/lib/include/host_key.h | 62 +++++++++++------ host/lib/include/host_signature.h | 17 ++--- host/lib21/include/host_key2.h | 1 + host/linktest/main.c | 3 - tests/vb20_common3_tests.c | 32 +++------ tests/vboot_common2_tests.c | 25 ++++--- 21 files changed, 238 insertions(+), 369 deletions(-) diff --git a/firmware/2lib/include/2return_codes.h b/firmware/2lib/include/2return_codes.h index b6979922..e0bc6f22 100644 --- a/firmware/2lib/include/2return_codes.h +++ b/firmware/2lib/include/2return_codes.h @@ -673,6 +673,9 @@ enum vb2_return_code { /* Bad key size in vb2_copy_packed_key() */ VB2_ERROR_COPY_KEY_SIZE, + /* Unable to convert back to vb1 crypto algorithm */ + VB2_ERROR_VB1_CRYPTO_ALGORITHM, + /********************************************************************** * Errors generated by host library signature functions */ diff --git a/futility/cmd_create.c b/futility/cmd_create.c index a1341799..748ce2f7 100644 --- a/futility/cmd_create.c +++ b/futility/cmd_create.c @@ -80,51 +80,50 @@ static void print_help(int argc, char *argv[]) static int vb1_make_keypair() { - VbPrivateKey *privkey = 0; + struct vb2_private_key *privkey = NULL; VbPublicKey *pubkey = 0; - RSA *rsa_key = 0; + struct rsa_st *rsa_key = NULL; uint8_t *keyb_data = 0; uint32_t keyb_size; - enum vb2_signature_algorithm sig_alg; - uint64_t vb1_algorithm; - FILE *fp; int ret = 1; - fp = fopen(infile, "rb"); + FILE *fp = fopen(infile, "rb"); if (!fp) { fprintf(stderr, "Unable to open %s\n", infile); goto done; } + /* TODO: this is very similar to vb2_read_private_key_pem() */ + rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); fclose(fp); - if (!rsa_key) { fprintf(stderr, "Unable to read RSA key from %s\n", infile); goto done; } - sig_alg = vb2_rsa_sig_alg(rsa_key); + enum vb2_signature_algorithm sig_alg = vb2_rsa_sig_alg(rsa_key); if (sig_alg == VB2_SIG_INVALID) { fprintf(stderr, "Unsupported sig algorithm in RSA key\n"); goto done; } - /* combine the sig_alg with the hash_alg to get the vb1 algorithm */ - vb1_algorithm = (sig_alg - VB2_SIG_RSA1024) * 3 - + opt_hash_alg - VB2_HASH_SHA1; + /* Combine the sig_alg with the hash_alg to get the vb1 algorithm */ + uint64_t vb1_algorithm = + vb2_get_crypto_algorithm(opt_hash_alg, sig_alg); /* Create the private key */ - privkey = (VbPrivateKey *)malloc(sizeof(VbPrivateKey)); + privkey = (struct vb2_private_key *)calloc(sizeof(*privkey), 1); if (!privkey) goto done; privkey->rsa_private_key = rsa_key; - privkey->algorithm = vb1_algorithm; + privkey->sig_alg = sig_alg; + privkey->hash_alg = opt_hash_alg; /* Write it out */ strcpy(outext, ".vbprivk"); - if (0 != PrivateKeyWrite(outfile, privkey)) { + if (0 != vb2_write_private_key(outfile, privkey)) { fprintf(stderr, "unable to write private key\n"); goto done; } diff --git a/futility/cmd_sign.c b/futility/cmd_sign.c index 23e298b9..3ff6ddac 100644 --- a/futility/cmd_sign.c +++ b/futility/cmd_sign.c @@ -78,15 +78,6 @@ int ft_sign_pubkey(const char *name, uint8_t *buf, uint32_t len, void *data) sign_option.flags, sign_option.pem_external); } else { - sign_option.signprivate = PrivateKeyReadPem( - sign_option.pem_signpriv, - sign_option.pem_algo); - if (!sign_option.signprivate) { - fprintf(stderr, - "Unable to read PEM signing key: %s\n", - strerror(errno)); - return 1; - } sign_option.signprivate2 = vb2_read_private_key_pem( sign_option.pem_signpriv, sign_option.pem_algo); @@ -139,7 +130,7 @@ int ft_sign_raw_kernel(const char *name, uint8_t *buf, uint32_t len, sign_option.version, sign_option.kloadaddr, sign_option.keyblock, - sign_option.signprivate, + sign_option.signprivate2, sign_option.flags, &vblock_size); if (!vblock_data) { fprintf(stderr, "Unable to sign kernel blob\n"); @@ -226,7 +217,7 @@ int ft_sign_kern_preamble(const char *name, uint8_t *buf, uint32_t len, sign_option.version, sign_option.kloadaddr, keyblock, - sign_option.signprivate, + sign_option.signprivate2, sign_option.flags, &vblock_size); if (!vblock_data) { @@ -663,11 +654,6 @@ static int do_sign(int argc, char *argv[]) &longindex)) != -1) { switch (i) { case 's': - sign_option.signprivate = PrivateKeyRead(optarg); - if (!sign_option.signprivate) { - fprintf(stderr, "Error reading %s\n", optarg); - errorcnt++; - } sign_option.signprivate2 = vb2_read_private_key(optarg); if (!sign_option.signprivate2) { fprintf(stderr, "Error reading %s\n", optarg); @@ -922,13 +908,13 @@ static int do_sign(int argc, char *argv[]) switch (sign_option.type) { case FILE_TYPE_PUBKEY: sign_option.create_new_outfile = 1; - if (sign_option.signprivate && sign_option.pem_signpriv) { + if (sign_option.signprivate2 && sign_option.pem_signpriv) { fprintf(stderr, "Only one of --signprivate and --pem_signpriv" " can be specified\n"); errorcnt++; } - if ((sign_option.signprivate && + if ((sign_option.signprivate2 && sign_option.pem_algo_specified) || (sign_option.pem_signpriv && !sign_option.pem_algo_specified)) { @@ -946,18 +932,18 @@ static int do_sign(int argc, char *argv[]) break; case FILE_TYPE_BIOS_IMAGE: case FILE_TYPE_OLD_BIOS_IMAGE: - errorcnt += no_opt_if(!sign_option.signprivate, "signprivate"); + errorcnt += no_opt_if(!sign_option.signprivate2, "signprivate"); errorcnt += no_opt_if(!sign_option.keyblock, "keyblock"); errorcnt += no_opt_if(!sign_option.kernel_subkey, "kernelkey"); break; case FILE_TYPE_KERN_PREAMBLE: - errorcnt += no_opt_if(!sign_option.signprivate, "signprivate"); + errorcnt += no_opt_if(!sign_option.signprivate2, "signprivate"); if (sign_option.vblockonly || sign_option.inout_file_count > 1) sign_option.create_new_outfile = 1; break; case FILE_TYPE_RAW_FIRMWARE: sign_option.create_new_outfile = 1; - errorcnt += no_opt_if(!sign_option.signprivate, "signprivate"); + errorcnt += no_opt_if(!sign_option.signprivate2, "signprivate"); errorcnt += no_opt_if(!sign_option.keyblock, "keyblock"); errorcnt += no_opt_if(!sign_option.kernel_subkey, "kernelkey"); errorcnt += no_opt_if(!sign_option.version_specified, @@ -965,7 +951,7 @@ static int do_sign(int argc, char *argv[]) break; case FILE_TYPE_RAW_KERNEL: sign_option.create_new_outfile = 1; - errorcnt += no_opt_if(!sign_option.signprivate, "signprivate"); + errorcnt += no_opt_if(!sign_option.signprivate2, "signprivate"); errorcnt += no_opt_if(!sign_option.keyblock, "keyblock"); errorcnt += no_opt_if(!sign_option.version_specified, "version"); @@ -1058,8 +1044,6 @@ done: strerror(errno)); } - if (sign_option.signprivate) - free(sign_option.signprivate); if (sign_option.signprivate2) free(sign_option.signprivate2); if (sign_option.keyblock) diff --git a/futility/cmd_vbutil_firmware.c b/futility/cmd_vbutil_firmware.c index 253add55..4f44426b 100644 --- a/futility/cmd_vbutil_firmware.c +++ b/futility/cmd_vbutil_firmware.c @@ -84,19 +84,11 @@ static void print_help(int argc, char *argv[]) } /* Create a firmware .vblock */ -static int Vblock(const char *outfile, const char *keyblock_file, - const char *signprivate, uint64_t version, - const char *fv_file, const char *kernelkey_file, - uint32_t preamble_flags) +static int do_vblock(const char *outfile, const char *keyblock_file, + const char *signprivate, uint32_t version, + const char *fv_file, const char *kernelkey_file, + uint32_t preamble_flags) { - - VbPrivateKey *signing_key; - VbPublicKey *kernel_subkey; - uint8_t *fv_data; - uint64_t fv_size; - FILE *f; - uint64_t i; - if (!outfile) { VbExError("Must specify output filename\n"); return 1; @@ -117,34 +109,30 @@ static int Vblock(const char *outfile, const char *keyblock_file, return 1; } - signing_key = PrivateKeyRead(signprivate); + struct vb2_private_key *signing_key = vb2_read_private_key(signprivate); if (!signing_key) { VbExError("Error reading signing key.\n"); return 1; } - struct vb2_private_key *signing_key2 = - vb2_read_private_key(signprivate); - if (!signing_key2) { - VbExError("Error reading signing key.\n"); - return 1; - } - kernel_subkey = PublicKeyRead(kernelkey_file); + struct vb2_packed_key *kernel_subkey = + vb2_read_packed_key(kernelkey_file); if (!kernel_subkey) { VbExError("Error reading kernel subkey.\n"); return 1; } /* Read and sign the firmware volume */ - fv_data = ReadFile(fv_file, &fv_size); - if (!fv_data) + uint8_t *fv_data; + uint32_t fv_size; + if (VB2_SUCCESS != vb2_read_file(fv_file, &fv_data, &fv_size)) return 1; if (!fv_size) { VbExError("Empty firmware volume file\n"); return 1; } struct vb2_signature *body_sig = - vb2_calculate_signature(fv_data, fv_size, signing_key2); + vb2_calculate_signature(fv_data, fv_size, signing_key); if (!body_sig) { VbExError("Error calculating body signature\n"); return 1; @@ -153,22 +141,21 @@ static int Vblock(const char *outfile, const char *keyblock_file, /* Create preamble */ struct vb2_fw_preamble *preamble = - vb2_create_fw_preamble(version, - (struct vb2_packed_key *)kernel_subkey, - body_sig, signing_key2, preamble_flags); + vb2_create_fw_preamble(version, kernel_subkey, body_sig, + signing_key, preamble_flags); if (!preamble) { VbExError("Error creating preamble.\n"); return 1; } /* Write the output file */ - f = fopen(outfile, "wb"); + FILE *f = fopen(outfile, "wb"); if (!f) { VbExError("Can't open output file %s\n", outfile); return 1; } - i = ((1 != fwrite(keyblock, keyblock->keyblock_size, 1, f)) || - (1 != fwrite(preamble, preamble->preamble_size, 1, f))); + int i = ((1 != fwrite(keyblock, keyblock->keyblock_size, 1, f)) || + (1 != fwrite(preamble, preamble->preamble_size, 1, f))); fclose(f); if (i) { VbExError("Can't write output file %s\n", outfile); @@ -180,8 +167,8 @@ static int Vblock(const char *outfile, const char *keyblock_file, return 0; } -static int Verify(const char *infile, const char *signpubkey, - const char *fv_file, const char *kernelkey_file) +static int do_verify(const char *infile, const char *signpubkey, + const char *fv_file, const char *kernelkey_file) { uint8_t workbuf[VB2_WORKBUF_RECOMMENDED_SIZE]; struct vb2_workbuf wb; @@ -316,7 +303,7 @@ static int do_vbutil_firmware(int argc, char *argv[]) char *key_block_file = NULL; char *signpubkey = NULL; char *signprivate = NULL; - uint64_t version = 0; + uint32_t version = 0; char *fv_file = NULL; char *kernelkey_file = NULL; uint32_t preamble_flags = 0; @@ -387,10 +374,10 @@ static int do_vbutil_firmware(int argc, char *argv[]) switch (mode) { case OPT_MODE_VBLOCK: - return Vblock(filename, key_block_file, signprivate, version, - fv_file, kernelkey_file, preamble_flags); + return do_vblock(filename, key_block_file, signprivate, version, + fv_file, kernelkey_file, preamble_flags); case OPT_MODE_VERIFY: - return Verify(filename, signpubkey, fv_file, kernelkey_file); + return do_verify(filename, signpubkey, fv_file, kernelkey_file); default: fprintf(stderr, "Must specify a mode.\n"); print_help(argc, argv); diff --git a/futility/cmd_vbutil_kernel.c b/futility/cmd_vbutil_kernel.c index cf8b26e0..274ea75f 100644 --- a/futility/cmd_vbutil_kernel.c +++ b/futility/cmd_vbutil_kernel.c @@ -239,7 +239,7 @@ static int do_vbutil_kernel(int argc, char *argv[]) int rv; struct vb2_keyblock *keyblock = NULL; struct vb2_keyblock *t_keyblock = NULL; - VbPrivateKey *signpriv_key = NULL; + struct vb2_private_key *signpriv_key = NULL; VbPublicKey *signpub_key = NULL; uint8_t *kpart_data = NULL; uint64_t kpart_size = 0; @@ -403,7 +403,7 @@ static int do_vbutil_kernel(int argc, char *argv[]) if (!signprivkey_file) Fatal("Missing required signprivate file.\n"); - signpriv_key = PrivateKeyRead(signprivkey_file); + signpriv_key = vb2_read_private_key(signprivkey_file); if (!signpriv_key) Fatal("Error reading signing key.\n"); @@ -475,7 +475,7 @@ static int do_vbutil_kernel(int argc, char *argv[]) if (!signprivkey_file) Fatal("Missing required signprivate file.\n"); - signpriv_key = PrivateKeyRead(signprivkey_file); + signpriv_key = vb2_read_private_key(signprivkey_file); if (!signpriv_key) Fatal("Error reading signing key.\n"); diff --git a/futility/cmd_vbutil_key.c b/futility/cmd_vbutil_key.c index e4e919ef..7f61e0a5 100644 --- a/futility/cmd_vbutil_key.c +++ b/futility/cmd_vbutil_key.c @@ -12,9 +12,11 @@ #include #include + #include "cryptolib.h" #include "futility.h" #include "host_common.h" +#include "host_key2.h" #include "util_misc.h" #include "vb1_helper.h" #include "vb2_common.h" @@ -71,11 +73,10 @@ static void print_help(int argc, char *argv[]) } /* Pack a .keyb file into a .vbpubk, or a .pem into a .vbprivk */ -static int Pack(const char *infile, const char *outfile, uint64_t algorithm, - uint64_t version) +static int do_pack(const char *infile, const char *outfile, uint32_t algorithm, + uint32_t version) { VbPublicKey *pubkey; - VbPrivateKey *privkey; if (!infile || !outfile) { fprintf(stderr, "vbutil_key: Must specify --in and --out\n"); @@ -92,9 +93,10 @@ static int Pack(const char *infile, const char *outfile, uint64_t algorithm, return 0; } - privkey = PrivateKeyReadPem(infile, algorithm); + struct vb2_private_key *privkey = + vb2_read_private_key_pem(infile, algorithm); if (privkey) { - if (0 != PrivateKeyWrite(outfile, privkey)) { + if (VB2_SUCCESS != vb2_write_private_key(outfile, privkey)) { fprintf(stderr, "vbutil_key: Error writing key.\n"); return 1; } @@ -107,10 +109,9 @@ static int Pack(const char *infile, const char *outfile, uint64_t algorithm, } /* Unpack a .vbpubk or .vbprivk */ -static int Unpack(const char *infile, const char *outfile) +static int do_unpack(const char *infile, const char *outfile) { VbPublicKey *pubkey; - VbPrivateKey *privkey; if (!infile) { fprintf(stderr, "Need file to unpack\n"); @@ -137,14 +138,17 @@ static int Unpack(const char *infile, const char *outfile) return 0; } - privkey = PrivateKeyRead(infile); + struct vb2_private_key *privkey = vb2_read_private_key(infile); if (privkey) { printf("Private Key file: %s\n", infile); - printf("Algorithm: %" PRIu64 " %s\n", - privkey->algorithm, - vb1_crypto_name(privkey->algorithm)); + + enum vb2_crypto_algorithm alg = + vb2_get_crypto_algorithm(privkey->hash_alg, + privkey->sig_alg); + printf("Algorithm: %u %s\n", alg, vb1_crypto_name(alg)); if (outfile) { - if (0 != PrivateKeyWrite(outfile, privkey)) { + if (VB2_SUCCESS != + vb2_write_private_key(outfile, privkey)) { fprintf(stderr, "vbutil_key: Error writing key copy\n"); free(privkey); @@ -167,8 +171,8 @@ static int do_vbutil_key(int argc, char *argv[]) char *outfile = NULL; int mode = 0; int parse_error = 0; - uint64_t version = 1; - uint64_t algorithm = kNumAlgorithms; + uint32_t version = 1; + uint32_t algorithm = VB2_ALG_COUNT; char *e; int i; @@ -226,9 +230,9 @@ static int do_vbutil_key(int argc, char *argv[]) switch (mode) { case OPT_MODE_PACK: - return Pack(infile, outfile, algorithm, version); + return do_pack(infile, outfile, algorithm, version); case OPT_MODE_UNPACK: - return Unpack(infile, outfile); + return do_unpack(infile, outfile); default: printf("Must specify a mode.\n"); print_help(argc, argv); diff --git a/futility/file_type.inc b/futility/file_type.inc index 788f7e8c..9259f648 100644 --- a/futility/file_type.inc +++ b/futility/file_type.inc @@ -39,11 +39,11 @@ FILE_TYPE(KEYBLOCK, "keyblock", "keyblock (signed public key)", R_(ft_recognize_vblock1), S_(ft_show_keyblock), NONE) -FILE_TYPE(PUBKEY, "pubkey", "VbPublicKey (.vbpubk)", +FILE_TYPE(PUBKEY, "pubkey", "vb1 packed public key (.vbpubk)", R_(ft_recognize_vb1_key), S_(ft_show_pubkey), S_(ft_sign_pubkey)) -FILE_TYPE(PRIVKEY, "prikey", "VbPrivateKey (.vbprivk)", +FILE_TYPE(PRIVKEY, "prikey", "vb1 private key (.vbprivk)", R_(ft_recognize_vb1_key), S_(ft_show_privkey), NONE) diff --git a/futility/futility_options.h b/futility/futility_options.h index 476898ef..4739f04a 100644 --- a/futility/futility_options.h +++ b/futility/futility_options.h @@ -33,7 +33,6 @@ struct show_option_s { extern struct show_option_s show_option; struct sign_option_s { - VbPrivateKey *signprivate; struct vb2_private_key *signprivate2; struct vb2_keyblock *keyblock; VbPublicKey *kernel_subkey; diff --git a/futility/vb1_helper.c b/futility/vb1_helper.c index b0f4fe8c..2ec77501 100644 --- a/futility/vb1_helper.c +++ b/futility/vb1_helper.c @@ -408,7 +408,7 @@ uint8_t *SignKernelBlob(uint8_t *kernel_blob, uint64_t kernel_size, uint64_t padding, int version, uint64_t kernel_body_load_address, struct vb2_keyblock *keyblock, - VbPrivateKey *signpriv_key, + struct vb2_private_key *signpriv_key, uint32_t flags, uint64_t *vblock_size_ptr) { VbSignature *body_sig; @@ -419,7 +419,9 @@ uint8_t *SignKernelBlob(uint8_t *kernel_blob, uint64_t kernel_size, uint64_t outsize; /* Sign the kernel data */ - body_sig = CalculateSignature(kernel_blob, kernel_size, signpriv_key); + body_sig = (VbSignature *)vb2_calculate_signature(kernel_blob, + kernel_size, + signpriv_key); if (!body_sig) { fprintf(stderr, "Error calculating body signature\n"); return NULL; @@ -797,25 +799,19 @@ enum futil_file_type ft_recognize_vblock1(uint8_t *buf, uint32_t len) enum futil_file_type ft_recognize_vb1_key(uint8_t *buf, uint32_t len) { - struct vb2_packed_key *pubkey = (struct vb2_packed_key *)buf; - VbPrivateKey key; - const unsigned char *start; - - /* Maybe just a VbPublicKey? */ + /* Maybe just a packed public key? */ + const struct vb2_packed_key *pubkey = (struct vb2_packed_key *)buf; if (packed_key_looks_ok(pubkey, len)) return FILE_TYPE_PUBKEY; - /* How about a VbPrivateKey? */ - if (len < sizeof(key.algorithm)) + /* How about a private key? */ + if (len < sizeof(uint64_t)) return FILE_TYPE_UNKNOWN; - - key.algorithm = *(typeof(key.algorithm) *)buf; - start = buf + sizeof(key.algorithm); - key.rsa_private_key = d2i_RSAPrivateKey(NULL, &start, - len - sizeof(key.algorithm)); - - if (key.rsa_private_key) { - RSA_free(key.rsa_private_key); + const unsigned char *start = buf + sizeof(uint64_t); + struct rsa_st *rsa = + d2i_RSAPrivateKey(NULL, &start, len - sizeof(uint64_t)); + if (rsa) { + RSA_free(rsa); return FILE_TYPE_PRIVKEY; } diff --git a/futility/vb1_helper.h b/futility/vb1_helper.h index ec0f0004..1c59da53 100644 --- a/futility/vb1_helper.h +++ b/futility/vb1_helper.h @@ -35,7 +35,7 @@ uint8_t *SignKernelBlob(uint8_t *kernel_blob, uint64_t kernel_size, uint64_t padding, int version, uint64_t kernel_body_load_address, struct vb2_keyblock *keyblock, - VbPrivateKey *signpriv_key, + struct vb2_private_key *signpriv_key, uint32_t flags, uint64_t *vblock_size_ptr); int WriteSomeParts(const char *outfile, diff --git a/host/lib/host_common.c b/host/lib/host_common.c index a666e809..a8c1d977 100644 --- a/host/lib/host_common.c +++ b/host/lib/host_common.c @@ -9,7 +9,11 @@ #include +#include "2sysincludes.h" +#include "2common.h" +#include "2rsa.h" #include "host_common.h" +#include "host_key2.h" #include "cryptolib.h" #include "utility.h" #include "vboot_common.h" @@ -24,26 +28,25 @@ VbKernelPreambleHeader *CreateKernelPreamble( uint64_t vmlinuz_header_size, uint32_t flags, uint64_t desired_size, - const VbPrivateKey *signing_key) + const struct vb2_private_key *signing_key) { VbKernelPreambleHeader *h; uint64_t signed_size = (sizeof(VbKernelPreambleHeader) + body_signature->sig_size); - uint64_t block_size = signed_size + siglen_map[signing_key->algorithm]; + uint32_t sig_size = vb2_rsa_sig_size(signing_key->sig_alg); + uint64_t block_size = signed_size + sig_size; uint8_t *body_sig_dest; uint8_t *block_sig_dest; - VbSignature *sigtmp; /* If the block size is smaller than the desired size, pad it */ if (block_size < desired_size) block_size = desired_size; /* Allocate key block */ - h = (VbKernelPreambleHeader *)malloc(block_size); + h = (VbKernelPreambleHeader *)calloc(block_size, 1); if (!h) return NULL; - Memset(h, 0, block_size); body_sig_dest = (uint8_t *)(h + 1); block_sig_dest = body_sig_dest + body_signature->sig_size; @@ -65,11 +68,12 @@ VbKernelPreambleHeader *CreateKernelPreamble( /* Set up signature struct so we can calculate the signature */ SignatureInit(&h->preamble_signature, block_sig_dest, - siglen_map[signing_key->algorithm], signed_size); + sig_size, signed_size); /* Calculate signature */ - sigtmp = CalculateSignature((uint8_t *)h, signed_size, signing_key); - SignatureCopy(&h->preamble_signature, sigtmp); + struct vb2_signature *sigtmp = + vb2_calculate_signature((uint8_t *)h, signed_size, signing_key); + SignatureCopy(&h->preamble_signature, (VbSignature *)sigtmp); free(sigtmp); /* Return the header */ diff --git a/host/lib/host_key.c b/host/lib/host_key.c index e594b2cd..a8b05b53 100644 --- a/host/lib/host_key.c +++ b/host/lib/host_key.c @@ -20,130 +20,6 @@ #include "vb2_common.h" #include "vboot_common.h" - -VbPrivateKey* PrivateKeyReadPem(const char* filename, uint64_t algorithm) { - - VbPrivateKey* key; - RSA* rsa_key; - FILE* f; - - if (algorithm >= kNumAlgorithms) { - VBDEBUG(("%s() called with invalid algorithm!\n", __FUNCTION__)); - return NULL; - } - - /* Read private key */ - f = fopen(filename, "r"); - if (!f) { - VBDEBUG(("%s(): Couldn't open key file: %s\n", __FUNCTION__, filename)); - return NULL; - } - rsa_key = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL); - fclose(f); - if (!rsa_key) { - VBDEBUG(("%s(): Couldn't read private key from file: %s\n", __FUNCTION__, - filename)); - return NULL; - } - - /* Store key and algorithm in our struct */ - key = (VbPrivateKey*)malloc(sizeof(VbPrivateKey)); - if (!key) { - RSA_free(rsa_key); - return NULL; - } - key->rsa_private_key = rsa_key; - key->algorithm = algorithm; - - /* Return the key */ - return key; -} - - -void PrivateKeyFree(VbPrivateKey* key) { - if (!key) - return; - if (key->rsa_private_key) - RSA_free(key->rsa_private_key); - free(key); -} - - -/* Write a private key to a file in .vbprivk format. */ -int PrivateKeyWrite(const char* filename, const VbPrivateKey* key) { - uint8_t *outbuf = 0; - int buflen; - FILE *f; - - buflen = i2d_RSAPrivateKey(key->rsa_private_key, &outbuf); - if (buflen <= 0) { - VbExError("Unable to write private key buffer\n"); - return 1; - } - - f = fopen(filename, "wb"); - if (!f) { - VbExError("Unable to open file %s\n", filename); - free(outbuf); - return 1; - } - - if (1 != fwrite(&key->algorithm, sizeof(key->algorithm), 1, f)) { - VbExError("Unable to write to file %s\n", filename); - fclose(f); - free(outbuf); - unlink(filename); /* Delete any partial file */ - } - - if (1 != fwrite(outbuf, buflen, 1, f)) { - VbExError("Unable to write to file %s\n", filename); - fclose(f); - unlink(filename); /* Delete any partial file */ - free(outbuf); - } - - fclose(f); - free(outbuf); - return 0; -} - -VbPrivateKey* PrivateKeyRead(const char* filename) { - VbPrivateKey *key; - uint64_t filelen = 0; - uint8_t *buffer; - const unsigned char *start; - - buffer = ReadFile(filename, &filelen); - if (!buffer) { - VbExError("unable to read from file %s\n", filename); - return 0; - } - - key = (VbPrivateKey*)malloc(sizeof(VbPrivateKey)); - if (!key) { - VbExError("Unable to allocate VbPrivateKey\n"); - free(buffer); - return 0; - } - - key->algorithm = *(typeof(key->algorithm) *)buffer; - start = buffer + sizeof(key->algorithm); - - key->rsa_private_key = d2i_RSAPrivateKey(0, &start, - filelen - sizeof(key->algorithm)); - - if (!key->rsa_private_key) { - VbExError("Unable to parse RSA private key\n"); - free(buffer); - free(key); - return 0; - } - - free(buffer); - return key; -} - - /* Allocate a new public key with space for a [key_size] byte key. */ VbPublicKey* PublicKeyAlloc(uint64_t key_size, uint64_t algorithm, uint64_t version) { diff --git a/host/lib/host_key2.c b/host/lib/host_key2.c index a100455e..783ea5d9 100644 --- a/host/lib/host_key2.c +++ b/host/lib/host_key2.c @@ -25,6 +25,21 @@ #include "vb2_common.h" #include "vboot_common.h" +enum vb2_crypto_algorithm vb2_get_crypto_algorithm( + enum vb2_hash_algorithm hash_alg, + enum vb2_signature_algorithm sig_alg) +{ + /* Make sure algorithms are in the range supported by crypto alg */ + if (sig_alg < VB2_SIG_RSA1024 || sig_alg > VB2_SIG_RSA8192) + return VB2_ALG_COUNT; + if (hash_alg < VB2_HASH_SHA1 || hash_alg > VB2_HASH_SHA512) + return VB2_ALG_COUNT; + + return (sig_alg - VB2_SIG_RSA1024) + * (VB2_HASH_SHA512 - VB2_HASH_SHA1 + 1) + + (hash_alg - VB2_HASH_SHA1); +}; + struct vb2_private_key *vb2_read_private_key(const char *filename) { uint8_t *buf = NULL; @@ -65,9 +80,6 @@ struct vb2_private_key *vb2_read_private_key_pem( const char* filename, enum vb2_crypto_algorithm algorithm) { - RSA *rsa_key; - FILE *f; - if (algorithm >= VB2_ALG_COUNT) { VB2_DEBUG("%s() called with invalid algorithm!\n", __FUNCTION__); @@ -75,13 +87,13 @@ struct vb2_private_key *vb2_read_private_key_pem( } /* Read private key */ - f = fopen(filename, "r"); + FILE *f = fopen(filename, "r"); if (!f) { VB2_DEBUG("%s(): Couldn't open key file: %s\n", __FUNCTION__, filename); return NULL; } - rsa_key = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL); + struct rsa_st *rsa_key = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL); fclose(f); if (!rsa_key) { VB2_DEBUG("%s(): Couldn't read private key from file: %s\n", @@ -104,6 +116,51 @@ struct vb2_private_key *vb2_read_private_key_pem( return key; } +void vb2_free_private_key(struct vb2_private_key *key) +{ + if (!key) + return; + if (key->rsa_private_key) + RSA_free(key->rsa_private_key); + free(key); +} + +int vb2_write_private_key(const char *filename, + const struct vb2_private_key *key) +{ + /* Convert back to legacy vb1 algorithm enum */ + uint64_t alg = vb2_get_crypto_algorithm(key->hash_alg, key->sig_alg); + if (alg == VB2_ALG_COUNT) + return VB2_ERROR_VB1_CRYPTO_ALGORITHM; + + uint8_t *outbuf = NULL; + int buflen = i2d_RSAPrivateKey(key->rsa_private_key, &outbuf); + if (buflen <= 0) { + fprintf(stderr, "Unable to write private key buffer\n"); + return VB2_ERROR_PRIVATE_KEY_WRITE_RSA; + } + + FILE *f = fopen(filename, "wb"); + if (!f) { + fprintf(stderr, "Unable to open file %s\n", filename); + free(outbuf); + return VB2_ERROR_PRIVATE_KEY_WRITE_FILE; + } + + if (1 != fwrite(&alg, sizeof(alg), 1, f) || + 1 != fwrite(outbuf, buflen, 1, f)) { + fprintf(stderr, "Unable to write to file %s\n", filename); + fclose(f); + unlink(filename); /* Delete any partial file */ + free(outbuf); + return VB2_ERROR_PRIVATE_KEY_WRITE_FILE; + } + + fclose(f); + free(outbuf); + return VB2_SUCCESS; +} + void vb2_init_packed_key(struct vb2_packed_key *key, uint8_t *key_data, uint32_t key_size) { diff --git a/host/lib/host_signature.c b/host/lib/host_signature.c index 33000f1f..db810f36 100644 --- a/host/lib/host_signature.c +++ b/host/lib/host_signature.c @@ -54,59 +54,6 @@ int SignatureCopy(VbSignature* dest, const VbSignature* src) { return 0; } -VbSignature* CalculateSignature(const uint8_t* data, uint64_t size, - const VbPrivateKey* key) { - int vb2_alg = vb2_crypto_to_hash(key->algorithm); - uint8_t digest[VB2_MAX_DIGEST_SIZE]; - int digest_size = vb2_digest_size(vb2_alg); - - const uint8_t* digestinfo = hash_digestinfo_map[key->algorithm]; - int digestinfo_size = digestinfo_size_map[key->algorithm]; - - uint8_t* signature_digest; - int signature_digest_len = digest_size + digestinfo_size; - - VbSignature* sig; - int rv; - - /* Calculate the digest */ - if (VB2_SUCCESS != vb2_digest_buffer(data, size, vb2_alg, - digest, sizeof(digest))) - return NULL; - - /* Prepend the digest info to the digest */ - signature_digest = malloc(signature_digest_len); - if (!signature_digest) - return NULL; - - Memcpy(signature_digest, digestinfo, digestinfo_size); - Memcpy(signature_digest + digestinfo_size, digest, digest_size); - - /* Allocate output signature */ - sig = SignatureAlloc(siglen_map[key->algorithm], size); - if (!sig) { - free(signature_digest); - return NULL; - } - - /* Sign the signature_digest into our output buffer */ - rv = RSA_private_encrypt(signature_digest_len, /* Input length */ - signature_digest, /* Input data */ - GetSignatureData(sig), /* Output sig */ - key->rsa_private_key, /* Key to use */ - RSA_PKCS1_PADDING); /* Padding to use */ - free(signature_digest); - - if (-1 == rv) { - VBDEBUG(("SignatureBuf(): RSA_private_encrypt() failed.\n")); - free(sig); - return NULL; - } - - /* Return the signature */ - return sig; -} - /* Invoke [external_signer] command with [pem_file] as * an argument, contents of [inbuf] passed redirected to stdin, * and the stdout of the command is put back into [outbuf]. @@ -192,9 +139,6 @@ int InvokeExternalSigner(uint64_t size, return rv; } -/* TODO(gauravsh): This could easily be integrated into CalculateSignature() - * since the code is almost a mirror - I have kept it as such to avoid changing - * the existing interface. */ VbSignature* CalculateSignature_external(const uint8_t* data, uint64_t size, const char* key_file, uint64_t key_algorithm, diff --git a/host/lib/include/host_common.h b/host/lib/include/host_common.h index c9f9713f..50684864 100644 --- a/host/lib/include/host_common.h +++ b/host/lib/include/host_common.h @@ -58,6 +58,6 @@ VbKernelPreambleHeader *CreateKernelPreamble( uint64_t vmlinuz_header_size, uint32_t flags, uint64_t desired_size, - const VbPrivateKey *signing_key); + const struct vb2_private_key *signing_key); #endif /* VBOOT_REFERENCE_HOST_COMMON_H_ */ diff --git a/host/lib/include/host_key.h b/host/lib/include/host_key.h index d355e228..0d4641b2 100644 --- a/host/lib/include/host_key.h +++ b/host/lib/include/host_key.h @@ -15,33 +15,57 @@ struct vb2_packed_key; struct vb2_private_key; -typedef struct rsa_st RSA; - -/* Private key data */ -typedef struct VbPrivateKey { - RSA* rsa_private_key; /* Private key data */ - uint64_t algorithm; /* Algorithm to use when signing */ -} VbPrivateKey; - +/** + * Convert a vb2 hash and crypto algorithm to a vb1 crypto algorithm. + * + * @param hash_alg Hash algorithm + * @param sig_alg Signature algorithm + * + * @return The equivalent vb1 crypto algorithm or VB2_ALG_COUNT if error. + */ +enum vb2_crypto_algorithm vb2_get_crypto_algorithm( + enum vb2_hash_algorithm hash_alg, + enum vb2_signature_algorithm sig_alg); -/* Read a private key from a .pem file. Caller owns the returned pointer, - * and must free() it. */ -VbPrivateKey* PrivateKeyReadPem(const char* filename, uint64_t algorithm); +/** + * Read a private key from a .pem file. + * + * @param filename Filename to read from + * @param algorithm Algorithm to associate with file + * (enum vb2_crypto_algorithm) + * + * @return The private key or NULL if error. Caller must free() it. + */ struct vb2_private_key *vb2_read_private_key_pem( const char *filename, enum vb2_crypto_algorithm algorithm); -/* Free a private key. */ -void PrivateKeyFree(VbPrivateKey* key); +/** + * Free a private key. + * + * @param key Key to free; ok to pass NULL (ignored). + */ +void vb2_free_private_key(struct vb2_private_key *key); -/* Write a private key to a file in .vbprivk format. */ -int PrivateKeyWrite(const char* filename, const VbPrivateKey* key); +/** + * Write a private key to a file in .vbprivk format. + * + * @param filename Filename to write to + * @param key Key to write + * + * @return VB2_SUCCESS, or non-zero if error. + */ +int vb2_write_private_key(const char *filename, + const struct vb2_private_key *key); -/* Read a private key from a .vbprivk file. Caller owns the returned - * pointer, and must free() it. + +/** + * Read a private key from a .vbprivk file. * - * Returns NULL if error. */ -VbPrivateKey* PrivateKeyRead(const char* filename); + * @param filename Filename to read key from. + * + * @return The private key or NULL if error. Caller must free() it. + */ struct vb2_private_key *vb2_read_private_key(const char *filename); /* Allocate a new public key with space for a [key_size] byte key. */ diff --git a/host/lib/include/host_signature.h b/host/lib/include/host_signature.h index 2c7f24ae..df907d28 100644 --- a/host/lib/include/host_signature.h +++ b/host/lib/include/host_signature.h @@ -56,21 +56,22 @@ int vb2_copy_signature(struct vb2_signature *dest, /** * Calculate a SHA-512 digest-only signature. * - * Caller owns the returned pointer, and must free() it. - * * @param data Pointer to data to hash * @param size Length of data in bytes * - * @return The signature, or NULL if error. + * @return The signature, or NULL if error. Caller must free() it. */ struct vb2_signature *vb2_sha512_signature(const uint8_t *data, uint32_t size); -/* Calculates a signature for the data using the specified key. - * Caller owns the returned pointer, and must free it with Free(). +/** + * Calculate a signature for the data using the specified key. * - * Returns NULL on error. */ -VbSignature* CalculateSignature(const uint8_t* data, uint64_t size, - const VbPrivateKey* key); + * @param data Pointer to data to sign + * @param size Length of data in bytes + * @param key Private key to use to sign data + * + * @return The signature, or NULL if error. Caller must free() it. + */ struct vb2_signature *vb2_calculate_signature( const uint8_t *data, uint32_t size, const struct vb2_private_key *key); diff --git a/host/lib21/include/host_key2.h b/host/lib21/include/host_key2.h index e58b37d7..e109cb19 100644 --- a/host/lib21/include/host_key2.h +++ b/host/lib21/include/host_key2.h @@ -8,6 +8,7 @@ #ifndef VBOOT_REFERENCE_HOST_KEY2_H_ #define VBOOT_REFERENCE_HOST_KEY2_H_ +#include "2id.h" #include "2struct.h" struct vb2_public_key; diff --git a/host/linktest/main.c b/host/linktest/main.c index 5d56b892..b98e8755 100644 --- a/host/linktest/main.c +++ b/host/linktest/main.c @@ -16,8 +16,6 @@ int main(void) { /* host_key.h */ - PrivateKeyReadPem(0, 0); - PrivateKeyFree(0); PublicKeyAlloc(0, 0, 0); PublicKeyRead(0); PublicKeyReadKeyb(0, 0, 0); @@ -31,7 +29,6 @@ int main(void) SignatureInit(0, 0, 0, 0); SignatureAlloc(0, 0); SignatureCopy(0, 0); - CalculateSignature(0, 0, 0); /* host_common.h */ CreateKernelPreamble(0, 0, 0, 0, 0, 0, 0, 0, 0, 0); diff --git a/tests/vb20_common3_tests.c b/tests/vb20_common3_tests.c index e1199d84..32ee0079 100644 --- a/tests/vb20_common3_tests.c +++ b/tests/vb20_common3_tests.c @@ -330,17 +330,18 @@ static void test_verify_fw_preamble(const VbPublicKey *public_key, } static void resign_kernel_preamble(struct vb2_kernel_preamble *h, - const VbPrivateKey *key) + const struct vb2_private_key *key) { - VbSignature *sig = CalculateSignature( + struct vb2_signature *sig = vb2_calculate_signature( (const uint8_t *)h, h->preamble_signature.data_size, key); - SignatureCopy((VbSignature *)&h->preamble_signature, sig); + vb2_copy_signature(&h->preamble_signature, sig); free(sig); } -static void test_verify_kernel_preamble(const VbPublicKey *public_key, - const VbPrivateKey *private_key) +static void test_verify_kernel_preamble( + const VbPublicKey *public_key, + const struct vb2_private_key *private_key) { struct vb2_kernel_preamble *hdr; struct vb2_kernel_preamble *h; @@ -511,7 +512,6 @@ int test_permutation(int signing_key_algorithm, int data_key_algorithm, int signing_rsa_len = siglen_map[signing_key_algorithm] * 8; int data_rsa_len = siglen_map[data_key_algorithm] * 8; - VbPrivateKey *signing_private_key = NULL; VbPublicKey *signing_public_key = NULL; VbPublicKey *data_public_key = NULL; @@ -521,17 +521,9 @@ int test_permutation(int signing_key_algorithm, int data_key_algorithm, algo_strings[data_key_algorithm]); sprintf(filename, "%s/key_rsa%d.pem", keys_dir, signing_rsa_len); - signing_private_key = PrivateKeyReadPem(filename, - signing_key_algorithm); - if (!signing_private_key) { - fprintf(stderr, "Error reading signing_private_key: %s\n", - filename); - return 1; - } - - struct vb2_private_key *signing_private_key2 = + struct vb2_private_key *signing_private_key = vb2_read_private_key_pem(filename, signing_key_algorithm); - if (!signing_private_key2) { + if (!signing_private_key) { fprintf(stderr, "Error reading signing_private_key: %s\n", filename); return 1; @@ -567,11 +559,11 @@ int test_permutation(int signing_key_algorithm, int data_key_algorithm, return 1; } - test_check_keyblock(&signing_public_key2, signing_private_key2, + test_check_keyblock(&signing_public_key2, signing_private_key, (struct vb2_packed_key *)data_public_key); - test_verify_keyblock(&signing_public_key2, signing_private_key2, + test_verify_keyblock(&signing_public_key2, signing_private_key, (struct vb2_packed_key *)data_public_key); - test_verify_fw_preamble(signing_public_key, signing_private_key2, + test_verify_fw_preamble(signing_public_key, signing_private_key, (struct vb2_packed_key *)data_public_key); test_verify_kernel_preamble(signing_public_key, signing_private_key); @@ -579,8 +571,6 @@ int test_permutation(int signing_key_algorithm, int data_key_algorithm, free(signing_public_key); if (signing_private_key) free(signing_private_key); - if (signing_private_key2) - free(signing_private_key2); if (data_public_key) free(data_public_key); diff --git a/tests/vboot_common2_tests.c b/tests/vboot_common2_tests.c index 8f662d38..5185debb 100644 --- a/tests/vboot_common2_tests.c +++ b/tests/vboot_common2_tests.c @@ -44,14 +44,15 @@ static void VerifyPublicKeyToRSA(const VbPublicKey *orig_key) } static void VerifyDataTest(const VbPublicKey *public_key, - const VbPrivateKey *private_key) + const struct vb2_private_key *private_key) { const uint8_t test_data[] = "This is some test data to sign."; const uint64_t test_size = sizeof(test_data); VbSignature *sig; RSAPublicKey *rsa; - sig = CalculateSignature(test_data, test_size, private_key); + sig = (VbSignature *)vb2_calculate_signature(test_data, test_size, + private_key); TEST_PTR_NEQ(sig, 0, "VerifyData() calculate signature"); rsa = PublicKeyToRSA(public_key); @@ -80,14 +81,16 @@ static void VerifyDataTest(const VbPublicKey *public_key, } static void VerifyDigestTest(const VbPublicKey *public_key, - const VbPrivateKey *private_key) + const struct vb2_private_key *private_key) { const uint8_t test_data[] = "This is some other test data to sign."; VbSignature *sig; RSAPublicKey *rsa; uint8_t digest[VB2_MAX_DIGEST_SIZE]; - sig = CalculateSignature(test_data, sizeof(test_data), private_key); + sig = (VbSignature *)vb2_calculate_signature(test_data, + sizeof(test_data), + private_key); rsa = PublicKeyToRSA(public_key); TEST_SUCC(vb2_digest_buffer(test_data, sizeof(test_data), vb2_crypto_to_hash(public_key->algorithm), @@ -111,17 +114,17 @@ static void VerifyDigestTest(const VbPublicKey *public_key, } static void ReSignKernelPreamble(VbKernelPreambleHeader *h, - const VbPrivateKey *key) + const struct vb2_private_key *key) { - VbSignature *sig = CalculateSignature((const uint8_t *)h, - h->preamble_signature.data_size, key); + struct vb2_signature *sig = vb2_calculate_signature( + (const uint8_t *)h, h->preamble_signature.data_size, key); - SignatureCopy(&h->preamble_signature, sig); + SignatureCopy(&h->preamble_signature, (VbSignature *)sig); free(sig); } static void VerifyKernelPreambleTest(const VbPublicKey *public_key, - const VbPrivateKey *private_key) + const struct vb2_private_key *private_key) { VbKernelPreambleHeader *hdr; VbKernelPreambleHeader *h; @@ -219,13 +222,13 @@ int test_algorithm(int key_algorithm, const char *keys_dir) char filename[1024]; int rsa_len = siglen_map[key_algorithm] * 8; - VbPrivateKey *private_key = NULL; VbPublicKey *public_key = NULL; printf("***Testing algorithm: %s\n", algo_strings[key_algorithm]); sprintf(filename, "%s/key_rsa%d.pem", keys_dir, rsa_len); - private_key = PrivateKeyReadPem(filename, key_algorithm); + struct vb2_private_key *private_key = + vb2_read_private_key_pem(filename, key_algorithm); if (!private_key) { fprintf(stderr, "Error reading private_key: %s\n", filename); return 1; -- cgit v1.2.1