15d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov/* 25d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * Copyright (C) 2016 The Android Open Source Project 35d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * 45d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * Licensed under the Apache License, Version 2.0 (the "License"); 55d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * you may not use this file except in compliance with the License. 65d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * You may obtain a copy of the License at 75d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * 85d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * http://www.apache.org/licenses/LICENSE-2.0 95d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * 105d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * Unless required by applicable law or agreed to in writing, software 115d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * distributed under the License is distributed on an "AS IS" BASIS, 125d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * See the License for the specific language governing permissions and 145d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * limitations under the License. 155d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov */ 165d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov 175d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganovpackage android.util; 185d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov 195d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganovimport android.annotation.NonNull; 205d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganovimport android.annotation.Nullable; 215d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganovimport android.content.pm.PackageInfo; 225d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganovimport android.content.pm.PackageManager; 235d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganovimport android.content.pm.Signature; 245d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov 255d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganovimport java.security.MessageDigest; 265d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganovimport java.security.NoSuchAlgorithmException; 275d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov 285d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov/** 295d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * Helper functions applicable to packages. 305d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * @hide 315d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov */ 325d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganovpublic final class PackageUtils { 335d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov 345d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov private PackageUtils() { 355d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov /* hide constructor */ 365d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov } 375d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov 385d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov /** 395d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * Computes the SHA256 digest of the signing cert for a package. 405d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * @param packageManager The package manager. 415d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * @param packageName The package for which to generate the digest. 425d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * @param userId The user for which to generate the digest. 435d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * @return The digest or null if the package does not exist for this user. 445d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov */ 455d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov public static @Nullable String computePackageCertSha256Digest( 465d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov @NonNull PackageManager packageManager, 475d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov @NonNull String packageName, int userId) { 485d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov final PackageInfo packageInfo; 495d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov try { 505d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov packageInfo = packageManager.getPackageInfoAsUser(packageName, 515d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov PackageManager.GET_SIGNATURES, userId); 525d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov } catch (PackageManager.NameNotFoundException e) { 535d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov return null; 545d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov } 555d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov return computeCertSha256Digest(packageInfo.signatures[0]); 565d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov } 575d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov 585d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov /** 595d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * Computes the SHA256 digest of a cert. 605d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * @param signature The signature. 615d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * @return The digest or null if an error occurs. 625d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov */ 635d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov public static @Nullable String computeCertSha256Digest(@NonNull Signature signature) { 645d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov return computeSha256Digest(signature.toByteArray()); 655d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov } 665d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov 675d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov /** 685d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * Computes the SHA256 digest of some data. 695d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * @param data The data. 705d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov * @return The digest or null if an error occurs. 715d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov */ 725d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov public static @Nullable String computeSha256Digest(@NonNull byte[] data) { 735d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov MessageDigest messageDigest; 745d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov try { 755d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov messageDigest = MessageDigest.getInstance("SHA256"); 765d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov } catch (NoSuchAlgorithmException e) { 775d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov /* can't happen */ 785d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov return null; 795d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov } 805d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov 815d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov messageDigest.update(data); 825d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov 837599f1366e8a08781f415e73f65cf270aae36868Mark Rathjen return ByteStringUtils.toHexString(messageDigest.digest()); 845d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov } 855d09c998a03eea53218c3b3c40e20db1b7693c9cSvet Ganov} 86