Loading tools/apksigner/core/src/com/android/apksigner/core/ApkVerifier.java +15 −0 Original line number Diff line number Diff line Loading @@ -662,6 +662,21 @@ public class ApkVerifier { */ JAR_SIG_VERIFY_EXCEPTION("Failed to verify JAR signature %1$s against %2$s: %3$s"), /** * JAR signature contains unsupported digest algorithm. * * <ul> * <li>Parameter 1: name of the signature block file ({@code String})</li> * <li>Parameter 2: digest algorithm OID ({@code String})</li> * <li>Parameter 2: signature algorithm OID ({@code String})</li> * <li>Parameter 3: API Levels on which this combination of algorithms is not supported * ({@code String})</li> * </ul> */ JAR_SIG_UNSUPPORTED_SIG_ALG( "JAR signature %1$s uses digest algorithm %2$s and signature algorithm %3$s which" + " is not supported on API Levels %4$s"), /** * An exception was encountered while parsing JAR signature contained in a signature block. * Loading tools/apksigner/core/src/com/android/apksigner/core/internal/apk/v1/V1SchemeSigner.java +2 −1 Original line number Diff line number Diff line Loading @@ -562,7 +562,8 @@ public abstract class V1SchemeSigner { // SignatureAlgorithm: dsaWithSha256 (2.16.840.1.101.3.4.3.2) and // dsa (1.2.840.10040.4.1). The latter works only on API Level 22+. Thus, we use // the former. sigAlgId = getSupportedAlgorithmId("2.16.840.1.101.3.4.3.2"); // DSA with SHA-256 sigAlgId = getSupportedAlgorithmId("2.16.840.1.101.3.4.3.2"); // DSA with SHA-256 break; default: throw new IllegalArgumentException( Loading tools/apksigner/core/src/com/android/apksigner/core/internal/apk/v1/V1SchemeVerifier.java +371 −4 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import com.android.apksigner.core.ApkVerifier.IssueWithParams; import com.android.apksigner.core.apk.ApkUtils; import com.android.apksigner.core.internal.jar.ManifestParser; import com.android.apksigner.core.internal.util.AndroidSdkVersion; import com.android.apksigner.core.internal.util.InclusiveIntRange; import com.android.apksigner.core.internal.util.MessageDigestSink; import com.android.apksigner.core.internal.zip.CentralDirectoryRecord; import com.android.apksigner.core.internal.zip.LocalFileHeader; Loading Loading @@ -412,7 +413,8 @@ public abstract class V1SchemeVerifier { mResult.addError( Issue.JAR_SIG_MALFORMED_CERTIFICATE, mSignatureBlockEntry.getName(), e); } else { mResult.addError(Issue.JAR_SIG_PARSE_EXCEPTION, mSignatureBlockEntry.getName(), e); mResult.addError( Issue.JAR_SIG_PARSE_EXCEPTION, mSignatureBlockEntry.getName(), e); } return; } Loading @@ -426,7 +428,25 @@ public abstract class V1SchemeVerifier { if ((unverifiedSignerInfos != null) && (unverifiedSignerInfos.length > 0)) { for (int i = 0; i < unverifiedSignerInfos.length; i++) { SignerInfo unverifiedSignerInfo = unverifiedSignerInfos[i]; // TODO: Reject sig/dig algorithms not supported on Android String digestAlgorithmOid = unverifiedSignerInfo.getDigestAlgorithmId().getOID().toString(); String signatureAlgorithmOid = unverifiedSignerInfo .getDigestEncryptionAlgorithmId().getOID().toString(); InclusiveIntRange desiredApiLevels = InclusiveIntRange.from(minSdkVersion); List<InclusiveIntRange> apiLevelsWhereDigestAndSigAlgorithmSupported = getSigAlgSupportedApiLevels(digestAlgorithmOid, signatureAlgorithmOid); List<InclusiveIntRange> apiLevelsWhereDigestAlgorithmNotSupported = desiredApiLevels.getValuesNotIn(apiLevelsWhereDigestAndSigAlgorithmSupported); if (!apiLevelsWhereDigestAlgorithmNotSupported.isEmpty()) { mResult.addError( Issue.JAR_SIG_UNSUPPORTED_SIG_ALG, mSignatureBlockEntry.getName(), digestAlgorithmOid, signatureAlgorithmOid, String.valueOf(apiLevelsWhereDigestAlgorithmNotSupported)); return; } try { verifiedSignerInfo = sigBlock.verify(unverifiedSignerInfo, mSigFileBytes); } catch (NoSuchAlgorithmException | SignatureException e) { Loading Loading @@ -472,6 +492,351 @@ public abstract class V1SchemeVerifier { mResult.certChain.addAll(certChain); } private static final String OID_DIGEST_MD5 = "1.2.840.113549.2.5"; private static final String OID_DIGEST_SHA1 = "1.3.14.3.2.26"; private static final String OID_DIGEST_SHA224 = "2.16.840.1.101.3.4.2.4"; private static final String OID_DIGEST_SHA256 = "2.16.840.1.101.3.4.2.1"; private static final String OID_DIGEST_SHA384 = "2.16.840.1.101.3.4.2.2"; private static final String OID_DIGEST_SHA512 = "2.16.840.1.101.3.4.2.3"; private static final String OID_SIG_RSA = "1.2.840.113549.1.1.1"; private static final String OID_SIG_MD5_WITH_RSA = "1.2.840.113549.1.1.4"; private static final String OID_SIG_SHA1_WITH_RSA = "1.2.840.113549.1.1.5"; private static final String OID_SIG_SHA224_WITH_RSA = "1.2.840.113549.1.1.14"; private static final String OID_SIG_SHA256_WITH_RSA = "1.2.840.113549.1.1.11"; private static final String OID_SIG_SHA384_WITH_RSA = "1.2.840.113549.1.1.12"; private static final String OID_SIG_SHA512_WITH_RSA = "1.2.840.113549.1.1.13"; private static final String OID_SIG_DSA = "1.2.840.10040.4.1"; private static final String OID_SIG_SHA1_WITH_DSA = "1.2.840.10040.4.3"; private static final String OID_SIG_SHA224_WITH_DSA = "2.16.840.1.101.3.4.3.1"; private static final String OID_SIG_SHA256_WITH_DSA = "2.16.840.1.101.3.4.3.2"; private static final String OID_SIG_SHA1_WITH_ECDSA = "1.2.840.10045.4.1"; private static final String OID_SIG_SHA224_WITH_ECDSA = "1.2.840.10045.4.3.1"; private static final String OID_SIG_SHA256_WITH_ECDSA = "1.2.840.10045.4.3.2"; private static final String OID_SIG_SHA384_WITH_ECDSA = "1.2.840.10045.4.3.3"; private static final String OID_SIG_SHA512_WITH_ECDSA = "1.2.840.10045.4.3.4"; private static final Map<String, List<InclusiveIntRange>> SUPPORTED_SIG_ALG_OIDS = new HashMap<>(); { addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_RSA, InclusiveIntRange.from(0)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_MD5_WITH_RSA, InclusiveIntRange.fromTo(0, 8), InclusiveIntRange.from(21)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA1_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA224_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA256_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA384_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA512_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_RSA, InclusiveIntRange.from(0)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_MD5_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA1_WITH_RSA, InclusiveIntRange.from(0)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA224_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA256_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA384_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA512_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_RSA, InclusiveIntRange.fromTo(0, 8), InclusiveIntRange.from(21)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_MD5_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA1_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA224_WITH_RSA, InclusiveIntRange.fromTo(0, 8), InclusiveIntRange.from(21)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA256_WITH_RSA, InclusiveIntRange.fromTo(21, 21)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA384_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA512_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_RSA, InclusiveIntRange.fromTo(0, 8), InclusiveIntRange.from(18)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_MD5_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA1_WITH_RSA, InclusiveIntRange.fromTo(21, 21)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA224_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA256_WITH_RSA, InclusiveIntRange.fromTo(0, 8), InclusiveIntRange.from(18)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA384_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA512_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_RSA, InclusiveIntRange.from(18)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_MD5_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA1_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA224_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA256_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA384_WITH_RSA, InclusiveIntRange.from(21)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA512_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_RSA, InclusiveIntRange.from(18)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_MD5_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA1_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA224_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA256_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA384_WITH_RSA, InclusiveIntRange.fromTo(21, 21)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA512_WITH_RSA, InclusiveIntRange.from(21)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA1_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA224_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA256_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_DSA, InclusiveIntRange.from(0)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA1_WITH_DSA, InclusiveIntRange.from(9)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA224_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA256_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_DSA, InclusiveIntRange.from(22)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA1_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA224_WITH_DSA, InclusiveIntRange.from(21)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA256_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_DSA, InclusiveIntRange.from(22)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA1_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA224_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA256_WITH_DSA, InclusiveIntRange.from(21)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA1_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA224_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA256_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA1_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA224_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA256_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA1_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA224_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA256_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA384_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA512_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA1_WITH_ECDSA, InclusiveIntRange.from(18)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA224_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA256_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA384_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA512_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA1_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA224_WITH_ECDSA, InclusiveIntRange.from(21)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA256_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA384_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA512_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA1_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA224_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA256_WITH_ECDSA, InclusiveIntRange.from(21)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA384_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA512_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA1_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA224_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA256_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA384_WITH_ECDSA, InclusiveIntRange.from(21)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA512_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA1_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA224_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA256_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA384_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA512_WITH_ECDSA, InclusiveIntRange.from(21)); } private static void addSupportedSigAlg( String digestAlgorithmOid, String signatureAlgorithmOid, InclusiveIntRange... supportedApiLevels) { SUPPORTED_SIG_ALG_OIDS.put( digestAlgorithmOid + "with" + signatureAlgorithmOid, Arrays.asList(supportedApiLevels)); } private List<InclusiveIntRange> getSigAlgSupportedApiLevels( String digestAlgorithmOid, String signatureAlgorithmOid) { List<InclusiveIntRange> result = SUPPORTED_SIG_ALG_OIDS.get(digestAlgorithmOid + "with" + signatureAlgorithmOid); return (result != null) ? result : Collections.emptyList(); } public void verifySigFileAgainstManifest( byte[] manifestBytes, ManifestParser.Section manifestMainSection, Loading Loading @@ -864,8 +1229,10 @@ public abstract class V1SchemeVerifier { MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST.put("MD5", 0); MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST.put("SHA-1", 0); MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST.put("SHA-256", 0); MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST.put("SHA-384", 9); MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST.put("SHA-512", 9); MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST.put( "SHA-384", AndroidSdkVersion.GINGERBREAD); MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST.put( "SHA-512", AndroidSdkVersion.GINGERBREAD); } private static byte[] getDigest(Collection<NamedDigest> digests, String jcaDigestAlgorithm) { Loading tools/apksigner/core/src/com/android/apksigner/core/internal/util/AndroidSdkVersion.java +3 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,9 @@ public abstract class AndroidSdkVersion { /** Hidden constructor to prevent instantiation. */ private AndroidSdkVersion() {} /** Android 2.3. */ public static final int GINGERBREAD = 9; /** Android 4.3. The revenge of the beans. */ public static final int JELLY_BEAN_MR2 = 18; Loading tools/apksigner/core/src/com/android/apksigner/core/internal/util/InclusiveIntRange.java 0 → 100644 +89 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.apksigner.core.internal.util; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Inclusive interval of integers. */ public class InclusiveIntRange { private final int min; private final int max; private InclusiveIntRange(int min, int max) { this.min = min; this.max = max; } public int getMin() { return min; } public int getMax() { return max; } public static InclusiveIntRange fromTo(int min, int max) { return new InclusiveIntRange(min, max); } public static InclusiveIntRange from(int min) { return new InclusiveIntRange(min, Integer.MAX_VALUE); } public List<InclusiveIntRange> getValuesNotIn( List<InclusiveIntRange> sortedNonOverlappingRanges) { if (sortedNonOverlappingRanges.isEmpty()) { return Collections.singletonList(this); } int testValue = min; List<InclusiveIntRange> result = null; for (InclusiveIntRange range : sortedNonOverlappingRanges) { int rangeMax = range.max; if (testValue > rangeMax) { continue; } int rangeMin = range.min; if (testValue < range.min) { if (result == null) { result = new ArrayList<>(); } result.add(fromTo(testValue, rangeMin - 1)); } if (rangeMax >= max) { return (result != null) ? result : Collections.emptyList(); } testValue = rangeMax + 1; } if (testValue <= max) { if (result == null) { result = new ArrayList<>(1); } result.add(fromTo(testValue, max)); } return (result != null) ? result : Collections.emptyList(); } @Override public String toString() { return "[" + min + ", " + ((max < Integer.MAX_VALUE) ? (max + "]") : "\u221e)"); } } Loading
tools/apksigner/core/src/com/android/apksigner/core/ApkVerifier.java +15 −0 Original line number Diff line number Diff line Loading @@ -662,6 +662,21 @@ public class ApkVerifier { */ JAR_SIG_VERIFY_EXCEPTION("Failed to verify JAR signature %1$s against %2$s: %3$s"), /** * JAR signature contains unsupported digest algorithm. * * <ul> * <li>Parameter 1: name of the signature block file ({@code String})</li> * <li>Parameter 2: digest algorithm OID ({@code String})</li> * <li>Parameter 2: signature algorithm OID ({@code String})</li> * <li>Parameter 3: API Levels on which this combination of algorithms is not supported * ({@code String})</li> * </ul> */ JAR_SIG_UNSUPPORTED_SIG_ALG( "JAR signature %1$s uses digest algorithm %2$s and signature algorithm %3$s which" + " is not supported on API Levels %4$s"), /** * An exception was encountered while parsing JAR signature contained in a signature block. * Loading
tools/apksigner/core/src/com/android/apksigner/core/internal/apk/v1/V1SchemeSigner.java +2 −1 Original line number Diff line number Diff line Loading @@ -562,7 +562,8 @@ public abstract class V1SchemeSigner { // SignatureAlgorithm: dsaWithSha256 (2.16.840.1.101.3.4.3.2) and // dsa (1.2.840.10040.4.1). The latter works only on API Level 22+. Thus, we use // the former. sigAlgId = getSupportedAlgorithmId("2.16.840.1.101.3.4.3.2"); // DSA with SHA-256 sigAlgId = getSupportedAlgorithmId("2.16.840.1.101.3.4.3.2"); // DSA with SHA-256 break; default: throw new IllegalArgumentException( Loading
tools/apksigner/core/src/com/android/apksigner/core/internal/apk/v1/V1SchemeVerifier.java +371 −4 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import com.android.apksigner.core.ApkVerifier.IssueWithParams; import com.android.apksigner.core.apk.ApkUtils; import com.android.apksigner.core.internal.jar.ManifestParser; import com.android.apksigner.core.internal.util.AndroidSdkVersion; import com.android.apksigner.core.internal.util.InclusiveIntRange; import com.android.apksigner.core.internal.util.MessageDigestSink; import com.android.apksigner.core.internal.zip.CentralDirectoryRecord; import com.android.apksigner.core.internal.zip.LocalFileHeader; Loading Loading @@ -412,7 +413,8 @@ public abstract class V1SchemeVerifier { mResult.addError( Issue.JAR_SIG_MALFORMED_CERTIFICATE, mSignatureBlockEntry.getName(), e); } else { mResult.addError(Issue.JAR_SIG_PARSE_EXCEPTION, mSignatureBlockEntry.getName(), e); mResult.addError( Issue.JAR_SIG_PARSE_EXCEPTION, mSignatureBlockEntry.getName(), e); } return; } Loading @@ -426,7 +428,25 @@ public abstract class V1SchemeVerifier { if ((unverifiedSignerInfos != null) && (unverifiedSignerInfos.length > 0)) { for (int i = 0; i < unverifiedSignerInfos.length; i++) { SignerInfo unverifiedSignerInfo = unverifiedSignerInfos[i]; // TODO: Reject sig/dig algorithms not supported on Android String digestAlgorithmOid = unverifiedSignerInfo.getDigestAlgorithmId().getOID().toString(); String signatureAlgorithmOid = unverifiedSignerInfo .getDigestEncryptionAlgorithmId().getOID().toString(); InclusiveIntRange desiredApiLevels = InclusiveIntRange.from(minSdkVersion); List<InclusiveIntRange> apiLevelsWhereDigestAndSigAlgorithmSupported = getSigAlgSupportedApiLevels(digestAlgorithmOid, signatureAlgorithmOid); List<InclusiveIntRange> apiLevelsWhereDigestAlgorithmNotSupported = desiredApiLevels.getValuesNotIn(apiLevelsWhereDigestAndSigAlgorithmSupported); if (!apiLevelsWhereDigestAlgorithmNotSupported.isEmpty()) { mResult.addError( Issue.JAR_SIG_UNSUPPORTED_SIG_ALG, mSignatureBlockEntry.getName(), digestAlgorithmOid, signatureAlgorithmOid, String.valueOf(apiLevelsWhereDigestAlgorithmNotSupported)); return; } try { verifiedSignerInfo = sigBlock.verify(unverifiedSignerInfo, mSigFileBytes); } catch (NoSuchAlgorithmException | SignatureException e) { Loading Loading @@ -472,6 +492,351 @@ public abstract class V1SchemeVerifier { mResult.certChain.addAll(certChain); } private static final String OID_DIGEST_MD5 = "1.2.840.113549.2.5"; private static final String OID_DIGEST_SHA1 = "1.3.14.3.2.26"; private static final String OID_DIGEST_SHA224 = "2.16.840.1.101.3.4.2.4"; private static final String OID_DIGEST_SHA256 = "2.16.840.1.101.3.4.2.1"; private static final String OID_DIGEST_SHA384 = "2.16.840.1.101.3.4.2.2"; private static final String OID_DIGEST_SHA512 = "2.16.840.1.101.3.4.2.3"; private static final String OID_SIG_RSA = "1.2.840.113549.1.1.1"; private static final String OID_SIG_MD5_WITH_RSA = "1.2.840.113549.1.1.4"; private static final String OID_SIG_SHA1_WITH_RSA = "1.2.840.113549.1.1.5"; private static final String OID_SIG_SHA224_WITH_RSA = "1.2.840.113549.1.1.14"; private static final String OID_SIG_SHA256_WITH_RSA = "1.2.840.113549.1.1.11"; private static final String OID_SIG_SHA384_WITH_RSA = "1.2.840.113549.1.1.12"; private static final String OID_SIG_SHA512_WITH_RSA = "1.2.840.113549.1.1.13"; private static final String OID_SIG_DSA = "1.2.840.10040.4.1"; private static final String OID_SIG_SHA1_WITH_DSA = "1.2.840.10040.4.3"; private static final String OID_SIG_SHA224_WITH_DSA = "2.16.840.1.101.3.4.3.1"; private static final String OID_SIG_SHA256_WITH_DSA = "2.16.840.1.101.3.4.3.2"; private static final String OID_SIG_SHA1_WITH_ECDSA = "1.2.840.10045.4.1"; private static final String OID_SIG_SHA224_WITH_ECDSA = "1.2.840.10045.4.3.1"; private static final String OID_SIG_SHA256_WITH_ECDSA = "1.2.840.10045.4.3.2"; private static final String OID_SIG_SHA384_WITH_ECDSA = "1.2.840.10045.4.3.3"; private static final String OID_SIG_SHA512_WITH_ECDSA = "1.2.840.10045.4.3.4"; private static final Map<String, List<InclusiveIntRange>> SUPPORTED_SIG_ALG_OIDS = new HashMap<>(); { addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_RSA, InclusiveIntRange.from(0)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_MD5_WITH_RSA, InclusiveIntRange.fromTo(0, 8), InclusiveIntRange.from(21)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA1_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA224_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA256_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA384_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA512_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_RSA, InclusiveIntRange.from(0)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_MD5_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA1_WITH_RSA, InclusiveIntRange.from(0)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA224_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA256_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA384_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA512_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_RSA, InclusiveIntRange.fromTo(0, 8), InclusiveIntRange.from(21)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_MD5_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA1_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA224_WITH_RSA, InclusiveIntRange.fromTo(0, 8), InclusiveIntRange.from(21)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA256_WITH_RSA, InclusiveIntRange.fromTo(21, 21)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA384_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA512_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_RSA, InclusiveIntRange.fromTo(0, 8), InclusiveIntRange.from(18)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_MD5_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA1_WITH_RSA, InclusiveIntRange.fromTo(21, 21)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA224_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA256_WITH_RSA, InclusiveIntRange.fromTo(0, 8), InclusiveIntRange.from(18)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA384_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA512_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_RSA, InclusiveIntRange.from(18)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_MD5_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA1_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA224_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA256_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA384_WITH_RSA, InclusiveIntRange.from(21)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA512_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_RSA, InclusiveIntRange.from(18)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_MD5_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA1_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA224_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA256_WITH_RSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA384_WITH_RSA, InclusiveIntRange.fromTo(21, 21)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA512_WITH_RSA, InclusiveIntRange.from(21)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA1_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA224_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA256_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_DSA, InclusiveIntRange.from(0)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA1_WITH_DSA, InclusiveIntRange.from(9)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA224_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA256_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_DSA, InclusiveIntRange.from(22)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA1_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA224_WITH_DSA, InclusiveIntRange.from(21)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA256_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_DSA, InclusiveIntRange.from(22)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA1_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA224_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA256_WITH_DSA, InclusiveIntRange.from(21)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA1_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA224_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA256_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA1_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA224_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA256_WITH_DSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA1_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA224_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA256_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA384_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_MD5, OID_SIG_SHA512_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA1_WITH_ECDSA, InclusiveIntRange.from(18)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA224_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA256_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA384_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA1, OID_SIG_SHA512_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA1_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA224_WITH_ECDSA, InclusiveIntRange.from(21)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA256_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA384_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA224, OID_SIG_SHA512_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA1_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA224_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA256_WITH_ECDSA, InclusiveIntRange.from(21)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA384_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA256, OID_SIG_SHA512_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA1_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA224_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA256_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA384_WITH_ECDSA, InclusiveIntRange.from(21)); addSupportedSigAlg( OID_DIGEST_SHA384, OID_SIG_SHA512_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA1_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA224_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA256_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA384_WITH_ECDSA, InclusiveIntRange.fromTo(21, 23)); addSupportedSigAlg( OID_DIGEST_SHA512, OID_SIG_SHA512_WITH_ECDSA, InclusiveIntRange.from(21)); } private static void addSupportedSigAlg( String digestAlgorithmOid, String signatureAlgorithmOid, InclusiveIntRange... supportedApiLevels) { SUPPORTED_SIG_ALG_OIDS.put( digestAlgorithmOid + "with" + signatureAlgorithmOid, Arrays.asList(supportedApiLevels)); } private List<InclusiveIntRange> getSigAlgSupportedApiLevels( String digestAlgorithmOid, String signatureAlgorithmOid) { List<InclusiveIntRange> result = SUPPORTED_SIG_ALG_OIDS.get(digestAlgorithmOid + "with" + signatureAlgorithmOid); return (result != null) ? result : Collections.emptyList(); } public void verifySigFileAgainstManifest( byte[] manifestBytes, ManifestParser.Section manifestMainSection, Loading Loading @@ -864,8 +1229,10 @@ public abstract class V1SchemeVerifier { MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST.put("MD5", 0); MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST.put("SHA-1", 0); MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST.put("SHA-256", 0); MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST.put("SHA-384", 9); MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST.put("SHA-512", 9); MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST.put( "SHA-384", AndroidSdkVersion.GINGERBREAD); MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST.put( "SHA-512", AndroidSdkVersion.GINGERBREAD); } private static byte[] getDigest(Collection<NamedDigest> digests, String jcaDigestAlgorithm) { Loading
tools/apksigner/core/src/com/android/apksigner/core/internal/util/AndroidSdkVersion.java +3 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,9 @@ public abstract class AndroidSdkVersion { /** Hidden constructor to prevent instantiation. */ private AndroidSdkVersion() {} /** Android 2.3. */ public static final int GINGERBREAD = 9; /** Android 4.3. The revenge of the beans. */ public static final int JELLY_BEAN_MR2 = 18; Loading
tools/apksigner/core/src/com/android/apksigner/core/internal/util/InclusiveIntRange.java 0 → 100644 +89 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.apksigner.core.internal.util; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Inclusive interval of integers. */ public class InclusiveIntRange { private final int min; private final int max; private InclusiveIntRange(int min, int max) { this.min = min; this.max = max; } public int getMin() { return min; } public int getMax() { return max; } public static InclusiveIntRange fromTo(int min, int max) { return new InclusiveIntRange(min, max); } public static InclusiveIntRange from(int min) { return new InclusiveIntRange(min, Integer.MAX_VALUE); } public List<InclusiveIntRange> getValuesNotIn( List<InclusiveIntRange> sortedNonOverlappingRanges) { if (sortedNonOverlappingRanges.isEmpty()) { return Collections.singletonList(this); } int testValue = min; List<InclusiveIntRange> result = null; for (InclusiveIntRange range : sortedNonOverlappingRanges) { int rangeMax = range.max; if (testValue > rangeMax) { continue; } int rangeMin = range.min; if (testValue < range.min) { if (result == null) { result = new ArrayList<>(); } result.add(fromTo(testValue, rangeMin - 1)); } if (rangeMax >= max) { return (result != null) ? result : Collections.emptyList(); } testValue = rangeMax + 1; } if (testValue <= max) { if (result == null) { result = new ArrayList<>(1); } result.add(fromTo(testValue, max)); } return (result != null) ? result : Collections.emptyList(); } @Override public String toString() { return "[" + min + ", " + ((max < Integer.MAX_VALUE) ? (max + "]") : "\u221e)"); } }