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