blob: ec33763dde2ab6ff8c27dfa8f80af782a990f5fe [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"
Jiyong Parka41f12a2019-04-23 18:00:10 +090019 "sort"
Jiyong Park0ca3ce82019-02-18 15:25:04 +090020 "strings"
Jiyong Parkff1458f2018-10-12 21:49:38 +090021
22 "android/soong/android"
Colin Cross5f692ec2019-02-01 16:53:07 -080023
Jiyong Parkff1458f2018-10-12 21:49:38 +090024 "github.com/google/blueprint/proptools"
25)
26
27var String = proptools.String
28
29func init() {
30 android.RegisterModuleType("apex_key", apexKeyFactory)
Jiyong Park0ca3ce82019-02-18 15:25:04 +090031 android.RegisterSingletonType("apex_keys_text", apexKeysTextFactory)
Jiyong Parkff1458f2018-10-12 21:49:38 +090032}
33
34type apexKey struct {
35 android.ModuleBase
36
37 properties apexKeyProperties
38
39 public_key_file android.Path
40 private_key_file android.Path
41
42 keyName string
43}
44
45type apexKeyProperties struct {
Jiyong Park67882562019-03-21 01:11:21 +090046 // Path or module to the public key file in avbpubkey format. Installed to the device.
Jiyong Parkff1458f2018-10-12 21:49:38 +090047 // Base name of the file is used as the ID for the key.
Jiyong Park67882562019-03-21 01:11:21 +090048 Public_key *string `android:"path"`
49 // Path or module to the private key file in pem format. Used to sign APEXs.
50 Private_key *string `android:"path"`
Jiyong Park50d99202018-12-27 13:32:34 +090051
52 // Whether this key is installable to one of the partitions. Defualt: true.
53 Installable *bool
Jiyong Parkff1458f2018-10-12 21:49:38 +090054}
55
56func apexKeyFactory() android.Module {
57 module := &apexKey{}
58 module.AddProperties(&module.properties)
Jiyong Parkd1e293d2019-03-15 02:13:21 +090059 // This module is device-only
60 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
Jiyong Parkff1458f2018-10-12 21:49:38 +090061 return module
62}
63
Jiyong Park50d99202018-12-27 13:32:34 +090064func (m *apexKey) installable() bool {
Jiyong Park42cca6c2019-04-01 11:15:50 +090065 return false
Jiyong Park50d99202018-12-27 13:32:34 +090066}
67
Jiyong Parkff1458f2018-10-12 21:49:38 +090068func (m *apexKey) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Jiyong Park67882562019-03-21 01:11:21 +090069 // If the keys are from other modules (i.e. :module syntax) respect it.
70 // Otherwise, try to locate the key files in the default cert dir or
71 // in the local module dir
72 if android.SrcIsModule(String(m.properties.Public_key)) != "" {
Jiyong Park9335a262018-12-24 11:31:58 +090073 m.public_key_file = android.PathForModuleSrc(ctx, String(m.properties.Public_key))
Jiyong Park67882562019-03-21 01:11:21 +090074 } else {
75 m.public_key_file = ctx.Config().ApexKeyDir(ctx).Join(ctx, String(m.properties.Public_key))
76 // If not found, fall back to the local key pairs
77 if !android.ExistentPathForSource(ctx, m.public_key_file.String()).Valid() {
78 m.public_key_file = android.PathForModuleSrc(ctx, String(m.properties.Public_key))
79 }
Jiyong Park9335a262018-12-24 11:31:58 +090080 }
Jiyong Park67882562019-03-21 01:11:21 +090081
82 if android.SrcIsModule(String(m.properties.Private_key)) != "" {
Jiyong Park9335a262018-12-24 11:31:58 +090083 m.private_key_file = android.PathForModuleSrc(ctx, String(m.properties.Private_key))
Jiyong Park67882562019-03-21 01:11:21 +090084 } else {
85 m.private_key_file = ctx.Config().ApexKeyDir(ctx).Join(ctx, String(m.properties.Private_key))
86 if !android.ExistentPathForSource(ctx, m.private_key_file.String()).Valid() {
87 m.private_key_file = android.PathForModuleSrc(ctx, String(m.properties.Private_key))
88 }
Jiyong Park9335a262018-12-24 11:31:58 +090089 }
Jiyong Parkff1458f2018-10-12 21:49:38 +090090
91 pubKeyName := m.public_key_file.Base()[0 : len(m.public_key_file.Base())-len(m.public_key_file.Ext())]
92 privKeyName := m.private_key_file.Base()[0 : len(m.private_key_file.Base())-len(m.private_key_file.Ext())]
93
Jaewoong Jung939ebd52019-03-26 15:07:36 -070094 if m.properties.Public_key != nil && m.properties.Private_key != nil && pubKeyName != privKeyName {
Jiyong Parkff1458f2018-10-12 21:49:38 +090095 ctx.ModuleErrorf("public_key %q (keyname:%q) and private_key %q (keyname:%q) do not have same keyname",
96 m.public_key_file.String(), pubKeyName, m.private_key_file, privKeyName)
97 return
98 }
99 m.keyName = pubKeyName
Jiyong Parkff1458f2018-10-12 21:49:38 +0900100}
Jiyong Park0ca3ce82019-02-18 15:25:04 +0900101
102////////////////////////////////////////////////////////////////////////
103// apex_keys_text
Jiyong Park37eb8bb2019-02-20 22:23:29 +0900104type apexKeysText struct {
105 output android.OutputPath
106}
Jiyong Park0ca3ce82019-02-18 15:25:04 +0900107
108func (s *apexKeysText) GenerateBuildActions(ctx android.SingletonContext) {
Jiyong Park37eb8bb2019-02-20 22:23:29 +0900109 s.output = android.PathForOutput(ctx, "apexkeys.txt")
Jiyong Park4a9f5122020-06-12 17:26:31 +0900110 type apexKeyEntry struct {
111 name string
112 presigned bool
113 public_key string
114 private_key string
115 container_certificate string
116 container_private_key string
117 partition string
118 }
119 toString := func(e apexKeyEntry) string {
120 format := "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q\\n"
121 if e.presigned {
122 return fmt.Sprintf(format, e.name, "PRESIGNED", "PRESIGNED", "PRESIGNED", "PRESIGNED")
123 } else {
124 return fmt.Sprintf(format, e.name, e.public_key, e.private_key, e.container_certificate, e.container_private_key)
125 }
126 }
127
128 apexKeyMap := make(map[string]apexKeyEntry)
Jiyong Park0ca3ce82019-02-18 15:25:04 +0900129 ctx.VisitAllModules(func(module android.Module) {
Jiyong Parka41f12a2019-04-23 18:00:10 +0900130 if m, ok := module.(*apexBundle); ok && m.Enabled() && m.installable() {
Jiyong Park4a9f5122020-06-12 17:26:31 +0900131 apexKeyMap[m.Name()] = apexKeyEntry{
132 name: m.Name() + ".apex",
133 presigned: false,
134 public_key: m.public_key_file.String(),
135 private_key: m.private_key_file.String(),
136 container_certificate: m.container_certificate_file.String(),
137 container_private_key: m.container_private_key_file.String(),
138 partition: m.PartitionTag(ctx.DeviceConfig()),
139 }
Jiyong Park0ca3ce82019-02-18 15:25:04 +0900140 }
Jiyong Parka41f12a2019-04-23 18:00:10 +0900141 })
Jiyong Park0ca3ce82019-02-18 15:25:04 +0900142
Jiyong Parka41f12a2019-04-23 18:00:10 +0900143 // Find prebuilts and let them override apexBundle if they are preferred
144 ctx.VisitAllModules(func(module android.Module) {
145 if m, ok := module.(*Prebuilt); ok && m.Enabled() && m.installable() &&
146 m.Prebuilt().UsePrebuilt() {
Jiyong Park4a9f5122020-06-12 17:26:31 +0900147 apexKeyMap[m.BaseModuleName()] = apexKeyEntry{
148 name: m.InstallFilename(),
149 presigned: true,
150 partition: m.PartitionTag(ctx.DeviceConfig()),
151 }
152 }
153 })
154
155 // Find apex_set and let them override apexBundle or prebuilts. This is done in a separate pass
156 // so that apex_set are not overridden by prebuilts.
157 ctx.VisitAllModules(func(module android.Module) {
158 if m, ok := module.(*ApexSet); ok && m.Enabled() {
159 entry := apexKeyEntry{
160 name: m.InstallFilename(),
161 presigned: true,
162 partition: m.PartitionTag(ctx.DeviceConfig()),
163 }
Jiyong Park4a9f5122020-06-12 17:26:31 +0900164 apexKeyMap[m.BaseModuleName()] = entry
Jiyong Parka41f12a2019-04-23 18:00:10 +0900165 }
166 })
167
168 // iterating over map does not give consistent ordering in golang
169 var moduleNames []string
Jiyong Park4a9f5122020-06-12 17:26:31 +0900170 for key, _ := range apexKeyMap {
Jiyong Parka41f12a2019-04-23 18:00:10 +0900171 moduleNames = append(moduleNames, key)
172 }
173 sort.Strings(moduleNames)
174
175 var filecontent strings.Builder
Jiyong Park4a9f5122020-06-12 17:26:31 +0900176 for _, name := range moduleNames {
177 fmt.Fprintf(&filecontent, "%s", toString(apexKeyMap[name]))
Jiyong Parka41f12a2019-04-23 18:00:10 +0900178 }
179
Jiyong Park0ca3ce82019-02-18 15:25:04 +0900180 ctx.Build(pctx, android.BuildParams{
181 Rule: android.WriteFile,
Jiyong Park37eb8bb2019-02-20 22:23:29 +0900182 Description: "apexkeys.txt",
183 Output: s.output,
Jiyong Park0ca3ce82019-02-18 15:25:04 +0900184 Args: map[string]string{
185 "content": filecontent.String(),
186 },
187 })
188}
189
Jiyong Park0ca3ce82019-02-18 15:25:04 +0900190func apexKeysTextFactory() android.Singleton {
191 return &apexKeysText{}
192}
193
Jiyong Park37eb8bb2019-02-20 22:23:29 +0900194func (s *apexKeysText) MakeVars(ctx android.MakeVarsContext) {
195 ctx.Strict("SOONG_APEX_KEYS_FILE", s.output.String())
Jiyong Park0ca3ce82019-02-18 15:25:04 +0900196}