1 /* 2 * Copyright 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 androidx.security.app.authenticator; 18 19 import android.content.Context; 20 import android.content.pm.ApplicationInfo; 21 import android.content.pm.PackageManager; 22 import android.os.Binder; 23 import android.os.Build; 24 25 import org.jspecify.annotations.NonNull; 26 27 import java.security.MessageDigest; 28 import java.security.NoSuchAlgorithmException; 29 30 /** 31 * Provides utility methods that facilitate app signing identity verification. 32 */ 33 class AppAuthenticatorUtils { 34 private static final char[] HEX_CHARACTERS = "0123456789abcdef".toCharArray(); 35 36 private Context mContext; 37 38 /** 39 * Package private constructor accepting the {@code context} to be used for package queries. 40 */ AppAuthenticatorUtils(Context context)41 AppAuthenticatorUtils(Context context) { 42 mContext = context; 43 } 44 45 /** 46 * Returns the ID of the process that sent the current transaction being processed, or the ID 47 * of the current process if not currently processing a transaction. 48 * 49 * @see Binder#getCallingPid() 50 */ getCallingPid()51 int getCallingPid() { 52 return Binder.getCallingPid(); 53 } 54 55 /** 56 * Returns the uid assigned to the process that sent the current transaction being processed, 57 * or the uid assigned to the current process if not currently processing a transaction. 58 * 59 * @see Binder#getCallingUid() 60 */ getCallingUid()61 int getCallingUid() { 62 return Binder.getCallingUid(); 63 } 64 65 /** 66 * Returns the uid assigned to specified {@code packageName}. 67 * 68 * @throws PackageManager.NameNotFoundException if the specified package cannot be found on 69 * the device 70 * 71 * @see ApplicationInfo#uid 72 */ 73 @SuppressWarnings("deprecation") getUidForPackage(String packageName)74 int getUidForPackage(String packageName) throws PackageManager.NameNotFoundException { 75 ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo(packageName, 0); 76 return appInfo.uid; 77 } 78 79 /** 80 * Returns the API level as reported by {@code Build.VERSION.SDK_INT}. 81 */ getApiLevel()82 static int getApiLevel() { 83 return Build.VERSION.SDK_INT; 84 } 85 86 /** 87 * Computes the digest of the provided {@code data} using the specified {@code 88 * digestAlgorithm}, returning a {@code String} representing the hex encoding of the digest. 89 * 90 * <p>The specified {@code digestAlgorithm} must be one supported from API level 1; use of 91 * MD5 and SHA-1 are strongly discouraged. 92 */ computeDigest(@onNull String digestAlgorithm, byte @NonNull [] data)93 static String computeDigest(@NonNull String digestAlgorithm, byte @NonNull [] data) { 94 MessageDigest messageDigest; 95 try { 96 messageDigest = MessageDigest.getInstance(digestAlgorithm); 97 } catch (NoSuchAlgorithmException e) { 98 // Should never happen; the AppAuthenticator only accepts digest algorithms that are 99 // available from API level 1. 100 throw new AppAuthenticatorUtilsException(digestAlgorithm + " not supported on this " 101 + "device", e); 102 } 103 return toHexString(messageDigest.digest(data)); 104 } 105 106 /** 107 * Returns a {@code String} representing the hex encoding of the provided {@code data}. 108 */ toHexString(byte @NonNull [] data)109 static String toHexString(byte @NonNull [] data) { 110 char[] result = new char[data.length * 2]; 111 for (int i = 0; i < data.length; i++) { 112 int resultIndex = i * 2; 113 result[resultIndex] = HEX_CHARACTERS[(data[i] >> 4) & 0x0f]; 114 result[resultIndex + 1] = HEX_CHARACTERS[data[i] & 0x0f]; 115 } 116 return new String(result); 117 } 118 119 /** 120 * This {@code RuntimeException} is thrown when an unexpected error is encountered while 121 * performing a utility operation. 122 */ 123 private static class AppAuthenticatorUtilsException extends RuntimeException { AppAuthenticatorUtilsException(@onNull String message, Throwable reason)124 AppAuthenticatorUtilsException(@NonNull String message, Throwable reason) { 125 super(message, reason); 126 } 127 } 128 } 129