Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9335a26c authored by Jiyong Park's avatar Jiyong Park
Browse files

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
parent 709a3294
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -561,6 +561,19 @@ func (c *config) DefaultAppCertificate(ctx PathContext) (pem, key SourcePath) {
	}
}

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)
}
+12 −10
Original line number Diff line number Diff line
@@ -448,6 +448,7 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
		{Mutator: "arch", Variation: "android_common"},
	}, prebuiltTag, a.properties.Prebuilts...)

	if !ctx.Config().FlattenApex() || ctx.Config().UnbundledBuild() {
		if String(a.properties.Key) == "" {
			ctx.ModuleErrorf("key is missing")
			return
@@ -459,6 +460,7 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
			ctx.AddDependency(ctx.Module(), certificateTag, cert)
		}
	}
}

func (a *apexBundle) Srcs() android.Paths {
	if file, ok := a.outputFiles[imageApex]; ok {
@@ -626,7 +628,8 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
		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 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
		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

+48 −2
Original line number Diff line number Diff line
@@ -124,13 +124,15 @@ func testApex(t *testing.T, bp string) *android.TestContext {

	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 @@ func setup(t *testing.T) (config android.Config, buildDir string) {

	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 @@ func TestStaticLinking(t *testing.T) {
	// 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")
	}
}
+15 −2
Original line number Diff line number Diff line
@@ -65,8 +65,21 @@ func (m *apexKey) DepsMutator(ctx android.BottomUpMutatorContext) {
}

func (m *apexKey) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	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())]