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