1 /* 2 * Copyright (C) 2011 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 com.android.server.pm; 18 19 import android.content.pm.PackageManager; 20 import android.util.SparseBooleanArray; 21 22 /** 23 * Tracks the package verification state for a particular package. Each package verification has a 24 * required verifier and zero or more sufficient verifiers. Only one of the sufficient verifier list 25 * must return affirmative to allow the package to be considered verified. If there are zero 26 * sufficient verifiers, then package verification is considered complete. 27 */ 28 class PackageVerificationState { 29 private final VerifyingSession mVerifyingSession; 30 31 private final SparseBooleanArray mSufficientVerifierUids; 32 33 private final SparseBooleanArray mRequiredVerifierUids; 34 private final SparseBooleanArray mUnrespondedRequiredVerifierUids; 35 36 private final SparseBooleanArray mExtendedTimeoutUids; 37 38 private boolean mSufficientVerificationComplete; 39 40 private boolean mSufficientVerificationPassed; 41 42 private boolean mRequiredVerificationComplete; 43 44 private boolean mRequiredVerificationPassed; 45 46 private boolean mIntegrityVerificationComplete; 47 48 /** 49 * Create a new package verification state where {@code requiredVerifierUid} is the user ID for 50 * the package that must reply affirmative before things can continue. 51 */ PackageVerificationState(VerifyingSession verifyingSession)52 PackageVerificationState(VerifyingSession verifyingSession) { 53 mVerifyingSession = verifyingSession; 54 mSufficientVerifierUids = new SparseBooleanArray(); 55 mRequiredVerifierUids = new SparseBooleanArray(); 56 mUnrespondedRequiredVerifierUids = new SparseBooleanArray(); 57 mExtendedTimeoutUids = new SparseBooleanArray(); 58 mRequiredVerificationComplete = false; 59 mRequiredVerificationPassed = true; 60 } 61 getVerifyingSession()62 VerifyingSession getVerifyingSession() { 63 return mVerifyingSession; 64 } 65 66 /** Add the user ID of the required package verifier. */ addRequiredVerifierUid(int uid)67 void addRequiredVerifierUid(int uid) { 68 mRequiredVerifierUids.put(uid, true); 69 mUnrespondedRequiredVerifierUids.put(uid, true); 70 } 71 72 /** Returns true if the uid a required verifier. */ checkRequiredVerifierUid(int uid)73 boolean checkRequiredVerifierUid(int uid) { 74 return mRequiredVerifierUids.get(uid, false); 75 } 76 77 /** 78 * Add a verifier which is added to our sufficient list. 79 * 80 * @param uid user ID of sufficient verifier 81 */ addSufficientVerifier(int uid)82 void addSufficientVerifier(int uid) { 83 mSufficientVerifierUids.put(uid, true); 84 } 85 86 /** Returns true if the uid a sufficient verifier. */ checkSufficientVerifierUid(int uid)87 boolean checkSufficientVerifierUid(int uid) { 88 return mSufficientVerifierUids.get(uid, false); 89 } 90 setVerifierResponseOnTimeout(int uid, int code)91 void setVerifierResponseOnTimeout(int uid, int code) { 92 if (!checkRequiredVerifierUid(uid)) { 93 return; 94 } 95 96 // Timeout, not waiting for the sufficient verifiers anymore. 97 mSufficientVerifierUids.clear(); 98 99 // Only if unresponded. 100 if (mUnrespondedRequiredVerifierUids.get(uid, false)) { 101 setVerifierResponse(uid, code); 102 } 103 } 104 105 /** 106 * Should be called when a verification is received from an agent so the state of the package 107 * verification can be tracked. 108 * 109 * @param uid user ID of the verifying agent 110 */ setVerifierResponse(int uid, int code)111 void setVerifierResponse(int uid, int code) { 112 if (mRequiredVerifierUids.get(uid)) { 113 switch (code) { 114 case PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT: 115 mSufficientVerifierUids.clear(); 116 // fall through 117 case PackageManager.VERIFICATION_ALLOW: 118 // Two possible options: 119 // - verification result is true, 120 // - another verifier set it to false. 121 // In both cases we don't need to assign anything, just exit. 122 break; 123 default: 124 mRequiredVerificationPassed = false; 125 // Required verifier rejected, no need to wait for the rest. 126 mUnrespondedRequiredVerifierUids.clear(); 127 mSufficientVerifierUids.clear(); 128 mExtendedTimeoutUids.clear(); 129 } 130 131 // Responded, no need to extend timeout. 132 mExtendedTimeoutUids.delete(uid); 133 134 mUnrespondedRequiredVerifierUids.delete(uid); 135 if (mUnrespondedRequiredVerifierUids.size() == 0) { 136 mRequiredVerificationComplete = true; 137 } 138 } else if (mSufficientVerifierUids.get(uid)) { 139 if (code == PackageManager.VERIFICATION_ALLOW) { 140 mSufficientVerificationPassed = true; 141 mSufficientVerificationComplete = true; 142 } 143 144 mSufficientVerifierUids.delete(uid); 145 if (mSufficientVerifierUids.size() == 0) { 146 mSufficientVerificationComplete = true; 147 } 148 } 149 } 150 151 /** 152 * Mark the session as passed required verification. 153 */ passRequiredVerification()154 void passRequiredVerification() { 155 if (mUnrespondedRequiredVerifierUids.size() > 0) { 156 throw new RuntimeException("Required verifiers still present."); 157 } 158 mRequiredVerificationPassed = true; 159 mRequiredVerificationComplete = true; 160 } 161 162 /** 163 * Returns whether verification is considered complete. This means that the required verifier 164 * and at least one of the sufficient verifiers has returned a positive verification. 165 * 166 * @return {@code true} when verification is considered complete 167 */ isVerificationComplete()168 boolean isVerificationComplete() { 169 if (!mRequiredVerificationComplete) { 170 return false; 171 } 172 173 if (mSufficientVerifierUids.size() == 0) { 174 return true; 175 } 176 177 return mSufficientVerificationComplete; 178 } 179 180 /** 181 * Returns whether installation should be allowed. This should only be called after {@link 182 * #isVerificationComplete()} returns {@code true}. 183 * 184 * @return {@code true} if installation should be allowed 185 */ isInstallAllowed()186 boolean isInstallAllowed() { 187 if (!mRequiredVerificationComplete || !mRequiredVerificationPassed) { 188 return false; 189 } 190 191 if (mSufficientVerificationComplete) { 192 return mSufficientVerificationPassed; 193 } 194 195 return true; 196 } 197 198 /** Extend the timeout for this Package to be verified. */ extendTimeout(int uid)199 boolean extendTimeout(int uid) { 200 if (!checkRequiredVerifierUid(uid) || timeoutExtended(uid)) { 201 return false; 202 } 203 mExtendedTimeoutUids.append(uid, true); 204 return true; 205 } 206 207 /** 208 * Returns whether the timeout was extended for verification. 209 * 210 * @return {@code true} if a timeout was already extended. 211 */ timeoutExtended(int uid)212 boolean timeoutExtended(int uid) { 213 return mExtendedTimeoutUids.get(uid, false); 214 } 215 setIntegrityVerificationResult(int code)216 void setIntegrityVerificationResult(int code) { 217 mIntegrityVerificationComplete = true; 218 } 219 isIntegrityVerificationComplete()220 boolean isIntegrityVerificationComplete() { 221 return mIntegrityVerificationComplete; 222 } 223 areAllVerificationsComplete()224 boolean areAllVerificationsComplete() { 225 return mIntegrityVerificationComplete && isVerificationComplete(); 226 } 227 } 228