APEXes can be signed with devkeys
When PRODUCT_DEFAULT_DEV_CERTIFICATE is set to /vendor/foo/devkeys/test,
then the public/private key pairs for an apex_key is searched at
/vendor/foo/devkeys directory.
To be specific,
/system/timezone/Android.bp:
apex_key {
name: "timezone.key",
public_key: "com.android.tzdata.avbpubkey",
private_key: "com.android.tzdata.pem",
}
When PRODUCT_DEFAULT_DEV_CERTIFICATE isn't set, the keys are searched at
/system/timezone, which is the path where Android.bp is located.
With PRODUCT_DEFAULT_DEV_CERTIFICATE set to /vendor/foo/devkeys/test,
the keys are searched at /vendor/foo/devkeys.
Bug: 121224311
Test: m (apex_test updated)
Test: m with crosshatch (PRODUCT_DEFAULT_DEV_CERTIFICATE is set to
/vendor/google/...)
Test: m with cheets (PRODUCT_DEFAULT_DEV_CERTIFICATE is set, but there
is no apex key there. The product is with TARGET_FLATTEN_APEX := true)
Change-Id: I213bbb96c433d851f9cc982871459fd7fb4fe47d
diff --git a/android/config.go b/android/config.go
index 65c58ac..38f6ec8 100644
--- a/android/config.go
+++ b/android/config.go
@@ -561,6 +561,19 @@
}
}
+func (c *config) ApexKeyDir(ctx ModuleContext) SourcePath {
+ // TODO(b/121224311): define another variable such as TARGET_APEX_KEY_OVERRIDE
+ defaultCert := String(c.productVariables.DefaultAppCertificate)
+ if defaultCert == "" || filepath.Dir(defaultCert) == "build/target/product/security" {
+ // When defaultCert is unset or is set to the testkeys path, use the APEX keys
+ // that is under the module dir
+ return PathForModuleSrc(ctx).SourcePath
+ } else {
+ // If not, APEX keys are under the specified directory
+ return PathForSource(ctx, filepath.Dir(defaultCert))
+ }
+}
+
func (c *config) AllowMissingDependencies() bool {
return Bool(c.productVariables.Allow_missing_dependencies)
}
diff --git a/apex/apex.go b/apex/apex.go
index 9f5a46c..e711c8b 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -448,15 +448,17 @@
{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))
+ if !ctx.Config().FlattenApex() || ctx.Config().UnbundledBuild() {
+ if String(a.properties.Key) == "" {
+ ctx.ModuleErrorf("key is missing")
+ return
+ }
+ ctx.AddDependency(ctx.Module(), keyTag, String(a.properties.Key))
- cert := android.SrcIsModule(String(a.properties.Certificate))
- if cert != "" {
- ctx.AddDependency(ctx.Module(), certificateTag, cert)
+ cert := android.SrcIsModule(String(a.properties.Certificate))
+ if cert != "" {
+ ctx.AddDependency(ctx.Module(), certificateTag, cert)
+ }
}
}
@@ -626,7 +628,8 @@
return false
})
- if keyFile == nil {
+ a.flattened = ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild()
+ if !a.flattened && keyFile == nil {
ctx.PropertyErrorf("key", "private_key for %q could not be found", String(a.properties.Key))
return
}
@@ -656,7 +659,6 @@
filesInfo[i].moduleName = ctx.ModuleName() + "." + filesInfo[i].moduleName
}
- a.flattened = ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild()
a.installDir = android.PathForModuleInstall(ctx, "apex")
a.filesInfo = filesInfo
diff --git a/apex/apex_test.go b/apex/apex_test.go
index d4f0f7e..dbc85d9 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -124,13 +124,15 @@
ctx.MockFileSystem(map[string][]byte{
"Android.bp": []byte(bp),
- "testkey.avbpubkey": nil,
- "testkey.pem": nil,
"build/target/product/security": nil,
"apex_manifest.json": nil,
"system/sepolicy/apex/myapex-file_contexts": nil,
"mylib.cpp": nil,
"myprebuilt": nil,
+ "vendor/foo/devkeys/test.x509.pem": nil,
+ "vendor/foo/devkeys/test.pk8": nil,
+ "vendor/foo/devkeys/testkey.avbpubkey": nil,
+ "vendor/foo/devkeys/testkey.pem": nil,
})
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
android.FailIfErrored(t, errs)
@@ -148,6 +150,7 @@
config = android.TestArchConfig(buildDir, nil)
config.TestProductVariables.DeviceVndkVersion = proptools.StringPtr("current")
+ config.TestProductVariables.DefaultAppCertificate = proptools.StringPtr("vendor/foo/devkeys/test")
return
}
@@ -683,3 +686,46 @@
// Ensure that not_in_apex is linking with the static variant of mylib
ensureContains(t, ldFlags, "mylib/android_arm64_armv8-a_core_static/mylib.a")
}
+
+func TestKeys(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["mylib"],
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ `)
+
+ // check the APEX keys
+ keys := ctx.ModuleForTests("myapex.key", "").Module().(*apexKey)
+
+ if keys.public_key_file.String() != "vendor/foo/devkeys/testkey.avbpubkey" {
+ t.Errorf("public key %q is not %q", keys.public_key_file.String(),
+ "vendor/foo/devkeys/testkey.avbpubkey")
+ }
+ if keys.private_key_file.String() != "vendor/foo/devkeys/testkey.pem" {
+ t.Errorf("private key %q is not %q", keys.private_key_file.String(),
+ "vendor/foo/devkeys/testkey.pem")
+ }
+
+ // check the APK certs
+ certs := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("signapk").Args["certificates"]
+ if certs != "vendor/foo/devkeys/test.x509.pem vendor/foo/devkeys/test.pk8" {
+ t.Errorf("cert and private key %q are not %q", certs,
+ "vendor/foo/devkeys/test.x509.pem vendor/foo/devkeys/test.pk8")
+ }
+}
diff --git a/apex/key.go b/apex/key.go
index 6fbc9b0..7e98d2b 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -65,8 +65,21 @@
}
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))
+ if ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild() {
+ // Flattened APEXes are not signed
+ return
+ }
+
+ m.public_key_file = ctx.Config().ApexKeyDir(ctx).Join(ctx, String(m.properties.Public_key))
+ m.private_key_file = ctx.Config().ApexKeyDir(ctx).Join(ctx, String(m.properties.Private_key))
+
+ // If not found, fall back to the local key pairs
+ if !android.ExistentPathForSource(ctx, m.public_key_file.String()).Valid() {
+ m.public_key_file = android.PathForModuleSrc(ctx, String(m.properties.Public_key))
+ }
+ if !android.ExistentPathForSource(ctx, m.private_key_file.String()).Valid() {
+ 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())]