How-to sign an iOS configuration profile generated programmatically in Xcode?

Context

I have a iOS app (Swift) that generates some MDM iOS configuration profiles (*.mobileconfig) programmatically.

App users enter some informations, then app generates a configuration profile "on-the-fly" with the user-specific data, open in Safari on localhost server via Swifter (GitHub link), so the user can click this link and install it on its iOS device.

In short: this profile contains in its payload only a webclip (safari shortcut).

Everything works fine, the configuration profile link opens the iOS Settings app that asks the user to install this profile on its device.

My problem is that this programmatically generated profile is not signed. So the user is warned by iOS that the profile is not signed and he must do several additional actions to confirm the profile installation.

I would like that the generated profiles to be signed, **so the user can install them more easily and quickly. **

Questions

  • is it possible?

  • if yes, is it possible with Swift (or Objective-C)?

  • if yes, how can I do that?

I read some ressources about signing configuration profiles, but I don't have any skills about signing, certificates etc.

That's not clear for me!

Any help appreciated, thanks in advance!

There’s three aspects to this:

  • How do you sign a configuration profile?

  • Digital identity provisioning

  • Whether this is a good idea at all


With regarding signing a configuration profile, signed profiles are actually CMS signed data values. To see this in action, take an example signed profile (I used the CFNetwork for iOS profile from our Profiles and Logs page) and dump it like so:

% xxd CFNetworkDiagnostics.mobileconfig 
00000000: 3082 1665 0609 2a86 4886 f70d 0107 02a0  0..e..*.H.......
00000010: 8216 5630 8216 5202 0103 310d 300b 0609  ..V0..R...1.0...
00000020: 6086 4801 6503 0402 0130 820b 8206 092a  `.H.e....0.....*
00000030: 8648 86f7 0d01 0701 a082 0b73 0482 0b6f  .H.........s...o
00000040: 3c3f 786d 6c20 7665 7273 696f 6e3d 2231  <?xml version="1
00000050: 2e30 2220 656e 636f 6469 6e67 3d22 5554  .0" encoding="UT
00000060: 462d 3822 3f3e 0a3c 2144 4f43 5459 5045  F-8"?>.<!DOCTYPE
00000070: 2070 6c69 7374 2050 5542 4c49 4320 222d   plist PUBLIC "-
00000080: 2f2f 4170 706c 652f 2f44 5444 2050 4c49  //Apple//DTD PLI
00000090: 5354 2031 2e30 2f2f 454e 2220 2268 7474  ST 1.0//EN" "htt
000000a0: 703a 2f2f 7777 772e 6170 706c 652e 636f  p://www.apple.co
000000b0: 6d2f 4454 4473 2f50 726f 7065 7274 794c  m/DTDs/PropertyL
000000c0: 6973 742d 312e 302e 6474 6422 3e0a 3c70  ist-1.0.dtd">.<p
000000d0: 6c69 7374 2076 6572 7369 6f6e 3d22 312e  list version="1.
000000e0: 3022 3e0a 3c64 6963 743e 0a09 3c6b 6579  0">.<dict>..<key
000000f0: 3e43 6f6e 7365 6e74 5465 7874 3c2f 6b65  >ConsentText</ke
…

As you can see, it contains a property list that’s embedded in some wrapper. This is the CMS wrapper and you can extract it like so:

% security cms -D -i CFNetworkDiagnostics.mobileconfig 
<?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>ConsentText</key>
…

iOS does not have APIs for encoding or decoding CMS values [1]. You’ll need to write, or acquire, your own code for this.


To sign a profile you need a digital identity. Your goal is to create a profile that is trusted by the device by default. This is going to be challenging:

  • It’s hard to get a digital identity that can sign profiles so that they’re trusted by the device (more on this below).

  • Even if you can, you can’t sign on-device because that requires your app to have a copy of the digital identity, and if your app has a copy then there’s a chance that someone could extract it from the app and use it to sign their own profiles. The only reasonable way to do hold the digital identity on a server and use that to sign profiles.


The reason why the above is such a problem relates to my last point: Should you be doing this at all?

Configuration profiles are intended to be used in a managed environment. In such environments it’s typical for the initial management setup to include a custom root certificate. With that root certificate installed, any certificate issued by that root is trusted by the device. So the management system can issue a signing certificate for the profile system, and any profiles it signs are trusted.

Doing this outside of a managed environment is tricky because the built-in root certificates come from CAs that are reluctant to issue you general-purpose signing certificates.

So, are you planning to deploy this app in a managed environment?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] We do have an API for this on macOS, namely CMSEncoder, but it’s not available on iOS.

Thank you for your answer.

I have an app that’s allows users to create WebClips and install it via Mobileconfig. So when user try to install it they see «Not signed» warning. 

  • Should I sign it?
  • Will App Store Review Team approve the app if it’s allows install not signed Mobileconfig file with WebClips that created on device?
  • If I should sign the only way is to do it is use the server with signing mechanism?

Will App Store Review Team approve the app … ?

I don’t work for App Review, and only they can give you a definitive answer about what will or won’t be allowed on the App Store. However, you are right to be concerned about this. I’ve seen developers try to use this technique to get around critical iOS security restrictions, both for benign reasons like this and for malicious ones, and my experience is that App Review takes a dim view of such things.

I will say that:

  • Configuration profiles are intended to be use in managed environments.

  • They are not intended to be used by App Store apps as a substitute for features that aren’t provided by the iOS SDK.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

How-to sign an iOS configuration profile generated programmatically in Xcode?
 
 
Q