key.go 7.8 KB

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