PBKDFTest.mm   [plain text]


//
//  PBKDFTest.mm
//  CommonCrypto
//
//  Created by Richard Murphy on 2/3/10.
//  Copyright 2010 McKenzie-Murphy. All rights reserved.
//

#import "PBKDFTest.h"
#include <stdio.h>


@implementation CCDerviationTestObject

@synthesize namePBKDF = _namePBKDF;
@synthesize algoPBKDF = _algoPBKDF;
@synthesize password = _password;
@synthesize salt = _salt;
@synthesize prf = _prf;
@synthesize rounds = _rounds;
@synthesize derivedResult = _derivedResult;
@synthesize expectedResult = _expectedResult;
@synthesize testObject = _testObject;
@synthesize testPassed = _testPassed;


/* --------------------------------------------------------------------------
 method: 		setupPBKDFTests
 returns: 		NSArray *												
 decription: 	This method allows for creating digest specific tests for
				all of the digest supported by the CommonCrypto library.
				It creates an instance of the CCDigestTestObject for
				each digest to be tested and places that object into
				an NSArray.
 -------------------------------------------------------------------------- */
+ (NSArray *)setupPBKDFTests:(id<TestToolProtocol>)testObject;
{
	
	NSMutableArray* result = [NSMutableArray array]; // autoreleased
	
	/*
	 * Test vectors from RFC 3962
	 */
	
	struct test_vector test_vectors[] = {
		{ 
			1, "password", "ATHENA.MIT.EDUraeburn", { 
				0xcd, 0xed, 0xb5, 0x28, 0x1b, 0xb2, 0xf8, 0x01, 0x56, 0x5a, 0x11, 0x22, 0xb2, 0x56, 0x35, 0x15,
				0x0a, 0xd1, 0xf7, 0xa0, 0x4b, 0xb9, 0xf3, 0xa3, 0x33, 0xec, 0xc0, 0xe2, 0xe1, 0xf7, 0x08, 0x37 },
		}, {
			2, "password", "ATHENA.MIT.EDUraeburn", { 
				0x01, 0xdb, 0xee, 0x7f, 0x4a, 0x9e, 0x24, 0x3e,  0x98, 0x8b, 0x62, 0xc7, 0x3c, 0xda, 0x93, 0x5d,
				0xa0, 0x53, 0x78, 0xb9, 0x32, 0x44, 0xec, 0x8f, 0x48, 0xa9, 0x9e, 0x61, 0xad, 0x79, 0x9d, 0x86 },
		}, {
			1200, "password", "ATHENA.MIT.EDUraeburn", { 
				0x5c, 0x08, 0xeb, 0x61, 0xfd, 0xf7, 0x1e, 0x4e, 0x4e, 0xc3, 0xcf, 0x6b, 0xa1, 0xf5, 0x51, 0x2b,
				0xa7, 0xe5, 0x2d, 0xdb, 0xc5, 0xe5, 0x14, 0x2f, 0x70, 0x8a, 0x31, 0xe2, 0xe6, 0x2b, 0x1e, 0x13 },
		}, {
			5, "password", "\0224VxxV4\022", /* 0x1234567878563412 */ { 
				0xd1, 0xda, 0xa7, 0x86, 0x15, 0xf2, 0x87, 0xe6, 0xa1, 0xc8, 0xb1, 0x20, 0xd7, 0x06, 0x2a, 0x49,
				0x3f, 0x98, 0xd2, 0x03, 0xe6, 0xbe, 0x49, 0xa6, 0xad, 0xf4, 0xfa, 0x57, 0x4b, 0x6e, 0x64, 0xee },
		}, { 1200, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "pass phrase equals block size", {
				0x13, 0x9c, 0x30, 0xc0, 0x96, 0x6b, 0xc3, 0x2b, 0xa5, 0x5f, 0xdb, 0xf2, 0x12, 0x53, 0x0a, 0xc9,
				0xc5, 0xec, 0x59, 0xf1, 0xa4, 0x52, 0xf5, 0xcc, 0x9a, 0xd9, 0x40, 0xfe, 0xa0, 0x59, 0x8e, 0xd1 },
		}, { 1200, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "pass phrase exceeds block size", {
				0x9c, 0xca, 0xd6, 0xd4, 0x68, 0x77, 0x0c, 0xd5, 0x1b, 0x10, 0xe6, 0xa6, 0x87, 0x21, 0xbe, 0x61,
				0x1a, 0x8b, 0x4d, 0x28, 0x26, 0x01, 0xdb, 0x3b, 0x36, 0xbe, 0x92, 0x46, 0x91, 0x5e, 0xc8, 0x2a },
		}, { 50, "\360\235\204\236", /* g-clef (0xf09d849e) */ "EXAMPLE.COMpianist", {
				0x6b, 0x9c, 0xf2, 0x6d, 0x45, 0x45, 0x5a, 0x43, 0xa5, 0xb8, 0xbb, 0x27, 0x6a, 0x40, 0x3b, 0x39,
				0xe7, 0xfe, 0x37, 0xa0, 0xc4, 0x1e, 0x02, 0xc2, 0x81, 0xff, 0x30, 0x69, 0xe1, 0xe9, 0x4f, 0x52 },
		}, { 1, "password", "salt", { 
				0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, 
                0x2f, 0xe0, 0x37, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
		}
	};
	int nvecs = (sizeof(test_vectors) / sizeof(*test_vectors));
	int i;

	for(i=0; i< nvecs-1; i++) {
		CCDerviationTestObject* pbkdfHMACSha1Test = [[[CCDerviationTestObject alloc] 
		   initWithPBKDFName:@"pbkdfHMACSha1Test1" 
		   withCCPBKDFAlgorithm: kCCPBKDF2
		   withPassword: [[NSData alloc] initWithBytes:test_vectors[i].pass length:strlen(test_vectors[i].pass)]
		   withSalt: [[NSData alloc] initWithBytes:test_vectors[i].salt length:strlen(test_vectors[i].salt)]
		   withCCPseudoRandomAlgorithm: kCCPRFHmacAlgSHA1
		   withRounds:(uint)test_vectors[i].rounds
		   withExpectedResult:[[NSData alloc] initWithBytes:test_vectors[i].expected length:32]
		   withTestObject:testObject] autorelease];
		[result addObject:pbkdfHMACSha1Test];
	}
    
    CCDerviationTestObject* pbkdfHMACSha1Test = [[[CCDerviationTestObject alloc] 
                                                  initWithPBKDFName:@"pbkdfHMACSha1Test1" 
                                                  withCCPBKDFAlgorithm: kCCPBKDF2
                                                  withPassword: [[NSData alloc] initWithBytes:test_vectors[i].pass length:strlen(test_vectors[i].pass)]
                                                  withSalt: [[NSData alloc] initWithBytes:test_vectors[i].salt length:strlen(test_vectors[i].salt)]
                                                  withCCPseudoRandomAlgorithm: kCCPRFHmacAlgSHA1
                                                  withRounds:(uint)test_vectors[i].rounds
                                                  withExpectedResult:[[NSData alloc] initWithBytes:test_vectors[i].expected length:20]
                                                  withTestObject:testObject] autorelease];
    [result addObject:pbkdfHMACSha1Test];
    
	
	return result;
}


- (id)initWithPBKDFName:(NSString *)namePBKDF 
   withCCPBKDFAlgorithm:(CCPBKDFAlgorithm) algoPBKDF
		   withPassword:(NSData *) password
			   withSalt:(NSData *) salt
withCCPseudoRandomAlgorithm:(CCPseudoRandomAlgorithm) prf
			 withRounds:(uint)rounds
	 withExpectedResult:(NSData *)expectedResult
		 withTestObject:(id<TestToolProtocol>)testObject;

{	
	if ((self = [super init]))
	{
		_namePBKDF = [namePBKDF copy];
		_algoPBKDF = algoPBKDF;
		_password = [password copy];
		_salt = [salt copy];
		_prf = prf;
		_rounds = rounds;
		_expectedResult = [expectedResult copy];
		_testObject = testObject; 
		_testPassed = YES;
	}
	return self;
	
}


/* --------------------------------------------------------------------------
 method: 		dealloc
 returns: 		void												
 decription: 	Alway put away your toys when you are done playing with
				them.
 -------------------------------------------------------------------------- */
- (void)dealloc
{
	[_namePBKDF release];
	[_password release];
	[_salt release];
	[_expectedResult release];
	[_derivedResult release];
	//[_testObject release];
	[super dealloc];
}

- (void)doAssertTest:(BOOL)result errorString:(NSString *)errorStr
{
	if (nil != self.testObject)
	{
		[self.testObject doAssertTest:result errorString:errorStr];
		return;
	}
	
	if (_testPassed)
	{
		_testPassed = result;
	}
}

/* --------------------------------------------------------------------------
 method: 		doTest
 returns: 		void												
 decription: 	Do the 'one shot' digest creation for this test placing the
				result into the _oneShotResult member
 -------------------------------------------------------------------------- */
- (void)doVectorTest
{
	// [self clearContext];
	(void) CCKeyDerivationPBKDF(self.algoPBKDF, (const char *)[self.password bytes], [self.password length], 
						 (const uint8_t *)[self.salt bytes], [self.salt length], 
						 _prf, _rounds,
						 _derivedKey, [self.expectedResult length]);
	
	//[_derivedResult release];
	_derivedResult = [[NSData alloc] initWithBytes:_derivedKey length:[self.expectedResult length]];
	
}

/* --------------------------------------------------------------------------
 method: 		runTest
 returns: 		void												
 decription: 	Do the testing of the digest by creating both a staged 
				and one shot digest from the same data and ensuring 
				that the two digests match
 -------------------------------------------------------------------------- */
- (void)runTest
{
	[self doVectorTest];
	
	BOOL testResult = [self.expectedResult isEqualToData:self.derivedResult];
	
	[self doAssertTest:testResult errorString:[
			NSString stringWithFormat:@"Expected Result is not equal to the derived result in %@", self.namePBKDF]];
	
	if (nil == _testObject)
	{
		printf("PBKDFTest: %s\n", (self.testPassed) ? "Passed" : "Failed");
	}
}

@end