TelephonyUtil.java revision 259fb5a5265e0a2aa8a851d5e694d28afe9a87f2
13c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills/* 23c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * Copyright (C) 2016 The Android Open Source Project 33c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * 43c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * Licensed under the Apache License, Version 2.0 (the "License"); 53c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * you may not use this file except in compliance with the License. 63c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * You may obtain a copy of the License at 73c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * 83c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * http://www.apache.org/licenses/LICENSE-2.0 93c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * 103c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * Unless required by applicable law or agreed to in writing, software 113c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * distributed under the License is distributed on an "AS IS" BASIS, 123c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * See the License for the specific language governing permissions and 143c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * limitations under the License. 153c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills */ 163c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills 173c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Willspackage com.android.server.wifi.util; 183c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills 193c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Willsimport android.net.wifi.WifiConfiguration; 203c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Willsimport android.net.wifi.WifiEnterpriseConfig; 213c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Willsimport android.telephony.TelephonyManager; 22259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Willsimport android.util.Base64; 23259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Willsimport android.util.Log; 243c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills 253c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills/** 263c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * Utilities for the Wifi Service to interact with telephony. 273c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills */ 283c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Willspublic class TelephonyUtil { 29259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills public static final String TAG = "TelephonyUtil"; 303c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills 313c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills /** 323c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * Get the identity for the current SIM or null if the sim is not available 333c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills */ 34259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills public static String getSimIdentity(TelephonyManager tm, int eapMethod) { 35259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills if (tm == null) { 36259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.e(TAG, "No valid TelephonyManager"); 373c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills return null; 383c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills } 39259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills String imsi = tm.getSubscriberId(); 40259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills String mccMnc = ""; 41259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 42259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills if (tm.getSimState() == TelephonyManager.SIM_STATE_READY) { 43259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills mccMnc = tm.getSimOperator(); 44259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 45259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 46259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills return buildIdentity(eapMethod, imsi, mccMnc); 473c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills } 483c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills 493c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills /** 503c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * create Permanent Identity base on IMSI, 513c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * 523c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * rfc4186 & rfc4187: 533c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * identity = usernam@realm 543c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * with username = prefix | IMSI 553c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * and realm is derived MMC/MNC tuple according 3GGP spec(TS23.003) 563c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills */ 573c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills private static String buildIdentity(int eapMethod, String imsi, String mccMnc) { 583c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills if (imsi == null || imsi.isEmpty()) { 593c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills return null; 603c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills } 613c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills 623c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills String prefix; 633c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills if (eapMethod == WifiEnterpriseConfig.Eap.SIM) { 643c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills prefix = "1"; 653c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills } else if (eapMethod == WifiEnterpriseConfig.Eap.AKA) { 663c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills prefix = "0"; 673c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills } else if (eapMethod == WifiEnterpriseConfig.Eap.AKA_PRIME) { 683c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills prefix = "6"; 693c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills } else { // not a valide EapMethod 703c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills return null; 713c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills } 723c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills 733c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills /* extract mcc & mnc from mccMnc */ 743c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills String mcc; 753c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills String mnc; 763c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills if (mccMnc != null && !mccMnc.isEmpty()) { 773c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills mcc = mccMnc.substring(0, 3); 783c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills mnc = mccMnc.substring(3); 793c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills if (mnc.length() == 2) { 803c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills mnc = "0" + mnc; 813c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills } 823c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills } else { 833c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills // extract mcc & mnc from IMSI, assume mnc size is 3 843c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills mcc = imsi.substring(0, 3); 853c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills mnc = imsi.substring(3, 6); 863c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills } 873c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills 883c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills return prefix + imsi + "@wlan.mnc" + mnc + ".mcc" + mcc + ".3gppnetwork.org"; 893c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills } 903c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills 913c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills /** 923c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * Checks if the network is a sim config. 933c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * 943c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * @param config Config corresponding to the network. 953c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * @return true if it is a sim config, false otherwise. 963c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills */ 973c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills public static boolean isSimConfig(WifiConfiguration config) { 983c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills if (config == null || config.enterpriseConfig == null) { 993c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills return false; 1003c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills } 1013c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills 1023c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills return isSimEapMethod(config.enterpriseConfig.getEapMethod()); 1033c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills } 1043c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills 1053c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills /** 1063c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * Checks if the network is a sim config. 1073c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * 1083c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * @param method 1093c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills * @return true if it is a sim config, false otherwise. 1103c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills */ 1113c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills public static boolean isSimEapMethod(int eapMethod) { 1123c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills return eapMethod == WifiEnterpriseConfig.Eap.SIM 1133c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills || eapMethod == WifiEnterpriseConfig.Eap.AKA 1143c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills || eapMethod == WifiEnterpriseConfig.Eap.AKA_PRIME; 1153c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills } 116259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 117259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills // TODO replace some of this code with Byte.parseByte 118259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills private static int parseHex(char ch) { 119259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills if ('0' <= ch && ch <= '9') { 120259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills return ch - '0'; 121259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } else if ('a' <= ch && ch <= 'f') { 122259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills return ch - 'a' + 10; 123259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } else if ('A' <= ch && ch <= 'F') { 124259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills return ch - 'A' + 10; 125259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } else { 126259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills throw new NumberFormatException("" + ch + " is not a valid hex digit"); 127259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 128259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 129259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 130259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills private static byte[] parseHex(String hex) { 131259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills /* This only works for good input; don't throw bad data at it */ 132259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills if (hex == null) { 133259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills return new byte[0]; 134259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 135259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 136259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills if (hex.length() % 2 != 0) { 137259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills throw new NumberFormatException(hex + " is not a valid hex string"); 138259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 139259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 140259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills byte[] result = new byte[(hex.length()) / 2 + 1]; 141259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills result[0] = (byte) ((hex.length()) / 2); 142259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills for (int i = 0, j = 1; i < hex.length(); i += 2, j++) { 143259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills int val = parseHex(hex.charAt(i)) * 16 + parseHex(hex.charAt(i + 1)); 144259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills byte b = (byte) (val & 0xFF); 145259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills result[j] = b; 146259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 147259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 148259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills return result; 149259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 150259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 151259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills private static String makeHex(byte[] bytes) { 152259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills StringBuilder sb = new StringBuilder(); 153259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills for (byte b : bytes) { 154259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills sb.append(String.format("%02x", b)); 155259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 156259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills return sb.toString(); 157259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 158259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 159259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills private static String makeHex(byte[] bytes, int from, int len) { 160259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills StringBuilder sb = new StringBuilder(); 161259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills for (int i = 0; i < len; i++) { 162259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills sb.append(String.format("%02x", bytes[from + i])); 163259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 164259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills return sb.toString(); 165259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 166259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 167259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills private static byte[] concatHex(byte[] array1, byte[] array2) { 168259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 169259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills int len = array1.length + array2.length; 170259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 171259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills byte[] result = new byte[len]; 172259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 173259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills int index = 0; 174259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills if (array1.length != 0) { 175259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills for (byte b : array1) { 176259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills result[index] = b; 177259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills index++; 178259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 179259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 180259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 181259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills if (array2.length != 0) { 182259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills for (byte b : array2) { 183259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills result[index] = b; 184259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills index++; 185259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 186259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 187259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 188259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills return result; 189259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 190259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 191259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills public static String getGsmSimAuthResponse(String[] requestData, TelephonyManager tm) { 192259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills if (tm == null) { 193259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.e(TAG, "No valid TelephonyManager"); 194259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills return null; 195259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 196259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills StringBuilder sb = new StringBuilder(); 197259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills for (String challenge : requestData) { 198259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills if (challenge == null || challenge.isEmpty()) { 199259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills continue; 200259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 201259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.d(TAG, "RAND = " + challenge); 202259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 203259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills byte[] rand = null; 204259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills try { 205259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills rand = parseHex(challenge); 206259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } catch (NumberFormatException e) { 207259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.e(TAG, "malformed challenge"); 208259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills continue; 209259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 210259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 211259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills String base64Challenge = Base64.encodeToString(rand, Base64.NO_WRAP); 212259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 213259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills // Try USIM first for authentication. 214259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills String tmResponse = tm.getIccAuthentication(TelephonyManager.APPTYPE_USIM, 215259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills TelephonyManager.AUTHTYPE_EAP_SIM, base64Challenge); 216259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills if (tmResponse == null) { 217259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills // Then, in case of failure, issue may be due to sim type, retry as a simple sim 218259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills tmResponse = tm.getIccAuthentication(TelephonyManager.APPTYPE_SIM, 219259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills TelephonyManager.AUTHTYPE_EAP_SIM, base64Challenge); 220259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 221259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.v(TAG, "Raw Response - " + tmResponse); 222259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 223259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills if (tmResponse == null || tmResponse.length() <= 4) { 224259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.e(TAG, "bad response - " + tmResponse); 225259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills return null; 226259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 227259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 228259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills byte[] result = Base64.decode(tmResponse, Base64.DEFAULT); 229259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.v(TAG, "Hex Response -" + makeHex(result)); 230259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills int sresLen = result[0]; 231259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills if (sresLen >= result.length) { 232259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.e(TAG, "malfomed response - " + tmResponse); 233259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills return null; 234259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 235259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills String sres = makeHex(result, 1, sresLen); 236259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills int kcOffset = 1 + sresLen; 237259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills if (kcOffset >= result.length) { 238259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.e(TAG, "malfomed response - " + tmResponse); 239259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills return null; 240259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 241259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills int kcLen = result[kcOffset]; 242259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills if (kcOffset + kcLen > result.length) { 243259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.e(TAG, "malfomed response - " + tmResponse); 244259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills return null; 245259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 246259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills String kc = makeHex(result, 1 + kcOffset, kcLen); 247259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills sb.append(":" + kc + ":" + sres); 248259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.v(TAG, "kc:" + kc + " sres:" + sres); 249259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 250259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 251259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills return sb.toString(); 252259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 253259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 254259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills /** 255259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills * Data supplied when making a SIM Auth Request 256259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills */ 257259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills public static class SimAuthRequestData { 258259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills public SimAuthRequestData() {} 259259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills public SimAuthRequestData(int networkId, int protocol, String ssid, String[] data) { 260259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills this.networkId = networkId; 261259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills this.protocol = protocol; 262259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills this.ssid = ssid; 263259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills this.data = data; 264259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 265259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 266259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills public int networkId; 267259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills public int protocol; 268259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills public String ssid; 269259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills // EAP-SIM: data[] contains the 3 rand, one for each of the 3 challenges 270259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills // EAP-AKA/AKA': data[] contains rand & authn couple for the single challenge 271259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills public String[] data; 272259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 273259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 274259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills /** 275259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills * The response to a SIM Auth request if successful 276259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills */ 277259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills public static class SimAuthResponseData { 278259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills public SimAuthResponseData(String type, String response) { 279259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills this.type = type; 280259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills this.response = response; 281259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 282259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 283259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills public String type; 284259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills public String response; 285259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 286259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 287259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills public static SimAuthResponseData get3GAuthResponse(SimAuthRequestData requestData, 288259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills TelephonyManager tm) { 289259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills StringBuilder sb = new StringBuilder(); 290259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills byte[] rand = null; 291259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills byte[] authn = null; 292259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills String resType = "UMTS-AUTH"; 293259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 294259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills if (requestData.data.length == 2) { 295259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills try { 296259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills rand = parseHex(requestData.data[0]); 297259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills authn = parseHex(requestData.data[1]); 298259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } catch (NumberFormatException e) { 299259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.e(TAG, "malformed challenge"); 300259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 301259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } else { 302259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.e(TAG, "malformed challenge"); 303259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 304259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 305259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills String tmResponse = ""; 306259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills if (rand != null && authn != null) { 307259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills String base64Challenge = Base64.encodeToString(concatHex(rand, authn), Base64.NO_WRAP); 308259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills if (tm != null) { 309259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills tmResponse = tm.getIccAuthentication(TelephonyManager.APPTYPE_USIM, 310259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills TelephonyManager.AUTHTYPE_EAP_AKA, base64Challenge); 311259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.v(TAG, "Raw Response - " + tmResponse); 312259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } else { 313259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.e(TAG, "No valid TelephonyManager"); 314259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 315259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 316259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 317259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills boolean goodReponse = false; 318259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills if (tmResponse != null && tmResponse.length() > 4) { 319259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills byte[] result = Base64.decode(tmResponse, Base64.DEFAULT); 320259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.e(TAG, "Hex Response - " + makeHex(result)); 321259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills byte tag = result[0]; 322259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills if (tag == (byte) 0xdb) { 323259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.v(TAG, "successful 3G authentication "); 324259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills int resLen = result[1]; 325259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills String res = makeHex(result, 2, resLen); 326259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills int ckLen = result[resLen + 2]; 327259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills String ck = makeHex(result, resLen + 3, ckLen); 328259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills int ikLen = result[resLen + ckLen + 3]; 329259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills String ik = makeHex(result, resLen + ckLen + 4, ikLen); 330259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills sb.append(":" + ik + ":" + ck + ":" + res); 331259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.v(TAG, "ik:" + ik + "ck:" + ck + " res:" + res); 332259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills goodReponse = true; 333259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } else if (tag == (byte) 0xdc) { 334259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.e(TAG, "synchronisation failure"); 335259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills int autsLen = result[1]; 336259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills String auts = makeHex(result, 2, autsLen); 337259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills resType = "UMTS-AUTS"; 338259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills sb.append(":" + auts); 339259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.v(TAG, "auts:" + auts); 340259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills goodReponse = true; 341259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } else { 342259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.e(TAG, "bad response - unknown tag = " + tag); 343259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 344259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } else { 345259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.e(TAG, "bad response - " + tmResponse); 346259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 347259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills 348259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills if (goodReponse) { 349259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills String response = sb.toString(); 350259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills Log.v(TAG, "Supplicant Response -" + response); 351259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills return new SimAuthResponseData(resType, response); 352259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } else { 353259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills return null; 354259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 355259fb5a5265e0a2aa8a851d5e694d28afe9a87f2Mitchell Wills } 3563c8094ab45f3320dbe45e6460c5d62dcc24ce7aeMitchell Wills} 357