Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 10d19e98 authored by Daniel Cashman's avatar Daniel Cashman
Browse files

Require signing cert history certs to be unique.

Bug: 73943012
Test: android.appsecurity.cts.PkgInstallSignatureVerificationTest
Change-Id: Id7e91c60f1619ef793d73a9dd736debf7ad2ae0c
(cherry picked from commit ef05408b)
parent ea3377b4
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -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);
            }
+28 −0
Original line number Diff line number Diff line
@@ -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;
    }
}