As Dianne points out, the behaviour has changed between Android
versions. You are probably testing on Android < 2.2, which
(intentionally or accidentally) allowed developers to "phase out"
signatures on package upgrades. What I mean by that is if an installed
package had signatures A and B, an upgrade to that package can have
only signature A, only signature B, or both.  However, if an installed
package has only one signature, an update to that package can only
have that same signature. Adding any new signatures caused the upgrade
to fail.

The code that checks the signatures was modified quite a bit in 2.2.
The installer now checks that the set of signatures is _EXACTLY_ the
same in _BOTH_ the installed package and the new package. Therefore,
any change to the set of signatures (adding or removing) will cause
the upgrade to fail.

Here's the code that compares signatures in version 2.1 (similar in
older versions):
from frameworks/base/services/java/com/android/server/PackageManagerService.java

    int checkSignaturesLP(Signature[] s1, Signature[] s2) {
        if (s1 == null) {
            return s2 == null
                    ? PackageManager.SIGNATURE_NEITHER_SIGNED
                    : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
        }
        if (s2 == null) {
            return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
        }
        final int N1 = s1.length;
        final int N2 = s2.length;
        for (int i=0; i<N1; i++) {
            boolean match = false;
            for (int j=0; j<N2; j++) {
                if (s1[i].equals(s2[j])) {
                    match = true;
                    break;
                }
            }
            if (!match) {
                return PackageManager.SIGNATURE_NO_MATCH;
            }
        }
        return PackageManager.SIGNATURE_MATCH;
    }

>From what I can tell in the source code of Android, this method is
called with s1 as the new package being installed and s2 as the
currently installed package. As you can see, the outer for loop
iterates through all signatures in the new package and tries to find
one that matches in the currently installed package. I'm fairly
certain that the first argument passed to checkSignaturesLP is always
the new package being installed, but if the arguments are switched,
the behaviour will be exactly the opposite, and would allow for
signatures to be added, but not removed. Thus, the order of the
parameters to this method in Android 2.1 and lower was extremely
important!

Here's the code that compares signatures in version 2.2:
from frameworks/base/services/java/com/android/server/PackageManagerService.java

    int checkSignaturesLP(Signature[] s1, Signature[] s2) {
        if (s1 == null) {
            return s2 == null
                    ? PackageManager.SIGNATURE_NEITHER_SIGNED
                    : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
        }
        if (s2 == null) {
            return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
        }
        HashSet<Signature> set1 = new HashSet<Signature>();
        for (Signature sig : s1) {
            set1.add(sig);
        }
        HashSet<Signature> set2 = new HashSet<Signature>();
        for (Signature sig : s2) {
            set2.add(sig);
        }
        // Make sure s2 contains all signatures in s1.
        if (set1.equals(set2)) {
            return PackageManager.SIGNATURE_MATCH;
        }
        return PackageManager.SIGNATURE_NO_MATCH;
    }

The developer comment above the check is not technically accurate,
it's not just checking if s2 contains all the signatures in s1. This
code checks if the signature sets are identical in both packages,
regardless of the order of the parameters.


On Fri, Nov 12, 2010 at 2:18 PM, Dianne Hackborn <[email protected]> wrote:
> The behavior depends on the version of the platform you are using, but in
> pretty much all cases it will not be what you want.  I can't stress how
> strongly I discourage apps from being signed with multiple certificates.
>  Just plain do not do this.  You will be very very unhappy if you do.  There
> is no support for doing something reasonable with multiple certificates, and
> the behavior you get will *not* be what you want.
>
> On Thu, Nov 11, 2010 at 5:44 PM, laminina <[email protected]> wrote:
>>
>> Hi,
>>
>> Does someone know how the package Manager behaves under this
>> environment:
>>
>> Have App1signed with certificate A
>> Have App1 signed with certificate A and certificate B.
>>
>> I'm only able to upgrade from one app to the other one if I install
>> first  App1 with certificates A&B and then I upgrade to App1 with
>> certificate A. (adb install -r app1.apk)
>>
>> If I do the opposite: Install first App1 with certificate A and then I
>> upgrade installing App1 with certificates A&B I get failure
>> Failure [INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES]
>>
>> Why it only works one way?
>> I've google it and I have never found something posted similiar to
>> this issue.
>> Does anyone have a clue on this?
>> Thanks.
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "Android Security Discussions" group.
>> To post to this group, send email to
>> [email protected].
>> To unsubscribe from this group, send email to
>> [email protected].
>> For more options, visit this group at
>> http://groups.google.com/group/android-security-discuss?hl=en.
>>
>
>
>
> --
> Dianne Hackborn
> Android framework engineer
> [email protected]
>
> Note: please don't send private questions to me, as I don't have time to
> provide private support, and so won't reply to such e-mails.  All such
> questions should be posted on public forums, where I and others can see and
> answer them.
>
> --
> You received this message because you are subscribed to the Google Groups
> "Android Security Discussions" group.
> To post to this group, send email to
> [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/android-security-discuss?hl=en.
>



-- 
David

-- 
You received this message because you are subscribed to the Google Groups 
"Android Security Discussions" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/android-security-discuss?hl=en.

Reply via email to