content: /*
   * Copyright (C) 2017 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package android.telephony;
  
  import android.os.Parcel;
  import android.os.Parcelable;
  import java.util.Date;
  import android.util.Log;
  
  import java.security.KeyFactory;
  import java.security.NoSuchAlgorithmException;
  import java.security.PublicKey;
  import java.security.spec.InvalidKeySpecException;
  import java.security.spec.X509EncodedKeySpec;
  
  /**
   * Class to represent information sent by the carrier, which will be used to encrypt
   * the IMSI + IMPI. The ecryption is being done by WLAN, and the modem.
   *
   * @hide
   */
  public final class ImsiEncryptionInfo implements Parcelable {
  
      private static final String LOG_TAG = "ImsiEncryptionInfo";
  
  
      private final String mcc;
      private final String mnc;
      private final PublicKey publicKey;
      private final String keyIdentifier;
      private final int keyType;
      //Date-Time in UTC when the key will expire.
      private final Date expirationTime;
  
      public ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier,
                                byte[] key, Date expirationTime) {
          this(mcc, mnc, keyType, keyIdentifier, makeKeyObject(key), expirationTime);
      }
  
      public ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier,
                                PublicKey publicKey, Date expirationTime) {
          // todo need to validate that ImsiEncryptionInfo is being created with the correct params.
          //      Including validating that the public key is in "X.509" format. This will be done in
          //      a subsequent CL.
          this.mcc = mcc;
          this.mnc = mnc;
          this.keyType = keyType;
          this.publicKey = publicKey;
          this.keyIdentifier = keyIdentifier;
          this.expirationTime = expirationTime;
      }
  
      public ImsiEncryptionInfo(Parcel in) {
          int length = in.readInt();
          byte b[] = new byte[length];
          in.readByteArray(b);
          publicKey = makeKeyObject(b);
          mcc = in.readString();
          mnc = in.readString();
          keyIdentifier = in.readString();
          keyType = in.readInt();
          expirationTime = new Date(in.readLong());
      }
  
      public String getMnc() {
          return this.mnc;
      }
  
      public String getMcc() {
          return this.mcc;
      }
  
      public String getKeyIdentifier() {
          return this.keyIdentifier;
      }
  
      public int getKeyType() {
          return this.keyType;
      }
  
      public PublicKey getPublicKey() {
          return this.publicKey;
      }
  
      public Date getExpirationTime() {
          return this.expirationTime;
      }
  
      private static PublicKey makeKeyObject(byte[] publicKeyBytes) {
          try {
              X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(publicKeyBytes);
              return KeyFactory.getInstance("RSA").generatePublic(pubKeySpec);
          } catch (InvalidKeySpecException | NoSuchAlgorithmException ex) {
              Log.e(LOG_TAG, "Error makeKeyObject: unable to convert into PublicKey", ex);
          }
          throw new IllegalArgumentException();
      }
  
      /** Implement the Parcelable interface */
      @Override
      public int describeContents() {
          return 0;
      }
  
      public static final @android.annotation.NonNull Parcelable.Creator<ImsiEncryptionInfo> CREATOR =
              new Parcelable.Creator<ImsiEncryptionInfo>() {
                  @Override
                  public ImsiEncryptionInfo createFromParcel(Parcel in) {
                      return new ImsiEncryptionInfo(in);
                  }
  
                  @Override
                  public ImsiEncryptionInfo[] newArray(int size) {
                      return new ImsiEncryptionInfo[size];
                  }
              };
  
      @Override
      public void writeToParcel(Parcel dest, int flags) {
          byte[] b = publicKey.getEncoded();
          dest.writeInt(b.length);
          dest.writeByteArray(b);
          dest.writeString(mcc);
          dest.writeString(mnc);
          dest.writeString(keyIdentifier);
          dest.writeInt(keyType);
          dest.writeLong(expirationTime.getTime());
      }
  
      @Override
      public String toString(){
          return "[ImsiEncryptionInfo "
                  + "mcc=" + mcc
                  + "mnc=" + mnc
                  + "publicKey=" + publicKey
                  + ", keyIdentifier=" + keyIdentifier
                  + ", keyType=" + keyType
                  + ", expirationTime=" + expirationTime
                  + "]";
      }
  }
  