Skip to content
This repository was archived by the owner on Jun 25, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.google.android.attestation.validator;

/**
* This exception is thrown if the certificate fails any of the validation rule
*/
public class CertValidationException extends Exception {

private static final long serialVersionUID = 1L;

public CertValidationException(String msg) {
super(msg);
}

public CertValidationException(String message, Throwable cause) {
super(message, cause);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.google.android.attestation.validator;

import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

/**
* Performs X509 certificate validation. Add required list of validation rules
*/
public class CertValidator implements CertValidatorRule {
private List<CertValidatorRule> rules;

private CertValidator(Builder builder) {
this.rules = builder.rules;
}

@Override
public void validate(X509Certificate cert) throws CertValidationException {
for (CertValidatorRule validatorRule : rules) {
validatorRule.validate(cert);
}
}

public static final class Builder {

private List<CertValidatorRule> rules;

public Builder() {
this.rules = new ArrayList<CertValidatorRule>();
}

public Builder addRule(CertValidatorRule validatorRule) {
rules.add(validatorRule);
return this;
}

public CertValidator build() {
return new CertValidator(this);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.google.android.attestation.validator;

import java.security.cert.X509Certificate;

/**
* Identify a validation rule
*/
public interface CertValidatorRule {
void validate(X509Certificate cert) throws CertValidationException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.google.android.attestation.validator.rule;

import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;

import com.google.android.attestation.validator.CertValidationException;

import com.google.android.attestation.validator.CertValidatorRule;

/**
* check if certificate has expired or is not yet valid
*/
public class ExpirationRule implements CertValidatorRule {

@Override
public void validate(X509Certificate cert) throws CertValidationException {

try {
cert.checkValidity();
} catch (CertificateExpiredException | CertificateNotYetValidException e) {
throw new CertValidationException(e.getMessage(), e);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.google.android.attestation.validator.rule;

import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import com.google.android.attestation.validator.CertValidationException;


/** Test for {@link ExpirationRule}. */
@RunWith(JUnit4.class)
public class ExpirationRuleTest {
private static final String expired_badssl_com = "-----BEGIN CERTIFICATE-----\n"
+ "MIIFSzCCBDOgAwIBAgIQSueVSfqavj8QDxekeOFpCTANBgkqhkiG9w0BAQsFADCB"
+ "kDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G"
+ "A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxNjA0BgNV"
+ "BAMTLUNPTU9ETyBSU0EgRG9tYWluIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZlciBD"
+ "QTAeFw0xNTA0MDkwMDAwMDBaFw0xNTA0MTIyMzU5NTlaMFkxITAfBgNVBAsTGERv"
+ "bWFpbiBDb250cm9sIFZhbGlkYXRlZDEdMBsGA1UECxMUUG9zaXRpdmVTU0wgV2ls"
+ "ZGNhcmQxFTATBgNVBAMUDCouYmFkc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD"
+ "ggEPADCCAQoCggEBAMIE7PiM7gTCs9hQ1XBYzJMY61yoaEmwIrX5lZ6xKyx2PmzA"
+ "S2BMTOqytMAPgLaw+XLJhgL5XEFdEyt/ccRLvOmULlA3pmccYYz2QULFRtMWhyef"
+ "dOsKnRFSJiFzbIRMeVXk0WvoBj1IFVKtsyjbqv9u/2CVSndrOfEk0TG23U3AxPxT"
+ "uW1CrbV8/q71FdIzSOciccfCFHpsKOo3St/qbLVytH5aohbcabFXRNsKEqveww9H"
+ "dFxBIuGa+RuT5q0iBikusbpJHAwnnqP7i/dAcgCskgjZjFeEU4EFy+b+a1SYQCeF"
+ "xxC7c3DvaRhBB0VVfPlkPz0sw6l865MaTIbRyoUCAwEAAaOCAdUwggHRMB8GA1Ud"
+ "IwQYMBaAFJCvajqUWgvYkOoSVnPfQ7Q6KNrnMB0GA1UdDgQWBBSd7sF7gQs6R2lx"
+ "GH0RN5O8pRs/+zAOBgNVHQ8BAf8EBAMCBaAwDAYDVR0TAQH/BAIwADAdBgNVHSUE"
+ "FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwTwYDVR0gBEgwRjA6BgsrBgEEAbIxAQIC"
+ "BzArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5jb21vZG8uY29tL0NQUzAI"
+ "BgZngQwBAgEwVAYDVR0fBE0wSzBJoEegRYZDaHR0cDovL2NybC5jb21vZG9jYS5j"
+ "b20vQ09NT0RPUlNBRG9tYWluVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNybDCB"
+ "hQYIKwYBBQUHAQEEeTB3ME8GCCsGAQUFBzAChkNodHRwOi8vY3J0LmNvbW9kb2Nh"
+ "LmNvbS9DT01PRE9SU0FEb21haW5WYWxpZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3J0"
+ "MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wIwYDVR0RBBww"
+ "GoIMKi5iYWRzc2wuY29tggpiYWRzc2wuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQBq"
+ "evHa/wMHcnjFZqFPRkMOXxQhjHUa6zbgH6QQFezaMyV8O7UKxwE4PSf9WNnM6i1p"
+ "OXy+l+8L1gtY54x/v7NMHfO3kICmNnwUW+wHLQI+G1tjWxWrAPofOxkt3+IjEBEH"
+ "fnJ/4r+3ABuYLyw/zoWaJ4wQIghBK4o+gk783SHGVnRwpDTysUCeK1iiWQ8dSO/r"
+ "ET7BSp68ZVVtxqPv1dSWzfGuJ/ekVxQ8lEEFeouhN0fX9X3c+s5vMaKwjOrMEpsi"
+ "8TRwz311SotoKQwe6Zaoz7ASH1wq7mcvf71z81oBIgxw+s1F73hczg36TuHvzmWf"
+ "RwxPuzZEaFZcVlmtqoq8\n"
+ "-----END CERTIFICATE-----";

public static X509Certificate loadCertFromString(String certStr) throws CertificateException {
CertificateFactory factory = CertificateFactory.getInstance("X509");
return (X509Certificate) factory
.generateCertificate(new ByteArrayInputStream(expired_badssl_com.getBytes(StandardCharsets.UTF_8)));
}

@Test
public void testCertificateExpired() throws CertificateException {
X509Certificate cert = loadCertFromString(expired_badssl_com);
var rule = new ExpirationRule();

try {
rule.validate(cert);
Assert.fail("CertificateException expected.");
} catch (CertValidationException e) {

}
}

}