The curious case of duplicated certificates sent by iOS

Here’s another one on certificates. Let’s say you are trying to do client certificate-based authentication in your iOS app and you came up with something like this:


- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
 if ([challenge previousFailureCount] > 0) {

 NSLog(@"Incorrect auth challenge %@", challenge);
 [[challenge sender] cancelAuthenticationChallenge:challenge];
 return;
 }

 // Checking the server certificate
 if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodClientCertificate &&
 self.account.clientCertificate.privateRepresentation.length > 0) {

 /*
 Reading the certificate and creating the identity
 */

 NSData *p12Data = self.account.clientCertificate.privateRepresentation;

 CFStringRef password = (__bridge CFStringRef)(self.account.clientCertificate.privatePassword);
 const void *keys[] = { kSecImportExportPassphrase };
 const void *values[] = { password };
 CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
 CFArrayRef p12Items;

 OSStatus result = SecPKCS12Import((__bridge CFDataRef)p12Data, optionsDictionary, &p12Items);

 if(result == noErr) {
 CFDictionaryRef identityDict = CFArrayGetValueAtIndex(p12Items, 0);
 SecIdentityRef identityApp =(SecIdentityRef)CFDictionaryGetValue(identityDict,kSecImportItemIdentity);

 SecCertificateRef certRef;
 SecIdentityCopyCertificate(identityApp, &certRef);

 SecCertificateRef certArray[1] = { certRef };
 CFArrayRef myCerts = CFArrayCreate(NULL, (void *)certArray, 1, NULL);
 CFRelease(certRef);

 NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identityApp certificates:(__bridge NSArray *)myCerts persistence:NSURLCredentialPersistencePermanent];
 CFRelease(myCerts);

 [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
 }
 else {
 // Certificate is invalid or password is invalid given the certificate
 NSLog(@"Invalid certificate or password");
 return;
 }
 } else {
 // For normal authentication based on username and password. This could be NTLM or Default.
 if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodClientCertificate) {
 NSLog(@"Certificate might be required");
 }
 NSURLCredential *credential = [NSURLCredential credentialWithUser:self.account.username
 password:self.account.password
 persistence:NSURLCredentialPersistenceNone];
 [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
 }

}

All looks good, doesn’t it? And in most cases – it will even work fine. Unless your server handles the handshake, something goes wrong and you look at what happens on the wire:

iOS certs

Can you see what happens here? The client certificate is sent twice. That is not always an issue, but if your server is parsing the certificates, and expects them to be in order, and expects that the first one is the client certificate and what follows is the issuer… you are in trouble.

You may argue whether this is a client bug or the server issue… I would say the client should be fixed. Per RFC2246 and RFC5246 the certificate structure should contain sender’s cert once.

certificate_list
This is a sequence (chain) of X.509v3 certificates. The sender’s
certificate must come first in the list. Each following
certificate must directly certify the one preceding it. Because
certificate validation requires that root keys be distributed
independently, the self-signed certificate which specifies the
root certificate authority may optionally be omitted from the
chain, under the assumption that the remote end must already
possess it in order to validate it in any case.
The same message type and structure will be used for the client’s
response to a certificate request message. Note that a client may
send no certificates if it does not have an appropriate certificate
to send in response to the server’s authentication request.

So how do we fix it? Fortunately the fix is trivial. Change this line:

NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identityApp certificates:(__bridge NSArray *)myCerts persistence:NSURLCredentialPersistencePermanent];

to this:

NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identityApp certificates:nil persistence:NSURLCredentialPersistencePermanent];

And everybody is happy again. The app sends a single certificate only, no change on the server required.

FM radio coming in Windows Phone 8 GDR2?

The Verge quotes Microsoft sources claiming FM radio support in upcoming WP8 update. General Distribution Release 2 (GDR2, Portico was GDR1) is supposed to add FM radio support to Nokia Lumia 920, 820 and other compatible phones. Looks like the registry keys were there for a reason.

Verge also mentions Nokia-specific GDR2 updates: double-tap to wake the device from standby, flip to silence option, color profile settings for the device screen.

The update will be made available over the coming months, I assume before Google ultimately turns ActiveSync off for WP users on July 31st.

Peeking inside Windows Phone 8 registry

Windows Phone 8 lacks, unfortunately, a bunch of tools – including something that would show you logs or registry. This limits your ability to see what is really going on in the phone. Forums like Windows Phone 8 Development and Hacking show you how to mount ffu or describe partition layout – that helps.

So to aid you a bit see below for a way to read registry from a WP8 emulator

  1. Launch WP8 emulator and do whatever you want to check later (for example enroll the phone with Intune)
  2. While the emulator is running, copy %userprofile%\AppData\Local\Microsoft\XDE\*.avhd to another folder, for example on your Desktop (that folder should contain a single .avhd file). Why do you want to do it while the emulator is running? The reason is .avhd is not merged back into emulator’s disk when you shut it down. Every time you shut down the emulator it essentially resets all settings and forgets whatever you did in the previous session. There should be a way around this – by running XDE.exe manually – but since that stopped working on my system recently, I won’t consider it a working alternative.
  3. Rename .avhd to .vhd
  4. Right-click on the .vhd and mount the disk
  5. Your system now should have couple new drives mounted (WP8 partitions) – we’re looking for the one with \Windows\System32\config\SOFTWARE (my case it was G drive)
  6. Copy the entire \Windows\System32\config folder somewhere else, for example to your Desktop
  7. Clean file attributes (read-only, archive, system) on all files in this folder
  8. Mount SOFTWARE hive using regedit (http://www.petri.co.il/edit_registry_settings_for_users_other_than_myself.htm)
  9. Profit!

So what’s interesting there?

  • Looks like there are FM radio-related keys – so was Microsoft preparing to support it?
  • The MDM related stuff:
    • \Microsoft\Enrollment – phone enrollment information
    • \Microsoft\Enrollment\OmaDmRetry – OMA DM protocol settings
    • \Microsoft\EnterpriseAppManagement\Database\Tbl_EnrollmentToken – Application Enrollment Token (AET) information
    • \Microsoft\EnterpriseAppManagement\Database\Tbl_XAPRequest – Company Hub/Enterprise App information – including whether the download was successful and what was the error if it failed
    • \Microsoft\Provisioning – this is the goldmine, for example a list of supported CSPs, including hints that there is much more supported than what the official documentation mentions, like “BrowserFavorite” or “HotSpot”… both were there in Windows Mobile Oma

Windows Phone to overtake by 2014

That’s an interesting article going around recently: “Looking at active installed base: Symbian easily third, WP to overtake by 2014?“. Have to comment a bit:

  1. It is an interesting approach – choosing “active” devices that are not older than 2-3 years. Makes sense, as most of us would have a chance to switch their devices on this schedule. At the same time the chart for 2 vs. 3 years are not that much different (except for Symbian) – so why show both?
  2. The title seems misleading – “WP to overtake” is to indicate that Windows Phone may be the 3rd platform in 2014. And it not only would have to overtake BlackBerry, but Symbian too.
  3. Is WP really going to be the 3rd platform? Indeed seems to depend on weak BB10 numbers. Does not seem like the best perspective for Microsoft – relying on BlackBerry doing bad means that Windows Phone may not be strong enough platform to perform on its own.
  4. “data compiled from Gartner, IDC and Canalys” – would be great to have more concrete data. How it was calculated etc.
  5. “Windows Phone, by far the newest mobile OS” – do we mean here that WP7 was not a continuation of Windows Mobile?