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 50 /** @hide */ ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier, byte[] key, Date expirationTime)51 public ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier, 52 byte[] key, Date expirationTime) { 53 this(mcc, mnc, keyType, keyIdentifier, makeKeyObject(key), expirationTime); 54 } 55 56 /** @hide */ ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier, PublicKey publicKey, Date expirationTime)57 public ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier, 58 PublicKey publicKey, Date expirationTime) { 59 // todo need to validate that ImsiEncryptionInfo is being created with the correct params. 60 // Including validating that the public key is in "X.509" format. This will be done in 61 // a subsequent CL. 62 this.mcc = mcc; 63 this.mnc = mnc; 64 this.keyType = keyType; 65 this.publicKey = publicKey; 66 this.keyIdentifier = keyIdentifier; 67 this.expirationTime = expirationTime; 68 } 69 70 /** @hide */ ImsiEncryptionInfo(Parcel in)71 public ImsiEncryptionInfo(Parcel in) { 72 int length = in.readInt(); 73 byte b[] = new byte[length]; 74 in.readByteArray(b); 75 publicKey = makeKeyObject(b); 76 mcc = in.readString(); 77 mnc = in.readString(); 78 keyIdentifier = in.readString(); 79 keyType = in.readInt(); 80 expirationTime = new Date(in.readLong()); 81 } 82 83 /** @hide */ getMnc()84 public String getMnc() { 85 return this.mnc; 86 } 87 88 /** @hide */ getMcc()89 public String getMcc() { 90 return this.mcc; 91 } 92 93 /** 94 * Returns key identifier, a string that helps the authentication server to locate the 95 * private key to decrypt the permanent identity, or {@code null} when uavailable. 96 */ 97 @Nullable getKeyIdentifier()98 public String getKeyIdentifier() { 99 return this.keyIdentifier; 100 } 101 102 /** @hide */ getKeyType()103 public int getKeyType() { 104 return this.keyType; 105 } 106 107 /** 108 * Returns the carrier public key that is used for the IMSI encryption, 109 * or {@code null} when uavailable. 110 */ 111 @Nullable getPublicKey()112 public PublicKey getPublicKey() { 113 return this.publicKey; 114 } 115 116 /** @hide */ getExpirationTime()117 public Date getExpirationTime() { 118 return this.expirationTime; 119 } 120 makeKeyObject(byte[] publicKeyBytes)121 private static PublicKey makeKeyObject(byte[] publicKeyBytes) { 122 try { 123 X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(publicKeyBytes); 124 return KeyFactory.getInstance("RSA").generatePublic(pubKeySpec); 125 } catch (InvalidKeySpecException | NoSuchAlgorithmException ex) { 126 Log.e(LOG_TAG, "Error makeKeyObject: unable to convert into PublicKey", ex); 127 } 128 throw new IllegalArgumentException(); 129 } 130 131 /** Implement the Parcelable interface */ 132 @Override describeContents()133 public int describeContents() { 134 return 0; 135 } 136 137 public static final @NonNull Parcelable.Creator<ImsiEncryptionInfo> CREATOR = 138 new Parcelable.Creator<ImsiEncryptionInfo>() { 139 @Override 140 public ImsiEncryptionInfo createFromParcel(Parcel in) { 141 return new ImsiEncryptionInfo(in); 142 } 143 144 @Override 145 public ImsiEncryptionInfo[] newArray(int size) { 146 return new ImsiEncryptionInfo[size]; 147 } 148 }; 149 150 @Override writeToParcel(@onNull Parcel dest, int flags)151 public void writeToParcel(@NonNull Parcel dest, int flags) { 152 byte[] b = publicKey.getEncoded(); 153 dest.writeInt(b.length); 154 dest.writeByteArray(b); 155 dest.writeString(mcc); 156 dest.writeString(mnc); 157 dest.writeString(keyIdentifier); 158 dest.writeInt(keyType); 159 dest.writeLong(expirationTime.getTime()); 160 } 161 162 @Override toString()163 public String toString(){ 164 return "[ImsiEncryptionInfo " 165 + "mcc=" + mcc 166 + "mnc=" + mnc 167 + "publicKey=" + publicKey 168 + ", keyIdentifier=" + keyIdentifier 169 + ", keyType=" + keyType 170 + ", expirationTime=" + expirationTime 171 + "]"; 172 } 173 } 174