blob: ab3aa27cfeb61c29f52236525f670aeafc2df2ce [file] [log] [blame]
Todd Kennedy5cbeb592016-02-24 22:45:00 +00001/*
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
17package android.content.pm;
18
19import android.annotation.SystemApi;
20import android.os.Parcel;
21import android.os.Parcelable;
22import android.text.TextUtils;
23import android.util.Slog;
24
25import java.security.InvalidAlgorithmParameterException;
26import java.security.spec.AlgorithmParameterSpec;
27import java.util.Arrays;
28
29import javax.crypto.SecretKey;
30import 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
40public 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}