futility: cmd_show uses only vboot 2.0 APIs
authorRandall Spangler <rspangler@chromium.org>
Fri, 3 Jun 2016 21:00:27 +0000 (14:00 -0700)
committerchrome-bot <chrome-bot@chromium.org>
Thu, 4 Aug 2016 00:47:13 +0000 (17:47 -0700)
This removes the remaining vboot 1.0 API calls from cmd_show.

BUG=chromium:611535
BRANCH=none
TEST=make runtests

Change-Id: I03c4260aa034100efbbea1005367cd85dfff273d
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/350173
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
Makefile
firmware/lib20/include/vb2_common.h
firmware/lib20/include/vb2_struct.h
firmware/lib20/kernel.c
futility/cmd_show.c
futility/vb1_helper.c
futility/vb1_helper.h
host/lib/include/util_misc.h
host/lib/util_misc.c
host/lib21/include/host_key2.h
tests/vb20_common3_tests.c

index 79c4668..0455542 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -293,7 +293,7 @@ INCLUDES += \
 # If we're not building for a specific target, just stub out things like the
 # TPM commands and various external functions that are provided by the BIOS.
 ifeq (${FIRMWARE_ARCH},)
-INCLUDES += -Ihost/include -Ihost/lib/include
+INCLUDES += -Ihost/include -Ihost/lib/include -Ihost/lib21/include
 endif
 
 # Firmware library, used by the other firmware components (depthcharge,
@@ -1199,7 +1199,7 @@ ${TEST20_BINS}: ${FWLIB20}
 ${TEST20_BINS}: LIBS += ${FWLIB20}
 
 ${TEST21_BINS}: ${UTILLIB21}
-${TEST21_BINS}: INCLUDES += -Ihost/lib21/include -Ifirmware/lib21/include
+${TEST21_BINS}: INCLUDES += -Ifirmware/lib21/include
 ${TEST21_BINS}: LIBS += ${UTILLIB21}
 
 ${TESTBDB_BINS}: ${FWLIB2X} ${UTILBDB}
index 0ab89ca..536fbbb 100644 (file)
@@ -204,4 +204,26 @@ int vb2_verify_kernel_preamble(struct vb2_kernel_preamble *preamble,
                               const struct vb2_public_key *key,
                               const struct vb2_workbuf *wb);
 
+/**
+ * Retrieve the 16-bit vmlinuz header address and size from the preamble.
+ *
+ * Size 0 means there is no 16-bit vmlinuz header present.  Old preamble
+ * versions (<2.1) return 0 for both fields.
+ *
+ * @param preamble     Preamble to check
+ * @param vmlinuz_header_address       Destination for header address
+ * @param vmlinuz_header_size          Destination for header size
+ */
+void vb2_kernel_get_vmlinuz_header(const struct vb2_kernel_preamble *preamble,
+                                  uint64_t *vmlinuz_header_address,
+                                  uint32_t *vmlinuz_header_size);
+
+/**
+ * Get the flags for the kernel preamble.
+ *
+ * @param preamble     Preamble to check
+ * @return Flags for the preamble.  Old preamble versions (<2.2) return 0.
+ */
+uint32_t vb2_kernel_get_flags(const struct vb2_kernel_preamble *preamble);
+
 #endif  /* VBOOT_REFERENCE_VB2_COMMON_H_ */
index f644a5f..eeaf0ce 100644 (file)
@@ -268,6 +268,8 @@ struct vb2_kernel_preamble {
        uint32_t flags;
 } __attribute__((packed));
 
-#define EXPECTED_VB2_KERNEL_PREAMBLE_SIZE 116
+#define EXPECTED_VB2_KERNEL_PREAMBLE_2_0_SIZE 96
+#define EXPECTED_VB2_KERNEL_PREAMBLE_2_1_SIZE 112
+#define EXPECTED_VB2_KERNEL_PREAMBLE_2_2_SIZE 116
 
 #endif  /* VBOOT_REFERENCE_VB2_STRUCT_H_ */
index 609f246..4ded5d5 100644 (file)
@@ -249,11 +249,12 @@ int vb2_verify_kernel_preamble(struct vb2_kernel_preamble *preamble,
                               const struct vb2_workbuf *wb)
 {
        struct vb2_signature *sig = &preamble->preamble_signature;
+       uint32_t min_size = EXPECTED_VB2_KERNEL_PREAMBLE_2_0_SIZE;
 
        VB2_DEBUG("Verifying kernel preamble.\n");
 
-       /* Sanity checks before attempting signature of data */
-       if(size < sizeof(*preamble)) {
+       /* Make sure it's even safe to look at the struct */
+       if(size < min_size) {
                VB2_DEBUG("Not enough data for preamble header.\n");
                return VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER;
        }
@@ -262,9 +263,14 @@ int vb2_verify_kernel_preamble(struct vb2_kernel_preamble *preamble,
                VB2_DEBUG("Incompatible kernel preamble header version.\n");
                return VB2_ERROR_PREAMBLE_HEADER_VERSION;
        }
-       if (preamble->header_version_minor < 2) {
-               VB2_DEBUG("Old preamble header format not supported\n");
-               return VB2_ERROR_PREAMBLE_HEADER_OLD;
+
+       if (preamble->header_version_minor >= 2)
+               min_size = EXPECTED_VB2_KERNEL_PREAMBLE_2_2_SIZE;
+       else if (preamble->header_version_minor == 1)
+               min_size = EXPECTED_VB2_KERNEL_PREAMBLE_2_1_SIZE;
+       if(preamble->preamble_size < min_size) {
+               VB2_DEBUG("Preamble size too small for header.\n");
+               return VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER;
        }
        if (size < preamble->preamble_size) {
                VB2_DEBUG("Not enough data for preamble.\n");
@@ -325,7 +331,8 @@ int vb2_verify_kernel_preamble(struct vb2_kernel_preamble *preamble,
         * If vmlinuz header is present, verify it's covered by the body
         * signature.
         */
-       if (preamble->vmlinuz_header_size) {
+       if (preamble->header_version_minor >= 1 &&
+           preamble->vmlinuz_header_size) {
                const void *body_ptr =
                        (const void *)(uintptr_t)preamble->body_load_address;
                const void *vmlinuz_header_ptr = (const void *)
@@ -442,3 +449,30 @@ int vb2_load_kernel_preamble(struct vb2_context *ctx)
 
        return VB2_SUCCESS;
 }
+
+void vb2_kernel_get_vmlinuz_header(const struct vb2_kernel_preamble *preamble,
+                                  uint64_t *vmlinuz_header_address,
+                                  uint32_t *vmlinuz_header_size)
+{
+       if (preamble->header_version_minor < 1) {
+               *vmlinuz_header_address = 0;
+               *vmlinuz_header_size = 0;
+       } else {
+               /*
+                * Set header and size only if the preamble header version is >
+                * 2.1 as they don't exist in version 2.0 (Note that we don't
+                * need to check header_version_major; if that's not 2 then
+                * VerifyKernelPreamble() would have already failed.
+                */
+               *vmlinuz_header_address = preamble->vmlinuz_header_address;
+               *vmlinuz_header_size = preamble->vmlinuz_header_size;
+       }
+}
+
+uint32_t vb2_kernel_get_flags(const struct vb2_kernel_preamble *preamble)
+{
+       if (preamble->header_version_minor < 2)
+               return 0;
+
+       return preamble->flags;
+}
index b278180..d3cfc7f 100644 (file)
 #include "futility.h"
 #include "futility_options.h"
 #include "host_common.h"
+#include "host_key2.h"
 #include "util_misc.h"
 #include "vb1_helper.h"
 #include "vb2_common.h"
-#include "vboot_common.h"
-#include "host_key2.h"
 
 /* Options */
 struct show_option_s show_option = {
@@ -43,7 +42,7 @@ struct show_option_s show_option = {
 };
 
 /* Shared work buffer */
-static uint8_t workbuf[VB2_WORKBUF_RECOMMENDED_SIZE];
+static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE];
 static struct vb2_workbuf wb;
 
 void show_pubkey(const struct vb2_packed_key *pubkey, const char *sp)
@@ -102,30 +101,24 @@ int ft_show_pubkey(const char *name, uint8_t *buf, uint32_t len, void *data)
 
 int ft_show_privkey(const char *name, uint8_t *buf, uint32_t len, void *data)
 {
-       VbPrivateKey key;
-       const unsigned char *start;
+       struct vb2_packed_private_key *pkey =
+               (struct vb2_packed_private_key *)buf;
+       struct vb2_private_key key;
+       const unsigned char *start = pkey->key_data;
 
-       key.algorithm = *(typeof(key.algorithm) *)buf;
-       start = buf + sizeof(key.algorithm);
-       if (len <= sizeof(key.algorithm)) {
+       if (len <= sizeof(*pkey)) {
                printf("%s looks bogus\n", name);
                return 1;
        }
-       len -= sizeof(key.algorithm);
+       len -= sizeof(*pkey);
        key.rsa_private_key = d2i_RSAPrivateKey(NULL, &start, len);
 
        printf("Private Key file:      %s\n", name);
        printf("  Vboot API:           1.0\n");
-       printf("  Algorithm:           %" PRIu64 " %s\n", key.algorithm,
-              vb1_crypto_name(key.algorithm));
-       printf("  Key sha1sum:         ");
-       if (key.rsa_private_key) {
-               PrintPrivKeySha1Sum(&key);
-               RSA_free(key.rsa_private_key);
-       } else {
-               printf("<error>");
-       }
-       printf("\n");
+       printf("  Algorithm:           %u %s\n", pkey->algorithm,
+              vb1_crypto_name(pkey->algorithm));
+       printf("  Key sha1sum:         %s\n",
+              private_key_sha1_string(&key));
 
        return 0;
 }
@@ -294,13 +287,7 @@ int ft_show_kernel_preamble(const char *name, uint8_t *buf, uint32_t len,
 {
        struct vb2_keyblock *keyblock = (struct vb2_keyblock *)buf;
        struct vb2_public_key *sign_key = show_option.k;
-       uint8_t *kernel_blob = 0;
-       uint64_t kernel_size = 0;
-       int good_sig = 0;
        int retval = 0;
-       uint64_t vmlinuz_header_size = 0;
-       uint64_t vmlinuz_header_address = 0;
-       uint32_t flags = 0;
 
        /* Check the hash... */
        if (VB2_SUCCESS != vb2_verify_keyblock_hash(keyblock, len, &wb)) {
@@ -309,6 +296,7 @@ int ft_show_kernel_preamble(const char *name, uint8_t *buf, uint32_t len,
        }
 
        /* If we have a key, check the signature too */
+       int good_sig = 0;
        if (sign_key && VB2_SUCCESS ==
            vb2_verify_keyblock(keyblock, len, sign_key, &wb))
                good_sig = 1;
@@ -319,57 +307,56 @@ int ft_show_kernel_preamble(const char *name, uint8_t *buf, uint32_t len,
        if (show_option.strict && (!sign_key || !good_sig))
                retval = 1;
 
-       RSAPublicKey *rsa = PublicKeyToRSA((VbPublicKey *)&keyblock->data_key);
-       if (!rsa) {
+       struct vb2_public_key data_key;
+       if (VB2_SUCCESS !=
+           vb2_unpack_key(&data_key, (const uint8_t *)&keyblock->data_key,
+                          keyblock->data_key.key_offset +
+                          keyblock->data_key.key_size)) {
                fprintf(stderr, "Error parsing data key in %s\n", name);
                return 1;
        }
+
        uint32_t more = keyblock->keyblock_size;
-       VbKernelPreambleHeader *preamble =
-               (VbKernelPreambleHeader *)(buf + more);
+       struct vb2_kernel_preamble *pre2 =
+               (struct vb2_kernel_preamble *)(buf + more);
 
-       if (VBOOT_SUCCESS != VerifyKernelPreamble(preamble,
-                                                   len - more, rsa)) {
+       if (VB2_SUCCESS != vb2_verify_kernel_preamble(pre2, len - more,
+                                                     &data_key, &wb)) {
                printf("%s is invalid\n", name);
                return 1;
        }
 
        printf("Kernel Preamble:\n");
-       printf("  Size:                  0x%" PRIx64 "\n",
-              preamble->preamble_size);
-       printf("  Header version:        %" PRIu32 ".%" PRIu32 "\n",
-              preamble->header_version_major,
-              preamble->header_version_minor);
-       printf("  Kernel version:        %" PRIu64 "\n",
-              preamble->kernel_version);
+       printf("  Size:                  0x%x\n", pre2->preamble_size);
+       printf("  Header version:        %u.%u\n",
+              pre2->header_version_major,
+              pre2->header_version_minor);
+       printf("  Kernel version:        %u\n", pre2->kernel_version);
        printf("  Body load address:     0x%" PRIx64 "\n",
-              preamble->body_load_address);
-       printf("  Body size:             0x%" PRIx64 "\n",
-              preamble->body_signature.data_size);
+              pre2->body_load_address);
+       printf("  Body size:             0x%x\n",
+              pre2->body_signature.data_size);
        printf("  Bootloader address:    0x%" PRIx64 "\n",
-              preamble->bootloader_address);
-       printf("  Bootloader size:       0x%" PRIx64 "\n",
-              preamble->bootloader_size);
-
-       if (VbGetKernelVmlinuzHeader(preamble,
-                                    &vmlinuz_header_address,
-                                    &vmlinuz_header_size)
-           != VBOOT_SUCCESS) {
-               fprintf(stderr, "Unable to retrieve Vmlinuz Header!");
-               return 1;
-       }
+              pre2->bootloader_address);
+       printf("  Bootloader size:       0x%x\n", pre2->bootloader_size);
+
+       uint64_t vmlinuz_header_address = 0;
+       uint32_t vmlinuz_header_size = 0;
+       vb2_kernel_get_vmlinuz_header(pre2,
+                                     &vmlinuz_header_address,
+                                     &vmlinuz_header_size);
        if (vmlinuz_header_size) {
                printf("  Vmlinuz_header address:    0x%" PRIx64 "\n",
                       vmlinuz_header_address);
-               printf("  Vmlinuz header size:       0x%" PRIx64 "\n",
+               printf("  Vmlinuz header size:       0x%x\n",
                       vmlinuz_header_size);
        }
 
-       if (VbKernelHasFlags(preamble) == VBOOT_SUCCESS)
-               flags = preamble->flags;
-       printf("  Flags:                 0x%" PRIx32 "\n", flags);
+       printf("  Flags:                 0x%x\n", vb2_kernel_get_flags(pre2));
 
        /* Verify kernel body */
+       uint8_t *kernel_blob = 0;
+       uint64_t kernel_size = 0;
        if (show_option.fv) {
                /* It's in a separate file, which we've already read in */
                kernel_blob = show_option.fv;
@@ -386,15 +373,16 @@ int ft_show_kernel_preamble(const char *name, uint8_t *buf, uint32_t len,
                return 1;
        }
 
-       if (0 != VerifyData(kernel_blob, kernel_size,
-                           &preamble->body_signature, rsa)) {
+       if (VB2_SUCCESS !=
+           vb2_verify_data(kernel_blob, kernel_size, &pre2->body_signature,
+                           &data_key, &wb)) {
                fprintf(stderr, "Error verifying kernel body.\n");
                return 1;
        }
 
        printf("Body verification succeeded.\n");
 
-       printf("Config:\n%s\n", kernel_blob + KernelCmdLineOffset(preamble));
+       printf("Config:\n%s\n", kernel_blob + kernel_cmd_line_offset(pre2));
 
        return retval;
 }
index c4cdda2..13c5f5e 100644 (file)
@@ -130,7 +130,7 @@ static unsigned int find_cmdline_start(uint8_t *buf_ptr, unsigned int max_len)
 }
 
 /* Offset of kernel command line string from the start of the kernel blob */
-uint64_t KernelCmdLineOffset(VbKernelPreambleHeader *preamble)
+uint64_t kernel_cmd_line_offset(const struct vb2_kernel_preamble *preamble)
 {
        return preamble->bootloader_address - preamble->body_load_address -
            CROS_CONFIG_SIZE - CROS_PARAMS_SIZE;
@@ -628,7 +628,8 @@ int VerifyKernelBlob(uint8_t *kernel_blob,
        }
        printf("Body verification succeeded.\n");
 
-       printf("Config:\n%s\n", kernel_blob + KernelCmdLineOffset(g_preamble));
+       printf("Config:\n%s\n", kernel_blob + kernel_cmd_line_offset(
+                    (struct vb2_kernel_preamble *)g_preamble));
 
        rv = 0;
 done:
index fbe3618..8f3b500 100644 (file)
@@ -6,6 +6,7 @@
 #ifndef VBOOT_REFERENCE_FUTILITY_VB1_HELPER_H_
 #define VBOOT_REFERENCE_FUTILITY_VB1_HELPER_H_
 
+struct vb2_kernel_preamble;
 struct vb2_packed_key;
 
 /**
@@ -54,6 +55,6 @@ int VerifyKernelBlob(uint8_t *kernel_blob,
                     const char *keyblock_outfile,
                     uint64_t min_version);
 
-uint64_t KernelCmdLineOffset(VbKernelPreambleHeader *preamble);
+uint64_t kernel_cmd_line_offset(const struct vb2_kernel_preamble *preamble);
 
 #endif /* VBOOT_REFERENCE_FUTILITY_VB1_HELPER_H_ */
index 648f2da..b6372db 100644 (file)
@@ -12,6 +12,7 @@
 #include "vboot_struct.h"
 struct rsa_st;
 struct vb2_packed_key;
+struct vb2_private_key;
 
 /**
  * Returns the SHA1 digest of the packed key data as a string.
@@ -26,8 +27,18 @@ struct vb2_packed_key;
  */
 const char *packed_key_sha1_string(const struct vb2_packed_key *key);
 
-/* Prints the sha1sum of a VbPrivateKey to stdout. */
-void PrintPrivKeySha1Sum(VbPrivateKey *key);
+/**
+ * Returns the SHA1 digest of the private key data as a string.
+ *
+ * The returned string is a global static buffer, so each call to this
+ * overwrites the previous digest string.  So don't call this more than once
+ * per printf().
+ *
+ * @param key          Key to print digest for
+ *
+ * @return A string containing the SHA1 digest.
+ */
+const char *private_key_sha1_string(const struct vb2_private_key *key);
 
 /*
  * Our packed RSBPublicKey buffer (historically in files ending with ".keyb",
index 2b0f91c..56d21b3 100644 (file)
@@ -21,6 +21,7 @@
 #include "host_common.h"
 #include "util_misc.h"
 #include "vb2_common.h"
+#include "host_key2.h"
 #include "vboot_common.h"
 
 const char *packed_key_sha1_string(const struct vb2_packed_key *key)
@@ -29,10 +30,10 @@ const char *packed_key_sha1_string(const struct vb2_packed_key *key)
        uint32_t buflen = key->key_size;
        uint8_t digest[VB2_SHA1_DIGEST_SIZE];
        static char dest[VB2_SHA1_DIGEST_SIZE * 2 + 1];
-       char *dnext = dest;
 
        vb2_digest_buffer(buf, buflen, VB2_HASH_SHA1, digest, sizeof(digest));
 
+       char *dnext = dest;
        int i;
        for (i = 0; i < sizeof(digest); i++)
                dnext += sprintf(dnext, "%02x", digest[i]);
@@ -40,24 +41,27 @@ const char *packed_key_sha1_string(const struct vb2_packed_key *key)
        return dest;
 }
 
-void PrintPrivKeySha1Sum(VbPrivateKey *key)
+const char *private_key_sha1_string(const struct vb2_private_key *key)
 {
        uint8_t *buf;
        uint32_t buflen;
        uint8_t digest[VB2_SHA1_DIGEST_SIZE];
-       int i;
+       static char dest[VB2_SHA1_DIGEST_SIZE * 2 + 1];
 
-       if (vb_keyb_from_rsa(key->rsa_private_key, &buf, &buflen)) {
-               printf("<error>");
-               return;
+       if (!key->rsa_private_key ||
+           vb_keyb_from_rsa(key->rsa_private_key, &buf, &buflen)) {
+               return "<error>";
        }
 
        vb2_digest_buffer(buf, buflen, VB2_HASH_SHA1, digest, sizeof(digest));
 
+       char *dnext = dest;
+       int i;
        for (i = 0; i < sizeof(digest); i++)
-               printf("%02x", digest[i]);
+               dnext += sprintf(dnext, "%02x", digest[i]);
 
        free(buf);
+       return dest;
 }
 
 int vb_keyb_from_rsa(struct rsa_st *rsa_private_key,
index 7c95ac1..e58b37d 100644 (file)
@@ -22,6 +22,14 @@ struct vb2_private_key {
        struct vb2_id id;                       /* Key ID */
 };
 
+struct vb2_packed_private_key {
+       /* Signature algorithm used by the key (enum vb2_crypto_algorithm) */
+       uint32_t algorithm;
+       uint32_t reserved2;
+       /* Key data formatted for d2i_RSAPrivateKey() */
+       uint8_t key_data[0];
+};
+
 /* Convert between enums and human-readable form. Terminated with {0, 0}. */
 struct vb2_text_vs_enum {
        const char *name;
index 0e135bd..9520738 100644 (file)
@@ -425,13 +425,6 @@ static void test_verify_kernel_preamble(const VbPublicKey *public_key,
        TEST_SUCC(vb2_verify_kernel_preamble(h, hsize, &rsa, &wb),
                  "vb2_verify_kernel_preamble() minor++");
 
-       Memcpy(h, hdr, hsize);
-       h->header_version_minor--;
-       resign_kernel_preamble(h, private_key);
-       TEST_EQ(vb2_verify_kernel_preamble(h, hsize, &rsa, &wb),
-               VB2_ERROR_PREAMBLE_HEADER_OLD,
-               "vb2_verify_kernel_preamble() 2.1 not supported");
-
        /* Check signature */
        Memcpy(h, hdr, hsize);
        h->preamble_signature.sig_offset = hsize;