Doa
Doa

Reputation: 2015

Checking provisioning profile's developer certificate validity

I want to allow customers to upload their own provisioning profile, including icons, so that I can make them a custom version of my app on the fly, which they can then publish.

However, I'm having a little trouble validating the provisioning profile. In particular, I want to check whether the DeveloperCertificate is actually a valid certificate. The profile looks something like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>ApplicationIdentifierPrefix</key>
    <array>
        <string>ABCDEFGH</string>
    </array>
    <key>CreationDate</key>
    <date>2012-03-28T11:17:23Z</date>
    <key>DeveloperCertificates</key>
    <array>
        <data>
        MIIFajCCBFKgAwIBAgIIddUra9YprMQwDQYJKoZIhvcNAQEFBQAwgZYxCzAJ
        BgNVBAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBs
        ZSBXb3JsZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBw
        ...     
        </data>
    </array>
    ...
</dict>

So, I extract the certificate(s) and then want to check them, preferably using an openssl command. What is the encryption used for these certificates, and how do I verify them using openssl? I would think that this uses pkcs12, but trying that gives me an error:

$ openssl pkcs12 -noout -in testcertificate
140653159306912:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:tasn_dec.c:1319:
140653159306912:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error:tasn_dec.c:381:Type=PKCS12

Can anyone point me in the right direction? It is essential that I can somehow verify developer certificates' validity.

Thanks

Upvotes: 6

Views: 5038

Answers (2)

Doa
Doa

Reputation: 2015

I've been looking into this, and it turns out that it doesn't have to be as hard as how David describes it. The solution is actually quite simple:

The certificate is a base64-encoded DER certificate. What you need to do is the following:

  • Extract the certificate from the XML
  • Base64-decode the certificate:

    base64 -d certificate > certificate.crt

  • Test the certificate with OpenSSL:

    openssl x509 -inform DER -in certificate.crt -noout -text

Or, if we pipe it:

cat certificate | base64 -d - | openssl x509 -inform DER -noout -text

The -text option makes openssl give all the details, but you can specify according to your wishes. Suppose, for example, that you are only interested in whether the certificate is an actual Distribution certificate, you can use the -subject option instead and look at the CN= field.

Upvotes: 10

David Hoerl
David Hoerl

Reputation: 41642

Well, I have good news and bad news. I have a friend who is a security expert on Mac/iOS, and he is doing a lot of work in this area. He actually had to so something quite similar. The info I got from his is as follows. But the bad news is no command line way to do it - you will most likely have to spin a Mac app to do it, using the techniques below.

-- technique ---

The certificate inside that XML file ... is read into a NSData object; though usually there are 3 certificates; at least in Apple-generated profiles. Dunno if that's the case.

If there are 3 certificates it's usually enough to check that one of them (usually the last one) is called "Apple Root CA" and has the SHA1 value of hex "611E5B662C593A08FF58D14AE22452D198DF6C60" - I use the SHA1 function in openssl.h for that.

If there's only one certificate that's probably the leaf certificate. To check if that's OK, it's more complicated, since you usually need a complete "trust chain" for verification.

In any case, you have to link against Security.framework, call SecCertificateCreateWithData() with the NSData (suitably cast) to get a SecCertificateRef.

A relative shortcut then might be to call SecCertificateCopyValues() to get the "Authority Key Identifier ( 2.5.29.35 )" field (the dictionary key for that seems to be kSecOIDAuthorityKeyIdentifier) and check if this field's value is hex "E7342A2E22DE39606BB494CE7783612F31A07C35" which seems to be true for all Apple-issued certificates. The return from SecCertificateCopyValues() is a nested dictionary-of-dictionaries, so have to drill down to find this.

The full and complete answer would be to pass the certificate ref to SecTrustSettingsCopyTrustSettings() with, successively, kSecTrustSettingsDomainUser, kSecTrustSettingsDomainAdmin, kSecTrustSettingsDomainSystem, checking if the certificate is either explicitly trusted or not. Unless the intermediate certificate is installed on the machine that will probably fail if it's a leaf certificate.

Upvotes: 0

Related Questions