1 /*
2  * Copyright (C) 2016 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.internal.apk;
18 
19 import com.android.apksig.internal.util.AndroidSdkVersion;
20 import com.android.apksig.internal.util.Pair;
21 import java.security.spec.AlgorithmParameterSpec;
22 import java.security.spec.MGF1ParameterSpec;
23 import java.security.spec.PSSParameterSpec;
24 
25 /**
26  * APK Signing Block signature algorithm.
27  */
28 public enum SignatureAlgorithm {
29     // TODO reserve the 0x0000 ID to mean null
30     /**
31      * RSASSA-PSS with SHA2-256 digest, SHA2-256 MGF1, 32 bytes of salt, trailer: 0xbc, content
32      * digested using SHA2-256 in 1 MB chunks.
33      */
34     RSA_PSS_WITH_SHA256(
35             0x0101,
36             ContentDigestAlgorithm.CHUNKED_SHA256,
37             "RSA",
38             Pair.of("SHA256withRSA/PSS",
39                     new PSSParameterSpec(
40                             "SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 256 / 8, 1)),
41             AndroidSdkVersion.N),
42 
43     /**
44      * RSASSA-PSS with SHA2-512 digest, SHA2-512 MGF1, 64 bytes of salt, trailer: 0xbc, content
45      * digested using SHA2-512 in 1 MB chunks.
46      */
47     RSA_PSS_WITH_SHA512(
48             0x0102,
49             ContentDigestAlgorithm.CHUNKED_SHA512,
50             "RSA",
51             Pair.of(
52                     "SHA512withRSA/PSS",
53                     new PSSParameterSpec(
54                             "SHA-512", "MGF1", MGF1ParameterSpec.SHA512, 512 / 8, 1)),
55             AndroidSdkVersion.N),
56 
57     /** RSASSA-PKCS1-v1_5 with SHA2-256 digest, content digested using SHA2-256 in 1 MB chunks. */
58     RSA_PKCS1_V1_5_WITH_SHA256(
59             0x0103,
60             ContentDigestAlgorithm.CHUNKED_SHA256,
61             "RSA",
62             Pair.of("SHA256withRSA", null),
63             AndroidSdkVersion.N),
64 
65     /** RSASSA-PKCS1-v1_5 with SHA2-512 digest, content digested using SHA2-512 in 1 MB chunks. */
66     RSA_PKCS1_V1_5_WITH_SHA512(
67             0x0104,
68             ContentDigestAlgorithm.CHUNKED_SHA512,
69             "RSA",
70             Pair.of("SHA512withRSA", null),
71             AndroidSdkVersion.N),
72 
73     /** ECDSA with SHA2-256 digest, content digested using SHA2-256 in 1 MB chunks. */
74     ECDSA_WITH_SHA256(
75             0x0201,
76             ContentDigestAlgorithm.CHUNKED_SHA256,
77             "EC",
78             Pair.of("SHA256withECDSA", null),
79             AndroidSdkVersion.N),
80 
81     /** ECDSA with SHA2-512 digest, content digested using SHA2-512 in 1 MB chunks. */
82     ECDSA_WITH_SHA512(
83             0x0202,
84             ContentDigestAlgorithm.CHUNKED_SHA512,
85             "EC",
86             Pair.of("SHA512withECDSA", null),
87             AndroidSdkVersion.N),
88 
89     /** DSA with SHA2-256 digest, content digested using SHA2-256 in 1 MB chunks. */
90     DSA_WITH_SHA256(
91             0x0301,
92             ContentDigestAlgorithm.CHUNKED_SHA256,
93             "DSA",
94             Pair.of("SHA256withDSA", null),
95             AndroidSdkVersion.N),
96 
97     /**
98      * RSASSA-PKCS1-v1_5 with SHA2-256 digest, content digested using SHA2-256 in 4 KB chunks, in
99      * the same way fsverity operates. This digest and the content length (before digestion, 8 bytes
100      * in little endian) construct the final digest.
101      */
102     VERITY_RSA_PKCS1_V1_5_WITH_SHA256(
103             0x0421,
104             ContentDigestAlgorithm.VERITY_CHUNKED_SHA256,
105             "RSA",
106             Pair.of("SHA256withRSA", null),
107             AndroidSdkVersion.P),
108 
109     /**
110      * ECDSA with SHA2-256 digest, content digested using SHA2-256 in 4 KB chunks, in the same way
111      * fsverity operates. This digest and the content length (before digestion, 8 bytes in little
112      * endian) construct the final digest.
113      */
114     VERITY_ECDSA_WITH_SHA256(
115             0x0423,
116             ContentDigestAlgorithm.VERITY_CHUNKED_SHA256,
117             "EC",
118             Pair.of("SHA256withECDSA", null),
119             AndroidSdkVersion.P),
120 
121     /**
122      * DSA with SHA2-256 digest, content digested using SHA2-256 in 4 KB chunks, in the same way
123      * fsverity operates. This digest and the content length (before digestion, 8 bytes in little
124      * endian) construct the final digest.
125      */
126     VERITY_DSA_WITH_SHA256(
127             0x0425,
128             ContentDigestAlgorithm.VERITY_CHUNKED_SHA256,
129             "DSA",
130             Pair.of("SHA256withDSA", null),
131             AndroidSdkVersion.P);
132 
133     private final int mId;
134     private final String mJcaKeyAlgorithm;
135     private final ContentDigestAlgorithm mContentDigestAlgorithm;
136     private final Pair<String, ? extends AlgorithmParameterSpec> mJcaSignatureAlgAndParams;
137     private final int mMinSdkVersion;
138 
SignatureAlgorithm(int id, ContentDigestAlgorithm contentDigestAlgorithm, String jcaKeyAlgorithm, Pair<String, ? extends AlgorithmParameterSpec> jcaSignatureAlgAndParams, int minSdkVersion)139     SignatureAlgorithm(int id,
140             ContentDigestAlgorithm contentDigestAlgorithm,
141             String jcaKeyAlgorithm,
142             Pair<String, ? extends AlgorithmParameterSpec> jcaSignatureAlgAndParams,
143             int minSdkVersion) {
144         mId = id;
145         mContentDigestAlgorithm = contentDigestAlgorithm;
146         mJcaKeyAlgorithm = jcaKeyAlgorithm;
147         mJcaSignatureAlgAndParams = jcaSignatureAlgAndParams;
148         mMinSdkVersion = minSdkVersion;
149     }
150 
151     /**
152      * Returns the ID of this signature algorithm as used in APK Signature Scheme v2 wire format.
153      */
getId()154     public int getId() {
155         return mId;
156     }
157 
158     /**
159      * Returns the content digest algorithm associated with this signature algorithm.
160      */
getContentDigestAlgorithm()161     public ContentDigestAlgorithm getContentDigestAlgorithm() {
162         return mContentDigestAlgorithm;
163     }
164 
165     /**
166      * Returns the JCA {@link java.security.Key} algorithm used by this signature scheme.
167      */
getJcaKeyAlgorithm()168     public String getJcaKeyAlgorithm() {
169         return mJcaKeyAlgorithm;
170     }
171 
172     /**
173      * Returns the {@link java.security.Signature} algorithm and the {@link AlgorithmParameterSpec}
174      * (or null if not needed) to parameterize the {@code Signature}.
175      */
getJcaSignatureAlgorithmAndParams()176     public Pair<String, ? extends AlgorithmParameterSpec> getJcaSignatureAlgorithmAndParams() {
177         return mJcaSignatureAlgAndParams;
178     }
179 
getMinSdkVersion()180     public int getMinSdkVersion() {
181         return mMinSdkVersion;
182     }
183 
findById(int id)184     public static SignatureAlgorithm findById(int id) {
185         for (SignatureAlgorithm alg : SignatureAlgorithm.values()) {
186             if (alg.getId() == id) {
187                 return alg;
188             }
189         }
190 
191         return null;
192     }
193 }
194