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 AndroidSdkVersion.M), 43 44 /** 45 * RSASSA-PSS with SHA2-512 digest, SHA2-512 MGF1, 64 bytes of salt, trailer: 0xbc, content 46 * digested using SHA2-512 in 1 MB chunks. 47 */ 48 RSA_PSS_WITH_SHA512( 49 0x0102, 50 ContentDigestAlgorithm.CHUNKED_SHA512, 51 "RSA", 52 Pair.of( 53 "SHA512withRSA/PSS", 54 new PSSParameterSpec( 55 "SHA-512", "MGF1", MGF1ParameterSpec.SHA512, 512 / 8, 1)), 56 AndroidSdkVersion.N, 57 AndroidSdkVersion.M), 58 59 /** RSASSA-PKCS1-v1_5 with SHA2-256 digest, content digested using SHA2-256 in 1 MB chunks. */ 60 RSA_PKCS1_V1_5_WITH_SHA256( 61 0x0103, 62 ContentDigestAlgorithm.CHUNKED_SHA256, 63 "RSA", 64 Pair.of("SHA256withRSA", null), 65 AndroidSdkVersion.N, 66 AndroidSdkVersion.INITIAL_RELEASE), 67 68 /** RSASSA-PKCS1-v1_5 with SHA2-512 digest, content digested using SHA2-512 in 1 MB chunks. */ 69 RSA_PKCS1_V1_5_WITH_SHA512( 70 0x0104, 71 ContentDigestAlgorithm.CHUNKED_SHA512, 72 "RSA", 73 Pair.of("SHA512withRSA", null), 74 AndroidSdkVersion.N, 75 AndroidSdkVersion.INITIAL_RELEASE), 76 77 /** ECDSA with SHA2-256 digest, content digested using SHA2-256 in 1 MB chunks. */ 78 ECDSA_WITH_SHA256( 79 0x0201, 80 ContentDigestAlgorithm.CHUNKED_SHA256, 81 "EC", 82 Pair.of("SHA256withECDSA", null), 83 AndroidSdkVersion.N, 84 AndroidSdkVersion.HONEYCOMB), 85 86 /** ECDSA with SHA2-512 digest, content digested using SHA2-512 in 1 MB chunks. */ 87 ECDSA_WITH_SHA512( 88 0x0202, 89 ContentDigestAlgorithm.CHUNKED_SHA512, 90 "EC", 91 Pair.of("SHA512withECDSA", null), 92 AndroidSdkVersion.N, 93 AndroidSdkVersion.HONEYCOMB), 94 95 /** DSA with SHA2-256 digest, content digested using SHA2-256 in 1 MB chunks. */ 96 DSA_WITH_SHA256( 97 0x0301, 98 ContentDigestAlgorithm.CHUNKED_SHA256, 99 "DSA", 100 Pair.of("SHA256withDSA", null), 101 AndroidSdkVersion.N, 102 AndroidSdkVersion.INITIAL_RELEASE), 103 104 /** 105 * DSA with SHA2-256 digest, content digested using SHA2-256 in 1 MB chunks. Signing is done 106 * deterministically according to RFC 6979. 107 */ 108 DETDSA_WITH_SHA256( 109 0x0301, 110 ContentDigestAlgorithm.CHUNKED_SHA256, 111 "DSA", 112 Pair.of("SHA256withDetDSA", null), 113 AndroidSdkVersion.N, 114 AndroidSdkVersion.INITIAL_RELEASE), 115 116 /** 117 * RSASSA-PKCS1-v1_5 with SHA2-256 digest, content digested using SHA2-256 in 4 KB chunks, in 118 * the same way fsverity operates. This digest and the content length (before digestion, 8 bytes 119 * in little endian) construct the final digest. 120 */ 121 VERITY_RSA_PKCS1_V1_5_WITH_SHA256( 122 0x0421, 123 ContentDigestAlgorithm.VERITY_CHUNKED_SHA256, 124 "RSA", 125 Pair.of("SHA256withRSA", null), 126 AndroidSdkVersion.P, 127 AndroidSdkVersion.INITIAL_RELEASE), 128 129 /** 130 * ECDSA with SHA2-256 digest, content digested using SHA2-256 in 4 KB chunks, in the same way 131 * fsverity operates. This digest and the content length (before digestion, 8 bytes in little 132 * endian) construct the final digest. 133 */ 134 VERITY_ECDSA_WITH_SHA256( 135 0x0423, 136 ContentDigestAlgorithm.VERITY_CHUNKED_SHA256, 137 "EC", 138 Pair.of("SHA256withECDSA", null), 139 AndroidSdkVersion.P, 140 AndroidSdkVersion.HONEYCOMB), 141 142 /** 143 * DSA with SHA2-256 digest, content digested using SHA2-256 in 4 KB chunks, in the same way 144 * fsverity operates. This digest and the content length (before digestion, 8 bytes in little 145 * endian) construct the final digest. 146 */ 147 VERITY_DSA_WITH_SHA256( 148 0x0425, 149 ContentDigestAlgorithm.VERITY_CHUNKED_SHA256, 150 "DSA", 151 Pair.of("SHA256withDSA", null), 152 AndroidSdkVersion.P, 153 AndroidSdkVersion.INITIAL_RELEASE); 154 155 private final int mId; 156 private final String mJcaKeyAlgorithm; 157 private final ContentDigestAlgorithm mContentDigestAlgorithm; 158 private final Pair<String, ? extends AlgorithmParameterSpec> mJcaSignatureAlgAndParams; 159 private final int mMinSdkVersion; 160 private final int mJcaSigAlgMinSdkVersion; 161 SignatureAlgorithm(int id, ContentDigestAlgorithm contentDigestAlgorithm, String jcaKeyAlgorithm, Pair<String, ? extends AlgorithmParameterSpec> jcaSignatureAlgAndParams, int minSdkVersion, int jcaSigAlgMinSdkVersion)162 SignatureAlgorithm(int id, 163 ContentDigestAlgorithm contentDigestAlgorithm, 164 String jcaKeyAlgorithm, 165 Pair<String, ? extends AlgorithmParameterSpec> jcaSignatureAlgAndParams, 166 int minSdkVersion, 167 int jcaSigAlgMinSdkVersion) { 168 mId = id; 169 mContentDigestAlgorithm = contentDigestAlgorithm; 170 mJcaKeyAlgorithm = jcaKeyAlgorithm; 171 mJcaSignatureAlgAndParams = jcaSignatureAlgAndParams; 172 mMinSdkVersion = minSdkVersion; 173 mJcaSigAlgMinSdkVersion = jcaSigAlgMinSdkVersion; 174 } 175 176 /** 177 * Returns the ID of this signature algorithm as used in APK Signature Scheme v2 wire format. 178 */ getId()179 public int getId() { 180 return mId; 181 } 182 183 /** 184 * Returns the content digest algorithm associated with this signature algorithm. 185 */ getContentDigestAlgorithm()186 public ContentDigestAlgorithm getContentDigestAlgorithm() { 187 return mContentDigestAlgorithm; 188 } 189 190 /** 191 * Returns the JCA {@link java.security.Key} algorithm used by this signature scheme. 192 */ getJcaKeyAlgorithm()193 public String getJcaKeyAlgorithm() { 194 return mJcaKeyAlgorithm; 195 } 196 197 /** 198 * Returns the {@link java.security.Signature} algorithm and the {@link AlgorithmParameterSpec} 199 * (or null if not needed) to parameterize the {@code Signature}. 200 */ getJcaSignatureAlgorithmAndParams()201 public Pair<String, ? extends AlgorithmParameterSpec> getJcaSignatureAlgorithmAndParams() { 202 return mJcaSignatureAlgAndParams; 203 } 204 getMinSdkVersion()205 public int getMinSdkVersion() { 206 return mMinSdkVersion; 207 } 208 209 /** 210 * Returns the minimum SDK version that supports the JCA signature algorithm. 211 */ getJcaSigAlgMinSdkVersion()212 public int getJcaSigAlgMinSdkVersion() { 213 return mJcaSigAlgMinSdkVersion; 214 } 215 findById(int id)216 public static SignatureAlgorithm findById(int id) { 217 for (SignatureAlgorithm alg : SignatureAlgorithm.values()) { 218 if (alg.getId() == id) { 219 return alg; 220 } 221 } 222 223 return null; 224 } 225 } 226