blob: d7bb654b9b18ec09d2bcd8e744f6fec0225cc6af [file] [log] [blame]
Inseob Kim53391842024-03-29 17:44:07 +09001// Copyright (C) 2024 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package filesystem
16
17import (
18 "path/filepath"
19 "strings"
20
21 "android/soong/android"
22)
23
24type fsverityProperties struct {
25 // Patterns of files for fsverity metadata generation. For each matched file, a .fsv_meta file
26 // will be generated and included to the filesystem image.
27 // etc/security/fsverity/BuildManifest.apk will also be generated which contains information
28 // about generated .fsv_meta files.
29 Inputs []string
Inseob Kim1e6afed2024-04-03 17:24:54 +090030
31 // APK libraries to link against, for etc/security/fsverity/BuildManifest.apk
32 Libs []string `android:"path"`
Inseob Kim53391842024-03-29 17:44:07 +090033}
34
35func (f *filesystem) writeManifestGeneratorListFile(ctx android.ModuleContext, outputPath android.OutputPath, matchedSpecs []android.PackagingSpec, rebasedDir android.OutputPath) {
36 var buf strings.Builder
37 for _, spec := range matchedSpecs {
38 buf.WriteString(rebasedDir.Join(ctx, spec.RelPathInPackage()).String())
39 buf.WriteRune('\n')
40 }
41 android.WriteFileRuleVerbatim(ctx, outputPath, buf.String())
42}
43
44func (f *filesystem) buildFsverityMetadataFiles(ctx android.ModuleContext, builder *android.RuleBuilder, specs map[string]android.PackagingSpec, rootDir android.OutputPath, rebasedDir android.OutputPath) {
45 match := func(path string) bool {
46 for _, pattern := range f.properties.Fsverity.Inputs {
47 if matched, err := filepath.Match(pattern, path); matched {
48 return true
49 } else if err != nil {
50 ctx.PropertyErrorf("fsverity.inputs", "bad pattern %q", pattern)
51 return false
52 }
53 }
54 return false
55 }
56
57 var matchedSpecs []android.PackagingSpec
58 for _, relPath := range android.SortedKeys(specs) {
59 if match(relPath) {
60 matchedSpecs = append(matchedSpecs, specs[relPath])
61 }
62 }
63
64 if len(matchedSpecs) == 0 {
65 return
66 }
67
68 fsverityBuilderPath := android.PathForModuleOut(ctx, "fsverity_builder.sh")
69 metadataGeneratorPath := ctx.Config().HostToolPath(ctx, "fsverity_metadata_generator")
70 fsverityPath := ctx.Config().HostToolPath(ctx, "fsverity")
71
72 cmd := builder.Command().Tool(fsverityBuilderPath)
73
74 // STEP 1: generate .fsv_meta
75 var sb strings.Builder
76 sb.WriteString("set -e\n")
77 cmd.Implicit(metadataGeneratorPath).Implicit(fsverityPath)
78 for _, spec := range matchedSpecs {
79 // srcPath is copied by CopySpecsToDir()
80 srcPath := rebasedDir.Join(ctx, spec.RelPathInPackage())
81 destPath := rebasedDir.Join(ctx, spec.RelPathInPackage()+".fsv_meta")
82 sb.WriteString(metadataGeneratorPath.String())
83 sb.WriteString(" --fsverity-path ")
84 sb.WriteString(fsverityPath.String())
85 sb.WriteString(" --signature none --hash-alg sha256 --output ")
86 sb.WriteString(destPath.String())
87 sb.WriteRune(' ')
88 sb.WriteString(srcPath.String())
89 sb.WriteRune('\n')
Kiyoung Kim99a954d2024-06-21 14:22:20 +090090 f.appendToEntry(ctx, destPath)
Inseob Kim53391842024-03-29 17:44:07 +090091 }
92
93 // STEP 2: generate signed BuildManifest.apk
94 // STEP 2-1: generate build_manifest.pb
95 assetsPath := android.PathForModuleOut(ctx, "fsverity_manifest/assets")
96 manifestPbPath := assetsPath.Join(ctx, "build_manifest.pb")
97 manifestGeneratorPath := ctx.Config().HostToolPath(ctx, "fsverity_manifest_generator")
98 cmd.Implicit(manifestGeneratorPath)
99 sb.WriteString("rm -rf ")
100 sb.WriteString(assetsPath.String())
101 sb.WriteString(" && mkdir -p ")
102 sb.WriteString(assetsPath.String())
103 sb.WriteRune('\n')
104 sb.WriteString(manifestGeneratorPath.String())
105 sb.WriteString(" --fsverity-path ")
106 sb.WriteString(fsverityPath.String())
107 sb.WriteString(" --base-dir ")
108 sb.WriteString(rootDir.String())
109 sb.WriteString(" --output ")
110 sb.WriteString(manifestPbPath.String())
111 sb.WriteRune(' ')
Kiyoung Kim99a954d2024-06-21 14:22:20 +0900112 f.appendToEntry(ctx, manifestPbPath)
Inseob Kim53391842024-03-29 17:44:07 +0900113
114 manifestGeneratorListPath := android.PathForModuleOut(ctx, "fsverity_manifest.list")
115 f.writeManifestGeneratorListFile(ctx, manifestGeneratorListPath.OutputPath, matchedSpecs, rebasedDir)
116 sb.WriteRune('@')
117 sb.WriteString(manifestGeneratorListPath.String())
118 sb.WriteRune('\n')
119 cmd.Implicit(manifestGeneratorListPath)
Kiyoung Kim99a954d2024-06-21 14:22:20 +0900120 f.appendToEntry(ctx, manifestGeneratorListPath.OutputPath)
Inseob Kim53391842024-03-29 17:44:07 +0900121
122 // STEP 2-2: generate BuildManifest.apk (unsigned)
123 aapt2Path := ctx.Config().HostToolPath(ctx, "aapt2")
124 apkPath := rebasedDir.Join(ctx, "etc", "security", "fsverity", "BuildManifest.apk")
Kiyoung Kim99a954d2024-06-21 14:22:20 +0900125 idsigPath := rebasedDir.Join(ctx, "etc", "security", "fsverity", "BuildManifest.apk.idsig")
Inseob Kim53391842024-03-29 17:44:07 +0900126 manifestTemplatePath := android.PathForSource(ctx, "system/security/fsverity/AndroidManifest.xml")
Inseob Kim1e6afed2024-04-03 17:24:54 +0900127 libs := android.PathsForModuleSrc(ctx, f.properties.Fsverity.Libs)
Inseob Kim53391842024-03-29 17:44:07 +0900128 cmd.Implicit(aapt2Path)
129 cmd.Implicit(manifestTemplatePath)
Inseob Kim1e6afed2024-04-03 17:24:54 +0900130 cmd.Implicits(libs)
Kiyoung Kim99a954d2024-06-21 14:22:20 +0900131 cmd.ImplicitOutput(apkPath)
Inseob Kim53391842024-03-29 17:44:07 +0900132
133 sb.WriteString(aapt2Path.String())
134 sb.WriteString(" link -o ")
135 sb.WriteString(apkPath.String())
136 sb.WriteString(" -A ")
137 sb.WriteString(assetsPath.String())
Inseob Kim1e6afed2024-04-03 17:24:54 +0900138 for _, lib := range libs {
139 sb.WriteString(" -I ")
140 sb.WriteString(lib.String())
141 }
Inseob Kim53391842024-03-29 17:44:07 +0900142 minSdkVersion := ctx.Config().PlatformSdkCodename()
143 if minSdkVersion == "REL" {
144 minSdkVersion = ctx.Config().PlatformSdkVersion().String()
145 }
146 sb.WriteString(" --min-sdk-version ")
147 sb.WriteString(minSdkVersion)
148 sb.WriteString(" --version-code ")
149 sb.WriteString(ctx.Config().PlatformSdkVersion().String())
150 sb.WriteString(" --version-name ")
151 sb.WriteString(ctx.Config().AppsDefaultVersionName())
152 sb.WriteString(" --manifest ")
153 sb.WriteString(manifestTemplatePath.String())
154 sb.WriteString(" --rename-manifest-package com.android.security.fsverity_metadata.")
155 sb.WriteString(f.partitionName())
156 sb.WriteRune('\n')
157
Kiyoung Kim99a954d2024-06-21 14:22:20 +0900158 f.appendToEntry(ctx, apkPath)
159
Inseob Kim53391842024-03-29 17:44:07 +0900160 // STEP 2-3: sign BuildManifest.apk
161 apksignerPath := ctx.Config().HostToolPath(ctx, "apksigner")
162 pemPath, keyPath := ctx.Config().DefaultAppCertificate(ctx)
163 cmd.Implicit(apksignerPath)
164 cmd.Implicit(pemPath)
165 cmd.Implicit(keyPath)
Kiyoung Kim99a954d2024-06-21 14:22:20 +0900166 cmd.ImplicitOutput(idsigPath)
Inseob Kim53391842024-03-29 17:44:07 +0900167 sb.WriteString(apksignerPath.String())
168 sb.WriteString(" sign --in ")
169 sb.WriteString(apkPath.String())
170 sb.WriteString(" --cert ")
171 sb.WriteString(pemPath.String())
172 sb.WriteString(" --key ")
173 sb.WriteString(keyPath.String())
174 sb.WriteRune('\n')
175
Kiyoung Kim99a954d2024-06-21 14:22:20 +0900176 f.appendToEntry(ctx, idsigPath)
177
Inseob Kim53391842024-03-29 17:44:07 +0900178 android.WriteExecutableFileRuleVerbatim(ctx, fsverityBuilderPath, sb.String())
179}