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