• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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