1 /*
2  * Copyright (C) 2020 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 package android.content.pm;
17 
18 import static android.content.pm.PackageParser.SigningDetails.CertCapabilities.AUTH;
19 import static android.content.pm.PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA;
20 import static android.content.pm.PackageParser.SigningDetails.CertCapabilities.PERMISSION;
21 import static android.content.pm.PackageParser.SigningDetails.CertCapabilities.ROLLBACK;
22 import static android.content.pm.PackageParser.SigningDetails.CertCapabilities.SHARED_USER_ID;
23 import static android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3;
24 
25 import static org.junit.Assert.assertEquals;
26 import static org.junit.Assert.assertFalse;
27 import static org.junit.Assert.assertTrue;
28 import static org.junit.Assert.fail;
29 
30 import android.content.pm.PackageParser.SigningDetails;
31 import android.util.ArraySet;
32 import android.util.PackageUtils;
33 
34 import androidx.test.ext.junit.runners.AndroidJUnit4;
35 import androidx.test.filters.SmallTest;
36 
37 import org.junit.Test;
38 import org.junit.runner.RunWith;
39 
40 import java.util.Set;
41 
42 @RunWith(AndroidJUnit4.class)
43 @SmallTest
44 public class SigningDetailsTest {
45     private static final int DEFAULT_CAPABILITIES =
46             INSTALLED_DATA | SHARED_USER_ID | PERMISSION | AUTH;
47 
48     // Some of the tests in this class require valid certificate encodings from which to pull the
49     // public key for the SigningDetails; the following are all DER encoded EC X.509 certificates.
50     private static final String FIRST_SIGNATURE =
51             "3082016c30820111a003020102020900ca0fb64dfb66e772300a06082a86"
52                     + "48ce3d04030230123110300e06035504030c0765632d70323536301e170d"
53                     + "3136303333313134353830365a170d3433303831373134353830365a3012"
54                     + "3110300e06035504030c0765632d703235363059301306072a8648ce3d02"
55                     + "0106082a8648ce3d03010703420004a65f113d22cb4913908307ac31ee2b"
56                     + "a0e9138b785fac6536d14ea2ce90d2b4bfe194b50cdc8e169f54a73a991e"
57                     + "f0fa76329825be078cc782740703da44b4d7eba350304e301d0603551d0e"
58                     + "04160414d4133568b95b30158b322071ea8c43ff5b05ccc8301f0603551d"
59                     + "23041830168014d4133568b95b30158b322071ea8c43ff5b05ccc8300c06"
60                     + "03551d13040530030101ff300a06082a8648ce3d04030203490030460221"
61                     + "00f504a0866caef029f417142c5cb71354c79ffcd1d640618dfca4f19e16"
62                     + "db78d6022100f8eea4829799c06cad08c6d3d2d2ec05e0574154e747ea0f"
63                     + "dbb8042cb655aadd";
64     private static final String SECOND_SIGNATURE =
65             "3082016d30820113a0030201020209008855bd1dd2b2b225300a06082a86"
66                     + "48ce3d04030230123110300e06035504030c0765632d70323536301e170d"
67                     + "3138303731333137343135315a170d3238303731303137343135315a3014"
68                     + "3112301006035504030c0965632d703235365f323059301306072a8648ce"
69                     + "3d020106082a8648ce3d030107034200041d4cca0472ad97ee3cecef0da9"
70                     + "3d62b450c6788333b36e7553cde9f74ab5df00bbba6ba950e68461d70bbc"
71                     + "271b62151dad2de2bf6203cd2076801c7a9d4422e1a350304e301d060355"
72                     + "1d0e041604147991d92b0208fc448bf506d4efc9fff428cb5e5f301f0603"
73                     + "551d23041830168014d4133568b95b30158b322071ea8c43ff5b05ccc830"
74                     + "0c0603551d13040530030101ff300a06082a8648ce3d0403020348003045"
75                     + "02202769abb1b49fc2f53479c4ae92a6631dabfd522c9acb0bba2b43ebeb"
76                     + "99c63011022100d260fb1d1f176cf9b7fa60098bfd24319f4905a3e5fda1"
77                     + "00a6fe1a2ab19ff09e";
78     private static final String THIRD_SIGNATURE =
79             "3082016e30820115a0030201020209008394f5cad16a89a7300a06082a86"
80                     + "48ce3d04030230143112301006035504030c0965632d703235365f32301e"
81                     + "170d3138303731343030303532365a170d3238303731313030303532365a"
82                     + "30143112301006035504030c0965632d703235365f333059301306072a86"
83                     + "48ce3d020106082a8648ce3d03010703420004f31e62430e9db6fc5928d9"
84                     + "75fc4e47419bacfcb2e07c89299e6cd7e344dd21adfd308d58cb49a1a2a3"
85                     + "fecacceea4862069f30be1643bcc255040d8089dfb3743a350304e301d06"
86                     + "03551d0e041604146f8d0828b13efaf577fc86b0e99fa3e54bcbcff0301f"
87                     + "0603551d230418301680147991d92b0208fc448bf506d4efc9fff428cb5e"
88                     + "5f300c0603551d13040530030101ff300a06082a8648ce3d040302034700"
89                     + "30440220256bdaa2784c273e4cc291a595a46779dee9de9044dc9f7ab820"
90                     + "309567df9fe902201a4ad8c69891b5a8c47434fe9540ed1f4979b5fad348"
91                     + "3f3fa04d5677355a579e";
92     private static final String FOURTH_SIGNATURE =
93             "3082017b30820120a00302010202146c8cb8a818433c1e6431fb16fb3ae0"
94                     + "fb5ad60aa7300a06082a8648ce3d04030230143112301006035504030c09"
95                     + "65632d703235365f33301e170d3230303531333139313532385a170d3330"
96                     + "303531313139313532385a30143112301006035504030c0965632d703235"
97                     + "365f343059301306072a8648ce3d020106082a8648ce3d03010703420004"
98                     + "db4a60031e79ad49cb759007d6855d4469b91c8bab065434f2fba971ade7"
99                     + "e4d19599a0f67b5e708cfda7543e5630c3769d37e093640d7c768a15144c"
100                     + "d0e5dcf4a350304e301d0603551d0e041604146e78970332554336b6ee89"
101                     + "24eaa70230e393f678301f0603551d230418301680146f8d0828b13efaf5"
102                     + "77fc86b0e99fa3e54bcbcff0300c0603551d13040530030101ff300a0608"
103                     + "2a8648ce3d0403020349003046022100ce786e79ec7547446082e9caf910"
104                     + "614ff80758f9819fb0f148695067abe0fcd4022100a4881e332ddec2116a"
105                     + "d2b59cf891d0f331ff7e27e77b7c6206c7988d9b539330";
106 
107     @Test
hasAncestor_multipleSignersInLineageWithAncestor_returnsTrue()108     public void hasAncestor_multipleSignersInLineageWithAncestor_returnsTrue() throws Exception {
109         SigningDetails twoSignersInLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
110                 SECOND_SIGNATURE, THIRD_SIGNATURE);
111         SigningDetails oneSignerInLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
112                 SECOND_SIGNATURE);
113 
114         boolean result = twoSignersInLineageDetails.hasAncestor(oneSignerInLineageDetails);
115 
116         assertTrue(result);
117     }
118 
119     @Test
hasAncestor_oneSignerInLineageAgainstMultipleSignersInLineage_returnsFalse()120     public void hasAncestor_oneSignerInLineageAgainstMultipleSignersInLineage_returnsFalse()
121             throws Exception {
122         SigningDetails twoSignersInLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
123                 SECOND_SIGNATURE, THIRD_SIGNATURE);
124         SigningDetails oneSignerInLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
125                 SECOND_SIGNATURE);
126 
127         boolean result = oneSignerInLineageDetails.hasAncestor(twoSignersInLineageDetails);
128 
129         assertFalse(result);
130     }
131 
132     @Test
hasAncestor_multipleSignersInLineageAgainstSelf_returnsFalse()133     public void hasAncestor_multipleSignersInLineageAgainstSelf_returnsFalse() throws Exception {
134         SigningDetails twoSignersInLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
135                 SECOND_SIGNATURE, THIRD_SIGNATURE);
136 
137         boolean result = twoSignersInLineageDetails.hasAncestor(twoSignersInLineageDetails);
138 
139         assertFalse(result);
140     }
141 
142     @Test
hasAncestor_oneSignerInLineageWithAncestor_returnsTrue()143     public void hasAncestor_oneSignerInLineageWithAncestor_returnsTrue() throws Exception {
144         SigningDetails twoSignersInLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
145                 SECOND_SIGNATURE, THIRD_SIGNATURE);
146         SigningDetails oneSignerDetails = createSigningDetails(FIRST_SIGNATURE);
147 
148         boolean result = twoSignersInLineageDetails.hasAncestor(oneSignerDetails);
149 
150         assertTrue(result);
151     }
152 
153     @Test
hasAncestor_singleSignerAgainstLineage_returnsFalse()154     public void hasAncestor_singleSignerAgainstLineage_returnsFalse() throws Exception {
155         SigningDetails oneSignerDetails = createSigningDetails(FIRST_SIGNATURE);
156         SigningDetails twoSignersInLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
157                 SECOND_SIGNATURE, THIRD_SIGNATURE);
158 
159         boolean result = oneSignerDetails.hasAncestor(twoSignersInLineageDetails);
160 
161         assertFalse(result);
162     }
163 
164     @Test
hasAncestor_multipleSigners_returnsFalse()165     public void hasAncestor_multipleSigners_returnsFalse() throws Exception {
166         SigningDetails twoSignersDetails = createSigningDetails(FIRST_SIGNATURE, SECOND_SIGNATURE);
167         SigningDetails twoSignersInLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
168                 SECOND_SIGNATURE, THIRD_SIGNATURE);
169 
170         boolean result1 = twoSignersInLineageDetails.hasAncestor(twoSignersDetails);
171         boolean result2 = twoSignersDetails.hasAncestor(twoSignersInLineageDetails);
172 
173         assertFalse(result1);
174         assertFalse(result2);
175     }
176 
177     @Test
hasAncestor_unknownDetails_returnsFalse()178     public void hasAncestor_unknownDetails_returnsFalse() throws Exception {
179         SigningDetails unknownDetails = SigningDetails.UNKNOWN;
180         SigningDetails twoSignersInLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
181                 SECOND_SIGNATURE, THIRD_SIGNATURE);
182 
183         boolean result1 = twoSignersInLineageDetails.hasAncestor(unknownDetails);
184         boolean result2 = unknownDetails.hasAncestor(twoSignersInLineageDetails);
185 
186         assertFalse(result1);
187         assertFalse(result2);
188     }
189 
190     @Test
mergeLineageWith_neitherHasLineage_returnsOriginal()191     public void mergeLineageWith_neitherHasLineage_returnsOriginal() throws Exception {
192         // When attempting to merge two instances of SigningDetails that do not have a lineage the
193         // initial object should be returned to indicate no changes were made.
194         SigningDetails noLineageDetails = createSigningDetails(FIRST_SIGNATURE);
195         SigningDetails otherNoLineageDetails = createSigningDetails(FIRST_SIGNATURE);
196 
197         SigningDetails result1 = noLineageDetails.mergeLineageWith(otherNoLineageDetails);
198         SigningDetails result2 = otherNoLineageDetails.mergeLineageWith(noLineageDetails);
199 
200         assertTrue(result1 == noLineageDetails);
201         assertTrue(result2 == otherNoLineageDetails);
202     }
203 
204     @Test
mergeLineageWith_oneHasNoLineage_returnsOther()205     public void mergeLineageWith_oneHasNoLineage_returnsOther() throws Exception {
206         // When attempting to merge a SigningDetails with no lineage with another that has a
207         // lineage and is a descendant the descendant SigningDetails with lineage should be returned
208         SigningDetails noLineageDetails = createSigningDetails(FIRST_SIGNATURE);
209         SigningDetails lineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
210                 SECOND_SIGNATURE);
211 
212         SigningDetails result1 = noLineageDetails.mergeLineageWith(lineageDetails);
213         SigningDetails result2 = lineageDetails.mergeLineageWith(noLineageDetails);
214 
215         assertSigningDetailsContainsLineage(result1, FIRST_SIGNATURE, SECOND_SIGNATURE);
216         assertSigningDetailsContainsLineage(result2, FIRST_SIGNATURE, SECOND_SIGNATURE);
217     }
218 
219     @Test
mergeLineageWith_bothHaveSameLineage_returnsOriginal()220     public void mergeLineageWith_bothHaveSameLineage_returnsOriginal() throws Exception {
221         // If twoSigningDetails instances have the exact same lineage with the same capabilities
222         // then the original instance should be returned without modification.
223         SigningDetails firstLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
224                 SECOND_SIGNATURE);
225         SigningDetails secondLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
226                 SECOND_SIGNATURE);
227 
228         SigningDetails result1 = firstLineageDetails.mergeLineageWith(secondLineageDetails);
229         SigningDetails result2 = secondLineageDetails.mergeLineageWith(firstLineageDetails);
230 
231         assertTrue(result1 == firstLineageDetails);
232         assertTrue(result2 == secondLineageDetails);
233     }
234 
235     @Test
mergeLineageWith_oneIsAncestorWithoutLineage_returnsDescendant()236     public void mergeLineageWith_oneIsAncestorWithoutLineage_returnsDescendant() throws Exception {
237         // If one instance without a lineage is an ancestor of the other then the descendant should
238         // be returned.
239         SigningDetails ancestorDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE);
240         SigningDetails descendantDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
241                 SECOND_SIGNATURE);
242 
243         SigningDetails result1 = ancestorDetails.mergeLineageWith(descendantDetails);
244         SigningDetails result2 = descendantDetails.mergeLineageWith(ancestorDetails);
245 
246         assertEquals(descendantDetails, result1);
247         assertTrue(result2 == descendantDetails);
248     }
249 
250     @Test
mergeLineageWith_oneIsAncestorWithLineage_returnsDescendant()251     public void mergeLineageWith_oneIsAncestorWithLineage_returnsDescendant() throws Exception {
252         // Similar to the above test if one instance with a lineage is an ancestor of the other then
253         // the descendant should be returned.
254         SigningDetails ancestorDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
255                 SECOND_SIGNATURE);
256         SigningDetails descendantDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
257                 SECOND_SIGNATURE, THIRD_SIGNATURE);
258 
259         SigningDetails result1 = ancestorDetails.mergeLineageWith(descendantDetails);
260         SigningDetails result2 = descendantDetails.mergeLineageWith(ancestorDetails);
261 
262         assertEquals(descendantDetails, result1);
263         assertTrue(result2 == descendantDetails);
264     }
265 
266     @Test
mergeLineageWith_singleSignerInMiddleOfLineage_returnsFullLineage()267     public void mergeLineageWith_singleSignerInMiddleOfLineage_returnsFullLineage()
268             throws Exception {
269         // If one instance without a lineage is an ancestor in the middle of the lineage for the
270         // descendant the descendant should be returned.
271         SigningDetails singleSignerDetails = createSigningDetails(SECOND_SIGNATURE);
272         SigningDetails fullLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
273                 SECOND_SIGNATURE, THIRD_SIGNATURE);
274 
275         SigningDetails result1 = singleSignerDetails.mergeLineageWith(fullLineageDetails);
276         SigningDetails result2 = fullLineageDetails.mergeLineageWith(singleSignerDetails);
277 
278         assertSigningDetailsContainsLineage(result1, FIRST_SIGNATURE, SECOND_SIGNATURE,
279                 THIRD_SIGNATURE);
280         assertSigningDetailsContainsLineage(result2, FIRST_SIGNATURE, SECOND_SIGNATURE,
281                 THIRD_SIGNATURE);
282     }
283 
284     @Test
mergeLineageWith_noCommonLineage_returnsOriginal()285     public void mergeLineageWith_noCommonLineage_returnsOriginal() throws Exception {
286         // While a call should never be made to merge two lineages without a common ancestor if it
287         // is attempted the original lineage should be returned.
288         SigningDetails firstLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
289                 SECOND_SIGNATURE);
290         SigningDetails secondLineageDetails = createSigningDetailsWithLineage(THIRD_SIGNATURE,
291                 FOURTH_SIGNATURE);
292 
293         SigningDetails result1 = firstLineageDetails.mergeLineageWith(secondLineageDetails);
294         SigningDetails result2 = secondLineageDetails.mergeLineageWith(firstLineageDetails);
295 
296         assertTrue(result1 == firstLineageDetails);
297         assertTrue(result2 == secondLineageDetails);
298     }
299 
300     @Test
mergeLineageWith_bothPartialLineages_returnsFullLineage()301     public void mergeLineageWith_bothPartialLineages_returnsFullLineage() throws Exception {
302         // This test verifies the following scenario:
303         // - One package is signed with a rotated key B and linage A -> B
304         // - The other package is signed with a rotated key C and lineage B -> C
305         // Merging the lineage of these two should return the full lineage A -> B -> C
306         SigningDetails firstLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
307                 SECOND_SIGNATURE);
308         SigningDetails secondLineageDetails = createSigningDetailsWithLineage(SECOND_SIGNATURE,
309                 THIRD_SIGNATURE);
310         SigningDetails expectedDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
311                 SECOND_SIGNATURE, THIRD_SIGNATURE);
312 
313         SigningDetails result1 = firstLineageDetails.mergeLineageWith(secondLineageDetails);
314         SigningDetails result2 = secondLineageDetails.mergeLineageWith(firstLineageDetails);
315 
316         assertEquals(expectedDetails, result1);
317         assertEquals(expectedDetails, result2);
318     }
319 
320     @Test
mergeLineageWith_oneSubsetLineage_returnsFullLineage()321     public void mergeLineageWith_oneSubsetLineage_returnsFullLineage() throws Exception {
322         // This test verifies when one lineage is a subset of the other the full lineage is
323         // returned.
324         SigningDetails subsetLineageDetails = createSigningDetailsWithLineage(SECOND_SIGNATURE,
325                 THIRD_SIGNATURE);
326         SigningDetails fullLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
327                 SECOND_SIGNATURE, THIRD_SIGNATURE, FOURTH_SIGNATURE);
328 
329         SigningDetails result1 = subsetLineageDetails.mergeLineageWith(fullLineageDetails);
330         SigningDetails result2 = fullLineageDetails.mergeLineageWith(subsetLineageDetails);
331 
332         assertEquals(fullLineageDetails, result1);
333         assertTrue(result2 == fullLineageDetails);
334     }
335 
336     @Test
mergeLineageWith_differentRootsOfTrust_returnsOriginal()337     public void mergeLineageWith_differentRootsOfTrust_returnsOriginal() throws Exception {
338         // If two SigningDetails share a common lineage but diverge at one of the ancestors then the
339         // merge should return the invoking instance since this is not supported.
340         SigningDetails firstLineageDetails = createSigningDetailsWithLineage("1234",
341                 FIRST_SIGNATURE, SECOND_SIGNATURE);
342         SigningDetails secondLineageDetails = createSigningDetailsWithLineage("5678",
343                 FIRST_SIGNATURE, SECOND_SIGNATURE, THIRD_SIGNATURE);
344 
345         SigningDetails result1 = firstLineageDetails.mergeLineageWith(secondLineageDetails);
346         SigningDetails result2 = secondLineageDetails.mergeLineageWith(firstLineageDetails);
347 
348         assertTrue(result1 == firstLineageDetails);
349         assertTrue(result2 == secondLineageDetails);
350     }
351 
352     @Test
mergeLineageWith_divergedSignerInLineage_returnsOriginal()353     public void mergeLineageWith_divergedSignerInLineage_returnsOriginal() throws Exception {
354         // Similar to the test above if two lineages diverge at any point then the merge should
355         // return the original since the signers in a sharedUserId must always be either the same,
356         // a subset, or a superset of the existing lineage.
357         SigningDetails firstLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
358                 "1234", SECOND_SIGNATURE, THIRD_SIGNATURE);
359         SigningDetails secondLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
360                 "5678", SECOND_SIGNATURE, THIRD_SIGNATURE);
361 
362         SigningDetails result1 = firstLineageDetails.mergeLineageWith(secondLineageDetails);
363         SigningDetails result2 = secondLineageDetails.mergeLineageWith(firstLineageDetails);
364 
365         assertTrue(result1 == firstLineageDetails);
366         assertTrue(result2 == secondLineageDetails);
367     }
368 
369     @Test
mergeLineageWith_sameLineageDifferentCaps_returnsLineageWithModifiedCaps()370     public void mergeLineageWith_sameLineageDifferentCaps_returnsLineageWithModifiedCaps()
371             throws Exception {
372         // This test verifies when two lineages consist of the same signers but have different
373         // capabilities the more restrictive capabilities are returned.
374         SigningDetails defaultCapabilitiesDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
375                 SECOND_SIGNATURE, THIRD_SIGNATURE);
376         SigningDetails modifiedCapabilitiesDetails = createSigningDetailsWithLineageAndCapabilities(
377                 new String[]{FIRST_SIGNATURE, SECOND_SIGNATURE, THIRD_SIGNATURE},
378                 new int[]{INSTALLED_DATA, INSTALLED_DATA, INSTALLED_DATA});
379 
380         SigningDetails result1 = defaultCapabilitiesDetails.mergeLineageWith(
381                 modifiedCapabilitiesDetails);
382         SigningDetails result2 = modifiedCapabilitiesDetails.mergeLineageWith(
383                 defaultCapabilitiesDetails);
384 
385         assertEquals(modifiedCapabilitiesDetails, result1);
386         assertTrue(result2 == modifiedCapabilitiesDetails);
387     }
388 
389     @Test
mergeLineageWith_overlappingLineageDiffCaps_returnsFullLineageWithModifiedCaps()390     public void mergeLineageWith_overlappingLineageDiffCaps_returnsFullLineageWithModifiedCaps()
391             throws Exception {
392         // This test verifies the following scenario:
393         // - First lineage has signers A -> B with modified capabilities for A and B
394         // - Second lineage has signers B -> C with modified capabilities for B and C
395         // The merged lineage should be A -> B -> C with the most restrictive capabilities for B
396         // since it is in both lineages.
397         int[] firstCapabilities =
398                 new int[]{INSTALLED_DATA | AUTH, INSTALLED_DATA | SHARED_USER_ID | PERMISSION};
399         int[] secondCapabilities = new int[]{INSTALLED_DATA | SHARED_USER_ID | AUTH,
400                 INSTALLED_DATA | SHARED_USER_ID | AUTH};
401         int[] expectedCapabilities =
402                 new int[]{firstCapabilities[0], firstCapabilities[1] & secondCapabilities[0],
403                         secondCapabilities[1]};
404         SigningDetails firstDetails = createSigningDetailsWithLineageAndCapabilities(
405                 new String[]{FIRST_SIGNATURE, SECOND_SIGNATURE}, firstCapabilities);
406         SigningDetails secondDetails = createSigningDetailsWithLineageAndCapabilities(
407                 new String[]{SECOND_SIGNATURE, THIRD_SIGNATURE}, secondCapabilities);
408         SigningDetails expectedDetails = createSigningDetailsWithLineageAndCapabilities(
409                 new String[]{FIRST_SIGNATURE, SECOND_SIGNATURE, THIRD_SIGNATURE},
410                 expectedCapabilities);
411 
412         SigningDetails result1 = firstDetails.mergeLineageWith(secondDetails);
413         SigningDetails result2 = secondDetails.mergeLineageWith(firstDetails);
414 
415         assertEquals(expectedDetails, result1);
416         assertEquals(expectedDetails, result2);
417     }
418 
419     @Test
mergeLineageWith_subLineageModifiedCaps_returnsFullLineageWithModifiedCaps()420     public void mergeLineageWith_subLineageModifiedCaps_returnsFullLineageWithModifiedCaps()
421             throws Exception {
422         // This test verifies the following scenario:
423         // - First lineage has signers B -> C with modified capabilities
424         // - Second lineage has signers A -> B -> C -> D with modified capabilities
425         // The merged lineage should be A -> B -> C -> D with the most restrictive capabilities for
426         // B and C since they are in both lineages.
427         int[] subCapabilities = new int[]{INSTALLED_DATA | SHARED_USER_ID | PERMISSION,
428                 DEFAULT_CAPABILITIES | ROLLBACK};
429         int[] fullCapabilities =
430                 new int[]{0, SHARED_USER_ID, DEFAULT_CAPABILITIES, DEFAULT_CAPABILITIES};
431         int[] expectedCapabilities =
432                 new int[]{fullCapabilities[0], subCapabilities[0] & fullCapabilities[1],
433                         subCapabilities[1] & fullCapabilities[2], fullCapabilities[3]};
434         SigningDetails subLineageDetails = createSigningDetailsWithLineageAndCapabilities(
435                 new String[]{SECOND_SIGNATURE, THIRD_SIGNATURE}, subCapabilities);
436         SigningDetails fullLineageDetails = createSigningDetailsWithLineageAndCapabilities(
437                 new String[]{FIRST_SIGNATURE, SECOND_SIGNATURE, THIRD_SIGNATURE, FOURTH_SIGNATURE},
438                 fullCapabilities);
439         SigningDetails expectedDetails = createSigningDetailsWithLineageAndCapabilities(
440                 new String[]{FIRST_SIGNATURE, SECOND_SIGNATURE, THIRD_SIGNATURE, FOURTH_SIGNATURE},
441                 expectedCapabilities);
442 
443         SigningDetails result1 = subLineageDetails.mergeLineageWith(fullLineageDetails);
444         SigningDetails result2 = fullLineageDetails.mergeLineageWith(subLineageDetails);
445 
446         assertEquals(expectedDetails, result1);
447         assertEquals(expectedDetails, result2);
448     }
449 
450     @Test
mergeLineageWith_commonLineageDivergedSigners_returnsOriginal()451     public void mergeLineageWith_commonLineageDivergedSigners_returnsOriginal() throws Exception {
452         // When mergeWithLineage is invoked with SigningDetails instances that have a common lineage
453         // but diverged signers the calling instance should be returned since the current signer
454         // is not in the ancestry of the other's lineage.
455         SigningDetails firstLineageDetails = createSigningDetails(FIRST_SIGNATURE, SECOND_SIGNATURE,
456                 THIRD_SIGNATURE);
457         SigningDetails secondLineageDetails = createSigningDetails(FIRST_SIGNATURE,
458                 SECOND_SIGNATURE, FOURTH_SIGNATURE);
459 
460         SigningDetails result1 = firstLineageDetails.mergeLineageWith(secondLineageDetails);
461         SigningDetails result2 = secondLineageDetails.mergeLineageWith(firstLineageDetails);
462 
463         assertTrue(result1 == firstLineageDetails);
464         assertTrue(result2 == secondLineageDetails);
465     }
466 
467     @Test
hasCommonAncestor_noLineageSameSingleSigner_returnsTrue()468     public void hasCommonAncestor_noLineageSameSingleSigner_returnsTrue() throws Exception {
469         // If neither SigningDetails have a lineage but they have the same single signer then
470         // hasCommonAncestor should return true.
471         SigningDetails firstDetails = createSigningDetails(FIRST_SIGNATURE);
472         SigningDetails secondDetails = createSigningDetails(FIRST_SIGNATURE);
473 
474         assertTrue(firstDetails.hasCommonAncestor(secondDetails));
475         assertTrue(secondDetails.hasCommonAncestor(firstDetails));
476     }
477 
478     @Test
hasCommonAncestor_noLineageSameMultipleSigners_returnsTrue()479     public void hasCommonAncestor_noLineageSameMultipleSigners_returnsTrue() throws Exception {
480         // Similar to above if neither SigningDetails have a lineage but they have the same multiple
481         // signers then hasCommonAncestor should return true.
482         SigningDetails firstDetails = createSigningDetails(FIRST_SIGNATURE, SECOND_SIGNATURE);
483         SigningDetails secondDetails = createSigningDetails(SECOND_SIGNATURE, FIRST_SIGNATURE);
484 
485         assertTrue(firstDetails.hasCommonAncestor(secondDetails));
486         assertTrue(secondDetails.hasCommonAncestor(firstDetails));
487     }
488 
489     @Test
hasCommonAncestor_noLineageDifferentSigners_returnsFalse()490     public void hasCommonAncestor_noLineageDifferentSigners_returnsFalse() throws Exception {
491         // If neither SigningDetails have a lineage and they have different signers then
492         // hasCommonAncestor should return false.
493         SigningDetails firstDetails = createSigningDetails(FIRST_SIGNATURE);
494         SigningDetails secondDetails = createSigningDetails(SECOND_SIGNATURE);
495         SigningDetails thirdDetails = createSigningDetails(FIRST_SIGNATURE, SECOND_SIGNATURE);
496         SigningDetails fourthDetails = createSigningDetails(SECOND_SIGNATURE, THIRD_SIGNATURE);
497 
498         assertFalse(firstDetails.hasCommonAncestor(secondDetails));
499         assertFalse(firstDetails.hasCommonAncestor(thirdDetails));
500         assertFalse(firstDetails.hasCommonAncestor(fourthDetails));
501         assertFalse(secondDetails.hasCommonAncestor(firstDetails));
502         assertFalse(secondDetails.hasCommonAncestor(thirdDetails));
503         assertFalse(secondDetails.hasCommonAncestor(fourthDetails));
504         assertFalse(thirdDetails.hasCommonAncestor(firstDetails));
505         assertFalse(thirdDetails.hasCommonAncestor(secondDetails));
506         assertFalse(thirdDetails.hasCommonAncestor(fourthDetails));
507         assertFalse(fourthDetails.hasCommonAncestor(firstDetails));
508         assertFalse(fourthDetails.hasCommonAncestor(secondDetails));
509         assertFalse(fourthDetails.hasCommonAncestor(thirdDetails));
510     }
511 
512     @Test
hasCommonAncestor_oneWithOthersSignerInLineage_returnsTrue()513     public void hasCommonAncestor_oneWithOthersSignerInLineage_returnsTrue() throws Exception {
514         // If only one of the SigningDetails has a lineage and the current signer of the other is in
515         // the lineage then hasCommonAncestor should return true.
516         SigningDetails noLineageDetails = createSigningDetails(FIRST_SIGNATURE);
517         SigningDetails lineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
518                 SECOND_SIGNATURE);
519 
520         assertTrue(noLineageDetails.hasCommonAncestor(lineageDetails));
521         assertTrue(lineageDetails.hasCommonAncestor(noLineageDetails));
522     }
523 
524     @Test
hasCommonAncestor_oneWithSameSignerWithoutLineage_returnsTrue()525     public void hasCommonAncestor_oneWithSameSignerWithoutLineage_returnsTrue() throws Exception {
526         // If only one of the SigningDetails has a lineage and both have the same current signer
527         // then hasCommonAncestor should return true.
528         SigningDetails noLineageDetails = createSigningDetails(SECOND_SIGNATURE);
529         SigningDetails lineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
530                 SECOND_SIGNATURE);
531 
532         assertTrue(noLineageDetails.hasCommonAncestor(lineageDetails));
533         assertTrue(lineageDetails.hasCommonAncestor(noLineageDetails));
534     }
535 
536     @Test
hasCommonAncestor_bothHaveSameLineage_returnsTrue()537     public void hasCommonAncestor_bothHaveSameLineage_returnsTrue() throws Exception {
538         // If both SigningDetails have the exact same lineage then hasCommonAncestor should return
539         // true.
540         SigningDetails firstDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
541                 SECOND_SIGNATURE);
542         SigningDetails secondDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
543                 SECOND_SIGNATURE);
544 
545         assertTrue(firstDetails.hasCommonAncestor(secondDetails));
546         assertTrue(secondDetails.hasCommonAncestor(firstDetails));
547     }
548 
549     @Test
hasCommonAncestor_oneLineageIsAncestor_returnsTrue()550     public void hasCommonAncestor_oneLineageIsAncestor_returnsTrue() throws Exception {
551         // If one SigningDetails has a lineage that is an ancestor of the other then
552         // hasCommonAncestor should return true.
553         SigningDetails ancestorDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
554                 SECOND_SIGNATURE);
555         SigningDetails descendantDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
556                 SECOND_SIGNATURE, THIRD_SIGNATURE);
557 
558         assertTrue(ancestorDetails.hasCommonAncestor(descendantDetails));
559         assertTrue(descendantDetails.hasCommonAncestor(ancestorDetails));
560     }
561 
562     @Test
hasCommonAncestor_oneLineageIsSubset_returnsTrue()563     public void hasCommonAncestor_oneLineageIsSubset_returnsTrue() throws Exception {
564         // If one SigningDetails has a lineage that is a subset of the other then hasCommonAncestor
565         // should return true.
566         SigningDetails subsetDetails = createSigningDetailsWithLineage(SECOND_SIGNATURE,
567                 THIRD_SIGNATURE);
568         SigningDetails fullDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
569                 SECOND_SIGNATURE, THIRD_SIGNATURE, FOURTH_SIGNATURE);
570 
571         assertTrue(subsetDetails.hasCommonAncestor(fullDetails));
572         assertTrue(fullDetails.hasCommonAncestor(subsetDetails));
573     }
574 
575     @Test
hasCommonAncestor_differentRootOfTrustInLineage_returnsFalse()576     public void hasCommonAncestor_differentRootOfTrustInLineage_returnsFalse() throws Exception {
577         // if the two SigningDetails have a different root of trust then hasCommonAncestor should
578         // return false.
579         SigningDetails firstDetails = createSigningDetailsWithLineage(THIRD_SIGNATURE,
580                 FIRST_SIGNATURE, SECOND_SIGNATURE);
581         SigningDetails secondDetails = createSigningDetailsWithLineage(FOURTH_SIGNATURE,
582                 FIRST_SIGNATURE, SECOND_SIGNATURE);
583 
584         assertFalse(firstDetails.hasCommonAncestor(secondDetails));
585         assertFalse(secondDetails.hasCommonAncestor(firstDetails));
586     }
587 
588     @Test
hasCommonAncestor_differentSignerInMiddleOfLineage_returnsFalse()589     public void hasCommonAncestor_differentSignerInMiddleOfLineage_returnsFalse() throws Exception {
590         // if the two SigningDetails have a different signer in the middle of a common lineage then
591         // hasCommonAncestor should return false.
592         SigningDetails firstDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE, "1234",
593                 SECOND_SIGNATURE, THIRD_SIGNATURE);
594         SigningDetails secondDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE, "5678",
595                 SECOND_SIGNATURE, THIRD_SIGNATURE);
596 
597         assertFalse(firstDetails.hasCommonAncestor(secondDetails));
598         assertFalse(secondDetails.hasCommonAncestor(firstDetails));
599     }
600 
601     @Test
hasCommonAncestor_overlappingLineages_returnsTrue()602     public void hasCommonAncestor_overlappingLineages_returnsTrue() throws Exception {
603         // if the two SigningDetails have overlapping lineages then hasCommonAncestor should return
604         // true.
605         SigningDetails firstLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
606                 SECOND_SIGNATURE);
607         SigningDetails secondLineageDetails = createSigningDetailsWithLineage(SECOND_SIGNATURE,
608                 THIRD_SIGNATURE);
609 
610         assertTrue(firstLineageDetails.hasCommonAncestor(secondLineageDetails));
611         assertTrue(secondLineageDetails.hasCommonAncestor(firstLineageDetails));
612     }
613 
614     @Test
hasCommonSignerWithCapabilities_singleMatchingSigner_returnsTrue()615     public void hasCommonSignerWithCapabilities_singleMatchingSigner_returnsTrue()
616             throws Exception {
617         // The hasCommonSignerWithCapabilities method is intended to grant the specified
618         // capabilities to a requesting package that has a common signer in the lineage (or as the
619         // current signer) even if their signing identities have diverged. This test verifies if the
620         // two SigningDetails have the same single signer then the requested capability can be
621         // granted since the current signer always has all capabilities granted.
622         SigningDetails firstDetails = createSigningDetails(FIRST_SIGNATURE);
623         SigningDetails secondSignerDetails = createSigningDetails(FIRST_SIGNATURE);
624 
625         assertTrue(firstDetails.hasCommonSignerWithCapability(secondSignerDetails, PERMISSION));
626     }
627 
628     @Test
hasCommonSignerWithCapabilities_singleDifferentSigners_returnsFalse()629     public void hasCommonSignerWithCapabilities_singleDifferentSigners_returnsFalse()
630             throws Exception {
631         // If each package is signed by a single different signer then the method should return
632         // false since there is no shared signer.
633         SigningDetails firstDetails = createSigningDetails(FIRST_SIGNATURE);
634         SigningDetails secondDetails = createSigningDetails(SECOND_SIGNATURE);
635 
636         assertFalse(firstDetails.hasCommonSignerWithCapability(secondDetails, PERMISSION));
637         assertFalse(secondDetails.hasCommonSignerWithCapability(firstDetails, PERMISSION));
638     }
639 
640     @Test
hasCommonSignerWithCapabilities_oneWithMultipleSigners_returnsFalse()641     public void hasCommonSignerWithCapabilities_oneWithMultipleSigners_returnsFalse()
642             throws Exception {
643         // If one of the packages is signed with multiple signers and the other only a single signer
644         // this method should return false since all signers must match exactly for multiple signer
645         // cases.
646         SigningDetails firstDetails = createSigningDetails(FIRST_SIGNATURE, SECOND_SIGNATURE);
647         SigningDetails secondDetails = createSigningDetails(FIRST_SIGNATURE);
648 
649         assertFalse(firstDetails.hasCommonSignerWithCapability(secondDetails, PERMISSION));
650         assertFalse(secondDetails.hasCommonSignerWithCapability(firstDetails, PERMISSION));
651     }
652 
653     @Test
hasCommonSignerWithCapabilities_multipleMatchingSigners_returnsTrue()654     public void hasCommonSignerWithCapabilities_multipleMatchingSigners_returnsTrue()
655             throws Exception {
656         // if both packages are signed by the same multiple signers then this method should return
657         // true since the current signer is granted all capabilities.
658         SigningDetails firstDetails = createSigningDetails(FIRST_SIGNATURE, SECOND_SIGNATURE);
659         SigningDetails secondDetails = createSigningDetails(SECOND_SIGNATURE, FIRST_SIGNATURE);
660 
661         assertTrue(firstDetails.hasCommonSignerWithCapability(secondDetails, PERMISSION));
662         assertTrue(secondDetails.hasCommonSignerWithCapability(firstDetails, PERMISSION));
663     }
664 
665     @Test
hasCommonSignerWithCapabilities_singleSignerInLineage_returnsTrue()666     public void hasCommonSignerWithCapabilities_singleSignerInLineage_returnsTrue()
667             throws Exception {
668         // if a single signer is in the lineage and that previous signer has the requested
669         // capability then this method should return true.
670         SigningDetails lineageDetails = createSigningDetailsWithLineageAndCapabilities(
671                 new String[]{FIRST_SIGNATURE, SECOND_SIGNATURE},
672                 new int[]{DEFAULT_CAPABILITIES, DEFAULT_CAPABILITIES});
673         SigningDetails singleSignerDetails = createSigningDetails(FIRST_SIGNATURE);
674 
675         assertTrue(lineageDetails.hasCommonSignerWithCapability(singleSignerDetails, PERMISSION));
676     }
677 
678     @Test
hasCommonSignerWithCapabilities_singleSignerInLineageWOCapability_returnsFalse()679     public void hasCommonSignerWithCapabilities_singleSignerInLineageWOCapability_returnsFalse()
680             throws Exception {
681         // If a single signer is in the lineage and that previous signer does not have the requested
682         // capability then this method should return false.
683         SigningDetails lineageDetails = createSigningDetailsWithLineageAndCapabilities(
684                 new String[]{FIRST_SIGNATURE, SECOND_SIGNATURE},
685                 new int[]{SHARED_USER_ID, DEFAULT_CAPABILITIES});
686         SigningDetails singleSignerDetails = createSigningDetails(FIRST_SIGNATURE);
687 
688         assertFalse(lineageDetails.hasCommonSignerWithCapability(singleSignerDetails, PERMISSION));
689     }
690 
691     @Test
hasCommonSignerWithCapabilities_singleSignerMatchesCurrentSigner_returnsTrue()692     public void hasCommonSignerWithCapabilities_singleSignerMatchesCurrentSigner_returnsTrue()
693             throws Exception {
694         // If a requesting app is signed by the same current signer as an app with a lineage the
695         // method should return true since the current signer is granted all capabilities.
696         SigningDetails lineageDetails = createSigningDetailsWithLineageAndCapabilities(
697                 new String[]{FIRST_SIGNATURE, SECOND_SIGNATURE},
698                 new int[]{SHARED_USER_ID, DEFAULT_CAPABILITIES});
699         SigningDetails singleSignerDetails = createSigningDetails(SECOND_SIGNATURE);
700 
701         assertTrue(lineageDetails.hasCommonSignerWithCapability(singleSignerDetails, PERMISSION));
702     }
703 
704     @Test
hasCommonSignerWithCapabilities_divergingSignersWithCommonSigner_returnsTrue()705     public void hasCommonSignerWithCapabilities_divergingSignersWithCommonSigner_returnsTrue()
706             throws Exception {
707         // This method is intended to allow granting a capability to another app that has a common
708         // signer in the lineage with the capability still granted; this test verifies when the
709         // current signers diverge but a common ancestor has the requested capability this method
710         // returns true.
711         SigningDetails firstLineageDetails = createSigningDetailsWithLineageAndCapabilities(
712                 new String[]{FIRST_SIGNATURE, SECOND_SIGNATURE, THIRD_SIGNATURE},
713                 new int[]{DEFAULT_CAPABILITIES, DEFAULT_CAPABILITIES, DEFAULT_CAPABILITIES});
714         SigningDetails secondLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
715                 SECOND_SIGNATURE, FOURTH_SIGNATURE);
716 
717         assertTrue(firstLineageDetails.hasCommonSignerWithCapability(secondLineageDetails,
718                 PERMISSION));
719     }
720 
721     @Test
hasCommonSignerWithCapabilities_divergingSignersOneGrantsCapability_returnsTrue()722     public void hasCommonSignerWithCapabilities_divergingSignersOneGrantsCapability_returnsTrue()
723             throws Exception {
724         // If apps have multiple common signers in the lineage with one denying the requested
725         // capability but the other granting it this method should return true.
726         SigningDetails firstLineageDetails = createSigningDetailsWithLineageAndCapabilities(
727                 new String[]{FIRST_SIGNATURE, SECOND_SIGNATURE, THIRD_SIGNATURE},
728                 new int[]{SHARED_USER_ID, DEFAULT_CAPABILITIES, DEFAULT_CAPABILITIES});
729         SigningDetails secondLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
730                 SECOND_SIGNATURE, FOURTH_SIGNATURE);
731 
732         assertTrue(firstLineageDetails.hasCommonSignerWithCapability(secondLineageDetails,
733                 PERMISSION));
734     }
735 
736     @Test
hasCommonSignerWithCapabilities_divergingSignersNoneGrantCapability_returnsFalse()737     public void hasCommonSignerWithCapabilities_divergingSignersNoneGrantCapability_returnsFalse()
738             throws Exception {
739         // If apps have multiple common signers in the lineage with all denying the requested
740         // capability this method should return false.
741         SigningDetails firstLineageDetails = createSigningDetailsWithLineageAndCapabilities(
742                 new String[]{FIRST_SIGNATURE, SECOND_SIGNATURE, THIRD_SIGNATURE},
743                 new int[]{SHARED_USER_ID, AUTH, DEFAULT_CAPABILITIES});
744         SigningDetails secondLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
745                 SECOND_SIGNATURE, FOURTH_SIGNATURE);
746 
747         assertFalse(firstLineageDetails.hasCommonSignerWithCapability(secondLineageDetails,
748                 PERMISSION));
749     }
750 
751     @Test
752     public void
hasCommonSignerWithCapabilities_divergingSignersNoneGrantsAllCapabilities_returnsTrue()753             hasCommonSignerWithCapabilities_divergingSignersNoneGrantsAllCapabilities_returnsTrue()
754             throws Exception {
755         // If an app has multiple common signers in the lineage, each granting one of the requested
756         // capabilities but neither granting all this method should return false since a single
757         // common ancestor must grant all requested capabilities.
758         SigningDetails firstLineageDetails = createSigningDetailsWithLineageAndCapabilities(
759                 new String[]{FIRST_SIGNATURE, SECOND_SIGNATURE, THIRD_SIGNATURE},
760                 new int[]{SHARED_USER_ID, PERMISSION, DEFAULT_CAPABILITIES});
761         SigningDetails secondLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
762                 SECOND_SIGNATURE, FOURTH_SIGNATURE);
763 
764         assertFalse(firstLineageDetails.hasCommonSignerWithCapability(secondLineageDetails,
765                 PERMISSION | SHARED_USER_ID));
766     }
767 
768     @Test
hasCommonSignerWithCapabilities_currentSignerInLineageOfRequestingApp_returnsTrue()769     public void hasCommonSignerWithCapabilities_currentSignerInLineageOfRequestingApp_returnsTrue()
770             throws Exception {
771         // If the current signer of an app is in the lineage of the requesting app then this method
772         // should return true since the current signer is granted all capabilities.
773         SigningDetails firstLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
774                 SECOND_SIGNATURE);
775         SigningDetails secondLineageDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
776                 SECOND_SIGNATURE, THIRD_SIGNATURE);
777 
778         assertTrue(firstLineageDetails.hasCommonSignerWithCapability(secondLineageDetails,
779                 PERMISSION));
780     }
781 
782     @Test
hasCommonSignerWithCapabilities_currentSignerInLineageOfDeclaringApp_returnsTrue()783     public void hasCommonSignerWithCapabilities_currentSignerInLineageOfDeclaringApp_returnsTrue()
784             throws Exception {
785         // If the current signer of a requesting app with a lineage is in the lineage of the
786         // declaring app and that previous signature is granted the requested capability the method
787         // should return true.
788         SigningDetails declaringDetails = createSigningDetailsWithLineageAndCapabilities(
789                 new String[]{FIRST_SIGNATURE, SECOND_SIGNATURE, THIRD_SIGNATURE},
790                 new int[]{SHARED_USER_ID, DEFAULT_CAPABILITIES, DEFAULT_CAPABILITIES});
791         SigningDetails requestingDetails = createSigningDetailsWithLineage(FIRST_SIGNATURE,
792                 SECOND_SIGNATURE);
793 
794         assertTrue(declaringDetails.hasCommonSignerWithCapability(requestingDetails, PERMISSION));
795     }
796 
797     @Test
hasCommonSignerWithCapabilities_oneSignerNullLineage_returns()798     public void hasCommonSignerWithCapabilities_oneSignerNullLineage_returns() throws Exception {
799         // While the pastSigningCertificates should only be null in the case of multiple current
800         // signers there are instances where this can be null with a single signer; verify that a
801         // null pastSigningCertificates array in either SigningDetails does not result in a
802         // NullPointerException.
803         SigningDetails firstDetails = createSigningDetails(true, FIRST_SIGNATURE);
804         SigningDetails secondDetails = createSigningDetails(SECOND_SIGNATURE);
805 
806         assertFalse(firstDetails.hasCommonSignerWithCapability(secondDetails, PERMISSION));
807         assertFalse(secondDetails.hasCommonSignerWithCapability(firstDetails, PERMISSION));
808     }
809 
810     @Test
hasCommonSignerWithCapabilities_unknownSigner_returnsFalse()811     public void hasCommonSignerWithCapabilities_unknownSigner_returnsFalse() throws Exception {
812         // An unknown SigningDetails for either instance should immediately result in false being
813         // returned.
814         SigningDetails firstDetails = SigningDetails.UNKNOWN;
815         SigningDetails secondDetails = createSigningDetails(FIRST_SIGNATURE);
816 
817         assertFalse(firstDetails.hasCommonSignerWithCapability(secondDetails, PERMISSION));
818         assertFalse(secondDetails.hasCommonSignerWithCapability(firstDetails, PERMISSION));
819     }
820 
821     @Test
hasAncestorOrSelfWithDigest_nullSet_returnsFalse()822     public void hasAncestorOrSelfWithDigest_nullSet_returnsFalse() throws Exception {
823         // The hasAncestorOrSelfWithDigest method is intended to verify whether the SigningDetails
824         // is currently signed, or has previously been signed, by any of the certificate digests
825         // in the provided Set. This test verifies if a null Set is provided then false is returned.
826         SigningDetails details = createSigningDetails(FIRST_SIGNATURE);
827 
828         assertFalse(details.hasAncestorOrSelfWithDigest(null));
829     }
830 
831     @Test
hasAncestorOrSelfWithDigest_unknownDetails_returnsFalse()832     public void hasAncestorOrSelfWithDigest_unknownDetails_returnsFalse() throws Exception {
833         // If hasAncestorOrSelfWithDigest is invoked against an UNKNOWN
834         // instance of the SigningDetails then false is returned.
835         SigningDetails details = SigningDetails.UNKNOWN;
836         Set<String> digests = createDigestSet(FIRST_SIGNATURE);
837 
838         assertFalse(details.hasAncestorOrSelfWithDigest(digests));
839     }
840 
841     @Test
hasAncestorOrSelfWithDigest_singleSignerInSet_returnsTrue()842     public void hasAncestorOrSelfWithDigest_singleSignerInSet_returnsTrue() throws Exception {
843         // If the single signer of an app is in the provided digest Set then
844         // the method should return true.
845         SigningDetails details = createSigningDetails(FIRST_SIGNATURE);
846         Set<String> digests = createDigestSet(FIRST_SIGNATURE, SECOND_SIGNATURE);
847 
848         assertTrue(details.hasAncestorOrSelfWithDigest(digests));
849     }
850 
851     @Test
hasAncestorOrSelfWithDigest_singleSignerNotInSet_returnsFalse()852     public void hasAncestorOrSelfWithDigest_singleSignerNotInSet_returnsFalse() throws Exception {
853         // If the single signer of an app is not in the provided digest Set then
854         // the method should return false.
855         SigningDetails details = createSigningDetails(FIRST_SIGNATURE);
856         Set<String> digests = createDigestSet(SECOND_SIGNATURE, THIRD_SIGNATURE);
857 
858         assertFalse(details.hasAncestorOrSelfWithDigest(digests));
859     }
860 
861     @Test
hasAncestorOrSelfWithDigest_multipleSignersInSet_returnsTrue()862     public void hasAncestorOrSelfWithDigest_multipleSignersInSet_returnsTrue() throws Exception {
863         // If an app is signed by multiple signers and all of the signers are in
864         // the digest Set then the method should return true.
865         SigningDetails details = createSigningDetails(FIRST_SIGNATURE, SECOND_SIGNATURE);
866         Set<String> digests = createDigestSet(FIRST_SIGNATURE, SECOND_SIGNATURE, THIRD_SIGNATURE);
867 
868         assertTrue(details.hasAncestorOrSelfWithDigest(digests));
869     }
870 
871     @Test
hasAncestorOrSelfWithDigest_multipleSignersNotInSet_returnsFalse()872     public void hasAncestorOrSelfWithDigest_multipleSignersNotInSet_returnsFalse()
873             throws Exception {
874         // If an app is signed by multiple signers then all signers must be in the digest Set; if
875         // only a subset of the signers are in the Set then the method should return false.
876         SigningDetails details = createSigningDetails(FIRST_SIGNATURE, SECOND_SIGNATURE);
877         Set<String> digests = createDigestSet(FIRST_SIGNATURE, THIRD_SIGNATURE);
878 
879         assertFalse(details.hasAncestorOrSelfWithDigest(digests));
880     }
881 
882     @Test
hasAncestorOrSelfWithDigest_multipleSignersOneInSet_returnsFalse()883     public void hasAncestorOrSelfWithDigest_multipleSignersOneInSet_returnsFalse()
884             throws Exception {
885         // If an app is signed by multiple signers and the Set size is smaller than the number of
886         // signers then the method should immediately return false since there's no way for the
887         // requirement of all signers in the Set to be met.
888         SigningDetails details = createSigningDetails(FIRST_SIGNATURE, SECOND_SIGNATURE);
889         Set<String> digests = createDigestSet(FIRST_SIGNATURE);
890 
891         assertFalse(details.hasAncestorOrSelfWithDigest(digests));
892     }
893 
894     @Test
hasAncestorOrSelfWithDigest_lineageSignerInSet_returnsTrue()895     public void hasAncestorOrSelfWithDigest_lineageSignerInSet_returnsTrue() throws Exception {
896         // If an app has a rotated signing key and a previous key in the lineage is in the digest
897         // Set then this method should return true.
898         SigningDetails details = createSigningDetailsWithLineage(FIRST_SIGNATURE, SECOND_SIGNATURE);
899         Set<String> digests = createDigestSet(FIRST_SIGNATURE, THIRD_SIGNATURE);
900 
901         assertTrue(details.hasAncestorOrSelfWithDigest(digests));
902     }
903 
904     @Test
hasAncestorOrSelfWithDigest_lineageSignerNotInSet_returnsFalse()905     public void hasAncestorOrSelfWithDigest_lineageSignerNotInSet_returnsFalse() throws Exception {
906         // If an app has a rotated signing key, but neither the current key nor any of the signers
907         // in the lineage are in the digest set then the method should return false.
908         SigningDetails details = createSigningDetailsWithLineage(FIRST_SIGNATURE, SECOND_SIGNATURE);
909         Set<String> digests = createDigestSet(THIRD_SIGNATURE, FOURTH_SIGNATURE);
910 
911         assertFalse(details.hasAncestorOrSelfWithDigest(digests));
912     }
913 
914     @Test
hasAncestorOrSelfWithDigest_lastSignerInLineageInSet_returnsTrue()915     public void hasAncestorOrSelfWithDigest_lastSignerInLineageInSet_returnsTrue()
916             throws Exception {
917         // If an app has multiple signers in the lineage only one of those signers must be in the
918         // Set for this method to return true. This test verifies if the last signer in the lineage
919         // is in the set then the method returns true.
920         SigningDetails details = createSigningDetailsWithLineage(FIRST_SIGNATURE, SECOND_SIGNATURE,
921                 THIRD_SIGNATURE);
922         Set<String> digests = createDigestSet(SECOND_SIGNATURE);
923 
924         assertTrue(details.hasAncestorOrSelfWithDigest(digests));
925     }
926 
927     @Test
hasAncestorOrSelfWithDigest_nullLineageSingleSIgner_returnsFalse()928     public void hasAncestorOrSelfWithDigest_nullLineageSingleSIgner_returnsFalse()
929             throws Exception {
930         // Under some instances an app with only a single signer can have a null lineage; this
931         // test verifies that null lineage does not result in a NullPointerException and instead the
932         // method returns false if the single signer is not in the Set.
933         SigningDetails details = createSigningDetails(true, FIRST_SIGNATURE);
934         Set<String> digests = createDigestSet(SECOND_SIGNATURE, THIRD_SIGNATURE);
935 
936         assertFalse(details.hasAncestorOrSelfWithDigest(digests));
937     }
938 
createSigningDetailsWithLineage(String... signers)939     private SigningDetails createSigningDetailsWithLineage(String... signers) throws Exception {
940         int[] capabilities = new int[signers.length];
941         for (int i = 0; i < capabilities.length; i++) {
942             capabilities[i] = DEFAULT_CAPABILITIES;
943         }
944         return createSigningDetailsWithLineageAndCapabilities(signers, capabilities);
945     }
946 
createSigningDetailsWithLineageAndCapabilities(String[] signers, int[] capabilities)947     private SigningDetails createSigningDetailsWithLineageAndCapabilities(String[] signers,
948             int[] capabilities) throws Exception {
949         if (capabilities.length != signers.length) {
950             fail("The capabilities array must contain the same number of elements as the signers "
951                     + "array");
952         }
953         Signature[] signingHistory = new Signature[signers.length];
954         for (int i = 0; i < signers.length; i++) {
955             signingHistory[i] = new Signature(signers[i]);
956             signingHistory[i].setFlags(capabilities[i]);
957         }
958         Signature[] currentSignature = new Signature[]{signingHistory[signers.length - 1]};
959         return new SigningDetails(currentSignature, SIGNING_BLOCK_V3, signingHistory);
960     }
961 
createSigningDetails(String... signers)962     private SigningDetails createSigningDetails(String... signers) throws Exception {
963         return createSigningDetails(false, signers);
964     }
965 
createSigningDetails(boolean useNullPastSigners, String... signers)966     private SigningDetails createSigningDetails(boolean useNullPastSigners, String... signers)
967             throws Exception {
968         Signature[] currentSignatures = new Signature[signers.length];
969         for (int i = 0; i < signers.length; i++) {
970             currentSignatures[i] = new Signature(signers[i]);
971         }
972         // If there are multiple signers then the pastSigningCertificates should be set to null, but
973         // if there is only a single signer both the current signer and the past signers should be
974         // set to that one signer.
975         if (signers.length > 1 || useNullPastSigners) {
976             return new SigningDetails(currentSignatures, SIGNING_BLOCK_V3, null);
977         }
978         return new SigningDetails(currentSignatures, SIGNING_BLOCK_V3, currentSignatures);
979     }
980 
createDigestSet(String... signers)981     private Set<String> createDigestSet(String... signers) {
982         Set<String> digests = new ArraySet<>();
983         for (String signer : signers) {
984             String digest = PackageUtils.computeSha256Digest(new Signature(signer).toByteArray());
985             digests.add(digest);
986         }
987         return digests;
988     }
989 
assertSigningDetailsContainsLineage(SigningDetails details, String... pastSigners)990     private void assertSigningDetailsContainsLineage(SigningDetails details,
991             String... pastSigners) {
992         // This method should only be invoked for results that contain a single signer.
993         assertEquals(1, details.signatures.length);
994         assertTrue(details.signatures[0].toCharsString().equalsIgnoreCase(
995                 pastSigners[pastSigners.length - 1]));
996         Set<String> signatures = new ArraySet<>(pastSigners);
997         for (Signature pastSignature : details.pastSigningCertificates) {
998             assertTrue(signatures.remove(pastSignature.toCharsString()));
999         }
1000         assertEquals(0, signatures.size());
1001     }
1002 }
1003