osbase/build/mkverity: generate salt from product info
The salt is now generated from the product info file, instead of the
input image file. This reduces build time by around 0.3 s.
Change-Id: Id3263e24604745324a5652658ff79cc79c9df5fa
Reviewed-on: https://review.monogon.dev/c/monogon/+/4431
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/node/BUILD.bazel b/metropolis/node/BUILD.bazel
index fd6dbcc..bdf7d8c 100644
--- a/metropolis/node/BUILD.bazel
+++ b/metropolis/node/BUILD.bazel
@@ -117,6 +117,7 @@
verity_image(
name = "verity_rootfs",
+ salt = ":product_info",
source = ":rootfs",
)
diff --git a/osbase/build/mkverity/def.bzl b/osbase/build/mkverity/def.bzl
index 417c883..1176060 100644
--- a/osbase/build/mkverity/def.bzl
+++ b/osbase/build/mkverity/def.bzl
@@ -17,22 +17,23 @@
# Run mkverity.
image = ctx.actions.declare_file(ctx.attr.name + ".img")
table = ctx.actions.declare_file(ctx.attr.name + ".dmt")
+ inputs = [ctx.file.source]
+ args = ctx.actions.args()
+ args.add("-input", ctx.file.source)
+ args.add("-output", image)
+ if ctx.file.salt:
+ args.add("-salt", ctx.file.salt)
+ inputs.append(ctx.file.salt)
+ args.add("-table", table)
+ args.add("-data_alias", ctx.attr.rootfs_partlabel)
+ args.add("-hash_alias", ctx.attr.rootfs_partlabel)
ctx.actions.run(
mnemonic = "GenVerityImage",
progress_message = "Generating a dm-verity image: {}".format(image.short_path),
- inputs = [ctx.file.source],
- outputs = [
- image,
- table,
- ],
+ inputs = inputs,
+ outputs = [image, table],
executable = ctx.file._mkverity,
- arguments = [
- "-input=" + ctx.file.source.path,
- "-output=" + image.path,
- "-table=" + table.path,
- "-data_alias=" + ctx.attr.rootfs_partlabel,
- "-hash_alias=" + ctx.attr.rootfs_partlabel,
- ],
+ arguments = [args],
)
return [
@@ -56,6 +57,16 @@
"source": attr.label(
doc = "A source image.",
allow_single_file = True,
+ mandatory = True,
+ ),
+ "salt": attr.label(
+ doc = """
+ A file which will be hashed to generate the salt.
+ This should be a small file which is different for each
+ released image, but which only changes when the source also
+ changes. The product info file is a good choice for this.
+ """,
+ allow_single_file = True,
),
"rootfs_partlabel": attr.string(
doc = "GPT partition label of the rootfs to be used with dm-mod.create.",
diff --git a/osbase/build/mkverity/mkverity.go b/osbase/build/mkverity/mkverity.go
index f75845d..55de7dd 100644
--- a/osbase/build/mkverity/mkverity.go
+++ b/osbase/build/mkverity/mkverity.go
@@ -26,7 +26,7 @@
// image. Then, the same contents are verity-encoded and appended to the
// output image. The verity superblock is written only if wsb is true. It
// returns either a dm-verity target table, or an error.
-func createImage(dataImagePath, outputImagePath string, wsb bool) (*verity.MappingTable, error) {
+func createImage(dataImagePath, outputImagePath, saltPath string, wsb bool) (*verity.MappingTable, error) {
// Hardcode both the data block size and the hash block size as 4096 bytes.
bs := uint32(4096)
@@ -66,20 +66,20 @@
return nil, err
}
- // Hash the input data for use as the salt, then rewind dataImage. The purpose
- // of the salt is to prevent reuse of collisions across different images. 16
- // bytes is enough for this. We use a hash of the input instead of generating
- // random bytes to make the build reproducible.
- dataHash := sha256.New()
- _, err = io.Copy(dataHash, dataImage)
+ // Generate the salt by hashing the salt file. The purpose of the salt is to
+ // prevent reuse of collisions across different images. 16 bytes is enough for
+ // this. We use a hash instead of generating random bytes to make the build
+ // reproducible.
+ saltFile, err := os.Open(saltPath)
+ if err != nil {
+ return nil, fmt.Errorf("while opening the salt file: %w", err)
+ }
+ saltHash := sha256.New()
+ _, err = io.Copy(saltHash, saltFile)
if err != nil {
return nil, err
}
- _, err = dataImage.Seek(0, io.SeekStart)
- if err != nil {
- return nil, err
- }
- salt := dataHash.Sum(nil)[:16]
+ salt := saltHash.Sum(nil)[:16]
// Write outputImage contents. Start with initializing a verity encoder,
// setting outputImage as its output.
@@ -112,6 +112,7 @@
var (
input = flag.String("input", "", "input disk image (required)")
output = flag.String("output", "", "output disk image with Verity metadata appended (required)")
+ salt = flag.String("salt", "", "input file from which the salt is generated")
dataDeviceAlias = flag.String("data_alias", "", "data device alias used in the mapping table")
hashDeviceAlias = flag.String("hash_alias", "", "hash device alias used in the mapping table")
table = flag.String("table", "", "a file the mapping table will be saved to; disables stdout")
@@ -128,8 +129,13 @@
log.Fatalf("-output must be set.")
}
+ saltPath := *salt
+ if saltPath == "" {
+ saltPath = *input
+ }
+
// Build the image.
- mt, err := createImage(*input, *output, false)
+ mt, err := createImage(*input, *output, saltPath, false)
if err != nil {
log.Fatal(err)
}