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