Storing certificate chains in the application keychain - iphone

On iOS, I know that we can evaluate a trust with SecTrustEvaluate(). To create a trust, we either import it from a *.p12 file or create it using an array of certificates and a set of policies.
I also know that in order to ensure that a server, that is not trusted by default, is trusted, we can use SecTrustSetAnchorCertificates() to augment the list of root CAs SecTrustEvaluate() uses to verify the server's certificate.
Now, how can I ensure that these anchor certificates are available on a subsequent launch? I can store certificates, keys and identities in the application keychain, but not a certificate chain. Even if I store all the certificates in the chain, how will I know what certificates are to be used as anchor certificates?
One solution that comes to mind is to just get all the certificates from the keychain and set them as anchor certificates. Another method could be to all the certificate chains on the disk as *.p12 files and load them once on every application run.

eskimo1 from Apple Devforums answered this so:
First up, you don't need to store the certificates in the keychain. You can store them elsewhere if you like (and create the SecCertificateRef using SecCertificateCreateWithData).
Secondly, your question talks about .p12 files, but I'm not sure what this has to do with things. In general you only use a .p12 file to distribute confidential information, and certificates are not confidential.
Finally, you can store a certificate chain by just storing the persistent reference to each certificate in that chain (or by storing the actual data of each certificate).

Related

Difference between SecPKCS12Import and storing certificate as NSData in keychain?

I've been writing client certificate code for iOS using many of the resources here: iOS Client Certificates and Mobile Device Management and I've broken out the process to these steps:
Get the Cert via email or AppConfig
Store the Cert (securely)
Extract Identity and Trust from the Cert.
Intercept failed web requests, create NSURLConnection to manually handle auth responses as per Eskimo's advice.
Turn Identity and Trust into the auth response challenge.
My problem is step 2. SecPKCS12Import function appears to automatically add Identity to the keychain as well as return all Identities and Trusts from the certificates, thus eliminating the need for the convenience function often given ExtractIdentityAndTrust().
But on my 2nd run, I will need the Identity and Trust, not just Identity. My current plan is to store the entire cert raw using SecItemAdd, test for duplicates and use it, but I feel like I should be able to just use SecPKCS12Import then later grab it without also using SecItemAdd.
The documentation that is most confusing is SecPKCS12Import, and I would like a clearer understanding of what it does vs secItemAdd, and if secItemCopyMatching() is the same in the end just to grab the certificate. Is Trust not needed or am I just being literal and it's stored with the identity?
The general save, use, store, grab is working, but I'm using NSData and would prefer to store it correctly
I eventually became more familiar with the KeyChain and Identity vs Trust and learned this:
The Trust is a Cert stored in a place that determines who your custom Certificate Authorities are. It only needs to be tested once, which is why it isn't stored.
Storing the Identity is also a certificate, but needed for later. The keychain considers Certificates/Identities to be a Special/Unique thing so it is stored as its own thing, which is why all the keychain code looks different than just securing a password.
Basically, storing the Trust is unnecessary for future reference, but should be checked for good practice. I personally think an expiration might be handy

Powershell and trusted certificates

I am trying to implement signed code for some PS scripts, and I have a question about trusting certificates.
I know the "right" way to address this is for IT to use Group Policy to trust the certificate office wide. But many of my customers just don't really have that option. My thought is to provide instructions on using CertUtil.exe to do the job, but I wanted to be 100% sure that adding to trustedpublisher this way still results in the certificate being validated by the issuing authority at startup or login, so a revoked certificate in trusted publishers would in fact not be trusted, correct?
Also, give that the tool to be run is a management tool, my initial thought is to use the tool to drive CertUtil.exe. Basically the first time you use it it adds its own certificate, so you get some user interaction required on first use only. But the idea of code creating a trust for itself seems potentially sketchy, and would raise a little flag for me if I was on the other side wearing my IT hat. So, from a PS distribution model standpoint, is setting up one's own certificate considered appropriate, or verboten, or something of a gray area?
If I recall correctly revocation is almost immediate, with a possible short time lag due to pre-fetching. you can find more info on how exactly revocation is handled here - https://technet.microsoft.com/en-us/library/ee619754(v=ws.10).aspx
As far as adding your own cert I don't see an issue with it but if they require code signing for scripts it won't be able to do it's initial launch, personally I'd send the certutil stuff as a separate script (potentially a batch file) and keep the code you are actually sending over all signed.

Windows Store app sideloading

I have associate my Windows Store app with the Windows store and I got a "Appname_StoreKey.pfx" key file, and I deleted my temporary key. If I create my app package using this key will my app expires after a month?
Temporary key expires on a month but this StoreKey says it will expire after a year. Please explain any cons of this procedure.
Due to company requirement I can't submit the app to the store.
The test certificates will expire one year (not month) after creating them. Technically you can use these to publish your app, but this is not recommended.
The same is true if you get a [appname]_StoreKey.pfx after associating your app with the store.
You can view the expiration date in VS, see screenshot.
This cert is taken to sign your code. The app package signature ensures that the package and contents haven't been modified after they were signed.
When you're not deploying using the store the disadvantage is that during deplyoment, the certificate is not trusted. This is in both cases no matter if you take the testcert or the storekey.pfx.
Your users are required to first install the certificate. This is something they might not be able to do (missing rights) or don't dare to do (because they're scared).
When you take a closer look, you will find that the issuer name of testcert might look good, and probably looks very strange (long guid) for a StoreKey.pfx . So users who are asked to install the cert might be scared for a reason.
The best way is to use your own certificate that you created that won't expire too early and that is installed by your IT device management Infrastructure (if you're building a company app for example). This will lead to a struggle-free installation for users.
Using a test certificate is possible technically but not a very "clean solution".
Also check out this post
https://msdn.microsoft.com/en-us/library/windows/apps/br230260(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/apps/jj835832.aspx

Accept untrusted SSL server certificate with CFStream socket on iOS

I need to open a CFStream socket connection to a server that has an untrusted CA root. I have the certificate of the server, and I can create a SecCertificateRef structure from it. The problem is how to set up the properties of the stream.
I think I should set the kCFStreamPropertySSLSettings property to a CFDictionary that in turn contains a kCFStreamSSLCertificates key. This key should hold a "a CFArray of SecCertificateRefs except for the first element in the array, which is a SecIdentityRef" according to the docs. Now I can create the SecCertificateRef from the server's certificate that I'll ship with the app, but how to get the SecIdentityRef? I guess it should be the client identity but I absolutely don't want client side authentication for now. And I can't find a way how to feed CFStream only with the server certificate.
Note, I don't want to add the untrusted certificate to the keychain, neither disable kCFStreamSSLValidatesCertificateChain in the settings. I need to accept the server authentication only if it is based on my own server certificate data loaded from the disk, and only on this CFStream.
I do not have the direct answer to your question, but perhaps few guidelines:
Why do you need to use the CFStream API and not the more intuitive NSURLConnection ?
From what I could find in the documentation, it seams like not everything that is available for Mac OS X, regarding CFStream API, is available for iOS. So think about it, and see if you can switch to NSURLConnection :-)
For NSURLConnection, you can use the NSURLConnectionDelegate methods to get the SSL challenge and validate the certificate on your own. You can check the wsdl2objc project, where I have implemented these features:
The project: http://code.google.com/p/wsdl2objc/
Some guidelines on how to get the certificate references: http://code.google.com/p/wsdl2objc/wiki/AdvancedOptions
Now about your questions :-)
I don't see how you can set a custom (untrusted) CA in kCFStreamPropertySSLSettings. I'm not sure if it can be done by using kCFStreamSSLCertificates since it is meant to be used for setting client-side certificates (thus the requirement of having the SecIdentityRef on index 0, which basically provides the private key).
When you say you don't want to add the certificate to the keychain, do you mean manually or programmatically ? I guess you don't like the users of your app to have to do it manually, but you can use the Security API to import the certificate programatically. In this case your certificate will be imported in a sandboxed keychain which is only available for your application. (again, not sure if this will work but worths the try)
In my applications I use NSURLConnectionDelegate to manually validate untrusted certificates.
Regards,
Pece
Basically you have to:
disable default trust evaluation using kCFStreamSSLValidatesCertificateChain
get the trust object (kCFStreamPropertySSLPeerTrust) once connected to the stream (but before sending any data, i.e, on kCFStreamEventCanAcceptBytes or kCFStreamEventHasBytesAvailable events)
set your self-signed root certicate as a trusted anchor for that trust object
optionally, you may add custom SSL policies to the trust object (e.g, hostname doesn't match certificate CN), but if you do that it's important that you do it before setting the trusted anchor or you may get kSecTrustResultRecoverableTrustFailure result
evaluate the trust object (SecTrustEvaluate) and check result is either kSecTrustResultProceed or kSecTrustResultUnspecified

Obtaining a Digital Certificate

We have a .net WPF application running as both XBAP and Desktop etc.I haven't signed any assemblies etc.My question is that
Q1.What kind of Digital Certificate do I need to purchase from VeriSign, Inc., or another certificate authority. to sign my application,use it as Authenticode Certificate (in clickonce) ?
Q2.Can I use this Digital Certificate to sign other applications like installers,assemblies,pdf etc?
Q3.Is one Digital Certificate enough for a company or I have to buy other?
Q4.What happens when the Certificate expires? (So is it better to not have it and screw yourself if no one is gonna hack and plant a virus in you app folder or something ???)
A1. You need a code signing certificate. They come in several flavours, and typically can be converted from one to the other, but it's probably easiest to get an Authenticode one rightaway.
A2. You can use the same cert to sign installers and assemblies (and any .EXE, .DLL, .OCX file). I think the same applies to .PDF, but I've never used that.
A3. I'd go for a single cert for your company.
A4. When the cert expires, you cannot use it for signing anymore. However, as long as you use a timestamping service when you sign your code, already signed files remain valid.
A1: You need code signing certificate. You may choose any provider, but do notice that not all of them are recognized by Windows as "trusted". Among trusted and cheaper ones (cheaper then VeriSign) there is Comodo.
A2: Yes.
A3: One is enough.
A4: You will not be able to sign new code. Old code will remain signed if you used timestamp server (you'll get location of one with certificate). If you opt not to use timestamp server, certification will remain valid, but users will get message that it it expired.