1*333d2b36SAndroid Build Coastguard Worker// Copyright (C) 2024 The Android Open Source Project 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage filesystem 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "fmt" 19*333d2b36SAndroid Build Coastguard Worker "path/filepath" 20*333d2b36SAndroid Build Coastguard Worker "strings" 21*333d2b36SAndroid Build Coastguard Worker 22*333d2b36SAndroid Build Coastguard Worker "android/soong/android" 23*333d2b36SAndroid Build Coastguard Worker) 24*333d2b36SAndroid Build Coastguard Worker 25*333d2b36SAndroid Build Coastguard Workertype fsverityProperties struct { 26*333d2b36SAndroid Build Coastguard Worker // Patterns of files for fsverity metadata generation. For each matched file, a .fsv_meta file 27*333d2b36SAndroid Build Coastguard Worker // will be generated and included to the filesystem image. 28*333d2b36SAndroid Build Coastguard Worker // etc/security/fsverity/BuildManifest.apk will also be generated which contains information 29*333d2b36SAndroid Build Coastguard Worker // about generated .fsv_meta files. 30*333d2b36SAndroid Build Coastguard Worker Inputs []string 31*333d2b36SAndroid Build Coastguard Worker 32*333d2b36SAndroid Build Coastguard Worker // APK libraries to link against, for etc/security/fsverity/BuildManifest.apk 33*333d2b36SAndroid Build Coastguard Worker Libs []string `android:"path"` 34*333d2b36SAndroid Build Coastguard Worker} 35*333d2b36SAndroid Build Coastguard Worker 36*333d2b36SAndroid Build Coastguard Workerfunc (f *filesystem) writeManifestGeneratorListFile(ctx android.ModuleContext, outputPath android.WritablePath, matchedSpecs []android.PackagingSpec, rebasedDir android.OutputPath) { 37*333d2b36SAndroid Build Coastguard Worker var buf strings.Builder 38*333d2b36SAndroid Build Coastguard Worker for _, spec := range matchedSpecs { 39*333d2b36SAndroid Build Coastguard Worker buf.WriteString(rebasedDir.Join(ctx, spec.RelPathInPackage()).String()) 40*333d2b36SAndroid Build Coastguard Worker buf.WriteRune('\n') 41*333d2b36SAndroid Build Coastguard Worker } 42*333d2b36SAndroid Build Coastguard Worker android.WriteFileRuleVerbatim(ctx, outputPath, buf.String()) 43*333d2b36SAndroid Build Coastguard Worker} 44*333d2b36SAndroid Build Coastguard Worker 45*333d2b36SAndroid Build Coastguard Workerfunc (f *filesystem) buildFsverityMetadataFiles(ctx android.ModuleContext, builder *android.RuleBuilder, specs map[string]android.PackagingSpec, rootDir android.OutputPath, rebasedDir android.OutputPath) { 46*333d2b36SAndroid Build Coastguard Worker match := func(path string) bool { 47*333d2b36SAndroid Build Coastguard Worker for _, pattern := range f.properties.Fsverity.Inputs { 48*333d2b36SAndroid Build Coastguard Worker if matched, err := filepath.Match(pattern, path); matched { 49*333d2b36SAndroid Build Coastguard Worker return true 50*333d2b36SAndroid Build Coastguard Worker } else if err != nil { 51*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf("fsverity.inputs", "bad pattern %q", pattern) 52*333d2b36SAndroid Build Coastguard Worker return false 53*333d2b36SAndroid Build Coastguard Worker } 54*333d2b36SAndroid Build Coastguard Worker } 55*333d2b36SAndroid Build Coastguard Worker return false 56*333d2b36SAndroid Build Coastguard Worker } 57*333d2b36SAndroid Build Coastguard Worker 58*333d2b36SAndroid Build Coastguard Worker var matchedSpecs []android.PackagingSpec 59*333d2b36SAndroid Build Coastguard Worker for _, relPath := range android.SortedKeys(specs) { 60*333d2b36SAndroid Build Coastguard Worker if match(relPath) { 61*333d2b36SAndroid Build Coastguard Worker matchedSpecs = append(matchedSpecs, specs[relPath]) 62*333d2b36SAndroid Build Coastguard Worker } 63*333d2b36SAndroid Build Coastguard Worker } 64*333d2b36SAndroid Build Coastguard Worker 65*333d2b36SAndroid Build Coastguard Worker if len(matchedSpecs) == 0 { 66*333d2b36SAndroid Build Coastguard Worker return 67*333d2b36SAndroid Build Coastguard Worker } 68*333d2b36SAndroid Build Coastguard Worker 69*333d2b36SAndroid Build Coastguard Worker fsverityPath := ctx.Config().HostToolPath(ctx, "fsverity") 70*333d2b36SAndroid Build Coastguard Worker 71*333d2b36SAndroid Build Coastguard Worker // STEP 1: generate .fsv_meta 72*333d2b36SAndroid Build Coastguard Worker var sb strings.Builder 73*333d2b36SAndroid Build Coastguard Worker sb.WriteString("set -e\n") 74*333d2b36SAndroid Build Coastguard Worker for _, spec := range matchedSpecs { 75*333d2b36SAndroid Build Coastguard Worker // srcPath is copied by CopySpecsToDir() 76*333d2b36SAndroid Build Coastguard Worker srcPath := rebasedDir.Join(ctx, spec.RelPathInPackage()) 77*333d2b36SAndroid Build Coastguard Worker destPath := rebasedDir.Join(ctx, spec.RelPathInPackage()+".fsv_meta") 78*333d2b36SAndroid Build Coastguard Worker builder.Command(). 79*333d2b36SAndroid Build Coastguard Worker BuiltTool("fsverity_metadata_generator"). 80*333d2b36SAndroid Build Coastguard Worker FlagWithInput("--fsverity-path ", fsverityPath). 81*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--signature ", "none"). 82*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--hash-alg ", "sha256"). 83*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--output ", destPath.String()). 84*333d2b36SAndroid Build Coastguard Worker Text(srcPath.String()) 85*333d2b36SAndroid Build Coastguard Worker f.appendToEntry(ctx, destPath) 86*333d2b36SAndroid Build Coastguard Worker } 87*333d2b36SAndroid Build Coastguard Worker 88*333d2b36SAndroid Build Coastguard Worker // STEP 2: generate signed BuildManifest.apk 89*333d2b36SAndroid Build Coastguard Worker // STEP 2-1: generate build_manifest.pb 90*333d2b36SAndroid Build Coastguard Worker manifestGeneratorListPath := android.PathForModuleOut(ctx, "fsverity_manifest.list") 91*333d2b36SAndroid Build Coastguard Worker f.writeManifestGeneratorListFile(ctx, manifestGeneratorListPath, matchedSpecs, rebasedDir) 92*333d2b36SAndroid Build Coastguard Worker assetsPath := android.PathForModuleOut(ctx, "fsverity_manifest/assets") 93*333d2b36SAndroid Build Coastguard Worker manifestPbPath := assetsPath.Join(ctx, "build_manifest.pb") 94*333d2b36SAndroid Build Coastguard Worker builder.Command().Text("rm -rf " + assetsPath.String()) 95*333d2b36SAndroid Build Coastguard Worker builder.Command().Text("mkdir -p " + assetsPath.String()) 96*333d2b36SAndroid Build Coastguard Worker builder.Command(). 97*333d2b36SAndroid Build Coastguard Worker BuiltTool("fsverity_manifest_generator"). 98*333d2b36SAndroid Build Coastguard Worker FlagWithInput("--fsverity-path ", fsverityPath). 99*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--base-dir ", rootDir.String()). 100*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--output ", manifestPbPath.String()). 101*333d2b36SAndroid Build Coastguard Worker FlagWithInput("@", manifestGeneratorListPath) 102*333d2b36SAndroid Build Coastguard Worker 103*333d2b36SAndroid Build Coastguard Worker f.appendToEntry(ctx, manifestPbPath) 104*333d2b36SAndroid Build Coastguard Worker f.appendToEntry(ctx, manifestGeneratorListPath) 105*333d2b36SAndroid Build Coastguard Worker 106*333d2b36SAndroid Build Coastguard Worker // STEP 2-2: generate BuildManifest.apk (unsigned) 107*333d2b36SAndroid Build Coastguard Worker apkNameSuffix := "" 108*333d2b36SAndroid Build Coastguard Worker if f.PartitionType() == "system_ext" { 109*333d2b36SAndroid Build Coastguard Worker //https://source.corp.google.com/h/googleplex-android/platform/build/+/e392d2b486c2d4187b20a72b1c67cc737ecbcca5:core/Makefile;l=3410;drc=ea8f34bc1d6e63656b4ec32f2391e9d54b3ebb6b;bpv=1;bpt=0 110*333d2b36SAndroid Build Coastguard Worker apkNameSuffix = "SystemExt" 111*333d2b36SAndroid Build Coastguard Worker } 112*333d2b36SAndroid Build Coastguard Worker apkPath := rebasedDir.Join(ctx, "etc", "security", "fsverity", fmt.Sprintf("BuildManifest%s.apk", apkNameSuffix)) 113*333d2b36SAndroid Build Coastguard Worker idsigPath := rebasedDir.Join(ctx, "etc", "security", "fsverity", fmt.Sprintf("BuildManifest%s.apk.idsig", apkNameSuffix)) 114*333d2b36SAndroid Build Coastguard Worker manifestTemplatePath := android.PathForSource(ctx, "system/security/fsverity/AndroidManifest.xml") 115*333d2b36SAndroid Build Coastguard Worker libs := android.PathsForModuleSrc(ctx, f.properties.Fsverity.Libs) 116*333d2b36SAndroid Build Coastguard Worker 117*333d2b36SAndroid Build Coastguard Worker minSdkVersion := ctx.Config().PlatformSdkCodename() 118*333d2b36SAndroid Build Coastguard Worker if minSdkVersion == "REL" { 119*333d2b36SAndroid Build Coastguard Worker minSdkVersion = ctx.Config().PlatformSdkVersion().String() 120*333d2b36SAndroid Build Coastguard Worker } 121*333d2b36SAndroid Build Coastguard Worker 122*333d2b36SAndroid Build Coastguard Worker unsignedApkCommand := builder.Command(). 123*333d2b36SAndroid Build Coastguard Worker BuiltTool("aapt2"). 124*333d2b36SAndroid Build Coastguard Worker Text("link"). 125*333d2b36SAndroid Build Coastguard Worker FlagWithOutput("-o ", apkPath). 126*333d2b36SAndroid Build Coastguard Worker FlagWithArg("-A ", assetsPath.String()) 127*333d2b36SAndroid Build Coastguard Worker for _, lib := range libs { 128*333d2b36SAndroid Build Coastguard Worker unsignedApkCommand.FlagWithInput("-I ", lib) 129*333d2b36SAndroid Build Coastguard Worker } 130*333d2b36SAndroid Build Coastguard Worker unsignedApkCommand. 131*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--min-sdk-version ", minSdkVersion). 132*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--version-code ", ctx.Config().PlatformSdkVersion().String()). 133*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--version-name ", ctx.Config().AppsDefaultVersionName()). 134*333d2b36SAndroid Build Coastguard Worker FlagWithInput("--manifest ", manifestTemplatePath). 135*333d2b36SAndroid Build Coastguard Worker Text(" --rename-manifest-package com.android.security.fsverity_metadata." + f.partitionName()) 136*333d2b36SAndroid Build Coastguard Worker 137*333d2b36SAndroid Build Coastguard Worker f.appendToEntry(ctx, apkPath) 138*333d2b36SAndroid Build Coastguard Worker 139*333d2b36SAndroid Build Coastguard Worker // STEP 2-3: sign BuildManifest.apk 140*333d2b36SAndroid Build Coastguard Worker pemPath, keyPath := ctx.Config().DefaultAppCertificate(ctx) 141*333d2b36SAndroid Build Coastguard Worker builder.Command(). 142*333d2b36SAndroid Build Coastguard Worker BuiltTool("apksigner"). 143*333d2b36SAndroid Build Coastguard Worker Text("sign"). 144*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--in ", apkPath.String()). 145*333d2b36SAndroid Build Coastguard Worker FlagWithInput("--cert ", pemPath). 146*333d2b36SAndroid Build Coastguard Worker FlagWithInput("--key ", keyPath). 147*333d2b36SAndroid Build Coastguard Worker ImplicitOutput(idsigPath) 148*333d2b36SAndroid Build Coastguard Worker 149*333d2b36SAndroid Build Coastguard Worker f.appendToEntry(ctx, idsigPath) 150*333d2b36SAndroid Build Coastguard Worker} 151