Retrieving certificate stored via Safari during enrollment - ios

How can we retrieve identity certificates received from SCEP during enrollment in objective c.
I guess the certificates are stored in KeyChain Access of the device.
PS: I read somewhere that we cannot access other apps keychain via any 3rd party app, so is it possible to get the certificates stored during enrollment process of MDM

I think you can't access it. As you correctly mentioned, it's stored in keychain. And I believe in this case, it will be stored in keychain of Safari or mdmd. And you don't have access to either of those on your device (except, if it's jailbroken).
However, if Certificate authority in your control, potentially you can write server side code which will allow query certificate (not a private key) for your device. Your application will talk to your server and it will go to Certificate authority and get a certificate associated with your device.

Related

Security of SSL Pinning

I have an iOS app which implements SSL Pinning. I compare the remote certificate against the locally stored certificate and proceed depending on the result of the comparison. If both certificates are equal, the URL connection is permitted. Otherwise, it is denied. My question is this: Can an attacker change the local certificate stored in the app (.ipa) with another certificate?
This would allow the attacker to see all of my requests and responses.
Thanks.
Yes, but only on jailbroken device, since on non-jailbroken device you can't view the content of the installed application.

Is it possible to refer to a certificate in Azure Key Vault via a file name?

In the scenario for this question I am using a library that takes a certificate path as a parameter.
Does that mean that it is not possible for me to store my certificate in Key Vault?
Does that mean that it is not possible for me to store my certificate in Key Vault?
It is possible, but you have to give it a Name (key) to access it.
When you add/import x.509 certificates to Azure Key Vault Certificates, you give it a name (which acts as a unique key for that certificate), and you access that certificate by that name.
More info here: https://blogs.technet.microsoft.com/kv/2016/09/26/get-started-with-azure-key-vault-certificates/
Now, with regards to your other question, I am assuming you are wondering how to access a certificate from an Azure function. In your other question, you have this:
ApiSettings["SigningCertPath"]
And you indicated, you are using a (3rd party) library which picks the signing certificate path, and presumably loads that certificate. I do not know how your (3rd party) library works, or if it even works with Azure Key Vault. But it appears your library is loading the cert from a file. You did not mention if you still would like to do it that way.
But as alternative, you can load/import your certificate into your Function App (Platform features > SSL). Besides taht, you also need to add this entry to the Application Settings (on Azure portal): key WEBSITE_LOAD_CERTIFICATES and the value of *. This loads all certificates in your SSL bindings and into your Function App's certificate store. Then your function can read/get the certificate as you would get it from a local certificate store.
You can do the above instead of storing your certs in Key Vault. But you can also have all your other certs in Key Vault and only store the client certificate you need to access Key Vault from within your function.

iOS - how do I get server certificate into iOS client keychain for pinning

TL;DR version: Is there any way to pass a Server certificate to an iOS client that doesn't involve also passing along the Server's private key?
I have written an iOS client app that communicates with my macOS server app (so I have control over both ends). I have implemented certificate pinning using a self-signed certificate to make things more secure. To accomplish this during development, I hardcoded the Server cert into the iOS client app and told the client to only connect to a server that gives you that exact cert during the TLS handshake. Everything is working great.
However in the real world I am selling this system as a set (1 Server, multiple clients to each customer), so I cannot hardcode a Server cert into the iOS client. My plan is to instead deliver the Server cert out of band (via email) to the iOS client like mentioned here: Making Certificates and Keys Available To Your App:
Apps can only access keychain items in their own keychain access groups.
To use digital identities in your own apps, you will need to write code to import them. This typically means reading in a PKCS#12-formatted blob and then importing the contents of the blob into the app's keychain using the function SecPKCS12Import
One way to provision an identity is via email. When you provision a device, send the associated user an email with their client identity attached as a PKCS#12 file.
My problem is that a .p12 file contains the certificate and the private key of the server - this seems very wrong to pass the private key along as well.
Is there any other way to pass the Server certificate to the iOS client that doesn't involve also passing along the Server's private key?
Thanks!!!
I was overthinking things here, the solution is actually pretty simple.
I just needed to email the Server's public certificate out of band to the client device with a custom extension like cert.myCustomExt1234. This is because the .crt extension is already claimed by iOS so you have to register your app to handle custom extensions (see apple docs here). Then in my app I can do all the logic of cert pinning using that out of band delivered Server public cert.
The key was changing the file extension to something not already claimed by iOS.

Validating requests in /server url

In iOS MDM /server url will be called for each operation by the device when it is woken by APNS. I have securely encrypted and signed other profiles at the time of enrollment and successfully passed the server url to device. Its working fine but I have few concerns over this server endpoint as follows.
1) Any client or entity who could send similar plist payload can invoke this service. If a 3rd party has access to a device UDID they can compose this xml payload and invoke this service. From the server point of view it will be hard to track this behavior and identify real devices. To identify that in the real scenario will it send and CMS data or related to validate this scenario?
2) Once the device hit this endpoint from server we can generate operation profiles and send back to devices. For the profiles at the enrollment time we could extract the public certificate from CMS data and encrypt from that. But for this server url how do I achieve that? Seems its not getting any cert like that from device side. Just wondering whether to save the public keys we got in earlier stages but since at the enrollment it goes through 2 SCEP calls not sure what to use it. Will those subsequent profiles payload can be encrypted using previous public cert? Right now I do the signing anyway which works fine.
1.) Any client or entity who could send similar plist payload can invoke this service. If a 3rd party has access to a device UDID they can compose this xml payload and invoke this service. From the server point of view it will be hard to track this behavior and identify real devices. To identify that in the real scenario will it send and CMS data or related to validate this scenario?
Yes, Any client who could possess the UDID and Server URl can send a valid Plist to your server acting like the device.
But they cannot sign the plist with the private key in the device(Which is generated during SCEP enrolment). You would be having corresponding Public key for it to validate the signature.
To force the device to send the signature along each request to Server URL, you have to include SignMessage tag in your MDM payload and set it as true. Like this
<key>SignMessage</key>
<true/>
So when you include this tag along with your MDM payload, you would be get the signature of Identity Private key in the Header HTTP_MDM_SIGNATURE.
Then you can validate the signature using your public key.
2.) Just wondering whether to save the public keys we got in earlier stages but since at the enrollment it goes through 2 SCEP calls not sure what to use it.
Yes I mentioned in the previous answer you should save the public certificate which is issued during SCEP phase. Later you will use that public certificate to Validate the signature from Device and Encrypt the profile you are sending.
Regarding 2 SCEP calls, First SCEP call is to generate the certificate and securely transfer the MDM Payload and actual SCEP payload which will be used as Idenitity certificate for MDM.
So you should use the second one for validating the signature and encryption.
One more hint is, you would have mentioned IdentityCertificateUUID in your MDM payload. The Identity Certificate SCEP payload should have same UUID as its PayloadUUID . That SCEP payload's certificate will be used as the identity certificate for MDM.
Ok. The bottom line that you want to authenticate device.
Each device has an identity cert (a cert distributed in PKCS12 or through SCEP).
Each time when a device communicate to the server it does authentication using SSL client certs.
Most of the time there is a reverse proxy sitting upfront of your web server. It could be Apache or Nginx or anything else. This reverse proxy terminates SSL connection and checks client certificate. Usually, they are configured to pass this client certificate as a header to your web application.
This way your web app can get this header, get a certificate out of it and check against your DB whether a device with specific udid (passed to your endpoint) have a certificate (passed to your webapp in the header).
I am not sure which reverse do you use and whether it's configured properly to pass the certificate.

iOS MDM profile signing, which certificate to use?

Okay, so look at this diagram.
There are two little boxes, that signify how a given profile should be signed.
In Phase 2, step 1, it says "Apple issued certificate", but it doesn't say which apple issued certificate (they issue more than one). I have tried my developer certificate and the MDM (APNS) certificate. It wasn't one of those. Is there a third magic certificate I somehow need (and how do I get it)?
In Phase 3, step 2, it says "Identity certificate", but again it's a little sketchy on the details. The only identity certificate I know of is installed on the device, using the device's private key, how is the server supposed to use that to sign a profile?
The only way I've gotten this to work, is by creating my own self-signed certificate, and pre-installing it on the device. Obviously this is not an elegant or particularly secure way to do things.
Follow up questions
My server certificate is issued by "DigiCert High Assurance EV Root CA" and is on the list: http://support.apple.com/kb/ht5012, but iOS 6 devices consider it "untrusted" when signing profiles, but just fine for SSL which is wierd. iOS 5 devices are fine though. Any idea why?
I don't really understand the encryption bit either. From the MDM documentation: "Each device must have a unique client identity certificate. You may deliver these certificates as PKCS#12 containers, or via SCEP. Using SCEP is recommended because the protocol ensures that the private key for the identity exists only on the device."
While I agree it is ultimately more secure that only the device itself knows its private key, it's somewhat problematic as a 2048-bit public key can only be used to encrypt about 100 bytes of data, which isn't enough for even the smallest possible payload.
Let me go over phase 2 and phase 3 first
In the Phase 2, step 1, iOS device will send to a server response which is signed by device certificate/key (each device comes with preinstalled certificate/key which is different for each device). These on device certificates/keys are issued by Apple.
On the server side, you should verify it using Apple Root Cetificate.
In the Phase 2, step 1-3 your profile service will send a SCEP request. This SCEP request contains information to let device know to which SCEP server it should talk. This SCEP server is your server. So, a device will talk to this SCEP server and will request new identity certificate from it.
In Phase 3, step 2 device response will be signed with certificate/key of this identity certificate. And now you should verify it with your Certificate authority root certificate. (One more note SCEP server in Phase 2 is kind-of proxy to yours Certificate authority)
And now answering your questions "MDM profile signining, which certificate to use?"
MDM profile could be encrypted and/or signed.
If you want to encrypt it, you encrypt it using identity certificate associated with this device. So, device which has a key for this identity, so it can decrypt it.
If you want to sign it, you sign with your server key. Device should have a server certificate installed, so it can verify signature.
BTW. On this subject. One thing which isn't shown on this diagram, but usually is requited - first step (before whole this enrollment) is usually installation of server certificate (for future profile signature verification). Potentially, you can skip this step if your server certificate is issued by well known CA (as example Verisign or something like that).
Let me know, if you have any followup questions. It took me a while to understand whole this OTA/MDM enrollment.
Update 1
I don't know why iOS 6 treat your certificate as untrusted for signing. I didn't work with certificates which were signed by well known CA's.
I have only one guess. It could be that between iOS 5 and iOS 6 they changed something regarding key chain. Generally speaking, each app has it's own key chain. And all well known certificates, I believe should be stored in Mobile Safari keychain. It could be that MDM/Preferences shared this keychain with MobileSafari in iOS 6 and now they don't share it.
In such case, you will have to install this "DigiCert High Assurance EV Root CA" through a profile (to put it in correct keychain). However, it's wild guess.
Regarding encryption. First of all, you are right, if each device has it's own private key, it's way more secure. In such case, if anybody will steal a profile they won't be able to decrypt it (because only a device has a private key to do so). This is especially critically, if you are sending down profiles which are sensitive (as example, email account with both user name and password).
Very high level introduction into cryptography:
Any key (with any length) can encrypt data of any length. All encryption algorithms are designed that way that you can use the same key to encrypt any amount of data.
Asymmetric algorithms (like RSA) rarely used to encrypt data directly. In most cases, this algorithm is used to encrypt a key for symmetric algorithm (as example AES) and all following encryption/decryption is done using AES. There are two reasons for that: performance (AES is faster then RSA) and resources (AES is less resource hungry than RSA).
So, as result, if you need to encrypt profile you use PKCS7, which is internally uses RSA, AES (or other algorithms). Usually, you have a library to do this (OpenSSL or BouncyCastle). So, you don't have to figure out all these complexities.
BTW. If you have questions which aren't good fit for SO, you are welcome to contact me directly (my contact info in my profile).

Resources