// // HMACTest.mm // CommonCrypto // // Created by Jim Murphy on 1/14/10. // Copyright 2010 Apple. All rights reserved. // #import "HMACTest.h" #import "RandomNumberService.h" #import "CommonHMAC.h" #include <stdio.h> // completely arbitrary #define kMIN_KEY_LENGTH 0 #define kMAX_KEY_LENGTH 512 #define kMIN_DATA_LENGTH 16 #define kMAC_DATA_LENGTH 0x8000 @implementation CCHMACTestObject @synthesize nameHMAC = _nameHMAC; @synthesize algoHMAC = _algoHMAC; @synthesize keyMaterial = _keyMaterial; @synthesize stagedResult = _stagedResult; @synthesize oneShotResult = _oneShotResult; @synthesize dataHMAC = _dataHMAC; @synthesize testObject = _testObject; @synthesize digestBuffer = _digestBuffer; @synthesize testPassed = _testPassed; /* -------------------------------------------------------------------------- method: setupHMACTests 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 *)setupHMACTests:(id<TestToolProtocol>)testObject; { NSMutableArray* result = [NSMutableArray array]; // autoreleased // ======================= SHA1 HMAC ========================== CCHMACTestObject* sha1HMACTest = [[[CCHMACTestObject alloc] initWithHMACName:@"Sha1HMAC" withCCHmacAlgorithm:kCCHmacAlgSHA1 withDigestSize:CC_SHA1_DIGEST_LENGTH withTestObject:testObject] autorelease]; [result addObject:sha1HMACTest]; // ======================= MD5 HMAC ========================== CCHMACTestObject* md5HMACTest = [[[CCHMACTestObject alloc] initWithHMACName:@"md5HMAC" withCCHmacAlgorithm:kCCHmacAlgMD5 withDigestSize:CC_MD5_DIGEST_LENGTH withTestObject:testObject] autorelease]; [result addObject:md5HMACTest]; // ====================== SHA256 HMAC ========================= CCHMACTestObject* sha256HMACTest = [[[CCHMACTestObject alloc] initWithHMACName:@"Sha256HMAC" withCCHmacAlgorithm:kCCHmacAlgSHA256 withDigestSize:CC_SHA256_DIGEST_LENGTH withTestObject:testObject] autorelease]; [result addObject:sha256HMACTest]; // ====================== SHA384 HMAC ========================= CCHMACTestObject* sha384HMACTest = [[[CCHMACTestObject alloc] initWithHMACName:@"Sha384HMAC" withCCHmacAlgorithm:kCCHmacAlgSHA384 withDigestSize:CC_SHA384_DIGEST_LENGTH withTestObject:testObject] autorelease]; [result addObject:sha384HMACTest]; // ====================== SHA512 HMAC ========================= CCHMACTestObject* sha512HMACTest = [[[CCHMACTestObject alloc] initWithHMACName:@"Sha512HMAC" withCCHmacAlgorithm:kCCHmacAlgSHA512 withDigestSize:CC_SHA512_DIGEST_LENGTH withTestObject:testObject] autorelease]; [result addObject:sha512HMACTest]; // ====================== SHA224 HMAC ========================= CCHMACTestObject* sha224HMACTest = [[[CCHMACTestObject alloc] initWithHMACName:@"Sha224HMAC" withCCHmacAlgorithm:kCCHmacAlgSHA224 withDigestSize:CC_SHA224_DIGEST_LENGTH withTestObject:testObject] autorelease]; [result addObject:sha224HMACTest]; return result; } - (id)initWithHMACName:(NSString *)name withCCHmacAlgorithm:(CCHmacAlgorithm)algo withDigestSize:(unsigned int)digestSize withTestObject:(id<TestToolProtocol>)testObject { if ((self = [super init])) { _testPassed = YES; _nameHMAC = [name copy]; _algoHMAC = algo; CCRandomNumberService* randService = [CCRandomNumberService defaultRandomNumberService]; unsigned int bufferSize = [randService generateRandomNumberInRange:kMIN_KEY_LENGTH toMax:kMAX_KEY_LENGTH]; _keyMaterial = [[randService generateRandomDataOfSize:bufferSize] copy]; _stagedResult = nil; _oneShotResult = nil; bufferSize = [randService generateRandomNumberInRange:kMIN_DATA_LENGTH toMax:kMAC_DATA_LENGTH]; _dataHMAC = [[randService generateRandomDataOfSize:bufferSize] copy]; _digestBufferSize = digestSize; _digestBuffer = malloc(_digestBufferSize); _testObject = [testObject retain]; } return self; } /* -------------------------------------------------------------------------- method: dealloc returns: void decription: Alway put away your toys when you are done playing with them. -------------------------------------------------------------------------- */ - (void)dealloc { [_keyMaterial release]; [_stagedResult release]; [_oneShotResult release]; [_dataHMAC release]; [_testObject release]; if (NULL != _digestBuffer) { free(_digestBuffer); _digestBuffer = NULL; } [super dealloc]; } - (CCHmacContext *)context { return &_context; } - (void)clearContext { memset(&_context, 0, sizeof(_context)); memset(_digestBuffer, 0, _digestBufferSize); } /* -------------------------------------------------------------------------- method: doStaged returns: void decription: Do the staged digest creation for this test placing the result into the _stagedResult member -------------------------------------------------------------------------- */ - (void)doStaged { [self clearContext]; CCHmacInit([self context], self.algoHMAC, [self.keyMaterial bytes], [self.keyMaterial length]); unsigned int dataLength = [self.dataHMAC length]; unsigned int thisMove; const unsigned char* raw_bytes = (const unsigned char*)[self.dataHMAC bytes]; CCRandomNumberService* randNumService = [CCRandomNumberService defaultRandomNumberService]; while (dataLength) { thisMove = [randNumService generateRandomNumberInRange:1 toMax:dataLength]; CCHmacUpdate([self context], raw_bytes, thisMove); raw_bytes += thisMove; dataLength -= thisMove; } CCHmacFinal([self context], _digestBuffer); [_stagedResult release]; _stagedResult = [[NSData alloc] initWithBytes:_digestBuffer length:_digestBufferSize]; } /* -------------------------------------------------------------------------- method: doOneShot returns: void decription: Do the 'one shot' digest creation for this test placing the result into the _oneShotResult member -------------------------------------------------------------------------- */ - (void)doOneShot { [self clearContext]; CCHmac(self.algoHMAC, [self.keyMaterial bytes], [self.keyMaterial length], [self.dataHMAC bytes], [self.dataHMAC length], _digestBuffer); [_oneShotResult release]; _oneShotResult = [[NSData alloc] initWithBytes:_digestBuffer length:_digestBufferSize]; } - (void)doAssertTest:(BOOL)result errorString:(NSString *)errorStr { if (nil != self.testObject) { [self.testObject doAssertTest:result errorString:errorStr]; return; } if (_testPassed) { _testPassed = result; } } /* -------------------------------------------------------------------------- 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 doOneShot]; [self doStaged]; BOOL testResult = [self.stagedResult isEqualToData:self.oneShotResult]; [self doAssertTest:testResult errorString:[ NSString stringWithFormat:@"Staged Result is not equal to the one shot result for digest type %@", self.nameHMAC]]; if (nil == _testObject) { printf("HMACTest: %s\n", (self.testPassed) ? "Passed" : "Failed"); } } @end