1 /* 2 * Copyright (C) 2009 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.webkit.cts; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotEquals; 22 import static org.junit.Assert.assertNotNull; 23 import static org.junit.Assert.assertNull; 24 import static org.junit.Assert.assertTrue; 25 26 import android.annotation.CallSuper; 27 import android.net.http.SslCertificate; 28 import android.net.http.SslError; 29 import android.os.StrictMode; 30 import android.os.StrictMode.ThreadPolicy; 31 import android.platform.test.annotations.AppModeFull; 32 import android.util.Log; 33 import android.webkit.ClientCertRequest; 34 import android.webkit.SslErrorHandler; 35 import android.webkit.WebView; 36 import android.webkit.WebViewClient; 37 import android.webkit.cts.WebViewSyncLoader.WaitForLoadedClient; 38 39 import androidx.test.ext.junit.rules.ActivityScenarioRule; 40 import androidx.test.ext.junit.runners.AndroidJUnit4; 41 import androidx.test.filters.MediumTest; 42 43 import com.android.compatibility.common.util.NullWebViewUtils; 44 import com.android.compatibility.common.util.PollingCheck; 45 46 import org.junit.After; 47 import org.junit.Assume; 48 import org.junit.Before; 49 import org.junit.Rule; 50 import org.junit.Test; 51 import org.junit.runner.RunWith; 52 53 import java.io.ByteArrayInputStream; 54 import java.io.File; 55 import java.security.KeyFactory; 56 import java.security.KeyStore; 57 import java.security.Principal; 58 import java.security.PrivateKey; 59 import java.security.cert.CertificateFactory; 60 import java.security.cert.X509Certificate; 61 import java.security.spec.PKCS8EncodedKeySpec; 62 import java.util.concurrent.atomic.AtomicBoolean; 63 64 @AppModeFull(reason = "Instant apps cannot bind sockets") 65 @MediumTest 66 @RunWith(AndroidJUnit4.class) 67 public class WebViewSslTest extends SharedWebViewTest { 68 private static final String LOGTAG = "WebViewSslTest"; 69 70 /** 71 * Taken verbatim from AndroidKeyStoreTest.java. Copying the build notes here for reference. 72 * The keys and certificates below are generated with: 73 * 74 * openssl req -new -x509 -days 3650 -extensions v3_ca -keyout cakey.pem -out cacert.pem 75 * openssl req -newkey rsa:1024 -keyout userkey.pem -nodes -days 3650 -out userkey.req 76 * mkdir -p demoCA/newcerts 77 * touch demoCA/index.txt 78 * echo "01" > demoCA/serial 79 * openssl ca -out usercert.pem -in userkey.req -cert cacert.pem -keyfile cakey.pem -days 3650 80 */ 81 82 /** 83 * Generated from above and converted with: 84 * 85 * openssl x509 -outform d -in usercert.pem | xxd -i | sed 's/0x/(byte) 0x/g' 86 */ 87 private static final byte[] FAKE_RSA_USER_1 = new byte[] { 88 (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x95, (byte) 0x30, (byte) 0x82, 89 (byte) 0x01, (byte) 0xfe, (byte) 0xa0, (byte) 0x03, (byte) 0x02, (byte) 0x01, 90 (byte) 0x02, (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x30, (byte) 0x0d, 91 (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, 92 (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x05, 93 (byte) 0x00, (byte) 0x30, (byte) 0x4f, (byte) 0x31, (byte) 0x0b, (byte) 0x30, 94 (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06, 95 (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x0b, 96 (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, 97 (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41, (byte) 0x31, 98 (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06, (byte) 0x03, (byte) 0x55, 99 (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d, (byte) 0x4d, (byte) 0x6f, 100 (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61, (byte) 0x69, (byte) 0x6e, 101 (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65, (byte) 0x77, (byte) 0x31, 102 (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03, (byte) 0x55, 103 (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41, (byte) 0x6e, 104 (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x20, 105 (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20, (byte) 0x43, 106 (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x30, (byte) 0x1e, 107 (byte) 0x17, (byte) 0x0d, (byte) 0x31, (byte) 0x32, (byte) 0x30, (byte) 0x38, 108 (byte) 0x31, (byte) 0x34, (byte) 0x32, (byte) 0x33, (byte) 0x32, (byte) 0x35, 109 (byte) 0x34, (byte) 0x38, (byte) 0x5a, (byte) 0x17, (byte) 0x0d, (byte) 0x32, 110 (byte) 0x32, (byte) 0x30, (byte) 0x38, (byte) 0x31, (byte) 0x32, (byte) 0x32, 111 (byte) 0x33, (byte) 0x32, (byte) 0x35, (byte) 0x34, (byte) 0x38, (byte) 0x5a, 112 (byte) 0x30, (byte) 0x55, (byte) 0x31, (byte) 0x0b, (byte) 0x30, (byte) 0x09, 113 (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06, (byte) 0x13, 114 (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x0b, (byte) 0x30, 115 (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x08, 116 (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41, (byte) 0x31, (byte) 0x1b, 117 (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, 118 (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41, (byte) 0x6e, (byte) 0x64, 119 (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x20, (byte) 0x54, 120 (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20, (byte) 0x43, (byte) 0x61, 121 (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x31, (byte) 0x1c, (byte) 0x30, 122 (byte) 0x1a, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x03, 123 (byte) 0x13, (byte) 0x13, (byte) 0x73, (byte) 0x65, (byte) 0x72, (byte) 0x76, 124 (byte) 0x65, (byte) 0x72, (byte) 0x31, (byte) 0x2e, (byte) 0x65, (byte) 0x78, 125 (byte) 0x61, (byte) 0x6d, (byte) 0x70, (byte) 0x6c, (byte) 0x65, (byte) 0x2e, 126 (byte) 0x63, (byte) 0x6f, (byte) 0x6d, (byte) 0x30, (byte) 0x81, (byte) 0x9f, 127 (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, 128 (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, 129 (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x03, (byte) 0x81, (byte) 0x8d, 130 (byte) 0x00, (byte) 0x30, (byte) 0x81, (byte) 0x89, (byte) 0x02, (byte) 0x81, 131 (byte) 0x81, (byte) 0x00, (byte) 0xce, (byte) 0x29, (byte) 0xeb, (byte) 0xf6, 132 (byte) 0x5b, (byte) 0x25, (byte) 0xdc, (byte) 0xa1, (byte) 0xa6, (byte) 0x2c, 133 (byte) 0x66, (byte) 0xcb, (byte) 0x20, (byte) 0x90, (byte) 0x27, (byte) 0x86, 134 (byte) 0x8a, (byte) 0x44, (byte) 0x71, (byte) 0x50, (byte) 0xda, (byte) 0xd3, 135 (byte) 0x02, (byte) 0x77, (byte) 0x55, (byte) 0xe9, (byte) 0xe8, (byte) 0x08, 136 (byte) 0xf3, (byte) 0x36, (byte) 0x9a, (byte) 0xae, (byte) 0xab, (byte) 0x04, 137 (byte) 0x6d, (byte) 0x00, (byte) 0x99, (byte) 0xbf, (byte) 0x7d, (byte) 0x0f, 138 (byte) 0x67, (byte) 0x8b, (byte) 0x1d, (byte) 0xd4, (byte) 0x2b, (byte) 0x7c, 139 (byte) 0xcb, (byte) 0xcd, (byte) 0x33, (byte) 0xc7, (byte) 0x84, (byte) 0x30, 140 (byte) 0xe2, (byte) 0x45, (byte) 0x21, (byte) 0xb3, (byte) 0x75, (byte) 0xf5, 141 (byte) 0x79, (byte) 0x02, (byte) 0xda, (byte) 0x50, (byte) 0xa3, (byte) 0x8b, 142 (byte) 0xce, (byte) 0xc3, (byte) 0x8e, (byte) 0x0f, (byte) 0x25, (byte) 0xeb, 143 (byte) 0x08, (byte) 0x2c, (byte) 0xdd, (byte) 0x1c, (byte) 0xcf, (byte) 0xff, 144 (byte) 0x3b, (byte) 0xde, (byte) 0xb6, (byte) 0xaa, (byte) 0x2a, (byte) 0xa9, 145 (byte) 0xc4, (byte) 0x8a, (byte) 0x24, (byte) 0x24, (byte) 0xe6, (byte) 0x29, 146 (byte) 0x0d, (byte) 0x98, (byte) 0x4c, (byte) 0x32, (byte) 0xa1, (byte) 0x7b, 147 (byte) 0x23, (byte) 0x2b, (byte) 0x42, (byte) 0x30, (byte) 0xee, (byte) 0x78, 148 (byte) 0x08, (byte) 0x47, (byte) 0xad, (byte) 0xf2, (byte) 0x96, (byte) 0xd5, 149 (byte) 0xf1, (byte) 0x62, (byte) 0x42, (byte) 0x2d, (byte) 0x35, (byte) 0x19, 150 (byte) 0xb4, (byte) 0x3c, (byte) 0xc9, (byte) 0xc3, (byte) 0x5f, (byte) 0x03, 151 (byte) 0x16, (byte) 0x3a, (byte) 0x23, (byte) 0xac, (byte) 0xcb, (byte) 0xce, 152 (byte) 0x9e, (byte) 0x51, (byte) 0x2e, (byte) 0x6d, (byte) 0x02, (byte) 0x03, 153 (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0xa3, (byte) 0x7b, (byte) 0x30, 154 (byte) 0x79, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, 155 (byte) 0x1d, (byte) 0x13, (byte) 0x04, (byte) 0x02, (byte) 0x30, (byte) 0x00, 156 (byte) 0x30, (byte) 0x2c, (byte) 0x06, (byte) 0x09, (byte) 0x60, (byte) 0x86, 157 (byte) 0x48, (byte) 0x01, (byte) 0x86, (byte) 0xf8, (byte) 0x42, (byte) 0x01, 158 (byte) 0x0d, (byte) 0x04, (byte) 0x1f, (byte) 0x16, (byte) 0x1d, (byte) 0x4f, 159 (byte) 0x70, (byte) 0x65, (byte) 0x6e, (byte) 0x53, (byte) 0x53, (byte) 0x4c, 160 (byte) 0x20, (byte) 0x47, (byte) 0x65, (byte) 0x6e, (byte) 0x65, (byte) 0x72, 161 (byte) 0x61, (byte) 0x74, (byte) 0x65, (byte) 0x64, (byte) 0x20, (byte) 0x43, 162 (byte) 0x65, (byte) 0x72, (byte) 0x74, (byte) 0x69, (byte) 0x66, (byte) 0x69, 163 (byte) 0x63, (byte) 0x61, (byte) 0x74, (byte) 0x65, (byte) 0x30, (byte) 0x1d, 164 (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x0e, (byte) 0x04, 165 (byte) 0x16, (byte) 0x04, (byte) 0x14, (byte) 0x32, (byte) 0xa1, (byte) 0x1e, 166 (byte) 0x6b, (byte) 0x69, (byte) 0x04, (byte) 0xfe, (byte) 0xb3, (byte) 0xcd, 167 (byte) 0xf8, (byte) 0xbb, (byte) 0x14, (byte) 0xcd, (byte) 0xff, (byte) 0xd4, 168 (byte) 0x16, (byte) 0xc3, (byte) 0xab, (byte) 0x44, (byte) 0x2f, (byte) 0x30, 169 (byte) 0x1f, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x23, 170 (byte) 0x04, (byte) 0x18, (byte) 0x30, (byte) 0x16, (byte) 0x80, (byte) 0x14, 171 (byte) 0x33, (byte) 0x05, (byte) 0xee, (byte) 0xfe, (byte) 0x6f, (byte) 0x60, 172 (byte) 0xc7, (byte) 0xf9, (byte) 0xa9, (byte) 0xd2, (byte) 0x73, (byte) 0x5c, 173 (byte) 0x8f, (byte) 0x6d, (byte) 0xa2, (byte) 0x2f, (byte) 0x97, (byte) 0x8e, 174 (byte) 0x5d, (byte) 0x51, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, 175 (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, 176 (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x05, (byte) 0x00, (byte) 0x03, 177 (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0x46, (byte) 0x42, (byte) 0xef, 178 (byte) 0x56, (byte) 0x89, (byte) 0x78, (byte) 0x90, (byte) 0x38, (byte) 0x24, 179 (byte) 0x9f, (byte) 0x8c, (byte) 0x7a, (byte) 0xce, (byte) 0x7a, (byte) 0xa5, 180 (byte) 0xb5, (byte) 0x1e, (byte) 0x74, (byte) 0x96, (byte) 0x34, (byte) 0x49, 181 (byte) 0x8b, (byte) 0xed, (byte) 0x44, (byte) 0xb3, (byte) 0xc9, (byte) 0x05, 182 (byte) 0xd7, (byte) 0x48, (byte) 0x55, (byte) 0x52, (byte) 0x59, (byte) 0x15, 183 (byte) 0x0b, (byte) 0xaa, (byte) 0x16, (byte) 0x86, (byte) 0xd2, (byte) 0x8e, 184 (byte) 0x16, (byte) 0x99, (byte) 0xe8, (byte) 0x5f, (byte) 0x11, (byte) 0x71, 185 (byte) 0x42, (byte) 0x55, (byte) 0xd1, (byte) 0xc4, (byte) 0x6f, (byte) 0x2e, 186 (byte) 0xa9, (byte) 0x64, (byte) 0x6f, (byte) 0xd8, (byte) 0xfd, (byte) 0x43, 187 (byte) 0x13, (byte) 0x24, (byte) 0xaa, (byte) 0x67, (byte) 0xe6, (byte) 0xf5, 188 (byte) 0xca, (byte) 0x80, (byte) 0x5e, (byte) 0x3a, (byte) 0x3e, (byte) 0xcc, 189 (byte) 0x4f, (byte) 0xba, (byte) 0x87, (byte) 0xe6, (byte) 0xae, (byte) 0xbf, 190 (byte) 0x8f, (byte) 0xd5, (byte) 0x28, (byte) 0x38, (byte) 0x58, (byte) 0x30, 191 (byte) 0x24, (byte) 0xf6, (byte) 0x53, (byte) 0x5b, (byte) 0x41, (byte) 0x53, 192 (byte) 0xe6, (byte) 0x45, (byte) 0xbc, (byte) 0xbe, (byte) 0xe6, (byte) 0xbb, 193 (byte) 0x5d, (byte) 0xd8, (byte) 0xa7, (byte) 0xf9, (byte) 0x64, (byte) 0x99, 194 (byte) 0x04, (byte) 0x43, (byte) 0x75, (byte) 0xd7, (byte) 0x2d, (byte) 0x32, 195 (byte) 0x0a, (byte) 0x94, (byte) 0xaf, (byte) 0x06, (byte) 0x34, (byte) 0xae, 196 (byte) 0x46, (byte) 0xbd, (byte) 0xda, (byte) 0x00, (byte) 0x0e, (byte) 0x25, 197 (byte) 0xc2, (byte) 0xf7, (byte) 0xc9, (byte) 0xc3, (byte) 0x65, (byte) 0xd2, 198 (byte) 0x08, (byte) 0x41, (byte) 0x0a, (byte) 0xf3, (byte) 0x72 199 }; 200 201 /** 202 * Generated from above and converted with: 203 * 204 * openssl x509 -outform d -in cacert.pem | xxd -i | sed 's/0x/(byte) 0x/g' 205 */ 206 private static final byte[] FAKE_RSA_CA_1 = { 207 (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0xce, (byte) 0x30, (byte) 0x82, 208 (byte) 0x02, (byte) 0x37, (byte) 0xa0, (byte) 0x03, (byte) 0x02, (byte) 0x01, 209 (byte) 0x02, (byte) 0x02, (byte) 0x09, (byte) 0x00, (byte) 0xe1, (byte) 0x6a, 210 (byte) 0xa2, (byte) 0xf4, (byte) 0x2e, (byte) 0x55, (byte) 0x48, (byte) 0x0a, 211 (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, 212 (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, 213 (byte) 0x05, (byte) 0x05, (byte) 0x00, (byte) 0x30, (byte) 0x4f, (byte) 0x31, 214 (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, 215 (byte) 0x04, (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53, 216 (byte) 0x31, (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, 217 (byte) 0x55, (byte) 0x04, (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43, 218 (byte) 0x41, (byte) 0x31, (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06, 219 (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d, 220 (byte) 0x4d, (byte) 0x6f, (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61, 221 (byte) 0x69, (byte) 0x6e, (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65, 222 (byte) 0x77, (byte) 0x31, (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06, 223 (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12, 224 (byte) 0x41, (byte) 0x6e, (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, 225 (byte) 0x64, (byte) 0x20, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, 226 (byte) 0x20, (byte) 0x43, (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73, 227 (byte) 0x30, (byte) 0x1e, (byte) 0x17, (byte) 0x0d, (byte) 0x31, (byte) 0x32, 228 (byte) 0x30, (byte) 0x38, (byte) 0x31, (byte) 0x34, (byte) 0x31, (byte) 0x36, 229 (byte) 0x35, (byte) 0x35, (byte) 0x34, (byte) 0x34, (byte) 0x5a, (byte) 0x17, 230 (byte) 0x0d, (byte) 0x32, (byte) 0x32, (byte) 0x30, (byte) 0x38, (byte) 0x31, 231 (byte) 0x32, (byte) 0x31, (byte) 0x36, (byte) 0x35, (byte) 0x35, (byte) 0x34, 232 (byte) 0x34, (byte) 0x5a, (byte) 0x30, (byte) 0x4f, (byte) 0x31, (byte) 0x0b, 233 (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, 234 (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31, 235 (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, 236 (byte) 0x04, (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41, 237 (byte) 0x31, (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06, (byte) 0x03, 238 (byte) 0x55, (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d, (byte) 0x4d, 239 (byte) 0x6f, (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61, (byte) 0x69, 240 (byte) 0x6e, (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65, (byte) 0x77, 241 (byte) 0x31, (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03, 242 (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41, 243 (byte) 0x6e, (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, 244 (byte) 0x20, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20, 245 (byte) 0x43, (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x30, 246 (byte) 0x81, (byte) 0x9f, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, 247 (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, 248 (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x03, 249 (byte) 0x81, (byte) 0x8d, (byte) 0x00, (byte) 0x30, (byte) 0x81, (byte) 0x89, 250 (byte) 0x02, (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0xa3, (byte) 0x72, 251 (byte) 0xab, (byte) 0xd0, (byte) 0xe4, (byte) 0xad, (byte) 0x2f, (byte) 0xe7, 252 (byte) 0xe2, (byte) 0x79, (byte) 0x07, (byte) 0x36, (byte) 0x3d, (byte) 0x0c, 253 (byte) 0x8d, (byte) 0x42, (byte) 0x9a, (byte) 0x0a, (byte) 0x33, (byte) 0x64, 254 (byte) 0xb3, (byte) 0xcd, (byte) 0xb2, (byte) 0xd7, (byte) 0x3a, (byte) 0x42, 255 (byte) 0x06, (byte) 0x77, (byte) 0x45, (byte) 0x29, (byte) 0xe9, (byte) 0xcb, 256 (byte) 0xb7, (byte) 0x4a, (byte) 0xd6, (byte) 0xee, (byte) 0xad, (byte) 0x01, 257 (byte) 0x91, (byte) 0x9b, (byte) 0x0c, (byte) 0x59, (byte) 0xa1, (byte) 0x03, 258 (byte) 0xfa, (byte) 0xf0, (byte) 0x5a, (byte) 0x7c, (byte) 0x4f, (byte) 0xf7, 259 (byte) 0x8d, (byte) 0x36, (byte) 0x0f, (byte) 0x1f, (byte) 0x45, (byte) 0x7d, 260 (byte) 0x1b, (byte) 0x31, (byte) 0xa1, (byte) 0x35, (byte) 0x0b, (byte) 0x00, 261 (byte) 0xed, (byte) 0x7a, (byte) 0xb6, (byte) 0xc8, (byte) 0x4e, (byte) 0xa9, 262 (byte) 0x86, (byte) 0x4c, (byte) 0x7b, (byte) 0x99, (byte) 0x57, (byte) 0x41, 263 (byte) 0x12, (byte) 0xef, (byte) 0x6b, (byte) 0xbc, (byte) 0x3d, (byte) 0x60, 264 (byte) 0xf2, (byte) 0x99, (byte) 0x1a, (byte) 0xcd, (byte) 0xed, (byte) 0x56, 265 (byte) 0xa4, (byte) 0xe5, (byte) 0x36, (byte) 0x9f, (byte) 0x24, (byte) 0x1f, 266 (byte) 0xdc, (byte) 0x89, (byte) 0x40, (byte) 0xc8, (byte) 0x99, (byte) 0x92, 267 (byte) 0xab, (byte) 0x4a, (byte) 0xb5, (byte) 0x61, (byte) 0x45, (byte) 0x62, 268 (byte) 0xff, (byte) 0xa3, (byte) 0x45, (byte) 0x65, (byte) 0xaf, (byte) 0xf6, 269 (byte) 0x27, (byte) 0x30, (byte) 0x51, (byte) 0x0e, (byte) 0x0e, (byte) 0xeb, 270 (byte) 0x79, (byte) 0x0c, (byte) 0xbe, (byte) 0xb3, (byte) 0x0a, (byte) 0x6f, 271 (byte) 0x29, (byte) 0x06, (byte) 0xdc, (byte) 0x2f, (byte) 0x6b, (byte) 0x51, 272 (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0xa3, 273 (byte) 0x81, (byte) 0xb1, (byte) 0x30, (byte) 0x81, (byte) 0xae, (byte) 0x30, 274 (byte) 0x1d, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x0e, 275 (byte) 0x04, (byte) 0x16, (byte) 0x04, (byte) 0x14, (byte) 0x33, (byte) 0x05, 276 (byte) 0xee, (byte) 0xfe, (byte) 0x6f, (byte) 0x60, (byte) 0xc7, (byte) 0xf9, 277 (byte) 0xa9, (byte) 0xd2, (byte) 0x73, (byte) 0x5c, (byte) 0x8f, (byte) 0x6d, 278 (byte) 0xa2, (byte) 0x2f, (byte) 0x97, (byte) 0x8e, (byte) 0x5d, (byte) 0x51, 279 (byte) 0x30, (byte) 0x7f, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, 280 (byte) 0x23, (byte) 0x04, (byte) 0x78, (byte) 0x30, (byte) 0x76, (byte) 0x80, 281 (byte) 0x14, (byte) 0x33, (byte) 0x05, (byte) 0xee, (byte) 0xfe, (byte) 0x6f, 282 (byte) 0x60, (byte) 0xc7, (byte) 0xf9, (byte) 0xa9, (byte) 0xd2, (byte) 0x73, 283 (byte) 0x5c, (byte) 0x8f, (byte) 0x6d, (byte) 0xa2, (byte) 0x2f, (byte) 0x97, 284 (byte) 0x8e, (byte) 0x5d, (byte) 0x51, (byte) 0xa1, (byte) 0x53, (byte) 0xa4, 285 (byte) 0x51, (byte) 0x30, (byte) 0x4f, (byte) 0x31, (byte) 0x0b, (byte) 0x30, 286 (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06, 287 (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x0b, 288 (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, 289 (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41, (byte) 0x31, 290 (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06, (byte) 0x03, (byte) 0x55, 291 (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d, (byte) 0x4d, (byte) 0x6f, 292 (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61, (byte) 0x69, (byte) 0x6e, 293 (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65, (byte) 0x77, (byte) 0x31, 294 (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03, (byte) 0x55, 295 (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41, (byte) 0x6e, 296 (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x20, 297 (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20, (byte) 0x43, 298 (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x82, (byte) 0x09, 299 (byte) 0x00, (byte) 0xe1, (byte) 0x6a, (byte) 0xa2, (byte) 0xf4, (byte) 0x2e, 300 (byte) 0x55, (byte) 0x48, (byte) 0x0a, (byte) 0x30, (byte) 0x0c, (byte) 0x06, 301 (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x13, (byte) 0x04, (byte) 0x05, 302 (byte) 0x30, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0xff, (byte) 0x30, 303 (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48, 304 (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x05, 305 (byte) 0x05, (byte) 0x00, (byte) 0x03, (byte) 0x81, (byte) 0x81, (byte) 0x00, 306 (byte) 0x8c, (byte) 0x30, (byte) 0x42, (byte) 0xfa, (byte) 0xeb, (byte) 0x1a, 307 (byte) 0x26, (byte) 0xeb, (byte) 0xda, (byte) 0x56, (byte) 0x32, (byte) 0xf2, 308 (byte) 0x9d, (byte) 0xa5, (byte) 0x24, (byte) 0xd8, (byte) 0x3a, (byte) 0xda, 309 (byte) 0x30, (byte) 0xa6, (byte) 0x8b, (byte) 0x46, (byte) 0xfe, (byte) 0xfe, 310 (byte) 0xdb, (byte) 0xf1, (byte) 0xe6, (byte) 0xe1, (byte) 0x7c, (byte) 0x1b, 311 (byte) 0xe7, (byte) 0x77, (byte) 0x00, (byte) 0xa1, (byte) 0x1c, (byte) 0x19, 312 (byte) 0x17, (byte) 0x73, (byte) 0xb0, (byte) 0xf0, (byte) 0x9d, (byte) 0xf3, 313 (byte) 0x4f, (byte) 0xb6, (byte) 0xbc, (byte) 0xc7, (byte) 0x47, (byte) 0x85, 314 (byte) 0x2a, (byte) 0x4a, (byte) 0xa1, (byte) 0xa5, (byte) 0x58, (byte) 0xf5, 315 (byte) 0xc5, (byte) 0x1a, (byte) 0x51, (byte) 0xb1, (byte) 0x04, (byte) 0x80, 316 (byte) 0xee, (byte) 0x3a, (byte) 0xec, (byte) 0x2f, (byte) 0xe1, (byte) 0xfd, 317 (byte) 0x58, (byte) 0xeb, (byte) 0xed, (byte) 0x82, (byte) 0x9e, (byte) 0x38, 318 (byte) 0xa3, (byte) 0x24, (byte) 0x75, (byte) 0xf7, (byte) 0x3e, (byte) 0xc2, 319 (byte) 0xc5, (byte) 0x27, (byte) 0xeb, (byte) 0x6f, (byte) 0x7b, (byte) 0x50, 320 (byte) 0xda, (byte) 0x43, (byte) 0xdc, (byte) 0x3b, (byte) 0x0b, (byte) 0x6f, 321 (byte) 0x78, (byte) 0x8f, (byte) 0xb0, (byte) 0x66, (byte) 0xe1, (byte) 0x12, 322 (byte) 0x87, (byte) 0x5f, (byte) 0x97, (byte) 0x7b, (byte) 0xca, (byte) 0x14, 323 (byte) 0x79, (byte) 0xf7, (byte) 0xe8, (byte) 0x6c, (byte) 0x72, (byte) 0xdb, 324 (byte) 0x91, (byte) 0x65, (byte) 0x17, (byte) 0x54, (byte) 0xe0, (byte) 0x74, 325 (byte) 0x1d, (byte) 0xac, (byte) 0x47, (byte) 0x04, (byte) 0x12, (byte) 0xe0, 326 (byte) 0xc3, (byte) 0x66, (byte) 0x19, (byte) 0x05, (byte) 0x2e, (byte) 0x7e, 327 (byte) 0xf1, (byte) 0x61 328 }; 329 330 /** 331 * Generated from above and converted with: 332 * 333 * openssl pkcs8 -topk8 -outform d -in userkey.pem -nocrypt | xxd -i | sed 's/0x/(byte) 0x/g' 334 */ 335 private static final byte[] FAKE_RSA_KEY_1 = new byte[] { 336 (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x78, (byte) 0x02, (byte) 0x01, 337 (byte) 0x00, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, 338 (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, 339 (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x82, 340 (byte) 0x02, (byte) 0x62, (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x5e, 341 (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x81, (byte) 0x81, 342 (byte) 0x00, (byte) 0xce, (byte) 0x29, (byte) 0xeb, (byte) 0xf6, (byte) 0x5b, 343 (byte) 0x25, (byte) 0xdc, (byte) 0xa1, (byte) 0xa6, (byte) 0x2c, (byte) 0x66, 344 (byte) 0xcb, (byte) 0x20, (byte) 0x90, (byte) 0x27, (byte) 0x86, (byte) 0x8a, 345 (byte) 0x44, (byte) 0x71, (byte) 0x50, (byte) 0xda, (byte) 0xd3, (byte) 0x02, 346 (byte) 0x77, (byte) 0x55, (byte) 0xe9, (byte) 0xe8, (byte) 0x08, (byte) 0xf3, 347 (byte) 0x36, (byte) 0x9a, (byte) 0xae, (byte) 0xab, (byte) 0x04, (byte) 0x6d, 348 (byte) 0x00, (byte) 0x99, (byte) 0xbf, (byte) 0x7d, (byte) 0x0f, (byte) 0x67, 349 (byte) 0x8b, (byte) 0x1d, (byte) 0xd4, (byte) 0x2b, (byte) 0x7c, (byte) 0xcb, 350 (byte) 0xcd, (byte) 0x33, (byte) 0xc7, (byte) 0x84, (byte) 0x30, (byte) 0xe2, 351 (byte) 0x45, (byte) 0x21, (byte) 0xb3, (byte) 0x75, (byte) 0xf5, (byte) 0x79, 352 (byte) 0x02, (byte) 0xda, (byte) 0x50, (byte) 0xa3, (byte) 0x8b, (byte) 0xce, 353 (byte) 0xc3, (byte) 0x8e, (byte) 0x0f, (byte) 0x25, (byte) 0xeb, (byte) 0x08, 354 (byte) 0x2c, (byte) 0xdd, (byte) 0x1c, (byte) 0xcf, (byte) 0xff, (byte) 0x3b, 355 (byte) 0xde, (byte) 0xb6, (byte) 0xaa, (byte) 0x2a, (byte) 0xa9, (byte) 0xc4, 356 (byte) 0x8a, (byte) 0x24, (byte) 0x24, (byte) 0xe6, (byte) 0x29, (byte) 0x0d, 357 (byte) 0x98, (byte) 0x4c, (byte) 0x32, (byte) 0xa1, (byte) 0x7b, (byte) 0x23, 358 (byte) 0x2b, (byte) 0x42, (byte) 0x30, (byte) 0xee, (byte) 0x78, (byte) 0x08, 359 (byte) 0x47, (byte) 0xad, (byte) 0xf2, (byte) 0x96, (byte) 0xd5, (byte) 0xf1, 360 (byte) 0x62, (byte) 0x42, (byte) 0x2d, (byte) 0x35, (byte) 0x19, (byte) 0xb4, 361 (byte) 0x3c, (byte) 0xc9, (byte) 0xc3, (byte) 0x5f, (byte) 0x03, (byte) 0x16, 362 (byte) 0x3a, (byte) 0x23, (byte) 0xac, (byte) 0xcb, (byte) 0xce, (byte) 0x9e, 363 (byte) 0x51, (byte) 0x2e, (byte) 0x6d, (byte) 0x02, (byte) 0x03, (byte) 0x01, 364 (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x81, (byte) 0x80, (byte) 0x16, 365 (byte) 0x59, (byte) 0xc3, (byte) 0x24, (byte) 0x1d, (byte) 0x33, (byte) 0x98, 366 (byte) 0x9c, (byte) 0xc9, (byte) 0xc8, (byte) 0x2c, (byte) 0x88, (byte) 0xbf, 367 (byte) 0x0a, (byte) 0x01, (byte) 0xce, (byte) 0xfb, (byte) 0x34, (byte) 0x7a, 368 (byte) 0x58, (byte) 0x7a, (byte) 0xb0, (byte) 0xbf, (byte) 0xa6, (byte) 0xb2, 369 (byte) 0x60, (byte) 0xbe, (byte) 0x70, (byte) 0x21, (byte) 0xf5, (byte) 0xfc, 370 (byte) 0x85, (byte) 0x0d, (byte) 0x33, (byte) 0x58, (byte) 0xa1, (byte) 0xe5, 371 (byte) 0x09, (byte) 0x36, (byte) 0x84, (byte) 0xb2, (byte) 0x04, (byte) 0x0a, 372 (byte) 0x02, (byte) 0xd3, (byte) 0x88, (byte) 0x1f, (byte) 0x0c, (byte) 0x2b, 373 (byte) 0x1d, (byte) 0xe9, (byte) 0x3d, (byte) 0xe7, (byte) 0x79, (byte) 0xf9, 374 (byte) 0x32, (byte) 0x5c, (byte) 0x8a, (byte) 0x75, (byte) 0x49, (byte) 0x12, 375 (byte) 0xe4, (byte) 0x05, (byte) 0x26, (byte) 0xd4, (byte) 0x2e, (byte) 0x9e, 376 (byte) 0x1f, (byte) 0xcc, (byte) 0x54, (byte) 0xad, (byte) 0x33, (byte) 0x8d, 377 (byte) 0x99, (byte) 0x00, (byte) 0xdc, (byte) 0xf5, (byte) 0xb4, (byte) 0xa2, 378 (byte) 0x2f, (byte) 0xba, (byte) 0xe5, (byte) 0x62, (byte) 0x30, (byte) 0x6d, 379 (byte) 0xe6, (byte) 0x3d, (byte) 0xeb, (byte) 0x24, (byte) 0xc2, (byte) 0xdc, 380 (byte) 0x5f, (byte) 0xb7, (byte) 0x16, (byte) 0x35, (byte) 0xa3, (byte) 0x98, 381 (byte) 0x98, (byte) 0xa8, (byte) 0xef, (byte) 0xe8, (byte) 0xc4, (byte) 0x96, 382 (byte) 0x6d, (byte) 0x38, (byte) 0xab, (byte) 0x26, (byte) 0x6d, (byte) 0x30, 383 (byte) 0xc2, (byte) 0xa0, (byte) 0x44, (byte) 0xe4, (byte) 0xff, (byte) 0x7e, 384 (byte) 0xbe, (byte) 0x7c, (byte) 0x33, (byte) 0xa5, (byte) 0x10, (byte) 0xad, 385 (byte) 0xd7, (byte) 0x1e, (byte) 0x13, (byte) 0x20, (byte) 0xb3, (byte) 0x1f, 386 (byte) 0x41, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xf1, (byte) 0x89, 387 (byte) 0x07, (byte) 0x0f, (byte) 0xe8, (byte) 0xcf, (byte) 0xab, (byte) 0x13, 388 (byte) 0x2a, (byte) 0x8f, (byte) 0x88, (byte) 0x80, (byte) 0x11, (byte) 0x9a, 389 (byte) 0x79, (byte) 0xb6, (byte) 0x59, (byte) 0x3a, (byte) 0x50, (byte) 0x6e, 390 (byte) 0x57, (byte) 0x37, (byte) 0xab, (byte) 0x2a, (byte) 0xd2, (byte) 0xaa, 391 (byte) 0xd9, (byte) 0x72, (byte) 0x73, (byte) 0xff, (byte) 0x8b, (byte) 0x47, 392 (byte) 0x76, (byte) 0xdd, (byte) 0xdc, (byte) 0xf5, (byte) 0x97, (byte) 0x44, 393 (byte) 0x3a, (byte) 0x78, (byte) 0xbe, (byte) 0x17, (byte) 0xb4, (byte) 0x22, 394 (byte) 0x6f, (byte) 0xe5, (byte) 0x23, (byte) 0x70, (byte) 0x1d, (byte) 0x10, 395 (byte) 0x5d, (byte) 0xba, (byte) 0x16, (byte) 0x81, (byte) 0xf1, (byte) 0x45, 396 (byte) 0xce, (byte) 0x30, (byte) 0xb4, (byte) 0xab, (byte) 0x80, (byte) 0xe4, 397 (byte) 0x98, (byte) 0x31, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xda, 398 (byte) 0x82, (byte) 0x9d, (byte) 0x3f, (byte) 0xca, (byte) 0x2f, (byte) 0xe1, 399 (byte) 0xd4, (byte) 0x86, (byte) 0x77, (byte) 0x48, (byte) 0xa6, (byte) 0xab, 400 (byte) 0xab, (byte) 0x1c, (byte) 0x42, (byte) 0x5c, (byte) 0xd5, (byte) 0xc7, 401 (byte) 0x46, (byte) 0x59, (byte) 0x91, (byte) 0x3f, (byte) 0xfc, (byte) 0xcc, 402 (byte) 0xec, (byte) 0xc2, (byte) 0x40, (byte) 0x12, (byte) 0x2c, (byte) 0x8d, 403 (byte) 0x1f, (byte) 0xa2, (byte) 0x18, (byte) 0x88, (byte) 0xee, (byte) 0x82, 404 (byte) 0x4a, (byte) 0x5a, (byte) 0x5e, (byte) 0x88, (byte) 0x20, (byte) 0xe3, 405 (byte) 0x7b, (byte) 0xe0, (byte) 0xd8, (byte) 0x3a, (byte) 0x52, (byte) 0x9a, 406 (byte) 0x26, (byte) 0x6a, (byte) 0x04, (byte) 0xec, (byte) 0xe8, (byte) 0xb9, 407 (byte) 0x48, (byte) 0x40, (byte) 0xe1, (byte) 0xe1, (byte) 0x83, (byte) 0xa6, 408 (byte) 0x67, (byte) 0xa6, (byte) 0xfd, (byte) 0x02, (byte) 0x41, (byte) 0x00, 409 (byte) 0x89, (byte) 0x72, (byte) 0x3e, (byte) 0xb0, (byte) 0x90, (byte) 0xfd, 410 (byte) 0x4c, (byte) 0x0e, (byte) 0xd6, (byte) 0x13, (byte) 0x63, (byte) 0xcb, 411 (byte) 0xed, (byte) 0x38, (byte) 0x88, (byte) 0xb6, (byte) 0x79, (byte) 0xc4, 412 (byte) 0x33, (byte) 0x6c, (byte) 0xf6, (byte) 0xf8, (byte) 0xd8, (byte) 0xd0, 413 (byte) 0xbf, (byte) 0x9d, (byte) 0x35, (byte) 0xac, (byte) 0x69, (byte) 0xd2, 414 (byte) 0x2b, (byte) 0xc1, (byte) 0xf9, (byte) 0x24, (byte) 0x7b, (byte) 0xce, 415 (byte) 0xcd, (byte) 0xcb, (byte) 0xa7, (byte) 0xb2, (byte) 0x7a, (byte) 0x0a, 416 (byte) 0x27, (byte) 0x19, (byte) 0xc9, (byte) 0xaf, (byte) 0x0d, (byte) 0x21, 417 (byte) 0x89, (byte) 0x88, (byte) 0x7c, (byte) 0xad, (byte) 0x9e, (byte) 0x8d, 418 (byte) 0x47, (byte) 0x6d, (byte) 0x3f, (byte) 0xce, (byte) 0x7b, (byte) 0xa1, 419 (byte) 0x74, (byte) 0xf1, (byte) 0xa0, (byte) 0xa1, (byte) 0x02, (byte) 0x41, 420 (byte) 0x00, (byte) 0xd9, (byte) 0xa8, (byte) 0xf5, (byte) 0xfe, (byte) 0xce, 421 (byte) 0xe6, (byte) 0x77, (byte) 0x6b, (byte) 0xfe, (byte) 0x2d, (byte) 0xe0, 422 (byte) 0x1e, (byte) 0xb6, (byte) 0x2e, (byte) 0x12, (byte) 0x4e, (byte) 0x40, 423 (byte) 0xaf, (byte) 0x6a, (byte) 0x7b, (byte) 0x37, (byte) 0x49, (byte) 0x2a, 424 (byte) 0x96, (byte) 0x25, (byte) 0x83, (byte) 0x49, (byte) 0xd4, (byte) 0x0c, 425 (byte) 0xc6, (byte) 0x78, (byte) 0x25, (byte) 0x24, (byte) 0x90, (byte) 0x90, 426 (byte) 0x06, (byte) 0x15, (byte) 0x9e, (byte) 0xfe, (byte) 0xf9, (byte) 0xdf, 427 (byte) 0x5b, (byte) 0xf3, (byte) 0x7e, (byte) 0x38, (byte) 0x70, (byte) 0xeb, 428 (byte) 0x57, (byte) 0xd0, (byte) 0xd9, (byte) 0xa7, (byte) 0x0e, (byte) 0x14, 429 (byte) 0xf7, (byte) 0x95, (byte) 0x68, (byte) 0xd5, (byte) 0xc8, (byte) 0xab, 430 (byte) 0x9d, (byte) 0x3a, (byte) 0x2b, (byte) 0x51, (byte) 0xf9, (byte) 0x02, 431 (byte) 0x41, (byte) 0x00, (byte) 0x96, (byte) 0xdf, (byte) 0xe9, (byte) 0x67, 432 (byte) 0x6c, (byte) 0xdc, (byte) 0x90, (byte) 0x14, (byte) 0xb4, (byte) 0x1d, 433 (byte) 0x22, (byte) 0x33, (byte) 0x4a, (byte) 0x31, (byte) 0xc1, (byte) 0x9d, 434 (byte) 0x2e, (byte) 0xff, (byte) 0x9a, (byte) 0x2a, (byte) 0x95, (byte) 0x4b, 435 (byte) 0x27, (byte) 0x74, (byte) 0xcb, (byte) 0x21, (byte) 0xc3, (byte) 0xd2, 436 (byte) 0x0b, (byte) 0xb2, (byte) 0x46, (byte) 0x87, (byte) 0xf8, (byte) 0x28, 437 (byte) 0x01, (byte) 0x8b, (byte) 0xd8, (byte) 0xb9, (byte) 0x4b, (byte) 0xcd, 438 (byte) 0x9a, (byte) 0x96, (byte) 0x41, (byte) 0x0e, (byte) 0x36, (byte) 0x6d, 439 (byte) 0x40, (byte) 0x42, (byte) 0xbc, (byte) 0xd9, (byte) 0xd3, (byte) 0x7b, 440 (byte) 0xbc, (byte) 0xa7, (byte) 0x92, (byte) 0x90, (byte) 0xdd, (byte) 0xa1, 441 (byte) 0x9c, (byte) 0xce, (byte) 0xa1, (byte) 0x87, (byte) 0x11, (byte) 0x51 442 }; 443 444 @Rule 445 public ActivityScenarioRule mActivityScenarioRule = 446 new ActivityScenarioRule(WebViewCtsActivity.class); 447 448 private WebViewCtsActivity mActivity; 449 450 private WebView mWebView; 451 private SharedSdkWebServer mWebServer; 452 private WebViewOnUiThread mOnUiThread; 453 454 @Before setUp()455 public void setUp() throws Exception { 456 mWebView = getTestEnvironment().getWebView(); 457 mOnUiThread = new WebViewOnUiThread(mWebView); 458 } 459 460 @After cleanup()461 public void cleanup() throws Exception { 462 if (mOnUiThread != null) { 463 mOnUiThread.cleanUp(); 464 } 465 if (mWebServer != null) { 466 stopWebServer(mWebServer); 467 } 468 mActivity = null; 469 } 470 471 @Override createTestEnvironment()472 protected SharedWebViewTestEnvironment createTestEnvironment() { 473 Assume.assumeTrue("WebView is not available", NullWebViewUtils.isWebViewAvailable()); 474 475 SharedWebViewTestEnvironment.Builder builder = new SharedWebViewTestEnvironment.Builder(); 476 477 mActivityScenarioRule 478 .getScenario() 479 .onActivity( 480 activity -> { 481 mActivity = (WebViewCtsActivity) activity; 482 483 WebView webView = mActivity.getWebView(); 484 builder.setHostAppInvoker( 485 SharedWebViewTestEnvironment.createHostAppInvoker( 486 mActivity)) 487 .setContext(mActivity) 488 .setWebView(webView); 489 }); 490 491 SharedWebViewTestEnvironment environment = builder.build(); 492 493 if (environment.getWebView() != null) { 494 new PollingCheck(WebkitUtils.TEST_TIMEOUT_MS) { 495 @Override 496 protected boolean check() { 497 return mActivity.hasWindowFocus(); 498 } 499 }.run(); 500 File f = mActivity.getFileStreamPath("snapshot"); 501 if (f.exists()) { 502 f.delete(); 503 } 504 } 505 return environment; 506 } 507 stopWebServer(SharedSdkWebServer webServer)508 private void stopWebServer(SharedSdkWebServer webServer) throws Exception { 509 assertNotNull(webServer); 510 ThreadPolicy oldPolicy = StrictMode.getThreadPolicy(); 511 ThreadPolicy tmpPolicy = new ThreadPolicy.Builder(oldPolicy) 512 .permitNetwork() 513 .build(); 514 StrictMode.setThreadPolicy(tmpPolicy); 515 webServer.shutdown(); 516 webServer = null; 517 StrictMode.setThreadPolicy(oldPolicy); 518 } 519 520 @Test testInsecureSiteClearsCertificate()521 public void testInsecureSiteClearsCertificate() throws Throwable { 522 final class MockWebViewClient extends WaitForLoadedClient { 523 public MockWebViewClient() { 524 super(mOnUiThread); 525 } 526 @Override 527 public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { 528 handler.proceed(); 529 } 530 } 531 532 mWebServer = getTestEnvironment().getSetupWebServer(SslMode.NO_CLIENT_AUTH); 533 mOnUiThread.setWebViewClient(new MockWebViewClient()); 534 mOnUiThread.loadUrlAndWaitForCompletion( 535 mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL)); 536 SslCertificate cert = mOnUiThread.getCertificate(); 537 assertNotNull(cert); 538 assertEquals("Android", cert.getIssuedTo().getUName()); 539 540 stopWebServer(mWebServer); 541 542 mWebServer = getTestEnvironment().getSetupWebServer(SslMode.INSECURE); 543 mOnUiThread.loadUrlAndWaitForCompletion( 544 mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL)); 545 assertNull(mOnUiThread.getCertificate()); 546 } 547 548 @Test testSecureSiteSetsCertificate()549 public void testSecureSiteSetsCertificate() throws Throwable { 550 SharedWebViewTestEnvironment testEnvironment = getTestEnvironment(); 551 552 final class MockWebViewClient extends WaitForLoadedClient { 553 public MockWebViewClient() { 554 super(mOnUiThread); 555 } 556 @Override 557 public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { 558 handler.proceed(); 559 } 560 } 561 562 mWebServer = testEnvironment.getSetupWebServer(SslMode.INSECURE); 563 mOnUiThread.loadUrlAndWaitForCompletion( 564 mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL)); 565 assertNull(mOnUiThread.getCertificate()); 566 567 stopWebServer(mWebServer); 568 569 mWebServer = testEnvironment.getSetupWebServer(SslMode.NO_CLIENT_AUTH); 570 mOnUiThread.setWebViewClient(new MockWebViewClient()); 571 mOnUiThread.loadUrlAndWaitForCompletion( 572 mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL)); 573 SslCertificate cert = mOnUiThread.getCertificate(); 574 assertNotNull(cert); 575 assertEquals("Android", cert.getIssuedTo().getUName()); 576 } 577 578 @Test testClearSslPreferences()579 public void testClearSslPreferences() throws Throwable { 580 // Load the first page. We expect a call to 581 // WebViewClient.onReceivedSslError(). 582 final SslErrorWebViewClient webViewClient = new SslErrorWebViewClient(mOnUiThread); 583 mWebServer = getTestEnvironment().getSetupWebServer(SslMode.NO_CLIENT_AUTH); 584 final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 585 mOnUiThread.setWebViewClient(webViewClient); 586 mOnUiThread.clearSslPreferences(); 587 mOnUiThread.loadUrlAndWaitForCompletion(url); 588 assertTrue("onReceivedSslError should be called", 589 webViewClient.wasOnReceivedSslErrorCalled()); 590 591 // Wait for the page's favicon to be set to avoid disrupting the test: 592 // if the favicon fetch happens after clearSslPreferences then the host 593 // will be allowed again and we may not see the onReceivedSslError call 594 // that we expect. This polls `getFavicon()` so that we will see it even 595 // if the favicon was cached and no network request needed to be made. 596 new PollingCheck(WebkitUtils.TEST_TIMEOUT_MS) { 597 @Override 598 protected boolean check() { 599 return mOnUiThread.getFavicon() != null; 600 } 601 }.run(); 602 603 // Load the page again. We expect another call to 604 // WebViewClient.onReceivedSslError() since we cleared sslpreferences. 605 mOnUiThread.clearSslPreferences(); 606 webViewClient.resetCallCounts(); 607 mOnUiThread.loadUrlAndWaitForCompletion(url); 608 assertTrue("onReceivedSslError should be called again after clearing SSL preferences", 609 webViewClient.wasOnReceivedSslErrorCalled()); 610 assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle()); 611 612 // Load the page once again, without clearing the sslpreferences. 613 // Make sure we do not get the callback. 614 webViewClient.resetCallCounts(); 615 mOnUiThread.loadUrlAndWaitForCompletion(url); 616 assertFalse("onReceivedSslError should not be called when SSL preferences are not cleared", 617 webViewClient.wasOnReceivedSslErrorCalled()); 618 assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle()); 619 } 620 621 @Test testOnReceivedSslError()622 public void testOnReceivedSslError() throws Throwable { 623 final class MockWebViewClient extends WaitForLoadedClient { 624 private String mErrorUrl; 625 private WebView mWebView; 626 627 public MockWebViewClient() { 628 super(mOnUiThread); 629 } 630 @Override 631 public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { 632 mWebView = view; 633 mErrorUrl = error.getUrl(); 634 handler.proceed(); 635 } 636 public String errorUrl() { 637 return mErrorUrl; 638 } 639 public WebView webView() { 640 return mWebView; 641 } 642 } 643 644 mWebServer = getTestEnvironment().getSetupWebServer(SslMode.NO_CLIENT_AUTH); 645 final String errorUrl = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 646 final MockWebViewClient webViewClient = new MockWebViewClient(); 647 mOnUiThread.setWebViewClient(webViewClient); 648 mOnUiThread.clearSslPreferences(); 649 mOnUiThread.loadUrlAndWaitForCompletion(errorUrl); 650 651 assertEquals(mWebView, webViewClient.webView()); 652 assertEquals(errorUrl, webViewClient.errorUrl()); 653 } 654 655 @Test testOnReceivedSslErrorProceed()656 public void testOnReceivedSslErrorProceed() throws Throwable { 657 final class MockWebViewClient extends WaitForLoadedClient { 658 public MockWebViewClient() { 659 super(mOnUiThread); 660 } 661 @Override 662 public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { 663 handler.proceed(); 664 } 665 } 666 667 mWebServer = getTestEnvironment().getSetupWebServer(SslMode.NO_CLIENT_AUTH); 668 final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 669 mOnUiThread.setWebViewClient(new MockWebViewClient()); 670 mOnUiThread.loadUrlAndWaitForCompletion(url); 671 assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle()); 672 } 673 674 @Test testOnReceivedSslErrorCancel()675 public void testOnReceivedSslErrorCancel() throws Throwable { 676 final class MockWebViewClient extends WaitForLoadedClient { 677 public MockWebViewClient() { 678 super(mOnUiThread); 679 } 680 @Override 681 public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { 682 handler.cancel(); 683 } 684 } 685 686 mWebServer = getTestEnvironment().getSetupWebServer(SslMode.NO_CLIENT_AUTH); 687 final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 688 mOnUiThread.setWebViewClient(new MockWebViewClient()); 689 mOnUiThread.clearSslPreferences(); 690 mOnUiThread.loadUrlAndWaitForCompletion(url); 691 assertNotEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle()); 692 } 693 694 @Test testSslErrorProceedResponseReusedForSameHost()695 public void testSslErrorProceedResponseReusedForSameHost() throws Throwable { 696 // Load the first page. We expect a call to 697 // WebViewClient.onReceivedSslError(). 698 final SslErrorWebViewClient webViewClient = new SslErrorWebViewClient(mOnUiThread); 699 mWebServer = getTestEnvironment().getSetupWebServer(SslMode.NO_CLIENT_AUTH); 700 final String firstUrl = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL1); 701 mOnUiThread.setWebViewClient(webViewClient); 702 mOnUiThread.clearSslPreferences(); 703 mOnUiThread.loadUrlAndWaitForCompletion(firstUrl); 704 assertTrue("onReceivedSslError should be called on loading first page", 705 webViewClient.wasOnReceivedSslErrorCalled()); 706 707 // Load the second page. We don't expect a call to 708 // WebViewClient.onReceivedSslError(), but the page should load. 709 webViewClient.resetCallCounts(); 710 final String sameHostUrl = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL2); 711 mOnUiThread.loadUrlAndWaitForCompletion(sameHostUrl); 712 assertFalse("onReceivedSslError should not be called on loading second page", 713 webViewClient.wasOnReceivedSslErrorCalled()); 714 assertEquals("Second page", mOnUiThread.getTitle()); 715 } 716 717 @Test testSslErrorProceedResponseNotReusedForDifferentHost()718 public void testSslErrorProceedResponseNotReusedForDifferentHost() throws Throwable { 719 // Load the first page. We expect a call to 720 // WebViewClient.onReceivedSslError(). 721 final SslErrorWebViewClient webViewClient = new SslErrorWebViewClient(mOnUiThread); 722 mWebServer = getTestEnvironment().getSetupWebServer(SslMode.NO_CLIENT_AUTH); 723 final String firstUrl = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL1); 724 mOnUiThread.setWebViewClient(webViewClient); 725 mOnUiThread.clearSslPreferences(); 726 mOnUiThread.loadUrlAndWaitForCompletion(firstUrl); 727 assertTrue("onReceivedSslError should be called when request is sent to localhost", 728 webViewClient.wasOnReceivedSslErrorCalled()); 729 730 // Load the second page. We expect another call to 731 // WebViewClient.onReceivedSslError(). 732 webViewClient.resetCallCounts(); 733 // The test server uses the host "localhost". "127.0.0.1" works as an 734 // alias, but will be considered unique by the WebView. 735 final String differentHostUrl = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL2).replace( 736 "localhost", "127.0.0.1"); 737 mOnUiThread.loadUrlAndWaitForCompletion(differentHostUrl); 738 assertTrue("onReceivedSslError should be called when request is sent to 127.0.0.1", 739 webViewClient.wasOnReceivedSslErrorCalled()); 740 assertEquals("Second page", mOnUiThread.getTitle()); 741 } 742 743 @Test testSecureServerRequestingClientCertDoesNotCancelRequest()744 public void testSecureServerRequestingClientCertDoesNotCancelRequest() throws Throwable { 745 mWebServer = getTestEnvironment().getSetupWebServer(SslMode.WANTS_CLIENT_AUTH); 746 final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 747 final SslErrorWebViewClient webViewClient = new SslErrorWebViewClient(mOnUiThread); 748 mOnUiThread.setWebViewClient(webViewClient); 749 mOnUiThread.clearSslPreferences(); 750 mOnUiThread.loadUrlAndWaitForCompletion(url); 751 // Page loaded OK... 752 assertTrue("onReceivedSslError should be called", 753 webViewClient.wasOnReceivedSslErrorCalled()); 754 assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle()); 755 assertEquals(0, webViewClient.onReceivedErrorCode()); 756 } 757 758 @Test testSecureServerRequiringClientCertDoesCancelRequest()759 public void testSecureServerRequiringClientCertDoesCancelRequest() throws Throwable { 760 mWebServer = getTestEnvironment().getSetupWebServer(SslMode.NEEDS_CLIENT_AUTH); 761 final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 762 final SslErrorWebViewClient webViewClient = new SslErrorWebViewClient(mOnUiThread); 763 mOnUiThread.setWebViewClient(webViewClient); 764 mOnUiThread.clearSslPreferences(); 765 loadUrlUntilError(webViewClient, url, WebViewClient.ERROR_FAILED_SSL_HANDSHAKE); 766 // Page NOT loaded OK... 767 // 768 // In this test, we expect both a recoverable and non-recoverable error: 769 // 770 // 1. WebView does not trust the test server's certificate. This is a recoverable error, so 771 // WebView invokes #onReceivedSslError (and the WebViewClient calls #proceed). We don't 772 // specifically intend to test this part of the scenario, but we can't easily mock out 773 // WebView's certificate roots. 774 // 2. WebView proceeds with the handshake without providing client authentication. The 775 // server fails the client. This is non-recoverable, so WebView invokes 776 // #onReceivedError. 777 // 778 // We only assert the second error, since earlier WebView versions had a bug in which 779 // WebView hit error 2 first, which prevented it from hitting error 1. 780 assertFalse("Title should not be updated, since page load should have failed", 781 TestHtmlConstants.HELLO_WORLD_TITLE.equals(mOnUiThread.getTitle())); 782 } 783 784 @Test testProceedClientCertRequest()785 public void testProceedClientCertRequest() throws Throwable { 786 mWebServer = getTestEnvironment().getSetupWebServer(SslMode.NEEDS_CLIENT_AUTH); 787 String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 788 final ClientCertWebViewClient webViewClient = new ClientCertWebViewClient(mOnUiThread); 789 mOnUiThread.setWebViewClient(webViewClient); 790 clearClientCertPreferences(); 791 mOnUiThread.loadUrlAndWaitForCompletion(url); 792 assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle()); 793 794 // Test that the user's response for this server is kept in cache. Load a different 795 // page from the same server and make sure we don't receive a client cert request callback. 796 webViewClient.resetCallCounts(); 797 url = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL1); 798 mOnUiThread.loadUrlAndWaitForCompletion(url); 799 assertEquals(TestHtmlConstants.HTML_URL1_TITLE, mOnUiThread.getTitle()); 800 assertEquals("onReceivedClientCertRequest should not be called", 801 0, webViewClient.getClientCertRequestCount()); 802 803 // Now clear the cache and reload the page. We should receive a new callback. 804 webViewClient.resetCallCounts(); 805 clearClientCertPreferences(); 806 mOnUiThread.loadUrlAndWaitForCompletion(url); 807 assertEquals(TestHtmlConstants.HTML_URL1_TITLE, mOnUiThread.getTitle()); 808 assertEquals("onReceivedClientCertRequest should be called once", 809 1, webViewClient.getClientCertRequestCount()); 810 } 811 812 @Test testProceedClientCertRequestKeyWithAndroidKeystoreKey()813 public void testProceedClientCertRequestKeyWithAndroidKeystoreKey() throws Throwable { 814 mWebServer = getTestEnvironment().getSetupWebServer(SslMode.NEEDS_CLIENT_AUTH); 815 String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 816 final ClientCertWebViewClient webViewClient = new ClientCertWebViewClient( 817 mOnUiThread, 818 true // use an Android Keystore backed private key 819 ); 820 mOnUiThread.setWebViewClient(webViewClient); 821 clearClientCertPreferences(); 822 mOnUiThread.loadUrlAndWaitForCompletion(url); 823 assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle()); 824 825 // Test that the user's response for this server is kept in cache. Load a different 826 // page from the same server and make sure we don't receive a client cert request callback. 827 webViewClient.resetCallCounts(); 828 url = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL1); 829 mOnUiThread.loadUrlAndWaitForCompletion(url); 830 assertEquals(TestHtmlConstants.HTML_URL1_TITLE, mOnUiThread.getTitle()); 831 assertEquals("onReceivedClientCertRequest should not be called", 832 0, webViewClient.getClientCertRequestCount()); 833 834 // Now clear the cache and reload the page. We should receive a new callback. 835 webViewClient.resetCallCounts(); 836 clearClientCertPreferences(); 837 mOnUiThread.loadUrlAndWaitForCompletion(url); 838 assertEquals(TestHtmlConstants.HTML_URL1_TITLE, mOnUiThread.getTitle()); 839 assertEquals("onReceivedClientCertRequest should be called once", 840 1, webViewClient.getClientCertRequestCount()); 841 } 842 843 /** 844 * Loads a url until a specific error code. This is meant to be used when two different errors 845 * can race. Specifically, this is meant to be used to workaround the TLS 1.3 (Android Q and 846 * above) race condition where a server <b>may</b> close the connection at the same time the 847 * client sends the HTTP request, emitting {@code ERROR_CONNECT} instead of {@code 848 * ERROR_FAILED_SSL_HANDSHAKE}. 849 */ loadUrlUntilError(SslErrorWebViewClient client, String url, int expectedErrorCode)850 private void loadUrlUntilError(SslErrorWebViewClient client, String url, 851 int expectedErrorCode) { 852 int maxTries = 40; 853 for (int i = 0; i < maxTries; i++) { 854 mOnUiThread.loadUrlAndWaitForCompletion(url); 855 if (client.onReceivedErrorCode() == expectedErrorCode) { 856 return; 857 } 858 } 859 throw new RuntimeException( 860 "Reached max number of tries and never saw error " + expectedErrorCode); 861 } 862 863 @Test testIgnoreClientCertRequest()864 public void testIgnoreClientCertRequest() throws Throwable { 865 mWebServer = getTestEnvironment().getSetupWebServer(SslMode.NEEDS_CLIENT_AUTH); 866 String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 867 final ClientCertWebViewClient webViewClient = new ClientCertWebViewClient(mOnUiThread); 868 mOnUiThread.setWebViewClient(webViewClient); 869 clearClientCertPreferences(); 870 // Ignore the request. Load should fail. 871 webViewClient.setAction(ClientCertWebViewClient.IGNORE); 872 loadUrlUntilError(webViewClient, url, WebViewClient.ERROR_FAILED_SSL_HANDSHAKE); 873 assertNotEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle()); 874 // At least one of the loads done by loadUrlUntilError() should produce 875 // onReceivedClientCertRequest. 876 assertTrue("onReceivedClientCertRequest should be called at least once", 877 webViewClient.getClientCertRequestCount() >= 1); 878 879 // Load a different page from the same domain, ignoring the request. We should get a callback, 880 // and load should fail. 881 webViewClient.resetCallCounts(); 882 url = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL1); 883 loadUrlUntilError(webViewClient, url, WebViewClient.ERROR_FAILED_SSL_HANDSHAKE); 884 assertNotEquals(TestHtmlConstants.HTML_URL1_TITLE, mOnUiThread.getTitle()); 885 // At least one of the loads done by loadUrlUntilError() should produce 886 // onReceivedClientCertRequest. 887 assertTrue("onReceivedClientCertRequest should be called at least once for second URL", 888 webViewClient.getClientCertRequestCount() >= 1); 889 890 // Reload, proceeding the request. Load should succeed. 891 webViewClient.setAction(ClientCertWebViewClient.PROCEED); 892 url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 893 mOnUiThread.loadUrlAndWaitForCompletion(url); 894 assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle()); 895 } 896 897 @Test testCancelClientCertRequest()898 public void testCancelClientCertRequest() throws Throwable { 899 mWebServer = getTestEnvironment().getSetupWebServer(SslMode.NEEDS_CLIENT_AUTH); 900 final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 901 final ClientCertWebViewClient webViewClient = new ClientCertWebViewClient(mOnUiThread); 902 mOnUiThread.setWebViewClient(webViewClient); 903 clearClientCertPreferences(); 904 // Cancel the request. Load should fail. 905 webViewClient.setAction(ClientCertWebViewClient.CANCEL); 906 loadUrlUntilError(webViewClient, url, WebViewClient.ERROR_FAILED_SSL_HANDSHAKE); 907 assertNotEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle()); 908 // At least one of the loads done by loadUrlUntilError() should produce 909 // onReceivedClientCertRequest. 910 assertTrue("onReceivedClientCertRequest should be called at least once", 911 webViewClient.getClientCertRequestCount() >= 1); 912 913 // Reload. The request should fail without generating a new callback. 914 webViewClient.resetCallCounts(); 915 loadUrlUntilError(webViewClient, url, WebViewClient.ERROR_FAILED_SSL_HANDSHAKE); 916 // None of the loads done by loadUrlUntilError() should produce onReceivedClientCertRequest. 917 assertEquals("onReceivedClientCertRequest should not be called for reload", 918 0, webViewClient.getClientCertRequestCount()); 919 assertNotEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle()); 920 } 921 922 @Test testClientCertIssuersReceivedCorrectly()923 public void testClientCertIssuersReceivedCorrectly() throws Throwable { 924 mWebServer = getTestEnvironment().getSetupWebServer(SslMode.NEEDS_CLIENT_AUTH, 925 FAKE_RSA_CA_1, 0, 0); 926 final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 927 final ClientCertWebViewClient webViewClient = new ClientCertWebViewClient(mOnUiThread); 928 mOnUiThread.setWebViewClient(webViewClient); 929 clearClientCertPreferences(); 930 mOnUiThread.loadUrlAndWaitForCompletion(url); 931 // Verify that issuers sent by the server are received correctly 932 CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); 933 X509Certificate cert = (X509Certificate) certFactory.generateCertificate( 934 new ByteArrayInputStream(FAKE_RSA_CA_1)); 935 Principal[] principals = webViewClient.getPrincipals(); 936 assertEquals(1, principals.length); 937 // TODO: should we issue getIssuerX500Principal instead? 938 assertEquals(cert.getIssuerDN(), principals[0]); 939 } 940 clearClientCertPreferences()941 private void clearClientCertPreferences() { 942 final AtomicBoolean cleared = new AtomicBoolean(false); 943 WebView.clearClientCertPreferences(new Runnable() { 944 @Override 945 public void run() { 946 cleared.set(true); 947 } 948 }); 949 // Wait until clearclientcertpreferences clears the preferences. Generally this is just a 950 // thread hopping. 951 new PollingCheck(WebkitUtils.TEST_TIMEOUT_MS) { 952 @Override 953 protected boolean check() { 954 return cleared.get(); 955 } 956 }.run(); 957 } 958 959 // Note that this class is not thread-safe. 960 static class SslErrorWebViewClient extends WaitForLoadedClient { 961 private boolean mWasOnReceivedSslErrorCalled; 962 private String mErrorUrl; 963 private int mErrorCode; 964 SslErrorWebViewClient(WebViewOnUiThread onUiThread)965 public SslErrorWebViewClient(WebViewOnUiThread onUiThread) { 966 super(onUiThread); 967 } 968 @Override onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)969 public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { 970 mWasOnReceivedSslErrorCalled = true; 971 mErrorUrl = error.getUrl(); 972 handler.proceed(); 973 } 974 @Override onReceivedError(WebView view, int errorCode, String description, String failingUrl)975 public void onReceivedError(WebView view, int errorCode, String description, 976 String failingUrl) { 977 mErrorCode = errorCode; 978 } 979 @CallSuper resetCallCounts()980 public void resetCallCounts() { 981 mWasOnReceivedSslErrorCalled = false; 982 mErrorUrl = null; 983 mErrorCode = 0; 984 } wasOnReceivedSslErrorCalled()985 public boolean wasOnReceivedSslErrorCalled() { 986 return mWasOnReceivedSslErrorCalled; 987 } errorUrl()988 public String errorUrl() { 989 return mErrorUrl; 990 } onReceivedErrorCode()991 public int onReceivedErrorCode() { 992 return mErrorCode; 993 } 994 } 995 996 // Modifies the default behavior of SslErrorWebViewClient to accept the request, and provide 997 // certs. 998 static class ClientCertWebViewClient extends SslErrorWebViewClient { 999 // User Actions 1000 public static final int PROCEED = 1; 1001 public static final int CANCEL = 2; 1002 public static final int IGNORE = 3; 1003 1004 private final boolean mKeyFromAndroidKeystore; 1005 1006 private int mClientCertRequests; 1007 private int mAction = PROCEED; 1008 private Principal[] mPrincipals; 1009 ClientCertWebViewClient(WebViewOnUiThread onUiThread)1010 public ClientCertWebViewClient(WebViewOnUiThread onUiThread) { 1011 this(onUiThread, false); 1012 } 1013 ClientCertWebViewClient(WebViewOnUiThread onUiThread, boolean keyFromAndroidKeystore)1014 public ClientCertWebViewClient(WebViewOnUiThread onUiThread, 1015 boolean keyFromAndroidKeystore) { 1016 super(onUiThread); 1017 mKeyFromAndroidKeystore = keyFromAndroidKeystore; 1018 } 1019 getClientCertRequestCount()1020 public int getClientCertRequestCount() { 1021 return mClientCertRequests; 1022 } 1023 getPrincipals()1024 public Principal[] getPrincipals() { 1025 return mPrincipals; 1026 } 1027 setAction(int action)1028 public void setAction(int action) { 1029 mAction = action; 1030 } 1031 1032 @Override resetCallCounts()1033 public void resetCallCounts() { 1034 super.resetCallCounts(); 1035 mClientCertRequests = 0; 1036 mPrincipals = null; 1037 } 1038 1039 @Override onReceivedClientCertRequest(WebView view, ClientCertRequest request)1040 public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) { 1041 mClientCertRequests++; 1042 mPrincipals = request.getPrincipals(); 1043 if (mAction == IGNORE) { 1044 request.ignore(); 1045 return; 1046 } 1047 if (mAction == CANCEL) { 1048 request.cancel(); 1049 return; 1050 } 1051 if (mAction == PROCEED) { 1052 try { 1053 CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); 1054 X509Certificate[] certChain = new X509Certificate[] { 1055 (X509Certificate) certFactory.generateCertificate( 1056 new ByteArrayInputStream(FAKE_RSA_USER_1)), 1057 (X509Certificate) certFactory.generateCertificate( 1058 new ByteArrayInputStream(FAKE_RSA_CA_1)) 1059 }; 1060 KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 1061 PrivateKey key = keyFactory.generatePrivate( 1062 new PKCS8EncodedKeySpec(FAKE_RSA_KEY_1)); 1063 1064 if (mKeyFromAndroidKeystore) { 1065 // Key needs to be backed by Android Keystore -- import it there. 1066 KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); 1067 keyStore.load(null); 1068 Log.d(LOGTAG, "Importing private key into Android Keystore..."); 1069 keyStore.setEntry( 1070 "fake1", 1071 new KeyStore.PrivateKeyEntry(key, certChain), 1072 null); 1073 1074 key = (PrivateKey) keyStore.getKey("fake1", null); 1075 Log.i(LOGTAG, "Imported private key into Android Keystore. key: " + key); 1076 } 1077 1078 request.proceed(key, certChain); 1079 return; 1080 } catch (Exception e) { 1081 throw new RuntimeException(e); 1082 } 1083 } 1084 throw new IllegalStateException("unknown action"); 1085 } 1086 } 1087 } 1088