1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.security.cts; 18 19 import static org.junit.Assert.assertFalse; 20 import static org.junit.Assume.assumeFalse; 21 import static org.junit.Assume.assumeNotNull; 22 23 import android.platform.test.annotations.AsbSecurityTest; 24 25 import androidx.test.runner.AndroidJUnit4; 26 27 import com.android.sts.common.util.StsExtraBusinessLogicTestCase; 28 29 import org.junit.Test; 30 import org.junit.runner.RunWith; 31 32 import java.io.ByteArrayInputStream; 33 import java.io.InputStream; 34 import java.security.Principal; 35 import java.security.cert.Certificate; 36 import java.security.cert.CertificateEncodingException; 37 import java.security.cert.CertificateFactory; 38 import java.util.Enumeration; 39 import java.util.Hashtable; 40 import java.util.Vector; 41 42 import javax.net.ssl.HostnameVerifier; 43 import javax.net.ssl.HttpsURLConnection; 44 import javax.net.ssl.SSLPeerUnverifiedException; 45 import javax.net.ssl.SSLSession; 46 import javax.net.ssl.SSLSessionBindingEvent; 47 import javax.net.ssl.SSLSessionBindingListener; 48 import javax.net.ssl.SSLSessionContext; 49 import javax.security.cert.CertificateException; 50 51 // Taken reference from 52 // libcore/support/src/test/java/org/apache/harmony/xnet/tests/support/mySSLSession.java 53 54 class CVE_2021_0341_SSLSession implements SSLSession { 55 56 private byte[] idData; 57 private String nameHost = null; 58 private int namePort = -1; 59 private Hashtable table; 60 private boolean invalidateDone = false; 61 private Certificate[] certs = null; 62 private javax.security.cert.X509Certificate[] xCerts = null; 63 CVE_2021_0341_SSLSession(Certificate[] xc)64 public CVE_2021_0341_SSLSession(Certificate[] xc) 65 throws CertificateEncodingException, CertificateException { 66 certs = xc; 67 xCerts = new javax.security.cert.X509Certificate[xc.length]; 68 int i = 0; 69 for (Certificate cert : xc) { 70 xCerts[i++] = javax.security.cert.X509Certificate.getInstance(cert.getEncoded()); 71 } 72 } 73 getApplicationBufferSize()74 public int getApplicationBufferSize() { 75 return 1234567; 76 } 77 getCipherSuite()78 public String getCipherSuite() { 79 return "SuiteName"; 80 } 81 getCreationTime()82 public long getCreationTime() { 83 return 1000L; 84 } 85 getId()86 public byte[] getId() { 87 return idData; 88 } 89 getLastAccessedTime()90 public long getLastAccessedTime() { 91 return 2000L; 92 } 93 getLocalCertificates()94 public Certificate[] getLocalCertificates() { 95 return null; 96 } 97 getLocalPrincipal()98 public Principal getLocalPrincipal() { 99 return null; 100 } 101 getPacketBufferSize()102 public int getPacketBufferSize() { 103 return 12345; 104 } 105 getPeerCertificates()106 public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException { 107 assumeFalse("peer not authenticated", (certs == null)); 108 return certs; 109 } 110 getPeerCertificateChain()111 public javax.security.cert.X509Certificate[] getPeerCertificateChain() 112 throws SSLPeerUnverifiedException { 113 assumeFalse("peer not authenticated", (xCerts == null)); 114 return xCerts; 115 } 116 getPeerHost()117 public String getPeerHost() { 118 return nameHost; 119 } 120 getPeerPort()121 public int getPeerPort() { 122 return namePort; 123 } 124 getPeerPrincipal()125 public Principal getPeerPrincipal() throws SSLPeerUnverifiedException { 126 return null; 127 } 128 getProtocol()129 public String getProtocol() { 130 return "ProtocolName"; 131 } 132 getSessionContext()133 public SSLSessionContext getSessionContext() { 134 return null; 135 } 136 putValue(String s, Object obj)137 public void putValue(String s, Object obj) { 138 assumeFalse("arguments can not be null", (s == null || obj == null)); 139 Object obj1 = table.put(s, obj); 140 if (obj1 instanceof SSLSessionBindingListener) { 141 SSLSessionBindingEvent sslsessionbindingevent = new SSLSessionBindingEvent(this, s); 142 ((SSLSessionBindingListener) obj1).valueUnbound(sslsessionbindingevent); 143 } 144 if (obj instanceof SSLSessionBindingListener) { 145 SSLSessionBindingEvent sslsessionbindingevent1 = new SSLSessionBindingEvent(this, s); 146 ((SSLSessionBindingListener) obj).valueBound(sslsessionbindingevent1); 147 } 148 } 149 removeValue(String s)150 public void removeValue(String s) { 151 assumeFalse("argument can not be null", (s == null)); 152 Object obj = table.remove(s); 153 if (obj instanceof SSLSessionBindingListener) { 154 SSLSessionBindingEvent sslsessionbindingevent = new SSLSessionBindingEvent(this, s); 155 ((SSLSessionBindingListener) obj).valueUnbound(sslsessionbindingevent); 156 } 157 } 158 getValue(String s)159 public Object getValue(String s) { 160 assumeFalse("argument can not be null", (s == null)); 161 return table.get(s); 162 } 163 getValueNames()164 public String[] getValueNames() { 165 Vector vector = new Vector(); 166 Enumeration enumeration = table.keys(); 167 while (enumeration.hasMoreElements()) { 168 vector.addElement(enumeration.nextElement()); 169 } 170 String as[] = new String[vector.size()]; 171 vector.copyInto(as); 172 return as; 173 } 174 invalidate()175 public void invalidate() { 176 invalidateDone = true; 177 } 178 isValid()179 public boolean isValid() { 180 return invalidateDone; 181 } 182 } 183 184 185 @RunWith(AndroidJUnit4.class) 186 public class CVE_2021_0341 extends StsExtraBusinessLogicTestCase { 187 188 public final static byte[] X509_TEST_CERTIFICATE = ("-----BEGIN CERTIFICATE-----\n" 189 + "MIIC3DCCAcSgAwIBAgIURJspNgSx6GVbOLijqravWoGlm+0wDQYJKoZIhvcNAQEL\n" 190 + "BQAwETEPMA0GA1UECgwGZ29vZ2xlMB4XDTIyMDIxNzExNTE1NFoXDTMxMTExNzEx\n" 191 + "NTE1NFowETEPMA0GA1UECgwGZ29vZ2xlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\n" 192 + "MIIBCgKCAQEA2PxVfeoY/uA66aVRXpuZXodTBFBGowTt/lAJxR8fVjDwRTOrRTrr\n" 193 + "2qdLPPK40lFQOSfHw/g6+9WjNjjSDBP+U2Agrvo8cU5R1DwJWyK2wcHOtBcL2bsj\n" 194 + "kRx18CZtZUu51a8KEhMCaIoHgGzwGMZkJnfmfO9ABbMfFsyn6KxFf0MXG3bRcQU7\n" 195 + "LyCXyQbo2Lal68QiTMXZs9rXN/a8ex+RmP9PKaXIEsIOeDrtLhzcWyNjrtTuDRoR\n" 196 + "K49xHOpz4EmqHLDzIKuhqyyo9tLR+okK0BRJoNxmfvRTbxNbjzpTTFgyB4KrKBCO\n" 197 + "VQXJROlBf7594xlCMn0QSwElVT4bMaMw/QIDAQABoywwKjAoBgNVHREEITAfggkq\n" 198 + "LmJhci5jb22CEiou44Kw44O844Kw44OrLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEA\n" 199 + "piIwY84InjX4BUmAmM+D9CHD/9euucGxgdXqL6kKG1HRL6lHfwZAIxhlbn3jWFEx\n" 200 + "k5DTkaL039FGLvYzMI0McwTIuHY/7JwCbZUJ3pVl0waW4sab+2LScnpe9c422Tqb\n" 201 + "hECEhc71E/kRlG9FjQN3wjEj3RcnWZAWCqAnJN/dcd/1tBD88tzHVckDC9mSvxzP\n" 202 + "hkmIRRifIDxcrmx7PkpJ6dAfiw9e1Pl5THdsPTDtiGJ4hjlsAi8ury3rrx31lsyo\n" 203 + "kAwQy23Q7Rcbr2z8bijDuSWWWc9RRsz+O/ePy35NJci/RUwVFTpvOFtahC30Jdv3\n" 204 + "vpmqxLqEF7Z9I1yb3Q6YUg==\n" + "-----END CERTIFICATE-----\n").getBytes(); 205 206 /** 207 * b/171980069 208 */ 209 @AsbSecurityTest(cveBugId = 171980069) 210 @Test testPocCVE_2021_0341()211 public void testPocCVE_2021_0341() throws Exception { 212 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 213 assumeNotNull(cf); 214 HostnameVerifier verifier = HttpsURLConnection.getDefaultHostnameVerifier(); 215 assumeNotNull(verifier); 216 InputStream in = new ByteArrayInputStream(X509_TEST_CERTIFICATE); 217 java.security.cert.X509Certificate x509 = 218 (java.security.cert.X509Certificate) cf.generateCertificate(in); 219 assumeNotNull(x509); 220 CVE_2021_0341_SSLSession session = 221 new CVE_2021_0341_SSLSession(new java.security.cert.X509Certificate[] {x509}); 222 assertFalse(verifier.verify("\u82b1\u5b50.bar.com", session)); 223 } 224 } 225