2
0

WIP performing marshalling of sites in C.

This commit is contained in:
Maarten Billemont
2017-07-15 21:13:49 -04:00
parent 738ad197b2
commit 560cb1a266
25 changed files with 1224 additions and 308 deletions

View File

@@ -49,7 +49,7 @@ NSString *NSStringFromTimeToCrack(TimeToCrack timeToCrack);
- (BOOL)tryMigrateUser:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc;
- (BOOL)tryMigrateSite:(MPSiteEntity *)site explicit:(BOOL)explicit;
- (NSData *)keyIDForKeyData:(NSData *)keyData;
- (NSData *)keyIDForKey:(MPMasterKey)masterKey;
- (NSData *)keyDataForFullName:(NSString *)fullName withMasterPassword:(NSString *)masterPassword;
- (NSString *)nameOfType:(MPSiteType)type;

View File

@@ -128,21 +128,21 @@ static NSOperationQueue *_mpwQueue = nil;
__block NSData *keyData;
[self mpw_perform:^{
NSDate *start = [NSDate date];
uint8_t const *masterKeyBytes = mpw_masterKeyForUser( fullName.UTF8String, masterPassword.UTF8String, [self version] );
if (masterKeyBytes) {
keyData = [NSData dataWithBytes:masterKeyBytes length:MP_dkLen];
MPMasterKey masterKey = mpw_masterKeyForUser( fullName.UTF8String, masterPassword.UTF8String, [self version] );
if (masterKey) {
keyData = [NSData dataWithBytes:masterKey length:MPMasterKeySize];
trc( @"User: %@, password: %@ derives to key ID: %@ (took %0.2fs)", //
fullName, masterPassword, [self keyIDForKeyData:keyData], -[start timeIntervalSinceNow] );
mpw_free( masterKeyBytes, MP_dkLen );
fullName, masterPassword, [self keyIDForKey:masterKey], -[start timeIntervalSinceNow] );
mpw_free( masterKey, MPMasterKeySize );
}
}];
return keyData;
}
- (NSData *)keyIDForKeyData:(NSData *)keyData {
- (NSData *)keyIDForKey:(MPMasterKey)masterKey {
return [keyData hashWith:PearlHashSHA256];
return [[NSData dataWithBytesNoCopy:(void *)masterKey length:MPMasterKeySize] hashWith:PearlHashSHA256];
}
- (NSString *)nameOfType:(MPSiteType)type {
@@ -350,9 +350,9 @@ static NSOperationQueue *_mpwQueue = nil;
- (NSString *)generateContentForSiteNamed:(NSString *)name ofType:(MPSiteType)type withCounter:(NSUInteger)counter
variant:(MPSiteVariant)variant context:(NSString *)context usingKey:(MPKey *)key {
__block NSString *content;
__block NSString *content = nil;
[self mpw_perform:^{
char const *contentBytes = mpw_passwordForSite( [key keyDataForAlgorithm:self].bytes,
char const *contentBytes = mpw_passwordForSite( [key keyForAlgorithm:self],
name.UTF8String, type, (uint32_t)counter, variant, context.UTF8String, [self version] );
if (contentBytes) {
content = [NSString stringWithCString:contentBytes encoding:NSUTF8StringEncoding];
@@ -396,7 +396,7 @@ static NSOperationQueue *_mpwQueue = nil;
return NO;
}
NSData *encryptionKey = [siteKey keyDataForAlgorithm:self trimmedLength:PearlCryptKeySize];
NSData *encryptionKey = [siteKey keyForAlgorithm:self trimmedLength:PearlCryptKeySize];
NSData *encryptedContent = [[clearContent dataUsingEncoding:NSUTF8StringEncoding]
encryptWithSymmetricKey:encryptionKey padding:YES];
if ([((MPStoredSiteEntity *)site).contentObject isEqualToData:encryptedContent])
@@ -412,7 +412,7 @@ static NSOperationQueue *_mpwQueue = nil;
return NO;
}
NSData *encryptionKey = [siteKey keyDataForAlgorithm:self trimmedLength:PearlCryptKeySize];
NSData *encryptionKey = [siteKey keyForAlgorithm:self trimmedLength:PearlCryptKeySize];
NSData *encryptedContent = [[clearContent dataUsingEncoding:NSUTF8StringEncoding]
encryptWithSymmetricKey:encryptionKey padding:YES];
NSDictionary *siteQuery = [self queryForDevicePrivateSiteNamed:site.name];
@@ -713,7 +713,7 @@ static NSOperationQueue *_mpwQueue = nil;
return nil;
NSData *decryptedContent = nil;
if ([encryptedContent length]) {
NSData *encryptionKey = [key keyDataForAlgorithm:self trimmedLength:PearlCryptKeySize];
NSData *encryptionKey = [key keyForAlgorithm:self trimmedLength:PearlCryptKeySize];
decryptedContent = [encryptedContent decryptWithSymmetricKey:encryptionKey padding:YES];
}
if (!decryptedContent)

View File

@@ -95,13 +95,14 @@
- (void)storeSavedKeyFor:(MPUserEntity *)user {
if (user.saveKey) {
NSData *keyData = [self.key keyDataForAlgorithm:user.algorithm];
if (keyData) {
MPMasterKey masterKey = [self.key keyForAlgorithm:user.algorithm];
if (masterKey) {
[self forgetSavedKeyFor:user];
inf( @"Saving key in keychain for user: %@", user.userID );
[PearlKeyChain addOrUpdateItemForQuery:[self createKeyQueryforUser:user origin:nil]
withAttributes:@{ (__bridge id)kSecValueData: keyData }];
[PearlKeyChain addOrUpdateItemForQuery:[self createKeyQueryforUser:user origin:nil] withAttributes:@{
(__bridge id)kSecValueData: [NSData dataWithBytesNoCopy:(void *)masterKey length:MPMasterKeySize]
}];
}
}
}

View File

@@ -17,6 +17,7 @@
//==============================================================================
#import "MPAppDelegate_Store.h"
#import "mpw-marshall.h"
#if TARGET_OS_IPHONE
#define STORE_OPTIONS NSPersistentStoreFileProtectionKey : NSFileProtectionComplete,
@@ -840,68 +841,26 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
MPUserEntity *activeUser = [self activeUserForMainThread];
inf( @"Exporting sites, %@, for user: %@", revealPasswords? @"revealing passwords": @"omitting passwords", activeUser.userID );
// Header.
NSMutableString *export = [NSMutableString new];
[export appendFormat:@"# Master Password site export\n"];
if (revealPasswords)
[export appendFormat:@"# Export of site names and passwords in clear-text.\n"];
else
[export appendFormat:@"# Export of site names and stored passwords (unless device-private) encrypted with the master key.\n"];
[export appendFormat:@"# \n"];
[export appendFormat:@"##\n"];
[export appendFormat:@"# Format: 1\n"];
[export appendFormat:@"# Date: %@\n", [[NSDateFormatter rfc3339DateFormatter] stringFromDate:[NSDate date]]];
[export appendFormat:@"# User Name: %@\n", activeUser.name];
[export appendFormat:@"# Full Name: %@\n", activeUser.name];
[export appendFormat:@"# Avatar: %lu\n", (unsigned long)activeUser.avatar];
[export appendFormat:@"# Key ID: %@\n", [activeUser.keyID encodeHex]];
[export appendFormat:@"# Version: %@\n", [PearlInfoPlist get].CFBundleVersion];
[export appendFormat:@"# Algorithm: %d\n", activeUser.algorithm.version];
[export appendFormat:@"# Default Type: %d\n", activeUser.defaultType];
[export appendFormat:@"# Passwords: %@\n", revealPasswords? @"VISIBLE": @"PROTECTED"];
[export appendFormat:@"##\n"];
[export appendFormat:@"#\n"];
[export appendFormat:@"# Last Times Password Login\t Site\tSite\n"];
[export appendFormat:@"# used used type name\t name\tpassword\n"];
MPMarshalledUser exportUser = mpw_marshall_user( activeUser.name.UTF8String,
[self.key keyForAlgorithm:activeUser.algorithm], activeUser.algorithm.version );
exportUser.avatar = activeUser.avatar;
exportUser.defaultType = activeUser.defaultType;
exportUser.lastUsed = (time_t)activeUser.lastUsed.timeIntervalSince1970;
// Sites.
for (MPSiteEntity *site in activeUser.sites) {
NSDate *lastUsed = site.lastUsed;
NSUInteger uses = site.uses;
MPSiteType type = site.type;
id<MPAlgorithm> algorithm = site.algorithm;
NSUInteger counter = 0;
NSString *loginName = site.loginName;
NSString *siteName = site.name;
NSString *content = nil;
MPMarshalledSite exportSite = mpw_marshall_site( &exportUser,
site.name.UTF8String, site.type, site.counter, site.algorithm.version );
exportSite.loginName = site.loginName.UTF8String;
exportSite.url = site.url.UTF8String;
exportSite.uses = site.uses;
exportSite.lastUsed = (time_t)site.lastUsed.timeIntervalSince1970;
// Generated-specific
if ([site isKindOfClass:[MPGeneratedSiteEntity class]])
counter = ((MPGeneratedSiteEntity *)site).counter;
// Determine the content to export.
if (!(type & MPSiteFeatureDevicePrivate)) {
if (revealPasswords)
content = [site.algorithm resolvePasswordForSite:site usingKey:self.key];
else if (type & MPSiteFeatureExportContent)
content = [site.algorithm exportPasswordForSite:site usingKey:self.key];
}
NSString *lastUsedExport = [[NSDateFormatter rfc3339DateFormatter] stringFromDate:lastUsed];
long usesExport = (long)uses;
NSString *typeExport = strf( @"%lu:%lu:%lu", (long)type, (long)[algorithm version], (long)counter );
NSString *loginNameExport = loginName?: @"";
NSString *contentExport = content?: @"";
[export appendFormat:@"%@ %8ld %8S %25S\t%25S\t%@\n",
lastUsedExport, usesExport,
(const unsigned short *)[typeExport cStringUsingEncoding:NSUTF16StringEncoding],
(const unsigned short *)[loginNameExport cStringUsingEncoding:NSUTF16StringEncoding],
(const unsigned short *)[siteName cStringUsingEncoding:NSUTF16StringEncoding],
contentExport];
for (MPSiteQuestionEntity *siteQuestion in site.questions)
mpw_marshal_question( &exportSite, siteQuestion.keyword.UTF8String );
}
return export;
mpw_marshall_write( &export, MPMarshallFormatFlat, exportUser );
}
@end

View File

@@ -18,6 +18,7 @@
#import <Foundation/Foundation.h>
#import "MPAlgorithm.h"
#import "mpw-types.h"
@protocol MPAlgorithm;
@@ -37,8 +38,7 @@ typedef NS_ENUM( NSUInteger, MPKeyOrigin ) {
keyOrigin:(MPKeyOrigin)origin;
- (NSData *)keyIDForAlgorithm:(id<MPAlgorithm>)algorithm;
- (NSData *)keyDataForAlgorithm:(id<MPAlgorithm>)algorithm;
- (NSData *)keyDataForAlgorithm:(id<MPAlgorithm>)algorithm trimmedLength:(NSUInteger)subKeyLength;
- (MPMasterKey)keyForAlgorithm:(id<MPAlgorithm>)algorithm;
- (BOOL)isEqualToKey:(MPKey *)key;

View File

@@ -53,30 +53,23 @@
- (NSData *)keyIDForAlgorithm:(id<MPAlgorithm>)algorithm {
return [algorithm keyIDForKeyData:[self keyDataForAlgorithm:algorithm]];
return [algorithm keyIDForKey:[self keyForAlgorithm:algorithm]];
}
- (NSData *)keyDataForAlgorithm:(id<MPAlgorithm>)algorithm {
- (MPMasterKey)keyForAlgorithm:(id<MPAlgorithm>)algorithm {
@synchronized (self) {
NSData *keyData = [self.keyCache objectForKey:algorithm];
if (keyData)
return keyData;
if (!keyData) {
keyData = self.keyResolver( algorithm );
if (keyData)
[self.keyCache setObject:keyData forKey:algorithm];
}
keyData = self.keyResolver( algorithm );
if (keyData)
[self.keyCache setObject:keyData forKey:algorithm];
return keyData;
return keyData.length == MPMasterKeySize? keyData.bytes: NULL;
}
}
- (NSData *)keyDataForAlgorithm:(id<MPAlgorithm>)algorithm trimmedLength:(NSUInteger)subKeyLength {
NSData *keyData = [self keyDataForAlgorithm:algorithm];
return [keyData subdataWithRange:NSMakeRange( 0, MIN( subKeyLength, keyData.length ) )];
}
- (BOOL)isEqualToKey:(MPKey *)key {
return [[self keyIDForAlgorithm:MPAlgorithmDefault] isEqualToData:[key keyIDForAlgorithm:MPAlgorithmDefault]];
@@ -84,10 +77,7 @@
- (BOOL)isEqual:(id)object {
if (![object isKindOfClass:[MPKey class]])
return NO;
return [self isEqualToKey:object];
return [object isKindOfClass:[MPKey class]] && [self isEqualToKey:object];
}
@end

View File

@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12120" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="Q1S-vU-GGO">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="Q1S-vU-GGO">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
<capability name="Alignment constraints with different attributes" minToolsVersion="5.1"/>
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
@@ -103,7 +103,7 @@
</constraints>
</imageView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0Sa-Vg-EEI" userLabel="Name Backdrop">
<rect key="frame" x="44" y="263" width="128.5" height="16"/>
<rect key="frame" x="43.5" y="263" width="128.5" height="16"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalCompressionResistancePriority="1000" text="Maarten Billemont" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cLT-s0-4SQ" userLabel="Name Field">
<rect key="frame" x="5" y="0.0" width="118.5" height="16"/>
@@ -1629,7 +1629,7 @@
</connections>
</searchBar>
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LEX-BK-PdS" userLabel="Bad Name Tip">
<rect key="frame" x="38" y="86" width="300.5" height="75.5"/>
<rect key="frame" x="37.5" y="86" width="300.5" height="75.5"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black_top.png" translatesAutoresizingMaskIntoConstraints="NO" id="Rt5-v4-I0R">
<rect key="frame" x="0.0" y="0.0" width="300.5" height="75.5"/>
@@ -1771,7 +1771,7 @@ eg. apple.com, rmitchell@twitter.com</string>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="1lc-e7-Qme" userLabel="Emergency Generator">
<rect key="frame" x="20" y="135" width="335" height="397.5"/>
<rect key="frame" x="20" y="135.5" width="335" height="397.5"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Emergency Generator" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="4Lh-s0-Dbt">
<rect key="frame" x="20" y="20" width="295" height="21"/>