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 private final String mInstallerName; 41 // Raw string encoding for the SHA-256 hash of the certificate of the installer. 42 private final List<String> mInstallerCertificates; 43 private final long mVersionCode; 44 private final boolean mIsPreInstalled; 45 private final boolean mIsStampPresent; 46 private final boolean mIsStampVerified; 47 private final boolean mIsStampTrusted; 48 // Raw string encoding for the SHA-256 hash of the certificate of the stamp. 49 private final String mStampCertificateHash; 50 private final Map<String, String> mAllowedInstallersAndCertificates; 51 AppInstallMetadata(Builder builder)52 private AppInstallMetadata(Builder builder) { 53 this.mPackageName = builder.mPackageName; 54 this.mAppCertificates = builder.mAppCertificates; 55 this.mInstallerName = builder.mInstallerName; 56 this.mInstallerCertificates = builder.mInstallerCertificates; 57 this.mVersionCode = builder.mVersionCode; 58 this.mIsPreInstalled = builder.mIsPreInstalled; 59 this.mIsStampPresent = builder.mIsStampPresent; 60 this.mIsStampVerified = builder.mIsStampVerified; 61 this.mIsStampTrusted = builder.mIsStampTrusted; 62 this.mStampCertificateHash = builder.mStampCertificateHash; 63 this.mAllowedInstallersAndCertificates = builder.mAllowedInstallersAndCertificates; 64 } 65 66 @NonNull getPackageName()67 public String getPackageName() { 68 return mPackageName; 69 } 70 71 @NonNull getAppCertificates()72 public List<String> getAppCertificates() { 73 return mAppCertificates; 74 } 75 76 @NonNull getInstallerName()77 public String getInstallerName() { 78 return mInstallerName; 79 } 80 81 @NonNull getInstallerCertificates()82 public List<String> getInstallerCertificates() { 83 return mInstallerCertificates; 84 } 85 86 /** @see AppInstallMetadata.Builder#setVersionCode(long) */ getVersionCode()87 public long getVersionCode() { 88 return mVersionCode; 89 } 90 91 /** @see AppInstallMetadata.Builder#setIsPreInstalled(boolean) */ isPreInstalled()92 public boolean isPreInstalled() { 93 return mIsPreInstalled; 94 } 95 96 /** @see AppInstallMetadata.Builder#setIsStampPresent(boolean) */ isStampPresent()97 public boolean isStampPresent() { 98 return mIsStampPresent; 99 } 100 101 /** @see AppInstallMetadata.Builder#setIsStampVerified(boolean) */ isStampVerified()102 public boolean isStampVerified() { 103 return mIsStampVerified; 104 } 105 106 /** @see AppInstallMetadata.Builder#setIsStampTrusted(boolean) */ isStampTrusted()107 public boolean isStampTrusted() { 108 return mIsStampTrusted; 109 } 110 111 /** @see AppInstallMetadata.Builder#setStampCertificateHash(String) */ getStampCertificateHash()112 public String getStampCertificateHash() { 113 return mStampCertificateHash; 114 } 115 116 /** Get the allowed installers and their corresponding cert. */ getAllowedInstallersAndCertificates()117 public Map<String, String> getAllowedInstallersAndCertificates() { 118 return mAllowedInstallersAndCertificates; 119 } 120 121 @Override toString()122 public String toString() { 123 return String.format( 124 "AppInstallMetadata { PackageName = %s, AppCerts = %s, InstallerName = %s," 125 + " InstallerCerts = %s, VersionCode = %d, PreInstalled = %b, StampPresent =" 126 + " %b, StampVerified = %b, StampTrusted = %b, StampCert = %s }", 127 mPackageName, 128 mAppCertificates, 129 mInstallerName == null ? "null" : mInstallerName, 130 mInstallerCertificates == null ? "null" : mInstallerCertificates, 131 mVersionCode, 132 mIsPreInstalled, 133 mIsStampPresent, 134 mIsStampVerified, 135 mIsStampTrusted, 136 mStampCertificateHash == null ? "null" : mStampCertificateHash); 137 } 138 139 /** Builder class for constructing {@link AppInstallMetadata} objects. */ 140 public static final class Builder { 141 private String mPackageName; 142 private List<String> mAppCertificates; 143 private String mInstallerName; 144 private List<String> mInstallerCertificates; 145 private long mVersionCode; 146 private boolean mIsPreInstalled; 147 private boolean mIsStampPresent; 148 private boolean mIsStampVerified; 149 private boolean mIsStampTrusted; 150 private String mStampCertificateHash; 151 private Map<String, String> mAllowedInstallersAndCertificates; 152 Builder()153 public Builder() { 154 mAllowedInstallersAndCertificates = new HashMap<>(); 155 } 156 157 /** 158 * Add allowed installers and cert. 159 * 160 * @see AppInstallMetadata#getAllowedInstallersAndCertificates() 161 */ 162 @NonNull setAllowedInstallersAndCert( @onNull Map<String, String> allowedInstallersAndCertificates)163 public Builder setAllowedInstallersAndCert( 164 @NonNull Map<String, String> allowedInstallersAndCertificates) { 165 this.mAllowedInstallersAndCertificates = allowedInstallersAndCertificates; 166 return this; 167 } 168 169 /** 170 * Set package name of the app to be installed. 171 * 172 * @see AppInstallMetadata#getPackageName() 173 */ 174 @NonNull setPackageName(@onNull String packageName)175 public Builder setPackageName(@NonNull String packageName) { 176 this.mPackageName = Objects.requireNonNull(packageName); 177 return this; 178 } 179 180 /** 181 * Set certificate of the app to be installed. 182 * 183 * <p>It is represented as the raw string encoding for the SHA-256 hash of the certificate 184 * of the app. 185 * 186 * @see AppInstallMetadata#getAppCertificates() 187 */ 188 @NonNull setAppCertificates(@onNull List<String> appCertificates)189 public Builder setAppCertificates(@NonNull List<String> appCertificates) { 190 this.mAppCertificates = Objects.requireNonNull(appCertificates); 191 return this; 192 } 193 194 /** 195 * Set name of the installer installing the app. 196 * 197 * @see AppInstallMetadata#getInstallerName() 198 */ 199 @NonNull setInstallerName(@onNull String installerName)200 public Builder setInstallerName(@NonNull String installerName) { 201 this.mInstallerName = Objects.requireNonNull(installerName); 202 return this; 203 } 204 205 /** 206 * Set certificate of the installer installing the app. 207 * 208 * <p>It is represented as the raw string encoding for the SHA-256 hash of the certificate 209 * of the installer. 210 * 211 * @see AppInstallMetadata#getInstallerCertificates() 212 */ 213 @NonNull setInstallerCertificates(@onNull List<String> installerCertificates)214 public Builder setInstallerCertificates(@NonNull List<String> installerCertificates) { 215 this.mInstallerCertificates = Objects.requireNonNull(installerCertificates); 216 return this; 217 } 218 219 /** 220 * Set version code of the app to be installed. 221 * 222 * @see AppInstallMetadata#getVersionCode() 223 */ 224 @NonNull setVersionCode(long versionCode)225 public Builder setVersionCode(long versionCode) { 226 this.mVersionCode = versionCode; 227 return this; 228 } 229 230 /** 231 * Set whether the app is pre-installed on the device or not. 232 * 233 * @see AppInstallMetadata#isPreInstalled() 234 */ 235 @NonNull setIsPreInstalled(boolean isPreInstalled)236 public Builder setIsPreInstalled(boolean isPreInstalled) { 237 this.mIsPreInstalled = isPreInstalled; 238 return this; 239 } 240 241 /** 242 * Set whether the stamp embedded in the APK is present or not. 243 * 244 * @see AppInstallMetadata#isStampPresent() 245 */ 246 @NonNull setIsStampPresent(boolean isStampPresent)247 public Builder setIsStampPresent(boolean isStampPresent) { 248 this.mIsStampPresent = isStampPresent; 249 return this; 250 } 251 252 /** 253 * Set whether the stamp embedded in the APK is verified or not. 254 * 255 * @see AppInstallMetadata#isStampVerified() 256 */ 257 @NonNull setIsStampVerified(boolean isStampVerified)258 public Builder setIsStampVerified(boolean isStampVerified) { 259 this.mIsStampVerified = isStampVerified; 260 return this; 261 } 262 263 /** 264 * Set whether the stamp embedded in the APK is trusted or not. 265 * 266 * @see AppInstallMetadata#isStampTrusted() 267 */ 268 @NonNull setIsStampTrusted(boolean isStampTrusted)269 public Builder setIsStampTrusted(boolean isStampTrusted) { 270 this.mIsStampTrusted = isStampTrusted; 271 return this; 272 } 273 274 /** 275 * Set certificate hash of the stamp embedded in the APK. 276 * 277 * <p>It is represented as the raw string encoding for the SHA-256 hash of the certificate 278 * of the stamp. 279 * 280 * @see AppInstallMetadata#getStampCertificateHash() 281 */ 282 @NonNull setStampCertificateHash(@onNull String stampCertificateHash)283 public Builder setStampCertificateHash(@NonNull String stampCertificateHash) { 284 this.mStampCertificateHash = Objects.requireNonNull(stampCertificateHash); 285 return this; 286 } 287 288 /** 289 * Build {@link AppInstallMetadata}. 290 * 291 * @throws IllegalArgumentException if package name or app certificate is null 292 */ 293 @NonNull build()294 public AppInstallMetadata build() { 295 Objects.requireNonNull(mPackageName); 296 Objects.requireNonNull(mAppCertificates); 297 return new AppInstallMetadata(this); 298 } 299 } 300 } 301