1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wifi;
18 
19 import android.annotation.NonNull;
20 import android.hardware.wifi.supplicant.GsmRand;
21 import android.hardware.wifi.supplicant.ISupplicantStaNetworkCallback;
22 import android.hardware.wifi.supplicant.NetworkRequestEapSimGsmAuthParams;
23 import android.hardware.wifi.supplicant.NetworkRequestEapSimUmtsAuthParams;
24 import android.hardware.wifi.supplicant.TransitionDisableIndication;
25 
26 import com.android.server.wifi.util.NativeUtil;
27 
28 import java.io.ByteArrayInputStream;
29 import java.io.InputStream;
30 import java.nio.ByteBuffer;
31 import java.nio.CharBuffer;
32 import java.nio.charset.CharacterCodingException;
33 import java.nio.charset.CharsetDecoder;
34 import java.nio.charset.StandardCharsets;
35 import java.security.cert.CertificateException;
36 import java.security.cert.CertificateFactory;
37 import java.security.cert.X509Certificate;
38 
39 class SupplicantStaNetworkCallbackAidlImpl extends ISupplicantStaNetworkCallback.Stub {
40     private static final String TAG = "SupplicantStaNetworkCallbackAidlImpl";
41     private final SupplicantStaNetworkHalAidlImpl mNetworkHal;
42     /**
43      * Current configured network's framework network id.
44      */
45     private final int mFrameworkNetworkId;
46     /**
47      * Current configured network's ssid.
48      */
49     private final String mSsid;
50     private final String mIfaceName;
51     private final WifiMonitor mWifiMonitor;
52     private final Object mLock;
53 
SupplicantStaNetworkCallbackAidlImpl( @onNull SupplicantStaNetworkHalAidlImpl networkHal, int frameworkNetworkId, @NonNull String ssid, @NonNull String ifaceName, @NonNull Object lock, @NonNull WifiMonitor wifiMonitor)54     SupplicantStaNetworkCallbackAidlImpl(
55             @NonNull SupplicantStaNetworkHalAidlImpl networkHal,
56             int frameworkNetworkId, @NonNull String ssid,
57             @NonNull String ifaceName, @NonNull Object lock, @NonNull WifiMonitor wifiMonitor) {
58         mNetworkHal = networkHal;
59         mFrameworkNetworkId = frameworkNetworkId;
60         mSsid = ssid;
61         mIfaceName = ifaceName;
62         mLock = lock;
63         mWifiMonitor = wifiMonitor;
64     }
65 
66     @Override
onNetworkEapSimGsmAuthRequest(NetworkRequestEapSimGsmAuthParams params)67     public void onNetworkEapSimGsmAuthRequest(NetworkRequestEapSimGsmAuthParams params) {
68         synchronized (mLock) {
69             mNetworkHal.logCallback("onNetworkEapSimGsmAuthRequest");
70             String[] data = new String[params.rands.length];
71             int i = 0;
72             for (GsmRand rand : params.rands) {
73                 data[i++] = NativeUtil.hexStringFromByteArray(rand.data);
74             }
75             mWifiMonitor.broadcastNetworkGsmAuthRequestEvent(
76                     mIfaceName, mFrameworkNetworkId, mSsid, data);
77         }
78     }
79 
80     @Override
onNetworkEapSimUmtsAuthRequest(NetworkRequestEapSimUmtsAuthParams params)81     public void onNetworkEapSimUmtsAuthRequest(NetworkRequestEapSimUmtsAuthParams params) {
82         synchronized (mLock) {
83             mNetworkHal.logCallback("onNetworkEapSimUmtsAuthRequest");
84             String randHex = NativeUtil.hexStringFromByteArray(params.rand);
85             String autnHex = NativeUtil.hexStringFromByteArray(params.autn);
86             String[] data = {randHex, autnHex};
87             mWifiMonitor.broadcastNetworkUmtsAuthRequestEvent(
88                     mIfaceName, mFrameworkNetworkId, mSsid, data);
89         }
90     }
91 
92     @Override
onNetworkEapIdentityRequest()93     public void onNetworkEapIdentityRequest() {
94         synchronized (mLock) {
95             mNetworkHal.logCallback("onNetworkEapIdentityRequest");
96             mWifiMonitor.broadcastNetworkIdentityRequestEvent(
97                     mIfaceName, mFrameworkNetworkId, mSsid);
98         }
99     }
100 
101     @Override
onTransitionDisable(int indicationBits)102     public void onTransitionDisable(int indicationBits) {
103         synchronized (mLock) {
104             mNetworkHal.logCallback("onTransitionDisable");
105             int frameworkBits = 0;
106             if ((indicationBits & TransitionDisableIndication.USE_WPA3_PERSONAL) != 0) {
107                 frameworkBits |= WifiMonitor.TDI_USE_WPA3_PERSONAL;
108             }
109             if ((indicationBits & TransitionDisableIndication.USE_SAE_PK) != 0) {
110                 frameworkBits |= WifiMonitor.TDI_USE_SAE_PK;
111             }
112             if ((indicationBits & TransitionDisableIndication.USE_WPA3_ENTERPRISE) != 0) {
113                 frameworkBits |= WifiMonitor.TDI_USE_WPA3_ENTERPRISE;
114             }
115             if ((indicationBits & TransitionDisableIndication.USE_ENHANCED_OPEN) != 0) {
116                 frameworkBits |= WifiMonitor.TDI_USE_ENHANCED_OPEN;
117             }
118             if (frameworkBits == 0) {
119                 return;
120             }
121 
122             mWifiMonitor.broadcastTransitionDisableEvent(
123                     mIfaceName, mFrameworkNetworkId, frameworkBits);
124         }
125     }
126 
byteArrayToString(byte[] byteArray)127     private String byteArrayToString(byte[] byteArray) {
128         // Not a valid bytes for a string
129         if (byteArray == null) return null;
130         CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
131         try {
132             CharBuffer decoded = decoder.decode(ByteBuffer.wrap(byteArray));
133             return decoded.toString();
134         } catch (CharacterCodingException cce) {
135         }
136         return null;
137     }
138 
139     @Override
onServerCertificateAvailable( int depth, byte[] subjectBytes, byte[] certHashBytes, byte[] certBytes)140     public void onServerCertificateAvailable(
141             int depth,
142             byte[] subjectBytes,
143             byte[] certHashBytes,
144             byte[] certBytes) {
145         synchronized (mLock) {
146             // OpenSSL default maximum depth is 100.
147             if (depth < 0 || depth > 100) {
148                 mNetworkHal.logCallback("onServerCertificateAvailable: invalid depth " + depth);
149                 return;
150             }
151             if (null == subjectBytes) {
152                 mNetworkHal.logCallback("onServerCertificateAvailable: subject is null.");
153                 return;
154             }
155             if (null == certHashBytes) {
156                 mNetworkHal.logCallback("onServerCertificateAvailable: cert hash is null.");
157                 return;
158             }
159             if (null == certBytes) {
160                 mNetworkHal.logCallback("onServerCertificateAvailable: cert is null.");
161                 return;
162             }
163 
164             mNetworkHal.logCallback("onServerCertificateAvailable: "
165                     + " depth=" + depth
166                     + " subjectBytes size=" + subjectBytes.length
167                     + " certHashBytes size=" + certHashBytes.length
168                     + " certBytes size=" + certBytes.length);
169 
170             if (0 == certHashBytes.length) return;
171             if (0 == certBytes.length) return;
172 
173             String subject = byteArrayToString(subjectBytes);
174             if (null == subject) {
175                 mNetworkHal.logCallback(
176                         "onServerCertificateAvailable: cannot convert subject bytes to string.");
177                 return;
178             }
179             String certHash = byteArrayToString(certHashBytes);
180             if (null == certHash) {
181                 mNetworkHal.logCallback(
182                         "onServerCertificateAvailable: cannot convert cert hash bytes to string.");
183                 return;
184             }
185             X509Certificate cert = null;
186             try {
187                 CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
188                 InputStream in = new ByteArrayInputStream(certBytes);
189                 cert = (X509Certificate) certFactory.generateCertificate(in);
190             } catch (CertificateException e) {
191                 cert = null;
192                 mNetworkHal.logCallback(
193                         "onServerCertificateAvailable: "
194                         + "Failed to get instance for CertificateFactory: " + e);
195             } catch (IllegalArgumentException e) {
196                 cert = null;
197                 mNetworkHal.logCallback(
198                         "onServerCertificateAvailable: Failed to decode the data: " + e);
199             }
200             if (null == cert) {
201                 mNetworkHal.logCallback(
202                         "onServerCertificateAvailable: Failed to read certificate.");
203                 return;
204             }
205 
206             mNetworkHal.logCallback("onServerCertificateAvailable:"
207                     + " depth=" + depth
208                     + " subject=" + subject
209                     + " certHash=" + certHash
210                     + " cert=" + cert);
211             mWifiMonitor.broadcastCertificationEvent(
212                     mIfaceName, mFrameworkNetworkId, mSsid, depth,
213                     new CertificateEventInfo(cert, certHash));
214         }
215     }
216 
217     @Override
onPermanentIdReqDenied()218     public void onPermanentIdReqDenied() {
219         mNetworkHal.logCallback("onPermanentIdReqDenied");
220 
221         mWifiMonitor.broadcastPermanentIdReqDenied(
222                 mIfaceName, mFrameworkNetworkId, mSsid);
223     }
224 
225     @Override
getInterfaceHash()226     public String getInterfaceHash() {
227         return ISupplicantStaNetworkCallback.HASH;
228     }
229 
230     @Override
getInterfaceVersion()231     public int getInterfaceVersion() {
232         return ISupplicantStaNetworkCallback.VERSION;
233     }
234 }
235