APEXs are signed with apk signer

The entire APEX (which is a zip file) is signed with the apk signer.
Certificate can be specified via the 'certificate' property just like
ordinary apps. Note: multiple additional certificates are not supported.

Bug: 115721587
Test: m apex.test
Test: jarsigner -verify -verbose -certs .../apex.test.apex shows the
certificate info

Change-Id: Ia4c898d3427779a3809fdc683b85d7661ca65137
This commit is contained in:
Jiyong Park
2018-10-30 21:20:05 +09:00
parent a758cda418
commit c00cbd9e7b
4 changed files with 66 additions and 24 deletions

View File

@@ -71,15 +71,17 @@ type dependencyTag struct {
} }
var ( var (
sharedLibTag = dependencyTag{name: "sharedLib"} sharedLibTag = dependencyTag{name: "sharedLib"}
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"} keyTag = dependencyTag{name: "key"}
certificateTag = dependencyTag{name: "certificate"}
) )
func init() { func init() {
pctx.Import("android/soong/common") pctx.Import("android/soong/common")
pctx.Import("android/soong/java")
pctx.HostBinToolVariable("apexer", "apexer") pctx.HostBinToolVariable("apexer", "apexer")
// ART minimal builds (using the master-art manifest) do not have the "frameworks/base" // ART minimal builds (using the master-art manifest) do not have the "frameworks/base"
// projects, and hence cannot built 'aapt2'. Use the SDK prebuilt instead. // projects, and hence cannot built 'aapt2'. Use the SDK prebuilt instead.
@@ -188,6 +190,10 @@ type apexBundleProperties struct {
// Name of the apex_key module that provides the private key to sign APEX // Name of the apex_key module that provides the private key to sign APEX
Key *string Key *string
// The name of a certificate in the default certificate directory, blank to use the default product certificate,
// or an android_app_certificate module name in the form ":module".
Certificate *string
Multilib struct { Multilib struct {
First struct { First struct {
// List of native libraries whose compile_multilib is "first" // List of native libraries whose compile_multilib is "first"
@@ -324,6 +330,11 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
return return
} }
ctx.AddDependency(ctx.Module(), keyTag, String(a.properties.Key)) ctx.AddDependency(ctx.Module(), keyTag, String(a.properties.Key))
cert := android.SrcIsModule(String(a.properties.Certificate))
if cert != "" {
ctx.AddDependency(ctx.Module(), certificateTag, cert)
}
} }
func getCopyManifestForNativeLibrary(cc *cc.Module) (fileToCopy android.Path, dirInApex string) { func getCopyManifestForNativeLibrary(cc *cc.Module) (fileToCopy android.Path, dirInApex string) {
@@ -366,6 +377,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
copyManifest := make(map[android.Path]string) copyManifest := make(map[android.Path]string)
var keyFile android.Path var keyFile android.Path
var certificate java.Certificate
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 {
@@ -412,6 +424,13 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
} else { } else {
ctx.PropertyErrorf("key", "%q is not an apex_key module", depName) ctx.PropertyErrorf("key", "%q is not an apex_key module", depName)
} }
case certificateTag:
if dep, ok := child.(*java.AndroidAppCertificate); ok {
certificate = dep.Certificate
return false
} else {
ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", depName)
}
} }
} else { } else {
// indirect dependencies // indirect dependencies
@@ -426,6 +445,18 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
return false return false
}) })
cert := String(a.properties.Certificate)
if cert != "" && android.SrcIsModule(cert) == "" {
defaultDir := ctx.Config().DefaultAppCertificateDir(ctx)
certificate = java.Certificate{
defaultDir.Join(ctx, cert+".x509.pem"),
defaultDir.Join(ctx, cert+".pk8"),
}
} else if cert == "" {
pem, key := ctx.Config().DefaultAppCertificate(ctx)
certificate = java.Certificate{pem, key}
}
// files and dirs that will be created in apex // files and dirs that will be created in apex
var readOnlyPaths []string var readOnlyPaths []string
var executablePaths []string // this also includes dirs var executablePaths []string // this also includes dirs
@@ -455,7 +486,7 @@ 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"))
a.outputFile = android.PathForModuleOut(ctx, a.ModuleBase.Name()+apexSuffix) unsignedOutputFile := android.PathForModuleOut(ctx, a.ModuleBase.Name()+apexSuffix+".unsigned")
filesToCopy := []android.Path{} filesToCopy := []android.Path{}
for file := range copyManifest { for file := range copyManifest {
@@ -479,7 +510,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
ctx.ModuleBuild(pctx, android.ModuleBuildParams{ ctx.ModuleBuild(pctx, android.ModuleBuildParams{
Rule: apexRule, Rule: apexRule,
Implicits: implicitInputs, Implicits: implicitInputs,
Output: a.outputFile, Output: unsignedOutputFile,
Args: map[string]string{ Args: map[string]string{
"tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir, "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir,
"image_dir": android.PathForModuleOut(ctx, "image").String(), "image_dir": android.PathForModuleOut(ctx, "image").String(),
@@ -491,6 +522,17 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}, },
}) })
a.outputFile = android.PathForModuleOut(ctx, a.ModuleBase.Name()+apexSuffix)
ctx.Build(pctx, android.BuildParams{
Rule: java.Signapk,
Description: "signapk",
Output: a.outputFile,
Input: unsignedOutputFile,
Args: map[string]string{
"certificates": strings.Join([]string{certificate.Pem.String(), certificate.Key.String()}, " "),
},
})
a.installDir = android.PathForModuleInstall(ctx, "apex") a.installDir = android.PathForModuleInstall(ctx, "apex")
} }

View File

@@ -239,7 +239,7 @@ func (app *AndroidApp) AndroidMk() android.AndroidMkData {
fmt.Fprintln(w, "LOCAL_PRIVILEGED_MODULE := true") fmt.Fprintln(w, "LOCAL_PRIVILEGED_MODULE := true")
} }
fmt.Fprintln(w, "LOCAL_CERTIFICATE :=", app.certificate.pem.String()) fmt.Fprintln(w, "LOCAL_CERTIFICATE :=", app.certificate.Pem.String())
if len(app.appProperties.Overrides) > 0 { if len(app.appProperties.Overrides) > 0 {
fmt.Fprintln(w, "LOCAL_OVERRIDES_PACKAGES := "+strings.Join(app.appProperties.Overrides, " ")) fmt.Fprintln(w, "LOCAL_OVERRIDES_PACKAGES := "+strings.Join(app.appProperties.Overrides, " "))
} }

View File

@@ -76,7 +76,7 @@ type AndroidApp struct {
Library Library
aapt aapt
certificate certificate certificate Certificate
appProperties appProperties appProperties appProperties
@@ -99,8 +99,8 @@ func (a *AndroidApp) ExportedManifest() android.Path {
var _ AndroidLibraryDependency = (*AndroidApp)(nil) var _ AndroidLibraryDependency = (*AndroidApp)(nil)
type certificate struct { type Certificate struct {
pem, key android.Path Pem, Key android.Path
} }
func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) { func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -237,7 +237,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
dexJarFile = nil dexJarFile = nil
} }
var certificates []certificate var certificates []Certificate
var jniJarFile android.WritablePath var jniJarFile android.WritablePath
jniLibs, certificateDeps := a.collectAppDeps(ctx) jniLibs, certificateDeps := a.collectAppDeps(ctx)
@@ -262,16 +262,16 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
certificateDeps = certificateDeps[1:] certificateDeps = certificateDeps[1:]
} else if cert != "" { } else if cert != "" {
defaultDir := ctx.Config().DefaultAppCertificateDir(ctx) defaultDir := ctx.Config().DefaultAppCertificateDir(ctx)
a.certificate = certificate{ a.certificate = Certificate{
defaultDir.Join(ctx, cert+".x509.pem"), defaultDir.Join(ctx, cert+".x509.pem"),
defaultDir.Join(ctx, cert+".pk8"), defaultDir.Join(ctx, cert+".pk8"),
} }
} else { } else {
pem, key := ctx.Config().DefaultAppCertificate(ctx) pem, key := ctx.Config().DefaultAppCertificate(ctx)
a.certificate = certificate{pem, key} a.certificate = Certificate{pem, key}
} }
certificates = append([]certificate{a.certificate}, certificateDeps...) certificates = append([]Certificate{a.certificate}, certificateDeps...)
packageFile := android.PathForModuleOut(ctx, "package.apk") packageFile := android.PathForModuleOut(ctx, "package.apk")
CreateAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates) CreateAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates)
@@ -287,9 +287,9 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
} }
} }
func (a *AndroidApp) collectAppDeps(ctx android.ModuleContext) ([]jniLib, []certificate) { func (a *AndroidApp) collectAppDeps(ctx android.ModuleContext) ([]jniLib, []Certificate) {
var jniLibs []jniLib var jniLibs []jniLib
var certificates []certificate var certificates []Certificate
ctx.VisitDirectDeps(func(module android.Module) { ctx.VisitDirectDeps(func(module android.Module) {
otherName := ctx.OtherModuleName(module) otherName := ctx.OtherModuleName(module)
@@ -313,7 +313,7 @@ func (a *AndroidApp) collectAppDeps(ctx android.ModuleContext) ([]jniLib, []cert
} }
} else if tag == certificateTag { } else if tag == certificateTag {
if dep, ok := module.(*AndroidAppCertificate); ok { if dep, ok := module.(*AndroidAppCertificate); ok {
certificates = append(certificates, dep.certificate) certificates = append(certificates, dep.Certificate)
} else { } else {
ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", otherName) ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", otherName)
} }
@@ -446,7 +446,7 @@ func AndroidTestHelperAppFactory() android.Module {
type AndroidAppCertificate struct { type AndroidAppCertificate struct {
android.ModuleBase android.ModuleBase
properties AndroidAppCertificateProperties properties AndroidAppCertificateProperties
certificate certificate Certificate Certificate
} }
type AndroidAppCertificateProperties struct { type AndroidAppCertificateProperties struct {
@@ -466,7 +466,7 @@ func (c *AndroidAppCertificate) DepsMutator(ctx android.BottomUpMutatorContext)
func (c *AndroidAppCertificate) GenerateAndroidBuildActions(ctx android.ModuleContext) { func (c *AndroidAppCertificate) GenerateAndroidBuildActions(ctx android.ModuleContext) {
cert := String(c.properties.Certificate) cert := String(c.properties.Certificate)
c.certificate = certificate{ c.Certificate = Certificate{
android.PathForModuleSrc(ctx, cert+".x509.pem"), android.PathForModuleSrc(ctx, cert+".x509.pem"),
android.PathForModuleSrc(ctx, cert+".pk8"), android.PathForModuleSrc(ctx, cert+".pk8"),
} }

View File

@@ -29,7 +29,7 @@ import (
) )
var ( var (
signapk = pctx.AndroidStaticRule("signapk", Signapk = pctx.AndroidStaticRule("signapk",
blueprint.RuleParams{ blueprint.RuleParams{
Command: `${config.JavaCmd} -Djava.library.path=$$(dirname $signapkJniLibrary) ` + Command: `${config.JavaCmd} -Djava.library.path=$$(dirname $signapkJniLibrary) ` +
`-jar $signapkCmd $certificates $in $out`, `-jar $signapkCmd $certificates $in $out`,
@@ -63,7 +63,7 @@ var combineApk = pctx.AndroidStaticRule("combineApk",
}) })
func CreateAppPackage(ctx android.ModuleContext, outputFile android.WritablePath, func CreateAppPackage(ctx android.ModuleContext, outputFile android.WritablePath,
resJarFile, jniJarFile, dexJarFile android.Path, certificates []certificate) { resJarFile, jniJarFile, dexJarFile android.Path, certificates []Certificate) {
unsignedApk := android.PathForModuleOut(ctx, "unsigned.apk") unsignedApk := android.PathForModuleOut(ctx, "unsigned.apk")
@@ -84,11 +84,11 @@ func CreateAppPackage(ctx android.ModuleContext, outputFile android.WritablePath
var certificateArgs []string var certificateArgs []string
for _, c := range certificates { for _, c := range certificates {
certificateArgs = append(certificateArgs, c.pem.String(), c.key.String()) certificateArgs = append(certificateArgs, c.Pem.String(), c.Key.String())
} }
ctx.Build(pctx, android.BuildParams{ ctx.Build(pctx, android.BuildParams{
Rule: signapk, Rule: Signapk,
Description: "signapk", Description: "signapk",
Output: outputFile, Output: outputFile,
Input: unsignedApk, Input: unsignedApk,