Convert PEM Response to PCKS12 Data in Swift - ios

We are using AWS iOS SDK for an IoT project in our company. It is a simple application for now. User logs in to our system and tries to connect to the AWS IoT service.
https://github.com/awslabs/aws-sdk-ios-samples/tree/master/IoT-Sample/Swift/IoTSampleSwift
In the sample project above, application generates its own certificate and key pair using AWSIoT SDK. However, in our case, we don't want to generate certificates like this.
We created a Lambda Function on the server side to generate certificates for our users. iOS application requests certificate and as a response server sends a key pair, certificatePem, certificateId and certificate Arn. All of the components are created by AWSIoT SDK, if we use AWSIoTManager.defaultManager(). createKeysAndCertificateFromCsr method.
In this case, we need to import our user identity to the iOS keychain. AWS SDK has another method to handle this problem:
AWSIoTManager.importIdentityFromPKCS12Data method
We need to convert the server response to PKCS12Data to use the generated certificate. How can we do this?
Thanks in advance.

If you've got the key pair, the certificate PEM, certificate ID, and the certificate ARN, you can use the AWS Mobile SDK for iOS's IoT classes as a reference while implementing code for importing these into the keychain. The AWSIoTKeychain class contains methods for importing keys, and the AWSIoTManager -createKeysAndCertificateFromCsr: method imports the certificate into the keychain. Let us know if that information helps, and thanks for using AWS IoT.

Related

Certificate and Private Key from server not in bundle for AWS IOT connection in swift

I am receiving certificate and private key from server to connect with AWS iot. Is there any method that takes certificate and private key as parameters and returns as .p12 file in aws SDK?
Or is there any other way to create .p12 file with received certificate and private key in swift 2.3?
Or if it is any other way, please suggest me
please have a look at this GitHub issue which has details about preparing the .p12 file for use with the iOS sample application. Let us know if that information helps, and thanks for using AWS IoT.

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.

Retrieve Client ios app certificate

I want to proxy traffic from an ios application to Fiddler (or Burp). It looks like the application sends a client certificate to the server.
I will need to retrieve this cert from the phone(it's jailbroken) and import it to my proxy. Is there a way to do that ?
The client certificate is used to identify the client. If the programmer of the app made his job well, you will face difficulties (hopefully). Likely, and most secure, the private key and identity resides in the key-chain. Less secure, it resides in a secured archive (.p12, .pkcs12, .pfx) in the bundle, whose password resides in the key-chain.
If the programmer did his job not so well, you might find the password of the secured archive in the clear somewhere in the apps binary (there're actually floating samples around which do exactly this).

Is it possible to generate certificate signing request(.csr) using security framework in iOS?

I would like to make HTTPS request with a server require client-certificate authentication. I looked into this Creating a SecCertificateRef for NSURLConnection Authentication Challenge. It worked as expected.
However, it needs to prepare the p12 file which includes the private key. It would be secured as it needs a password to import the p12 file using SecPKCS12Import().
However, there could be other option. That is the iOS-client should make a certificate signing request(.CSR) and let a third party (the server) sign it.
For my search, I see that I can use SecKeyGeneratePair() for generating a key pair. But I don't see any API that generate a CSR.
Do I really need OpenSSL to achieve this?
Also, a bit off topic, once the iOS-client somehow receives the signed certificate. I can use SecCertificateCreateWithData() to retrieve an SecCertificateRef(). However, to fill in a NSURLCredential. I also need the SecIdentityRef which come from p12 file using SecPKCS12Import(). How can I retrieve a SecIdentityRef without SecPKCS12Import() but just a certificate file like crt or der?
There is no explicit support for CSR in Security Framework in iOS. However, it is not that difficult to build CSR 'manually' - it is just ASN.1 DER block of data that are available at iOS runtime.
Here is pseudo code of that:
Use SecKeyGeneratePair() from Security Framework to create fresh public/private key
Implement getPublicKeyBits method to retrieve NSData-form of fresh public key (see https://developer.apple.com/library/ios/samplecode/CryptoExercise/Introduction/Intro.html )
Implement getPrivateKey method to retrieve SecKeyRef from Keychain
Follow http://www.ietf.org/rfc/rfc2986.txt to construct ASN.1 DER of CSR in NSMutableData
Use CC_SHA1_* to create signature hash of Certification Request Info (part of CSR)
Use SecKeyRawSign and private key to sign CSR
This will create proper CSR (in form of NSData) that can be sent to CA for approval.
My implementation is available on GitHub: http://github.com/ateska/ios-csr .
To anyone who comes across this in the future, I encountered outfoxx's Shield library which makes it super easy to create CSRs via Swift.

Resources