iOS Code Signing Part 2

In the previous post for the iOS Code Signing we talk about the certificates and how they work. Certificates are needed to sign all the software that the developers are going to deploy to an iOS device. When we build an application with Xcode it invokes “codesign”. This generates a signature of the contents of the executable code in the binary using the private key associated with the identity certificate that was created by Apple. The signature will be embedded into the executable binary. It allows it to be validated and also ensure that the code that the application has cannot be modified without causing a validation error.

But the signed binary is not enough to be sure of the integrity of the application because the iOS applications are comprised with more stuff that the executable binary.

So, to continue with the learning of the signing process, in this post we are going to analyze and try to understand the different parts of the .app files and the Provisioning Profiles.

 

The .app files

There are two different types of .app files: OS X applications and iOS applications. OS X applications are the ones for Apple computers and iOS applications are the ones for Apple devices and they have a different structure.

OS X applications structure

OS X applications are files with .app extension. This is called bundle, a directory that contains  structured contents. They are directories with file extensions. That allows another programs load them or launch them. For example you can launch Xcode application by clicking in the Xcode Dock icon, double clicking in the .app file in Finder or searching Xcode in Spotlight and press enter. This is possible because .app bundles get loaded by LaunchServices, a system responsible for running software that gets started by other software.

If you right-click in the file and click in Show Package Contents you can see the Contents folder:

This is what you can see inside an OS X bundle folder:

  • _CodeSignature: a directory that contains CodeResources file.
  • Frameworks: this directory includes all the dynamic libraries and frameworks used by the application.
  • Info.plist: it contains the most critical keys required by the system and they are almost always accessed by it. It ensures that the system has the information it needs to work with the app.
  • MacOS: include the executable binary.
  • PkgInfo: contains a 4-byte package type followed by the 4-byte signature of the application. This file is created the same time as the bundle.
  • Resources: this directory includes resources available to the application. You can find a lot of different type of files like audio, icons, window layouts, etc. (Even the archived-expanded-entitlements.xcent)

iOS applications structure

iOS applications are files with .ipa extension. They are also bundles the same way as the OSX applications but the structure is a little bit different. If we decompress the .ipa we can see the Payload folder. In this folder is the .app bundle. And this is what it includes:

  • _CodeSignature: a directory that contains CodeResources file.
  • .png files: files for the application icons.
  • archived-expanded-entitlements.xcent: since Xcode 6, this file has been embedded in the app bundle. It is a list of entitlements that the app has requested and when submitting the app to the AppStore provides also more helpful error messages when the provisioning errors occur.
  • Assets.car: that contains the multiple resolution images for each device you use when create the application. They are the ones that appears in Xcode IDE in Assets.xcassets.
  • Base.lproj: contains the .storyboard and .xib files in the development language. Other folders with the .lproj extension are included if you select multiple languages.
  • embedded.mobileprovision: the embedded provisioning profile.
  • Frameworks: this directory includes all the dynamic libraries and frameworks used by the application.
  • Info.plist: it contains the most critical keys required by the system and they are almost always accessed by it. It ensures that the system has the information it needs to work with the app.
  • PkgInfo: contains a 4-byte package type followed by the 4-byte signature of the application. This file is created the same time as the bundle and it is not necessary for the functioning of an iOS app.
  • SolidGeariOSExample: is the executable binary for this application.

But the important thing to us is the _CodeSignature folder. As we said before it contains the CodeResources file. This ensures that not only the binary remains unmodified, but also the data and assets that are used while it is being run. The CodeResources file is a plist with all the fields that are included as part of the bundle with a hash for each one. This can be used to validate that the contents of the bundle are untouched. To prevent the application from invalidate its own signature there are some resources that can be configured to be omitted or updated. All of this allows the developers to sign a builded project and know if the binary they are going to distribute is the same as the one they built.

 

The Provisioning Profiles

The certificates we explained in the previous post are used to validate the authenticity of the signer of the application. The Provisioning Profiles  are used to allow an application to be installed on a device. You need to select the App ID,the appropriate Entitlements and the UDIDs for the devices you want to install the app. Apple digitally signs the file (a PKCS#7 signed plist) so the file cannot be modified after being created if you want to use it.

Apple verify that the application being installed is from the right developer and the content inside the plist has not been modified.

To verify that the signature is correct you can use this command:

openssl smime -in ProvisioningProfilePath/SolidGearExampleiOS.mobileprovision -inform der -verify

If everything goes well you will see the message:

</dict>

Verification successful

</plist>%

So what happens, for example if you edit using vi a Provisioning Profile. If you change the ApplicationIdentifierPrefix string to another one with a valid format (i.e. ten digit string composed by numbers and letters) you can see:

Verification failure

29456:error:21071065:PKCS7 routines:PKCS7_signatureVerify:digest failure:/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-64.50.7/src/crypto/pkcs7/pk7_doit.c:1039:

29456:error:21075069:PKCS7 routines:PKCS7_verify:signature failure:/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-64.50.7/src/crypto/pkcs7/pk7_smime.c:312:

But if you change this string for another one without the correct format the error message that appears is:

Error reading S/MIME message

29616:error:0D07207B:asn1 encoding routines:ASN1_get_object:header too long:/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-64.50.7/src/crypto/asn1/asn1_lib.c:153:

29616:error:0D068066:asn1 encoding routines:ASN1_CHECK_TLEN:bad object header:/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-64.50.7/src/crypto/asn1/tasn_dec.c:1331:

29616:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-64.50.7/src/crypto/asn1/tasn_dec.c:678:Field=cert, Type=PKCS7_SIGNED

29616:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-64.50.7/src/crypto/asn1/tasn_dec.c:768:

29616:error:0D08403A:asn1 encoding routines:ASN1_TEMPLATE_EX_D2I:nested asn1 error:/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-64.50.7/src/crypto/asn1/tasn_dec.c:598:Field=d.sign, Type=PKCS7

 

Inside the Provisioning Profile

The first part until you can see the start of the plist label is the header of the PKCS#7 signature and the part at the end of the file is also part of the signature.

Here we listed the key/values included in this plist in the order they appear in the file:

  • AppIDName: the AppID name in the iOS Provisioning Portal.
  • ApplicationIdentifierPrefix: the ten characters string that is generated when the App ID is created. Also known as the  App ID Prefix or the Bundle Seed ID.
  • CreationDate: the date for when the Provisioning Profile was created.
  • DeveloperCertificates: it is an array that contains the certificate. To inspect the certificate you can copy the text between the <data> labels and paste it between these two lines:

—–BEGIN CERTIFICATE—–

TEXT YOU COPY INSIDE THE <DATA> LABELS

—–END CERTIFICATE—–

           Separate the text in 64 character rows and name the file with .pem extension, for example SolidGearExampleCertificate.pem and use this command:

                   openssl x509 -text -in SolidGearExampleCertificate.pem

  • Entitlements: a dictionary that contain values related to Push Notifications, iCloud, GameCenter, PassKit, etc.
  • ExpirantionDate: the date this Provisioning Profile expires.
  • Name: the name for the Provisioning Profile when the file was created in the Apple Developer Portal .
  • ProvisionedDevices/ ProvisionsAllDevices: first one includes the list of UDIDs on which the application can be installed. The second one is available for Enterprise accounts and “In House Distribution” and as the name of the key says any device can install the app associated with this Provisioning Profile. A Provisioning Profile can have only one of these two keys.
  • TeamIdentifier: an array with only one value, the identifier for the team to which this Provisioning Profile belongs
  • TeamName: the name for the team which this Provisioning Profile belongs.
  • TimeToLive: a value that shows the number of days that this Provisioning Profile is valid.
  • UUID: a unique identifier that changes every time this file is updated.
  • Version: the current version of this type of files.

The purpose of the Provisioning Profile is to allow the installation of your application in devices. The file include information about the devices and  the software you need. Because of the signature you can be sure that you are installing the same application that the developer created. Additionally, with a basic Developer account for Apple, the administrator can control the particular devices that can install the app (100 maximum, and unlimited with Enterprise Developer Account).

Now when you build and .app file you know what is the result and also you know how works the file you need to install your application in a device. Next time we will see more things about the iOS Code Signing.

Other interesting articles

SimpleBar Chart with UIStackViews

Automated test for iOS with appium: set up the environment

Leave a Comment

By completing the form you agree to the Privacy Policy