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 }