Home | History | Annotate | Download | only in pm
      1 /*
      2  * Copyright (C) 2018 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 android.content.pm;
     18 
     19 
     20 import android.annotation.NonNull;
     21 import android.os.Parcel;
     22 import android.os.Parcelable;
     23 
     24 /**
     25  * Information pertaining to the signing certificates used to sign a package.
     26  */
     27 public final class SigningInfo implements Parcelable {
     28 
     29     @NonNull
     30     private final PackageParser.SigningDetails mSigningDetails;
     31 
     32     public SigningInfo() {
     33         mSigningDetails = PackageParser.SigningDetails.UNKNOWN;
     34     }
     35 
     36     /**
     37      * @hide only packagemanager should be populating this
     38      */
     39     public SigningInfo(PackageParser.SigningDetails signingDetails) {
     40         mSigningDetails = new PackageParser.SigningDetails(signingDetails);
     41     }
     42 
     43     public SigningInfo(SigningInfo orig) {
     44         mSigningDetails = new PackageParser.SigningDetails(orig.mSigningDetails);
     45     }
     46 
     47     private SigningInfo(Parcel source) {
     48         mSigningDetails = PackageParser.SigningDetails.CREATOR.createFromParcel(source);
     49     }
     50 
     51     /**
     52      * Although relatively uncommon, packages may be signed by more than one signer, in which case
     53      * their identity is viewed as being the set of all signers, not just any one.
     54      */
     55     public boolean hasMultipleSigners() {
     56         return mSigningDetails.signatures != null && mSigningDetails.signatures.length > 1;
     57     }
     58 
     59     /**
     60      * APK Signature Scheme v3 enables packages to provide a proof-of-rotation record that the
     61      * platform verifies, and uses, to allow the use of new signing certificates.  This is only
     62      * available to packages that are not signed by multiple signers.  In the event of a change to a
     63      * new signing certificate, the package's past signing certificates are presented as well.  Any
     64      * check of a package's signing certificate should also include a search through its entire
     65      * signing history, since it could change to a new signing certificate at any time.
     66      */
     67     public boolean hasPastSigningCertificates() {
     68         return mSigningDetails.signatures != null
     69                 && mSigningDetails.pastSigningCertificates != null;
     70     }
     71 
     72     /**
     73      * Returns the signing certificates this package has proven it is authorized to use. This
     74      * includes both the signing certificate associated with the signer of the package and the past
     75      * signing certificates it included as its proof of signing certificate rotation.  This method
     76      * is the preferred replacement for the {@code GET_SIGNATURES} flag used with {@link
     77      * PackageManager#getPackageInfo(String, int)}.  When determining if a package is signed by a
     78      * desired certificate, the returned array should be checked to determine if it is one of the
     79      * entries.
     80      *
     81      * <note>
     82      *     This method returns null if the package is signed by multiple signing certificates, as
     83      *     opposed to being signed by one current signer and also providing the history of past
     84      *     signing certificates.  {@link #hasMultipleSigners()} may be used to determine if this
     85      *     package is signed by multiple signers.  Packages which are signed by multiple signers
     86      *     cannot change their signing certificates and their {@code Signature} array should be
     87      *     checked to make sure that every entry matches the looked-for signing certificates.
     88      * </note>
     89      */
     90     public Signature[] getSigningCertificateHistory() {
     91         if (hasMultipleSigners()) {
     92             return null;
     93         } else if (!hasPastSigningCertificates()) {
     94 
     95             // this package is only signed by one signer with no history, return it
     96             return mSigningDetails.signatures;
     97         } else {
     98 
     99             // this package has provided proof of past signing certificates, include them
    100             return mSigningDetails.pastSigningCertificates;
    101         }
    102     }
    103 
    104     /**
    105      * Returns the signing certificates used to sign the APK contents of this application.  Not
    106      * including any past signing certificates the package proved it is authorized to use.
    107      * <note>
    108      *     This method should not be used unless {@link #hasMultipleSigners()} returns true,
    109      *     indicating that {@link #getSigningCertificateHistory()} cannot be used, otherwise {@link
    110      *     #getSigningCertificateHistory()} should be preferred.
    111      * </note>
    112      */
    113     public Signature[] getApkContentsSigners() {
    114         return mSigningDetails.signatures;
    115     }
    116 
    117     @Override
    118     public int describeContents() {
    119         return 0;
    120     }
    121 
    122     @Override
    123     public void writeToParcel(Parcel dest, int parcelableFlags) {
    124         mSigningDetails.writeToParcel(dest, parcelableFlags);
    125     }
    126 
    127     public static final Parcelable.Creator<SigningInfo> CREATOR =
    128             new Parcelable.Creator<SigningInfo>() {
    129         @Override
    130         public SigningInfo createFromParcel(Parcel source) {
    131             return new SigningInfo(source);
    132         }
    133 
    134         @Override
    135         public SigningInfo[] newArray(int size) {
    136             return new SigningInfo[size];
    137         }
    138     };
    139 }
    140