1522b9174fca3ce4724ef8e032e26664697529e03Kenny Root/* 2522b9174fca3ce4724ef8e032e26664697529e03Kenny Root * Copyright 2016 The Android Open Source Project 3522b9174fca3ce4724ef8e032e26664697529e03Kenny Root * 4522b9174fca3ce4724ef8e032e26664697529e03Kenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 5522b9174fca3ce4724ef8e032e26664697529e03Kenny Root * you may not use this file except in compliance with the License. 6522b9174fca3ce4724ef8e032e26664697529e03Kenny Root * You may obtain a copy of the License at 7522b9174fca3ce4724ef8e032e26664697529e03Kenny Root * 8522b9174fca3ce4724ef8e032e26664697529e03Kenny Root * http://www.apache.org/licenses/LICENSE-2.0 9522b9174fca3ce4724ef8e032e26664697529e03Kenny Root * 10522b9174fca3ce4724ef8e032e26664697529e03Kenny Root * Unless required by applicable law or agreed to in writing, software 11522b9174fca3ce4724ef8e032e26664697529e03Kenny Root * distributed under the License is distributed on an "AS IS" BASIS, 12522b9174fca3ce4724ef8e032e26664697529e03Kenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13522b9174fca3ce4724ef8e032e26664697529e03Kenny Root * See the License for the specific language governing permissions and 14522b9174fca3ce4724ef8e032e26664697529e03Kenny Root * limitations under the License. 15522b9174fca3ce4724ef8e032e26664697529e03Kenny Root */ 16522b9174fca3ce4724ef8e032e26664697529e03Kenny Root 17522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootpackage libcore.java.security.cert; 18522b9174fca3ce4724ef8e032e26664697529e03Kenny Root 19522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport java.security.KeyStore.PrivateKeyEntry; 20522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport java.security.PrivateKey; 21522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport java.security.cert.CertPath; 22522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport java.security.cert.CertPathValidator; 23522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport java.security.cert.CertPathValidatorException; 24522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport java.security.cert.CertificateFactory; 25522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport java.security.cert.PKIXCertPathChecker; 26522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport java.security.cert.PKIXParameters; 27522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport java.security.cert.PKIXRevocationChecker; 28522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport java.security.cert.TrustAnchor; 29522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport java.security.cert.X509Certificate; 30522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport java.security.cert.PKIXRevocationChecker.Option; 31522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport java.util.ArrayList; 32522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport java.util.Collections; 33522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport java.util.Date; 34522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport java.util.List; 35522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport com.android.org.bouncycastle.asn1.x509.CRLReason; 36522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 37522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport com.android.org.bouncycastle.cert.X509CertificateHolder; 38522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport com.android.org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; 39522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport com.android.org.bouncycastle.cert.ocsp.BasicOCSPResp; 40522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport com.android.org.bouncycastle.cert.ocsp.BasicOCSPRespBuilder; 41522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport com.android.org.bouncycastle.cert.ocsp.CertificateID; 42522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport com.android.org.bouncycastle.cert.ocsp.CertificateStatus; 43522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport com.android.org.bouncycastle.cert.ocsp.OCSPResp; 44522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport com.android.org.bouncycastle.cert.ocsp.OCSPRespBuilder; 45522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport com.android.org.bouncycastle.cert.ocsp.RevokedStatus; 46522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport com.android.org.bouncycastle.operator.DigestCalculatorProvider; 47522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport com.android.org.bouncycastle.operator.bc.BcDigestCalculatorProvider; 48522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport com.android.org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; 49522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport junit.framework.TestCase; 50522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootimport libcore.java.security.TestKeyStore; 51522b9174fca3ce4724ef8e032e26664697529e03Kenny Root 52491d88834d8af35b9701f92d972212d873dbb6a0Adam Vartanianimport dalvik.system.VMRuntime; 53491d88834d8af35b9701f92d972212d873dbb6a0Adam Vartanianimport sun.security.jca.Providers; 54491d88834d8af35b9701f92d972212d873dbb6a0Adam Vartanian 55522b9174fca3ce4724ef8e032e26664697529e03Kenny Rootpublic class CertPathValidatorTest extends TestCase { 56491d88834d8af35b9701f92d972212d873dbb6a0Adam Vartanian 57491d88834d8af35b9701f92d972212d873dbb6a0Adam Vartanian // Allow access to deprecated BC algorithms in this test, so we can ensure they 58491d88834d8af35b9701f92d972212d873dbb6a0Adam Vartanian // continue to work 59491d88834d8af35b9701f92d972212d873dbb6a0Adam Vartanian @Override 60491d88834d8af35b9701f92d972212d873dbb6a0Adam Vartanian public void setUp() throws Exception { 61491d88834d8af35b9701f92d972212d873dbb6a0Adam Vartanian super.setUp(); 62491d88834d8af35b9701f92d972212d873dbb6a0Adam Vartanian Providers.setMaximumAllowableApiLevelForBcDeprecation( 63491d88834d8af35b9701f92d972212d873dbb6a0Adam Vartanian VMRuntime.getRuntime().getTargetSdkVersion()); 64491d88834d8af35b9701f92d972212d873dbb6a0Adam Vartanian } 65491d88834d8af35b9701f92d972212d873dbb6a0Adam Vartanian 66491d88834d8af35b9701f92d972212d873dbb6a0Adam Vartanian @Override 67491d88834d8af35b9701f92d972212d873dbb6a0Adam Vartanian public void tearDown() throws Exception { 68491d88834d8af35b9701f92d972212d873dbb6a0Adam Vartanian Providers.setMaximumAllowableApiLevelForBcDeprecation( 69491d88834d8af35b9701f92d972212d873dbb6a0Adam Vartanian Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION); 70491d88834d8af35b9701f92d972212d873dbb6a0Adam Vartanian super.tearDown(); 71491d88834d8af35b9701f92d972212d873dbb6a0Adam Vartanian } 72491d88834d8af35b9701f92d972212d873dbb6a0Adam Vartanian 73522b9174fca3ce4724ef8e032e26664697529e03Kenny Root private OCSPResp generateOCSPResponse(X509Certificate serverCertJca, X509Certificate caCertJca, 74522b9174fca3ce4724ef8e032e26664697529e03Kenny Root PrivateKey caKey, CertificateStatus status) throws Exception { 75522b9174fca3ce4724ef8e032e26664697529e03Kenny Root X509CertificateHolder caCert = new JcaX509CertificateHolder(caCertJca); 76522b9174fca3ce4724ef8e032e26664697529e03Kenny Root 77522b9174fca3ce4724ef8e032e26664697529e03Kenny Root DigestCalculatorProvider digCalcProv = new BcDigestCalculatorProvider(); 78522b9174fca3ce4724ef8e032e26664697529e03Kenny Root BasicOCSPRespBuilder basicBuilder = new BasicOCSPRespBuilder( 79522b9174fca3ce4724ef8e032e26664697529e03Kenny Root SubjectPublicKeyInfo.getInstance(caCertJca.getPublicKey().getEncoded()), 80522b9174fca3ce4724ef8e032e26664697529e03Kenny Root digCalcProv.get(CertificateID.HASH_SHA1)); 81522b9174fca3ce4724ef8e032e26664697529e03Kenny Root 82522b9174fca3ce4724ef8e032e26664697529e03Kenny Root CertificateID certId = new CertificateID(digCalcProv.get(CertificateID.HASH_SHA1), 83522b9174fca3ce4724ef8e032e26664697529e03Kenny Root caCert, serverCertJca.getSerialNumber()); 84522b9174fca3ce4724ef8e032e26664697529e03Kenny Root 85522b9174fca3ce4724ef8e032e26664697529e03Kenny Root basicBuilder.addResponse(certId, status); 86522b9174fca3ce4724ef8e032e26664697529e03Kenny Root 87522b9174fca3ce4724ef8e032e26664697529e03Kenny Root BasicOCSPResp resp = basicBuilder.build( 88522b9174fca3ce4724ef8e032e26664697529e03Kenny Root new JcaContentSignerBuilder("SHA1withRSA").build(caKey), null, new Date()); 89522b9174fca3ce4724ef8e032e26664697529e03Kenny Root 90522b9174fca3ce4724ef8e032e26664697529e03Kenny Root OCSPRespBuilder builder = new OCSPRespBuilder(); 91522b9174fca3ce4724ef8e032e26664697529e03Kenny Root return builder.build(OCSPRespBuilder.SUCCESSFUL, resp); 92522b9174fca3ce4724ef8e032e26664697529e03Kenny Root } 93522b9174fca3ce4724ef8e032e26664697529e03Kenny Root 94522b9174fca3ce4724ef8e032e26664697529e03Kenny Root private void runOCSPStapledTest(CertificateStatus certStatus, final boolean goodStatus) 95522b9174fca3ce4724ef8e032e26664697529e03Kenny Root throws Exception { 96522b9174fca3ce4724ef8e032e26664697529e03Kenny Root PrivateKeyEntry serverEntry = TestKeyStore.getServer().getPrivateKey("RSA", "RSA"); 97522b9174fca3ce4724ef8e032e26664697529e03Kenny Root PrivateKeyEntry caEntry = TestKeyStore.getIntermediateCa().getPrivateKey("RSA", "RSA"); 98522b9174fca3ce4724ef8e032e26664697529e03Kenny Root PrivateKeyEntry rootCaEntry = TestKeyStore.getRootCa().getPrivateKey("RSA", "RSA"); 99522b9174fca3ce4724ef8e032e26664697529e03Kenny Root 100522b9174fca3ce4724ef8e032e26664697529e03Kenny Root X509Certificate serverCert = (X509Certificate) serverEntry.getCertificate(); 101522b9174fca3ce4724ef8e032e26664697529e03Kenny Root OCSPResp ocspResponse = generateOCSPResponse(serverCert, 102522b9174fca3ce4724ef8e032e26664697529e03Kenny Root (X509Certificate) caEntry.getCertificate(), caEntry.getPrivateKey(), certStatus); 103522b9174fca3ce4724ef8e032e26664697529e03Kenny Root 104522b9174fca3ce4724ef8e032e26664697529e03Kenny Root PKIXParameters params = new PKIXParameters(Collections 105522b9174fca3ce4724ef8e032e26664697529e03Kenny Root .singleton(new TrustAnchor((X509Certificate) rootCaEntry.getCertificate(), null))); 106522b9174fca3ce4724ef8e032e26664697529e03Kenny Root 107522b9174fca3ce4724ef8e032e26664697529e03Kenny Root // By default we shouldn't have a PKIXRevocationChecker already. 108522b9174fca3ce4724ef8e032e26664697529e03Kenny Root for (PKIXCertPathChecker checker : params.getCertPathCheckers()) { 109522b9174fca3ce4724ef8e032e26664697529e03Kenny Root assertFalse(checker instanceof PKIXRevocationChecker); 110522b9174fca3ce4724ef8e032e26664697529e03Kenny Root } 111522b9174fca3ce4724ef8e032e26664697529e03Kenny Root 112522b9174fca3ce4724ef8e032e26664697529e03Kenny Root CertPathValidator cpv = CertPathValidator.getInstance("PKIX"); 113522b9174fca3ce4724ef8e032e26664697529e03Kenny Root 114522b9174fca3ce4724ef8e032e26664697529e03Kenny Root PKIXRevocationChecker revChecker = (PKIXRevocationChecker) cpv.getRevocationChecker(); 115522b9174fca3ce4724ef8e032e26664697529e03Kenny Root revChecker.setOptions(Collections.singleton(Option.ONLY_END_ENTITY)); 116522b9174fca3ce4724ef8e032e26664697529e03Kenny Root revChecker.setOcspResponses( 117522b9174fca3ce4724ef8e032e26664697529e03Kenny Root Collections.singletonMap(serverCert, ocspResponse.getEncoded())); 118522b9174fca3ce4724ef8e032e26664697529e03Kenny Root 119522b9174fca3ce4724ef8e032e26664697529e03Kenny Root List<PKIXCertPathChecker> checkers = new ArrayList<>(params.getCertPathCheckers()); 120522b9174fca3ce4724ef8e032e26664697529e03Kenny Root checkers.add(revChecker); 121522b9174fca3ce4724ef8e032e26664697529e03Kenny Root params.setCertPathCheckers(checkers); 122522b9174fca3ce4724ef8e032e26664697529e03Kenny Root 123522b9174fca3ce4724ef8e032e26664697529e03Kenny Root ArrayList<X509Certificate> chain = new ArrayList<>(); 124522b9174fca3ce4724ef8e032e26664697529e03Kenny Root chain.add(serverCert); 125522b9174fca3ce4724ef8e032e26664697529e03Kenny Root chain.add((X509Certificate) caEntry.getCertificate()); 126522b9174fca3ce4724ef8e032e26664697529e03Kenny Root 127522b9174fca3ce4724ef8e032e26664697529e03Kenny Root CertificateFactory cf = CertificateFactory.getInstance("X.509"); 128522b9174fca3ce4724ef8e032e26664697529e03Kenny Root CertPath certPath = cf.generateCertPath(chain); 129522b9174fca3ce4724ef8e032e26664697529e03Kenny Root 130522b9174fca3ce4724ef8e032e26664697529e03Kenny Root try { 131522b9174fca3ce4724ef8e032e26664697529e03Kenny Root cpv.validate(certPath, params); 132522b9174fca3ce4724ef8e032e26664697529e03Kenny Root assertTrue("should fail with failure OCSP status", goodStatus); 133522b9174fca3ce4724ef8e032e26664697529e03Kenny Root } catch (CertPathValidatorException maybeExpected) { 134522b9174fca3ce4724ef8e032e26664697529e03Kenny Root assertFalse("should not fail with good OCSP status", goodStatus); 135522b9174fca3ce4724ef8e032e26664697529e03Kenny Root } 136522b9174fca3ce4724ef8e032e26664697529e03Kenny Root } 137522b9174fca3ce4724ef8e032e26664697529e03Kenny Root 138522b9174fca3ce4724ef8e032e26664697529e03Kenny Root public void test_OCSP_EndEntity_KeyCompromise_Failure() throws Exception { 139522b9174fca3ce4724ef8e032e26664697529e03Kenny Root runOCSPStapledTest(new RevokedStatus(new Date(), CRLReason.keyCompromise), false); 140522b9174fca3ce4724ef8e032e26664697529e03Kenny Root } 141522b9174fca3ce4724ef8e032e26664697529e03Kenny Root 142522b9174fca3ce4724ef8e032e26664697529e03Kenny Root public void test_OCSP_EndEntity_Good_Success() throws Exception { 143522b9174fca3ce4724ef8e032e26664697529e03Kenny Root runOCSPStapledTest(CertificateStatus.GOOD, true); 144522b9174fca3ce4724ef8e032e26664697529e03Kenny Root } 145522b9174fca3ce4724ef8e032e26664697529e03Kenny Root} 146