1 /*
2  * Copyright (C) 2020 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.apksig;
18 
19 /**
20  * This class is intended as a lightweight representation of an APK signature verification issue
21  * where the client does not require the additional textual details provided by a subclass.
22  */
23 public class ApkVerificationIssue {
24     /* The V2 signer(s) could not be read from the V2 signature block */
25     public static final int V2_SIG_MALFORMED_SIGNERS = 1;
26     /* A V2 signature block exists without any V2 signers */
27     public static final int V2_SIG_NO_SIGNERS = 2;
28     /* Failed to parse a signer's block in the V2 signature block */
29     public static final int V2_SIG_MALFORMED_SIGNER = 3;
30     /* Failed to parse the signer's signature record in the V2 signature block */
31     public static final int V2_SIG_MALFORMED_SIGNATURE = 4;
32     /* The V2 signer contained no signatures */
33     public static final int V2_SIG_NO_SIGNATURES = 5;
34     /* The V2 signer's certificate could not be parsed */
35     public static final int V2_SIG_MALFORMED_CERTIFICATE = 6;
36     /* No signing certificates exist for the V2 signer */
37     public static final int V2_SIG_NO_CERTIFICATES = 7;
38     /* Failed to parse the V2 signer's digest record */
39     public static final int V2_SIG_MALFORMED_DIGEST = 8;
40     /* The V3 signer(s) could not be read from the V3 signature block */
41     public static final int V3_SIG_MALFORMED_SIGNERS = 9;
42     /* A V3 signature block exists without any V3 signers */
43     public static final int V3_SIG_NO_SIGNERS = 10;
44     /* Failed to parse a signer's block in the V3 signature block */
45     public static final int V3_SIG_MALFORMED_SIGNER = 11;
46     /* Failed to parse the signer's signature record in the V3 signature block */
47     public static final int V3_SIG_MALFORMED_SIGNATURE = 12;
48     /* The V3 signer contained no signatures */
49     public static final int V3_SIG_NO_SIGNATURES = 13;
50     /* The V3 signer's certificate could not be parsed */
51     public static final int V3_SIG_MALFORMED_CERTIFICATE = 14;
52     /* No signing certificates exist for the V3 signer */
53     public static final int V3_SIG_NO_CERTIFICATES = 15;
54     /* Failed to parse the V3 signer's digest record */
55     public static final int V3_SIG_MALFORMED_DIGEST = 16;
56     /* The source stamp signer contained no signatures */
57     public static final int SOURCE_STAMP_NO_SIGNATURE = 17;
58     /* The source stamp signer's certificate could not be parsed */
59     public static final int SOURCE_STAMP_MALFORMED_CERTIFICATE = 18;
60     /* The source stamp contains a signature produced using an unknown algorithm */
61     public static final int SOURCE_STAMP_UNKNOWN_SIG_ALGORITHM = 19;
62     /* Failed to parse the signer's signature in the source stamp signature block */
63     public static final int SOURCE_STAMP_MALFORMED_SIGNATURE = 20;
64     /* The source stamp's signature block failed verification */
65     public static final int SOURCE_STAMP_DID_NOT_VERIFY = 21;
66     /* An exception was encountered when verifying the source stamp */
67     public static final int SOURCE_STAMP_VERIFY_EXCEPTION = 22;
68     /* The certificate digest in the APK does not match the expected digest */
69     public static final int SOURCE_STAMP_EXPECTED_DIGEST_MISMATCH = 23;
70     /*
71      * The APK contains a source stamp signature block without a corresponding stamp certificate
72      * digest in the APK contents.
73      */
74     public static final int SOURCE_STAMP_SIGNATURE_BLOCK_WITHOUT_CERT_DIGEST = 24;
75     /*
76      * The APK does not contain the source stamp certificate digest file nor the source stamp
77      * signature block.
78      */
79     public static final int SOURCE_STAMP_CERT_DIGEST_AND_SIG_BLOCK_MISSING = 25;
80     /*
81      * None of the signatures provided by the source stamp were produced with a known signature
82      * algorithm.
83      */
84     public static final int SOURCE_STAMP_NO_SUPPORTED_SIGNATURE = 26;
85     /*
86      * The source stamp signer's certificate in the signing block does not match the certificate in
87      * the APK.
88      */
89     public static final int SOURCE_STAMP_CERTIFICATE_MISMATCH_BETWEEN_SIGNATURE_BLOCK_AND_APK = 27;
90     /* The APK could not be properly parsed due to a ZIP or APK format exception */
91     public static final int MALFORMED_APK = 28;
92     /* An unexpected exception was caught when attempting to verify the APK's signatures */
93     public static final int UNEXPECTED_EXCEPTION = 29;
94     /* The APK contains the certificate digest file but does not contain a stamp signature block */
95     public static final int SOURCE_STAMP_SIG_MISSING = 30;
96     /* Source stamp block contains a malformed attribute. */
97     public static final int SOURCE_STAMP_MALFORMED_ATTRIBUTE = 31;
98     /* Source stamp block contains an unknown attribute. */
99     public static final int SOURCE_STAMP_UNKNOWN_ATTRIBUTE = 32;
100     /**
101      * Failed to parse the SigningCertificateLineage structure in the source stamp
102      * attributes section.
103      */
104     public static final int SOURCE_STAMP_MALFORMED_LINEAGE = 33;
105     /**
106      * The source stamp certificate does not match the terminal node in the provided
107      * proof-of-rotation structure describing the stamp certificate history.
108      */
109     public static final int SOURCE_STAMP_POR_CERT_MISMATCH = 34;
110     /**
111      * The source stamp SigningCertificateLineage attribute contains a proof-of-rotation record
112      * with signature(s) that did not verify.
113      */
114     public static final int SOURCE_STAMP_POR_DID_NOT_VERIFY = 35;
115     /** No V1 / jar signing signature blocks were found in the APK. */
116     public static final int JAR_SIG_NO_SIGNATURES = 36;
117     /** An exception was encountered when parsing the V1 / jar signer in the signature block. */
118     public static final int JAR_SIG_PARSE_EXCEPTION = 37;
119     /** The source stamp timestamp attribute has an invalid value. */
120     public static final int SOURCE_STAMP_INVALID_TIMESTAMP = 38;
121     /**
122      * One or more digests for a signature scheme that is not in the source stamp were provided to
123      * the source stamp verifier.
124      */
125     public static final int SOURCE_STAMP_SIGNATURE_SCHEME_NOT_AVAILABLE = 39;
126 
127     private final int mIssueId;
128     private final String mFormat;
129     private final Object[] mParams;
130 
131     /**
132      * Constructs a new {@code ApkVerificationIssue} using the provided {@code format} string and
133      * {@code params}.
134      */
ApkVerificationIssue(String format, Object... params)135     public ApkVerificationIssue(String format, Object... params) {
136         mIssueId = -1;
137         mFormat = format;
138         mParams = params;
139     }
140 
141     /**
142      * Constructs a new {@code ApkVerificationIssue} using the provided {@code issueId} and {@code
143      * params}.
144      */
ApkVerificationIssue(int issueId, Object... params)145     public ApkVerificationIssue(int issueId, Object... params) {
146         mIssueId = issueId;
147         mFormat = null;
148         mParams = params;
149     }
150 
151     /**
152      * Returns the numeric ID for this issue.
153      */
getIssueId()154     public int getIssueId() {
155         return mIssueId;
156     }
157 
158     /**
159      * Returns the optional parameters for this issue.
160      */
getParams()161     public Object[] getParams() {
162         return mParams;
163     }
164 
165     @Override
toString()166     public String toString() {
167         // If this instance was created by a subclass with a format string then return the same
168         // formatted String as the subclass.
169         if (mFormat != null) {
170             return String.format(mFormat, mParams);
171         }
172         StringBuilder result = new StringBuilder("mIssueId: ").append(mIssueId);
173         for (Object param : mParams) {
174             result.append(", ").append(param.toString());
175         }
176         return result.toString();
177     }
178 }
179