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