Blame client/iOS/Controllers/EncryptionController.m

Packit 1fb8d4
/*
Packit 1fb8d4
 Password Encryption Controller
Packit 1fb8d4
 
Packit 1fb8d4
 Copyright 2013 Thincast Technologies GmbH, Author: Dorian Johnson
Packit 1fb8d4
 
Packit 1fb8d4
 This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 
Packit 1fb8d4
 If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#import "EncryptionController.h"
Packit 1fb8d4
#import "SFHFKeychainUtils.h"
Packit 1fb8d4
#import "TSXAdditions.h"
Packit 1fb8d4
Packit 1fb8d4
@interface EncryptionController (Private)
Packit 1fb8d4
Packit 1fb8d4
- (BOOL)verifyPassword:(Encryptor*)decryptor;
Packit 1fb8d4
- (NSData*)encryptedVerificationData;
Packit 1fb8d4
- (void)setEncryptedVerificationData:(Encryptor*)encryptor;
Packit 1fb8d4
Packit 1fb8d4
- (NSString*)keychainServerName;
Packit 1fb8d4
- (NSString*)keychainUsername;
Packit 1fb8d4
- (void)setKeychainPassword:(NSString*)password;
Packit 1fb8d4
- (NSString*)keychainPassword;
Packit 1fb8d4
- (NSString*)keychainDefaultPassword;
Packit 1fb8d4
Packit 1fb8d4
@end
Packit 1fb8d4
Packit 1fb8d4
static EncryptionController* _shared_encryption_controller = nil;
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
#pragma mark -
Packit 1fb8d4
Packit 1fb8d4
@implementation EncryptionController
Packit 1fb8d4
Packit 1fb8d4
+ (EncryptionController*)sharedEncryptionController
Packit 1fb8d4
{
Packit 1fb8d4
	@synchronized(self)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (_shared_encryption_controller == nil)
Packit 1fb8d4
			_shared_encryption_controller = [[EncryptionController alloc] init];		
Packit 1fb8d4
	}
Packit 1fb8d4
	
Packit 1fb8d4
	return _shared_encryption_controller;	
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#pragma mark Getting an encryptor or decryptor
Packit 1fb8d4
Packit 1fb8d4
- (Encryptor*)encryptor
Packit 1fb8d4
{
Packit 1fb8d4
	if (_shared_encryptor)
Packit 1fb8d4
		return _shared_encryptor;
Packit 1fb8d4
	
Packit 1fb8d4
	NSString* saved_password = [self keychainPassword];    
Packit 1fb8d4
	if (saved_password == nil)
Packit 1fb8d4
    {
Packit 1fb8d4
        saved_password = [self keychainDefaultPassword];        
Packit 1fb8d4
        Encryptor* encryptor = [[[Encryptor alloc] initWithPassword:saved_password] autorelease];
Packit 1fb8d4
        [self setEncryptedVerificationData:encryptor];        
Packit 1fb8d4
        _shared_encryptor = [encryptor retain];
Packit 1fb8d4
    }
Packit 1fb8d4
    else
Packit 1fb8d4
    {
Packit 1fb8d4
        Encryptor* encryptor = [[[Encryptor alloc] initWithPassword:saved_password] autorelease];
Packit 1fb8d4
        if ([self verifyPassword:encryptor])
Packit 1fb8d4
            _shared_encryptor = [encryptor retain];
Packit 1fb8d4
    }    
Packit 1fb8d4
    
Packit 1fb8d4
    return _shared_encryptor;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
// For the current implementation, decryptors and encryptors are equivilant.
Packit 1fb8d4
- (Encryptor*)decryptor { return [self encryptor]; }
Packit 1fb8d4
Packit 1fb8d4
@end
Packit 1fb8d4
Packit 1fb8d4
#pragma mark -
Packit 1fb8d4
Packit 1fb8d4
@implementation EncryptionController (Private)
Packit 1fb8d4
Packit 1fb8d4
#pragma mark -
Packit 1fb8d4
#pragma mark Keychain password storage
Packit 1fb8d4
Packit 1fb8d4
- (NSString*)keychainServerName
Packit 1fb8d4
{
Packit 1fb8d4
	return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (NSString*)keychainUsername
Packit 1fb8d4
{
Packit 1fb8d4
	return @"master.password";
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (void)setKeychainPassword:(NSString*)password
Packit 1fb8d4
{	
Packit 1fb8d4
    NSError* error;
Packit 1fb8d4
	if (password == nil)
Packit 1fb8d4
	{
Packit 1fb8d4
        [SFHFKeychainUtils deleteItemForUsername:[self keychainUsername] andServerName:[self keychainServerName] error:&error];
Packit 1fb8d4
		return;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	[SFHFKeychainUtils storeUsername:[self keychainUsername] andPassword:password forServerName:[self keychainServerName] updateExisting:YES error:&error];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (NSString*)keychainPassword
Packit 1fb8d4
{
Packit 1fb8d4
    NSError* error;
Packit 1fb8d4
    return [SFHFKeychainUtils getPasswordForUsername:[self keychainUsername] andServerName:[self keychainServerName] error:&error];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (NSString*)keychainDefaultPassword
Packit 1fb8d4
{
Packit 1fb8d4
    NSString* password = [[NSUserDefaults standardUserDefaults] stringForKey:@"UUID"];
Packit 1fb8d4
    if ([password length] == 0)
Packit 1fb8d4
    {
Packit 1fb8d4
        password = [NSString stringWithUUID];
Packit 1fb8d4
        [[NSUserDefaults standardUserDefaults] setObject:password forKey:@"UUID"];
Packit 1fb8d4
        [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"TSXMasterPasswordVerification"];
Packit 1fb8d4
    }
Packit 1fb8d4
    return password;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#pragma mark -
Packit 1fb8d4
#pragma mark Verification of encryption key against verification data
Packit 1fb8d4
Packit 1fb8d4
- (BOOL)verifyPassword:(Encryptor*)decryptor 
Packit 1fb8d4
{
Packit 1fb8d4
	return [[decryptor plaintextPassword] isEqualToString:[decryptor decryptString:[self encryptedVerificationData]]];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (NSData*)encryptedVerificationData
Packit 1fb8d4
{
Packit 1fb8d4
	return [[NSUserDefaults standardUserDefaults] dataForKey:@"TSXMasterPasswordVerification"];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
- (void)setEncryptedVerificationData:(Encryptor*)encryptor
Packit 1fb8d4
{
Packit 1fb8d4
	[[NSUserDefaults standardUserDefaults] setObject:[encryptor encryptString:[encryptor plaintextPassword]] forKey:@"TSXMasterPasswordVerification"];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
@end