1 /* 2 * Copyright (C) 2023 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 android.telephony; 18 19 import android.annotation.FlaggedApi; 20 import android.annotation.IntDef; 21 import android.annotation.NonNull; 22 import android.annotation.SystemApi; 23 import android.annotation.TestApi; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 27 import com.android.internal.telephony.flags.Flags; 28 29 import java.lang.annotation.Retention; 30 import java.lang.annotation.RetentionPolicy; 31 import java.util.Objects; 32 33 /** 34 * A single occurrence of a cellular identifier being disclosed in the clear before a security 35 * context is established. 36 * 37 * @hide 38 */ 39 @SystemApi 40 @FlaggedApi(Flags.FLAG_CELLULAR_IDENTIFIER_DISCLOSURE_INDICATIONS) 41 public final class CellularIdentifierDisclosure implements Parcelable { 42 private static final String TAG = "CellularIdentifierDisclosure"; 43 44 /* Non-access stratum protocol messages */ 45 /** Unknown */ 46 public static final int NAS_PROTOCOL_MESSAGE_UNKNOWN = 0; 47 /** ATTACH REQUESTS. Sample reference: TS 24.301 8.2.4 Applies to 2g, 3g, and 4g networks */ 48 public static final int NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST = 1; 49 /** IDENTITY RESPONSE. Sample Reference: TS 24.301 8.2.19. 50 * Applies to 2g, 3g, 4g, and 5g networks */ 51 public static final int NAS_PROTOCOL_MESSAGE_IDENTITY_RESPONSE = 2; 52 /** DETACH_REQUEST. Sample Reference: TS 24.301 8.2.11. Applies to 2g, 3g, and 4g networks */ 53 public static final int NAS_PROTOCOL_MESSAGE_DETACH_REQUEST = 3; 54 /** TRACKING AREA UPDATE (TAU) REQUEST. Sample Reference: 3GPP TS 24.301 8.2.29. 55 * Note: that per the spec, only temporary IDs should be sent in the TAU Request, but since the 56 * EPS Mobile Identity field supports IMSIs, this is included as an extra safety measure to 57 * combat implementation bugs. Applies to 4g and 5g networks. */ 58 public static final int NAS_PROTOCOL_MESSAGE_TRACKING_AREA_UPDATE_REQUEST = 4; 59 /** LOCATION UPDATE REQUEST. Sample Reference: TS 24.008 4.4.3. Applies to 2g and 3g networks */ 60 public static final int NAS_PROTOCOL_MESSAGE_LOCATION_UPDATE_REQUEST = 5; 61 /** AUTHENTICATION AND CIPHERING RESPONSE. Reference: 3GPP TS 24.008 4.7.7.1. 62 * Applies to 2g and 3g networks */ 63 public static final int NAS_PROTOCOL_MESSAGE_AUTHENTICATION_AND_CIPHERING_RESPONSE = 6; 64 /** REGISTRATION REQUEST. Reference: 3GPP TS 24.501 8.2.6. Applies to 5g networks */ 65 public static final int NAS_PROTOCOL_MESSAGE_REGISTRATION_REQUEST = 7; 66 /** DEREGISTRATION REQUEST. Reference: 3GPP TS 24.501 8.2.12. Applies to 5g networks */ 67 public static final int NAS_PROTOCOL_MESSAGE_DEREGISTRATION_REQUEST = 8; 68 /** CONNECTION MANAGEMENT REESTABLISHMENT REQUEST. Reference: 3GPP TS 24.008 9.2.4. 69 * Applies to 2g and 3g networks */ 70 public static final int NAS_PROTOCOL_MESSAGE_CM_REESTABLISHMENT_REQUEST = 9; 71 /** CONNECTION MANAGEMENT SERVICE REQUEST. Reference: 3GPP TS 24.008 9.2.9. 72 * Applies to 2g and 3g networks */ 73 public static final int NAS_PROTOCOL_MESSAGE_CM_SERVICE_REQUEST = 10; 74 /** IMEI DETATCH INDICATION. Reference: 3GPP TS 24.008 9.2.14. 75 * Applies to 2g and 3g networks. Used for circuit-switched detach. */ 76 public static final int NAS_PROTOCOL_MESSAGE_IMSI_DETACH_INDICATION = 11; 77 /** Vendor-specific enumeration to identify a disclosure as potentially benign. 78 * Enables vendors to semantically classify disclosures based on their own logic. */ 79 @FlaggedApi(Flags.FLAG_VENDOR_SPECIFIC_CELLULAR_IDENTIFIER_DISCLOSURE_INDICATIONS) 80 public static final int NAS_PROTOCOL_MESSAGE_THREAT_IDENTIFIER_FALSE = 12; 81 /** Vendor-specific enumeration to identify a disclosure as potentially harmful. 82 * Enables vendors to semantically classify disclosures based on their own logic. */ 83 @FlaggedApi(Flags.FLAG_VENDOR_SPECIFIC_CELLULAR_IDENTIFIER_DISCLOSURE_INDICATIONS) 84 public static final int NAS_PROTOCOL_MESSAGE_THREAT_IDENTIFIER_TRUE = 13; 85 86 /** @hide */ 87 @Retention(RetentionPolicy.SOURCE) 88 @IntDef(prefix = {"NAS_PROTOCOL_MESSAGE_"}, value = {NAS_PROTOCOL_MESSAGE_UNKNOWN, 89 NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST, NAS_PROTOCOL_MESSAGE_IDENTITY_RESPONSE, 90 NAS_PROTOCOL_MESSAGE_DETACH_REQUEST, NAS_PROTOCOL_MESSAGE_TRACKING_AREA_UPDATE_REQUEST, 91 NAS_PROTOCOL_MESSAGE_LOCATION_UPDATE_REQUEST, 92 NAS_PROTOCOL_MESSAGE_AUTHENTICATION_AND_CIPHERING_RESPONSE, 93 NAS_PROTOCOL_MESSAGE_REGISTRATION_REQUEST, NAS_PROTOCOL_MESSAGE_DEREGISTRATION_REQUEST, 94 NAS_PROTOCOL_MESSAGE_CM_REESTABLISHMENT_REQUEST, 95 NAS_PROTOCOL_MESSAGE_CM_SERVICE_REQUEST, NAS_PROTOCOL_MESSAGE_IMSI_DETACH_INDICATION, 96 NAS_PROTOCOL_MESSAGE_THREAT_IDENTIFIER_FALSE, 97 NAS_PROTOCOL_MESSAGE_THREAT_IDENTIFIER_TRUE}) 98 public @interface NasProtocolMessage { 99 } 100 101 /* Cellular identifiers */ 102 /** Unknown */ 103 public static final int CELLULAR_IDENTIFIER_UNKNOWN = 0; 104 /** IMSI (International Mobile Subscriber Identity) */ 105 public static final int CELLULAR_IDENTIFIER_IMSI = 1; 106 /** IMEI (International Mobile Equipment Identity) */ 107 public static final int CELLULAR_IDENTIFIER_IMEI = 2; 108 /** 5G-specific SUCI (Subscription Concealed Identifier) */ 109 public static final int CELLULAR_IDENTIFIER_SUCI = 3; 110 111 /** @hide */ 112 @Retention(RetentionPolicy.SOURCE) 113 @IntDef(prefix = {"CELLULAR_IDENTIFIER_"}, value = {CELLULAR_IDENTIFIER_UNKNOWN, 114 CELLULAR_IDENTIFIER_IMSI, CELLULAR_IDENTIFIER_IMEI, CELLULAR_IDENTIFIER_SUCI}) 115 public @interface CellularIdentifier { 116 } 117 118 private @NasProtocolMessage int mNasProtocolMessage; 119 private @CellularIdentifier int mCellularIdentifier; 120 private String mPlmn; 121 private boolean mIsEmergency; 122 123 /** 124 * Constructor for new CellularIdentifierDisclosure instances. 125 * 126 * @hide 127 */ 128 @TestApi CellularIdentifierDisclosure(@asProtocolMessage int nasProtocolMessage, @CellularIdentifier int cellularIdentifier, @NonNull String plmn, boolean isEmergency)129 public CellularIdentifierDisclosure(@NasProtocolMessage int nasProtocolMessage, 130 @CellularIdentifier int cellularIdentifier, @NonNull String plmn, boolean isEmergency) { 131 mNasProtocolMessage = nasProtocolMessage; 132 mCellularIdentifier = cellularIdentifier; 133 mPlmn = plmn; 134 mIsEmergency = isEmergency; 135 } 136 CellularIdentifierDisclosure(Parcel in)137 private CellularIdentifierDisclosure(Parcel in) { 138 readFromParcel(in); 139 } 140 141 /** 142 * @return the NAS protocol message associated with the disclosed identifier. 143 */ getNasProtocolMessage()144 public @NasProtocolMessage int getNasProtocolMessage() { 145 return mNasProtocolMessage; 146 } 147 148 /** 149 * @return the identifier disclosed. 150 */ getCellularIdentifier()151 public @CellularIdentifier int getCellularIdentifier() { 152 return mCellularIdentifier; 153 } 154 155 /** 156 * @return the PLMN associated with the disclosure. 157 */ getPlmn()158 @NonNull public String getPlmn() { 159 return mPlmn; 160 } 161 162 /** 163 * @return if the disclosure is associated with an emergency call. 164 */ isEmergency()165 public boolean isEmergency() { 166 return mIsEmergency; 167 } 168 169 /** 170 * @return if the modem vendor classifies the disclosure as benign. 171 */ 172 @FlaggedApi(Flags.FLAG_VENDOR_SPECIFIC_CELLULAR_IDENTIFIER_DISCLOSURE_INDICATIONS) isBenign()173 public boolean isBenign() { 174 return mNasProtocolMessage == NAS_PROTOCOL_MESSAGE_THREAT_IDENTIFIER_FALSE; 175 } 176 177 @Override describeContents()178 public int describeContents() { 179 return 0; 180 } 181 182 @Override writeToParcel(@onNull Parcel out, int flags)183 public void writeToParcel(@NonNull Parcel out, int flags) { 184 out.writeInt(mNasProtocolMessage); 185 out.writeInt(mCellularIdentifier); 186 out.writeBoolean(mIsEmergency); 187 out.writeString8(mPlmn); 188 } 189 190 public static final @NonNull Parcelable.Creator<CellularIdentifierDisclosure> CREATOR = 191 new Parcelable.Creator<CellularIdentifierDisclosure>() { 192 public CellularIdentifierDisclosure createFromParcel(Parcel in) { 193 return new CellularIdentifierDisclosure(in); 194 } 195 196 public CellularIdentifierDisclosure[] newArray(int size) { 197 return new CellularIdentifierDisclosure[size]; 198 } 199 }; 200 201 @Override toString()202 public String toString() { 203 return TAG + ":{ mNasProtocolMessage = " + mNasProtocolMessage 204 + " mCellularIdentifier = " + mCellularIdentifier + " mIsEmergency = " 205 + mIsEmergency + " mPlmn = " + mPlmn; 206 } 207 208 @Override equals(Object o)209 public boolean equals(Object o) { 210 if (this == o) return true; 211 if (!(o instanceof CellularIdentifierDisclosure)) return false; 212 CellularIdentifierDisclosure that = (CellularIdentifierDisclosure) o; 213 return mNasProtocolMessage == that.mNasProtocolMessage 214 && mCellularIdentifier == that.mCellularIdentifier 215 && mIsEmergency == that.mIsEmergency && mPlmn.equals(that.mPlmn); 216 } 217 218 @Override hashCode()219 public int hashCode() { 220 return Objects.hash(mNasProtocolMessage, mCellularIdentifier, mIsEmergency, 221 mPlmn); 222 } 223 readFromParcel(@onNull Parcel in)224 private void readFromParcel(@NonNull Parcel in) { 225 mNasProtocolMessage = in.readInt(); 226 mCellularIdentifier = in.readInt(); 227 mIsEmergency = in.readBoolean(); 228 mPlmn = in.readString8(); 229 } 230 } 231