AppAuthenticatorUtils.java
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.security.app.authenticator;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Build;
import androidx.annotation.NonNull;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* Provides utility methods that facilitate app signing identity verification.
*/
class AppAuthenticatorUtils {
private static final char[] HEX_CHARACTERS = "0123456789abcdef".toCharArray();
private Context mContext;
/**
* Package private constructor accepting the {@code context} to be used for package queries.
*/
AppAuthenticatorUtils(Context context) {
mContext = context;
}
/**
* Returns the ID of the process that sent the current transaction being processed, or the ID
* of the current process if not currently processing a transaction.
*
* @see Binder#getCallingPid()
*/
int getCallingPid() {
return Binder.getCallingPid();
}
/**
* Returns the uid assigned to the process that sent the current transaction being processed,
* or the uid assigned to the current process if not currently processing a transaction.
*
* @see Binder#getCallingUid()
*/
int getCallingUid() {
return Binder.getCallingUid();
}
/**
* Returns the uid assigned to specified {@code packageName}.
*
* @throws PackageManager.NameNotFoundException if the specified package cannot be found on
* the device
*
* @see ApplicationInfo#uid
*/
int getUidForPackage(String packageName) throws PackageManager.NameNotFoundException {
ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo(packageName, 0);
return appInfo.uid;
}
/**
* Returns the API level as reported by {@code Build.VERSION.SDK_INT}.
*/
static int getApiLevel() {
return Build.VERSION.SDK_INT;
}
/**
* Computes the digest of the provided {@code data} using the specified {@code
* digestAlgorithm}, returning a {@code String} representing the hex encoding of the digest.
*
* <p>The specified {@code digestAlgorithm} must be one supported from API level 1; use of
* MD5 and SHA-1 are strongly discouraged.
*/
static String computeDigest(@NonNull String digestAlgorithm, @NonNull byte[] data) {
MessageDigest messageDigest;
try {
messageDigest = MessageDigest.getInstance(digestAlgorithm);
} catch (NoSuchAlgorithmException e) {
// Should never happen; the AppAuthenticator only accepts digest algorithms that are
// available from API level 1.
throw new AppAuthenticatorUtilsException(digestAlgorithm + " not supported on this "
+ "device", e);
}
return toHexString(messageDigest.digest(data));
}
/**
* Returns a {@code String} representing the hex encoding of the provided {@code data}.
*/
static String toHexString(@NonNull byte[] data) {
char[] result = new char[data.length * 2];
for (int i = 0; i < data.length; i++) {
int resultIndex = i * 2;
result[resultIndex] = HEX_CHARACTERS[(data[i] >> 4) & 0x0f];
result[resultIndex + 1] = HEX_CHARACTERS[data[i] & 0x0f];
}
return new String(result);
}
/**
* This {@code RuntimeException} is thrown when an unexpected error is encountered while
* performing a utility operation.
*/
private static class AppAuthenticatorUtilsException extends RuntimeException {
AppAuthenticatorUtilsException(@NonNull String message, Throwable reason) {
super(message, reason);
}
}
}