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