1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.content.integrity; 18 19 import android.annotation.NonNull; 20 21 import java.util.HashMap; 22 import java.util.List; 23 import java.util.Map; 24 import java.util.Objects; 25 26 /** 27 * The app install metadata. 28 * 29 * <p>The integrity component retrieves metadata for app installs from package manager, passing it 30 * to the rule evaluation engine to evaluate the metadata against the rules. 31 * 32 * <p>Instances of this class are immutable. 33 * 34 * @hide 35 */ 36 public final class AppInstallMetadata { 37 private final String mPackageName; 38 // Raw string encoding for the SHA-256 hash of the certificate of the app. 39 private final List<String> mAppCertificates; 40 // Raw string encoding for the SHA-256 hash of the certificate lineage/history of the app. 41 private final List<String> mAppCertificateLineage; 42 private final String mInstallerName; 43 // Raw string encoding for the SHA-256 hash of the certificate of the installer. 44 private final List<String> mInstallerCertificates; 45 private final long mVersionCode; 46 private final boolean mIsPreInstalled; 47 private final boolean mIsStampPresent; 48 private final boolean mIsStampVerified; 49 private final boolean mIsStampTrusted; 50 // Raw string encoding for the SHA-256 hash of the certificate of the stamp. 51 private final String mStampCertificateHash; 52 private final Map<String, String> mAllowedInstallersAndCertificates; 53 AppInstallMetadata(Builder builder)54 private AppInstallMetadata(Builder builder) { 55 this.mPackageName = builder.mPackageName; 56 this.mAppCertificates = builder.mAppCertificates; 57 this.mAppCertificateLineage = builder.mAppCertificateLineage; 58 this.mInstallerName = builder.mInstallerName; 59 this.mInstallerCertificates = builder.mInstallerCertificates; 60 this.mVersionCode = builder.mVersionCode; 61 this.mIsPreInstalled = builder.mIsPreInstalled; 62 this.mIsStampPresent = builder.mIsStampPresent; 63 this.mIsStampVerified = builder.mIsStampVerified; 64 this.mIsStampTrusted = builder.mIsStampTrusted; 65 this.mStampCertificateHash = builder.mStampCertificateHash; 66 this.mAllowedInstallersAndCertificates = builder.mAllowedInstallersAndCertificates; 67 } 68 69 @NonNull getPackageName()70 public String getPackageName() { 71 return mPackageName; 72 } 73 74 @NonNull getAppCertificates()75 public List<String> getAppCertificates() { 76 return mAppCertificates; 77 } 78 79 @NonNull getAppCertificateLineage()80 public List<String> getAppCertificateLineage() { 81 return mAppCertificateLineage; 82 } 83 84 @NonNull getInstallerName()85 public String getInstallerName() { 86 return mInstallerName; 87 } 88 89 @NonNull getInstallerCertificates()90 public List<String> getInstallerCertificates() { 91 return mInstallerCertificates; 92 } 93 94 /** @see AppInstallMetadata.Builder#setVersionCode(long) */ getVersionCode()95 public long getVersionCode() { 96 return mVersionCode; 97 } 98 99 /** @see AppInstallMetadata.Builder#setIsPreInstalled(boolean) */ isPreInstalled()100 public boolean isPreInstalled() { 101 return mIsPreInstalled; 102 } 103 104 /** @see AppInstallMetadata.Builder#setIsStampPresent(boolean) */ isStampPresent()105 public boolean isStampPresent() { 106 return mIsStampPresent; 107 } 108 109 /** @see AppInstallMetadata.Builder#setIsStampVerified(boolean) */ isStampVerified()110 public boolean isStampVerified() { 111 return mIsStampVerified; 112 } 113 114 /** @see AppInstallMetadata.Builder#setIsStampTrusted(boolean) */ isStampTrusted()115 public boolean isStampTrusted() { 116 return mIsStampTrusted; 117 } 118 119 /** @see AppInstallMetadata.Builder#setStampCertificateHash(String) */ getStampCertificateHash()120 public String getStampCertificateHash() { 121 return mStampCertificateHash; 122 } 123 124 /** Get the allowed installers and their corresponding cert. */ getAllowedInstallersAndCertificates()125 public Map<String, String> getAllowedInstallersAndCertificates() { 126 return mAllowedInstallersAndCertificates; 127 } 128 129 @Override toString()130 public String toString() { 131 return String.format( 132 "AppInstallMetadata {" 133 + " PackageName = %s," 134 + " AppCerts = %s," 135 + " AppCertsLineage = %s," 136 + " InstallerName = %s," 137 + " InstallerCerts = %s," 138 + " VersionCode = %d," 139 + " PreInstalled = %b," 140 + " StampPresent = %b," 141 + " StampVerified = %b," 142 + " StampTrusted = %b," 143 + " StampCert = %s }", 144 mPackageName, 145 mAppCertificates, 146 mAppCertificateLineage, 147 mInstallerName == null ? "null" : mInstallerName, 148 mInstallerCertificates == null ? "null" : mInstallerCertificates, 149 mVersionCode, 150 mIsPreInstalled, 151 mIsStampPresent, 152 mIsStampVerified, 153 mIsStampTrusted, 154 mStampCertificateHash == null ? "null" : mStampCertificateHash); 155 } 156 157 /** Builder class for constructing {@link AppInstallMetadata} objects. */ 158 public static final class Builder { 159 private String mPackageName; 160 private List<String> mAppCertificates; 161 private List<String> mAppCertificateLineage; 162 private String mInstallerName; 163 private List<String> mInstallerCertificates; 164 private long mVersionCode; 165 private boolean mIsPreInstalled; 166 private boolean mIsStampPresent; 167 private boolean mIsStampVerified; 168 private boolean mIsStampTrusted; 169 private String mStampCertificateHash; 170 private Map<String, String> mAllowedInstallersAndCertificates; 171 Builder()172 public Builder() { 173 mAllowedInstallersAndCertificates = new HashMap<>(); 174 } 175 176 /** 177 * Add allowed installers and cert. 178 * 179 * @see AppInstallMetadata#getAllowedInstallersAndCertificates() 180 */ 181 @NonNull setAllowedInstallersAndCert( @onNull Map<String, String> allowedInstallersAndCertificates)182 public Builder setAllowedInstallersAndCert( 183 @NonNull Map<String, String> allowedInstallersAndCertificates) { 184 this.mAllowedInstallersAndCertificates = allowedInstallersAndCertificates; 185 return this; 186 } 187 188 /** 189 * Set package name of the app to be installed. 190 * 191 * @see AppInstallMetadata#getPackageName() 192 */ 193 @NonNull setPackageName(@onNull String packageName)194 public Builder setPackageName(@NonNull String packageName) { 195 this.mPackageName = Objects.requireNonNull(packageName); 196 return this; 197 } 198 199 /** 200 * Set certificate of the app to be installed. 201 * 202 * <p>It is represented as the raw string encoding for the SHA-256 hash of the certificate 203 * of the app. 204 * 205 * @see AppInstallMetadata#getAppCertificates() 206 */ 207 @NonNull setAppCertificates(@onNull List<String> appCertificates)208 public Builder setAppCertificates(@NonNull List<String> appCertificates) { 209 this.mAppCertificates = Objects.requireNonNull(appCertificates); 210 return this; 211 } 212 213 /** 214 * Set the list of (old and new) certificates used for signing the app to be installed. 215 * 216 * <p>It is represented as the raw string encoding for the SHA-256 hash of the certificate 217 * lineage/history of the app. 218 * 219 * @see AppInstallMetadata#getAppCertificateLineage() 220 */ 221 @NonNull setAppCertificateLineage(@onNull List<String> appCertificateLineage)222 public Builder setAppCertificateLineage(@NonNull List<String> appCertificateLineage) { 223 this.mAppCertificateLineage = Objects.requireNonNull(appCertificateLineage); 224 return this; 225 } 226 227 /** 228 * Set name of the installer installing the app. 229 * 230 * @see AppInstallMetadata#getInstallerName() 231 */ 232 @NonNull setInstallerName(@onNull String installerName)233 public Builder setInstallerName(@NonNull String installerName) { 234 this.mInstallerName = Objects.requireNonNull(installerName); 235 return this; 236 } 237 238 /** 239 * Set certificate of the installer installing the app. 240 * 241 * <p>It is represented as the raw string encoding for the SHA-256 hash of the certificate 242 * of the installer. 243 * 244 * @see AppInstallMetadata#getInstallerCertificates() 245 */ 246 @NonNull setInstallerCertificates(@onNull List<String> installerCertificates)247 public Builder setInstallerCertificates(@NonNull List<String> installerCertificates) { 248 this.mInstallerCertificates = Objects.requireNonNull(installerCertificates); 249 return this; 250 } 251 252 /** 253 * Set version code of the app to be installed. 254 * 255 * @see AppInstallMetadata#getVersionCode() 256 */ 257 @NonNull setVersionCode(long versionCode)258 public Builder setVersionCode(long versionCode) { 259 this.mVersionCode = versionCode; 260 return this; 261 } 262 263 /** 264 * Set whether the app is pre-installed on the device or not. 265 * 266 * @see AppInstallMetadata#isPreInstalled() 267 */ 268 @NonNull setIsPreInstalled(boolean isPreInstalled)269 public Builder setIsPreInstalled(boolean isPreInstalled) { 270 this.mIsPreInstalled = isPreInstalled; 271 return this; 272 } 273 274 /** 275 * Set whether the stamp embedded in the APK is present or not. 276 * 277 * @see AppInstallMetadata#isStampPresent() 278 */ 279 @NonNull setIsStampPresent(boolean isStampPresent)280 public Builder setIsStampPresent(boolean isStampPresent) { 281 this.mIsStampPresent = isStampPresent; 282 return this; 283 } 284 285 /** 286 * Set whether the stamp embedded in the APK is verified or not. 287 * 288 * @see AppInstallMetadata#isStampVerified() 289 */ 290 @NonNull setIsStampVerified(boolean isStampVerified)291 public Builder setIsStampVerified(boolean isStampVerified) { 292 this.mIsStampVerified = isStampVerified; 293 return this; 294 } 295 296 /** 297 * Set whether the stamp embedded in the APK is trusted or not. 298 * 299 * @see AppInstallMetadata#isStampTrusted() 300 */ 301 @NonNull setIsStampTrusted(boolean isStampTrusted)302 public Builder setIsStampTrusted(boolean isStampTrusted) { 303 this.mIsStampTrusted = isStampTrusted; 304 return this; 305 } 306 307 /** 308 * Set certificate hash of the stamp embedded in the APK. 309 * 310 * <p>It is represented as the raw string encoding for the SHA-256 hash of the certificate 311 * of the stamp. 312 * 313 * @see AppInstallMetadata#getStampCertificateHash() 314 */ 315 @NonNull setStampCertificateHash(@onNull String stampCertificateHash)316 public Builder setStampCertificateHash(@NonNull String stampCertificateHash) { 317 this.mStampCertificateHash = Objects.requireNonNull(stampCertificateHash); 318 return this; 319 } 320 321 /** 322 * Build {@link AppInstallMetadata}. 323 * 324 * @throws IllegalArgumentException if package name or app certificate is null 325 */ 326 @NonNull build()327 public AppInstallMetadata build() { 328 Objects.requireNonNull(mPackageName); 329 Objects.requireNonNull(mAppCertificates); 330 Objects.requireNonNull(mAppCertificateLineage); 331 return new AppInstallMetadata(this); 332 } 333 } 334 } 335