1 /* 2 * Copyright (C) 2018 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 android.net.wifi.WifiManager.EASY_CONNECT_NETWORK_ROLE_AP; 20 21 import android.annotation.Nullable; 22 import android.content.Context; 23 import android.net.wifi.EasyConnectStatusCallback; 24 import android.net.wifi.IDppCallback; 25 import android.net.wifi.ScanResult; 26 import android.net.wifi.WifiConfiguration; 27 import android.net.wifi.WifiManager; 28 import android.net.wifi.WifiSsid; 29 import android.os.Build; 30 import android.os.Handler; 31 import android.os.IBinder; 32 import android.os.RemoteException; 33 import android.text.TextUtils; 34 import android.util.Log; 35 import android.util.SparseArray; 36 37 import androidx.annotation.RequiresApi; 38 39 import com.android.internal.annotations.VisibleForTesting; 40 import com.android.internal.util.WakeupMessage; 41 import com.android.modules.utils.build.SdkLevel; 42 import com.android.server.wifi.SupplicantStaIfaceHal.DppAkm; 43 import com.android.server.wifi.SupplicantStaIfaceHal.DppCurve; 44 import com.android.server.wifi.SupplicantStaIfaceHal.DppEventType; 45 import com.android.server.wifi.SupplicantStaIfaceHal.DppFailureCode; 46 import com.android.server.wifi.SupplicantStaIfaceHal.DppNetRole; 47 import com.android.server.wifi.SupplicantStaIfaceHal.DppProgressCode; 48 import com.android.server.wifi.WifiNative.DppEventCallback; 49 import com.android.server.wifi.util.ApConfigUtil; 50 import com.android.server.wifi.util.WifiPermissionsUtil; 51 52 import java.nio.charset.StandardCharsets; 53 import java.util.ArrayList; 54 import java.util.List; 55 56 /** 57 * DPP Manager class 58 * Implements the DPP Initiator APIs and callbacks 59 */ 60 public class DppManager { 61 private static final String TAG = "DppManager"; 62 private final WifiInjector mWifiInjector; 63 private final Handler mHandler; 64 65 private DppRequestInfo mDppRequestInfo = null; 66 private final WifiNative mWifiNative; 67 private String mClientIfaceName; 68 private boolean mVerboseLoggingEnabled; 69 WifiConfigManager mWifiConfigManager; 70 private final Context mContext; 71 @VisibleForTesting 72 public WakeupMessage mDppTimeoutMessage = null; 73 private final Clock mClock; 74 private static final String DPP_TIMEOUT_TAG = TAG + " Request Timeout"; 75 private static final int DPP_TIMEOUT_MS = 40_000; // 40 seconds 76 private static final int DPP_RESPONDER_TIMEOUT_MS = 300_000; // 5 minutes 77 private static final int DPP_ENROLLEE_CONN_STATUS_RESULT_TX_TIMEOUT_MS = 16_000; // 16 seconds 78 public static final int DPP_AUTH_ROLE_INACTIVE = -1; 79 public static final int DPP_AUTH_ROLE_INITIATOR = 0; 80 public static final int DPP_AUTH_ROLE_RESPONDER = 1; 81 private final DppMetrics mDppMetrics; 82 private final ScanRequestProxy mScanRequestProxy; 83 private final WifiPermissionsUtil mWifiPermissionsUtil; 84 85 private final DppEventCallback mDppEventCallback = new DppEventCallback() { 86 @Override 87 public void onSuccessConfigReceived(WifiConfiguration newWifiConfiguration, 88 boolean connStatusRequested) { 89 mHandler.post(() -> { 90 DppManager.this.onSuccessConfigReceived(newWifiConfiguration, connStatusRequested); 91 }); 92 } 93 94 @Override 95 public void onSuccess(int dppStatusCode) { 96 mHandler.post(() -> { 97 DppManager.this.onSuccess(dppStatusCode); 98 }); 99 } 100 101 @Override 102 public void onProgress(int dppStatusCode) { 103 mHandler.post(() -> { 104 DppManager.this.onProgress(dppStatusCode); 105 }); 106 } 107 108 @Override 109 public void onFailure(int dppStatusCode, String ssid, String channelList, int[] bandList) { 110 mHandler.post(() -> { 111 DppManager.this.onFailure(dppStatusCode, ssid, channelList, bandList); 112 }); 113 } 114 115 @Override 116 public void onDppConfiguratorKeyUpdate(byte[] key) { 117 mHandler.post(() -> { 118 DppManager.this.onDppConfiguratorKeyUpdate(key); 119 }); 120 } 121 122 @Override 123 public void onConnectionStatusResultSent(int result) { 124 mHandler.post(() -> { 125 DppManager.this.onConnectionStatusResultSent(result); 126 }); 127 128 } 129 }; 130 DppManager(WifiInjector wifiInjector, Handler handler, WifiNative wifiNative, WifiConfigManager wifiConfigManager, Context context, DppMetrics dppMetrics, ScanRequestProxy scanRequestProxy, WifiPermissionsUtil wifiPermissionsUtil)131 DppManager(WifiInjector wifiInjector, Handler handler, WifiNative wifiNative, 132 WifiConfigManager wifiConfigManager, Context context, DppMetrics dppMetrics, 133 ScanRequestProxy scanRequestProxy, WifiPermissionsUtil wifiPermissionsUtil) { 134 mWifiInjector = wifiInjector; 135 mHandler = handler; 136 mWifiNative = wifiNative; 137 mWifiConfigManager = wifiConfigManager; 138 mWifiNative.registerDppEventCallback(mDppEventCallback); 139 mContext = context; 140 mClock = new Clock(); 141 mDppMetrics = dppMetrics; 142 mScanRequestProxy = scanRequestProxy; 143 mWifiPermissionsUtil = wifiPermissionsUtil; 144 145 // Setup timer 146 mDppTimeoutMessage = new WakeupMessage(mContext, mHandler, 147 DPP_TIMEOUT_TAG, () -> { 148 timeoutDppRequest(); 149 }); 150 } 151 encodeStringToUtf8Hex(String str)152 private static String encodeStringToUtf8Hex(String str) { 153 if ((str.length() > 1) && (str.charAt(0) == '"') && (str.charAt(str.length() - 1) == '"')) { 154 // Remove the surrounding quotes 155 str = str.substring(1, str.length() - 1); 156 157 // Convert to Hex 158 byte[] bytesArray = str.getBytes(StandardCharsets.UTF_8); 159 StringBuffer hexBuffer = new StringBuffer(); 160 for (int i = 0; i < bytesArray.length; i++) { 161 hexBuffer.append(Integer.toHexString(0xFF & bytesArray[i])); 162 } 163 return hexBuffer.toString(); 164 } 165 return str; 166 } 167 timeoutDppRequest()168 private void timeoutDppRequest() { 169 logd("DPP timeout"); 170 171 if (mDppRequestInfo == null) { 172 Log.e(TAG, "DPP timeout with no request info"); 173 return; 174 } 175 176 // Clean up supplicant resources 177 if (!mWifiNative.stopDppInitiator(mClientIfaceName)) { 178 Log.e(TAG, "Failed to stop DPP Initiator"); 179 } 180 181 // Clean up resources and let the caller know about the timeout 182 onFailure(DppFailureCode.TIMEOUT); 183 } 184 185 /** 186 * Generate DPP connection keys for Configurator. This is used to connect to 187 * other devices (APs) which this configurator has enrolled using DPP-AKM. 188 * DPP connection keys are received via DppEventCallback.onSuccessConfigReceived 189 * 190 * @param networkId Network ID of DPP-AKM wifi configuration. 191 */ generateSelfDppConfiguration(int networkId)192 private void generateSelfDppConfiguration(int networkId) { 193 WifiConfiguration config = mWifiConfigManager 194 .getConfiguredNetworkWithoutMasking(networkId); 195 196 if (config == null || !config.isSecurityType(WifiConfiguration.SECURITY_TYPE_DPP) 197 || !config.isDppConfigurator() || (config.getDppConnector().length > 0)) { 198 Log.e(TAG, "Not eligible for generateSelfDppConfiguration yet."); 199 return; 200 } 201 202 mDppRequestInfo.isGeneratingSelfConfiguration = true; 203 204 if (!mWifiNative.generateSelfDppConfiguration(mClientIfaceName, 205 config.SSID, config.getDppPrivateEcKey())) { 206 Log.e(TAG, "generateSelfDppConfiguration failed!!"); 207 mDppRequestInfo.isGeneratingSelfConfiguration = false; 208 } 209 210 return; 211 } 212 213 /** 214 * Start DPP request in Configurator-Initiator mode. The goal of this call is to send the 215 * selected Wi-Fi configuration to a remote peer so it could join that network. 216 * 217 * @param uid UID 218 * @param packageName Package name of the calling app 219 * @param clientIfaceName Client interface to use for this operation. 220 * @param binder Binder object 221 * @param enrolleeUri The Enrollee URI, scanned externally (e.g. via QR code) 222 * @param selectedNetworkId The selected Wi-Fi network ID to be sent 223 * @param enrolleeNetworkRole Network role of remote enrollee: STA or AP 224 * @param callback DPP Callback object 225 */ startDppAsConfiguratorInitiator(int uid, @Nullable String packageName, @Nullable String clientIfaceName, IBinder binder, String enrolleeUri, int selectedNetworkId, @WifiManager.EasyConnectNetworkRole int enrolleeNetworkRole, IDppCallback callback)226 public void startDppAsConfiguratorInitiator(int uid, @Nullable String packageName, 227 @Nullable String clientIfaceName, IBinder binder, String enrolleeUri, 228 int selectedNetworkId, @WifiManager.EasyConnectNetworkRole int enrolleeNetworkRole, 229 IDppCallback callback) { 230 mDppMetrics.updateDppConfiguratorInitiatorRequests(); 231 if (isSessionInProgress()) { 232 try { 233 Log.e(TAG, "DPP request already in progress"); 234 Log.e(TAG, "Ongoing request - UID: " + mDppRequestInfo.uid 235 + " Package: " + mDppRequestInfo.packageName 236 + ", New request - UID: " + uid + " Package: " + packageName); 237 238 mDppMetrics.updateDppFailure(EasyConnectStatusCallback 239 .EASY_CONNECT_EVENT_FAILURE_BUSY); 240 // On going DPP. Call the failure callback directly 241 callback.onFailure(EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_BUSY, null, 242 null, new int[0]); 243 } catch (RemoteException e) { 244 // Empty 245 } 246 return; 247 } 248 249 mClientIfaceName = clientIfaceName; 250 if (mClientIfaceName == null) { 251 try { 252 Log.e(TAG, "Wi-Fi client interface does not exist"); 253 // On going DPP. Call the failure callback directly 254 mDppMetrics.updateDppFailure(EasyConnectStatusCallback 255 .EASY_CONNECT_EVENT_FAILURE_GENERIC); 256 callback.onFailure(EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_GENERIC, 257 null, null, new int[0]); 258 } catch (RemoteException e) { 259 // Empty 260 } 261 return; 262 } 263 264 WifiConfiguration selectedNetwork = mWifiConfigManager 265 .getConfiguredNetworkWithoutMasking(selectedNetworkId); 266 267 if (selectedNetwork == null) { 268 try { 269 Log.e(TAG, "Selected network is null"); 270 // On going DPP. Call the failure callback directly 271 mDppMetrics.updateDppFailure(EasyConnectStatusCallback 272 .EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK); 273 callback.onFailure(EasyConnectStatusCallback 274 .EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK, null, null, new int[0]); 275 } catch (RemoteException e) { 276 // Empty 277 } 278 return; 279 } 280 281 String password = null; 282 String psk = null; 283 int securityAkm; 284 byte[] privEcKey = null; 285 286 // Currently support either SAE mode or PSK mode or DPP mode 287 // Check PSK first because PSK config always has a SAE type as a upgrading type. 288 if (selectedNetwork.isSecurityType(WifiConfiguration.SECURITY_TYPE_PSK)) { 289 if (selectedNetwork.preSharedKey.matches("[0-9A-Fa-f]{64}")) { 290 // PSK 291 psk = selectedNetwork.preSharedKey; 292 } else { 293 // Passphrase 294 password = selectedNetwork.preSharedKey; 295 } 296 securityAkm = DppAkm.PSK; 297 } else if (selectedNetwork.isSecurityType(WifiConfiguration.SECURITY_TYPE_SAE)) { 298 // SAE 299 password = selectedNetwork.preSharedKey; 300 securityAkm = DppAkm.SAE; 301 } else if (selectedNetwork.isSecurityType(WifiConfiguration.SECURITY_TYPE_DPP)) { 302 // DPP 303 if (selectedNetwork.isDppConfigurator()) { 304 privEcKey = selectedNetwork.getDppPrivateEcKey(); 305 } else { 306 if (enrolleeNetworkRole != EASY_CONNECT_NETWORK_ROLE_AP) { 307 try { 308 Log.e(TAG, "Device is not configured previously to configure" 309 + "the peer enrollee devices to this network"); 310 callback.onFailure( 311 EasyConnectStatusCallback 312 .EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK, 313 null, null, new int[0]); 314 } catch (RemoteException e) { 315 // Empty 316 } 317 return; 318 } 319 } 320 securityAkm = DppAkm.DPP; 321 } else { 322 try { 323 // Key management must be either PSK or SAE or DPP 324 Log.e(TAG, "Key management must be either PSK or SAE"); 325 mDppMetrics.updateDppFailure(EasyConnectStatusCallback 326 .EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK); 327 callback.onFailure( 328 EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK, null, 329 null, new int[0]); 330 } catch (RemoteException e) { 331 // Empty 332 } 333 return; 334 } 335 336 mDppRequestInfo = new DppRequestInfo(); 337 mDppRequestInfo.uid = uid; 338 mDppRequestInfo.packageName = packageName; 339 mDppRequestInfo.binder = binder; 340 mDppRequestInfo.callback = callback; 341 mDppRequestInfo.authRole = DPP_AUTH_ROLE_INITIATOR; 342 mDppRequestInfo.networkId = selectedNetworkId; 343 344 if (!linkToDeath(mDppRequestInfo)) { 345 // Notify failure and clean up 346 onFailure(EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_GENERIC); 347 return; 348 } 349 350 logd("Interface " + mClientIfaceName + ": Initializing URI: " + enrolleeUri); 351 352 mDppRequestInfo.startTime = mClock.getElapsedSinceBootMillis(); 353 mDppTimeoutMessage.schedule(mDppRequestInfo.startTime + DPP_TIMEOUT_MS); 354 355 // Send Enrollee URI and get a peer ID 356 int peerId = mWifiNative.addDppPeerUri(mClientIfaceName, enrolleeUri); 357 358 if (peerId < 0) { 359 Log.e(TAG, "DPP add URI failure"); 360 361 // Notify failure and clean up 362 onFailure(DppFailureCode.INVALID_URI); 363 return; 364 } 365 mDppRequestInfo.peerId = peerId; 366 367 // Auth init 368 logd("Authenticating"); 369 370 String ssidEncoded; 371 WifiSsid originalSsid = mWifiInjector.getSsidTranslator().getOriginalSsid(selectedNetwork); 372 if (originalSsid != null) { 373 ssidEncoded = encodeStringToUtf8Hex(originalSsid.toString()); 374 } else { 375 ssidEncoded = encodeStringToUtf8Hex(selectedNetwork.SSID); 376 } 377 String passwordEncoded = null; 378 379 if (password != null) { 380 passwordEncoded = encodeStringToUtf8Hex(selectedNetwork.preSharedKey); 381 } 382 383 if (!mWifiNative.startDppConfiguratorInitiator(mClientIfaceName, 384 mDppRequestInfo.peerId, 0, ssidEncoded, passwordEncoded, psk, 385 enrolleeNetworkRole == EASY_CONNECT_NETWORK_ROLE_AP ? DppNetRole.AP 386 : DppNetRole.STA, 387 securityAkm, privEcKey)) { 388 Log.e(TAG, "DPP Start Configurator Initiator failure"); 389 390 // Notify failure and clean up 391 onFailure(DppFailureCode.FAILURE); 392 return; 393 } 394 395 logd("Success: Started DPP Initiator with peer ID " 396 + mDppRequestInfo.peerId); 397 } 398 399 /** 400 * Start DPP request in Enrollee-Initiator mode. The goal of this call is to receive a 401 * Wi-Fi configuration object from the peer configurator in order to join a network. 402 * 403 * @param uid UID 404 * @param clientIfaceName Client interface to use for this operation. 405 * @param binder Binder object 406 * @param configuratorUri The Configurator URI, scanned externally (e.g. via QR code) 407 * @param callback DPP Callback object 408 */ startDppAsEnrolleeInitiator(int uid, @Nullable String clientIfaceName, IBinder binder, String configuratorUri, IDppCallback callback)409 public void startDppAsEnrolleeInitiator(int uid, @Nullable String clientIfaceName, 410 IBinder binder, String configuratorUri, IDppCallback callback) { 411 mDppMetrics.updateDppEnrolleeInitiatorRequests(); 412 if (isSessionInProgress()) { 413 try { 414 Log.e(TAG, "DPP request already in progress"); 415 Log.e(TAG, "Ongoing request UID: " + mDppRequestInfo.uid + ", new UID: " 416 + uid); 417 418 mDppMetrics.updateDppFailure(EasyConnectStatusCallback 419 .EASY_CONNECT_EVENT_FAILURE_BUSY); 420 // On going DPP. Call the failure callback directly 421 callback.onFailure(EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_BUSY, null, 422 null, new int[0]); 423 } catch (RemoteException e) { 424 // Empty 425 } 426 return; 427 } 428 429 mDppRequestInfo = new DppRequestInfo(); 430 mDppRequestInfo.uid = uid; 431 mDppRequestInfo.binder = binder; 432 mDppRequestInfo.callback = callback; 433 mDppRequestInfo.authRole = DPP_AUTH_ROLE_INITIATOR; 434 435 if (!linkToDeath(mDppRequestInfo)) { 436 // Notify failure and clean up 437 onFailure(DppFailureCode.FAILURE); 438 return; 439 } 440 441 mDppRequestInfo.startTime = mClock.getElapsedSinceBootMillis(); 442 mDppTimeoutMessage.schedule(mDppRequestInfo.startTime + DPP_TIMEOUT_MS); 443 444 mClientIfaceName = clientIfaceName; 445 logd("Interface " + mClientIfaceName + ": Initializing URI: " + configuratorUri); 446 447 // Send Configurator URI and get a peer ID 448 int peerId = mWifiNative.addDppPeerUri(mClientIfaceName, configuratorUri); 449 450 if (peerId < 0) { 451 Log.e(TAG, "DPP add URI failure"); 452 onFailure(DppFailureCode.INVALID_URI); 453 return; 454 } 455 mDppRequestInfo.peerId = peerId; 456 457 // Auth init 458 logd("Authenticating"); 459 460 if (!mWifiNative.startDppEnrolleeInitiator(mClientIfaceName, mDppRequestInfo.peerId, 461 0)) { 462 Log.e(TAG, "DPP Start Enrollee Initiator failure"); 463 464 // Notify failure and clean up 465 onFailure(DppFailureCode.FAILURE); 466 return; 467 } 468 469 logd("Success: Started DPP Initiator with peer ID " 470 + mDppRequestInfo.peerId); 471 } 472 473 /** 474 * Start DPP request in Enrollee-Responder mode. The goal of this call is to receive a 475 * Wi-Fi configuration object from the peer configurator by showing a QR code and being scanned 476 * by the peer configurator. 477 * 478 * @param uid UID 479 * @param clientIfaceName Client interface to use for this operation. 480 * @param binder Binder object 481 * @param deviceInfo The Device specific info to attach to the generated URI 482 * @param curve Elliptic curve cryptography type used to generate DPP 483 * public/private key pair. 484 * @param callback DPP Callback object 485 */ startDppAsEnrolleeResponder(int uid, @Nullable String clientIfaceName, IBinder binder, @Nullable String deviceInfo, @WifiManager.EasyConnectCryptographyCurve int curve, IDppCallback callback)486 public void startDppAsEnrolleeResponder(int uid, @Nullable String clientIfaceName, 487 IBinder binder, @Nullable String deviceInfo, 488 @WifiManager.EasyConnectCryptographyCurve int curve, IDppCallback callback) { 489 mDppMetrics.updateDppEnrolleeResponderRequests(); 490 if (isSessionInProgress()) { 491 try { 492 Log.e(TAG, "DPP request already in progress"); 493 Log.e(TAG, "Ongoing request UID: " + mDppRequestInfo.uid + ", new UID: " 494 + uid); 495 496 mDppMetrics.updateDppFailure(EasyConnectStatusCallback 497 .EASY_CONNECT_EVENT_FAILURE_BUSY); 498 // On going DPP. Call the failure callback directly 499 callback.onFailure(EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_BUSY, 500 null, null, new int[0]); 501 } catch (RemoteException e) { 502 // Empty 503 } 504 return; 505 } 506 507 mDppRequestInfo = new DppRequestInfo(); 508 mDppRequestInfo.uid = uid; 509 mDppRequestInfo.binder = binder; 510 mDppRequestInfo.callback = callback; 511 mDppRequestInfo.authRole = DPP_AUTH_ROLE_RESPONDER; 512 513 if (!linkToDeath(mDppRequestInfo)) { 514 // Notify failure and clean up 515 onFailure(DppFailureCode.FAILURE); 516 return; 517 } 518 519 mDppRequestInfo.startTime = mClock.getElapsedSinceBootMillis(); 520 mDppTimeoutMessage.schedule(mDppRequestInfo.startTime + DPP_RESPONDER_TIMEOUT_MS); 521 522 mClientIfaceName = clientIfaceName; 523 logd("Interface " + mClientIfaceName + " Product Info: " + deviceInfo 524 + " Curve: " + curve); 525 526 String info = deviceInfo == null ? "" : deviceInfo; 527 // Generate a QR code based bootstrap info 528 WifiNative.DppBootstrapQrCodeInfo bootstrapInfo = null; 529 if (SdkLevel.isAtLeastS()) { 530 bootstrapInfo = 531 mWifiNative.generateDppBootstrapInfoForResponder(mClientIfaceName, deviceInfo, 532 convertEasyConnectCryptographyCurveToHidlDppCurve(curve)); 533 } 534 535 if (bootstrapInfo == null || bootstrapInfo.bootstrapId < 0 536 || TextUtils.isEmpty(bootstrapInfo.uri)) { 537 Log.e(TAG, "DPP request to generate URI failed"); 538 onFailure(DppFailureCode.URI_GENERATION); 539 return; 540 } 541 542 mDppRequestInfo.bootstrapId = bootstrapInfo.bootstrapId; 543 logd("BootstrapId:" + mDppRequestInfo.bootstrapId + " URI: " + bootstrapInfo.uri); 544 545 if (!mWifiNative.startDppEnrolleeResponder(mClientIfaceName, bootstrapInfo.listenChannel)) { 546 Log.e(TAG, "DPP Start Enrollee Responder failure"); 547 // Notify failure and clean up 548 onFailure(DppFailureCode.FAILURE); 549 return; 550 } 551 552 logd("Success: Started DPP Enrollee Responder on listen channel " 553 + bootstrapInfo.listenChannel); 554 555 try { 556 mDppRequestInfo.callback.onBootstrapUriGenerated(bootstrapInfo.uri); 557 } catch (RemoteException e) { 558 Log.e(TAG, " onBootstrapUriGenerated Callback failure"); 559 onFailure(DppFailureCode.FAILURE); 560 return; 561 } 562 } 563 564 /** 565 * Stop a current DPP session 566 * 567 * @param uid User ID 568 */ stopDppSession(int uid)569 public void stopDppSession(int uid) { 570 if (!isSessionInProgress()) { 571 logd("UID " + uid + " called stop DPP session with no active DPP session"); 572 return; 573 } 574 575 if (mDppRequestInfo.uid != uid) { 576 Log.e(TAG, "UID " + uid + " called stop DPP session but UID " + mDppRequestInfo.uid 577 + " has started it"); 578 return; 579 } 580 581 // Clean up supplicant resources 582 if (mDppRequestInfo.authRole == DPP_AUTH_ROLE_INITIATOR) { 583 if (!mWifiNative.stopDppInitiator(mClientIfaceName)) { 584 Log.e(TAG, "Failed to stop DPP Initiator"); 585 } 586 } 587 mDppRequestInfo.isGeneratingSelfConfiguration = false; 588 589 if (mDppRequestInfo.connStatusRequested) { 590 logd("skip DPP resource cleanup - waiting for send connection status result"); 591 return; 592 } 593 594 cleanupDppResources(); 595 596 logd("Success: Stopped DPP Session"); 597 } 598 cleanupDppResources()599 private void cleanupDppResources() { 600 logd("DPP clean up resources"); 601 if (!isSessionInProgress()) { 602 return; 603 } 604 605 if (mDppRequestInfo.isGeneratingSelfConfiguration) { 606 logd("Generate Self Configuration in progress. Skip cleanup"); 607 return; 608 } 609 610 // Cancel pending timeout 611 mDppTimeoutMessage.cancel(); 612 613 // Remove the URI from the supplicant list 614 if (mDppRequestInfo.authRole == DPP_AUTH_ROLE_INITIATOR) { 615 if (!mWifiNative.removeDppUri(mClientIfaceName, mDppRequestInfo.peerId)) { 616 Log.e(TAG, "Failed to remove DPP URI ID " + mDppRequestInfo.peerId); 617 } 618 } else if (mDppRequestInfo.authRole == DPP_AUTH_ROLE_RESPONDER) { 619 if (!mWifiNative.stopDppResponder(mClientIfaceName, mDppRequestInfo.bootstrapId)) { 620 Log.e(TAG, "Failed to stop DPP Responder"); 621 } 622 } 623 624 mDppRequestInfo.binder.unlinkToDeath(mDppRequestInfo.dr, 0); 625 626 mDppRequestInfo = null; 627 } 628 629 /** 630 * Indicates whether there is a dpp session in progress or not. 631 */ isSessionInProgress()632 public boolean isSessionInProgress() { 633 return mDppRequestInfo != null; 634 } 635 636 private static class DppRequestInfo { 637 public int uid; 638 public String packageName; 639 public IBinder binder; 640 public IBinder.DeathRecipient dr; 641 public int peerId; 642 public IDppCallback callback; 643 public long startTime; 644 public int authRole = DPP_AUTH_ROLE_INACTIVE; 645 public int bootstrapId; 646 public int networkId; 647 public boolean isGeneratingSelfConfiguration = false; 648 public boolean connStatusRequested = false; 649 650 @Override toString()651 public String toString() { 652 return new StringBuilder("DppRequestInfo: uid=").append(uid).append(", binder=").append( 653 binder).append(", dr=").append(dr) 654 .append(", callback=").append(callback) 655 .append(", peerId=").append(peerId) 656 .append(", authRole=").append(authRole) 657 .append(", bootstrapId=").append(bootstrapId) 658 .append(", nId=").append(networkId) 659 .append(", connStatusRequested=").append(connStatusRequested).toString(); 660 } 661 } 662 663 /** 664 * Enable vervose logging from DppManager 665 * 666 * @param verbose 0 to disable verbose logging, or any other value to enable. 667 */ enableVerboseLogging(boolean verboseEnabled)668 public void enableVerboseLogging(boolean verboseEnabled) { 669 mVerboseLoggingEnabled = verboseEnabled; 670 } 671 onSuccessConfigReceived(WifiConfiguration newWifiConfiguration, boolean connStatusRequested)672 private void onSuccessConfigReceived(WifiConfiguration newWifiConfiguration, 673 boolean connStatusRequested) { 674 try { 675 if (mDppRequestInfo == null) { 676 Log.e(TAG, "onSuccessConfigReceived event without a request information object"); 677 return; 678 } 679 logd("onSuccessConfigReceived: connection status requested: " + connStatusRequested); 680 if (mDppRequestInfo.isGeneratingSelfConfiguration) { 681 WifiConfiguration existingWifiConfig = mWifiConfigManager 682 .getConfiguredNetworkWithoutMasking(mDppRequestInfo.networkId); 683 684 if (newWifiConfiguration.isSecurityType(WifiConfiguration.SECURITY_TYPE_DPP) 685 && existingWifiConfig != null && existingWifiConfig.isDppConfigurator() 686 && TextUtils.equals(existingWifiConfig.SSID, newWifiConfiguration.SSID) 687 && existingWifiConfig.isSecurityType(WifiConfiguration.SECURITY_TYPE_DPP)) { 688 if (newWifiConfiguration.getDppConnector().length > 0 689 && newWifiConfiguration.getDppCSignKey().length > 0 690 && newWifiConfiguration.getDppNetAccessKey().length > 0) { 691 Log.d(TAG, "Updating DPP Connection keys for self"); 692 existingWifiConfig.setDppConnectionKeys( 693 newWifiConfiguration.getDppConnector(), 694 newWifiConfiguration.getDppCSignKey(), 695 newWifiConfiguration.getDppNetAccessKey()); 696 697 NetworkUpdateResult networkUpdateResult = mWifiConfigManager 698 .addOrUpdateNetwork(existingWifiConfig, mDppRequestInfo.uid); 699 700 if (!networkUpdateResult.isSuccess()) { 701 Log.e(TAG, "DPP configuration generated, but failed to update network"); 702 mDppRequestInfo.callback.onFailure(EasyConnectStatusCallback 703 .EASY_CONNECT_EVENT_FAILURE_CONFIGURATION, null, 704 null, new int[0]); 705 } 706 } 707 } 708 // Done with self configuration. reset flag. 709 mDppRequestInfo.isGeneratingSelfConfiguration = false; 710 } else { 711 long now = mClock.getElapsedSinceBootMillis(); 712 mDppMetrics.updateDppOperationTime((int) (now - mDppRequestInfo.startTime)); 713 714 NetworkUpdateResult networkUpdateResult = mWifiConfigManager 715 .addOrUpdateNetwork(newWifiConfiguration, mDppRequestInfo.uid); 716 717 if (networkUpdateResult.isSuccess()) { 718 mDppMetrics.updateDppEnrolleeSuccess(); 719 if (mDppRequestInfo.authRole == DPP_AUTH_ROLE_RESPONDER) { 720 mDppMetrics.updateDppEnrolleeResponderSuccess(); 721 } 722 mDppRequestInfo.connStatusRequested = connStatusRequested; 723 mDppRequestInfo.callback.onSuccessConfigReceived( 724 networkUpdateResult.getNetworkId()); 725 } else { 726 Log.e(TAG, "DPP configuration received, but failed to update network"); 727 mDppMetrics.updateDppFailure(EasyConnectStatusCallback 728 .EASY_CONNECT_EVENT_FAILURE_CONFIGURATION); 729 mDppRequestInfo.callback.onFailure(EasyConnectStatusCallback 730 .EASY_CONNECT_EVENT_FAILURE_CONFIGURATION, null, null, new int[0]); 731 } 732 } 733 } catch (RemoteException e) { 734 Log.e(TAG, "Callback failure"); 735 } 736 737 // Success 738 // If Peer configurator has not requested for connection status, 739 // DPP session is completed. Clear the DPP session immediately, otherwise wait for 740 // send connection status result 741 if (!mDppRequestInfo.connStatusRequested) { 742 cleanupDppResources(); 743 } else { 744 Log.d(TAG, "Wait " + (DPP_ENROLLEE_CONN_STATUS_RESULT_TX_TIMEOUT_MS / 1000) 745 + " seconds for enrollee to send connection status"); 746 mDppTimeoutMessage.cancel(); 747 mDppTimeoutMessage.schedule(mClock.getElapsedSinceBootMillis() 748 + DPP_ENROLLEE_CONN_STATUS_RESULT_TX_TIMEOUT_MS); 749 } 750 } 751 onSuccess(int dppStatusCode)752 private void onSuccess(int dppStatusCode) { 753 try { 754 if (mDppRequestInfo == null) { 755 Log.e(TAG, "onSuccess event without a request information object"); 756 return; 757 } 758 759 logd("onSuccess: " + dppStatusCode); 760 long now = mClock.getElapsedSinceBootMillis(); 761 mDppMetrics.updateDppOperationTime((int) (now - mDppRequestInfo.startTime)); 762 763 int dppSuccessCode; 764 765 // Convert from HAL codes to WifiManager/user codes 766 switch (dppStatusCode) { 767 case DppEventType.CONFIGURATION_SENT: 768 mDppMetrics.updateDppR1CapableEnrolleeResponderDevices(); 769 dppSuccessCode = EasyConnectStatusCallback 770 .EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT; 771 // For Configurator STA, generate self signed keys for network access. 772 generateSelfDppConfiguration(mDppRequestInfo.networkId); 773 break; 774 775 case DppEventType.CONFIGURATION_APPLIED: 776 dppSuccessCode = EasyConnectStatusCallback 777 .EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED; 778 break; 779 780 default: 781 Log.e(TAG, "onSuccess: unknown code " + dppStatusCode); 782 // Success, DPP is complete. Clear the DPP session automatically 783 mDppRequestInfo.isGeneratingSelfConfiguration = false; 784 cleanupDppResources(); 785 return; 786 } 787 788 mDppMetrics.updateDppConfiguratorSuccess(dppSuccessCode); 789 mDppRequestInfo.callback.onSuccess(dppSuccessCode); 790 791 } catch (RemoteException e) { 792 Log.e(TAG, "Callback failure"); 793 } 794 795 // Success, DPP is complete. Clear the DPP session automatically 796 cleanupDppResources(); 797 } 798 onProgress(int dppStatusCode)799 private void onProgress(int dppStatusCode) { 800 try { 801 if (mDppRequestInfo == null) { 802 Log.e(TAG, "onProgress event without a request information object"); 803 return; 804 } 805 806 logd("onProgress: " + dppStatusCode); 807 808 int dppProgressCode; 809 810 // Convert from HAL codes to WifiManager/user codes 811 switch (dppStatusCode) { 812 case DppProgressCode.AUTHENTICATION_SUCCESS: 813 dppProgressCode = EasyConnectStatusCallback 814 .EASY_CONNECT_EVENT_PROGRESS_AUTHENTICATION_SUCCESS; 815 break; 816 817 case DppProgressCode.RESPONSE_PENDING: 818 dppProgressCode = EasyConnectStatusCallback 819 .EASY_CONNECT_EVENT_PROGRESS_RESPONSE_PENDING; 820 break; 821 822 case DppProgressCode.CONFIGURATION_SENT_WAITING_RESPONSE: 823 mDppMetrics.updateDppR2CapableEnrolleeResponderDevices(); 824 dppProgressCode = EasyConnectStatusCallback 825 .EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_SENT_WAITING_RESPONSE; 826 break; 827 828 case DppProgressCode.CONFIGURATION_ACCEPTED: 829 dppProgressCode = EasyConnectStatusCallback 830 .EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_ACCEPTED; 831 break; 832 833 default: 834 Log.e(TAG, "onProgress: unknown code " + dppStatusCode); 835 return; 836 } 837 838 mDppRequestInfo.callback.onProgress(dppProgressCode); 839 840 } catch (RemoteException e) { 841 Log.e(TAG, "Callback failure"); 842 } 843 } 844 onFailure(int dppStatusCode)845 private void onFailure(int dppStatusCode) { 846 onFailure(dppStatusCode, null, null, null); 847 } 848 onDppConfiguratorKeyUpdate(byte[] privEcKey)849 private void onDppConfiguratorKeyUpdate(byte[] privEcKey) { 850 if (mDppRequestInfo == null) { 851 Log.e(TAG, 852 "onDppConfiguratorKeyUpdate event without a request information object"); 853 return; 854 } 855 856 WifiConfiguration selectedNetwork = mWifiConfigManager 857 .getConfiguredNetworkWithoutMasking(mDppRequestInfo.networkId); 858 859 if (selectedNetwork != null && privEcKey != null && privEcKey.length > 0 860 && selectedNetwork.isSecurityType(WifiConfiguration.SECURITY_TYPE_DPP)) { 861 Log.d(TAG, "Updating network access keys for DPP networkId=" 862 + mDppRequestInfo.networkId); 863 selectedNetwork.setDppConfigurator(privEcKey); 864 865 NetworkUpdateResult networkUpdateResult = mWifiConfigManager 866 .addOrUpdateNetwork(selectedNetwork, mDppRequestInfo.uid); 867 868 if (!networkUpdateResult.isSuccess()) { 869 Log.e(TAG, "Failed to update DPP configurator key."); 870 } 871 } 872 } 873 onConnectionStatusResultSent(int result)874 private void onConnectionStatusResultSent(int result) { 875 if (mDppRequestInfo == null) { 876 Log.e(TAG, 877 "onConnectionStatusResultSent event without a request information object"); 878 return; 879 } 880 logd("onConnectionStatusResultSent: result code: " + result); 881 cleanupDppResources(); 882 } 883 884 /** 885 * 886 * This function performs the Enrollee compatibility check with the network. 887 * Compatibilty check is done based on the channel match. 888 * The logic looks into the scan cache and checks if network's 889 * operating channel match with one of the channel in enrollee's scanned channel list. 890 * 891 * @param ssid Network name. 892 * @param channelList contains the list of operating class/channels enrollee used to search for 893 * the network. 894 * Reference: DPP spec section: DPP Connection Status Object section. 895 * (eg for channelList: "81/1,2,3,4,5,6,7,8,9,10,11,117/40,115/48") 896 * @return True On compatibility check failures due to error conditions or 897 * when AP is not seen in scan cache or when AP is seen in scan cache and 898 * operating channel is included in enrollee's scanned channel list. 899 * False when network's operating channel is not included in Enrollee's 900 * scanned channel list. 901 * 902 */ isEnrolleeCompatibleWithNetwork(String ssid, String channelList)903 private boolean isEnrolleeCompatibleWithNetwork(String ssid, String channelList) { 904 if (ssid == null || channelList == null) { 905 return true; 906 } 907 SparseArray<int[]> dppChannelList = WifiManager.parseDppChannelList(channelList); 908 909 if (dppChannelList.size() == 0) { 910 Log.d(TAG, "No channels found after parsing channel list string"); 911 return true; 912 } 913 914 List<Integer> freqList = new ArrayList<Integer>(); 915 916 /* Convert the received operatingClass/channels to list of frequencies */ 917 for (int i = 0; i < dppChannelList.size(); i++) { 918 /* Derive the band corresponding to operating class */ 919 int operatingClass = dppChannelList.keyAt(i); 920 int[] channels = dppChannelList.get(operatingClass); 921 int band = ApConfigUtil.getBandFromOperatingClass(operatingClass); 922 if (band < 0) { 923 Log.e(TAG, "Band corresponding to the operating class: " + operatingClass 924 + " not found in the table"); 925 continue; 926 } 927 /* Derive frequency list from channel and band */ 928 for (int j = 0; j < channels.length; j++) { 929 int freq = ApConfigUtil.convertChannelToFrequency(channels[j], band); 930 if (freq < 0) { 931 Log.e(TAG, "Invalid frequency after converting channel: " + channels[j] 932 + " band: " + band); 933 continue; 934 } 935 freqList.add(freq); 936 } 937 } 938 939 if (freqList.size() == 0) { 940 Log.d(TAG, "frequency list is empty"); 941 return true; 942 } 943 944 /* Check the scan cache for the network enrollee tried to find */ 945 boolean isNetworkInScanCache = false; 946 boolean channelMatch = false; 947 for (ScanResult scanResult : mScanRequestProxy.getScanResults()) { 948 if (!TextUtils.equals(ssid, scanResult.SSID)) { 949 continue; 950 } 951 isNetworkInScanCache = true; 952 if (freqList.contains(scanResult.frequency)) { 953 channelMatch = true; 954 break; 955 } 956 } 957 958 if (isNetworkInScanCache & !channelMatch) { 959 Log.d(TAG, "Optionally update the error code to " 960 + "ENROLLEE_FAILED_TO_SCAN_NETWORK_CHANNEL as enrollee didn't scan" 961 + "network's operating channel"); 962 mDppMetrics.updateDppR2EnrolleeResponderIncompatibleConfiguration(); 963 return false; 964 } 965 return true; 966 } 967 968 private @EasyConnectStatusCallback.EasyConnectFailureStatusCode int getFailureStatusCodeOnEnrolleeInCompatibleWithNetwork()969 getFailureStatusCodeOnEnrolleeInCompatibleWithNetwork() { 970 if (!SdkLevel.isAtLeastS() || mDppRequestInfo.packageName != null 971 && mWifiPermissionsUtil.isTargetSdkLessThan( 972 mDppRequestInfo.packageName, Build.VERSION_CODES.S, 973 mDppRequestInfo.uid)) { 974 return EasyConnectStatusCallback 975 .EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE; 976 } else { 977 return EasyConnectStatusCallback 978 .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_FAILED_TO_SCAN_NETWORK_CHANNEL; 979 } 980 } 981 onFailure(int dppStatusCode, String ssid, String channelList, int[] bandList)982 private void onFailure(int dppStatusCode, String ssid, String channelList, int[] bandList) { 983 try { 984 if (mDppRequestInfo == null) { 985 Log.e(TAG, "onFailure event without a request information object"); 986 return; 987 } 988 989 logd("OnFailure: " + dppStatusCode); 990 991 long now = mClock.getElapsedSinceBootMillis(); 992 mDppMetrics.updateDppOperationTime((int) (now - mDppRequestInfo.startTime)); 993 994 int dppFailureCode; 995 996 // Convert from HAL codes to WifiManager/user codes 997 switch (dppStatusCode) { 998 case DppFailureCode.INVALID_URI: 999 dppFailureCode = 1000 EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_URI; 1001 break; 1002 1003 case DppFailureCode.AUTHENTICATION: 1004 dppFailureCode = 1005 EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION; 1006 break; 1007 1008 case DppFailureCode.NOT_COMPATIBLE: 1009 dppFailureCode = 1010 EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE; 1011 break; 1012 1013 case DppFailureCode.CONFIGURATION: 1014 dppFailureCode = 1015 EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_CONFIGURATION; 1016 break; 1017 1018 case DppFailureCode.BUSY: 1019 dppFailureCode = EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_BUSY; 1020 break; 1021 1022 case DppFailureCode.TIMEOUT: 1023 dppFailureCode = EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_TIMEOUT; 1024 break; 1025 1026 case DppFailureCode.NOT_SUPPORTED: 1027 dppFailureCode = 1028 EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED; 1029 break; 1030 1031 case DppFailureCode.CANNOT_FIND_NETWORK: 1032 // This is the only case where channel list is populated, according to the 1033 // DPP spec section 6.3.5.2 DPP Connection Status Object 1034 if (isEnrolleeCompatibleWithNetwork(ssid, channelList)) { 1035 dppFailureCode = 1036 EasyConnectStatusCallback 1037 .EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK; 1038 } else { 1039 dppFailureCode = getFailureStatusCodeOnEnrolleeInCompatibleWithNetwork(); 1040 } 1041 break; 1042 1043 case DppFailureCode.ENROLLEE_AUTHENTICATION: 1044 dppFailureCode = EasyConnectStatusCallback 1045 .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION; 1046 break; 1047 1048 case DppFailureCode.CONFIGURATION_REJECTED: 1049 dppFailureCode = EasyConnectStatusCallback 1050 .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION; 1051 break; 1052 1053 case DppFailureCode.URI_GENERATION: 1054 if (SdkLevel.isAtLeastS()) { 1055 dppFailureCode = EasyConnectStatusCallback 1056 .EASY_CONNECT_EVENT_FAILURE_URI_GENERATION; 1057 } else { 1058 dppFailureCode = EasyConnectStatusCallback 1059 .EASY_CONNECT_EVENT_FAILURE_GENERIC; 1060 } 1061 break; 1062 1063 case DppFailureCode.FAILURE: 1064 default: 1065 dppFailureCode = EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_GENERIC; 1066 break; 1067 } 1068 1069 mDppMetrics.updateDppFailure(dppFailureCode); 1070 if (bandList == null) { 1071 bandList = new int[0]; 1072 } 1073 mDppRequestInfo.callback.onFailure(dppFailureCode, ssid, channelList, bandList); 1074 1075 } catch (RemoteException e) { 1076 Log.e(TAG, "Callback failure"); 1077 } 1078 1079 // All failures are fatal, clear the DPP session 1080 mDppRequestInfo.isGeneratingSelfConfiguration = false; 1081 cleanupDppResources(); 1082 } 1083 logd(String message)1084 private void logd(String message) { 1085 if (mVerboseLoggingEnabled) { 1086 Log.d(TAG, message, null); 1087 } 1088 } 1089 linkToDeath(DppRequestInfo dppRequestInfo)1090 private boolean linkToDeath(DppRequestInfo dppRequestInfo) { 1091 // register for binder death 1092 dppRequestInfo.dr = new IBinder.DeathRecipient() { 1093 @Override 1094 public void binderDied() { 1095 if (dppRequestInfo == null) { 1096 return; 1097 } 1098 1099 logd("binderDied: uid=" + dppRequestInfo.uid); 1100 1101 mHandler.post(() -> { 1102 // Clean up supplicant resource 1103 if (mDppRequestInfo == null) { 1104 Log.e(TAG, "binderDied event without a request information object"); 1105 return; 1106 } 1107 mDppRequestInfo.isGeneratingSelfConfiguration = false; 1108 1109 if (mDppRequestInfo.authRole == DPP_AUTH_ROLE_INITIATOR) { 1110 if (!mWifiNative.stopDppInitiator(mClientIfaceName)) { 1111 Log.e(TAG, "Failed to stop DPP Initiator"); 1112 } 1113 } 1114 cleanupDppResources(); 1115 }); 1116 } 1117 }; 1118 1119 try { 1120 dppRequestInfo.binder.linkToDeath(dppRequestInfo.dr, 0); 1121 } catch (RemoteException e) { 1122 Log.e(TAG, "Error on linkToDeath - " + e); 1123 dppRequestInfo.dr = null; 1124 return false; 1125 } 1126 1127 return true; 1128 } 1129 1130 @RequiresApi(Build.VERSION_CODES.S) convertEasyConnectCryptographyCurveToHidlDppCurve( @ifiManager.EasyConnectCryptographyCurve int curve)1131 private int convertEasyConnectCryptographyCurveToHidlDppCurve( 1132 @WifiManager.EasyConnectCryptographyCurve int curve) { 1133 switch (curve) { 1134 case WifiManager.EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP384R1: 1135 return DppCurve.SECP384R1; 1136 case WifiManager.EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP521R1: 1137 return DppCurve.SECP521R1; 1138 case WifiManager.EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP256R1: 1139 return DppCurve.BRAINPOOLP256R1; 1140 case WifiManager.EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP384R1: 1141 return DppCurve.BRAINPOOLP384R1; 1142 case WifiManager.EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP512R1: 1143 return DppCurve.BRAINPOOLP512R1; 1144 case WifiManager.EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1: 1145 default: 1146 return DppCurve.PRIME256V1; 1147 } 1148 } 1149 } 1150