Home | History | Annotate | Download | only in pm
      1 /*
      2  * Copyright (C) 2012 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 
     17 package android.content.pm;
     18 
     19 import android.annotation.SystemApi;
     20 import android.os.Parcel;
     21 import android.os.Parcelable;
     22 import android.text.TextUtils;
     23 import android.util.Slog;
     24 
     25 import java.security.InvalidAlgorithmParameterException;
     26 import java.security.spec.AlgorithmParameterSpec;
     27 import java.util.Arrays;
     28 
     29 import javax.crypto.SecretKey;
     30 import javax.crypto.spec.IvParameterSpec;
     31 
     32 /**
     33  * Represents encryption parameters used to read a container.
     34  *
     35  * @deprecated encrypted containers are legacy.
     36  * @hide
     37  */
     38 @SystemApi
     39 @Deprecated
     40 public class ContainerEncryptionParams implements Parcelable {
     41     protected static final String TAG = "ContainerEncryptionParams";
     42 
     43     /** What we print out first when toString() is called. */
     44     private static final String TO_STRING_PREFIX = "ContainerEncryptionParams{";
     45 
     46     /**
     47      * Parameter type for parceling that indicates the next parameters are
     48      * IvParameters.
     49      */
     50     private static final int ENC_PARAMS_IV_PARAMETERS = 1;
     51 
     52     /** Parameter type for paceling that indicates there are no MAC parameters. */
     53     private static final int MAC_PARAMS_NONE = 1;
     54 
     55     /** The encryption algorithm used. */
     56     private final String mEncryptionAlgorithm;
     57 
     58     /** The parameter spec to be used for encryption. */
     59     private final IvParameterSpec mEncryptionSpec;
     60 
     61     /** Secret key to be used for decryption. */
     62     private final SecretKey mEncryptionKey;
     63 
     64     /** Algorithm name for the MAC to be used. */
     65     private final String mMacAlgorithm;
     66 
     67     /** The parameter spec to be used for the MAC tag authentication. */
     68     private final AlgorithmParameterSpec mMacSpec;
     69 
     70     /** Secret key to be used for MAC tag authentication. */
     71     private final SecretKey mMacKey;
     72 
     73     /** MAC tag authenticating the data in the container. */
     74     private final byte[] mMacTag;
     75 
     76     /** Offset into file where authenticated (e.g., MAC protected) data begins. */
     77     private final long mAuthenticatedDataStart;
     78 
     79     /** Offset into file where encrypted data begins. */
     80     private final long mEncryptedDataStart;
     81 
     82     /**
     83      * Offset into file for the end of encrypted data (and, by extension,
     84      * authenticated data) in file.
     85      */
     86     private final long mDataEnd;
     87 
     88     public ContainerEncryptionParams(String encryptionAlgorithm,
     89             AlgorithmParameterSpec encryptionSpec, SecretKey encryptionKey)
     90             throws InvalidAlgorithmParameterException {
     91         this(encryptionAlgorithm, encryptionSpec, encryptionKey, null, null, null, null, -1, -1,
     92                 -1);
     93     }
     94 
     95     /**
     96      * Creates container encryption specifications for installing from encrypted
     97      * containers.
     98      *
     99      * @param encryptionAlgorithm encryption algorithm to use; format matches
    100      *            JCE
    101      * @param encryptionSpec algorithm parameter specification
    102      * @param encryptionKey key used for decryption
    103      * @param macAlgorithm MAC algorithm to use; format matches JCE
    104      * @param macSpec algorithm parameters specification, may be {@code null}
    105      * @param macKey key used for authentication (i.e., for the MAC tag)
    106      * @param macTag message authentication code (MAC) tag for the authenticated
    107      *            data
    108      * @param authenticatedDataStart offset of start of authenticated data in
    109      *            stream
    110      * @param encryptedDataStart offset of start of encrypted data in stream
    111      * @param dataEnd offset of the end of both the authenticated and encrypted
    112      *            data
    113      * @throws InvalidAlgorithmParameterException
    114      */
    115     public ContainerEncryptionParams(String encryptionAlgorithm,
    116             AlgorithmParameterSpec encryptionSpec, SecretKey encryptionKey, String macAlgorithm,
    117             AlgorithmParameterSpec macSpec, SecretKey macKey, byte[] macTag,
    118             long authenticatedDataStart, long encryptedDataStart, long dataEnd)
    119             throws InvalidAlgorithmParameterException {
    120         if (TextUtils.isEmpty(encryptionAlgorithm)) {
    121             throw new NullPointerException("algorithm == null");
    122         } else if (encryptionSpec == null) {
    123             throw new NullPointerException("encryptionSpec == null");
    124         } else if (encryptionKey == null) {
    125             throw new NullPointerException("encryptionKey == null");
    126         }
    127 
    128         if (!TextUtils.isEmpty(macAlgorithm)) {
    129             if (macKey == null) {
    130                 throw new NullPointerException("macKey == null");
    131             }
    132         }
    133 
    134         if (!(encryptionSpec instanceof IvParameterSpec)) {
    135             throw new InvalidAlgorithmParameterException(
    136                     "Unknown parameter spec class; must be IvParameters");
    137         }
    138 
    139         mEncryptionAlgorithm = encryptionAlgorithm;
    140         mEncryptionSpec = (IvParameterSpec) encryptionSpec;
    141         mEncryptionKey = encryptionKey;
    142 
    143         mMacAlgorithm = macAlgorithm;
    144         mMacSpec = macSpec;
    145         mMacKey = macKey;
    146         mMacTag = macTag;
    147 
    148         mAuthenticatedDataStart = authenticatedDataStart;
    149         mEncryptedDataStart = encryptedDataStart;
    150         mDataEnd = dataEnd;
    151     }
    152 
    153     public String getEncryptionAlgorithm() {
    154         return mEncryptionAlgorithm;
    155     }
    156 
    157     public AlgorithmParameterSpec getEncryptionSpec() {
    158         return mEncryptionSpec;
    159     }
    160 
    161     public SecretKey getEncryptionKey() {
    162         return mEncryptionKey;
    163     }
    164 
    165     public String getMacAlgorithm() {
    166         return mMacAlgorithm;
    167     }
    168 
    169     public AlgorithmParameterSpec getMacSpec() {
    170         return mMacSpec;
    171     }
    172 
    173     public SecretKey getMacKey() {
    174         return mMacKey;
    175     }
    176 
    177     public byte[] getMacTag() {
    178         return mMacTag;
    179     }
    180 
    181     public long getAuthenticatedDataStart() {
    182         return mAuthenticatedDataStart;
    183     }
    184 
    185     public long getEncryptedDataStart() {
    186         return mEncryptedDataStart;
    187     }
    188 
    189     public long getDataEnd() {
    190         return mDataEnd;
    191     }
    192 
    193     @Override
    194     public int describeContents() {
    195         return 0;
    196     }
    197 
    198     @Override
    199     public boolean equals(Object o) {
    200         if (this == o) {
    201             return true;
    202         }
    203 
    204         if (!(o instanceof ContainerEncryptionParams)) {
    205             return false;
    206         }
    207 
    208         final ContainerEncryptionParams other = (ContainerEncryptionParams) o;
    209 
    210         // Primitive comparison
    211         if ((mAuthenticatedDataStart != other.mAuthenticatedDataStart)
    212                 || (mEncryptedDataStart != other.mEncryptedDataStart)
    213                 || (mDataEnd != other.mDataEnd)) {
    214             return false;
    215         }
    216 
    217         // String comparison
    218         if (!mEncryptionAlgorithm.equals(other.mEncryptionAlgorithm)
    219                 || !mMacAlgorithm.equals(other.mMacAlgorithm)) {
    220             return false;
    221         }
    222 
    223         // Object comparison
    224         if (!isSecretKeyEqual(mEncryptionKey, other.mEncryptionKey)
    225                 || !isSecretKeyEqual(mMacKey, other.mMacKey)) {
    226             return false;
    227         }
    228 
    229         if (!Arrays.equals(mEncryptionSpec.getIV(), other.mEncryptionSpec.getIV())
    230                 || !Arrays.equals(mMacTag, other.mMacTag) || (mMacSpec != other.mMacSpec)) {
    231             return false;
    232         }
    233 
    234         return true;
    235     }
    236 
    237     private static final boolean isSecretKeyEqual(SecretKey key1, SecretKey key2) {
    238         final String keyFormat = key1.getFormat();
    239         final String otherKeyFormat = key2.getFormat();
    240 
    241         if (keyFormat == null) {
    242             if (keyFormat != otherKeyFormat) {
    243                 return false;
    244             }
    245 
    246             if (key1.getEncoded() != key2.getEncoded()) {
    247                 return false;
    248             }
    249         } else {
    250             if (!keyFormat.equals(key2.getFormat())) {
    251                 return false;
    252             }
    253 
    254             if (!Arrays.equals(key1.getEncoded(), key2.getEncoded())) {
    255                 return false;
    256             }
    257         }
    258 
    259         return true;
    260     }
    261 
    262     @Override
    263     public int hashCode() {
    264         int hash = 3;
    265 
    266         hash += 5 * mEncryptionAlgorithm.hashCode();
    267         hash += 7 * Arrays.hashCode(mEncryptionSpec.getIV());
    268         hash += 11 * mEncryptionKey.hashCode();
    269         hash += 13 * mMacAlgorithm.hashCode();
    270         hash += 17 * mMacKey.hashCode();
    271         hash += 19 * Arrays.hashCode(mMacTag);
    272         hash += 23 * mAuthenticatedDataStart;
    273         hash += 29 * mEncryptedDataStart;
    274         hash += 31 * mDataEnd;
    275 
    276         return hash;
    277     }
    278 
    279     @Override
    280     public String toString() {
    281         final StringBuilder sb = new StringBuilder(TO_STRING_PREFIX);
    282 
    283         sb.append("mEncryptionAlgorithm=\"");
    284         sb.append(mEncryptionAlgorithm);
    285         sb.append("\",");
    286         sb.append("mEncryptionSpec=");
    287         sb.append(mEncryptionSpec.toString());
    288         sb.append("mEncryptionKey=");
    289         sb.append(mEncryptionKey.toString());
    290 
    291         sb.append("mMacAlgorithm=\"");
    292         sb.append(mMacAlgorithm);
    293         sb.append("\",");
    294         sb.append("mMacSpec=");
    295         sb.append(mMacSpec.toString());
    296         sb.append("mMacKey=");
    297         sb.append(mMacKey.toString());
    298 
    299         sb.append(",mAuthenticatedDataStart=");
    300         sb.append(mAuthenticatedDataStart);
    301         sb.append(",mEncryptedDataStart=");
    302         sb.append(mEncryptedDataStart);
    303         sb.append(",mDataEnd=");
    304         sb.append(mDataEnd);
    305         sb.append('}');
    306 
    307         return sb.toString();
    308     }
    309 
    310     @Override
    311     public void writeToParcel(Parcel dest, int flags) {
    312         dest.writeString(mEncryptionAlgorithm);
    313         dest.writeInt(ENC_PARAMS_IV_PARAMETERS);
    314         dest.writeByteArray(mEncryptionSpec.getIV());
    315         dest.writeSerializable(mEncryptionKey);
    316 
    317         dest.writeString(mMacAlgorithm);
    318         dest.writeInt(MAC_PARAMS_NONE);
    319         dest.writeByteArray(new byte[0]);
    320         dest.writeSerializable(mMacKey);
    321 
    322         dest.writeByteArray(mMacTag);
    323 
    324         dest.writeLong(mAuthenticatedDataStart);
    325         dest.writeLong(mEncryptedDataStart);
    326         dest.writeLong(mDataEnd);
    327     }
    328 
    329     private ContainerEncryptionParams(Parcel source) throws InvalidAlgorithmParameterException {
    330         mEncryptionAlgorithm = source.readString();
    331         final int encParamType = source.readInt();
    332         final byte[] encParamsEncoded = source.createByteArray();
    333         mEncryptionKey = (SecretKey) source.readSerializable();
    334 
    335         mMacAlgorithm = source.readString();
    336         final int macParamType = source.readInt();
    337         source.createByteArray(); // byte[] macParamsEncoded
    338         mMacKey = (SecretKey) source.readSerializable();
    339 
    340         mMacTag = source.createByteArray();
    341 
    342         mAuthenticatedDataStart = source.readLong();
    343         mEncryptedDataStart = source.readLong();
    344         mDataEnd = source.readLong();
    345 
    346         switch (encParamType) {
    347             case ENC_PARAMS_IV_PARAMETERS:
    348                 mEncryptionSpec = new IvParameterSpec(encParamsEncoded);
    349                 break;
    350             default:
    351                 throw new InvalidAlgorithmParameterException("Unknown parameter type "
    352                         + encParamType);
    353         }
    354 
    355         switch (macParamType) {
    356             case MAC_PARAMS_NONE:
    357                 mMacSpec = null;
    358                 break;
    359             default:
    360                 throw new InvalidAlgorithmParameterException("Unknown parameter type "
    361                         + macParamType);
    362         }
    363 
    364         if (mEncryptionKey == null) {
    365             throw new NullPointerException("encryptionKey == null");
    366         }
    367     }
    368 
    369     public static final Parcelable.Creator<ContainerEncryptionParams> CREATOR =
    370             new Parcelable.Creator<ContainerEncryptionParams>() {
    371         public ContainerEncryptionParams createFromParcel(Parcel source) {
    372             try {
    373                 return new ContainerEncryptionParams(source);
    374             } catch (InvalidAlgorithmParameterException e) {
    375                 Slog.e(TAG, "Invalid algorithm parameters specified", e);
    376                 return null;
    377             }
    378         }
    379 
    380         public ContainerEncryptionParams[] newArray(int size) {
    381             return new ContainerEncryptionParams[size];
    382         }
    383     };
    384 }