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