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