• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.ondevicepersonalization.services.util;
18 
19 import static android.content.pm.PackageManager.GET_META_DATA;
20 import static android.content.pm.PackageManager.GET_SIGNING_CERTIFICATES;
21 import static android.content.pm.PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES;
22 
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.content.Context;
26 import android.content.pm.ApplicationInfo;
27 import android.content.pm.PackageInfo;
28 import android.content.pm.PackageManager;
29 import android.content.pm.Signature;
30 import android.content.pm.SigningInfo;
31 
32 import libcore.util.HexEncoding;
33 
34 import java.security.MessageDigest;
35 import java.security.NoSuchAlgorithmException;
36 
37 /**
38  * PackageUtils for OnDevicePersonalization module.
39  *
40  * @hide
41  */
42 public class PackageUtils {
PackageUtils()43     private PackageUtils() {
44     }
45 
46     /**
47      * Computes the SHA256 digest of some data.
48      *
49      * @param data The data.
50      * @return The digest or null if an error occurs.
51      */
52     @Nullable
computeSha256DigestBytes(@onNull byte[] data)53     public static byte[] computeSha256DigestBytes(@NonNull byte[] data) {
54         MessageDigest messageDigest;
55         try {
56             messageDigest = MessageDigest.getInstance("SHA256");
57         } catch (NoSuchAlgorithmException e) {
58             /* can't happen */
59             return null;
60         }
61 
62         messageDigest.update(data);
63 
64         return messageDigest.digest();
65     }
66 
67     /**
68      * Retrieves the certDigest of the given packageName
69      *
70      * @param context     Context of the calling service
71      * @param packageName Package name owning the certDigest
72      * @return certDigest of the given packageName
73      */
74     @Nullable
getCertDigest(@onNull Context context, @NonNull String packageName)75     public static String getCertDigest(@NonNull Context context, @NonNull String packageName) throws
76             PackageManager.NameNotFoundException {
77         PackageInfo sdkPackageInfo = context.getPackageManager().getPackageInfo(packageName,
78                 PackageManager.PackageInfoFlags.of(
79                         GET_SIGNING_CERTIFICATES | MATCH_STATIC_SHARED_AND_SDK_LIBRARIES));
80         SigningInfo signingInfo = sdkPackageInfo.signingInfo;
81         Signature[] signatures =
82                 signingInfo != null ? signingInfo.getSigningCertificateHistory() : null;
83         byte[] digest = PackageUtils.computeSha256DigestBytes(signatures[0].toByteArray());
84         return new String(HexEncoding.encode(digest));
85     }
86 
87     /**
88      * Determines if a package is debuggable
89      *
90      * @return true if the package is debuggable, false otherwise
91      */
isPackageDebuggable(@onNull Context context, @NonNull String packageName)92     public static boolean isPackageDebuggable(@NonNull Context context, @NonNull String packageName)
93             throws PackageManager.NameNotFoundException {
94         ApplicationInfo sdkApplicationInfo = context.getPackageManager().getApplicationInfo(
95                 packageName,
96                 PackageManager.ApplicationInfoFlags.of(
97                         GET_META_DATA));
98         return (sdkApplicationInfo.flags &= ApplicationInfo.FLAG_DEBUGGABLE) != 0;
99     }
100 }
101