blob: 4c83861b2dd44e86959f85072d196222088fc4d8 [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 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)
32 android.RegisterMakeVarsProvider(pctx, apexKeysFileProvider)
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
42
43 keyName string
44}
45
46type apexKeyProperties struct {
47 // Path to the public key file in avbpubkey format. Installed to the device.
48 // Base name of the file is used as the ID for the key.
49 Public_key *string
50 // Path to the private key file in pem format. Used to sign APEXs.
51 Private_key *string
Jiyong Park50d99202018-12-27 13:32:34 +090052
53 // Whether this key is installable to one of the partitions. Defualt: true.
54 Installable *bool
Jiyong Parkff1458f2018-10-12 21:49:38 +090055}
56
57func apexKeyFactory() android.Module {
58 module := &apexKey{}
59 module.AddProperties(&module.properties)
60 android.InitAndroidModule(module)
61 return module
62}
63
Jiyong Park50d99202018-12-27 13:32:34 +090064func (m *apexKey) installable() bool {
65 return m.properties.Installable == nil || proptools.Bool(m.properties.Installable)
66}
67
Jiyong Parkff1458f2018-10-12 21:49:38 +090068func (m *apexKey) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Jiyong Park9335a262018-12-24 11:31:58 +090069 m.public_key_file = ctx.Config().ApexKeyDir(ctx).Join(ctx, String(m.properties.Public_key))
70 m.private_key_file = ctx.Config().ApexKeyDir(ctx).Join(ctx, String(m.properties.Private_key))
71
72 // If not found, fall back to the local key pairs
73 if !android.ExistentPathForSource(ctx, m.public_key_file.String()).Valid() {
74 m.public_key_file = android.PathForModuleSrc(ctx, String(m.properties.Public_key))
75 }
76 if !android.ExistentPathForSource(ctx, m.private_key_file.String()).Valid() {
77 m.private_key_file = android.PathForModuleSrc(ctx, String(m.properties.Private_key))
78 }
Jiyong Parkff1458f2018-10-12 21:49:38 +090079
80 pubKeyName := m.public_key_file.Base()[0 : len(m.public_key_file.Base())-len(m.public_key_file.Ext())]
81 privKeyName := m.private_key_file.Base()[0 : len(m.private_key_file.Base())-len(m.private_key_file.Ext())]
82
83 if pubKeyName != privKeyName {
84 ctx.ModuleErrorf("public_key %q (keyname:%q) and private_key %q (keyname:%q) do not have same keyname",
85 m.public_key_file.String(), pubKeyName, m.private_key_file, privKeyName)
86 return
87 }
88 m.keyName = pubKeyName
89
Jiyong Park50d99202018-12-27 13:32:34 +090090 if m.installable() {
91 ctx.InstallFile(android.PathForModuleInstall(ctx, "etc/security/apex"), m.keyName, m.public_key_file)
92 }
Jiyong Parkff1458f2018-10-12 21:49:38 +090093}
94
95func (m *apexKey) AndroidMk() android.AndroidMkData {
96 return android.AndroidMkData{
97 Class: "ETC",
98 OutputFile: android.OptionalPathForPath(m.public_key_file),
99 Extra: []android.AndroidMkExtraFunc{
100 func(w io.Writer, outputFile android.Path) {
101 fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", "$(TARGET_OUT)/etc/security/apex")
102 fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", m.keyName)
Jiyong Park50d99202018-12-27 13:32:34 +0900103 fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !m.installable())
Jiyong Parkff1458f2018-10-12 21:49:38 +0900104 },
105 },
106 }
107}
Jiyong Park0ca3ce82019-02-18 15:25:04 +0900108
109////////////////////////////////////////////////////////////////////////
110// apex_keys_text
111type apexKeysText struct{}
112
113func (s *apexKeysText) GenerateBuildActions(ctx android.SingletonContext) {
114 output := android.PathForOutput(ctx, "apexkeys.txt")
115 *apexKeysFile(ctx.Config()) = output.String()
116 var filecontent strings.Builder
117 ctx.VisitAllModules(func(module android.Module) {
118 if m, ok := module.(android.Module); ok && !m.Enabled() {
119 return
120 }
121
122 if m, ok := module.(*apexBundle); ok {
123 fmt.Fprintf(&filecontent,
124 "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q\\n",
125 m.Name()+".apex",
126 m.public_key_file.String(),
127 m.private_key_file.String(),
128 m.container_certificate_file.String(),
129 m.container_private_key_file.String())
130 }
131 })
132 ctx.Build(pctx, android.BuildParams{
133 Rule: android.WriteFile,
134 Description: "apex_keys.txt",
135 Output: output,
136 Args: map[string]string{
137 "content": filecontent.String(),
138 },
139 })
140}
141
142var apexKeysFileKey = android.NewOnceKey("apexKeysFile")
143
144func apexKeysFile(config android.Config) *string {
145 return config.Once(apexKeysFileKey, func() interface{} {
146 str := ""
147 return &str
148 }).(*string)
149}
150
151func apexKeysTextFactory() android.Singleton {
152 return &apexKeysText{}
153}
154
155func apexKeysFileProvider(ctx android.MakeVarsContext) {
156 ctx.Strict("SOONG_APEX_KEYS_FILE", *apexKeysFile(ctx.Config()))
157}