From patchwork Sat Jul 18 20:51:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brian Norris X-Patchwork-Id: 1331615 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.openwrt.org (client-ip=2001:8b0:10b:1231::1; helo=merlin.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=merlin.20170209 header.b=aDrGyGna; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=rgkGcZJP; dkim-atps=neutral Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4B8KxX70vCz9sR4 for ; Sun, 19 Jul 2020 06:54:56 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=tLIt3aZX3DAQ1aKapqTJPcT22kc4E4FJ/atC/RVA9nQ=; b=aDrGyGna2SVeG9HIU3Cpg5Dup n1ndVDGJ1zQCTVLnGoi1z8LVeFK6psEhvGjU/Z9PqhYSKoutzOvpHtKIUmxl5q5Nma3sC8iAsF2x6 YvV401vydIpyQaqz3iEjcJFRQ2p+IDMEbE86ujefnHIx8urUFHIfcDZZ4+QlYl/DCsC1Dh6bl31dG f+udTGXNM//d4synjNPo3hz6aR9hMY9SXstw+fSwsVeoNEgcRnSBdiMGrIoA3wyM4Q7PvZUUEk8tO cxgwWQcV3zZbbl+MrRPrBEgFfAa4Rm90OL/TrhBZhzYHhE1LxJGfiLMZ7HTIOfkwCMHE39VnZPERZ foG1SNS2Q==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jwtpT-0002w4-TE; Sat, 18 Jul 2020 20:53:07 +0000 Received: from mail-pl1-x644.google.com ([2607:f8b0:4864:20::644]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jwtpK-0002tW-Dh for openwrt-devel@lists.openwrt.org; Sat, 18 Jul 2020 20:53:02 +0000 Received: by mail-pl1-x644.google.com with SMTP id k4so6880588pld.12 for ; Sat, 18 Jul 2020 13:52:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=vXJgdnWI++JYs8hnSv3F7WyyLs54HiC0cVlGEt+Kmz8=; b=rgkGcZJPJe9S9wE9W0HeuzyvkABsCqvVTolho3gY/G2iu83+GKiUFyPwqWCBdfAOYX e21wpHLjOA31x52TrevtWRQLVTja7l+IT4jENFv2/fdqFY87cnPt1sF/f3g0o86GqoED KjtjPFrjPN6NtvKWBUnOENKb9y1kbNGNwcOqluJFw3A254/EMtu2OgCcFy++39ai4AQT XASvfxXVLEjmh+Y9X+iIs8Z0+vw7aIC5NkpHcQRYBMtYpTISBXmLMOrLwAvYEpk2M30I VTeYvhY4nkWy5p5uT0p+eR7Cywr2JqoRu1IsxPl7m1a50iEtul/FspRbH+gqlDh6aEll CSzA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=vXJgdnWI++JYs8hnSv3F7WyyLs54HiC0cVlGEt+Kmz8=; b=QOiQtxG8iPGRdMklS32f8s2mWmRBjeZ3h7GCDwaSpsHc4Ud2/IcdKXcLuQIoekdHIs p5Maqs6t/oa0c6i4nJe+svhl7exaTbWPwqHtwOUp6q0uNZbCkeeO65Lt1SHGM/eFXGuE 5yCXrk1WXtqjj+1+jafl0ZubBkn0dH5WApJH6YXkklIpw7lIAjHUZixC6mQzYwncDsry CMF/e2X3eyHMllmBCIfdnTMijZYI/+Rh7igdZM3BiHSV6U/YHBUDFicNS160sUpb3hIc i1dfWLLXBQ/ouBjb+CZGUjB9pou76wP/YrqM7Hf4PrhrvN30hDygBi6yhwwlehbh/+nA jlKw== X-Gm-Message-State: AOAM530C9iwgGdy0lELWAqOVR/0ig/rlnfpaRQZMb5xaUL9WXPr8Cb/Y xivPzwR9ocUBnNH+GTJRlOqJ0M/MEMU= X-Google-Smtp-Source: ABdhPJwsSSCCOq+Zl1dtCzYw2/OP+fwoLOHoguQRYz0S+dHmZ6evvWgq57/IzHRFxO9Jq8g8bucXDg== X-Received: by 2002:a17:90a:5208:: with SMTP id v8mr16647425pjh.29.1595105575600; Sat, 18 Jul 2020 13:52:55 -0700 (PDT) Received: from localhost ([2601:647:5800:8d47:9eef:d5ff:fefc:64ae]) by smtp.gmail.com with ESMTPSA id c132sm11376176pfb.112.2020.07.18.13.52.54 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 18 Jul 2020 13:52:55 -0700 (PDT) From: Brian Norris To: openwrt-devel@lists.openwrt.org Subject: [RFC PATCH 2/5] firmware-utils/cros-vbutil: add Chrome OS vboot kernel-signing utility Date: Sat, 18 Jul 2020 20:51:45 +0000 Message-Id: <20200718205148.1743807-3-computersforpeace@gmail.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200718205148.1743807-1-computersforpeace@gmail.com> References: <20200718205148.1743807-1-computersforpeace@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200718_165258_747217_5CDF1C57 X-CRM114-Status: GOOD ( 24.00 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:644 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [computersforpeace[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: OpenWrt Development List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Brian Norris Sender: "openwrt-devel" Errors-To: openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org Chrom{ium,e} OS based devices use a Coreboot+Depthcharge-based firmware, which verifies and loads a kernel packed in a verified-boot payload. The verification tooling (both for creating and verifying payloads) is implemented here: https://chromium.googlesource.com/chromiumos/platform/vboot_reference Devices running such bootloaders also tend to support a "developer mode," where a device can be unlocked to run arbitrary kernel payloads, using the same verified-boot format plus well-known developer keys. More information can be found here: https://chromium.googlesource.com/chromiumos/docs/+/master/developer_mode.md Rather than build and package the vboot_reference utilities as part of the base OpenWRT tools, I chose to reimplement just the portion that's required for signing payloads. I also embed the developer key directly in the source for convenience, though it's certainly possible to provide other keys too, if one were to build their own firmware that accepts it. This tool is essentially the same as running something like this, using the Chromium OS tooling: vbutil_kernel --pack kernel_partition.bin \ --keyblock /usr/share/vboot/devkeys/kernel.keyblock \ --signprivate /usr/share/vboot/devkeys/kernel_data_key.vbprivk \ --version 1 \ --vmlinuz kernel.bin \ --bootloader zero.txt \ --config commnad_line.txt \ --arch ${ARCH} I have also packaged the Chromium OS vboot_reference tooling for the packages feed, as it can be useful beyond simply creating a bootable image (e.g., manipulating Chromium OS specific GPT attributes, handling other NVRAM attributes, vboot packing/unpacking/verifying): https://github.com/openwrt/packages/pull/12829 The vboot_reference tools are released by Google under a BSD 3-clause license. I've provided the original license text as well as a GPL-2 notice for my modifications (essentially just borrowing the data structures and rewriting everything else). Signed-off-by: Brian Norris --- tools/firmware-utils/Makefile | 1 + tools/firmware-utils/src/cros-vbutil.c | 609 +++++++++++++++++++++++++ 2 files changed, 610 insertions(+) create mode 100644 tools/firmware-utils/src/cros-vbutil.c diff --git a/tools/firmware-utils/Makefile b/tools/firmware-utils/Makefile index 3dd9ac5c2cc1..8216c97e9cfc 100644 --- a/tools/firmware-utils/Makefile +++ b/tools/firmware-utils/Makefile @@ -29,6 +29,7 @@ define Host/Compile $(call cc,buffalo-enc buffalo-lib,-Wall) $(call cc,buffalo-tag buffalo-lib,-Wall) $(call cc,buffalo-tftp buffalo-lib,-Wall) + $(call cc,cros-vbutil,-lcrypto -lpthread) $(call cc,dgfirmware) $(call cc,dgn3500sum,-Wall) $(call cc,dns313-header,-Wall) diff --git a/tools/firmware-utils/src/cros-vbutil.c b/tools/firmware-utils/src/cros-vbutil.c new file mode 100644 index 000000000000..2040c5901985 --- /dev/null +++ b/tools/firmware-utils/src/cros-vbutil.c @@ -0,0 +1,609 @@ +/* + * cros-vbutil - Tool for signing kernels using the Chromium OS verified boot + * format, using widely-shared "developer" keys. The output of this tool is + * intended to be written to a GPT partition of type "Chrome OS Kernel", such + * that a Chromium OS bootloader can find it. + * + * Much of this is adapted from Google's vboot_reference project found here: + * https://chromium.googlesource.com/chromiumos/platform/vboot_reference + * + * Copyright (c) 2010 The Chromium OS Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Rewritten: + * Copyright (c) 2020 Brian Norris + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define BLOCK_PAD 65536 +/* Sections are aligned to 4K blocks */ +#define ALIGN 4096 +#define ROUNDUP(x) (((x) + (ALIGN-1)) & ~(ALIGN-1)) + +/* + * Signature size, in bytes. This is an RSA-2048 encryption of a SHA256 hash. + */ +#define SIG_SIZE (2048 / 8) + +/* + * From vboot_reference: tests/devkeys/kernel.keyblock + */ +static const unsigned char keyblock[] = { + 0x43, 0x48, 0x52, 0x4f, 0x4d, 0x45, 0x4f, 0x53, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xb8, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xa0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x48, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xcb, 0x02, 0x40, 0x41, + 0x1d, 0x2d, 0x86, 0x0f, 0x6d, 0x53, 0xcc, 0xcc, 0xa7, 0x9b, 0x1b, 0xca, + 0xdc, 0x22, 0xc4, 0xc2, 0x3a, 0x72, 0xa5, 0x12, 0x21, 0xfe, 0x78, 0x1d, + 0x9c, 0x03, 0x65, 0x0c, 0x94, 0xba, 0x3d, 0x5b, 0x5e, 0x98, 0x16, 0x8a, + 0xaf, 0xaf, 0x67, 0x5a, 0x46, 0x88, 0x2c, 0xf0, 0x2a, 0x65, 0xbd, 0xc7, + 0x59, 0xcc, 0x70, 0xe9, 0x01, 0x4e, 0x7d, 0x8c, 0x43, 0x2e, 0x1c, 0x6d, + 0x72, 0x15, 0xaf, 0xd0, 0x71, 0x9f, 0xb4, 0x3a, 0xe7, 0x44, 0x82, 0xd1, + 0x83, 0x8b, 0x9d, 0x6c, 0x64, 0x99, 0xaf, 0xdb, 0x8a, 0xcc, 0xd1, 0xd6, + 0x83, 0xa6, 0xa4, 0xea, 0xa9, 0x81, 0x1d, 0x9f, 0x1b, 0x5a, 0x8c, 0xf8, + 0xdb, 0x26, 0x21, 0xb2, 0x7b, 0x53, 0x92, 0xf0, 0x6a, 0xc5, 0x8c, 0x11, + 0xba, 0x7e, 0x43, 0xcb, 0x1e, 0x57, 0xa1, 0x6e, 0xd5, 0xfe, 0x82, 0x28, + 0x3d, 0x6d, 0xbd, 0x97, 0xb0, 0xe8, 0xfb, 0x1f, 0x88, 0x06, 0x1b, 0x0a, + 0xc5, 0x8f, 0x96, 0x69, 0x48, 0x69, 0x41, 0x2a, 0x52, 0xd7, 0xb7, 0x33, + 0x78, 0x8b, 0x6f, 0x97, 0xa7, 0x7d, 0xdc, 0xd0, 0x2b, 0xd9, 0x81, 0x67, + 0xc9, 0x3f, 0xa9, 0xb4, 0x1e, 0x0b, 0x08, 0x54, 0xc6, 0x01, 0xc6, 0x20, + 0xe6, 0xc6, 0x09, 0x5f, 0x0a, 0xc5, 0x02, 0x05, 0x6b, 0x40, 0x96, 0x11, + 0x20, 0xe5, 0xa2, 0x88, 0x37, 0x6a, 0xd3, 0xda, 0xda, 0xda, 0x76, 0x1c, + 0xe4, 0x3d, 0x2c, 0xfe, 0x65, 0x86, 0x98, 0xa2, 0xa8, 0x49, 0x7d, 0x26, + 0x45, 0x14, 0x04, 0x10, 0xe3, 0x38, 0x4b, 0x66, 0x9c, 0x5c, 0x2c, 0xe8, + 0xd9, 0x06, 0xd4, 0xc3, 0x05, 0x94, 0x1c, 0x7b, 0x23, 0x89, 0x86, 0x1d, + 0x32, 0xbb, 0x23, 0x90, 0x2b, 0x72, 0xd7, 0x90, 0x53, 0x52, 0x10, 0x12, + 0xd0, 0xc2, 0xe2, 0x72, 0x81, 0x70, 0x3c, 0xb1, 0x27, 0x42, 0xec, 0xbf, + 0x2b, 0x54, 0xd6, 0xcb, 0x61, 0xea, 0xb4, 0xd4, 0xa8, 0xde, 0xf3, 0xdf, + 0x3d, 0xd1, 0x17, 0xde, 0x86, 0x89, 0xf4, 0xa1, 0x28, 0x5e, 0xda, 0xb4, + 0x47, 0x19, 0x9b, 0xc2, 0xce, 0x49, 0xea, 0x63, 0xda, 0x42, 0x1c, 0x85, + 0x1c, 0xab, 0x6c, 0xd7, 0xc2, 0xfd, 0x34, 0x1b, 0xd5, 0x11, 0xa2, 0x44, + 0xb7, 0x7a, 0x85, 0x61, 0x03, 0xba, 0xd4, 0x64, 0xe1, 0x49, 0x87, 0x92, + 0xe6, 0xdc, 0x39, 0x94, 0x9c, 0xba, 0xef, 0x58, 0x9e, 0x0e, 0x36, 0x98, + 0xd7, 0xd2, 0x4c, 0x14, 0x71, 0x94, 0x78, 0xaf, 0x86, 0xe7, 0x2f, 0xe9, + 0xf9, 0x20, 0x4d, 0xfe, 0xda, 0xd7, 0x3f, 0x89, 0xc1, 0x59, 0xae, 0xbd, + 0x60, 0x9b, 0x97, 0xa4, 0x66, 0x00, 0xbb, 0x7b, 0xd0, 0x49, 0x85, 0x6f, + 0x7b, 0x01, 0x24, 0xc3, 0x48, 0xe2, 0xc7, 0x61, 0x98, 0x9c, 0xe5, 0x93, + 0x87, 0x04, 0x09, 0x3a, 0x92, 0x54, 0x1f, 0xb5, 0x80, 0x29, 0x15, 0xe5, + 0x7f, 0xfe, 0xdc, 0xaf, 0xd3, 0xe1, 0x62, 0xc4, 0xb6, 0xdb, 0x2f, 0x1a, + 0x08, 0xf3, 0x54, 0x06, 0x3a, 0xce, 0x5e, 0x89, 0x71, 0xdf, 0x3b, 0x5c, + 0x8c, 0x6b, 0x83, 0xa9, 0x0c, 0x05, 0x50, 0x7b, 0x84, 0x09, 0x18, 0x66, + 0x84, 0xe1, 0x7e, 0x60, 0xd6, 0xdc, 0xbf, 0x1c, 0xac, 0x5c, 0xdc, 0xe6, + 0x4c, 0x9e, 0xa0, 0x4a, 0x59, 0x30, 0xff, 0x91, 0x90, 0x1e, 0x21, 0x29, + 0x50, 0x99, 0x76, 0xfd, 0x2f, 0x5a, 0x67, 0x6a, 0x00, 0x6b, 0x40, 0x27, + 0xe7, 0xbd, 0x17, 0xe6, 0x5f, 0x9e, 0xe4, 0x6b, 0xe0, 0x05, 0x9e, 0x7d, + 0xcb, 0x90, 0xe9, 0x3c, 0x9c, 0x79, 0xc9, 0x47, 0xf8, 0x58, 0xbc, 0x3f, + 0xb1, 0xa5, 0xef, 0x67, 0xf0, 0x22, 0xa1, 0x70, 0x33, 0x36, 0xb0, 0x5c, + 0xed, 0xea, 0x4e, 0xde, 0x24, 0x0c, 0x5b, 0xd8, 0x4d, 0xbe, 0xac, 0x6a, + 0x12, 0x31, 0xa6, 0x5e, 0x5f, 0x04, 0xb6, 0x58, 0xa1, 0xd1, 0x29, 0xa3, + 0x33, 0x9c, 0x64, 0xb1, 0x8e, 0x3b, 0xfa, 0xaf, 0x35, 0x94, 0x7a, 0xa4, + 0xf5, 0xcb, 0x9e, 0x67, 0x1b, 0x8d, 0x35, 0xca, 0x10, 0x69, 0x8d, 0xea, + 0x78, 0xc2, 0xf6, 0x63, 0xc0, 0x11, 0xf1, 0xf6, 0x66, 0x70, 0x2e, 0x96, + 0xf0, 0xbc, 0x7b, 0x1e, 0x16, 0x26, 0xde, 0xe3, 0x7f, 0xc0, 0xf4, 0x6c, + 0x3c, 0x0b, 0x52, 0xe2, 0x07, 0xde, 0x70, 0x8b, 0xaf, 0x84, 0x95, 0x1b, + 0x46, 0x95, 0x69, 0x05, 0x92, 0xea, 0x36, 0xa5, 0xca, 0x50, 0xdb, 0x49, + 0xc8, 0x44, 0xee, 0x7c, 0x49, 0x40, 0x34, 0x05, 0xf3, 0x06, 0x1f, 0x1c, + 0xcc, 0x78, 0x62, 0x1b, 0x9d, 0xe2, 0x4f, 0x3e, 0x04, 0x96, 0xba, 0xd0, + 0xc7, 0xa2, 0x3a, 0xaa, 0xf7, 0xc3, 0xae, 0xc0, 0x6b, 0xca, 0xc8, 0x59, + 0x90, 0xe0, 0x45, 0x7b, 0x4b, 0x60, 0xbf, 0xae, 0x15, 0x25, 0xd0, 0xa2, + 0x2f, 0x95, 0x6a, 0x2e, 0x37, 0x24, 0x15, 0x69, 0x0e, 0x3a, 0x6d, 0x40, + 0x21, 0xf6, 0x74, 0x5c, 0xa6, 0x9f, 0xe0, 0x03, 0x60, 0x04, 0x59, 0x70, + 0x70, 0xa0, 0x46, 0xf4, 0xdf, 0x0a, 0x4b, 0x14, 0xab, 0x87, 0x0c, 0xaa, + 0x64, 0x9b, 0x82, 0xca, 0x21, 0xb0, 0x72, 0xfa, 0x8b, 0x37, 0xf5, 0x60, + 0xd7, 0xb7, 0x4e, 0x72, 0x5e, 0x13, 0x23, 0x73, 0x84, 0x6c, 0xd1, 0x8d, + 0x72, 0xa2, 0x15, 0x8b, 0x51, 0x38, 0x90, 0x68, 0x90, 0xd9, 0x8b, 0x65, + 0x30, 0x61, 0xdb, 0x51, 0x80, 0x58, 0xdd, 0xc3, 0xf0, 0x29, 0x33, 0xdc, + 0x39, 0x92, 0xbf, 0x27, 0xe6, 0xc7, 0x82, 0xf6, 0xea, 0xcf, 0x21, 0xd2, + 0xa0, 0x38, 0x02, 0x57, 0x52, 0xf5, 0xdd, 0x07, 0x99, 0xe3, 0x09, 0xd7, + 0xad, 0x9e, 0x1e, 0xe7, 0xf3, 0x5e, 0x72, 0xa0, 0xc6, 0x9d, 0x41, 0x86, + 0x96, 0x82, 0x74, 0x46, 0x1f, 0x05, 0xd2, 0x05, 0x25, 0x29, 0x27, 0x66, + 0xe1, 0xab, 0x5c, 0x06, 0xf4, 0xac, 0xe7, 0xd0, 0xf8, 0xe6, 0x5e, 0x8b, + 0x19, 0x55, 0xc2, 0x99, 0x8e, 0xa7, 0x2e, 0x66, 0x0c, 0x2a, 0x61, 0xb0, + 0x98, 0x41, 0x93, 0x05, 0x54, 0x90, 0xaa, 0xbe, 0x15, 0x26, 0x5b, 0x77, + 0x7c, 0xb0, 0xf8, 0x08, 0x68, 0xb6, 0xb8, 0xd4, 0xdd, 0xd8, 0xa8, 0x4f, + 0xdd, 0xf6, 0x93, 0xe5, 0xa1, 0x88, 0x1b, 0x7a, 0x05, 0x81, 0xc5, 0x98, + 0x34, 0x1d, 0x88, 0x63, 0x55, 0xaf, 0x9a, 0xa1, 0xcb, 0x4b, 0xaf, 0x86, + 0xb3, 0x45, 0xda, 0xa4, 0xb4, 0xa5, 0x10, 0x7a, 0x50, 0x6a, 0xe5, 0xda, + 0x6f, 0x8f, 0xc0, 0x1d, 0x95, 0xb1, 0x91, 0x48, 0x53, 0xc3, 0xe5, 0x1f, + 0x0e, 0x05, 0x75, 0xaa, 0xc7, 0xd8, 0x36, 0xd0, 0x6d, 0x50, 0x48, 0xd4, + 0xe6, 0xbd, 0xd0, 0x2d, 0x97, 0x17, 0x2d, 0xb3, 0x46, 0xab, 0x19, 0x0e, + 0xe4, 0xac, 0xfd, 0x93, 0xab, 0x0c, 0x4c, 0xad, 0xbf, 0x58, 0x1b, 0xaa, + 0x26, 0xcd, 0x0d, 0xda, 0xaf, 0xcb, 0xeb, 0xb0, 0x19, 0x5c, 0x46, 0x1f, + 0x9b, 0xb0, 0xb8, 0x12, 0x6c, 0xa7, 0x4e, 0xb8, 0xa7, 0x1f, 0x12, 0x6b, + 0xf8, 0xbe, 0x4b, 0xa9, 0x04, 0xb4, 0xf9, 0x36, 0xcc, 0xd9, 0xd5, 0x91, + 0xac, 0x7e, 0xe9, 0x13, 0xc0, 0x7f, 0xca, 0xd7, 0xdc, 0xbe, 0xa9, 0xb0, + 0xd6, 0x28, 0x17, 0x2f, 0xd6, 0xdf, 0x0e, 0x6b, 0x48, 0x11, 0xd6, 0x51, + 0xc7, 0x6d, 0x87, 0xf6, 0x08, 0xb7, 0x6c, 0x69, 0xf7, 0xd6, 0x28, 0x50, + 0x7e, 0x74, 0xad, 0x96, 0x6a, 0x0c, 0xca, 0x6b, 0xb1, 0xf1, 0xde, 0xa3, + 0x5f, 0x23, 0xf5, 0x2a, 0x44, 0x11, 0x0f, 0xa3, 0xf7, 0x24, 0x36, 0x1b, + 0x33, 0xe6, 0x7e, 0xd9, 0x0e, 0xa5, 0x8b, 0xa0, 0xb8, 0x8b, 0x85, 0xee, + 0xd0, 0xe4, 0x69, 0x43, 0xc6, 0xf9, 0x5f, 0x27, 0xa5, 0xc9, 0x61, 0x3b, + 0x8e, 0xaf, 0x62, 0x77, 0x42, 0xb6, 0x27, 0x5f, 0xed, 0x96, 0x86, 0xb3, + 0xef, 0x32, 0x31, 0x43, 0x2e, 0x7b, 0xaf, 0x5b, 0xe2, 0x75, 0x82, 0x72, + 0xad, 0x3b, 0x5d, 0x92, 0xc1, 0x15, 0xaa, 0xfb, 0x21, 0x07, 0xe9, 0xaa, + 0xc4, 0xe2, 0xd7, 0x99, 0x83, 0x6c, 0x72, 0x39, 0x6f, 0x35, 0x20, 0x9d, + 0xe0, 0xd8, 0xf8, 0xdb, 0x72, 0x24, 0xe5, 0x8d, 0x29, 0xfd, 0x24, 0x7b, + 0xbc, 0x48, 0xe9, 0xbb, 0xc2, 0x84, 0xc7, 0xb9 +}; +static unsigned int keyblock_len = sizeof(keyblock); + +/* + * RSA 2048-bit key from vboot_reference: + * tests/devkeys/kernel_data_key.vbprivk, minus the 8-byte custom header. + */ +static const unsigned char privk[] = { + 0x30, 0x82, 0x04, 0xa3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, + 0xcb, 0xd6, 0x54, 0x2b, 0xbf, 0xec, 0x42, 0x27, 0xb1, 0x3c, 0x70, 0x81, + 0x72, 0xe2, 0xc2, 0xd0, 0x12, 0x10, 0x52, 0x53, 0x90, 0xd7, 0x72, 0x2b, + 0x90, 0x23, 0xbb, 0x32, 0x1d, 0x86, 0x89, 0x23, 0x7b, 0x1c, 0x94, 0x05, + 0xc3, 0xd4, 0x06, 0xd9, 0xe8, 0x2c, 0x5c, 0x9c, 0x66, 0x4b, 0x38, 0xe3, + 0x10, 0x04, 0x14, 0x45, 0x26, 0x7d, 0x49, 0xa8, 0xa2, 0x98, 0x86, 0x65, + 0xfe, 0x2c, 0x3d, 0xe4, 0x1c, 0x76, 0xda, 0xda, 0xda, 0xd3, 0x6a, 0x37, + 0x88, 0xa2, 0xe5, 0x20, 0x11, 0x96, 0x40, 0x6b, 0x05, 0x02, 0xc5, 0x0a, + 0x5f, 0x09, 0xc6, 0xe6, 0x20, 0xc6, 0x01, 0xc6, 0x54, 0x08, 0x0b, 0x1e, + 0xb4, 0xa9, 0x3f, 0xc9, 0x67, 0x81, 0xd9, 0x2b, 0xd0, 0xdc, 0x7d, 0xa7, + 0x97, 0x6f, 0x8b, 0x78, 0x33, 0xb7, 0xd7, 0x52, 0x2a, 0x41, 0x69, 0x48, + 0x69, 0x96, 0x8f, 0xc5, 0x0a, 0x1b, 0x06, 0x88, 0x1f, 0xfb, 0xe8, 0xb0, + 0x97, 0xbd, 0x6d, 0x3d, 0x28, 0x82, 0xfe, 0xd5, 0x6e, 0xa1, 0x57, 0x1e, + 0xcb, 0x43, 0x7e, 0xba, 0x11, 0x8c, 0xc5, 0x6a, 0xf0, 0x92, 0x53, 0x7b, + 0xb2, 0x21, 0x26, 0xdb, 0xf8, 0x8c, 0x5a, 0x1b, 0x9f, 0x1d, 0x81, 0xa9, + 0xea, 0xa4, 0xa6, 0x83, 0xd6, 0xd1, 0xcc, 0x8a, 0xdb, 0xaf, 0x99, 0x64, + 0x6c, 0x9d, 0x8b, 0x83, 0xd1, 0x82, 0x44, 0xe7, 0x3a, 0xb4, 0x9f, 0x71, + 0xd0, 0xaf, 0x15, 0x72, 0x6d, 0x1c, 0x2e, 0x43, 0x8c, 0x7d, 0x4e, 0x01, + 0xe9, 0x70, 0xcc, 0x59, 0xc7, 0xbd, 0x65, 0x2a, 0xf0, 0x2c, 0x88, 0x46, + 0x5a, 0x67, 0xaf, 0xaf, 0x8a, 0x16, 0x98, 0x5e, 0x5b, 0x3d, 0xba, 0x94, + 0x0c, 0x65, 0x03, 0x9c, 0x1d, 0x78, 0xfe, 0x21, 0x12, 0xa5, 0x72, 0x3a, + 0xc2, 0xc4, 0x22, 0xdc, 0xca, 0x1b, 0x9b, 0xa7, 0xcc, 0xcc, 0x53, 0x6d, + 0x0f, 0x86, 0x2d, 0x1d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, + 0x00, 0x4d, 0xb8, 0xea, 0x9d, 0x47, 0xef, 0xf1, 0x05, 0xab, 0x79, 0xed, + 0x38, 0x1e, 0xb3, 0x42, 0x2f, 0x0e, 0x44, 0x34, 0xef, 0xf2, 0x31, 0x84, + 0x32, 0x02, 0x22, 0xed, 0xb4, 0xdd, 0x37, 0x38, 0x41, 0x54, 0x27, 0x00, + 0x75, 0xf6, 0x46, 0x79, 0x5a, 0x4b, 0x41, 0xe7, 0x0a, 0x27, 0xa3, 0x15, + 0x0c, 0xd7, 0x45, 0x86, 0xe9, 0x1b, 0x14, 0xf8, 0xaa, 0x19, 0x5d, 0x69, + 0x19, 0xa8, 0xc1, 0xfb, 0xd3, 0x67, 0xdb, 0x15, 0xf6, 0x0f, 0x2c, 0x3f, + 0xba, 0xef, 0x19, 0x95, 0x9e, 0x15, 0xb6, 0xa1, 0xd7, 0x6c, 0xb0, 0xb2, + 0xab, 0x12, 0xb3, 0xea, 0xa8, 0x42, 0xe4, 0xdd, 0x36, 0x5f, 0x42, 0x35, + 0xe3, 0x3e, 0x65, 0xae, 0x91, 0xc0, 0x2a, 0xed, 0xc0, 0xdc, 0x41, 0xc6, + 0x93, 0xc9, 0x95, 0x59, 0xab, 0xba, 0xa4, 0xa5, 0xb0, 0x89, 0xb6, 0x29, + 0x4b, 0xd8, 0x1e, 0xf5, 0xb0, 0xde, 0xfa, 0x91, 0x11, 0x55, 0xd6, 0x9d, + 0xe1, 0xa7, 0x9c, 0xf2, 0xf4, 0x9d, 0x7f, 0x96, 0x49, 0x7a, 0xab, 0xe9, + 0x9a, 0x0c, 0xcb, 0x10, 0x5c, 0x67, 0xf0, 0x1d, 0xf3, 0x33, 0x84, 0xae, + 0x6e, 0xe4, 0xbb, 0xa7, 0x57, 0x98, 0x99, 0x2b, 0xf3, 0x1d, 0xab, 0xec, + 0x01, 0xa2, 0x2e, 0x3c, 0x10, 0x5c, 0xff, 0xe8, 0xcc, 0x50, 0x45, 0x21, + 0x2f, 0x04, 0x69, 0xdd, 0x02, 0x5b, 0x10, 0xd6, 0x54, 0x36, 0x4c, 0x73, + 0x0c, 0x1e, 0xc1, 0xff, 0xac, 0x60, 0x5d, 0xbc, 0x13, 0x84, 0xe8, 0xa4, + 0xbd, 0x66, 0xca, 0xca, 0xaf, 0x55, 0x8a, 0xf8, 0x87, 0x17, 0x93, 0xbf, + 0x66, 0xa4, 0x97, 0xe9, 0x47, 0x81, 0x03, 0xfa, 0x4c, 0x32, 0xf6, 0xec, + 0x7a, 0x03, 0xbb, 0x2d, 0x3b, 0x9b, 0xea, 0xdc, 0x6c, 0x61, 0x7f, 0x05, + 0xc8, 0x2d, 0x50, 0x89, 0xe9, 0x10, 0x3d, 0x3c, 0x02, 0xb0, 0x5d, 0x3e, + 0x25, 0x71, 0xd2, 0xa1, 0xe1, 0x02, 0x81, 0x81, 0x00, 0xf6, 0x3c, 0x7f, + 0x15, 0x63, 0x04, 0x0a, 0xd4, 0x68, 0xe8, 0xd9, 0x4b, 0x7f, 0xbc, 0xca, + 0xb5, 0x84, 0x01, 0x71, 0x11, 0x33, 0x4d, 0xe1, 0x0a, 0xe8, 0xa7, 0x95, + 0xcc, 0x23, 0x59, 0x19, 0xb5, 0x82, 0xaa, 0xae, 0xe4, 0x90, 0x33, 0x95, + 0x20, 0x1a, 0xfd, 0xef, 0x8e, 0x36, 0xc1, 0x57, 0xde, 0x94, 0xdd, 0x99, + 0x6f, 0x14, 0x0c, 0x8e, 0x30, 0xe0, 0xe7, 0x64, 0x33, 0xa7, 0x1d, 0xfd, + 0x99, 0xdc, 0x58, 0x49, 0x4e, 0x56, 0x82, 0x43, 0xea, 0xd9, 0xf7, 0xcc, + 0x1a, 0xf5, 0x09, 0x38, 0x4c, 0xf6, 0x87, 0x8f, 0xa6, 0x40, 0x96, 0xd1, + 0x81, 0x62, 0xbb, 0x49, 0x53, 0x69, 0x56, 0xdf, 0x4a, 0x85, 0xfd, 0x72, + 0x34, 0x21, 0x56, 0xa3, 0x7b, 0xda, 0x50, 0x24, 0x88, 0xc6, 0x0b, 0x03, + 0x94, 0x0d, 0xe2, 0x03, 0x2a, 0x3c, 0x5a, 0xdd, 0x73, 0xe7, 0x07, 0x01, + 0x7d, 0xdd, 0x38, 0x81, 0x19, 0x02, 0x81, 0x81, 0x00, 0xd3, 0xeb, 0x72, + 0x3f, 0xf6, 0x9b, 0x03, 0x8c, 0xab, 0xd9, 0x41, 0x47, 0xbe, 0x6c, 0x07, + 0x7f, 0xd7, 0xcb, 0xee, 0xbf, 0x45, 0x13, 0x1e, 0x53, 0x35, 0xd2, 0xe4, + 0x6a, 0x13, 0xe9, 0xd8, 0xe3, 0xf4, 0x28, 0x5e, 0xeb, 0xd8, 0xd2, 0x87, + 0x60, 0xdc, 0xa7, 0x21, 0xd8, 0x33, 0xce, 0xca, 0x60, 0x50, 0x1b, 0x87, + 0xbf, 0x71, 0x88, 0x90, 0x71, 0x6f, 0xde, 0xdb, 0x33, 0x1d, 0x3c, 0xb1, + 0x2f, 0x1b, 0x41, 0xb8, 0x55, 0xa1, 0x5c, 0xa8, 0xb2, 0x73, 0x1b, 0x39, + 0x69, 0x5c, 0xa1, 0x57, 0x9b, 0x2e, 0xcd, 0x0d, 0x71, 0x42, 0xdf, 0x2a, + 0xd3, 0x4f, 0x51, 0xdc, 0x35, 0x5c, 0x14, 0x86, 0x16, 0xb8, 0x22, 0x8c, + 0x73, 0x37, 0x7a, 0x6c, 0xb7, 0xfe, 0x01, 0x1b, 0xa8, 0xc5, 0xf1, 0xff, + 0xda, 0xd4, 0x63, 0x58, 0x81, 0xe1, 0x6a, 0xaf, 0xc2, 0x3d, 0xbb, 0x17, + 0x3f, 0x2c, 0xf9, 0xb8, 0xa5, 0x02, 0x81, 0x81, 0x00, 0xd1, 0x1e, 0x6b, + 0xa7, 0x54, 0x22, 0x18, 0xb8, 0x70, 0x28, 0x60, 0x72, 0x98, 0x17, 0x53, + 0xe8, 0x78, 0x25, 0x69, 0x4a, 0xfc, 0x51, 0x45, 0xb0, 0x28, 0x0a, 0x3b, + 0x53, 0xd5, 0x29, 0x54, 0x86, 0x2c, 0x64, 0x9c, 0x87, 0x8c, 0x57, 0xe2, + 0x6c, 0x13, 0xc0, 0x59, 0x74, 0x63, 0xd8, 0x2b, 0xb1, 0xe2, 0xa7, 0x98, + 0x29, 0x17, 0xd3, 0xd9, 0xe6, 0x74, 0xfa, 0xce, 0xc4, 0x77, 0x47, 0x27, + 0x1b, 0x46, 0x60, 0xcc, 0x50, 0xf5, 0x73, 0x48, 0x0e, 0xe9, 0xf2, 0x62, + 0xaa, 0xfa, 0x33, 0x4c, 0x57, 0x40, 0x7f, 0xbc, 0x65, 0xab, 0x30, 0xea, + 0xd8, 0x81, 0x6b, 0x21, 0x48, 0xef, 0x8b, 0x51, 0xb3, 0x4e, 0xbc, 0x02, + 0x03, 0x77, 0xd4, 0xc6, 0x9e, 0xe6, 0xb7, 0x6d, 0x6f, 0xa3, 0x11, 0xb3, + 0x86, 0x47, 0x8c, 0x0c, 0xb8, 0x0f, 0xed, 0xf3, 0x68, 0xfd, 0x69, 0x9b, + 0xc0, 0xb2, 0xe1, 0xcb, 0xf1, 0x02, 0x81, 0x80, 0x46, 0xc6, 0xdb, 0xe1, + 0x80, 0xfb, 0x44, 0xb4, 0x36, 0xb0, 0xd8, 0x9c, 0x9d, 0x7c, 0x77, 0x04, + 0xbb, 0x8d, 0xe0, 0xaf, 0x00, 0xe2, 0xe1, 0xbd, 0xe8, 0xbc, 0x06, 0x8d, + 0x67, 0x19, 0x32, 0xd6, 0xef, 0x34, 0x8c, 0x7f, 0x38, 0x6b, 0x17, 0xcb, + 0xc1, 0xe6, 0x0f, 0xe7, 0xa5, 0x65, 0xeb, 0x31, 0x3f, 0x8f, 0xf2, 0x46, + 0x7e, 0x24, 0x9e, 0x19, 0x44, 0xc3, 0xa9, 0x71, 0xe8, 0xd1, 0xdc, 0x5b, + 0x5f, 0x3f, 0x13, 0xd1, 0x85, 0x92, 0xec, 0xc4, 0xac, 0xac, 0xea, 0xff, + 0xc5, 0x70, 0x1d, 0x52, 0x36, 0xcf, 0x45, 0x2e, 0x0e, 0xa7, 0x7a, 0x26, + 0x18, 0xd7, 0xbe, 0x34, 0x14, 0x0c, 0xc6, 0xbb, 0xcf, 0xc3, 0xba, 0x24, + 0xc0, 0xe2, 0xa2, 0x6c, 0xd0, 0xe8, 0x8d, 0xd4, 0x50, 0x48, 0x02, 0xab, + 0x93, 0x43, 0x9a, 0xcb, 0xc5, 0xfd, 0x5b, 0xb6, 0x03, 0xe7, 0xf8, 0x5b, + 0xa1, 0x29, 0xc6, 0x01, 0x02, 0x81, 0x80, 0x0e, 0x18, 0xbc, 0x00, 0xa3, + 0x81, 0xda, 0xc2, 0xc8, 0xfb, 0x0a, 0xbd, 0x7f, 0xb7, 0x7f, 0xa1, 0x18, + 0x7f, 0x49, 0xb8, 0x32, 0x83, 0x4b, 0x71, 0x35, 0x59, 0x51, 0x7b, 0xee, + 0x8e, 0x4e, 0xd2, 0x42, 0xa8, 0x6c, 0x82, 0x57, 0xf7, 0x34, 0xf6, 0x82, + 0x59, 0xe9, 0x75, 0x7a, 0x8f, 0x0a, 0x8d, 0x46, 0x1e, 0xa1, 0x77, 0xa1, + 0x4c, 0xb3, 0x9e, 0x86, 0x93, 0x18, 0xdf, 0x3e, 0xfb, 0x81, 0xd0, 0xbc, + 0x65, 0xa2, 0xb3, 0x80, 0xf0, 0x8f, 0x73, 0x2f, 0xb5, 0xc4, 0xc0, 0x03, + 0xac, 0x24, 0xfa, 0x4f, 0x05, 0xe3, 0x16, 0x29, 0x7c, 0xff, 0x63, 0xd5, + 0x0a, 0x0a, 0xbd, 0xd7, 0x65, 0x3a, 0xb5, 0x5e, 0xe7, 0x23, 0xfc, 0x3d, + 0x08, 0xea, 0x62, 0xc2, 0xe3, 0x4a, 0xbb, 0x86, 0x5a, 0xc5, 0x93, 0xd7, + 0xbc, 0xb4, 0x4c, 0xcf, 0xcf, 0x78, 0x9f, 0x52, 0x6e, 0xa1, 0x49, 0x21, + 0xf7, 0x20, 0x42 +}; +static const unsigned int privk_len = sizeof(privk); + +/* Signature data (a secure hash, possibly signed) */ +struct vb2_signature { + /* Offset of signature data from start of this struct */ + uint32_t sig_offset; + uint32_t reserved0; + + /* Size of signature data in bytes */ + uint32_t sig_size; + uint32_t reserved1; + + /* Size of the data block which was signed in bytes */ + uint32_t data_size; + uint32_t reserved2; +} __attribute__((packed)); + +/* + * Preamble block for kernel, version 2.2 + * + * This should be followed by: + * 1) The signature data for the kernel body, pointed to by + * body_signature.sig_offset. + * 2) The signature data for (vb2_kernel_preamble + body signature data), + * pointed to by preamble_signature.sig_offset. + * 3) The 16-bit vmlinuz header, which is used for reconstruction of + * vmlinuz image. + */ +struct vb2_kernel_preamble { + /* + * Size of this preamble, including keys, signatures, vmlinuz header, + * and padding, in bytes + */ + uint32_t preamble_size; + uint32_t reserved0; + + /* Signature for this preamble (header + body signature) */ + struct vb2_signature preamble_signature; + + /* Version of this header format */ + uint32_t header_version_major; + uint32_t header_version_minor; + + /* Kernel version */ + uint32_t kernel_version; + uint32_t reserved1; + + /* Load address for kernel body */ + uint64_t body_load_address; + + /* Address of bootloader, after body is loaded at body_load_address */ + uint64_t bootloader_address; + + /* Size of bootloader in bytes */ + uint32_t bootloader_size; + uint32_t reserved2; + + /* Signature for the kernel body */ + struct vb2_signature body_signature; + + /* Address of 16-bit header for vmlinuz reassembly. */ + uint64_t vmlinuz_header_address; + + /* Size of 16-bit header for vmlinuz in bytes. */ + uint32_t vmlinuz_header_size; + uint32_t reserved3; + + uint32_t flags; +} __attribute__((packed)); + +/* + * Order matters. |data| may overlap with |siginfo|, so we need to fill out + * |siginfo| before computing the signature. + */ +static int sign(const void *data, size_t len, struct vb2_signature *siginfo, + void *sigout) +{ + unsigned char hash[SHA256_DIGEST_LENGTH]; + SHA256_CTX sha256; + int ret; + + memset(siginfo, 0, sizeof(*siginfo)); + siginfo->sig_offset = (uintptr_t)(void *)sigout - (uintptr_t)(void *)siginfo; + siginfo->sig_size = SIG_SIZE; + siginfo->data_size = len; + + const unsigned char *p = privk; + char digest_info[] = { + 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, + 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20, + }; + + uint8_t digest[sizeof(digest_info) + sizeof(hash)]; + + SHA256_Init(&sha256); + SHA256_Update(&sha256, data, len); + SHA256_Final(hash, &sha256); + + memcpy(digest, digest_info, sizeof(digest_info)); + memcpy(digest + sizeof(digest_info), hash, sizeof(hash)); + + RSA *key = d2i_RSAPrivateKey(0, &p, privk_len); + if (!key) { + fprintf(stderr, "Failed d2i_RSAPrivateKey()\n"); + return -1; + } + + ret = RSA_private_encrypt(sizeof(digest), digest, sigout, key, + RSA_PKCS1_PADDING); + if (ret == -1) { + fprintf(stderr, "%s: RSA_private_encrypt() failed\n", __func__); + return -1; + } + + return 0; +} + +static struct vb2_kernel_preamble * +generate_preamble(const void *kblob, size_t kblob_len, + size_t kernel_len, size_t config_len) +{ + struct vb2_kernel_preamble *h; + uint32_t signed_size = sizeof(struct vb2_kernel_preamble) + SIG_SIZE; + uint32_t block_size = signed_size + SIG_SIZE; + int ret; + + if (block_size + keyblock_len < BLOCK_PAD) + block_size = BLOCK_PAD - keyblock_len; + h = (struct vb2_kernel_preamble *)calloc(block_size, 1); + if (!h) { + perror("calloc"); + return NULL; + } + + /* Sign the body, place the signature in the preamble */ + ret = sign(kblob, kblob_len, &h->body_signature, h + 1); + if (ret) { + fprintf(stderr, "sign() failed: %d\n", ret); + return NULL; + } + + h->header_version_major = 2; + h->header_version_minor = 2; + h->preamble_size = block_size; + h->kernel_version = 1; + h->body_load_address = 0x100000; + /* + * "Bootloder" area (currently empty) is after kernel + config + + * parameter page. + */ + h->bootloader_address = h->body_load_address + + ROUNDUP(kernel_len) + + ROUNDUP(config_len) + + ALIGN; + h->bootloader_size = 0x1000; + h->vmlinuz_header_address = 0; + h->vmlinuz_header_size = 0; + h->flags = 0; + + ret = sign(h, signed_size, &h->preamble_signature, + (void *)(h + 1) + SIG_SIZE); + if (ret) { + fprintf(stderr, "failed to sign preamble: %d\n", ret); + return NULL; + } + return h; +} + + +/* + * Distilled from vboot_reference futility/cmd_vbutil_kernel.c pack command. + * + * NB: "config" is the kernel cmdline + */ +static int vbutil_pack(const char *kernel, size_t kernel_len, + const char *config, size_t config_len, + void **out, size_t *out_len) +{ + int ret; + size_t kblob_len = ROUNDUP(kernel_len) + ROUNDUP(config_len) + ALIGN + ALIGN; + void *kblob = malloc(kblob_len); + if (!kblob) { + perror("malloc"); + return -1; + } + void *kp = kblob; + memset(kblob, 0, kblob_len); + + /* Kernel */ + memcpy(kp, kernel, kernel_len); + kp += ROUNDUP(kernel_len); + + /* Kernel command line */ + memcpy(kp, config, config_len); + kp += ROUNDUP(config_len); + + /* "Parameters" -- empty, 4K-aligned */ + /* "Bootloader" region -- empty, 4K-aligned */ + /* Vmlinuz header -- only for x86 (not currently supported), empty */ + + struct vb2_kernel_preamble *h; + h = generate_preamble(kblob, kblob_len, kernel_len, config_len); + if (!h) { + fprintf(stderr, "Failed to generate preamble\n"); + return -1; + } + size_t outlen = sizeof(keyblock) + h->preamble_size + kblob_len; + void *outbuf = malloc(outlen); + if (!outbuf) + return -1; + + void *p = outbuf; + memcpy(p, keyblock, sizeof(keyblock)); + p += sizeof(keyblock); + + memcpy(p, h, h->preamble_size); + p += h->preamble_size; + + memcpy(p, kblob, kblob_len); + p += kblob_len; + + if (outbuf) { + *out = outbuf; + *out_len = outlen; + } + + return 0; +} + +static void * read_file(const char *path, size_t *out_len) +{ + struct stat st; + int fd = open(path, O_RDONLY); + if (fd == -1) { + perror("failed to open"); + return NULL; + } + + if (fstat(fd, &st) < 0) { + perror("fstat"); + return NULL; + } + + size_t len = st.st_size; + void *p = malloc(len); + if (!p) + return NULL; + + size_t count = 0; + while (count < len) { + ssize_t ret = read(fd, p + count, len - count); + if (ret < 0) { + perror("read"); + return NULL; + } + count += ret; + } + + close(fd); + + *out_len = len; + return p; +} + +int main(int argc, char * const argv[]) +{ + int i, ret; + const char *kernel_file = NULL; + const char *out_file = NULL; + const char *cmdline = NULL; + size_t cmdline_len; + void *kernel; + size_t kernel_len; + void *out; + size_t out_len; + + int opt; + while ((opt = getopt(argc, argv, "k:c:o:")) != -1) { + switch (opt) { + case 'k': + kernel_file = optarg; + break; + case 'c': + cmdline = optarg; + break; + case 'o': + out_file = optarg; + break; + default: + fprintf(stderr, "Usage [-k ] [-c ] -o \n"); + return -1; + } + } + if (optind < argc) { + fprintf(stderr, "Unexpected args?\n"); + return -1; + } + if (!out_file || !cmdline || !kernel_file) { + fprintf(stderr, "Missing required argument\n"); + return -1; + } + + /* Include the \0 terminator */ + cmdline_len = strlen(cmdline) + 1; + + kernel = read_file(kernel_file, &kernel_len); + if (!kernel) { + fprintf(stderr, "failed to read kernel file: %s\n", kernel_file); + return -1; + } + + ret = vbutil_pack(kernel, kernel_len, cmdline, cmdline_len, &out, &out_len); + if (ret) + return ret; + + int fd = open(out_file, O_RDWR|O_CREAT, 0644); + if (fd == -1) { + perror("open"); + return -1; + } + + ret = write(fd, out, out_len); + if (ret == -1) { + perror("write"); + return -1; + } + close(fd); + + return 0; +}