Just An Application

August 9, 2014

And Another One: Part Four — Certificates And Certificate Chains

1.0 Certificates

The ASN.1 definition of an X.509 Certificate as defined by RFC 2459 looks like this

    Certificate ::= SEQUENCE {
        tbsCertificate      TBSCertificate,
        signatureAlgorithm  AlgorithmIdentifier,
        signature           BIT STRING
    }

An X.509 Certificate is simply a signed TBSCertificate.

The definition of a TBSCertificate looks like this

     TBSCertificate ::= SEQUENCE {
         version                [0] EXPLICIT Version DEFAULT v1(0),
         serialNumber               CertificateSerialNumber,
         signature                  AlgorithmIdentifier,
         issuer                     Name,
         validity                   Validity,
         subject                    Name,
         subjectPublicKeyInfo       SubjectPublicKeyInfo,
         issuerUniqueId         [1] IMPLICIT UniqueIdentifier OPTIONAL,
                                    -- If present, version shall be v2 or v3
         subjectUniqueId        [2] IMPLICIT UniqueIdentifier OPTIONAL,
                                    -- If present, version shall be v2 or v3
         extensions             [3] EXPLICIT Extensions OPTIONAL
                                    -- If present, version shall be v3
     }

1.1 subjectPublicKeyInfo And subject

The

    subjectPublicKeyInfo

field specifies a public key, and the

    subject

field identifies the owner of the specified public key.

1.2 issuer and serialNumber

The

    issuer

field identifies the signer of the TBSCertificate.

This together with the

    serialNumber

field should uniquely identify the certificate.

1.3 Validity

The validity field specifies the period during which the certificate is valid.

The ASN.1 definition of the Validity type looks like this

    Validity ::= SEQUENCE {
        notBefore      Time,
        notAfter       Time }

The public key specified by the certificate should not be used at time T if T is before the value specified by notBefore or after the value specified by notAfter.

Unfortunately, in practice certificates are often issued with such long validity periods that checking the validity really serves no useful purpose.

1.4 Self-Signed Certificates

If the subject and issuer fields are identical then the certificate is self-signed, that is, the signature of the certificate was generated using the private key corresponding to the public key specified by the certificate.

2.0 Certificate Chains

A certificate chain in simply a certificate (A) plus the certificate (B) of the issuer of certificate A, plus the certificate of the issuer of certificate B, and so on.

To put it another way

    certificate[i+1].subject == certificate[i].issuer

A finite certificate chain must necessarily terminate in a self-signed certificate, or terminate arbitrarily and not include all of the certificates back to a self-signed certificate.

The purpose of a certificate chain is to make it possible to verify the signature of the i’th ‘certificate in the chain using the public key specified in the i+1’th certificate.

2.1 Certificate Chains And Trust

Given a certificate chain terminated by a self-signed certificate it is always possible to verify all the certificates in the chain and hence anything signed by subject of the first certificate in the chain.

This is also possible given a chain terminated by a non-self-signed certificate plus the rest of the certificates back to a self-signed certificate obtained from some other source.

In either case what it is possible to do is to establish unequivocally is that something supposedly signed by the subject of the first certificate in the chain was in fact signed by them but that is all.

It is not possible to establish whether the subjects of any of the certificate are who they claim to be.

To do this you must trust one of the certificates in the chain and this cannot be done algorithmically it can only done by policy.

This is usually achieved by having one or more certificates known to the system defined a priori as trust roots.

Any certificate which can be verified directly or indirectly using a trust root can itself be trusted and consequently anything else signed by the subject of a trusted certificate can itself be trusted for some value of trust.

This of course assumes that the subject of a certificate considered to be a trust root is not simply signing every and any certificate that comes their way, and similarly for the subjects of those certificates and so on and so forth.

This is not necessarily a good assumption to make and the longer the certificate chain the less good it becomes but given the way certificates and the public key infrastructure work its all you can do.

3.0 Example

This is a simple example of a certificate chain of length three terminating in a self-signed certificate.


    Certificate[0]
    
    Data:
        Version: 1 (0x0)
        Serial Number:
            8c:f3:8c:e9:05:ed:d1:7c
        Signature Algorithm: sha1WithRSAEncryption
        Issuer:
            C=OZ, ST=Nowhere, L=Emerald City, O=ASH Two, OU=Android Applications Group, \
                CN=Admin/emailAddress=admin@android.applications.group.ash2.oz
        Validity
            Not Before: Aug  4 10:53:06 2014 GMT
            Not After : Sep  3 10:53:06 2014 GMT
        Subject:
            C=OZ, ST=Nowhere, L=Emerald City, O=ASH Two, OU=AndroidApp Flounder Group, \
                CN=AndroidApp Flounder
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public Key: (2048 bit)
                    Modulus (2048 bit):
                        00:8a:84:e0:00:7f:ee:fe:1d:18:57:2d:be:a7:2e:
                        68:aa:6b:6d:26:6d:14:1b:0c:e0:b5:44:46:0c:62:
                        40:7a:d9:d5:46:c3:d0:38:28:29:cb:e4:8f:42:5d:
                        8f:7d:81:78:24:ae:61:f6:a5:9b:a6:b4:0b:b6:f4:
                        01:96:1b:b4:90:b7:74:c7:99:55:33:9d:fc:80:4b:
                        e3:fd:00:4b:99:ee:68:b5:81:6a:60:c3:f2:2e:fc:
                        31:7e:ff:b9:66:24:6f:6b:a0:82:e8:15:f6:cd:d1:
                        b1:b5:05:41:2c:19:e2:f4:92:e9:df:23:94:80:ad:
                        e1:45:41:31:78:52:d2:8d:18:58:c2:0a:a1:ef:9d:
                        5e:d6:5c:60:07:09:6d:87:51:79:42:25:2b:99:0c:
                        35:2d:3d:1f:09:d0:71:05:bb:a7:90:fb:70:e7:26:
                        d9:c6:43:53:35:60:5b:4c:1f:df:38:74:ca:a0:b0:
                        0e:77:9c:fa:7d:c2:32:9a:99:b2:53:6a:c8:fa:ea:
                        0a:3e:b7:99:50:7d:d1:94:3f:a4:2e:18:aa:ff:8a:
                        82:69:0e:2b:83:07:7b:fc:b0:7b:62:7a:99:1e:e7:
                        6b:ab:d6:0d:5e:d2:f2:19:55:af:81:82:e8:d1:db:
                        a9:ea:16:58:32:8a:55:ac:be:8e:cf:87:a0:ed:2d:
                        4f:9f
                    Exponent:
                        65537 (0x10001)
    Signature Algorithm: sha1WithRSAEncryption
        48:7e:34:61:08:14:18:b2:8f:66:3f:2e:58:fd:a5:4c:4f:85:
        fa:d1:36:5b:b9:ba:21:1e:3e:fd:8e:a9:40:23:b6:8a:84:38:
        9f:40:4f:f6:4f:73:a9:f8:79:e7:21:a1:67:32:48:1b:5f:e0:
        5b:6b:13:53:ff:9a:40:41:13:99:e2:0d:eb:6b:15:c5:24:be:
        71:d7:9e:98:af:11:2b:9d:9a:f1:e1:d9:27:27:47:b2:41:3a:
        43:65:ce:b9:c6:7b:00:ee:77:5e:b1:a8:63:e0:f2:fc:94:32:
        42:4f:9b:30:6b:8e:fe:26:e5:0a:ed:1f:ab:9d:5b:48:56:4e:
        30:1d

    Certificate[1]
    
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=OZ, ST=Nowhere, L=Emerald City, O=ASH Two, OU=Certs Group, \
                    CN=Admin/emailAddress=admin@certs.group.ash2.oz
        Validity
            Not Before: Aug  4 10:45:35 2014 GMT
            Not After : Aug  4 10:45:35 2015 GMT
        Subject: C=OZ, ST=Nowhere, L=Emerald City, O=ASH Two, OU=Android Applications Group, \
                     CN=Admin/emailAddress=admin@android.applications.group.ash2.oz
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public Key: (1024 bit)
                    Modulus (1024 bit):
                        00:dd:17:06:f9:6a:44:be:96:ed:01:39:e2:fe:5e:
                        99:9e:cf:4f:55:b5:c8:5b:27:42:b6:b5:bf:49:73:
                        41:fd:17:b2:b7:bd:1f:6e:28:07:fc:24:07:57:76:
                        80:5b:88:12:f4:09:28:1d:97:d4:b9:37:7a:2f:52:
                        83:9b:64:60:6f:72:b2:4e:d0:ed:15:d5:26:b2:5a:
                        33:e6:27:37:4f:42:7e:24:36:f1:2e:dc:a8:5d:bd:
                        52:8e:c0:72:62:39:fa:cb:08:f6:4e:e2:89:d0:3b:
                        ab:88:da:e6:a4:18:cc:e3:9d:fb:6d:2e:a1:ac:ec:
                        56:44:f6:8f:d1:c7:b3:e7:c5
                    Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                7B:AB:2E:B9:61:D2:08:3E:78:42:4F:CA:EE:DF:28:3D:27:76:C4:2D
            X509v3 Authority Key Identifier:
                keyid:5B:ED:98:20:92:DD:B5:8F:0F:0F:32:47:29:48:38:BB:F7:52:B0:48
                DirName:/C=OZ/ST=Nowhere/L=Emerald City/O=ASH Two/OU=Certs Group\
                        /CN=Admin/emailAddress=admin@certs.group.ash2.oz
                serial:EF:55:32:3F:F5:CF:64:E5
    
    Signature Algorithm: sha1WithRSAEncryption
        98:a1:e6:be:33:06:94:1f:93:e1:c5:1a:a4:53:5c:c5:ad:f0:
        b7:c4:bd:f3:dd:22:2e:f1:aa:0e:c7:08:42:1b:9a:f8:1c:f4:
        05:c2:a2:96:a3:ea:d6:5d:7d:ee:65:78:4c:24:5d:35:8b:0b:
        7c:fe:b3:a4:c7:5f:b6:45:f0:3b:f2:5d:8c:32:fa:8e:2d:0b:
        6e:10:1c:5c:3c:55:d4:f0:f3:c3:61:53:22:6a:65:93:d0:2a:
        a4:29:09:61:8e:46:9c:ab:47:0b:74:16:97:d3:30:51:4f:eb:
        ad:e1:4f:6e:83:a9:f6:11:0f:7d:ab:97:73:f9:8a:cf:43:53:
        f8:6d

    Certificate[2]
    
    Data:
        Version: 3 (0x2)
        Serial Number:
            9a:32:99:e8:05:ee:62:db
            Signature Algorithm: sha1WithRSAEncryption
            Issuer:
                C=OZ, ST=Nowhere, L=Emerald City, O=ASH Two, OU=Android Applications Group, \
                    CN=Admin/emailAddress=admin@android.applications.group.ash2.oz
            Validity
                Not Before: Aug  5 16:57:20 2014 GMT
                Not After : Aug  5 16:57:20 2015 GMT
            Subject:
                C=OZ, ST=Nowhere, L=Emerald City, O=ASH Two, OU=Android Applications Group, \
                    CN=Admin/emailAddress=admin@android.applications.group.ash2.oz
            Subject Public Key Info:
                Public Key Algorithm: rsaEncryption
                    RSA Public Key: (1024 bit)
                        Modulus (1024 bit):
                            00:c6:27:36:f5:fd:33:26:14:7b:a9:1b:10:84:fc:
                            7b:58:e3:cf:21:b9:28:50:4b:b9:d0:9b:73:5b:e4:
                            81:06:be:0d:b6:ff:d2:d4:06:bd:bd:63:3d:e6:65:
                            f3:10:e5:39:5b:4c:e1:96:e4:fe:a3:e3:52:c1:6b:
                            bd:a0:e8:fb:a8:11:f8:0c:68:ee:6b:1b:e0:c8:9d:
                            41:0a:41:c6:dd:ff:1b:4c:c4:a1:9b:17:85:58:4a:
                            3d:4e:88:4f:2e:ea:d3:28:8e:23:a1:d9:92:ba:87:
                            b6:91:d9:07:8b:c2:9a:e3:75:18:36:3e:fc:12:ae:
                            ff:3a:4b:3a:e7:21:a1:08:2d
                        Exponent: 65537 (0x10001)
            X509v3 extensions:
                X509v3 Subject Key Identifier:
                    79:59:43:52:D9:04:7D:C0:EA:A8:14:37:BB:7B:85:92:91:44:07:D1
                X509v3 Authority Key Identifier:
                    keyid:79:59:43:52:D9:04:7D:C0:EA:A8:14:37:BB:7B:85:92:91:44:07:D1
                    DirName:/C=OZ/ST=Nowhere/L=Emerald City/O=ASH Two/OU=Android Applications Group \
                            /CN=Admin/emailAddress=admin@android.applications.group.ash2.oz
                    serial:9A:32:99:E8:05:EE:62:DB
    
                X509v3 Basic Constraints:
                    CA:TRUE
    Signature Algorithm: sha1WithRSAEncryption
        a2:7b:0f:7d:02:ee:5a:b4:e0:b7:78:33:5d:59:9b:13:be:71:
        98:6b:2e:44:95:56:e5:69:78:49:99:5d:f9:14:a8:4f:1c:fc:
        4d:13:f7:2a:cd:eb:cc:97:7c:41:1e:24:2b:d4:56:3d:0a:90:
        cd:7b:9f:af:84:99:9a:bc:c7:63:3a:24:46:7c:f7:06:48:f9:
        7c:10:9b:58:ee:2e:07:1b:a9:66:66:d0:cc:e7:cb:f2:8c:53:
        6b:a8:d3:2e:a6:d2:f0:f4:ca:65:fb:66:73:18:86:8a:30:ef:
        f7:09:27:56:00:5f:e2:30:d8:5e:a2:6b:d6:22:af:bd:18:59:
        b9:7b

Copyright (c) 2014 By Simon Lewis. All Rights Reserved.

Unauthorized use and/or duplication of this material without express and written permission from this blog’s author and owner Simon Lewis is strictly prohibited.

Excerpts and links may be used, provided that full and clear credit is given to Simon Lewis and justanapplication.wordpress.com with appropriate and specific direction to the original content.

July 13, 2013

The Great Android Security Hole Of ’08 ? – Part Two: Signed JARs

1.0 Structure

An Android APK is a signed JAR and a signed JAR is a good old-fashioned ZIP file.

If you list the contents of an APK using unzip you will see something like this

    Archive:  GoodAppBadApp.apk
      Length     Date   Time    Name
     --------    ----   ----    ----
          624  07-10-13 21:11   res/layout/activity_main.xml
          464  07-10-13 21:11   res/menu/activity_main.xml
         1588  07-10-13 21:11   AndroidManifest.xml
         2504  07-10-13 21:11   resources.arsc
          409  07-10-13 21:11   res/drawable-hdpi/ic_action_search.png
         4129  07-10-13 21:11   res/drawable-hdpi/ic_launcher.png
         1756  07-10-13 21:11   res/drawable-ldpi/ic_launcher.png
          311  07-10-13 21:11   res/drawable-mdpi/ic_action_search.png
         2654  07-10-13 21:11   res/drawable-mdpi/ic_launcher.png
          491  07-10-13 21:11   res/drawable-xhdpi/ic_action_search.png
         5456  07-10-13 21:11   res/drawable-xhdpi/ic_launcher.png
       366112  07-10-13 21:11   classes.dex
         1034  07-10-13 21:11   META-INF/MANIFEST.MF
         1087  07-10-13 21:11   META-INF/CERT.SF
          776  07-10-13 21:11   META-INF/CERT.RSA
     --------                   -------
       389395                   15 files

It is the presence of the manifest file

    META-INF/MANIFEST.MF

which make this ZIP file a JAR, and it is the presence of the ‘signature’ files

    META-INF/CERT.SF
    META-INF/CERT.RSA

that makes it a signed JAR.

2.0 The Meta Files

2.1 MANIFEST.MF

This is what’s in the MANIFEST.MF file contained in the APK shown in the example above

    Manifest-Version: 1.0
    Created-By: 1.0 (Android)

    Name: res/drawable-xhdpi/ic_launcher.png
    SHA1-Digest: TJE1tg63y88xLdIALKGpuLmgh0s=

    Name: res/drawable-mdpi/ic_action_search.png
    SHA1-Digest: XjltJdEB3tvakTn9CN7KwdaNT68=

    Name: AndroidManifest.xml
    SHA1-Digest: iXwTXVvLX3gY+ByGhybEJvIxP08=

    Name: res/drawable-mdpi/ic_launcher.png
    SHA1-Digest: aM73uFWfPOOvq5Kk9Ffd3cWm0OQ=

    Name: res/drawable-hdpi/ic_launcher.png
    SHA1-Digest: ioH2V9g4FYKkqpDHk7jPryMKtcE=

    Name: res/layout/activity_main.xml
    SHA1-Digest: zd1eNopMfZ7CmMk8GjyPGPpYloc=

    Name: resources.arsc
    SHA1-Digest: 7nYq90PW0OZVg8ytyjBEcwQhYiA=

    Name: classes.dex
    SHA1-Digest: b80KFg5gdqlORweY5LrUS87tbVU=

    Name: res/drawable-hdpi/ic_action_search.png
    SHA1-Digest: rOWnNxWCWKwkicf+FpYGMg1fX2Y=

    Name: res/drawable-xhdpi/ic_action_search.png
    SHA1-Digest: WzSVDDIHZpn0cFeuxgKRJete4TU=

    Name: res/menu/activity_main.xml
    SHA1-Digest: TfxVPQP5IRVlJun7A7PdOqdkp+I=

    Name: res/drawable-ldpi/ic_launcher.png
    SHA1-Digest: r6Mdl54h2qEvVnqgfsgxU4CysiI=

As you can see there is a section for each file in the APK with the exception of those contained in the META-INF directory.

The SHA1-Digest attribute specifies the SHA-1[1] digest of the named file. The value is Base64 encoded.

2.2 CERT.SF

The CERT.SF file is a ‘signature file’. This is odd because technically it does not contain any signatures in the cryptographic sense, but there it is.

Signature files are identified by the suffix .SF

This is what’s in the CERT.SF file contained in the APK shown in the example above

    Signature-Version: 1.0
    Created-By: 1.0 (Android)
    SHA1-Digest-Manifest: uy1/gV4Q91cFNXDPKFWnIkdp7Hs=

    Name: res/drawable-xhdpi/ic_launcher.png
    SHA1-Digest: uQhdAiwpzle4OMU4KiZ8rHZZW0s=

    Name: res/drawable-mdpi/ic_action_search.png
    SHA1-Digest: jAGFiT7RUDOYcmBQqk2FP01Xtb0=

    Name: AndroidManifest.xml
    SHA1-Digest: app7CkR5QClO2DngK2SwqyoYT/4=

    Name: res/drawable-mdpi/ic_launcher.png
    SHA1-Digest: 7AYLMxFKX2g7vudLLZTXlC9DWHI=

    Name: res/drawable-hdpi/ic_launcher.png
    SHA1-Digest: diYsvf3zRlU+JNDApc7+KLVhhk0=

    Name: res/layout/activity_main.xml
    SHA1-Digest: tK4fMdQKbbzD/KoE5awGKM7o++Y=

    Name: resources.arsc
    SHA1-Digest: mMTrtN8w3SByhMHUQ19nJ3OT3wo=

    Name: res/drawable-hdpi/ic_action_search.png
    SHA1-Digest: WvsoZfcfGbz7vtTCwzXLh3VcxFw=

    Name: classes.dex
    SHA1-Digest: /okgNUxVNi1erXMkC7ftetu9S9U=

    Name: res/drawable-xhdpi/ic_action_search.png
    SHA1-Digest: 772ITFXOlprwo44bOLvLMa3Vdeg=

    Name: res/menu/activity_main.xml
    SHA1-Digest: K1PTOAgvzmJK47MHIsJIWgVr/04=

    Name: res/drawable-ldpi/ic_launcher.png
    SHA1-Digest: zC+Z/B5ib1ntZmz9D80Rj3muYqE=

The SHA1-Digest-Manifest in the first section specifies the SHA-1 digest of the manifest file.

In the following sections the SHA1-Digest attribute specifies the SHA-1 digest of the corresponding section in the manifest file.

2.3 CERT.RSA

The CERT.RSA file is the ‘signed signature file’.

The CERT.RSA file contained in the APK shown in the example above is a binary file, so this is a representation of its contents produced using the ubiquitous dumpasn1.


   0  772: SEQUENCE {
   4    9:   OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2)
  15  757:   [0] {
  19  753:     SEQUENCE {
  23    1:       INTEGER 1
  26   11:       SET {
  28    9:         SEQUENCE {
  30    5:           OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
  37    0:           NULL
         :           }
         :         }
  39   11:       SEQUENCE {
  41    9:         OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
         :         }
  52  489:       [0] {
  56  485:         SEQUENCE {
  60  334:           SEQUENCE {
  64    3:             [0] {
  66    1:               INTEGER 2
         :               }
  69    4:             INTEGER 1322302491
  75   13:             SEQUENCE {
  77    9:               OBJECT IDENTIFIER
         :                 sha1withRSAEncryption (1 2 840 113549 1 1 5)
  88    0:               NULL
         :               }
  90   55:             SEQUENCE {
  92   11:               SET {
  94    9:                 SEQUENCE {
  96    3:                   OBJECT IDENTIFIER countryName (2 5 4 6)
 101    2:                   PrintableString 'US'
         :                   }
         :                 }
 105   16:               SET {
 107   14:                 SEQUENCE {
 109    3:                   OBJECT IDENTIFIER organizationName (2 5 4 10)
 114    7:                   PrintableString 'Android'
         :                   }
         :                 }
 123   22:               SET {
 125   20:                 SEQUENCE {
 127    3:                   OBJECT IDENTIFIER commonName (2 5 4 3)
 132   13:                   PrintableString 'Android Debug'
         :                   }
         :                 }
         :               }
 147   30:             SEQUENCE {
 149   13:               UTCTime 26/11/2011 10:14:51 GMT
 164   13:               UTCTime 18/11/2041 10:14:51 GMT
         :               }
 179   55:             SEQUENCE {
 181   11:               SET {
 183    9:                 SEQUENCE {
 185    3:                   OBJECT IDENTIFIER countryName (2 5 4 6)
 190    2:                   PrintableString 'US'
         :                   }
         :                 }
 194   16:               SET {
 196   14:                 SEQUENCE {
 198    3:                   OBJECT IDENTIFIER organizationName (2 5 4 10)
 203    7:                   PrintableString 'Android'
         :                   }
         :                 }
 212   22:               SET {
 214   20:                 SEQUENCE {
 216    3:                   OBJECT IDENTIFIER commonName (2 5 4 3)
 221   13:                   PrintableString 'Android Debug'
         :                   }
         :                 }
         :               }
 236  159:             SEQUENCE {
 239   13:               SEQUENCE {
 241    9:                 OBJECT IDENTIFIER
         :                   rsaEncryption (1 2 840 113549 1 1 1)
 252    0:                 NULL
         :                 }
 254  141:               BIT STRING, encapsulates {
 258  137:                 SEQUENCE {
 261  129:                   INTEGER
         :                   00 8A 0A 1D 53 48 FC 26 6D BF 65 57 04 8B 0B E9
         :                   58 EE E7 11 CE A8 A2 01 72 7B 34 C1 31 60 B4 64
         :                   FC D3 0D 1E 94 BE B3 5B 55 7F 23 97 B9 3D 6F E8
         :                   17 17 FE CA 50 EB F3 EA 4B 7C F6 F9 B6 6E E7 5D
         :                   0D 64 79 00 8F 12 1A 76 09 C1 32 4F 28 E8 27 94
         :                   34 F5 C8 50 C3 0D E9 2E FF A2 97 71 6C 18 7F 7C
         :                   8A 78 EA 37 50 20 8D DA 6C F2 3F 65 85 67 6A 7B
         :                   35 BF 5A 8D 53 DE AD 9D 50 70 30 B4 0D A4 60 D4
         :                           [ Another 1 bytes skipped ]
 393    3:                   INTEGER 65537
         :                   }
         :                 }
         :               }
         :             }
 398   13:           SEQUENCE {
 400    9:             OBJECT IDENTIFIER
         :               sha1withRSAEncryption (1 2 840 113549 1 1 5)
 411    0:             NULL
         :             }
 413  129:           BIT STRING
         :             2E 77 85 3F F4 AF EE 1E 81 9B 8B BB E2 9C AA 95
         :             BE 38 1E 20 EA E3 63 BE 2B A7 F2 AB 8A F4 F5 27
         :             35 F6 7C 67 CF E5 07 82 D0 B5 D8 00 77 CC 9A 8B
         :             86 DD 4C DD 41 88 2E C5 B4 B9 7E E9 C4 B2 B9 FA
         :             31 A0 60 6F DA 8D D1 F9 FA F6 94 08 92 C2 58 D6
         :             BF 93 1E 4D B8 DF DD D3 C1 11 89 14 22 C8 8B 85
         :             98 04 7A F5 00 D5 1D F2 E0 54 42 82 46 2D FE 2D
         :             C3 AB 2B C6 BC E7 07 A2 B8 CD 04 26 01 F1 EB E5
         :           }
         :         }
 545  228:       SET {
 548  225:         SEQUENCE {
 551    1:           INTEGER 1
 554   63:           SEQUENCE {
 556   55:             SEQUENCE {
 558   11:               SET {
 560    9:                 SEQUENCE {
 562    3:                   OBJECT IDENTIFIER countryName (2 5 4 6)
 567    2:                   PrintableString 'US'
         :                   }
         :                 }
 571   16:               SET {
 573   14:                 SEQUENCE {
 575    3:                   OBJECT IDENTIFIER organizationName (2 5 4 10)
 580    7:                   PrintableString 'Android'
         :                   }
         :                 }
 589   22:               SET {
 591   20:                 SEQUENCE {
 593    3:                   OBJECT IDENTIFIER commonName (2 5 4 3)
 598   13:                   PrintableString 'Android Debug'
         :                   }
         :                 }
         :               }
 613    4:             INTEGER 1322302491
         :             }
 619    9:           SEQUENCE {
 621    5:             OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
 628    0:             NULL
         :             }
 630   13:           SEQUENCE {
 632    9:             OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
 643    0:             NULL
         :             }
 645  128:           OCTET STRING
         :             22 52 11 23 F5 AA 38 2E 28 FD 96 1E 2C AB 96 FC
         :             E7 85 95 54 A0 F7 14 49 93 F4 19 A7 F0 E5 CC B9
         :             FF 82 B6 8D 84 A2 3A DD F6 CA 6A 4F 3A 38 B4 EA
         :             69 23 BF B1 29 5F C2 49 48 34 63 35 84 59 C6 69
         :             0C E3 F1 D3 90 B5 02 F5 0D 79 CC B4 B0 25 0C BD
         :             38 4F B2 FC D1 D7 D4 11 84 EA A1 66 31 F0 08 DA
         :             0F F6 94 23 96 5C 83 96 C9 DA CA C0 FC 60 84 C2
         :             54 21 DA CA E4 C4 D0 7D FD 98 C4 91 8A 2C 5D E4
         :           }
         :         }
         :       }
         :     }
         :   }

If you are well-versed in the arcana of ASN.1 and the myriad security standards you will recognize this as ‘signed data’ as specified by PKCS#7. If you aren’t, you won’t, but that’s what it is nonetheless.

It is the SHA-1 digest of the CERT.SF file which has been encrypted using the private key corresponding to the public key contained in the accompanying certificate.

There is a bit more to it than that, but that is basically it.

3.0 Signed JAR Verification In Theory

To make life more exciting there can in fact be multiple signature files and signed signature files in a signed JAR but in what follows I am going to assume we are attempting to verify the APK shown in the example above in which there is just the one signature/signed signature file pair.

3.1 Decide Whether You ‘Trust’ The Signer Of The JAR

The signer of the JAR is the entity identified by the certificate which accompanies the signed data in the signed signature file (CERT.RSA).

The decision to ‘trust’ that entity is often made by going up the chain of certificates looking for one which is defined to be a ‘trust root’.

If the certificate that accompanies the signed data in the signed signature file is self-signed or was not signed directly or indirectly by a certificate defined to be a ‘trust root’ then the JAR should be rejected.

3.2 Verify The Signature File

Compute the digest of the signature file (CERT.SF) and use the signature in the signed signature file (CERT.SF) to verify it. If verification fails then reject the JAR.

3.3 Verify The Manifest File

If the expected digest of the manifest file is specified in the signature file compute the digest of the manifest file. If the expected and computed digests do not match then reject the JAR.

Alternatively, for each file in the JAR other than those in the META-INF directory find the corresponding section in the manifest.

If there is no corresponding section reject the JAR.

Otherwise find the expected digest of the section in the signature file.

If there is no expected digest fo the section in the signature file reject the JAR.

Otherwise compute the hash of the section in the manifest. If the computed and expected digests do not match reject the JAR.

3.4 Verify The Remaining Files In The JAR

For each file in the JAR that has not already been verified check that its digest has been specified in the manifest file.

If it has not then reject the JAR.

If the expected digest is specified in the manifest file then compute the actual digest. If the expected and computed digests do not match then reject the JAR.

If all the files in the JAR are successfully verified then accept the JAR.

4.0 Signed JAR Verification In Practice

The Java class java.util.JarFile supports the piecemeal implicit verification of files in signed JARs

4.1 java.util.JarFile

Source: $(ANDROID_SRC)/libcore/luni/src/main/java/java/util/jar/JarFile.java

4.1.1 Constructing A JarFile

4.1.1.1 JarFile(File)

    public JarFile(File file) throws IOException {
        this(file, true);
    }

4.1.1.2 JarFile(File, boolean)

    public JarFile(File file, boolean verify) throws IOException

Passing this constructor a File argument which represents a signed JAR and a verify argument of true will result in a JarFile instance which supports the verification of individual files within the underlying signed JAR.

4.2 The Verification Of Individual Files Within A Signed JAR Using A JarFile Instance

Given a JarFile instance initialized to verify an underlying signed JAR as descibed above there is surprisingly no way to explicitly verify the entire contents of the signed JAR.

Nor is there any way to explicitly verify an individual file within the signed JAR.

The only way to verify an individual file is to read the entire contents of the file. Doing this will implicitly verify the file but only at the point when all the contents have been read.

Since verification of a file involves computing the digest of the contents it is obviously necessary to read the entire contents before being able to verify it.

What is extremely problematic is that there is nothing whatsoever in the API documentation that explains that this is what happens and more particularly that it is not safe to act on anything in the contents of a file in a signed JAR, despite the fact that the contents are being made available via the API, until the entire file has been read.

4.2.1 The ‘Verification’ API

4.2.1.1 getInputStream

     public InputStream getInputStream(ZipEntry ze) throws IOException

The getInputStream method returns an InputStream which can be used to read the contents of the file represented by the JarEntry argument.

If the JarFile instance was constructed with a signed JAR and it is being verified then the method returns a an instance of the inner class JarFileInputStream with an associated JarVerifier.VerifyEntry instance.

4.2.1.2 The JarFileInputStream read Methods

The read methods read from the underlying stream. They then write the bytes read to the associated verifier.

If the call results in all of the file data having been read then verify method of the associated verifier is called. This will throw a SecurityException if the verification fails.

5.0 Signed JAR Verification During The Installation Of An APK By The Android PackageManagerService

When the PackageManagerService finds an APK while scanning a directory it calls the method scanPackageLI.

This triggers the verification of the APK as a signed JAR as follows.

5.1 PackageManagerService

Source: $(ANDROID_SRC)/frameworks/base/services/java/com/android/server/pm/PackageManagerService.java

5.1.1 scanPackageLI

    private PackageParser.Package scanPackageLI(
                                      File       scanFile, 
                                      int        parseFlags, 
                                      int        scanMode, 
                                      long       currentTime, 
                                      UserHandle user)

After determining whether it already knows about the APK, in which case it may return, scanPackageLI calls the method collectCertificatesLI.

5.1.2 collectCertificatesLI

private boolean collectCertificatesLI(
                    PackageParser         pp, 
                    PackageSetting        ps,
                    PackageParser.Package pkg, 
                    File                  srcFile, 
                    int                   parseFlags)

The method calls collectCertificates on the PackageParser argument to do the actual work.

5.2 PackageParser

Class: android.content.pm.PackageParser

Source: $(ANDROID_SRC)/frameworks/base/core/java/android/content/pm/PackageParser.java

5.2.1 collectCertificates

    public boolean collectCertificates(Package pkg, int flags)

The method begins by creating a JarFile using the JarFile(File) constructor.

It then calls the method entries on the JarFile instance.

It then iterates over these entries. For each entry it calls the method loadCertificates.

5.2.2 loadCertificates

    private Certificate[] loadCertificates(JarFile jarFile, JarEntry je, byte[] readBuffer)

The method begins by calling getInputStream on the JarFile argument passing it the JarEntry argument.

It then calls read repeatedly on the InputStream, ignoring what it is actually read, until the entire contents of the file have been read.

As we have seen it is the call to the read method which results in the last of the data being returned which causes the verification of that file.

Notes

  1. The official SHA standard is here (This is a PDF document).


Copyright (c) 2013 By Simon Lewis. All Rights Reserved.

Unauthorized use and/or duplication of this material without express and written permission from this blog’s author and owner Simon Lewis is strictly prohibited.

Excerpts and links may be used, provided that full and clear credit is given to Simon Lewis and justanapplication.wordpress.com with appropriate and specific direction to the original content.

Blog at WordPress.com.

%d bloggers like this: