diff --git a/Android.bp b/Android.bp index 203781899..bdc34d046 100644 --- a/Android.bp +++ b/Android.bp @@ -348,6 +348,7 @@ bootstrap_go_package { ], srcs: [ "apex/apex.go", + "apex/key.go", ], pluginFor: ["soong_build"], } diff --git a/apex/apex.go b/apex/apex.go index 68d9cb8db..619ac331a 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -75,6 +75,7 @@ var ( executableTag = dependencyTag{name: "executable"} javaLibTag = dependencyTag{name: "javaLib"} prebuiltTag = dependencyTag{name: "prebuilt"} + keyTag = dependencyTag{name: "key"} ) func init() { @@ -172,6 +173,9 @@ type apexBundleProperties struct { // List of prebuilt files that are embedded inside this APEX bundle Prebuilts []string + + // Name of the apex_key module that provides the private key to sign APEX + Key *string } type apexBundle struct { @@ -185,14 +189,6 @@ type apexBundle struct { } func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) { - // Native shared libs are added for all architectures of the device - // i.e., native_shared_lib_modules: ["libc"] adds both 64 and 32 variation - // of the module - arches := ctx.DeviceConfig().Arches() - if len(arches) == 0 { - panic("device build with no primary arch") - } - for _, arch := range ctx.MultiTargets() { // Use *FarVariation* to be able to depend on modules having // conflicting variations with this module. This is required since @@ -208,16 +204,21 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) { {Mutator: "arch", Variation: arch.String()}, {Mutator: "image", Variation: "core"}, }, executableTag, a.properties.Binaries...) - - ctx.AddFarVariationDependencies([]blueprint.Variation{ - {Mutator: "arch", Variation: "android_common"}, - }, javaLibTag, a.properties.Java_libs...) - - ctx.AddFarVariationDependencies([]blueprint.Variation{ - {Mutator: "arch", Variation: "android_common"}, - }, prebuiltTag, a.properties.Prebuilts...) } + ctx.AddFarVariationDependencies([]blueprint.Variation{ + {Mutator: "arch", Variation: "android_common"}, + }, javaLibTag, a.properties.Java_libs...) + + ctx.AddFarVariationDependencies([]blueprint.Variation{ + {Mutator: "arch", Variation: "android_common"}, + }, prebuiltTag, a.properties.Prebuilts...) + + if String(a.properties.Key) == "" { + ctx.ModuleErrorf("key is missing") + return + } + ctx.AddDependency(ctx.Module(), keyTag, String(a.properties.Key)) } func getCopyManifestForNativeLibrary(cc *cc.Module) (fileToCopy android.Path, dirInApex string) { @@ -259,34 +260,52 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { // files to copy -> dir in apex copyManifest := make(map[android.Path]string) + var keyFile android.Path + ctx.WalkDeps(func(child, parent android.Module) bool { if _, ok := parent.(*apexBundle); ok { // direct dependencies depTag := ctx.OtherModuleDependencyTag(child) + depName := ctx.OtherModuleName(child) switch depTag { case sharedLibTag: if cc, ok := child.(*cc.Module); ok { fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc) copyManifest[fileToCopy] = dirInApex return true + } else { + ctx.PropertyErrorf("native_shared_libs", "%q is not a cc_library or cc_library_shared module", depName) } case executableTag: if cc, ok := child.(*cc.Module); ok { fileToCopy, dirInApex := getCopyManifestForExecutable(cc) copyManifest[fileToCopy] = dirInApex return true + } else { + ctx.PropertyErrorf("binaries", "%q is not a cc_binary module", depName) } case javaLibTag: if java, ok := child.(*java.Library); ok { fileToCopy, dirInApex := getCopyManifestForJavaLibrary(java) copyManifest[fileToCopy] = dirInApex return true + } else { + ctx.PropertyErrorf("java_libs", "%q is not a java_library module", depName) } case prebuiltTag: if prebuilt, ok := child.(*android.PrebuiltEtc); ok { fileToCopy, dirInApex := getCopyManifestForPrebuiltEtc(prebuilt) copyManifest[fileToCopy] = dirInApex return true + } else { + ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName) + } + case keyTag: + if key, ok := child.(*apexKey); ok { + keyFile = key.private_key_file + return false + } else { + ctx.PropertyErrorf("key", "%q is not an apex_key module", depName) } } } else { @@ -330,8 +349,6 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "manifest.json")) fileContexts := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.File_contexts, "file_contexts")) - // TODO(b/114488804) make this customizable - key := android.PathForSource(ctx, "system/apex/apexer/testdata/testkey.pem") a.outputFile = android.PathForModuleOut(ctx, a.ModuleBase.Name()+apexSuffix) @@ -351,7 +368,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { copyCommands = append(copyCommands, "cp "+src.String()+" "+dest_path) } implicitInputs := append(android.Paths(nil), filesToCopy...) - implicitInputs = append(implicitInputs, cannedFsConfig, manifest, fileContexts, key) + implicitInputs = append(implicitInputs, cannedFsConfig, manifest, fileContexts, keyFile) outHostBinDir := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "bin").String() prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin") ctx.ModuleBuild(pctx, android.ModuleBuildParams{ @@ -365,7 +382,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { "manifest": manifest.String(), "file_contexts": fileContexts.String(), "canned_fs_config": cannedFsConfig.String(), - "key": key.String(), + "key": keyFile.String(), }, }) @@ -382,6 +399,7 @@ func (a *apexBundle) AndroidMk() android.AndroidMkData { fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", a.outputFile.String()) fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(OUT_DIR)", a.installDir.RelPathString())) fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", name+apexSuffix) + fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", String(a.properties.Key)) fmt.Fprintln(w, "include $(BUILD_PREBUILT)") }} } diff --git a/apex/key.go b/apex/key.go new file mode 100644 index 000000000..ff348a844 --- /dev/null +++ b/apex/key.go @@ -0,0 +1,88 @@ +// Copyright (C) 2018 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package apex + +import ( + "fmt" + "io" + + "android/soong/android" + "github.com/google/blueprint/proptools" +) + +var String = proptools.String + +func init() { + android.RegisterModuleType("apex_key", apexKeyFactory) +} + +type apexKey struct { + android.ModuleBase + + properties apexKeyProperties + + public_key_file android.Path + private_key_file android.Path + + keyName string +} + +type apexKeyProperties struct { + // Path to the public key file in avbpubkey format. Installed to the device. + // Base name of the file is used as the ID for the key. + Public_key *string + // Path to the private key file in pem format. Used to sign APEXs. + Private_key *string +} + +func apexKeyFactory() android.Module { + module := &apexKey{} + module.AddProperties(&module.properties) + android.InitAndroidModule(module) + return module +} + +func (m *apexKey) DepsMutator(ctx android.BottomUpMutatorContext) { +} + +func (m *apexKey) GenerateAndroidBuildActions(ctx android.ModuleContext) { + m.public_key_file = android.PathForModuleSrc(ctx, String(m.properties.Public_key)) + m.private_key_file = android.PathForModuleSrc(ctx, String(m.properties.Private_key)) + + pubKeyName := m.public_key_file.Base()[0 : len(m.public_key_file.Base())-len(m.public_key_file.Ext())] + privKeyName := m.private_key_file.Base()[0 : len(m.private_key_file.Base())-len(m.private_key_file.Ext())] + + if pubKeyName != privKeyName { + ctx.ModuleErrorf("public_key %q (keyname:%q) and private_key %q (keyname:%q) do not have same keyname", + m.public_key_file.String(), pubKeyName, m.private_key_file, privKeyName) + return + } + m.keyName = pubKeyName + + ctx.InstallFile(android.PathForModuleInstall(ctx, "etc/security/apex"), m.keyName, m.public_key_file) +} + +func (m *apexKey) AndroidMk() android.AndroidMkData { + return android.AndroidMkData{ + Class: "ETC", + OutputFile: android.OptionalPathForPath(m.public_key_file), + Extra: []android.AndroidMkExtraFunc{ + func(w io.Writer, outputFile android.Path) { + fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", "$(TARGET_OUT)/etc/security/apex") + fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", m.keyName) + }, + }, + } +}