blob: 848e8cebc0b01e1d0aaa75a813ff29d806ac42f9 [file] [log] [blame]
Jiyong Parkff1458f2018-10-12 21:49:38 +09001// Copyright (C) 2018 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package apex
16
17import (
18 "fmt"
19 "io"
Jiyong Parkd1e293d2019-03-15 02:13:21 +090020 "path/filepath"
Jiyong Park0ca3ce82019-02-18 15:25:04 +090021 "strings"
Jiyong Parkff1458f2018-10-12 21:49:38 +090022
23 "android/soong/android"
Colin Cross5f692ec2019-02-01 16:53:07 -080024
Jiyong Parkff1458f2018-10-12 21:49:38 +090025 "github.com/google/blueprint/proptools"
26)
27
28var String = proptools.String
29
30func init() {
31 android.RegisterModuleType("apex_key", apexKeyFactory)
Jiyong Park0ca3ce82019-02-18 15:25:04 +090032 android.RegisterSingletonType("apex_keys_text", apexKeysTextFactory)
Jiyong Parkff1458f2018-10-12 21:49:38 +090033}
34
35type apexKey struct {
36 android.ModuleBase
37
38 properties apexKeyProperties
39
40 public_key_file android.Path
41 private_key_file android.Path
Jiyong Parkd1e293d2019-03-15 02:13:21 +090042 installDir android.OutputPath
Jiyong Parkff1458f2018-10-12 21:49:38 +090043
44 keyName string
45}
46
47type apexKeyProperties struct {
Jiyong Park67882562019-03-21 01:11:21 +090048 // Path or module to the public key file in avbpubkey format. Installed to the device.
Jiyong Parkff1458f2018-10-12 21:49:38 +090049 // Base name of the file is used as the ID for the key.
Jiyong Park67882562019-03-21 01:11:21 +090050 Public_key *string `android:"path"`
51 // Path or module to the private key file in pem format. Used to sign APEXs.
52 Private_key *string `android:"path"`
Jiyong Park50d99202018-12-27 13:32:34 +090053
54 // Whether this key is installable to one of the partitions. Defualt: true.
55 Installable *bool
Jiyong Parkff1458f2018-10-12 21:49:38 +090056}
57
58func apexKeyFactory() android.Module {
59 module := &apexKey{}
60 module.AddProperties(&module.properties)
Jiyong Parkd1e293d2019-03-15 02:13:21 +090061 // This module is device-only
62 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
Jiyong Parkff1458f2018-10-12 21:49:38 +090063 return module
64}
65
Jiyong Park50d99202018-12-27 13:32:34 +090066func (m *apexKey) installable() bool {
67 return m.properties.Installable == nil || proptools.Bool(m.properties.Installable)
68}
69
Jiyong Parkff1458f2018-10-12 21:49:38 +090070func (m *apexKey) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Jiyong Park67882562019-03-21 01:11:21 +090071 // If the keys are from other modules (i.e. :module syntax) respect it.
72 // Otherwise, try to locate the key files in the default cert dir or
73 // in the local module dir
74 if android.SrcIsModule(String(m.properties.Public_key)) != "" {
Jiyong Park9335a262018-12-24 11:31:58 +090075 m.public_key_file = android.PathForModuleSrc(ctx, String(m.properties.Public_key))
Jiyong Park67882562019-03-21 01:11:21 +090076 } else {
77 m.public_key_file = ctx.Config().ApexKeyDir(ctx).Join(ctx, String(m.properties.Public_key))
78 // If not found, fall back to the local key pairs
79 if !android.ExistentPathForSource(ctx, m.public_key_file.String()).Valid() {
80 m.public_key_file = android.PathForModuleSrc(ctx, String(m.properties.Public_key))
81 }
Jiyong Park9335a262018-12-24 11:31:58 +090082 }
Jiyong Park67882562019-03-21 01:11:21 +090083
84 if android.SrcIsModule(String(m.properties.Private_key)) != "" {
Jiyong Park9335a262018-12-24 11:31:58 +090085 m.private_key_file = android.PathForModuleSrc(ctx, String(m.properties.Private_key))
Jiyong Park67882562019-03-21 01:11:21 +090086 } else {
87 m.private_key_file = ctx.Config().ApexKeyDir(ctx).Join(ctx, String(m.properties.Private_key))
88 if !android.ExistentPathForSource(ctx, m.private_key_file.String()).Valid() {
89 m.private_key_file = android.PathForModuleSrc(ctx, String(m.properties.Private_key))
90 }
Jiyong Park9335a262018-12-24 11:31:58 +090091 }
Jiyong Parkff1458f2018-10-12 21:49:38 +090092
93 pubKeyName := m.public_key_file.Base()[0 : len(m.public_key_file.Base())-len(m.public_key_file.Ext())]
94 privKeyName := m.private_key_file.Base()[0 : len(m.private_key_file.Base())-len(m.private_key_file.Ext())]
95
96 if pubKeyName != privKeyName {
97 ctx.ModuleErrorf("public_key %q (keyname:%q) and private_key %q (keyname:%q) do not have same keyname",
98 m.public_key_file.String(), pubKeyName, m.private_key_file, privKeyName)
99 return
100 }
101 m.keyName = pubKeyName
102
Jiyong Parkd1e293d2019-03-15 02:13:21 +0900103 m.installDir = android.PathForModuleInstall(ctx, "etc/security/apex")
Jiyong Park50d99202018-12-27 13:32:34 +0900104 if m.installable() {
Jiyong Parkd1e293d2019-03-15 02:13:21 +0900105 ctx.InstallFile(m.installDir, m.keyName, m.public_key_file)
Jiyong Park50d99202018-12-27 13:32:34 +0900106 }
Jiyong Parkff1458f2018-10-12 21:49:38 +0900107}
108
109func (m *apexKey) AndroidMk() android.AndroidMkData {
110 return android.AndroidMkData{
111 Class: "ETC",
112 OutputFile: android.OptionalPathForPath(m.public_key_file),
113 Extra: []android.AndroidMkExtraFunc{
114 func(w io.Writer, outputFile android.Path) {
Jiyong Parkd1e293d2019-03-15 02:13:21 +0900115 fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(OUT_DIR)", m.installDir.RelPathString()))
Jiyong Parkff1458f2018-10-12 21:49:38 +0900116 fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", m.keyName)
Jiyong Park50d99202018-12-27 13:32:34 +0900117 fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !m.installable())
Jiyong Parkff1458f2018-10-12 21:49:38 +0900118 },
119 },
120 }
121}
Jiyong Park0ca3ce82019-02-18 15:25:04 +0900122
123////////////////////////////////////////////////////////////////////////
124// apex_keys_text
Jiyong Park37eb8bb2019-02-20 22:23:29 +0900125type apexKeysText struct {
126 output android.OutputPath
127}
Jiyong Park0ca3ce82019-02-18 15:25:04 +0900128
129func (s *apexKeysText) GenerateBuildActions(ctx android.SingletonContext) {
Jiyong Park37eb8bb2019-02-20 22:23:29 +0900130 s.output = android.PathForOutput(ctx, "apexkeys.txt")
Jiyong Park0ca3ce82019-02-18 15:25:04 +0900131 var filecontent strings.Builder
132 ctx.VisitAllModules(func(module android.Module) {
133 if m, ok := module.(android.Module); ok && !m.Enabled() {
134 return
135 }
136
137 if m, ok := module.(*apexBundle); ok {
138 fmt.Fprintf(&filecontent,
139 "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q\\n",
140 m.Name()+".apex",
141 m.public_key_file.String(),
142 m.private_key_file.String(),
143 m.container_certificate_file.String(),
144 m.container_private_key_file.String())
145 }
146 })
147 ctx.Build(pctx, android.BuildParams{
148 Rule: android.WriteFile,
Jiyong Park37eb8bb2019-02-20 22:23:29 +0900149 Description: "apexkeys.txt",
150 Output: s.output,
Jiyong Park0ca3ce82019-02-18 15:25:04 +0900151 Args: map[string]string{
152 "content": filecontent.String(),
153 },
154 })
155}
156
Jiyong Park0ca3ce82019-02-18 15:25:04 +0900157func apexKeysTextFactory() android.Singleton {
158 return &apexKeysText{}
159}
160
Jiyong Park37eb8bb2019-02-20 22:23:29 +0900161func (s *apexKeysText) MakeVars(ctx android.MakeVarsContext) {
162 ctx.Strict("SOONG_APEX_KEYS_FILE", s.output.String())
Jiyong Park0ca3ce82019-02-18 15:25:04 +0900163}