Nick Harris

Archive for the ‘Code’ Category

Core Data and Enterprise iPhone Applications – Protecting Your Data

with 28 comments

Introduction

NewsGator’s primary software offering is a product called Social Sites which basically adds social networking aspects to Microsoft SharePoint. My role in this product is to create the iOS device apps that interact with the server. My app is pulling in a lot of data that an enterprise customer considers *very* sensitive so data protection is the first thing many CIOs ask about when considering Social Sites. This post is to layout both how iOS protects data on the device so our prospective clients have a better idea about how it works, along with some additional steps developers can take to further protect their data.

Much of what I’ll discuss was covered in Session 209 at WWDC, but since that information is under NDA, I’ll stick to information that’s available in the public domain (including this post about iPhone 3GS and this post about iOS4). But if you have access to the WWDC videos, Session 209 is a great resource.

Data Encryption Starting with iPhone 3GS

Social Sites uses Core Data with a SQLite store type for storage and persistence. When the app first runs, it creates a Social_Sites.sqlite database file in its sand boxed documents directory on the device file system.

With the 3GS, any data written to the filesystem is encrypted using hardware encryption. By simply creating the Social_Sites.sqlite file on the file system, the data stored in it is already encrypted. This encryption also allows for the Social Sites data to be instantaneously unavailable when you use Remote Wipe. I say unavailable because the remote wipe doesn’t actually overwrite the encrypted data on the filesystem, but instead overwrites the hardware key used to encrypt/decrypt it. But still, the important thing is that the data on disk is encrypted.

This type of data encryption is also used on the current iPads.

Data Encryption on iOS 4

The way hardware encryption works on iOS4 has been greatly improved. I can’t find any public document from Apple that explains the improvements in detail, but their iOS 4: Understanding data protection support page gives a hint with “Data protection enhances the built-in hardware encryption by protecting the hardware encryption keys with your passcode.” I’ll just say that hardware data encryption on the 3GS and iPad use a single hardware encryption key. The WWDC session goes into great detail about the under the hood improvements. The main takeaway for a CIO though is that the Social Sites sqlite datafile on iOS4 has stronger encryption than it did in the past.

Further Protection – NSFileProtectionComplete

In iOS4, Apple introduced data protection. It gives you the ability to encrypt the hardware keys used to encrypt your files and to erase those keys when the system is locked – leaving your file unreadable until the phone is unlocked and the keys are regenerated.

This level of protection is not built in by default though. The user has to enable it (or an IT department can enable it and force users to have it on) and your code must set an attribute on your Core Data sqlite store as well.

Steps for the user to enable data protection are outlined on the iOS 4: Understanding data protection support page. You need to have the passcode turned on since this is what the system will use to generate the encryption for the keys.

As a developer, you need to set the NSFileProtection level of your sqlite store to NSFileProtectionComplete (by default it will be NSFileProtectionNone). You can do this right after you instantiate your persistent store coordinator:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }

    NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"Social_Sites.sqlite"];
    NSURL *storeUrl = [NSURL fileURLWithPath:storePath ];

    NSError *error = nil;
    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {
        // Handle error
    }

    if(RSRunningOnOS4OrBetter())
    {
        NSDictionary *fileAttributes = [NSDictionary dictionaryWithObject:NSFileProtectionComplete forKey:NSFileProtectionKey];
        if (![[NSFileManager defaultManager] setAttributes:fileAttributes ofItemAtPath:storePath error:&error]) {
            // Handle error
        }
    }

    return persistentStoreCoordinator;
}

BOOL RSRunningOnOS4OrBetter(void) {
    static BOOL didCheckIfOnOS4 = NO;
    static BOOL runningOnOS4OrBetter = NO;

    if (!didCheckIfOnOS4) {
        NSString *systemVersion = [UIDevice currentDevice].systemVersion;
        NSInteger majorSystemVersion = 3;

        if (systemVersion != nil && [systemVersion length] > 0) { //Can't imagine it would be empty, but.
            NSString *firstCharacter = [systemVersion substringToIndex:1];
            majorSystemVersion = [firstCharacter integerValue];			
        }

        runningOnOS4OrBetter = (majorSystemVersion >= 4);
        didCheckIfOnOS4 = YES;
    }
    return runningOnOS4OrBetter;
}

Considerations

If your application needs your Core Data store in any background processing, then you cannot use data protection. Any attempt to access files that are NSFileProtectionComplete will cause an exception.

There are application delegates applicationProtectedDataWillBecomeUnavailable and applicationProtectedDataDidBecomeAvailable as well as notifications UIApplicationProtectedDataWillBecomeUnavailable and UIApplicationProtectedDataWillBecomeAvailable that you can use to determine what state your protected data is in.

You could then in theory keep unprotected data in memory in your background processing then write it into your Core Data store when protected data becomes available again.

You can find more information in the iPhone Application Programming Guide.

Conclusions

My answer to any CIO asking would be to ensure any device using Social Sites be a 3GS, an iPad or an iPhone 4. I would also encourage enforcing passcode and data protection for any device running iOS4. These steps ensure that the SQLite data store for Social Sites is hardware encrypted with remote wipe capabilities and further protected with iOS4 and data protection.

UPDATE:
Here’s the link to the iPhone Configuration Utility 3.0 which can be used to “create, maintain, encrypt, and install configuration profiles, track and install provisioning profiles and authorized applications, and capture device information including console logs.”

Written by Nick Harris

July 14, 2010 at 8:23 pm

Posted in Code, Core Data

Tagged with ,

UIAlertView with an NSObject

with 3 comments

Here’s my situation… I have an operation that gets performed in the background. If that operation fails I need to alert the user and see what they would like to do about it. If they want to retry it, I just add the operation back onto the queue.

To do this, I’m sending a notification that the operation failed and am including the operation as the notifications object. I then set up a responder on my view controller for that notification. It creates a UIAlertView to ask the user what to do.

If the user selects “Retry”, it would be nice to have the operation right there on the alert view in alertView:clickedButtonAtIndex: so that I can just add it back to the operation queue. But there doesn’t seem to be any properties on UIAlertView for an arbitrary object. Instead I’ve subclassed UIAlertView and simply added a NSObject property.

Pretty easy code wise, just wondering if I’m missing something on UIAlertView that would handle the same thing.

Written by Nick Harris

March 26, 2010 at 5:00 pm

Posted in Code

Tagged with

Follow

Get every new post delivered to your Inbox.

Join 480 other followers