1 /*
2  * Copyright (C) 2021 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 com.android.server.wifi;
18 
19 import static com.android.server.wifi.InsecureEapNetworkHandler.TOFU_ANONYMOUS_IDENTITY;
20 
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertNotNull;
24 import static org.junit.Assert.assertTrue;
25 import static org.junit.Assume.assumeFalse;
26 import static org.junit.Assume.assumeTrue;
27 import static org.mockito.Mockito.any;
28 import static org.mockito.Mockito.anyBoolean;
29 import static org.mockito.Mockito.anyInt;
30 import static org.mockito.Mockito.anyString;
31 import static org.mockito.Mockito.argThat;
32 import static org.mockito.Mockito.atLeastOnce;
33 import static org.mockito.Mockito.eq;
34 import static org.mockito.Mockito.mock;
35 import static org.mockito.Mockito.never;
36 import static org.mockito.Mockito.spy;
37 import static org.mockito.Mockito.validateMockitoUsage;
38 import static org.mockito.Mockito.verify;
39 import static org.mockito.Mockito.when;
40 import static org.mockito.Mockito.withSettings;
41 
42 import android.app.Notification;
43 import android.content.BroadcastReceiver;
44 import android.content.Intent;
45 import android.net.wifi.WifiConfiguration;
46 import android.net.wifi.WifiContext;
47 import android.net.wifi.WifiEnterpriseConfig;
48 import android.os.Handler;
49 import android.os.test.TestLooper;
50 import android.text.TextUtils;
51 import android.text.format.DateFormat;
52 
53 import androidx.test.filters.SmallTest;
54 
55 import com.android.dx.mockito.inline.extended.ExtendedMockito;
56 import com.android.modules.utils.build.SdkLevel;
57 import com.android.server.wifi.util.CertificateSubjectInfo;
58 import com.android.wifi.resources.R;
59 
60 import org.junit.After;
61 import org.junit.Before;
62 import org.junit.Test;
63 import org.mockito.Answers;
64 import org.mockito.ArgumentCaptor;
65 import org.mockito.Captor;
66 import org.mockito.Mock;
67 import org.mockito.MockitoAnnotations;
68 import org.mockito.MockitoSession;
69 import org.mockito.stubbing.Answer;
70 
71 import java.io.ByteArrayInputStream;
72 import java.io.InputStream;
73 import java.security.KeyStore;
74 import java.security.cert.CertificateFactory;
75 import java.security.cert.X509Certificate;
76 import java.util.ArrayList;
77 import java.util.Collections;
78 import java.util.List;
79 
80 /**
81  * Unit tests for {@link com.android.server.wifi.InsecureEapNetworkHandlerTest}.
82  */
83 @SmallTest
84 public class InsecureEapNetworkHandlerTest extends WifiBaseTest {
85 
86     private static final int ACTION_ACCEPT = 0;
87     private static final int ACTION_REJECT = 1;
88     private static final int ACTION_TAP = 2;
89     private static final int ACTION_FORGET = 3;
90     private static final String WIFI_IFACE_NAME = "wlan-test-9";
91     private static final int FRAMEWORK_NETWORK_ID = 2;
92     private static final String TEST_SSID = "\"test_ssid\"";
93     private static final String TEST_IDENTITY = "userid";
94     private static final String TEST_PASSWORD = "myPassWord!";
95     private static final String TEST_EXPECTED_SHA_256_SIGNATURE = "54:59:5D:FC:64:9C:17:72:C0:59:"
96             + "9D:25:BD:1F:04:18:E6:00:AB:F4:0A:F0:78:D8:9A:FF:56:C0:7C:89:96:2F";
97     private static final int TEST_GEN_CA_CERT = 0;
98     private static final int TEST_GEN_CA2_CERT = 1;
99     private static final int TEST_GEN_SERVER_CERT = 2;
100     private static final int TEST_GEN_SELF_SIGNED_CERT = 3;
101     private static final int TEST_GEN_FAKE_CA_CERT = 4;
102     private static final int TEST_GEN_SERVER_CERTIFICATE_WITHOUT_COMMON_NAME = 5;
103 
104     private static final String TEST_SERVER_CERTIFICATE = "-----BEGIN CERTIFICATE-----\n"
105             + "MIIGPjCCBCagAwIBAgIUN2Ss1JmvjveRe97iWoNh4V+Y5LYwDQYJKoZIhvcNAQEM\n"
106             + "BQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRswGQYDVQQK\n"
107             + "DBJBbmRyb2lkIFdpLUZpIFRlc3QxGDAWBgNVBAsMD2FuZHJvaWR3aWZpLm9lbTE8\n"
108             + "MDoGA1UEAwwzQW5kcm9pZCBQYXJ0bmVyIFJvb3QgQ0EgZm9yIHRlc3RpbmcgYW5k\n"
109             + "IGRldmVsb3BtZW50MB4XDTIzMDQxMzAyMTYwMVoXDTQzMDQwODAyMTYwMVowgYMx\n"
110             + "CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMR0wGwYDVQQKDBRBbmRy\n"
111             + "b2lkIFdpLUZpIFRlc3RlcjEYMBYGA1UECwwPYW5kcm9pZHdpZmkub2VtMSYwJAYD\n"
112             + "VQQDDB1BbmRyb2lkIFdpLUZpIE9FTSBUZXN0IFNlcnZlcjCCAiIwDQYJKoZIhvcN\n"
113             + "AQEBBQADggIPADCCAgoCggIBAKveC9QnsxvM2TMzkUINabtM2Bi5M5gzV4v1MN0h\n"
114             + "n1XjXhfRXwwLMK9xtV05r91YQaOTPkHNgA6nhjmL7agcquGPlR7nuS04oxCaqfo4\n"
115             + "unbroyyqDMaXd8U6B1VlvWSbWAAhBEEAPYDhFXF9V83XHEGcp61Hs4VetGmlC3tW\n"
116             + "W1CLIk+o9JRYsZeK4Q1DurAY7YPU8U84QNxPG7OXg+ensGtspuLLNFEdnd9tSi45\n"
117             + "u5KyPpnSwTdRGSCfMVocxj0EINpdrLnWZyf9NX8Uo7tg/D0TFVBo+MbKjgItIdMg\n"
118             + "STLQwceOdOGHZTPiItzpFcP9EA5ug5gXobPjzDTJO2S3NhUt5NURfGr/wyepxR25\n"
119             + "PDRhBgc/xwc7JrtDGaqmknguZuf7Zai/m4iquC0Wh38bWKms8R0ND/H923aFppxp\n"
120             + "vzX/sWotsTYWiGMehh7v6iwIYADifsXBlJXTUhTZt6cnwttZYfp5oqymCsIhXKVU\n"
121             + "IXOE/PLcU71G9U+jCa7PNs5X5LgqorNPABOpkVL+fDpvopNCdhOEVvwCAIl4tIxl\n"
122             + "M0goFbBmY1wnFFYIUki91UfbeUimCUbBq/RSxuXn3liVB/X+dnyjJ3RnNxJ3Wy1m\n"
123             + "mcHFIVV5VxN6tC7XTXYgZAv0EJGCcVn0RN3ldPWGRLTEIQu7cXRSfqs89N4S31Et\n"
124             + "SjaxAgMBAAGjgZMwgZAwHQYDVR0OBBYEFHh9fcIU3LHamK7PdpasvHmzyRoLMB8G\n"
125             + "A1UdIwQYMBaAFH7ro7AWsBlMNpyRXHGW1hG4c1ocMAkGA1UdEwQCMAAwCwYDVR0P\n"
126             + "BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMCEGA1UdEQQaMBiCFnNlcnZlci5h\n"
127             + "bmRyb2lkd2lmaS5vZW0wDQYJKoZIhvcNAQEMBQADggIBAOIkOLyF8mmYvj8TeM2V\n"
128             + "d4YMj4sWf7L5C2lq9OGBJwZad1xytymWWZ7PpNf1MopabfUzxPjw5EfMC94MJmpf\n"
129             + "gqYOwFAye5fXQ8CLC39tb681u44tv/B5vqP74TKVhCR8O1YCsIssa8t8e5nIwcYr\n"
130             + "fj3SBu7iOLtL7zjfEXFo3oSEwVYnvS3lhZL8NTrrHscy/ZLFE3nGRq2d3jPbyuoH\n"
131             + "1FJwenxnD6a/AztERPkRNGk2oSFkWecNU9PC9w3bI5wF4I2AIaFgBOj20S7pVtq7\n"
132             + "7nhKnQFrZYVeWbqbInQcRAcSopI6D6tB/F/T9R1WCWBxvpwdciv7BeNgOtGKAszA\n"
133             + "z0sOxI6O4U77R+tFeb0vCwC0OhVL3W0zX3Fy2835D/hC2P1jmMBlxLVKYHY48RBC\n"
134             + "sG1I1qAMD4eXle8rG9MkB9cE5KfncjCrzSQjT8gs7QBTafb6B3WDdwzfaCaQTOOF\n"
135             + "Tsyrdq0TTJP71bt5qWTr6UZIBE5Tjel+DPpvQlPZPYygXPrI3WBcT12VLhti0II6\n"
136             + "1jgkS8fPLR0VypHR02V5fqCRmy9ln0rSyHXFwL3JpeXYD92eLOKdS1MhIUN4bDxZ\n"
137             + "fiXXVKpKU4gqqWAan2RjbBzQjsi6Eh3yuDm2SAqNZVacpOt7BIslqEZ+Og6KhTTk\n"
138             + "DCzyEOB87ySrUWu3PN3r2sJN\n"
139             + "-----END CERTIFICATE-----";
140 
141     private static final String TEST_CA_CERTIFICATE = "-----BEGIN CERTIFICATE-----\n"
142             + "MIIGADCCA+igAwIBAgIUFkmrYCj/UYNrizDdMATu6dE3lBIwDQYJKoZIhvcNAQEM\n"
143             + "BQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRswGQYDVQQK\n"
144             + "DBJBbmRyb2lkIFdpLUZpIFRlc3QxGDAWBgNVBAsMD2FuZHJvaWR3aWZpLm9lbTE8\n"
145             + "MDoGA1UEAwwzQW5kcm9pZCBQYXJ0bmVyIFJvb3QgQ0EgZm9yIHRlc3RpbmcgYW5k\n"
146             + "IGRldmVsb3BtZW50MB4XDTIzMDQxMzAyMTYwMVoXDTQzMDQwODAyMTYwMVowgZcx\n"
147             + "CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRswGQYDVQQKDBJBbmRy\n"
148             + "b2lkIFdpLUZpIFRlc3QxGDAWBgNVBAsMD2FuZHJvaWR3aWZpLm9lbTE8MDoGA1UE\n"
149             + "AwwzQW5kcm9pZCBQYXJ0bmVyIFJvb3QgQ0EgZm9yIHRlc3RpbmcgYW5kIGRldmVs\n"
150             + "b3BtZW50MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9JERd2HVp/PI\n"
151             + "3WmaaHDKHDuWZoxUDlyVrTDd1Vu2zhH3A5KJ232QOMxJiLdZ/KxgcpGlAEllijae\n"
152             + "xihxhkHEYr7ff2/p6ZhUWr+0vuk8f4TZsKDAE0SoZoDBHTIbrJf8hHM5/+R//sx1\n"
153             + "/fTf8abOj20zyeWmXqvUNXoVKiRvjiZD69tcRHmfmTOMX0lAirOel8ZwwDFamH8d\n"
154             + "wov0IIyd58m6CV91WnScgg7TOzw/IGpccft73RbDw7cHU5i3G3KhOqamwJbErgya\n"
155             + "x97AsSVCqjBz7rEwm6pHjUagbgVAk9ULmI1McQzMINIrOWRF0Q8awWpvDNwPu86J\n"
156             + "W/LfyzAruWtriimycpl7wv0b/f7JhKerG0+44JUI0sgTz/kobAsU8nfYSyVu8+cX\n"
157             + "HwnDE2jBGB6co2Y00eVKxy6+gWTekpQTyHuPoCieNDukC/38Mj+U0KUZkgGv4CL7\n"
158             + "zaVBGzjSjtnAp47aXciaDvDbpST23ICS7TN5cUnXQ1fWfNUMNkEbIPy2mrlRoCxg\n"
159             + "OJ67UEvGIygE0IUvwDfFvF21+1yKk6D/kU9gMgd6DKtvWj1CIyKXWf+rQ01OHNhX\n"
160             + "YcOTkF5aF2WU558DuS+utGBzXWFsLxqBRe9nDb9W/SlrT2jajfwLelMddvtZmVsY\n"
161             + "NG8IeY8lDs5hcFBvm/BDr0SvBDhs9H0CAwEAAaNCMEAwHQYDVR0OBBYEFH7ro7AW\n"
162             + "sBlMNpyRXHGW1hG4c1ocMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGG\n"
163             + "MA0GCSqGSIb3DQEBDAUAA4ICAQBINF6auWUhCO0l/AqO5pLgOqZ7BjAzHGDNapW+\n"
164             + "3nn2YicDD/X2eJASfsd3jN5JluBlbLqRBBWnIsNG/fyKxY8I4+IrR1x8ovwBjeJ3\n"
165             + "McQeCW2zedluVp2SW3LaNQS+aptXHATJ6O8EOny2LDM+obEtFyLuDC89a1TXjEdj\n"
166             + "XGIYmSJ8RwpKAi4u6ff4jhtNTSEa/eIUE5zUREV0916xtmu5y1vlmsEbpLEquOph\n"
167             + "ZWxpUVTqGEyc0hHaivAWyBG1dtRgov5olzHchM2TsEq/VufiRAw5uzRQ/sAyVjj4\n"
168             + "pcvWnLDLTYk/+uIG1zmbc0rNpAC7b3tplA4OqTtFb3yX0ppPFUg4OaxhMyu4WqS3\n"
169             + "roNiXc8BmtfzMqyWAG21QUfosLa8heiiHgnvkiUa9V2oJ4kWAhOTmLdU70aocu4N\n"
170             + "pcN5jcT5hSl/A91Lvfht0C9BLOrXU+RDCNAVIUnnWSrgduUPTydKVdUkLxau4G/+\n"
171             + "G8fKAyeCouFNq7bp4DEMkgqAWpx96Qe6FLxAS59Ig3tI8MZSieBZezJyjP4GWtuq\n"
172             + "QsnARbwD7z73FWQ+eqXOhkoqDoQc8E2lQGe8OGbacGuUwXo3PUgGaJobz+2Hqa9g\n"
173             + "6AnBkH6AbvooUwSWSCyYIf2LA+GvZotI+PXWuQL7dqWtkaNf98qqfnlZXjp51e+h\n"
174             + "B8nquw==\n"
175             + "-----END CERTIFICATE-----";
176 
177     private static final String TEST_CA2_CERTIFICATE = "-----BEGIN CERTIFICATE-----\n"
178             + "MIIGADCCA+igAwIBAgIUGm2nmrZw4ADU7h/TGKd67Uz5bJIwDQYJKoZIhvcNAQEM\n"
179             + "BQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRswGQYDVQQK\n"
180             + "DBJBbmRyb2lkIFdpLUZpIFRlc3QxGDAWBgNVBAsMD2FuZHJvaWR3aWZpLm9lbTE8\n"
181             + "MDoGA1UEAwwzQW5vdGhlciBBbmRyb2lkIFJvb3QgQ0EgZm9yIHRlc3RpbmcgYW5k\n"
182             + "IGRldmVsb3BtZW50MB4XDTIzMDQxMzAyMTkxOVoXDTQzMDQwODAyMTkxOVowgZcx\n"
183             + "CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRswGQYDVQQKDBJBbmRy\n"
184             + "b2lkIFdpLUZpIFRlc3QxGDAWBgNVBAsMD2FuZHJvaWR3aWZpLm9lbTE8MDoGA1UE\n"
185             + "AwwzQW5vdGhlciBBbmRyb2lkIFJvb3QgQ0EgZm9yIHRlc3RpbmcgYW5kIGRldmVs\n"
186             + "b3BtZW50MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvv7PYhFHK+nC\n"
187             + "KoDiQI7dhDFTNU4RxTTsxMRSt1n/FJGZX/r8nnr76gB+oofFVjKQusYhuquKGPGq\n"
188             + "ZfrfmtsNhcVBMnNRjZkBWpNb3XO+7F+Qd/gT7yoiZ0L3Ef4QMCGqNrf10EWmXvVQ\n"
189             + "tpaM7RrkmlW6Zu2VbfP/iQQ7EVFrFWmnZfkCxpkLT+LK+pxwNxtJz5l7VRYkXelw\n"
190             + "9vFdq81C+obBpLWg62mNVNa25g6y46YrSOPyxhiemiRih+avIZ9Z6/7qRoVu7t8U\n"
191             + "NpxzMdsDL5bJREadsjpQWZr7A+umm0nlod1DB204K18Y5Z4GuOEGifdHIUmb+3c4\n"
192             + "Kz14FzBahyc3xsZL73AsGEVWLHIQQ/kjepomVl8HuSHdgw6SZR30JhWgU/bcVl01\n"
193             + "8qc6qH7x3e64Ip9xHdng42oPJHEKYipRed3AXzlCQ7Lc9MeAeR+nB9JuSNc6HW0L\n"
194             + "eh9Po0cDJa194UfNeqJ7SG2uNpeg/OUbM+M3iO3dmCRcV3GzirbT8eHZk3Cor3gb\n"
195             + "h9AzmJnHyRaRc9Xtj7AE8swJRvAoWVlCzcBcvaLAW0hn2DWXbWXHDf63Q8n5F4J5\n"
196             + "pf//2eXWaOXFLvkm9wYUj6kXOehcibB2O1F1YvqWE3XZ5GTDq/+E5wK55aifq+bz\n"
197             + "l1Mb1ILIB3cEEL9w+0ClHCno+2XGMOkCAwEAAaNCMEAwHQYDVR0OBBYEFH0KeaUK\n"
198             + "koS2PMYfpcanoTkRBTzmMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGG\n"
199             + "MA0GCSqGSIb3DQEBDAUAA4ICAQCnnL83fEA3g8fiJHpeSNSVZ4R3VunQU2BDkwUj\n"
200             + "NgFWPMsZNQcKoChUA5mb8wOM/fk9tdjMsQR5fRO30B94Eoo9NM39HztBcvvLV9i7\n"
201             + "qNQCTjFE7zf4weX6K3tZICR8nZ1Ogccp3itEDkNpOylFLdQxkc29RrKcuculb3PM\n"
202             + "C7IMREKROKFzrAwWkFAaxJGfByTRfjOqWJFgdRq/GHU2yCKkCLN4zRLjr5ZaAk2J\n"
203             + "+8b+Y1/pIW4j2FAB7ebmq0ZbMbdc+EFdVf36WrsWf54L3DsZOuoaC+2wTsyWQ0b/\n"
204             + "8tqJ/XS39I4uo8KpI5//aQpM1usxP0/pWUm9sTXE618Yf2Ynh64eDQHPIAmt+Xoh\n"
205             + "BfIx+nXVkCl4DGGdwvOURUULdHN9wf6YPOXxaMEYxQRGMwmBAlmiDaH41xeaht/A\n"
206             + "+iv3y918rJFDAXWKvGia8oDi1xIL+IDZ1AGVByNp+C/AE5BTV2m9UHZyXsXrMiQA\n"
207             + "ezUrVpiWB6h4C4rUuaucQv1gO6gEPZGEDdvIG8TGJg8wvLL0oZiyaL3gQxlGs0CZ\n"
208             + "tbDGqugtlh4RLeJ1N/TTFkLzf4CAgDTxfqhMKXkFvpMvO6ZHOT7xC0sdaD2FbZRj\n"
209             + "h5ziC9nvWEdTA8RLr0i/r5nFb6GsxmEk6NYFmpnyo5pvlxf5xqOhsJZlcKnUJ8SQ\n"
210             + "NIGLmw==\n"
211             + "-----END CERTIFICATE-----";
212 
213     private static final String TEST_SELF_SIGNED_CERTIFICATE = "-----BEGIN CERTIFICATE-----\n"
214             + "MIIFxzCCA6+gAwIBAgIUB8Kqwhhhs1liW23ve7pZsFlv0zAwDQYJKoZIhvcNAQEM\n"
215             + "BQAwezELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExGzAZBgNVBAoM\n"
216             + "EkFuZHJvaWQgV2ktRmkgVGVzdDEYMBYGA1UECwwPYW5kcm9pZHdpZmkuZGV2MSAw\n"
217             + "HgYDVQQDDBdTZWxmLXNpZ25lZCBjZXJ0aWZpY2F0ZTAeFw0yMzA0MTMwMjE0MTda\n"
218             + "Fw00MzA0MDgwMjE0MTdaMHsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9y\n"
219             + "bmlhMRswGQYDVQQKDBJBbmRyb2lkIFdpLUZpIFRlc3QxGDAWBgNVBAsMD2FuZHJv\n"
220             + "aWR3aWZpLmRldjEgMB4GA1UEAwwXU2VsZi1zaWduZWQgY2VydGlmaWNhdGUwggIi\n"
221             + "MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDD0oI2c+1D4D2wc4PnhkXbtA7g\n"
222             + "64Mp/JSbnVbl7PseJKnFD/pdos5joFXFbySFqu60S905T1a3AWNwbucKc7C7IwQw\n"
223             + "gtO7uMEPr35j7MhItyAbmj89dY729yXJ8gBnNnqc8PyYEIfZmnBvSry0Tsm60298\n"
224             + "GGZ9yCQfOOb4TJFX/CIKjniI170eLCiGybOrBvG11Rx6BwwHnk1cjkDspejrkhb0\n"
225             + "13RfkQ1S0cEnylrgnn/nRDAAnOscpHRerJ6Ud2vM64iIJy206ZyU/CrhcGeBWwi9\n"
226             + "C1F4ojzvgoFW7bJahXiyEaC5R3G5WdvX5qOr/eu/yMaCAner0LHUibHc5XA02F/c\n"
227             + "LO0LpN59tTT4dx9sLJVjZQGSUxyXnKHiR5TKkoAMWAZSO5hbE4drgivKLnYmYnhC\n"
228             + "Z1rGM5R0D0gB2llAvecItmynDJNApY6L1F8wnNA9NfGUYFpeqJ8uEOn7RxAvyYmB\n"
229             + "trmUFOqL7W84d1/XzORPGQ7n1wyPfBG3xyGIm2MMvanVsLs0/9NXAYAz2ZAHJPnS\n"
230             + "DsiV+7OHtMCdgTI5BJFmiJpXKgVE+IaewQdSjXDU7bgMlll3lTVoVAiKJmxpOmZ6\n"
231             + "FFz7mkd0pYhsO5jQpNGMfl+IaoIiTx4Zg9ZjwjTcPn9eGunBLJJ8SofkhM4boLrC\n"
232             + "KSen8NYuHVDPwAOwpQIDAQABo0MwQTAdBgNVHQ4EFgQU2IB1Q35ysx0HpRttAqMU\n"
233             + "FO9OhIAwCwYDVR0PBAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3\n"
234             + "DQEBDAUAA4ICAQBqf4zbooJ4hHeZs7Nd31G7i2WEr6/8OWTuEuDAmJkGW8WBeyUG\n"
235             + "JMrxF3U+kGxVGops4mSxMwVpcsqQa+IwkrP807dSqkuntLVGFqVo7rcQ+l8OcNUv\n"
236             + "oNQIFGPLlWPyMnjXvmWbfvgbgFoY9yUFoxFlHqsVf+1mEvTmW9ya4BGT2hlfvtb6\n"
237             + "Jfvrrocg9zGSnBs9oyI+GzP4Xdqd0riXfk6OuFH3R05/cQj7SlPm8LU1J7ZML/4H\n"
238             + "1AuMg+Ql8vxql4IzIk93CDR8Hq1jb3MhF/ae9UfttuNnHT4vu5X/6qLqWNKMs3zP\n"
239             + "DQQaYkqxWTUWiNlWV7i7pXn8e2J8ZkRHVELvrpdXLKIfL6RxjzKWY+TKiHY+F48I\n"
240             + "JwCAbL1FX+NzB2dS0RxXk/RTAxagenfmDcY1notHNsnDZB54cP9nv+N3wqkDoaKg\n"
241             + "nqOZTlIRWJ4agygqGaxieUuZRgy/AE/dSGpetlXAScKUvhCcO22qXL2jSjBAg5+k\n"
242             + "AynUuiZxdogXbvXrAwSWAVwlz8qEOK3NPFYnEKcjgNbTxiUHp3P/ULBgHQo55o9K\n"
243             + "DdUEbIurd02xG6usEDWxR5ds/RPy6VZ5c6bFUiTEsfMMmQotPL/btuPVXsSdJUR4\n"
244             + "xcxpcV7zx9IjFs/IylyQ1YEYDKWV+nH7iiOigO5WiZ5ck2Wa/Tk3uXg1Ew==\n"
245             + "-----END CERTIFICATE-----\n";
246 
247     private static final String TEST_FAKE_CA_CERTIFICATE = "-----BEGIN CERTIFICATE-----\n"
248             + "MIIGADCCA+igAwIBAgIUIxVGWM5Wrs86DpDA2+fo53UryqMwDQYJKoZIhvcNAQEM\n"
249             + "BQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRswGQYDVQQK\n"
250             + "DBJBbmRyb2lkIFdpLUZpIFRlc3QxGDAWBgNVBAsMD2FuZHJvaWR3aWZpLm9lbTE8\n"
251             + "MDoGA1UEAwwzQW5kcm9pZCBQYXJ0bmVyIFJvb3QgQ0EgZm9yIHRlc3RpbmcgYW5k\n"
252             + "IGRldmVsb3BtZW50MB4XDTIzMDQxMzE1MzkyM1oXDTQzMDQwODE1MzkyM1owgZcx\n"
253             + "CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRswGQYDVQQKDBJBbmRy\n"
254             + "b2lkIFdpLUZpIFRlc3QxGDAWBgNVBAsMD2FuZHJvaWR3aWZpLm9lbTE8MDoGA1UE\n"
255             + "AwwzQW5kcm9pZCBQYXJ0bmVyIFJvb3QgQ0EgZm9yIHRlc3RpbmcgYW5kIGRldmVs\n"
256             + "b3BtZW50MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAhTF8MJsucR5P\n"
257             + "6oN/Nho92EYz9b3m7n52m9KgI/G6/9bK9PSDZ6Z6U3qNxpG7nFML+5qyk+qeBHP8\n"
258             + "39lGNNoH1c2dQDXw3oLjOmd1UoN+zSZBznLwkDD8YQYafz1GWRcI34FYDgiPuSx7\n"
259             + "o4+O4hxcimrelhoNRQcRsrZFoUyJZjtPy2Z5DTZTB7udg1QwZ+7+pHCme3DB2Im/\n"
260             + "Eszsmm2TAG6yM3G/lxphLZMhUFy6kjeeIiuar56ED6dg7qEqdeIznt2gGKolXRWs\n"
261             + "vPW4a5NX1RUjsQxOcKEQnrXZXJ9mATptY1hOxuP6kg8Jzh0tN/NzyyERGFvnvhGz\n"
262             + "sN7CkTUhPOKUW3dVrKl9ZJ9PbYZ6xbpbOWOR/5znYQ/f3+bxxibbFI3WN/89VO50\n"
263             + "WEzwfmiGiWC6Bz0iBoAmGjCxySbJg8iDCjrbRexkFsOJ84jlY0fDrfaqY1+WuyYu\n"
264             + "vdk+w4lzk0wYRbp+oRuIXplMyZDsS15CPq+svoYeNCCOXlkRiMLuq/SpkdM8lRKp\n"
265             + "Mrsc1AckI+BGVqh8S9lyJoP67uDmba1FUw7X3IMCkZQwvFduLkJLNYwO6QDV2M6R\n"
266             + "nUCVCx+vxJdlIOLNQIAeKW9jzfASom4ehZY2HHErbUYGKzFQJJ/2+uQLLYn7PsaE\n"
267             + "gYTYA1naakQegCgbD2UsbKqrEfOiHEECAwEAAaNCMEAwHQYDVR0OBBYEFBiYeS/E\n"
268             + "IQ5+IoQ3bsXoibK3QuMzMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGG\n"
269             + "MA0GCSqGSIb3DQEBDAUAA4ICAQACOOZdfcQ53BF43glA/0VuFeXQ+VS+keR9aFBX\n"
270             + "caKrIbFXSns9EsnvKj1L/IoHem5k4LkMFoNgE1Skit2iktPYs6unV83p99PG6EQo\n"
271             + "RG1CeZ50cHzZK6N56MbwZUGRy/p6Zr9ak9d6XE8GpvSwMW8XebrLPtgSBvpI+WIZ\n"
272             + "epMVg7v8AIIRQuoR2VtZ7RZF/X1kwfU5t2aASVBnxTjlSy6KtBLuL+Vu4Aefa+Z0\n"
273             + "d9Ma2jZV+hwWp0X6piSrVKkMZIR5tlvwJootNBlO0J1Jn4J0ecGNEGXmFwz4adnK\n"
274             + "eYfpuNBJI4CKq7mv2Aszsvg0rQxfKlN8LV7gSNu3H6BjjkNUtHI6uwsajJfEmGKD\n"
275             + "YRpAFgZq7FzRwoI8uWr0Bucz6+qxpISi48t0pmceSVpn6UV1UdSebLo8CX5P283F\n"
276             + "yUqlw2hMpo22Gm3uW8GfPyHfMfsqfMU+7BCP38DDnhcGUO3CTINjREXUGtn6CuWS\n"
277             + "ImhmATld6KJNtRCql3zQnaEO84IvKdFVOkm5q9qQjNWDr1oYsLhxoZJZjKK2rP5F\n"
278             + "GRbMvqDhmzrV0yG+sIyW+aEjBl44bVjWQnFhGjtNr1BOOftSyjnseYiioLbiiaYG\n"
279             + "9Mqu78VmTWJzfxyOP2QPK5K00jnVBZ+jQH0NyIE9yf2Cg/llfYRoHsz80cfY/DNt\n"
280             + "jUR49A==\n"
281             + "-----END CERTIFICATE-----";
282 
283     private static final String TEST_SERVER_CERTIFICATE_WITHOUT_COMMON_NAME =
284             "-----BEGIN CERTIFICATE-----\n"
285             + "MIIF+zCCA+OgAwIBAgIUCvmbTyLRy+5/Tt8iSpBB+xmZTfUwDQYJKoZIhvcNAQEM\n"
286             + "BQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRswGQYDVQQK\n"
287             + "DBJBbmRyb2lkIFdpLUZpIFRlc3QxGDAWBgNVBAsMD2FuZHJvaWR3aWZpLm9lbTE8\n"
288             + "MDoGA1UEAwwzQW5kcm9pZCBQYXJ0bmVyIFJvb3QgQ0EgZm9yIHRlc3RpbmcgYW5k\n"
289             + "IGRldmVsb3BtZW50MB4XDTI0MDMxMzE3NTIwMFoXDTI2MDMxMzE3NTIwMFowQTEL\n"
290             + "MAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExHTAbBgNVBAoMFEFuZHJv\n"
291             + "aWQgV2ktRmkgVGVzdGVyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA\n"
292             + "uVNdRG1M/DVcfqi1Cl1FRXxZ2eeKe/IM6OA4KhkR0aymZtjmsoTO52JFVoTykCrj\n"
293             + "bnDp6wOTDaglwbClip/Be5Oj//6LS+A5J3PqUfQsOI+s8ZeAu6s4Kur4g0oPhfNz\n"
294             + "msRyQvhIUkwYCXEum+uQ3INLpy38JggEbTRR4nnn2UUh4+Shv9xYA/SiYrV/sd/f\n"
295             + "Vj++lAmOUQu/CLCWtpfBFTeiyg/DhypbHQVPnr+k1QBy7DKZlBXQb7POjE4M6Ed/\n"
296             + "/st11tB8qHZnM8Xe4CdM3xSJj9qs2BQyT228z7SCmA3r3P1CMvSRYqWu1mn4iMO1\n"
297             + "t0sShF/OfUkihE1ADA0q6GRHDLQ3T/TSnuYWyH4/iMMygHl+yfDeECaLOn/KEQM9\n"
298             + "hOBlXo5iKB/GMkFKeoGQQePwWllHK7HjNEAOOPyXS4nzRA1VUq0gVvhFpQX7ZK9X\n"
299             + "OWdNdcnof4wzOEJse96I7v3A1C0FYg57f1HKOnx195hb1wQfi0MOyE/mgqvtVWbP\n"
300             + "90Vd2nFMlNSVc38DUT7jyYTygUAl5eQDRZo/npNs32nf8YW4cWmN1r+LCHUkK22v\n"
301             + "y8bmSVTts7WHzx9K1kg5+XvaTxpgmmFneuh0XIFvTcGFwMPrHzwaa5pOCYjUvlSy\n"
302             + "GXOmRuSqFipufxxlRKM0cJhMUqI/vmYJ5byx5Wb1N+MCAwEAAaOBkzCBkDAdBgNV\n"
303             + "HQ4EFgQUz4BlPUEPOANhQ74NbClj0CrdiHswHwYDVR0jBBgwFoAUyWVsWmPxPCB6\n"
304             + "D7hRF7K2vyVzKOMwCQYDVR0TBAIwADALBgNVHQ8EBAMCBaAwEwYDVR0lBAwwCgYI\n"
305             + "KwYBBQUHAwEwIQYDVR0RBBowGIIWc2VydmVyLmFuZHJvaWR3aWZpLm9lbTANBgkq\n"
306             + "hkiG9w0BAQwFAAOCAgEAkf5CHaqzDsQKn8udsA9/fIKSOEqr0LUfwP20JzFe0HBA\n"
307             + "F3cWoMrEVoAJFfi5NFQJOjlEib7kvu2MI92lL6ch3D3iW5mnY5Ncnm2eyqi1kvii\n"
308             + "uueKnH4a9jsolWgcsGiw5vUhsodgxWzFr/yDURYZEWkzP4uiW3+0K6eoc11DPiDr\n"
309             + "16LS4xAINHVeEDhhkuZG2Bqo1ctbcQWR7Leb5JGpfkC7xNGyVNUwJYjI5vow5GzR\n"
310             + "Af2SvJuG3mMxBfM+8TMx4wf4Sgq80FmaJLNAOlfKlYIN0u/NV/pq6nWb0B4u3K0u\n"
311             + "ytH3BRJsuKg35fZEy4qRpBZL1Us9FzwPkRaUK+Sgtz9BLRPL5my3xUwnZaqw+ZRp\n"
312             + "Gw+vwErnSc3md9DhYMeGc0JdA141/pxc/P20hoLG7cDK/tO4PwBzNrF57XLEFC7v\n"
313             + "bww0rQoADGCIk48n2gZX/wh1XeHWJhk7C+lGGbA/qrs5zZbzDaMi/N3C74eiQJOH\n"
314             + "KdQk10pt2nU8xwC/RsfL7W+2K4c4/mZvaroxQvIxs8tRB3glbpwQe4HntpE0LdvH\n"
315             + "7hotzbIt0YtGtzIdOwpR277a73qT09pmYL97+rwPGWMviCkb9QNvFHBKc0MsgxXz\n"
316             + "15THXfttbGruZySMyj9kMox0NbhsVKiSEEiqMMHvJMbn4FDI1O9U5IDZdUplI0A=\n"
317             + "-----END CERTIFICATE-----";
318 
319     @Mock WifiContext mContext;
320     @Mock WifiConfigManager mWifiConfigManager;
321     @Mock WifiNative mWifiNative;
322     @Mock FrameworkFacade mFrameworkFacade;
323     @Mock WifiNotificationManager mWifiNotificationManager;
324     @Mock WifiDialogManager mWifiDialogManager;
325     @Mock InsecureEapNetworkHandler.InsecureEapNetworkHandlerCallbacks mCallbacks;
326     @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Notification.Builder mNotificationBuilder;
327     @Mock private WifiDialogManager.DialogHandle mTofuAlertDialog;
328     @Mock private java.text.DateFormat mDateFormat;
329     @Mock private KeyStore mKeyStore;
330 
331     @Captor ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor;
332     @Captor ArgumentCaptor<WifiConfigManager.OnNetworkUpdateListener>
333         mOnNetworkUpdateListenerCaptor;
334 
335     TestLooper mLooper;
336     Handler mHandler;
337     MockResources mResources;
338     InsecureEapNetworkHandler mInsecureEapNetworkHandler;
339 
340     private MockitoSession mSession;
341 
342     /**
343      * Sets up for unit test
344      */
345     @Before
setUp()346     public void setUp() throws Exception {
347         MockitoAnnotations.initMocks(this);
348         mResources = new MockResources();
349         when(mContext.getString(anyInt())).thenReturn("TestString");
350         when(mContext.getString(anyInt(), any())).thenReturn("TestStringWithArgument");
351         when(mContext.getText(anyInt())).thenReturn("TestStr");
352         when(mContext.getString(eq(R.string.wifi_ca_cert_dialog_message_issuer_name_text),
353                 anyString()))
354                 .thenAnswer((Answer<String>) invocation ->
355                         "Issuer Name:\n" + invocation.getArguments()[1] + "\n\n");
356         when(mContext.getString(eq(R.string.wifi_ca_cert_dialog_message_server_name_text),
357                 anyString()))
358                 .thenAnswer((Answer<String>) invocation ->
359                         "Server Name:\n" + invocation.getArguments()[1] + "\n\n");
360         when(mContext.getString(eq(R.string.wifi_ca_cert_dialog_message_organization_text),
361                 anyString()))
362                 .thenAnswer((Answer<String>) invocation ->
363                         "Organization:\n" + invocation.getArguments()[1] + "\n\n");
364         when(mContext.getString(eq(R.string.wifi_ca_cert_dialog_message_contact_text),
365                 anyString()))
366                 .thenAnswer((Answer<String>) invocation ->
367                         "Contact:\n" + invocation.getArguments()[1] + "\n\n");
368         when(mContext.getString(eq(R.string.wifi_ca_cert_dialog_message_signature_name_text),
369                 anyString()))
370                 .thenAnswer((Answer<String>) invocation ->
371                         "SHA-256 Fingerprint:\n" + invocation.getArguments()[1] + "\n\n");
372         when(mContext.getWifiOverlayApkPkgName()).thenReturn("test.com.android.wifi.resources");
373         when(mContext.getResources()).thenReturn(mResources);
374         when(mWifiDialogManager.createLegacySimpleDialogWithUrl(
375                 any(), any(), any(), anyInt(), anyInt(), any(), any(), any(), any(), any()))
376                 .thenReturn(mTofuAlertDialog);
377         when(mWifiDialogManager.createLegacySimpleDialog(
378                 any(), any(), any(), any(), any(), any(), any()))
379                 .thenReturn(mTofuAlertDialog);
380 
381         when(mFrameworkFacade.makeNotificationBuilder(any(), any()))
382                 .thenReturn(mNotificationBuilder);
383 
384         // static mocking
385         mSession = ExtendedMockito.mockitoSession()
386                 .mockStatic(DateFormat.class, withSettings().lenient())
387                 .mockStatic(KeyStore.class, withSettings().lenient())
388                 .startMocking();
389         when(DateFormat.getMediumDateFormat(any())).thenReturn(mDateFormat);
390         when(mDateFormat.format(any())).thenReturn("April 12, 2023");
391         when(KeyStore.getInstance(anyString())).thenReturn(mKeyStore);
392 
393         mLooper = new TestLooper();
394         mHandler = new Handler(mLooper.getLooper());
395     }
396 
397     @After
cleanUp()398     public void cleanUp() throws Exception {
399         validateMockitoUsage();
400         mSession.finishMocking();
401     }
402 
403     /**
404      * Verify Trust On First Use flow.
405      * - This network is selected by a user.
406      * - Accept the connection.
407      */
408     @Test
verifyTrustOnFirstUseAcceptWhenConnectByUser()409     public void verifyTrustOnFirstUseAcceptWhenConnectByUser() throws Exception {
410         assumeTrue(SdkLevel.isAtLeastT());
411         boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true;
412         boolean needUserApproval = true;
413 
414         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
415         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
416         verifyTrustOnFirstUseFlowWithDefaultCerts(config, ACTION_ACCEPT,
417                 isTrustOnFirstUseSupported, isUserSelected, needUserApproval);
418     }
419 
420     /**
421      * Verify Trust On First Use flow.
422      * - This network is selected by a user.
423      * - Reject the connection.
424      */
425     @Test
verifyTrustOnFirstUseRejectWhenConnectByUser()426     public void verifyTrustOnFirstUseRejectWhenConnectByUser() throws Exception {
427         assumeTrue(SdkLevel.isAtLeastT());
428         boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true;
429         boolean needUserApproval = true;
430 
431         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
432         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
433         verifyTrustOnFirstUseFlowWithDefaultCerts(config, ACTION_REJECT,
434                 isTrustOnFirstUseSupported, isUserSelected, needUserApproval);
435     }
436 
437     /**
438      * Verify Trust On First Use flow.
439      * - This network is auto-connected.
440      * - Accept the connection.
441      */
442     @Test
verifyTrustOnFirstUseAcceptWhenConnectByAutoConnect()443     public void verifyTrustOnFirstUseAcceptWhenConnectByAutoConnect() throws Exception {
444         assumeTrue(SdkLevel.isAtLeastT());
445         boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = false;
446         boolean needUserApproval = true;
447 
448         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
449         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
450         verifyTrustOnFirstUseFlowWithDefaultCerts(config, ACTION_ACCEPT,
451                 isTrustOnFirstUseSupported, isUserSelected, needUserApproval);
452     }
453 
454     /**
455      * Verify Trust On First Use flow.
456      * - This network is auto-connected.
457      * - Reject the connection.
458      */
459     @Test
verifyTrustOnFirstUseRejectWhenConnectByAutoConnect()460     public void verifyTrustOnFirstUseRejectWhenConnectByAutoConnect() throws Exception {
461         assumeTrue(SdkLevel.isAtLeastT());
462         boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = false;
463         boolean needUserApproval = true;
464 
465         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
466         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
467         verifyTrustOnFirstUseFlowWithDefaultCerts(config, ACTION_REJECT,
468                 isTrustOnFirstUseSupported, isUserSelected, needUserApproval);
469     }
470 
471     /**
472      * Verify Trust On First Use flow.
473      * - This network is auto-connected.
474      * - Tap the notification to show the dialog.
475      */
476     @Test
verifyTrustOnFirstUseTapWhenConnectByAutoConnect()477     public void verifyTrustOnFirstUseTapWhenConnectByAutoConnect() throws Exception {
478         assumeTrue(SdkLevel.isAtLeastT());
479         boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = false;
480         boolean needUserApproval = true;
481 
482         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
483         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
484         verifyTrustOnFirstUseFlowWithDefaultCerts(config, ACTION_TAP,
485                 isTrustOnFirstUseSupported, isUserSelected, needUserApproval);
486     }
487 
488     /**
489      * Verify that it reports errors if there is no pending Root CA certifiate
490      * with Trust On First Use support.
491      */
492     @Test
verifyTrustOnFirstUseWhenTrustOnFirstUseNoPendingCert()493     public void verifyTrustOnFirstUseWhenTrustOnFirstUseNoPendingCert() throws Exception {
494         assumeTrue(SdkLevel.isAtLeastT());
495         boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true;
496 
497         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
498         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
499         mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected);
500         verify(mCallbacks).onError(eq(config.SSID));
501         verify(mWifiConfigManager, atLeastOnce()).updateNetworkSelectionStatus(eq(config.networkId),
502                 eq(WifiConfiguration.NetworkSelectionStatus
503                         .DISABLED_BY_WIFI_MANAGER));
504     }
505 
506     /**
507      * Verify that Trust On First Use is not supported on T.
508      * It follows the same behavior on preT release.
509      */
510     @Test
verifyTrustOnFirstUseWhenTrustOnFirstUseNotSupported()511     public void verifyTrustOnFirstUseWhenTrustOnFirstUseNotSupported() throws Exception {
512         assumeTrue(SdkLevel.isAtLeastT());
513         boolean isAtLeastT = true, isTrustOnFirstUseSupported = false, isUserSelected = true;
514 
515         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
516         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
517         mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected);
518         verify(mCallbacks, never()).onError(any());
519     }
520 
521     /**
522      * Verify legacy insecure EAP network flow.
523      * - This network is selected by a user.
524      * - Accept the connection.
525      */
526     @Test
verifyLegacyEapNetworkAcceptWhenConnectByUser()527     public void verifyLegacyEapNetworkAcceptWhenConnectByUser() throws Exception {
528         assumeFalse(SdkLevel.isAtLeastT());
529         boolean isAtLeastT = false, isTrustOnFirstUseSupported = false, isUserSelected = true;
530         boolean needUserApproval = true;
531 
532         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
533         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
534         verifyTrustOnFirstUseFlowWithDefaultCerts(config, ACTION_ACCEPT,
535                 isTrustOnFirstUseSupported, isUserSelected, needUserApproval);
536     }
537 
538     /**
539      * Verify legacy insecure EAP network flow.
540      * - Trust On First Use is not supported.
541      * - This network is selected by a user.
542      * - Reject the connection.
543      */
544     @Test
verifyLegacyEapNetworkRejectWhenConnectByUser()545     public void verifyLegacyEapNetworkRejectWhenConnectByUser() throws Exception {
546         assumeFalse(SdkLevel.isAtLeastT());
547         boolean isAtLeastT = false, isTrustOnFirstUseSupported = false, isUserSelected = true;
548         boolean needUserApproval = true;
549 
550         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
551         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
552         verifyTrustOnFirstUseFlowWithDefaultCerts(config, ACTION_REJECT,
553                 isTrustOnFirstUseSupported, isUserSelected, needUserApproval);
554     }
555 
556     /**
557      * Verify legacy insecure EAP network flow.
558      * - This network is auto-connected.
559      * - Accept the connection.
560      */
561     @Test
verifyLegacyEapNetworkAcceptWhenAutoConnect()562     public void verifyLegacyEapNetworkAcceptWhenAutoConnect() throws Exception {
563         assumeFalse(SdkLevel.isAtLeastT());
564         boolean isAtLeastT = false, isTrustOnFirstUseSupported = false, isUserSelected = false;
565         boolean needUserApproval = true;
566 
567         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
568         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
569         verifyTrustOnFirstUseFlowWithDefaultCerts(config, ACTION_ACCEPT,
570                 isTrustOnFirstUseSupported, isUserSelected, needUserApproval);
571     }
572 
573     /**
574      * Verify legacy insecure EAP network flow.
575      * - Trust On First Use is not supported.
576      * - This network is auto-connected.
577      * - Reject the connection.
578      */
579     @Test
verifyLegacyEapNetworkRejectWhenAutoConnect()580     public void verifyLegacyEapNetworkRejectWhenAutoConnect() throws Exception {
581         assumeFalse(SdkLevel.isAtLeastT());
582         boolean isAtLeastT = false, isTrustOnFirstUseSupported = false, isUserSelected = false;
583         boolean needUserApproval = true;
584 
585         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
586         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
587         verifyTrustOnFirstUseFlowWithDefaultCerts(config, ACTION_REJECT,
588                 isTrustOnFirstUseSupported, isUserSelected, needUserApproval);
589     }
590 
591     /**
592      * Verify legacy insecure EAP network flow.
593      * - This network is selected by a user.
594      * - Tap the notification
595      */
596     @Test
verifyLegacyEapNetworkOpenLinkWhenConnectByUser()597     public void verifyLegacyEapNetworkOpenLinkWhenConnectByUser() throws Exception {
598         assumeFalse(SdkLevel.isAtLeastT());
599         boolean isAtLeastT = false, isTrustOnFirstUseSupported = false, isUserSelected = true;
600         boolean needUserApproval = true;
601 
602         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
603         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
604         verifyTrustOnFirstUseFlowWithDefaultCerts(config, ACTION_TAP,
605                 isTrustOnFirstUseSupported, isUserSelected, needUserApproval);
606     }
607 
608     /**
609      * Verify Trust On First Use flow with server certificate pinning
610      * - Single depth server certificate by signed by some unknown issuer, CA flag not set
611      * - This network is selected by a user.
612      * - Accept the connection.
613      */
614     @Test
verifyTrustOnFirstUseFlowWithServerCertPinning1()615     public void verifyTrustOnFirstUseFlowWithServerCertPinning1() throws Exception {
616         assumeTrue(SdkLevel.isAtLeastT());
617         runServerCertPinningTest(TEST_GEN_SERVER_CERT);
618     }
619 
620     /**
621      * Verify Trust On First Use flow with server certificate pinning
622      * - Single depth server certificate by signed by some unknown issuer, CA flag set
623      * - This network is selected by a user.
624      * - Accept the connection.
625      */
626     @Test
verifyTrustOnFirstUseFlowWithServerCertPinning2()627     public void verifyTrustOnFirstUseFlowWithServerCertPinning2() throws Exception {
628         assumeTrue(SdkLevel.isAtLeastT());
629         runServerCertPinningTest(TEST_GEN_CA_CERT);
630     }
631 
runServerCertPinningTest(int type)632     private void runServerCertPinningTest(int type)
633             throws Exception {
634         WifiConfiguration config = prepareWifiConfiguration(true);
635         setupTest(config, true, true);
636 
637         CertificateEventInfo mockServerCert = generateMockCertEventInfo(type);
638         mInsecureEapNetworkHandler.addPendingCertificate(config.networkId, 0, mockServerCert);
639         verifyTrustOnFirstUseFlow(config, ACTION_ACCEPT, true,
640                 true, false, null, mockServerCert.getCert(),
641                 null);
642     }
643 
644     /**
645      * Verify Trust On First Use flow with the CA certificate path.
646      * - Single depth server certificate by signed by a trusted Root CA from the trust store.
647      * - This network is selected by a user.
648      * - Accept the connection.
649      */
650     @Test
verifyTrustOnFirstUseFlowWithRootCaFromFromStore()651     public void verifyTrustOnFirstUseFlowWithRootCaFromFromStore() throws Exception {
652         assumeTrue(SdkLevel.isAtLeastU());
653         runServerCertFromTrustStoreTest();
654     }
655 
runServerCertFromTrustStoreTest()656     private void runServerCertFromTrustStoreTest() throws Exception {
657         WifiConfiguration config = configureTofuWithAidlVersion2Value(true);
658 
659         // CA_CERT is also in the trust store
660         CertificateEventInfo mockCaCert = generateMockCertEventInfo(TEST_GEN_CA_CERT);
661         CertificateEventInfo mockServerCert = generateMockCertEventInfo(TEST_GEN_SERVER_CERT);
662         mInsecureEapNetworkHandler.addPendingCertificate(config.networkId, 1, mockCaCert);
663         mInsecureEapNetworkHandler.addPendingCertificate(config.networkId, 0, mockServerCert);
664 
665         List<String> aliases = new ArrayList<>();
666         aliases.add("TEST_GEN_CA_CERT");
667         aliases.add("TEST_GEN_CA2_CERT");
668         when(mKeyStore.aliases()).thenReturn(Collections.enumeration(aliases));
669         when(mKeyStore.getCertificate("TEST_GEN_CA_CERT"))
670                 .thenReturn(getCertificate(TEST_GEN_CA_CERT));
671         when(mKeyStore.getCertificate("TEST_GEN_CA2_CERT"))
672                 .thenReturn(getCertificate(TEST_GEN_CA2_CERT));
673         verifyTrustOnFirstUseFlow(config, ACTION_ACCEPT, true,
674                 true, false, mockCaCert.getCert(), mockServerCert.getCert(),
675                 WifiConfigurationUtil.getSystemTrustStorePath());
676     }
677 
generateMockCertEventInfo(int type)678     private CertificateEventInfo generateMockCertEventInfo(int type) throws Exception {
679         CertificateEventInfo certificateEventInfo = mock(CertificateEventInfo.class);
680         X509Certificate cert = getCertificate(type);
681 
682         when(certificateEventInfo.getCert()).thenReturn(cert);
683         when(certificateEventInfo.getCertHash()).thenReturn("12345678");
684         return certificateEventInfo;
685     }
686 
getCertificate(int type)687     private X509Certificate getCertificate(int type) throws Exception {
688         String certString;
689 
690         if (type == TEST_GEN_CA_CERT) {
691             certString = TEST_CA_CERTIFICATE;
692         } else if (type == TEST_GEN_CA2_CERT) {
693             certString = TEST_CA2_CERTIFICATE;
694         } else if (type == TEST_GEN_SERVER_CERT) {
695             certString = TEST_SERVER_CERTIFICATE;
696         } else if (type == TEST_GEN_SELF_SIGNED_CERT) {
697             certString = TEST_SELF_SIGNED_CERTIFICATE;
698         } else if (type == TEST_GEN_FAKE_CA_CERT) {
699             certString = TEST_FAKE_CA_CERTIFICATE;
700         } else if (type == TEST_GEN_SERVER_CERTIFICATE_WITHOUT_COMMON_NAME) {
701             certString = TEST_SERVER_CERTIFICATE_WITHOUT_COMMON_NAME;
702         } else {
703             throw (new Exception());
704         }
705 
706         CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
707         InputStream in = new ByteArrayInputStream(certString.getBytes());
708         return (X509Certificate) certFactory.generateCertificate(in);
709     }
710 
prepareWifiConfiguration(boolean isAtLeastT)711     private WifiConfiguration prepareWifiConfiguration(boolean isAtLeastT) {
712         WifiConfiguration config = spy(WifiConfigurationTestUtil.createEapNetwork(
713                 WifiEnterpriseConfig.Eap.TTLS, WifiEnterpriseConfig.Phase2.MSCHAPV2));
714         config.networkId = FRAMEWORK_NETWORK_ID;
715         config.SSID = TEST_SSID;
716         if (isAtLeastT) {
717             config.enterpriseConfig.enableTrustOnFirstUse(true);
718         }
719         config.enterpriseConfig.setCaPath("");
720         config.enterpriseConfig.setDomainSuffixMatch("");
721         config.enterpriseConfig.setIdentity(TEST_IDENTITY);
722         config.enterpriseConfig.setPassword(TEST_PASSWORD);
723         return config;
724     }
725 
setupTest(WifiConfiguration config, boolean isAtLeastT, boolean isTrustOnFirstUseSupported)726     private void setupTest(WifiConfiguration config,
727             boolean isAtLeastT, boolean isTrustOnFirstUseSupported) {
728         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported, false);
729     }
730 
setupTest(WifiConfiguration config, boolean isAtLeastT, boolean isTrustOnFirstUseSupported, boolean isInsecureEnterpriseConfigurationAllowed)731     private void setupTest(WifiConfiguration config,
732             boolean isAtLeastT, boolean isTrustOnFirstUseSupported,
733             boolean isInsecureEnterpriseConfigurationAllowed) {
734         mInsecureEapNetworkHandler = new InsecureEapNetworkHandler(
735                 mContext,
736                 mWifiConfigManager,
737                 mWifiNative,
738                 mFrameworkFacade,
739                 mWifiNotificationManager,
740                 mWifiDialogManager,
741                 isTrustOnFirstUseSupported,
742                 isInsecureEnterpriseConfigurationAllowed,
743                 mCallbacks,
744                 WIFI_IFACE_NAME,
745                 mHandler);
746 
747         if (isTrustOnFirstUseSupported
748                 && (config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TTLS
749                 || config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.PEAP)
750                 && config.enterpriseConfig.getPhase2Method() != WifiEnterpriseConfig.Phase2.NONE) {
751             // Verify that the configuration contains an identity
752             assertEquals(TEST_IDENTITY, config.enterpriseConfig.getIdentity());
753             assertTrue(TextUtils.isEmpty(config.enterpriseConfig.getAnonymousIdentity()));
754             assertEquals(TEST_PASSWORD, config.enterpriseConfig.getPassword());
755         }
756         mInsecureEapNetworkHandler.prepareConnection(config);
757 
758         if (isTrustOnFirstUseSupported && config.enterpriseConfig.isTrustOnFirstUseEnabled()
759                 && (config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TTLS
760                 || config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.PEAP)
761                 && config.enterpriseConfig.getPhase2Method() != WifiEnterpriseConfig.Phase2.NONE) {
762             // Verify identities are cleared
763             assertTrue(TextUtils.isEmpty(config.enterpriseConfig.getIdentity()));
764             assertEquals(TOFU_ANONYMOUS_IDENTITY, config.enterpriseConfig.getAnonymousIdentity());
765             assertTrue(TextUtils.isEmpty(config.enterpriseConfig.getPassword()));
766         }
767 
768         if (isTrustOnFirstUseSupported && config.enterpriseConfig.isTrustOnFirstUseEnabled()) {
769             verify(mContext, atLeastOnce()).registerReceiver(
770                     mBroadcastReceiverCaptor.capture(),
771                     argThat(f -> f.hasAction(InsecureEapNetworkHandler.ACTION_CERT_NOTIF_TAP)),
772                     eq(null),
773                     eq(mHandler));
774         } else if ((isTrustOnFirstUseSupported
775                 && !config.enterpriseConfig.isTrustOnFirstUseEnabled()
776                 && isInsecureEnterpriseConfigurationAllowed)
777                 || !isTrustOnFirstUseSupported) {
778             verify(mContext, atLeastOnce()).registerReceiver(
779                     mBroadcastReceiverCaptor.capture(),
780                     argThat(f -> f.hasAction(InsecureEapNetworkHandler.ACTION_CERT_NOTIF_ACCEPT)
781                             && f.hasAction(InsecureEapNetworkHandler.ACTION_CERT_NOTIF_REJECT)),
782                     eq(null),
783                     eq(mHandler));
784         }
785 
786         verify(mWifiConfigManager).addOnNetworkUpdateListener(
787                 mOnNetworkUpdateListenerCaptor.capture());
788     }
789 
790     /**
791      * Verify Trust On First Use flow with a minimal cert chain
792      * - This network is selected by a user.
793      * - Accept the connection.
794      */
795     @Test
verifyTrustOnFirstUseAcceptWhenConnectByUserWithMinimalChain()796     public void verifyTrustOnFirstUseAcceptWhenConnectByUserWithMinimalChain() throws Exception {
797         assumeTrue(SdkLevel.isAtLeastT());
798         boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true;
799         boolean needUserApproval = true;
800 
801         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
802         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
803 
804         CertificateEventInfo mockCaCert = generateMockCertEventInfo(TEST_GEN_CA_CERT);
805         CertificateEventInfo mockServerCert = generateMockCertEventInfo(TEST_GEN_SERVER_CERT);
806         mInsecureEapNetworkHandler.addPendingCertificate(config.networkId, 1, mockCaCert);
807         mInsecureEapNetworkHandler.addPendingCertificate(config.networkId, 0, mockServerCert);
808 
809         verifyTrustOnFirstUseFlow(config, ACTION_ACCEPT, isTrustOnFirstUseSupported,
810                 isUserSelected, needUserApproval, mockCaCert.getCert(), mockServerCert.getCert(),
811                 null);
812     }
813 
814     /**
815      * Verify Trust On First Use flow with a self-signed CA cert.
816      * - This network is selected by a user.
817      * - Forget the connection.
818      */
819     @Test
verifyTrustOnFirstUseForgetWhenConnectByUserWithSelfSignedCaCert()820     public void verifyTrustOnFirstUseForgetWhenConnectByUserWithSelfSignedCaCert()
821             throws Exception {
822         assumeTrue(SdkLevel.isAtLeastT());
823         boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true;
824         boolean needUserApproval = true;
825 
826         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
827         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
828 
829         CertificateEventInfo mockSelfSignedCert =
830                 generateMockCertEventInfo(TEST_GEN_SELF_SIGNED_CERT);
831         mInsecureEapNetworkHandler.addPendingCertificate(config.networkId, 0, mockSelfSignedCert);
832 
833         verifyTrustOnFirstUseFlow(config, ACTION_FORGET, isTrustOnFirstUseSupported,
834                 isUserSelected, needUserApproval, mockSelfSignedCert.getCert(),
835                 mockSelfSignedCert.getCert(), null);
836     }
837 
838     /**
839      * Verify that the connection should be terminated.
840      * - TOFU is supported.
841      * - Insecure EAP network is not allowed.
842      * - No cert is received.
843      */
844     @Test
verifyOnErrorWithoutCert()845     public void verifyOnErrorWithoutCert() throws Exception {
846         assumeTrue(SdkLevel.isAtLeastT());
847         boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true;
848 
849         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
850         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
851 
852         mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected);
853         verify(mCallbacks).onError(eq(config.SSID));
854         verify(mWifiConfigManager, atLeastOnce()).updateNetworkSelectionStatus(eq(config.networkId),
855                 eq(WifiConfiguration.NetworkSelectionStatus
856                         .DISABLED_BY_WIFI_MANAGER));
857     }
858 
859     /**
860      * Verify that the connection should be upgraded to TOFU.
861      * - TOFU is supported.
862      * - Insecure EAP network is not allowed.
863      * - TOFU is not enabled
864      */
865     @Test
verifyOnErrorWithTofuDisabledWhenInsecureEapNetworkIsNotAllowed()866     public void verifyOnErrorWithTofuDisabledWhenInsecureEapNetworkIsNotAllowed()
867             throws Exception {
868         assumeTrue(SdkLevel.isAtLeastT());
869         boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true;
870 
871         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
872         config.enterpriseConfig.enableTrustOnFirstUse(false);
873         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
874 
875         mInsecureEapNetworkHandler.addPendingCertificate(config.networkId, 1,
876                 generateMockCertEventInfo(TEST_GEN_CA_CERT));
877         mInsecureEapNetworkHandler.addPendingCertificate(config.networkId, 0,
878                 generateMockCertEventInfo(TEST_GEN_SERVER_CERT));
879 
880         mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected);
881         assertTrue(config.enterpriseConfig.isTrustOnFirstUseEnabled());
882     }
883 
884     /**
885      * Verify that no error occurs in insecure network handling flow.
886      * - TOFU is supported.
887      * - Insecure EAP network is allowed.
888      * - TOFU is not enabled
889      * - No user approval is needed.
890      */
891     @Test
verifyNoErrorWithTofuDisabledWhenInsecureEapNetworkIsAllowed()892     public void verifyNoErrorWithTofuDisabledWhenInsecureEapNetworkIsAllowed()
893             throws Exception {
894         assumeTrue(SdkLevel.isAtLeastT());
895         boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true;
896         boolean isInsecureEnterpriseConfigurationAllowed = true;
897 
898         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
899         config.enterpriseConfig.enableTrustOnFirstUse(false);
900         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported,
901                 isInsecureEnterpriseConfigurationAllowed);
902 
903         mInsecureEapNetworkHandler.addPendingCertificate(config.networkId, 1,
904                 generateMockCertEventInfo(TEST_GEN_CA_CERT));
905         mInsecureEapNetworkHandler.addPendingCertificate(config.networkId, 0,
906                 generateMockCertEventInfo(TEST_GEN_SERVER_CERT));
907 
908         mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected);
909         verify(mCallbacks, never()).onError(any());
910     }
911 
912     /**
913      * Verify that is reports errors if the server cert issuer does not match the parent subject.
914      */
915     @Test
verifyOnErrorWithIncompleteChain()916     public void verifyOnErrorWithIncompleteChain() throws Exception {
917         assumeTrue(SdkLevel.isAtLeastT());
918         boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true;
919 
920         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
921         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
922 
923         CertificateEventInfo mockCaCert = generateMockCertEventInfo(TEST_GEN_CA2_CERT);
924         // Missing intermediate cert.
925         CertificateEventInfo mockServerCert = generateMockCertEventInfo(TEST_GEN_SERVER_CERT);
926         mInsecureEapNetworkHandler.addPendingCertificate(config.networkId, 1, mockCaCert);
927         mInsecureEapNetworkHandler.addPendingCertificate(config.networkId, 0, mockServerCert);
928 
929         mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected);
930         verify(mCallbacks).onError(eq(config.SSID));
931         verify(mWifiConfigManager, atLeastOnce()).updateNetworkSelectionStatus(eq(config.networkId),
932                 eq(WifiConfiguration.NetworkSelectionStatus
933                         .DISABLED_BY_WIFI_MANAGER));
934     }
935 
936     /**
937      * Verify that it reports errors if the issuer is a fake Root CA with the same subject of the
938      * real Root CA. Simulates an attack where the leaf is copied from the real server but a fake
939      * Root CA that an attacker controls is attached.
940      */
941     @Test
verifyOnErrorWithFakeRootCaCertInTheChain()942     public void verifyOnErrorWithFakeRootCaCertInTheChain() throws Exception {
943         assumeTrue(SdkLevel.isAtLeastT());
944         boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true;
945 
946         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
947         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
948 
949         // Fake Root CA that didn't sign the server cert
950         CertificateEventInfo mockCaCert = generateMockCertEventInfo(TEST_GEN_FAKE_CA_CERT);
951         CertificateEventInfo mockServerCert = generateMockCertEventInfo(TEST_GEN_SERVER_CERT);
952         mInsecureEapNetworkHandler.addPendingCertificate(config.networkId, 1, mockCaCert);
953         mInsecureEapNetworkHandler.addPendingCertificate(config.networkId, 0, mockServerCert);
954 
955         mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected);
956         verify(mCallbacks).onError(eq(config.SSID));
957         verify(mWifiConfigManager, atLeastOnce()).updateNetworkSelectionStatus(eq(config.networkId),
958                 eq(WifiConfiguration.NetworkSelectionStatus
959                         .DISABLED_BY_WIFI_MANAGER));
960     }
961 
962     /**
963      * Verify that is reports errors if the server certificate doesn't contain the common name
964      */
965     @Test
verifyOnErrorWithServerCertificateWithoutCommonName()966     public void verifyOnErrorWithServerCertificateWithoutCommonName() throws Exception {
967         assumeTrue(SdkLevel.isAtLeastT());
968         boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true;
969 
970         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
971         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
972 
973         CertificateEventInfo mockCaCert = generateMockCertEventInfo(TEST_GEN_CA2_CERT);
974         // Server certificate without common name
975         CertificateEventInfo mockServerCert =
976                 generateMockCertEventInfo(TEST_GEN_SERVER_CERTIFICATE_WITHOUT_COMMON_NAME);
977         mInsecureEapNetworkHandler.addPendingCertificate(config.networkId, 1, mockCaCert);
978         mInsecureEapNetworkHandler.addPendingCertificate(config.networkId, 0, mockServerCert);
979 
980         mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected);
981         verify(mCallbacks).onError(eq(config.SSID));
982         verify(mWifiConfigManager, atLeastOnce()).updateNetworkSelectionStatus(eq(config.networkId),
983                 eq(WifiConfiguration.NetworkSelectionStatus
984                         .DISABLED_BY_WIFI_MANAGER));
985     }
986 
987     /**
988      * Verify that setting pending certificate won't crash with no current configuration.
989      */
990     @Test
verifySetPendingCertificateNoCrashWithNoConfig()991     public void verifySetPendingCertificateNoCrashWithNoConfig()
992             throws Exception {
993         assumeTrue(SdkLevel.isAtLeastT());
994         mInsecureEapNetworkHandler = new InsecureEapNetworkHandler(
995                 mContext,
996                 mWifiConfigManager,
997                 mWifiNative,
998                 mFrameworkFacade,
999                 mWifiNotificationManager,
1000                 mWifiDialogManager,
1001                 true /* isTrustOnFirstUseSupported */,
1002                 false /* isInsecureEnterpriseConfigurationAllowed */,
1003                 mCallbacks,
1004                 WIFI_IFACE_NAME,
1005                 mHandler);
1006         CertificateEventInfo mockSelfSignedCert =
1007                 generateMockCertEventInfo(TEST_GEN_SELF_SIGNED_CERT);
1008         mInsecureEapNetworkHandler.addPendingCertificate(WifiConfiguration.INVALID_NETWORK_ID, 0,
1009                 mockSelfSignedCert);
1010         mInsecureEapNetworkHandler.addPendingCertificate(0xF1AF, 0, mockSelfSignedCert);
1011     }
1012 
1013     @Test
testExistingCertChainIsClearedOnPreparingNewConnection()1014     public void testExistingCertChainIsClearedOnPreparingNewConnection() throws Exception {
1015         assumeTrue(SdkLevel.isAtLeastT());
1016         boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true;
1017 
1018         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
1019         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
1020 
1021         // Missing root CA cert.
1022         mInsecureEapNetworkHandler.addPendingCertificate(config.networkId, 0,
1023                 generateMockCertEventInfo(TEST_GEN_SERVER_CERT));
1024 
1025         // The wrong cert chain should be cleared after this call.
1026         mInsecureEapNetworkHandler.prepareConnection(config);
1027 
1028         CertificateEventInfo mockSelfSignedCert =
1029                 generateMockCertEventInfo(TEST_GEN_SELF_SIGNED_CERT);
1030         mInsecureEapNetworkHandler.addPendingCertificate(config.networkId, 0, mockSelfSignedCert);
1031 
1032         mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected);
1033         verify(mCallbacks, never()).onError(any());
1034     }
1035 
1036     @Test
verifyUserApprovalIsNotNeededWithDifferentTargetConfig()1037     public void verifyUserApprovalIsNotNeededWithDifferentTargetConfig() throws Exception {
1038         assumeTrue(SdkLevel.isAtLeastT());
1039         boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true;
1040 
1041         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
1042         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
1043 
1044         CertificateEventInfo mockSelfSignedCert =
1045                 generateMockCertEventInfo(TEST_GEN_SELF_SIGNED_CERT);
1046         mInsecureEapNetworkHandler.addPendingCertificate(config.networkId, 0, mockSelfSignedCert);
1047 
1048         // Pass another PSK config which is not the same as the current one.
1049         WifiConfiguration pskConfig = WifiConfigurationTestUtil.createPskNetwork();
1050         pskConfig.networkId = FRAMEWORK_NETWORK_ID + 2;
1051         mInsecureEapNetworkHandler.prepareConnection(pskConfig);
1052         mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected);
1053         verify(mCallbacks, never()).onError(any());
1054 
1055         // Pass another non-TOFU EAP config which is not the same as the current one.
1056         WifiConfiguration anotherEapConfig = spy(WifiConfigurationTestUtil.createEapNetwork(
1057                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE));
1058         anotherEapConfig.networkId = FRAMEWORK_NETWORK_ID + 1;
1059         assertFalse(mInsecureEapNetworkHandler.addPendingCertificate(anotherEapConfig.networkId, 0,
1060                 mockSelfSignedCert));
1061         mInsecureEapNetworkHandler.prepareConnection(anotherEapConfig);
1062         mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected);
1063         verify(mCallbacks, never()).onError(any());
1064     }
1065 
verifyTrustOnFirstUseFlowWithDefaultCerts(WifiConfiguration config, int action, boolean isTrustOnFirstUseSupported, boolean isUserSelected, boolean needUserApproval)1066     private void verifyTrustOnFirstUseFlowWithDefaultCerts(WifiConfiguration config,
1067             int action, boolean isTrustOnFirstUseSupported, boolean isUserSelected,
1068             boolean needUserApproval) throws Exception {
1069         CertificateEventInfo mockCaCert = generateMockCertEventInfo(TEST_GEN_CA_CERT);
1070         CertificateEventInfo mockServerCert = generateMockCertEventInfo(TEST_GEN_SERVER_CERT);
1071         if (isTrustOnFirstUseSupported) {
1072             mInsecureEapNetworkHandler.addPendingCertificate(config.networkId, 1, mockCaCert);
1073             mInsecureEapNetworkHandler.addPendingCertificate(config.networkId, 0, mockServerCert);
1074         }
1075         verifyTrustOnFirstUseFlow(config, action, isTrustOnFirstUseSupported,
1076                 isUserSelected, needUserApproval, mockCaCert.getCert(), mockServerCert.getCert(),
1077                 null);
1078     }
1079 
verifyTrustOnFirstUseFlow(WifiConfiguration config, int action, boolean isTrustOnFirstUseSupported, boolean isUserSelected, boolean needUserApproval, X509Certificate expectedCaCert, X509Certificate expectedServerCert, String expectedCaPath)1080     private void verifyTrustOnFirstUseFlow(WifiConfiguration config,
1081             int action, boolean isTrustOnFirstUseSupported, boolean isUserSelected,
1082             boolean needUserApproval, X509Certificate expectedCaCert,
1083             X509Certificate expectedServerCert, String expectedCaPath) throws Exception {
1084         mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected);
1085 
1086         ArgumentCaptor<String> dialogMessageCaptor = ArgumentCaptor.forClass(String.class);
1087         if (isUserSelected) {
1088             ArgumentCaptor<WifiDialogManager.SimpleDialogCallback> dialogCallbackCaptor =
1089                     ArgumentCaptor.forClass(WifiDialogManager.SimpleDialogCallback.class);
1090             verify(mWifiDialogManager).createLegacySimpleDialogWithUrl(
1091                     any(), dialogMessageCaptor.capture(), any(), anyInt(), anyInt(), any(), any(),
1092                     any(), dialogCallbackCaptor.capture(), any());
1093             if (isTrustOnFirstUseSupported) {
1094                 assertTofuDialogMessage(expectedServerCert,
1095                         dialogMessageCaptor.getValue());
1096             }
1097             if (action == ACTION_ACCEPT) {
1098                 dialogCallbackCaptor.getValue().onPositiveButtonClicked();
1099             } else if (action == ACTION_REJECT) {
1100                 dialogCallbackCaptor.getValue().onNegativeButtonClicked();
1101             } else if (action == ACTION_FORGET) {
1102                 mOnNetworkUpdateListenerCaptor.getValue().onNetworkRemoved(config);
1103             }
1104         } else {
1105             verify(mFrameworkFacade, never()).makeAlertDialogBuilder(any());
1106             verify(mFrameworkFacade).makeNotificationBuilder(
1107                     eq(mContext), eq(WifiService.NOTIFICATION_NETWORK_ALERTS));
1108 
1109             // Trust On First Use notification has no accept and reject action buttons.
1110             // It only supports TAP and launch the dialog.
1111             if (isTrustOnFirstUseSupported) {
1112                 Intent intent = new Intent(InsecureEapNetworkHandler.ACTION_CERT_NOTIF_TAP);
1113                 intent.putExtra(InsecureEapNetworkHandler.EXTRA_PENDING_CERT_SSID, TEST_SSID);
1114                 BroadcastReceiver br = mBroadcastReceiverCaptor.getValue();
1115                 br.onReceive(mContext, intent);
1116                 ArgumentCaptor<WifiDialogManager.SimpleDialogCallback> dialogCallbackCaptor =
1117                         ArgumentCaptor.forClass(WifiDialogManager.SimpleDialogCallback.class);
1118                 verify(mWifiDialogManager).createLegacySimpleDialogWithUrl(
1119                         any(), dialogMessageCaptor.capture(), any(), anyInt(), anyInt(), any(),
1120                         any(), any(), dialogCallbackCaptor.capture(), any());
1121                 assertTofuDialogMessage(expectedServerCert,
1122                         dialogMessageCaptor.getValue());
1123                 if (action == ACTION_ACCEPT) {
1124                     dialogCallbackCaptor.getValue().onPositiveButtonClicked();
1125                 } else if (action == ACTION_REJECT) {
1126                     dialogCallbackCaptor.getValue().onNegativeButtonClicked();
1127                 }
1128             } else {
1129                 Intent intent = new Intent();
1130                 if (action == ACTION_ACCEPT) {
1131                     intent = new Intent(InsecureEapNetworkHandler.ACTION_CERT_NOTIF_ACCEPT);
1132                 } else if (action == ACTION_REJECT) {
1133                     intent = new Intent(InsecureEapNetworkHandler.ACTION_CERT_NOTIF_REJECT);
1134                 } else if (action == ACTION_TAP) {
1135                     intent = new Intent(InsecureEapNetworkHandler.ACTION_CERT_NOTIF_TAP);
1136                 }
1137                 intent.putExtra(InsecureEapNetworkHandler.EXTRA_PENDING_CERT_SSID, TEST_SSID);
1138                 BroadcastReceiver br = mBroadcastReceiverCaptor.getValue();
1139                 br.onReceive(mContext, intent);
1140             }
1141         }
1142 
1143         if (action == ACTION_ACCEPT) {
1144             verify(mWifiConfigManager).updateNetworkSelectionStatus(eq(config.networkId),
1145                     eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE));
1146             if (isTrustOnFirstUseSupported) {
1147                 int postConnectionMethod;
1148                 if (!TextUtils.isEmpty(expectedCaPath)) {
1149                     // Simulate Root CA from trust store
1150                     postConnectionMethod = WifiEnterpriseConfig.TOFU_STATE_CONFIGURE_ROOT_CA;
1151                     verify(mWifiConfigManager).updateCaCertificate(
1152                             eq(config.networkId), eq(expectedCaCert), eq(expectedServerCert),
1153                             eq(null), eq(true));
1154                 } else if (expectedCaCert == null) {
1155                     // Simulate server cert pinning case where there is no Root CA
1156                     postConnectionMethod = WifiEnterpriseConfig.TOFU_STATE_CERT_PINNING;
1157                     verify(mWifiConfigManager).updateCaCertificate(
1158                             eq(config.networkId), eq(expectedServerCert), eq(expectedServerCert),
1159                             eq("12345678"), eq(false)); // Server certificate hash
1160                 } else {
1161                     postConnectionMethod = WifiEnterpriseConfig.TOFU_STATE_CONFIGURE_ROOT_CA;
1162                     verify(mWifiConfigManager).updateCaCertificate(
1163                             eq(config.networkId), eq(expectedCaCert), eq(expectedServerCert),
1164                             eq(null), eq(false)); // Cert pinning not used
1165                 }
1166                 verify(mWifiConfigManager).setTofuPostConnectionState(
1167                         eq(config.networkId), eq(postConnectionMethod));
1168             } else {
1169                 verify(mWifiConfigManager, never()).updateCaCertificate(
1170                         anyInt(), any(), any(), any(), anyBoolean());
1171                 verify(mWifiConfigManager, never()).setTofuPostConnectionState(anyInt(), anyInt());
1172             }
1173             verify(mWifiConfigManager).setTofuDialogApproved(eq(config.networkId), eq(true));
1174             verify(mCallbacks).onAccept(eq(config.SSID), eq(config.networkId));
1175         } else if (action == ACTION_REJECT) {
1176             verify(mWifiConfigManager).setTofuDialogApproved(eq(config.networkId), eq(false));
1177             verify(mWifiConfigManager, atLeastOnce())
1178                     .updateNetworkSelectionStatus(eq(config.networkId),
1179                             eq(WifiConfiguration.NetworkSelectionStatus
1180                             .DISABLED_BY_WIFI_MANAGER));
1181             verify(mCallbacks).onReject(eq(config.SSID), eq(!isTrustOnFirstUseSupported));
1182         } else if (action == ACTION_TAP) {
1183             verify(mWifiDialogManager).createLegacySimpleDialogWithUrl(
1184                     any(), any(), any(), anyInt(), anyInt(), any(), any(), any(), any(), any());
1185             verify(mTofuAlertDialog).launchDialog();
1186         } else if (action == ACTION_FORGET) {
1187             verify(mTofuAlertDialog).dismissDialog();
1188         }
1189         verify(mCallbacks, never()).onError(any());
1190     }
1191 
assertTofuDialogMessage( X509Certificate serverCert, String message)1192     private void assertTofuDialogMessage(
1193             X509Certificate serverCert,
1194             String message) {
1195         CertificateSubjectInfo serverCertSubjectInfo =
1196                 CertificateSubjectInfo.parse(serverCert.getSubjectX500Principal().getName());
1197         CertificateSubjectInfo serverCertIssuerInfo =
1198                 CertificateSubjectInfo.parse(serverCert.getIssuerX500Principal().getName());
1199         assertNotNull("Server cert subject info is null", serverCertSubjectInfo);
1200         assertNotNull("Server cert issuer info is null", serverCertIssuerInfo);
1201 
1202         assertTrue("TOFU dialog message does not contain server cert subject name ",
1203                 message.contains(serverCertSubjectInfo.commonName));
1204         assertTrue("TOFU dialog message does not contain server cert issuer name",
1205                 message.contains(serverCertIssuerInfo.commonName));
1206         if (!TextUtils.isEmpty(serverCertSubjectInfo.organization)) {
1207             assertTrue("TOFU dialog message does not contain server cert organization",
1208                     message.contains(serverCertSubjectInfo.organization));
1209         }
1210     }
1211 
1212     @Test
testCleanUp()1213     public void testCleanUp() throws Exception {
1214         assumeTrue(SdkLevel.isAtLeastT());
1215 
1216         boolean isAtLeastT = true, isTrustOnFirstUseSupported = true;
1217         WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
1218         setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
1219 
1220         BroadcastReceiver br = mBroadcastReceiverCaptor.getValue();
1221         mInsecureEapNetworkHandler.cleanup();
1222         verify(mContext).unregisterReceiver(br);
1223         verify(mWifiConfigManager).removeOnNetworkUpdateListener(
1224                 mOnNetworkUpdateListenerCaptor.capture());
1225     }
1226 
1227     /**
1228      * Verify the getDigest and fingerprint methods
1229      */
1230     @Test
verifyGetDigest()1231     public void verifyGetDigest() throws Exception {
1232         CertificateEventInfo mockServerCert = generateMockCertEventInfo(TEST_GEN_SERVER_CERT);
1233         assertEquals(TEST_EXPECTED_SHA_256_SIGNATURE,
1234                 mInsecureEapNetworkHandler.getDigest(mockServerCert.getCert(), "SHA256"));
1235     }
1236 
1237     @Test
verifyTrustStoreUsedForAidlVersion2AndUp()1238     public void verifyTrustStoreUsedForAidlVersion2AndUp() throws Exception {
1239         WifiConfiguration config = configureTofuWithAidlVersion2Value(true);
1240         verify(config.enterpriseConfig)
1241                 .setCaPath(eq(WifiConfigurationUtil.getSystemTrustStorePath()));
1242     }
1243 
1244     @Test
verifyTrustStoreUsedForAidlVersionBelow2()1245     public void verifyTrustStoreUsedForAidlVersionBelow2() throws Exception {
1246         WifiConfiguration config = configureTofuWithAidlVersion2Value(false);
1247         verify(config.enterpriseConfig, never()).setCaPath(anyString());
1248     }
1249 
configureTofuWithAidlVersion2Value(boolean aidlVersion2OrUp)1250     private WifiConfiguration configureTofuWithAidlVersion2Value(boolean aidlVersion2OrUp) {
1251         mInsecureEapNetworkHandler = new InsecureEapNetworkHandler(
1252                 mContext,
1253                 mWifiConfigManager,
1254                 mWifiNative,
1255                 mFrameworkFacade,
1256                 mWifiNotificationManager,
1257                 mWifiDialogManager,
1258                 true,
1259                 false,
1260                 mCallbacks,
1261                 WIFI_IFACE_NAME,
1262                 mHandler);
1263 
1264         when(mWifiNative.isSupplicantAidlServiceVersionAtLeast(anyInt()))
1265                 .thenReturn(aidlVersion2OrUp);
1266 
1267         WifiConfiguration config = spy(WifiConfigurationTestUtil.createEapNetwork(
1268                 WifiEnterpriseConfig.Eap.TTLS, WifiEnterpriseConfig.Phase2.MSCHAPV2));
1269         config.networkId = FRAMEWORK_NETWORK_ID;
1270         config.SSID = TEST_SSID;
1271         WifiEnterpriseConfig enterpriseConfig = mock(WifiEnterpriseConfig.class);
1272         when(enterpriseConfig.isTrustOnFirstUseEnabled()).thenReturn(true);
1273         when(enterpriseConfig.isEapMethodServerCertUsed()).thenReturn(true);
1274         when(enterpriseConfig.hasCaCertificate()).thenReturn(false);
1275         when(enterpriseConfig.isUserApproveNoCaCert()).thenReturn(false);
1276         config.enterpriseConfig = enterpriseConfig;
1277 
1278         mInsecureEapNetworkHandler.prepareConnection(config);
1279         return config;
1280     }
1281 }
1282