| /* |
| * Copyright (C) 2022 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 android.security.cts; |
| |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assume.assumeFalse; |
| import static org.junit.Assume.assumeNotNull; |
| |
| import android.platform.test.annotations.AsbSecurityTest; |
| |
| import androidx.test.runner.AndroidJUnit4; |
| |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.InputStream; |
| import java.security.Principal; |
| import java.security.cert.Certificate; |
| import java.security.cert.CertificateEncodingException; |
| import java.security.cert.CertificateFactory; |
| import java.util.Enumeration; |
| import java.util.Hashtable; |
| import java.util.Vector; |
| |
| import javax.net.ssl.HostnameVerifier; |
| import javax.net.ssl.HttpsURLConnection; |
| import javax.net.ssl.SSLPeerUnverifiedException; |
| import javax.net.ssl.SSLSession; |
| import javax.net.ssl.SSLSessionBindingEvent; |
| import javax.net.ssl.SSLSessionBindingListener; |
| import javax.net.ssl.SSLSessionContext; |
| import javax.security.cert.CertificateException; |
| |
| // Taken reference from |
| // libcore/support/src/test/java/org/apache/harmony/xnet/tests/support/mySSLSession.java |
| class CVE_2021_0341_SSLSession implements SSLSession { |
| |
| private byte[] idData; |
| private String nameHost = null; |
| private int namePort = -1; |
| private Hashtable table; |
| private boolean invalidateDone = false; |
| private Certificate[] certs = null; |
| private javax.security.cert.X509Certificate[] xCerts = null; |
| |
| public CVE_2021_0341_SSLSession(Certificate[] xc) |
| throws CertificateEncodingException, CertificateException { |
| certs = xc; |
| xCerts = new javax.security.cert.X509Certificate[xc.length]; |
| int i = 0; |
| for (Certificate cert : xc) { |
| xCerts[i++] = javax.security.cert.X509Certificate.getInstance(cert.getEncoded()); |
| } |
| } |
| |
| public int getApplicationBufferSize() { |
| return 1234567; |
| } |
| |
| public String getCipherSuite() { |
| return "SuiteName"; |
| } |
| |
| public long getCreationTime() { |
| return 1000L; |
| } |
| |
| public byte[] getId() { |
| return idData; |
| } |
| |
| public long getLastAccessedTime() { |
| return 2000L; |
| } |
| |
| public Certificate[] getLocalCertificates() { |
| return null; |
| } |
| |
| public Principal getLocalPrincipal() { |
| return null; |
| } |
| |
| public int getPacketBufferSize() { |
| return 12345; |
| } |
| |
| public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException { |
| assumeFalse("peer not authenticated", (certs == null)); |
| return certs; |
| } |
| |
| public javax.security.cert.X509Certificate[] getPeerCertificateChain() |
| throws SSLPeerUnverifiedException { |
| assumeFalse("peer not authenticated", (xCerts == null)); |
| return xCerts; |
| } |
| |
| public String getPeerHost() { |
| return nameHost; |
| } |
| |
| public int getPeerPort() { |
| return namePort; |
| } |
| |
| public Principal getPeerPrincipal() throws SSLPeerUnverifiedException { |
| return null; |
| } |
| |
| public String getProtocol() { |
| return "ProtocolName"; |
| } |
| |
| public SSLSessionContext getSessionContext() { |
| return null; |
| } |
| |
| public void putValue(String s, Object obj) { |
| assumeFalse("arguments can not be null", (s == null || obj == null)); |
| Object obj1 = table.put(s, obj); |
| if (obj1 instanceof SSLSessionBindingListener) { |
| SSLSessionBindingEvent sslsessionbindingevent = new SSLSessionBindingEvent(this, s); |
| ((SSLSessionBindingListener) obj1).valueUnbound(sslsessionbindingevent); |
| } |
| if (obj instanceof SSLSessionBindingListener) { |
| SSLSessionBindingEvent sslsessionbindingevent1 = new SSLSessionBindingEvent(this, s); |
| ((SSLSessionBindingListener) obj).valueBound(sslsessionbindingevent1); |
| } |
| } |
| |
| public void removeValue(String s) { |
| assumeFalse("argument can not be null", (s == null)); |
| Object obj = table.remove(s); |
| if (obj instanceof SSLSessionBindingListener) { |
| SSLSessionBindingEvent sslsessionbindingevent = new SSLSessionBindingEvent(this, s); |
| ((SSLSessionBindingListener) obj).valueUnbound(sslsessionbindingevent); |
| } |
| } |
| |
| public Object getValue(String s) { |
| assumeFalse("argument can not be null", (s == null)); |
| return table.get(s); |
| } |
| |
| public String[] getValueNames() { |
| Vector vector = new Vector(); |
| Enumeration enumeration = table.keys(); |
| while (enumeration.hasMoreElements()) { |
| vector.addElement(enumeration.nextElement()); |
| } |
| String as[] = new String[vector.size()]; |
| vector.copyInto(as); |
| return as; |
| } |
| |
| public void invalidate() { |
| invalidateDone = true; |
| } |
| |
| public boolean isValid() { |
| return invalidateDone; |
| } |
| } |
| |
| |
| @RunWith(AndroidJUnit4.class) |
| public class CVE_2021_0341 { |
| |
| public final static byte[] X509_TEST_CERTIFICATE = ("-----BEGIN CERTIFICATE-----\n" |
| + "MIIC3DCCAcSgAwIBAgIURJspNgSx6GVbOLijqravWoGlm+0wDQYJKoZIhvcNAQEL\n" |
| + "BQAwETEPMA0GA1UECgwGZ29vZ2xlMB4XDTIyMDIxNzExNTE1NFoXDTMxMTExNzEx\n" |
| + "NTE1NFowETEPMA0GA1UECgwGZ29vZ2xlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\n" |
| + "MIIBCgKCAQEA2PxVfeoY/uA66aVRXpuZXodTBFBGowTt/lAJxR8fVjDwRTOrRTrr\n" |
| + "2qdLPPK40lFQOSfHw/g6+9WjNjjSDBP+U2Agrvo8cU5R1DwJWyK2wcHOtBcL2bsj\n" |
| + "kRx18CZtZUu51a8KEhMCaIoHgGzwGMZkJnfmfO9ABbMfFsyn6KxFf0MXG3bRcQU7\n" |
| + "LyCXyQbo2Lal68QiTMXZs9rXN/a8ex+RmP9PKaXIEsIOeDrtLhzcWyNjrtTuDRoR\n" |
| + "K49xHOpz4EmqHLDzIKuhqyyo9tLR+okK0BRJoNxmfvRTbxNbjzpTTFgyB4KrKBCO\n" |
| + "VQXJROlBf7594xlCMn0QSwElVT4bMaMw/QIDAQABoywwKjAoBgNVHREEITAfggkq\n" |
| + "LmJhci5jb22CEiou44Kw44O844Kw44OrLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEA\n" |
| + "piIwY84InjX4BUmAmM+D9CHD/9euucGxgdXqL6kKG1HRL6lHfwZAIxhlbn3jWFEx\n" |
| + "k5DTkaL039FGLvYzMI0McwTIuHY/7JwCbZUJ3pVl0waW4sab+2LScnpe9c422Tqb\n" |
| + "hECEhc71E/kRlG9FjQN3wjEj3RcnWZAWCqAnJN/dcd/1tBD88tzHVckDC9mSvxzP\n" |
| + "hkmIRRifIDxcrmx7PkpJ6dAfiw9e1Pl5THdsPTDtiGJ4hjlsAi8ury3rrx31lsyo\n" |
| + "kAwQy23Q7Rcbr2z8bijDuSWWWc9RRsz+O/ePy35NJci/RUwVFTpvOFtahC30Jdv3\n" |
| + "vpmqxLqEF7Z9I1yb3Q6YUg==\n" + "-----END CERTIFICATE-----\n").getBytes(); |
| |
| /** |
| * b/171980069 |
| */ |
| @AsbSecurityTest(cveBugId = 171980069) |
| @Test |
| public void testPocCVE_2021_0341() throws Exception { |
| CertificateFactory cf = CertificateFactory.getInstance("X.509"); |
| assumeNotNull(cf); |
| HostnameVerifier verifier = HttpsURLConnection.getDefaultHostnameVerifier(); |
| assumeNotNull(verifier); |
| InputStream in = new ByteArrayInputStream(X509_TEST_CERTIFICATE); |
| java.security.cert.X509Certificate x509 = |
| (java.security.cert.X509Certificate) cf.generateCertificate(in); |
| assumeNotNull(x509); |
| CVE_2021_0341_SSLSession session = |
| new CVE_2021_0341_SSLSession(new java.security.cert.X509Certificate[] {x509}); |
| assertFalse(verifier.verify("\u82b1\u5b50.bar.com", session)); |
| } |
| } |