Merge "APEX can be signed with different keys"
This commit is contained in:
@@ -348,6 +348,7 @@ bootstrap_go_package {
|
|||||||
],
|
],
|
||||||
srcs: [
|
srcs: [
|
||||||
"apex/apex.go",
|
"apex/apex.go",
|
||||||
|
"apex/key.go",
|
||||||
],
|
],
|
||||||
pluginFor: ["soong_build"],
|
pluginFor: ["soong_build"],
|
||||||
}
|
}
|
||||||
|
58
apex/apex.go
58
apex/apex.go
@@ -75,6 +75,7 @@ var (
|
|||||||
executableTag = dependencyTag{name: "executable"}
|
executableTag = dependencyTag{name: "executable"}
|
||||||
javaLibTag = dependencyTag{name: "javaLib"}
|
javaLibTag = dependencyTag{name: "javaLib"}
|
||||||
prebuiltTag = dependencyTag{name: "prebuilt"}
|
prebuiltTag = dependencyTag{name: "prebuilt"}
|
||||||
|
keyTag = dependencyTag{name: "key"}
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -172,6 +173,9 @@ type apexBundleProperties struct {
|
|||||||
|
|
||||||
// List of prebuilt files that are embedded inside this APEX bundle
|
// List of prebuilt files that are embedded inside this APEX bundle
|
||||||
Prebuilts []string
|
Prebuilts []string
|
||||||
|
|
||||||
|
// Name of the apex_key module that provides the private key to sign APEX
|
||||||
|
Key *string
|
||||||
}
|
}
|
||||||
|
|
||||||
type apexBundle struct {
|
type apexBundle struct {
|
||||||
@@ -185,14 +189,6 @@ type apexBundle struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
|
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() {
|
for _, arch := range ctx.MultiTargets() {
|
||||||
// Use *FarVariation* to be able to depend on modules having
|
// Use *FarVariation* to be able to depend on modules having
|
||||||
// conflicting variations with this module. This is required since
|
// 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: "arch", Variation: arch.String()},
|
||||||
{Mutator: "image", Variation: "core"},
|
{Mutator: "image", Variation: "core"},
|
||||||
}, executableTag, a.properties.Binaries...)
|
}, 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) {
|
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
|
// files to copy -> dir in apex
|
||||||
copyManifest := make(map[android.Path]string)
|
copyManifest := make(map[android.Path]string)
|
||||||
|
|
||||||
|
var keyFile android.Path
|
||||||
|
|
||||||
ctx.WalkDeps(func(child, parent android.Module) bool {
|
ctx.WalkDeps(func(child, parent android.Module) bool {
|
||||||
if _, ok := parent.(*apexBundle); ok {
|
if _, ok := parent.(*apexBundle); ok {
|
||||||
// direct dependencies
|
// direct dependencies
|
||||||
depTag := ctx.OtherModuleDependencyTag(child)
|
depTag := ctx.OtherModuleDependencyTag(child)
|
||||||
|
depName := ctx.OtherModuleName(child)
|
||||||
switch depTag {
|
switch depTag {
|
||||||
case sharedLibTag:
|
case sharedLibTag:
|
||||||
if cc, ok := child.(*cc.Module); ok {
|
if cc, ok := child.(*cc.Module); ok {
|
||||||
fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc)
|
fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc)
|
||||||
copyManifest[fileToCopy] = dirInApex
|
copyManifest[fileToCopy] = dirInApex
|
||||||
return true
|
return true
|
||||||
|
} else {
|
||||||
|
ctx.PropertyErrorf("native_shared_libs", "%q is not a cc_library or cc_library_shared module", depName)
|
||||||
}
|
}
|
||||||
case executableTag:
|
case executableTag:
|
||||||
if cc, ok := child.(*cc.Module); ok {
|
if cc, ok := child.(*cc.Module); ok {
|
||||||
fileToCopy, dirInApex := getCopyManifestForExecutable(cc)
|
fileToCopy, dirInApex := getCopyManifestForExecutable(cc)
|
||||||
copyManifest[fileToCopy] = dirInApex
|
copyManifest[fileToCopy] = dirInApex
|
||||||
return true
|
return true
|
||||||
|
} else {
|
||||||
|
ctx.PropertyErrorf("binaries", "%q is not a cc_binary module", depName)
|
||||||
}
|
}
|
||||||
case javaLibTag:
|
case javaLibTag:
|
||||||
if java, ok := child.(*java.Library); ok {
|
if java, ok := child.(*java.Library); ok {
|
||||||
fileToCopy, dirInApex := getCopyManifestForJavaLibrary(java)
|
fileToCopy, dirInApex := getCopyManifestForJavaLibrary(java)
|
||||||
copyManifest[fileToCopy] = dirInApex
|
copyManifest[fileToCopy] = dirInApex
|
||||||
return true
|
return true
|
||||||
|
} else {
|
||||||
|
ctx.PropertyErrorf("java_libs", "%q is not a java_library module", depName)
|
||||||
}
|
}
|
||||||
case prebuiltTag:
|
case prebuiltTag:
|
||||||
if prebuilt, ok := child.(*android.PrebuiltEtc); ok {
|
if prebuilt, ok := child.(*android.PrebuiltEtc); ok {
|
||||||
fileToCopy, dirInApex := getCopyManifestForPrebuiltEtc(prebuilt)
|
fileToCopy, dirInApex := getCopyManifestForPrebuiltEtc(prebuilt)
|
||||||
copyManifest[fileToCopy] = dirInApex
|
copyManifest[fileToCopy] = dirInApex
|
||||||
return true
|
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 {
|
} else {
|
||||||
@@ -330,8 +349,6 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||||||
|
|
||||||
manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "manifest.json"))
|
manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "manifest.json"))
|
||||||
fileContexts := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.File_contexts, "file_contexts"))
|
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)
|
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)
|
copyCommands = append(copyCommands, "cp "+src.String()+" "+dest_path)
|
||||||
}
|
}
|
||||||
implicitInputs := append(android.Paths(nil), filesToCopy...)
|
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()
|
outHostBinDir := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "bin").String()
|
||||||
prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin")
|
prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin")
|
||||||
ctx.ModuleBuild(pctx, android.ModuleBuildParams{
|
ctx.ModuleBuild(pctx, android.ModuleBuildParams{
|
||||||
@@ -365,7 +382,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||||||
"manifest": manifest.String(),
|
"manifest": manifest.String(),
|
||||||
"file_contexts": fileContexts.String(),
|
"file_contexts": fileContexts.String(),
|
||||||
"canned_fs_config": cannedFsConfig.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_PREBUILT_MODULE_FILE :=", a.outputFile.String())
|
||||||
fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(OUT_DIR)", a.installDir.RelPathString()))
|
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_INSTALLED_MODULE_STEM :=", name+apexSuffix)
|
||||||
|
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", String(a.properties.Key))
|
||||||
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
|
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
88
apex/key.go
Normal file
88
apex/key.go
Normal file
@@ -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)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user