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
17package android.content.pm;
18
19import android.os.Parcel;
20import android.test.AndroidTestCase;
21
22import java.util.Arrays;
23
24import javax.crypto.SecretKey;
25import javax.crypto.spec.IvParameterSpec;
26import javax.crypto.spec.SecretKeySpec;
27
28public class ContainerEncryptionParamsTest extends AndroidTestCase {
29    private static final String ENC_ALGORITHM = "AES/CBC/PKCS7Padding";
30
31    private static final byte[] IV_BYTES = "FOOBAR".getBytes();
32
33    private static final IvParameterSpec ENC_PARAMS = new IvParameterSpec(IV_BYTES);
34
35    private static final byte[] ENC_KEY_BYTES = "abcd1234wxyz7890".getBytes();
36
37    private static final SecretKey ENC_KEY = new SecretKeySpec(ENC_KEY_BYTES, "RAW");
38
39    private static final String MAC_ALGORITHM = "HMAC-SHA1";
40
41    private static final byte[] MAC_KEY_BYTES = "4wxyzabcd1237890".getBytes();
42
43    private static final SecretKey MAC_KEY = new SecretKeySpec(MAC_KEY_BYTES, "RAW");
44
45    private static final byte[] MAC_TAG = "faketag".getBytes();
46
47    private static final int AUTHENTICATED_START = 5;
48
49    private static final int ENCRYPTED_START = 11;
50
51    private static final int DATA_END = 19;
52
53    public void testParcel() throws Exception {
54        ContainerEncryptionParams expected = new ContainerEncryptionParams(ENC_ALGORITHM,
55                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
56                ENCRYPTED_START, DATA_END);
57
58        Parcel parcel = Parcel.obtain();
59        expected.writeToParcel(parcel, 0);
60        parcel.setDataPosition(0);
61
62        ContainerEncryptionParams actual = ContainerEncryptionParams.CREATOR
63                .createFromParcel(parcel);
64
65        assertEquals(ENC_ALGORITHM, actual.getEncryptionAlgorithm());
66
67        if (!(actual.getEncryptionSpec() instanceof IvParameterSpec)) {
68            fail("encryption parameters should be IvParameterSpec");
69        } else {
70            IvParameterSpec actualParams = (IvParameterSpec) actual.getEncryptionSpec();
71            assertTrue(Arrays.equals(IV_BYTES, actualParams.getIV()));
72        }
73
74        assertEquals(ENC_KEY, actual.getEncryptionKey());
75
76        assertEquals(MAC_ALGORITHM, actual.getMacAlgorithm());
77
78        assertNull(actual.getMacSpec());
79
80        assertEquals(MAC_KEY, actual.getMacKey());
81
82        assertTrue(Arrays.equals(MAC_TAG, actual.getMacTag()));
83
84        assertEquals(AUTHENTICATED_START, actual.getAuthenticatedDataStart());
85
86        assertEquals(ENCRYPTED_START, actual.getEncryptedDataStart());
87
88        assertEquals(DATA_END, actual.getDataEnd());
89    }
90
91    public void testEquals_Success() throws Exception {
92        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
93                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
94                ENCRYPTED_START, DATA_END);
95
96        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
97                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
98                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
99                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
100                ENCRYPTED_START, DATA_END);
101
102        assertEquals(params1, params2);
103    }
104
105    public void testEquals_EncAlgo_Failure() throws Exception {
106        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
107                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
108                ENCRYPTED_START, DATA_END);
109
110        ContainerEncryptionParams params2 = new ContainerEncryptionParams(new String(
111                "AES-256/CBC/PKCS7Padding"), new IvParameterSpec(IV_BYTES.clone()),
112                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
113                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
114                ENCRYPTED_START, DATA_END);
115
116        assertFalse(params1.equals(params2));
117    }
118
119    public void testEquals_EncParams_Failure() throws Exception {
120        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
121                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
122                ENCRYPTED_START, DATA_END);
123
124        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
125                new String(ENC_ALGORITHM), new IvParameterSpec("BLAHBLAH".getBytes()),
126                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
127                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
128                ENCRYPTED_START, DATA_END);
129
130        assertFalse(params1.equals(params2));
131    }
132
133    public void testEquals_EncKey_Failure() throws Exception {
134        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
135                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
136                ENCRYPTED_START, DATA_END);
137
138        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
139                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
140                new SecretKeySpec("BLAHBLAH".getBytes(), "RAW"), new String(MAC_ALGORITHM), null,
141                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
142                ENCRYPTED_START, DATA_END);
143
144        assertFalse(params1.equals(params2));
145    }
146
147    public void testEquals_MacAlgo_Failure() throws Exception {
148        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
149                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
150                ENCRYPTED_START, DATA_END);
151
152        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
153                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
154                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), "BLAHBLAH", null,
155                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
156                ENCRYPTED_START, DATA_END);
157
158        assertFalse(params1.equals(params2));
159    }
160
161    public void testEquals_MacKey_Failure() throws Exception {
162        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
163                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
164                ENCRYPTED_START, DATA_END);
165
166        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
167                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
168                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
169                new SecretKeySpec("FAKE_MAC_KEY".getBytes(), "RAW"), MAC_TAG, AUTHENTICATED_START,
170                ENCRYPTED_START, DATA_END);
171
172        assertFalse(params1.equals(params2));
173    }
174
175    public void testEquals_MacTag_Failure() throws Exception {
176        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
177                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
178                ENCRYPTED_START, DATA_END);
179
180        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
181                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
182                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
183                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), "broken".getBytes(),
184                AUTHENTICATED_START, ENCRYPTED_START, DATA_END);
185
186        assertFalse(params1.equals(params2));
187    }
188
189    public void testEquals_AuthenticatedStart_Failure() throws Exception {
190        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
191                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
192                ENCRYPTED_START, DATA_END);
193
194        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
195                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
196                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
197                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START - 1,
198                ENCRYPTED_START, DATA_END);
199
200        assertFalse(params1.equals(params2));
201    }
202
203    public void testEquals_EncryptedStart_Failure() throws Exception {
204        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
205                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
206                ENCRYPTED_START, DATA_END);
207
208        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
209                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
210                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
211                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
212                ENCRYPTED_START - 1, DATA_END);
213
214        assertFalse(params1.equals(params2));
215    }
216
217    public void testEquals_DataEnd_Failure() throws Exception {
218        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
219                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
220                ENCRYPTED_START, DATA_END);
221
222        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
223                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
224                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
225                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
226                ENCRYPTED_START, DATA_END + 1);
227
228        assertFalse(params1.equals(params2));
229    }
230
231    public void testHashCode_Success() throws Exception {
232        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
233                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
234                ENCRYPTED_START, DATA_END);
235
236        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
237                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
238                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
239                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
240                ENCRYPTED_START, DATA_END);
241
242        assertEquals(params1.hashCode(), params2.hashCode());
243    }
244
245    public void testHashCode_EncAlgo_Failure() throws Exception {
246        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
247                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
248                ENCRYPTED_START, DATA_END);
249
250        ContainerEncryptionParams params2 = new ContainerEncryptionParams(new String(
251                "AES-256/CBC/PKCS7Padding"), new IvParameterSpec(IV_BYTES.clone()),
252                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
253                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
254                ENCRYPTED_START, DATA_END);
255
256        assertFalse(params1.hashCode() == params2.hashCode());
257    }
258
259    public void testHashCode_EncParams_Failure() throws Exception {
260        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
261                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
262                ENCRYPTED_START, DATA_END);
263
264        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
265                new String(ENC_ALGORITHM), new IvParameterSpec("BLAHBLAH".getBytes()),
266                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
267                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
268                ENCRYPTED_START, DATA_END);
269
270        assertFalse(params1.hashCode() == params2.hashCode());
271    }
272
273    public void testHashCode_EncKey_Failure() throws Exception {
274        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
275                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
276                ENCRYPTED_START, DATA_END);
277
278        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
279                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
280                new SecretKeySpec("BLAHBLAH".getBytes(), "RAW"), new String(MAC_ALGORITHM), null,
281                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
282                ENCRYPTED_START, DATA_END);
283
284        assertFalse(params1.hashCode() == params2.hashCode());
285    }
286
287    public void testHashCode_MacAlgo_Failure() throws Exception {
288        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
289                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
290                ENCRYPTED_START, DATA_END);
291
292        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
293                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
294                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), "BLAHBLAH", null,
295                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
296                ENCRYPTED_START, DATA_END);
297
298        assertFalse(params1.hashCode() == params2.hashCode());
299    }
300
301    public void testHashCode_MacKey_Failure() throws Exception {
302        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
303                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
304                ENCRYPTED_START, DATA_END);
305
306        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
307                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
308                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
309                new SecretKeySpec("FAKE_MAC_KEY".getBytes(), "RAW"), MAC_TAG, AUTHENTICATED_START,
310                ENCRYPTED_START, DATA_END);
311
312        assertFalse(params1.hashCode() == params2.hashCode());
313    }
314
315    public void testHashCode_MacTag_Failure() throws Exception {
316        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
317                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
318                ENCRYPTED_START, DATA_END);
319
320        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
321                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
322                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
323                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), "broken".getBytes(),
324                AUTHENTICATED_START, ENCRYPTED_START, DATA_END);
325
326        assertFalse(params1.hashCode() == params2.hashCode());
327    }
328
329    public void testHashCode_AuthenticatedStart_Failure() throws Exception {
330        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
331                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
332                ENCRYPTED_START, DATA_END);
333
334        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
335                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
336                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
337                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START - 1,
338                ENCRYPTED_START, DATA_END);
339
340        assertFalse(params1.hashCode() == params2.hashCode());
341    }
342
343    public void testHashCode_EncryptedStart_Failure() throws Exception {
344        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
345                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
346                ENCRYPTED_START, DATA_END);
347
348        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
349                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
350                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
351                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
352                ENCRYPTED_START - 1, DATA_END);
353
354        assertFalse(params1.hashCode() == params2.hashCode());
355    }
356
357    public void testHashCode_DataEnd_Failure() throws Exception {
358        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
359                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
360                ENCRYPTED_START, DATA_END);
361
362        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
363                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
364                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
365                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
366                ENCRYPTED_START, DATA_END + 1);
367
368        assertFalse(params1.hashCode() == params2.hashCode());
369    }
370}
371