key.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // 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. package apex
  15. import (
  16. "fmt"
  17. "sort"
  18. "strings"
  19. "android/soong/android"
  20. "android/soong/bazel"
  21. "github.com/google/blueprint/proptools"
  22. )
  23. var String = proptools.String
  24. func init() {
  25. registerApexKeyBuildComponents(android.InitRegistrationContext)
  26. }
  27. func registerApexKeyBuildComponents(ctx android.RegistrationContext) {
  28. ctx.RegisterModuleType("apex_key", ApexKeyFactory)
  29. ctx.RegisterParallelSingletonType("apex_keys_text", apexKeysTextFactory)
  30. }
  31. type apexKey struct {
  32. android.ModuleBase
  33. android.BazelModuleBase
  34. properties apexKeyProperties
  35. publicKeyFile android.Path
  36. privateKeyFile android.Path
  37. }
  38. type apexKeyProperties struct {
  39. // Path or module to the public key file in avbpubkey format. Installed to the device.
  40. // Base name of the file is used as the ID for the key.
  41. Public_key *string `android:"path"`
  42. // Path or module to the private key file in pem format. Used to sign APEXs.
  43. Private_key *string `android:"path"`
  44. // Whether this key is installable to one of the partitions. Defualt: true.
  45. Installable *bool
  46. }
  47. func ApexKeyFactory() android.Module {
  48. module := &apexKey{}
  49. module.AddProperties(&module.properties)
  50. android.InitAndroidArchModule(module, android.HostAndDeviceDefault, android.MultilibCommon)
  51. android.InitBazelModule(module)
  52. return module
  53. }
  54. func (m *apexKey) installable() bool {
  55. return false
  56. }
  57. func (m *apexKey) GenerateAndroidBuildActions(ctx android.ModuleContext) {
  58. // If the keys are from other modules (i.e. :module syntax) respect it.
  59. // Otherwise, try to locate the key files in the default cert dir or
  60. // in the local module dir
  61. if android.SrcIsModule(String(m.properties.Public_key)) != "" {
  62. m.publicKeyFile = android.PathForModuleSrc(ctx, String(m.properties.Public_key))
  63. } else {
  64. m.publicKeyFile = ctx.Config().ApexKeyDir(ctx).Join(ctx, String(m.properties.Public_key))
  65. // If not found, fall back to the local key pairs
  66. if !android.ExistentPathForSource(ctx, m.publicKeyFile.String()).Valid() {
  67. m.publicKeyFile = android.PathForModuleSrc(ctx, String(m.properties.Public_key))
  68. }
  69. }
  70. if android.SrcIsModule(String(m.properties.Private_key)) != "" {
  71. m.privateKeyFile = android.PathForModuleSrc(ctx, String(m.properties.Private_key))
  72. } else {
  73. m.privateKeyFile = ctx.Config().ApexKeyDir(ctx).Join(ctx, String(m.properties.Private_key))
  74. if !android.ExistentPathForSource(ctx, m.privateKeyFile.String()).Valid() {
  75. m.privateKeyFile = android.PathForModuleSrc(ctx, String(m.properties.Private_key))
  76. }
  77. }
  78. pubKeyName := m.publicKeyFile.Base()[0 : len(m.publicKeyFile.Base())-len(m.publicKeyFile.Ext())]
  79. privKeyName := m.privateKeyFile.Base()[0 : len(m.privateKeyFile.Base())-len(m.privateKeyFile.Ext())]
  80. if m.properties.Public_key != nil && m.properties.Private_key != nil && pubKeyName != privKeyName {
  81. ctx.ModuleErrorf("public_key %q (keyname:%q) and private_key %q (keyname:%q) do not have same keyname",
  82. m.publicKeyFile.String(), pubKeyName, m.privateKeyFile, privKeyName)
  83. return
  84. }
  85. }
  86. // //////////////////////////////////////////////////////////////////////
  87. // apex_keys_text
  88. type apexKeysText struct {
  89. output android.OutputPath
  90. }
  91. func (s *apexKeysText) GenerateBuildActions(ctx android.SingletonContext) {
  92. s.output = android.PathForOutput(ctx, "apexkeys.txt")
  93. type apexKeyEntry struct {
  94. name string
  95. presigned bool
  96. publicKey string
  97. privateKey string
  98. containerCertificate string
  99. containerPrivateKey string
  100. partition string
  101. signTool string
  102. }
  103. toString := func(e apexKeyEntry) string {
  104. signTool := ""
  105. if e.signTool != "" {
  106. signTool = fmt.Sprintf(" sign_tool=%q", e.signTool)
  107. }
  108. format := "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q partition=%q%s\n"
  109. if e.presigned {
  110. return fmt.Sprintf(format, e.name, "PRESIGNED", "PRESIGNED", "PRESIGNED", "PRESIGNED", e.partition, signTool)
  111. } else {
  112. return fmt.Sprintf(format, e.name, e.publicKey, e.privateKey, e.containerCertificate, e.containerPrivateKey, e.partition, signTool)
  113. }
  114. }
  115. apexKeyMap := make(map[string]apexKeyEntry)
  116. ctx.VisitAllModules(func(module android.Module) {
  117. if m, ok := module.(*apexBundle); ok && m.Enabled() && m.installable() {
  118. pem, key := m.getCertificateAndPrivateKey(ctx)
  119. apexKeyMap[m.Name()] = apexKeyEntry{
  120. name: m.Name() + ".apex",
  121. presigned: false,
  122. publicKey: m.publicKeyFile.String(),
  123. privateKey: m.privateKeyFile.String(),
  124. containerCertificate: pem.String(),
  125. containerPrivateKey: key.String(),
  126. partition: m.PartitionTag(ctx.DeviceConfig()),
  127. signTool: proptools.String(m.properties.Custom_sign_tool),
  128. }
  129. }
  130. })
  131. // Find prebuilts and let them override apexBundle if they are preferred
  132. ctx.VisitAllModules(func(module android.Module) {
  133. if m, ok := module.(*Prebuilt); ok && m.Enabled() && m.installable() &&
  134. m.Prebuilt().UsePrebuilt() {
  135. apexKeyMap[m.BaseModuleName()] = apexKeyEntry{
  136. name: m.InstallFilename(),
  137. presigned: true,
  138. partition: m.PartitionTag(ctx.DeviceConfig()),
  139. }
  140. }
  141. })
  142. // Find apex_set and let them override apexBundle or prebuilts. This is done in a separate pass
  143. // so that apex_set are not overridden by prebuilts.
  144. ctx.VisitAllModules(func(module android.Module) {
  145. if m, ok := module.(*ApexSet); ok && m.Enabled() {
  146. entry := apexKeyEntry{
  147. name: m.InstallFilename(),
  148. presigned: true,
  149. partition: m.PartitionTag(ctx.DeviceConfig()),
  150. }
  151. apexKeyMap[m.BaseModuleName()] = entry
  152. }
  153. })
  154. // iterating over map does not give consistent ordering in golang
  155. var moduleNames []string
  156. for key, _ := range apexKeyMap {
  157. moduleNames = append(moduleNames, key)
  158. }
  159. sort.Strings(moduleNames)
  160. var filecontent strings.Builder
  161. for _, name := range moduleNames {
  162. filecontent.WriteString(toString(apexKeyMap[name]))
  163. }
  164. android.WriteFileRule(ctx, s.output, filecontent.String())
  165. }
  166. func apexKeysTextFactory() android.Singleton {
  167. return &apexKeysText{}
  168. }
  169. func (s *apexKeysText) MakeVars(ctx android.MakeVarsContext) {
  170. ctx.Strict("SOONG_APEX_KEYS_FILE", s.output.String())
  171. }
  172. // For Bazel / bp2build
  173. type bazelApexKeyAttributes struct {
  174. Public_key bazel.LabelAttribute
  175. Public_key_name bazel.StringAttribute
  176. Private_key bazel.LabelAttribute
  177. Private_key_name bazel.StringAttribute
  178. }
  179. // ConvertWithBp2build performs conversion apexKey for bp2build
  180. func (m *apexKey) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
  181. apexKeyBp2BuildInternal(ctx, m)
  182. }
  183. func apexKeyBp2BuildInternal(ctx android.TopDownMutatorContext, module *apexKey) {
  184. privateKeyLabelAttribute, privateKeyNameAttribute :=
  185. android.BazelStringOrLabelFromProp(ctx, module.properties.Private_key)
  186. publicKeyLabelAttribute, publicKeyNameAttribute :=
  187. android.BazelStringOrLabelFromProp(ctx, module.properties.Public_key)
  188. attrs := &bazelApexKeyAttributes{
  189. Private_key: privateKeyLabelAttribute,
  190. Private_key_name: privateKeyNameAttribute,
  191. Public_key: publicKeyLabelAttribute,
  192. Public_key_name: publicKeyNameAttribute,
  193. }
  194. props := bazel.BazelTargetModuleProperties{
  195. Rule_class: "apex_key",
  196. Bzl_load_location: "//build/bazel/rules/apex:apex_key.bzl",
  197. }
  198. ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs)
  199. }