1 /* 2 * Copyright (C) 2017 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 package android.telephony; 17 18 import android.annotation.NonNull; 19 import android.annotation.Nullable; 20 import android.annotation.SystemApi; 21 import android.os.Parcel; 22 import android.os.Parcelable; 23 import android.util.Log; 24 25 import java.security.KeyFactory; 26 import java.security.NoSuchAlgorithmException; 27 import java.security.PublicKey; 28 import java.security.spec.InvalidKeySpecException; 29 import java.security.spec.X509EncodedKeySpec; 30 import java.util.Date; 31 32 /** 33 * Class to represent information sent by the carrier, which will be used to encrypt 34 * the IMSI + IMPI. The ecryption is being done by WLAN, and the modem. 35 * @hide 36 */ 37 @SystemApi 38 public final class ImsiEncryptionInfo implements Parcelable { 39 40 private static final String LOG_TAG = "ImsiEncryptionInfo"; 41 42 private final String mcc; 43 private final String mnc; 44 private final PublicKey publicKey; 45 private final String keyIdentifier; 46 private final int keyType; 47 //Date-Time in UTC when the key will expire. 48 private final Date expirationTime; 49 private final int carrierId; 50 51 /** @hide */ ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier, byte[] key, Date expirationTime, int carrierId)52 public ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier, 53 byte[] key, Date expirationTime, int carrierId) { 54 this(mcc, mnc, keyType, keyIdentifier, makeKeyObject(key), expirationTime, carrierId); 55 } 56 57 /** @hide */ ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier, PublicKey publicKey, Date expirationTime, int carrierId)58 public ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier, 59 PublicKey publicKey, Date expirationTime, int carrierId) { 60 // todo need to validate that ImsiEncryptionInfo is being created with the correct params. 61 // Including validating that the public key is in "X.509" format. This will be done in 62 // a subsequent CL. 63 this.mcc = mcc; 64 this.mnc = mnc; 65 this.keyType = keyType; 66 this.publicKey = publicKey; 67 this.keyIdentifier = keyIdentifier; 68 this.expirationTime = expirationTime; 69 this.carrierId = carrierId; 70 } 71 72 /** @hide */ ImsiEncryptionInfo(Parcel in)73 public ImsiEncryptionInfo(Parcel in) { 74 int length = in.readInt(); 75 byte b[] = new byte[length]; 76 in.readByteArray(b); 77 publicKey = makeKeyObject(b); 78 mcc = in.readString(); 79 mnc = in.readString(); 80 keyIdentifier = in.readString(); 81 keyType = in.readInt(); 82 expirationTime = new Date(in.readLong()); 83 carrierId = in.readInt(); 84 } 85 86 /** @hide */ getMnc()87 public String getMnc() { 88 return this.mnc; 89 } 90 91 /** @hide */ getMcc()92 public String getMcc() { 93 return this.mcc; 94 } 95 96 /** @hide */ getCarrierId()97 public int getCarrierId() { 98 return carrierId; 99 } 100 101 /** 102 * Returns key identifier, a string that helps the authentication server to locate the 103 * private key to decrypt the permanent identity, or {@code null} when uavailable. 104 */ 105 @Nullable getKeyIdentifier()106 public String getKeyIdentifier() { 107 return this.keyIdentifier; 108 } 109 110 /** @hide */ getKeyType()111 public int getKeyType() { 112 return this.keyType; 113 } 114 115 /** 116 * Returns the carrier public key that is used for the IMSI encryption, 117 * or {@code null} when uavailable. 118 */ 119 @Nullable getPublicKey()120 public PublicKey getPublicKey() { 121 return this.publicKey; 122 } 123 124 /** @hide */ getExpirationTime()125 public Date getExpirationTime() { 126 return this.expirationTime; 127 } 128 makeKeyObject(byte[] publicKeyBytes)129 private static PublicKey makeKeyObject(byte[] publicKeyBytes) { 130 try { 131 X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(publicKeyBytes); 132 return KeyFactory.getInstance("RSA").generatePublic(pubKeySpec); 133 } catch (InvalidKeySpecException | NoSuchAlgorithmException ex) { 134 Log.e(LOG_TAG, "Error makeKeyObject: unable to convert into PublicKey", ex); 135 } 136 throw new IllegalArgumentException(); 137 } 138 139 /** Implement the Parcelable interface */ 140 @Override describeContents()141 public int describeContents() { 142 return 0; 143 } 144 145 public static final @NonNull Parcelable.Creator<ImsiEncryptionInfo> CREATOR = 146 new Parcelable.Creator<ImsiEncryptionInfo>() { 147 @Override 148 public ImsiEncryptionInfo createFromParcel(Parcel in) { 149 return new ImsiEncryptionInfo(in); 150 } 151 152 @Override 153 public ImsiEncryptionInfo[] newArray(int size) { 154 return new ImsiEncryptionInfo[size]; 155 } 156 }; 157 158 @Override writeToParcel(@onNull Parcel dest, int flags)159 public void writeToParcel(@NonNull Parcel dest, int flags) { 160 byte[] b = publicKey.getEncoded(); 161 dest.writeInt(b.length); 162 dest.writeByteArray(b); 163 dest.writeString(mcc); 164 dest.writeString(mnc); 165 dest.writeString(keyIdentifier); 166 dest.writeInt(keyType); 167 dest.writeLong(expirationTime.getTime()); 168 dest.writeInt(carrierId); 169 } 170 171 @Override toString()172 public String toString(){ 173 return "[ImsiEncryptionInfo " 174 + "mcc=" + mcc 175 + " mnc=" + mnc 176 + ", publicKey=" + publicKey 177 + ", keyIdentifier=" + keyIdentifier 178 + ", keyType=" + keyType 179 + ", expirationTime=" + expirationTime 180 + ", carrier_id=" + carrierId 181 + "]"; 182 } 183 } 184