summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Daniel Cashman <dcashman@google.com> 2018-03-28 15:58:14 -0700
committer Daniel Cashman <dcashman@google.com> 2018-03-30 15:13:42 +0000
commit10d19e98081bec0e2ee5274f2c46d02d036ce89f (patch)
tree45f0a53cb3b4521972fecfd72578317702b0a964
parentea3377b4d47cf590548428df230b713231793ea6 (diff)
Require signing cert history certs to be unique.
Bug: 73943012 Test: android.appsecurity.cts.PkgInstallSignatureVerificationTest Change-Id: Id7e91c60f1619ef793d73a9dd736debf7ad2ae0c (cherry picked from commit ef05408bcdcb32d005f91ca295a1e514845a58f4)
-rw-r--r--core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java8
-rw-r--r--core/java/android/util/apk/VerbatimX509Certificate.java28
2 files changed, 36 insertions, 0 deletions
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
index 4431bcef1ff4..758cd2b877f2 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
@@ -62,6 +62,7 @@ import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -457,6 +458,7 @@ public class ApkSignatureSchemeV3Verifier {
// get the version code, but don't do anything with it: creator knew about all our flags
porBuf.getInt();
+ HashSet<X509Certificate> certHistorySet = new HashSet<>();
while (porBuf.hasRemaining()) {
levelCount++;
ByteBuffer level = getLengthPrefixedSlice(porBuf);
@@ -495,6 +497,12 @@ public class ApkSignatureSchemeV3Verifier {
lastCert = new VerbatimX509Certificate(lastCert, encodedCert);
lastSigAlgorithm = sigAlgorithm;
+ if (certHistorySet.contains(lastCert)) {
+ throw new SecurityException("Encountered duplicate entries in "
+ + "Proof-of-rotation record at certificate #" + levelCount + ". All "
+ + "signing certificates should be unique");
+ }
+ certHistorySet.add(lastCert);
certs.add(lastCert);
flagsList.add(flags);
}
diff --git a/core/java/android/util/apk/VerbatimX509Certificate.java b/core/java/android/util/apk/VerbatimX509Certificate.java
index 9984c6d26c64..391c5fc39416 100644
--- a/core/java/android/util/apk/VerbatimX509Certificate.java
+++ b/core/java/android/util/apk/VerbatimX509Certificate.java
@@ -18,6 +18,7 @@ package android.util.apk;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
+import java.util.Arrays;
/**
* For legacy reasons we need to return exactly the original encoded certificate bytes, instead
@@ -25,6 +26,7 @@ import java.security.cert.X509Certificate;
*/
class VerbatimX509Certificate extends WrappedX509Certificate {
private final byte[] mEncodedVerbatim;
+ private int mHash = -1;
VerbatimX509Certificate(X509Certificate wrapped, byte[] encodedVerbatim) {
super(wrapped);
@@ -35,4 +37,30 @@ class VerbatimX509Certificate extends WrappedX509Certificate {
public byte[] getEncoded() throws CertificateEncodingException {
return mEncodedVerbatim;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof VerbatimX509Certificate)) return false;
+
+ try {
+ byte[] a = this.getEncoded();
+ byte[] b = ((VerbatimX509Certificate) o).getEncoded();
+ return Arrays.equals(a, b);
+ } catch (CertificateEncodingException e) {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ if (mHash == -1) {
+ try {
+ mHash = Arrays.hashCode(this.getEncoded());
+ } catch (CertificateEncodingException e) {
+ mHash = 0;
+ }
+ }
+ return mHash;
+ }
}