Index: ObjFW.xcodeproj/project.pbxproj ================================================================== --- ObjFW.xcodeproj/project.pbxproj +++ ObjFW.xcodeproj/project.pbxproj @@ -452,10 +452,11 @@ 4BE52D2617B990DA005958D1 /* OFChecksumFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BE52D2417B990DA005958D1 /* OFChecksumFailedException.m */; }; 4BEAF52D19A811DA00B61868 /* module.map in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4BEAF52519A8107500B61868 /* module.map */; }; 4BEC83B919B7CB7100E4BB08 /* OFRIPEMD160Hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BEC83B719B7CB7100E4BB08 /* OFRIPEMD160Hash.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4BEC83BA19B7CB7100E4BB08 /* OFRIPEMD160Hash.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BEC83B819B7CB7100E4BB08 /* OFRIPEMD160Hash.m */; }; 4BEC83BC19B7CBDE00E4BB08 /* OFRIPEMD160HashTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BEC83BB19B7CBDE00E4BB08 /* OFRIPEMD160HashTests.m */; }; + 4BF0DD741D44645D001D9949 /* OFHMACTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF0DD731D44645D001D9949 /* OFHMACTests.m */; }; 4BF171B21C949A3300F5B47B /* OFStdIOStream+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF171B11C9499F300F5B47B /* OFStdIOStream+Private.h */; }; 4BF33AFB133807590059CEF7 /* ObjFW.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B3D23761337FBC800DD29B8 /* ObjFW.framework */; }; 4BF33AFC133807A20059CEF7 /* OFArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF66E1235358D0076B512 /* OFArrayTests.m */; }; 4BF33AFD133807A20059CEF7 /* OFBlockTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BE5F0E412DF4259005C7A0C /* OFBlockTests.m */; }; 4BF33AFE133807A20059CEF7 /* OFDataArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF66F1235358D0076B512 /* OFDataArrayTests.m */; }; @@ -996,10 +997,11 @@ 4BEAF52519A8107500B61868 /* module.map */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; name = module.map; path = misc/module.map; sourceTree = SOURCE_ROOT; }; 4BEC83B719B7CB7100E4BB08 /* OFRIPEMD160Hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFRIPEMD160Hash.h; path = src/OFRIPEMD160Hash.h; sourceTree = ""; }; 4BEC83B819B7CB7100E4BB08 /* OFRIPEMD160Hash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFRIPEMD160Hash.m; path = src/OFRIPEMD160Hash.m; sourceTree = ""; }; 4BEC83BB19B7CBDE00E4BB08 /* OFRIPEMD160HashTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFRIPEMD160HashTests.m; path = tests/OFRIPEMD160HashTests.m; sourceTree = ""; }; 4BF0749512DFAFCA00A4ADD1 /* OFURLTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFURLTests.m; path = tests/OFURLTests.m; sourceTree = SOURCE_ROOT; }; + 4BF0DD731D44645D001D9949 /* OFHMACTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFHMACTests.m; path = tests/OFHMACTests.m; sourceTree = ""; }; 4BF171B11C9499F300F5B47B /* OFStdIOStream+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "OFStdIOStream+Private.h"; path = "src/OFStdIOStream+Private.h"; sourceTree = ""; }; 4BF1BCBF11C9663F0025511F /* objfw-defs.h.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "objfw-defs.h.in"; path = "src/objfw-defs.h.in"; sourceTree = ""; }; 4BF1BCC011C9663F0025511F /* OFCryptoHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFCryptoHash.h; path = src/OFCryptoHash.h; sourceTree = ""; }; 4BF1BCC211C9663F0025511F /* OFMD5Hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFMD5Hash.h; path = src/OFMD5Hash.h; sourceTree = ""; }; 4BF1BCC311C9663F0025511F /* OFMD5Hash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFMD5Hash.m; path = src/OFMD5Hash.m; sourceTree = ""; }; @@ -1575,10 +1577,11 @@ 4B6EF66E1235358D0076B512 /* OFArrayTests.m */, 4BE5F0E412DF4259005C7A0C /* OFBlockTests.m */, 4B6EF66F1235358D0076B512 /* OFDataArrayTests.m */, 4BE5F0E512DF4259005C7A0C /* OFDateTests.m */, 4B6EF6701235358D0076B512 /* OFDictionaryTests.m */, + 4BF0DD731D44645D001D9949 /* OFHMACTests.m */, 4BB4B54916776094002A2DCE /* OFHTTPClientTests.m */, 4B5B02C018B2897500CE6AE4 /* OFINIFileTests.m */, 4BAA60C714D09699006F068D /* OFJSONTests.m */, 4B22BE1F1AE594A000CD320A /* OFKernelEventObserverTests.m */, 4B6EF6721235358D0076B512 /* OFListTests.m */, @@ -2259,10 +2262,11 @@ 4BF33AFC133807A20059CEF7 /* OFArrayTests.m in Sources */, 4BF33AFD133807A20059CEF7 /* OFBlockTests.m in Sources */, 4BF33AFE133807A20059CEF7 /* OFDataArrayTests.m in Sources */, 4BF33AFF133807A20059CEF7 /* OFDateTests.m in Sources */, 4BF33B00133807A20059CEF7 /* OFDictionaryTests.m in Sources */, + 4BF0DD741D44645D001D9949 /* OFHMACTests.m in Sources */, 4BB4B54A16776094002A2DCE /* OFHTTPClientTests.m in Sources */, 4B5B02C118B2897500CE6AE4 /* OFINIFileTests.m in Sources */, 4BAA60C814D09699006F068D /* OFJSONTests.m in Sources */, 4B22BE201AE594A000CD320A /* OFKernelEventObserverTests.m in Sources */, 4BF33B03133807A20059CEF7 /* OFListTests.m in Sources */, Index: tests/Makefile ================================================================== --- tests/Makefile +++ tests/Makefile @@ -12,10 +12,11 @@ OFArrayTests.m \ ${OFBLOCKTESTS_M} \ OFDataArrayTests.m \ OFDateTests.m \ OFDictionaryTests.m \ + OFHMACTests.m \ OFJSONTests.m \ OFListTests.m \ OFNumberTests.m \ OFObjectTests.m \ OFSetTests.m \ ADDED tests/OFHMACTests.m Index: tests/OFHMACTests.m ================================================================== --- tests/OFHMACTests.m +++ tests/OFHMACTests.m @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include + +#import "OFHMAC.h" +#import "OFString.h" +#import "OFFile.h" +#import "OFMD5Hash.h" +#import "OFSHA1Hash.h" +#import "OFRIPEMD160Hash.h" +#import "OFSHA256Hash.h" +#import "OFSHA384Hash.h" +#import "OFSHA512Hash.h" +#import "OFAutoreleasePool.h" + +#import "OFHashAlreadyCalculatedException.h" +#import "OFInvalidArgumentException.h" + +#import "TestsAppDelegate.h" + +static OFString *module = @"OFHMAC"; +static const uint8_t key[] = + "yM9h8K6IWnJRvxC/0F8XRWG7RnACDBz8wqK2tbXrYVLoKC3vPLeJikyJSM47tVHc" + "DlXHww9zULAC2sJUlm2Kg1z4oz2aXY3Y1PQSB4VkC/m0DQ7hCI6cAg4TWnKdzWTy" + "cvYGX+Y6HWeDY79/PGSd8fNItme6I8w4HDBqU7BP2sum3jbePJqoiSnhcyJZQTeZ" + "jw0ZXoyrfHgOYD2M+NsTDaGpLblFtQ7n5CczjKtafG40PkEwx1dcrd46U9i3GyTK"; +static const size_t key_length = sizeof(key); +static const uint8_t digest_md5[] = + "\xCC\x1F\xEF\x09\x29\xA3\x25\x1A\x06\xA9\x83\x99\xF9\xBC\x8F\x42"; +static const uint8_t digest_sha1[] = + "\x94\xB9\x0A\x6F\xFB\xA7\x13\x6A\x75\x55" + "\xD5\x7F\x5D\xB7\xF4\xCA\xEB\x4A\xDE\xBF"; +static const uint8_t digest_rmd160[] = + "\x2C\xE1\xED\x41\xC6\xF3\x51\xA8\x04\xD2" + "\xC3\x9B\x08\x33\x3B\xD5\xC9\x00\x39\x50"; +static const uint8_t digest_sha256[] = + "\xFB\x8C\xDA\x88\xB3\x81\x32\x16\xD7\xD8\x62\xD4\xA6\x26\x9D\x77" + "\x01\x99\x62\x65\x29\x02\x41\xE6\xEF\xA1\x02\x31\xA8\x9D\x77\x5D"; +static const uint8_t digest_sha384[] = + "\x2F\x4A\x47\xAE\x13\x8E\x96\x52\xF1\x8F\x05\xFD\x65\xCD\x9A\x97" + "\x93\x2F\xC9\x02\xD6\xC6\xAB\x2E\x15\x76\xC0\xA7\xA0\x05\xF4\xEF" + "\x14\x52\x33\x4B\x9C\x5F\xD8\x07\x4E\x98\xAE\x97\x46\x29\x24\xB4"; +static const uint8_t digest_sha512[] = + "\xF5\x8C\x3F\x9C\xA2\x2F\x0A\xF3\x26\xD8\xC0\x7E\x20\x63\x88\x61" + "\xC9\xE1\x1F\xD7\xC7\xE5\x59\x33\xD5\x2F\xAF\x56\x1C\x94\xC8\xA4" + "\x61\xB3\xF9\x1A\xE3\x09\x43\xA6\x5B\x85\xB1\x50\x5B\xCB\x1A\x2E" + "\xB7\xE8\x87\xC1\x73\x19\x63\xF6\xA2\x91\x8D\x7E\x2E\xCC\xEC\x99"; + +@implementation TestsAppDelegate (OFHMACTests) +- (void)HMACTests +{ + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; + OFFile *f = [OFFile fileWithPath: @"testfile.bin" + mode: @"rb"]; + OFHMAC *HMAC_MD5, *HMAC_SHA1, *HMAC_RMD160; + OFHMAC *HMAC_SHA256, *HMAC_SHA384, *HMAC_SHA512; + + TEST(@"+[HMACWithHashClass:] with MD5", + (HMAC_MD5 = [OFHMAC HMACWithHashClass: [OFMD5Hash class]])) + TEST(@"+[HMACWithHashClass:] with SHA-1", + (HMAC_SHA1 = [OFHMAC HMACWithHashClass: [OFSHA1Hash class]])) + TEST(@"+[HMACWithHashClass:] with RIPEMD-160", + (HMAC_RMD160 = [OFHMAC HMACWithHashClass: [OFRIPEMD160Hash class]])) + TEST(@"+[HMACWithHashClass:] with SHA-256", + (HMAC_SHA256 = [OFHMAC HMACWithHashClass: [OFSHA256Hash class]])) + TEST(@"+[HMACWithHashClass:] with SHA-384", + (HMAC_SHA384 = [OFHMAC HMACWithHashClass: [OFSHA384Hash class]])) + TEST(@"+[HMACWithHashClass:] with SHA-512", + (HMAC_SHA512 = [OFHMAC HMACWithHashClass: [OFSHA512Hash class]])) + + EXPECT_EXCEPTION(@"Detection of missing key", + OFInvalidArgumentException, [HMAC_MD5 updateWithBuffer: "" + length: 0]) + + TEST(@"-[setKey:length:] with MD5", + R([HMAC_MD5 setKey: key + length: key_length])) + TEST(@"-[setKey:length:] with SHA-1", + R([HMAC_SHA1 setKey: key + length: key_length])) + TEST(@"-[setKey:length:] with RIPEMD-160", + R([HMAC_RMD160 setKey: key + length: key_length])) + TEST(@"-[setKey:length:] with SHA-256", + R([HMAC_SHA256 setKey: key + length: key_length])) + TEST(@"-[setKey:length:] with SHA-384", + R([HMAC_SHA384 setKey: key + length: key_length])) + TEST(@"-[setKey:length:] with SHA-512", + R([HMAC_SHA512 setKey: key + length: key_length])) + + while (![f isAtEndOfStream]) { + char buf[64]; + size_t len = [f readIntoBuffer: buf + length: 64]; + [HMAC_MD5 updateWithBuffer: buf + length: len]; + [HMAC_SHA1 updateWithBuffer: buf + length: len]; + [HMAC_RMD160 updateWithBuffer: buf + length: len]; + [HMAC_SHA256 updateWithBuffer: buf + length: len]; + [HMAC_SHA384 updateWithBuffer: buf + length: len]; + [HMAC_SHA512 updateWithBuffer: buf + length: len]; + } + [f close]; + + TEST(@"-[digest] with MD5", + memcmp([HMAC_MD5 digest], digest_md5, [HMAC_MD5 digestSize]) == 0) + TEST(@"-[digest] with SHA-1", + memcmp([HMAC_SHA1 digest], digest_sha1, + [HMAC_SHA1 digestSize]) == 0) + TEST(@"-[digest] with RIPEMD-160", + memcmp([HMAC_RMD160 digest], digest_rmd160, + [HMAC_RMD160 digestSize]) == 0) + TEST(@"-[digest] with SHA-256", + memcmp([HMAC_SHA256 digest], digest_sha256, + [HMAC_SHA256 digestSize]) == 0) + TEST(@"-[digest] with SHA-384", + memcmp([HMAC_SHA384 digest], digest_sha384, + [HMAC_SHA384 digestSize]) == 0) + TEST(@"-[digest] with SHA-512", + memcmp([HMAC_SHA512 digest], digest_sha512, + [HMAC_SHA512 digestSize]) == 0) + + [pool drain]; +} +@end Index: tests/TestsAppDelegate.h ================================================================== --- tests/TestsAppDelegate.h +++ tests/TestsAppDelegate.h @@ -165,10 +165,14 @@ @end @interface TestsAppDelegate (OFSHA512HashTests) - (void)SHA512HashTests; @end + +@interface TestsAppDelegate (OFHMACTests) +- (void)HMACTests; +@end @interface TestsAppDelegate (OFStreamTests) - (void)streamTests; @end Index: tests/TestsAppDelegate.m ================================================================== --- tests/TestsAppDelegate.m +++ tests/TestsAppDelegate.m @@ -382,10 +382,11 @@ [self SHA1HashTests]; [self SHA224HashTests]; [self SHA256HashTests]; [self SHA384HashTests]; [self SHA512HashTests]; + [self HMACTests]; [self INIFileTests]; #endif #ifdef OF_HAVE_SOCKETS [self TCPSocketTests]; [self UDPSocketTests];