Index: ObjFW.xcodeproj/project.pbxproj ================================================================== --- ObjFW.xcodeproj/project.pbxproj +++ ObjFW.xcodeproj/project.pbxproj @@ -121,10 +121,16 @@ 4B187E61163EA4530049A832 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B187E60163EA4530049A832 /* Foundation.framework */; }; 4B187E62163EA46D0049A832 /* ObjFW.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B3D23761337FBC800DD29B8 /* ObjFW.framework */; }; 4B23CA92133811DC0047A1D9 /* TestPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF684123535B60076B512 /* TestPlugin.m */; }; 4B23CA93133811E20047A1D9 /* ObjFW.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B3D23761337FBC800DD29B8 /* ObjFW.framework */; }; 4B23CA941338121C0047A1D9 /* TestPlugin.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B23CA8A133811610047A1D9 /* TestPlugin.bundle */; }; + 4B24592A19B5397C0059F271 /* OFSHA224Hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B24592619B5397C0059F271 /* OFSHA224Hash.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4B24592B19B5397C0059F271 /* OFSHA224Hash.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B24592719B5397C0059F271 /* OFSHA224Hash.m */; }; + 4B24592C19B5397C0059F271 /* OFSHA224OrSHA256Hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B24592819B5397C0059F271 /* OFSHA224OrSHA256Hash.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4B24592D19B5397C0059F271 /* OFSHA224OrSHA256Hash.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B24592919B5397C0059F271 /* OFSHA224OrSHA256Hash.m */; }; + 4B24593019B53BC80059F271 /* OFSHA224HashTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B24592E19B53BC80059F271 /* OFSHA224HashTests.m */; }; + 4B24593119B53BC80059F271 /* OFSHA256HashTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B24592F19B53BC80059F271 /* OFSHA256HashTests.m */; }; 4B29BC3F133AC4E80004B236 /* OFCreateDirectoryFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B29BC37133AC4E80004B236 /* OFCreateDirectoryFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B29BC40133AC4E80004B236 /* OFCreateDirectoryFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B29BC38133AC4E80004B236 /* OFCreateDirectoryFailedException.m */; }; 4B29BC41133AC4E80004B236 /* OFSeekFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B29BC39133AC4E80004B236 /* OFSeekFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B29BC42133AC4E80004B236 /* OFSeekFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B29BC3A133AC4E80004B236 /* OFSeekFailedException.m */; }; 4B29BC58133AC8540004B236 /* OFConditionBroadcastFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B8B1701133A3B8E007CD8B3 /* OFConditionBroadcastFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -613,10 +619,16 @@ 4B187E3A163EA3DA0049A832 /* OFString+NSObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "OFString+NSObject.m"; path = "src/bridge/OFString+NSObject.m"; sourceTree = ""; }; 4B187E60163EA4530049A832 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 4B19023A1338D6A2000374C9 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; name = Makefile; path = src/Makefile; sourceTree = SOURCE_ROOT; }; 4B19023D1338D6D5000374C9 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; name = Makefile; path = tests/Makefile; sourceTree = ""; }; 4B23CA8A133811610047A1D9 /* TestPlugin.bundle */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = TestPlugin.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B24592619B5397C0059F271 /* OFSHA224Hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFSHA224Hash.h; path = src/OFSHA224Hash.h; sourceTree = ""; }; + 4B24592719B5397C0059F271 /* OFSHA224Hash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFSHA224Hash.m; path = src/OFSHA224Hash.m; sourceTree = ""; }; + 4B24592819B5397C0059F271 /* OFSHA224OrSHA256Hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFSHA224OrSHA256Hash.h; path = src/OFSHA224OrSHA256Hash.h; sourceTree = ""; }; + 4B24592919B5397C0059F271 /* OFSHA224OrSHA256Hash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFSHA224OrSHA256Hash.m; path = src/OFSHA224OrSHA256Hash.m; sourceTree = ""; }; + 4B24592E19B53BC80059F271 /* OFSHA224HashTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFSHA224HashTests.m; path = tests/OFSHA224HashTests.m; sourceTree = ""; }; + 4B24592F19B53BC80059F271 /* OFSHA256HashTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFSHA256HashTests.m; path = tests/OFSHA256HashTests.m; sourceTree = ""; }; 4B29BC37133AC4E80004B236 /* OFCreateDirectoryFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFCreateDirectoryFailedException.h; path = src/exceptions/OFCreateDirectoryFailedException.h; sourceTree = ""; }; 4B29BC38133AC4E80004B236 /* OFCreateDirectoryFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFCreateDirectoryFailedException.m; path = src/exceptions/OFCreateDirectoryFailedException.m; sourceTree = ""; }; 4B29BC39133AC4E80004B236 /* OFSeekFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFSeekFailedException.h; path = src/exceptions/OFSeekFailedException.h; sourceTree = ""; }; 4B29BC3A133AC4E80004B236 /* OFSeekFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFSeekFailedException.m; path = src/exceptions/OFSeekFailedException.m; sourceTree = ""; }; 4B29BC5D133AC9C40004B236 /* OFLinkFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFLinkFailedException.h; path = src/exceptions/OFLinkFailedException.h; sourceTree = ""; }; @@ -1337,10 +1349,14 @@ 4B8385151951BF9500D5358A /* OFSettings.m */, 4B8385121951BF9500D5358A /* OFSettings_INIFile.h */, 4B8385131951BF9500D5358A /* OFSettings_INIFile.m */, 4BF1BCC411C9663F0025511F /* OFSHA1Hash.h */, 4BF1BCC511C9663F0025511F /* OFSHA1Hash.m */, + 4B24592619B5397C0059F271 /* OFSHA224Hash.h */, + 4B24592719B5397C0059F271 /* OFSHA224Hash.m */, + 4B24592819B5397C0059F271 /* OFSHA224OrSHA256Hash.h */, + 4B24592919B5397C0059F271 /* OFSHA224OrSHA256Hash.m */, 4B3B03E919B3F70500F70C05 /* OFSHA256Hash.h */, 4B3B03EA19B3F70500F70C05 /* OFSHA256Hash.m */, 4B141BA215FCDF74000C21A8 /* OFSortedList.h */, 4B141BA315FCDF74000C21A8 /* OFSortedList.m */, 4B0256E2172B60400062B5F1 /* OFStdIOStream.h */, @@ -1463,10 +1479,12 @@ 4B6EF6751235358D0076B512 /* OFObjectTests.m */, 4B6EF6761235358D0076B512 /* OFPluginTests.m */, 4B3D5693139A617D0010A78F /* OFSerializationTests.m */, 4B4B6903191437D500334775 /* OFSetTests.m */, 4B6EF6771235358D0076B512 /* OFSHA1HashTests.m */, + 4B24592E19B53BC80059F271 /* OFSHA224HashTests.m */, + 4B24592F19B53BC80059F271 /* OFSHA256HashTests.m */, 4B6EF6781235358D0076B512 /* OFStreamTests.m */, 4B6EF6791235358D0076B512 /* OFStringTests.m */, 4B6EF67A1235358D0076B512 /* OFTCPSocketTests.m */, 4B6EF67B1235358D0076B512 /* OFThreadTests.m */, 4B0EA924189869D900F573A4 /* OFUDPSocketTests.m */, @@ -1605,10 +1623,12 @@ 4B3D23D31337FCB000DD29B8 /* OFSeekableStream.h in Headers */, 4B989C2F13771A3700109A30 /* OFSerialization.h in Headers */, 4B39844213D3A24600E6F825 /* OFSet.h in Headers */, 4B8385181951BF9500D5358A /* OFSettings.h in Headers */, 4B3D23D41337FCB000DD29B8 /* OFSHA1Hash.h in Headers */, + 4B24592A19B5397C0059F271 /* OFSHA224Hash.h in Headers */, + 4B24592C19B5397C0059F271 /* OFSHA224OrSHA256Hash.h in Headers */, 4B3B03EB19B3F70500F70C05 /* OFSHA256Hash.h in Headers */, 4B141BA415FCDF74000C21A8 /* OFSortedList.h in Headers */, 4B0256E4172B60400062B5F1 /* OFStdIOStream.h in Headers */, 4B3D23D51337FCB000DD29B8 /* OFStream.h in Headers */, 4B3D23D71337FCB000DD29B8 /* OFStreamSocket.h in Headers */, @@ -1980,10 +2000,12 @@ 4B39844313D3A24600E6F825 /* OFSet.m in Sources */, 4BA85BCF140ECCE800E91D51 /* OFSet_hashtable.m in Sources */, 4B8385191951BF9500D5358A /* OFSettings.m in Sources */, 4B8385171951BF9500D5358A /* OFSettings_INIFile.m in Sources */, 4B3D23A21337FC0D00DD29B8 /* OFSHA1Hash.m in Sources */, + 4B24592B19B5397C0059F271 /* OFSHA224Hash.m in Sources */, + 4B24592D19B5397C0059F271 /* OFSHA224OrSHA256Hash.m in Sources */, 4B3B03EC19B3F70500F70C05 /* OFSHA256Hash.m in Sources */, 4B141BA515FCDF74000C21A8 /* OFSortedList.m in Sources */, 4B0256E5172B60400062B5F1 /* OFStdIOStream.m in Sources */, 4B3D23A31337FC0D00DD29B8 /* OFStream.m in Sources */, 4B3D23A51337FC0D00DD29B8 /* OFStreamSocket.m in Sources */, @@ -2104,10 +2126,12 @@ 4BF33B06133807A20059CEF7 /* OFObjectTests.m in Sources */, 4BF33B07133807A20059CEF7 /* OFPluginTests.m in Sources */, 4B3D5694139A617D0010A78F /* OFSerializationTests.m in Sources */, 4B4B6904191437D500334775 /* OFSetTests.m in Sources */, 4BF33B08133807A20059CEF7 /* OFSHA1HashTests.m in Sources */, + 4B24593019B53BC80059F271 /* OFSHA224HashTests.m in Sources */, + 4B24593119B53BC80059F271 /* OFSHA256HashTests.m in Sources */, 4BF33B09133807A20059CEF7 /* OFStreamTests.m in Sources */, 4BF33B0A133807A20059CEF7 /* OFStringTests.m in Sources */, 4BF33B0B133807A20059CEF7 /* OFTCPSocketTests.m in Sources */, 4BF33B0C133807A20059CEF7 /* OFThreadTests.m in Sources */, 4B0EA925189869D900F573A4 /* OFUDPSocketTests.m in Sources */, Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -42,10 +42,12 @@ ${OFPROCESS_M} \ OFRunLoop.m \ OFSeekableStream.m \ OFSet.m \ OFSHA1Hash.m \ + OFSHA224Hash.m \ + OFSHA224OrSHA256Hash.m \ OFSHA256Hash.m \ OFSortedList.m \ OFStdIOStream.m \ OFStream.m \ OFString.m \ Index: src/OFDataArray+Hashing.h ================================================================== --- src/OFDataArray+Hashing.h +++ src/OFDataArray+Hashing.h @@ -39,13 +39,21 @@ * * @return The SHA-1 hash of the data array as an autoreleased OFString */ - (OFString*)SHA1Hash; +/*! + * @brief Returns the SHA-224 hash of the data array as an autoreleased + * OFString. + * + * @return The SHA-224 hash of the data array as an autoreleased OFString + */ +- (OFString*)SHA224Hash; + /*! * @brief Returns the SHA-256 hash of the data array as an autoreleased * OFString. * * @return The SHA-256 hash of the data array as an autoreleased OFString */ - (OFString*)SHA256Hash; @end Index: src/OFDataArray+Hashing.m ================================================================== --- src/OFDataArray+Hashing.m +++ src/OFDataArray+Hashing.m @@ -19,10 +19,11 @@ #import "OFDataArray.h" #import "OFString.h" #import "OFHash.h" #import "OFMD5Hash.h" #import "OFSHA1Hash.h" +#import "OFSHA224Hash.h" #import "OFSHA256Hash.h" int _OFDataArray_Hashing_reference; @implementation OFDataArray (Hashing) @@ -63,11 +64,16 @@ - (OFString*)SHA1Hash { return [self OF_hashAsStringWithHash: [OFSHA1Hash class]]; } + +- (OFString*)SHA224Hash +{ + return [self OF_hashAsStringWithHash: [OFSHA224Hash class]]; +} - (OFString*)SHA256Hash { return [self OF_hashAsStringWithHash: [OFSHA256Hash class]]; } @end ADDED src/OFSHA224Hash.h Index: src/OFSHA224Hash.h ================================================================== --- src/OFSHA224Hash.h +++ src/OFSHA224Hash.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 + * 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. + */ + +#import "OFSHA224OrSHA256Hash.h" + +/*! + * @class OFSHA224Hash OFSHA224Hash.h ObjFW/OFSHA224Hash.h + * + * @brief A class which provides functions to create an SHA-224 hash. + */ +@interface OFSHA224Hash: OFSHA224OrSHA256Hash +@end ADDED src/OFSHA224Hash.m Index: src/OFSHA224Hash.m ================================================================== --- src/OFSHA224Hash.m +++ src/OFSHA224Hash.m @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 + * 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. + */ + +#import "OFSHA224Hash.h" + +@implementation OFSHA224Hash ++ (size_t)digestSize +{ + return 28; +} + +- init +{ + self = [super init]; + + _state[0] = 0xC1059ED8; + _state[1] = 0x367CD507; + _state[2] = 0x3070DD17; + _state[3] = 0xF70E5939; + _state[4] = 0xFFC00B31; + _state[5] = 0x68581511; + _state[6] = 0x64F98FA7; + _state[7] = 0xBEFA4FA4; + + return self; +} +@end ADDED src/OFSHA224OrSHA256Hash.h Index: src/OFSHA224OrSHA256Hash.h ================================================================== --- src/OFSHA224OrSHA256Hash.h +++ src/OFSHA224OrSHA256Hash.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 + * 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. + */ + +#import "OFHash.h" + +/*! + * @class OFSHA224OrSHA256Hash OFSHA224OrSHA256Hash.h \ + * ObjFW/OFSHA224OrSHA256Hash.h + * + * @brief A base class for SHA-224 and SHA-256. + */ +@interface OFSHA224OrSHA256Hash: OFObject +{ + uint32_t _state[8]; + uint64_t _bits; + union { + uint8_t bytes[64]; + uint32_t words[64]; + } _buffer; + size_t _bufferLength; + bool _calculated; +} +@end ADDED src/OFSHA224OrSHA256Hash.m Index: src/OFSHA224OrSHA256Hash.m ================================================================== --- src/OFSHA224OrSHA256Hash.m +++ src/OFSHA224OrSHA256Hash.m @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 + * 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 +#include + +#import "OFSHA224OrSHA256Hash.h" + +#import "OFHashAlreadyCalculatedException.h" + +static const uint32_t table[] = { + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, + 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, + 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, + 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, + 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, + 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, + 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 +}; + +static void +byteSwapVectorIfLE(uint32_t *vector, uint_fast8_t length) +{ + uint_fast8_t i; + + for (i = 0; i < length; i++) + vector[i] = OF_BSWAP32_IF_LE(vector[i]); +} + +static void +processBlock(uint32_t *state, uint32_t *buffer) +{ + uint32_t new[8]; + uint_fast8_t i; + + new[0] = state[0]; + new[1] = state[1]; + new[2] = state[2]; + new[3] = state[3]; + new[4] = state[4]; + new[5] = state[5]; + new[6] = state[6]; + new[7] = state[7]; + + byteSwapVectorIfLE(buffer, 16); + + for (i = 16; i < 64; i++) { + uint32_t tmp; + + tmp = buffer[i - 2]; + buffer[i] = (OF_ROR(tmp, 17) ^ OF_ROR(tmp, 19) ^ (tmp >> 10)) + + buffer[i - 7]; + tmp = buffer[i - 15]; + buffer[i] += (OF_ROR(tmp, 7) ^ OF_ROR(tmp, 18) ^ (tmp >> 3)) + + buffer[i - 16]; + } + + for (i = 0; i < 64; i++) { + uint32_t tmp1 = new[7] + (OF_ROR(new[4], 6) ^ + OF_ROR(new[4], 11) ^ OF_ROR(new[4], 25)) + + ((new[4] & (new[5] ^ new[6])) ^ new[6]) + + table[i] + buffer[i]; + uint32_t tmp2 = (OF_ROR(new[0], 2) ^ OF_ROR(new[0], 13) ^ + OF_ROR(new[0], 22)) + + ((new[0] & (new[1] | new[2])) | (new[1] & new[2])); + + new[7] = new[6]; + new[6] = new[5]; + new[5] = new[4]; + new[4] = new[3] + tmp1; + new[3] = new[2]; + new[2] = new[1]; + new[1] = new[0]; + new[0] = tmp1 + tmp2; + } + + state[0] += new[0]; + state[1] += new[1]; + state[2] += new[2]; + state[3] += new[3]; + state[4] += new[4]; + state[5] += new[5]; + state[6] += new[6]; + state[7] += new[7]; +} + +@implementation OFSHA224OrSHA256Hash ++ (size_t)digestSize +{ + OF_UNRECOGNIZED_SELECTOR +} + ++ (size_t)blockSize +{ + return 64; +} + ++ (instancetype)hash +{ + return [[[self alloc] init] autorelease]; +} + +- init +{ + if (object_getClass(self) == [OFSHA224OrSHA256Hash class]) { + @try { + [self doesNotRecognizeSelector: _cmd]; + } @catch (id e) { + [self release]; + @throw e; + } + + abort(); + } + + return [super init]; +} + +- (void)updateWithBuffer: (const void*)buffer_ + length: (size_t)length +{ + const uint8_t *buffer = buffer_; + + if (_calculated) + @throw [OFHashAlreadyCalculatedException + exceptionWithHash: self]; + + _bits += (length * 8); + + while (length > 0) { + size_t min = 64 - _bufferLength; + + if (min > length) + min = length; + + memcpy(_buffer.bytes + _bufferLength, buffer, min); + _bufferLength += min; + + buffer += min; + length -= min; + + if (_bufferLength == 64) { + processBlock(_state, _buffer.words); + _bufferLength = 0; + } + } +} + +- (const uint8_t*)digest +{ + if (_calculated) + return (const uint8_t*)_state; + + _buffer.bytes[_bufferLength] = 0x80; + memset(_buffer.bytes + _bufferLength + 1, 0, 64 - _bufferLength - 1); + + if (_bufferLength >= 56) { + processBlock(_state, _buffer.words); + memset(_buffer.bytes, 0, 64); + } + + _buffer.words[14] = OF_BSWAP32_IF_LE((uint32_t)(_bits >> 32)); + _buffer.words[15] = OF_BSWAP32_IF_LE((uint32_t)(_bits & 0xFFFFFFFF)); + + processBlock(_state, _buffer.words); + memset(&_buffer, 0, sizeof(_buffer)); + byteSwapVectorIfLE(_state, 8); + _calculated = true; + + return (const uint8_t*)_state; +} + +- (bool)isCalculated +{ + return _calculated; +} +@end Index: src/OFSHA256Hash.h ================================================================== --- src/OFSHA256Hash.h +++ src/OFSHA256Hash.h @@ -12,24 +12,14 @@ * 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. */ -#import "OFHash.h" +#import "OFSHA224OrSHA256Hash.h" /*! * @class OFSHA256Hash OFSHA256Hash.h ObjFW/OFSHA256Hash.h * * @brief A class which provides functions to create an SHA-256 hash. */ -@interface OFSHA256Hash: OFObject -{ - uint32_t _state[8]; - uint64_t _bits; - union { - uint8_t bytes[64]; - uint32_t words[64]; - } _buffer; - size_t _bufferLength; - bool _calculated; -} +@interface OFSHA256Hash: OFSHA224OrSHA256Hash @end Index: src/OFSHA256Hash.m ================================================================== --- src/OFSHA256Hash.m +++ src/OFSHA256Hash.m @@ -12,119 +12,18 @@ * 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 "OFSHA256Hash.h" -#import "OFHashAlreadyCalculatedException.h" - -static const uint32_t table[] = { - 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, - 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, - 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, - 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, - 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, - 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, - 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, - 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, - 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, - 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, - 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, - 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, - 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, - 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, - 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, - 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 -}; - -static void -byteSwapVectorIfLE(uint32_t *vector, uint_fast8_t length) -{ - uint_fast8_t i; - - for (i = 0; i < length; i++) - vector[i] = OF_BSWAP32_IF_LE(vector[i]); -} - -static void -processBlock(uint32_t *state, uint32_t *buffer) -{ - uint32_t new[8]; - uint_fast8_t i; - - new[0] = state[0]; - new[1] = state[1]; - new[2] = state[2]; - new[3] = state[3]; - new[4] = state[4]; - new[5] = state[5]; - new[6] = state[6]; - new[7] = state[7]; - - byteSwapVectorIfLE(buffer, 16); - - for (i = 16; i < 64; i++) { - uint32_t tmp; - - tmp = buffer[i - 2]; - buffer[i] = (OF_ROR(tmp, 17) ^ OF_ROR(tmp, 19) ^ (tmp >> 10)) + - buffer[i - 7]; - tmp = buffer[i - 15]; - buffer[i] += (OF_ROR(tmp, 7) ^ OF_ROR(tmp, 18) ^ (tmp >> 3)) + - buffer[i - 16]; - } - - for (i = 0; i < 64; i++) { - uint32_t tmp1 = new[7] + (OF_ROR(new[4], 6) ^ - OF_ROR(new[4], 11) ^ OF_ROR(new[4], 25)) + - ((new[4] & (new[5] ^ new[6])) ^ new[6]) + - table[i] + buffer[i]; - uint32_t tmp2 = (OF_ROR(new[0], 2) ^ OF_ROR(new[0], 13) ^ - OF_ROR(new[0], 22)) + - ((new[0] & (new[1] | new[2])) | (new[1] & new[2])); - - new[7] = new[6]; - new[6] = new[5]; - new[5] = new[4]; - new[4] = new[3] + tmp1; - new[3] = new[2]; - new[2] = new[1]; - new[1] = new[0]; - new[0] = tmp1 + tmp2; - } - - state[0] += new[0]; - state[1] += new[1]; - state[2] += new[2]; - state[3] += new[3]; - state[4] += new[4]; - state[5] += new[5]; - state[6] += new[6]; - state[7] += new[7]; -} - @implementation OFSHA256Hash + (size_t)digestSize { return 32; } -+ (size_t)blockSize -{ - return 64; -} - -+ (instancetype)hash -{ - return [[[self alloc] init] autorelease]; -} - - init { self = [super init]; _state[0] = 0x6A09E667; @@ -136,65 +35,6 @@ _state[6] = 0x1F83D9AB; _state[7] = 0x5BE0CD19; return self; } - -- (void)updateWithBuffer: (const void*)buffer_ - length: (size_t)length -{ - const uint8_t *buffer = buffer_; - - if (_calculated) - @throw [OFHashAlreadyCalculatedException - exceptionWithHash: self]; - - _bits += (length * 8); - - while (length > 0) { - size_t min = 64 - _bufferLength; - - if (min > length) - min = length; - - memcpy(_buffer.bytes + _bufferLength, buffer, min); - _bufferLength += min; - - buffer += min; - length -= min; - - if (_bufferLength == 64) { - processBlock(_state, _buffer.words); - _bufferLength = 0; - } - } -} - -- (const uint8_t*)digest -{ - if (_calculated) - return (const uint8_t*)_state; - - _buffer.bytes[_bufferLength] = 0x80; - memset(_buffer.bytes + _bufferLength + 1, 0, 64 - _bufferLength - 1); - - if (_bufferLength >= 56) { - processBlock(_state, _buffer.words); - memset(_buffer.bytes, 0, 64); - } - - _buffer.words[14] = OF_BSWAP32_IF_LE((uint32_t)(_bits >> 32)); - _buffer.words[15] = OF_BSWAP32_IF_LE((uint32_t)(_bits & 0xFFFFFFFF)); - - processBlock(_state, _buffer.words); - memset(&_buffer, 0, sizeof(_buffer)); - byteSwapVectorIfLE(_state, 8); - _calculated = true; - - return (const uint8_t*)_state; -} - -- (bool)isCalculated -{ - return _calculated; -} @end Index: src/OFString+Hashing.h ================================================================== --- src/OFString+Hashing.h +++ src/OFString+Hashing.h @@ -37,12 +37,19 @@ * * @return The SHA-1 hash of the string as an autoreleased OFString */ - (OFString*)SHA1Hash; +/*! + * @brief Returns the SHA-224 hash of the string as an autoreleased OFString. + * + * @return The SHA-224 hash of the string as an autoreleased OFString + */ +- (OFString*)SHA224Hash; + /*! * @brief Returns the SHA-256 hash of the string as an autoreleased OFString. * * @return The SHA-256 hash of the string as an autoreleased OFString */ - (OFString*)SHA256Hash; @end Index: src/OFString+Hashing.m ================================================================== --- src/OFString+Hashing.m +++ src/OFString+Hashing.m @@ -18,10 +18,11 @@ #import "OFString.h" #import "OFHash.h" #import "OFMD5Hash.h" #import "OFSHA1Hash.h" +#import "OFSHA224Hash.h" #import "OFSHA256Hash.h" int _OFString_Hashing_reference; @implementation OFString (Hashing) @@ -62,11 +63,16 @@ - (OFString*)SHA1Hash { return [self OF_hashAsStringWithHash: [OFSHA1Hash class]]; } + +- (OFString*)SHA224Hash +{ + return [self OF_hashAsStringWithHash: [OFSHA224Hash class]]; +} - (OFString*)SHA256Hash { return [self OF_hashAsStringWithHash: [OFSHA256Hash class]]; } @end Index: tests/Makefile ================================================================== --- tests/Makefile +++ tests/Makefile @@ -34,10 +34,11 @@ ${OFHTTPCLIENTTESTS_M} SRCS_FILES = OFINIFileTests.m \ OFMD5HashTests.m \ OFSerializationTests.m \ OFSHA1HashTests.m \ + OFSHA224HashTests.m \ OFSHA256HashTests.m SRCS_PLUGINS = OFPluginTests.m SRCS_SOCKETS = OFTCPSocketTests.m \ OFUDPSocketTests.m SRCS_THREADS = OFThreadTests.m Index: tests/OFDataArrayTests.m ================================================================== --- tests/OFDataArrayTests.m +++ tests/OFDataArrayTests.m @@ -102,10 +102,13 @@ !memcmp([array[0] items], "abcde", 5)) TEST(@"-[MD5Hash]", [[array[0] MD5Hash] isEqual: [@"abcde" MD5Hash]]) TEST(@"-[SHA1Hash]", [[array[0] SHA1Hash] isEqual: [@"abcde" SHA1Hash]]) + + TEST(@"-[SHA224Hash]", [[array[0] SHA224Hash] + isEqual: [@"abcde" SHA224Hash]]) TEST(@"-[SHA256Hash]", [[array[0] SHA256Hash] isEqual: [@"abcde" SHA256Hash]]) TEST(@"-[stringByBase64Encoding]", ADDED tests/OFSHA224HashTests.m Index: tests/OFSHA224HashTests.m ================================================================== --- tests/OFSHA224HashTests.m +++ tests/OFSHA224HashTests.m @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 + * 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 "OFSHA224Hash.h" +#import "OFString.h" +#import "OFFile.h" +#import "OFAutoreleasePool.h" + +#import "OFHashAlreadyCalculatedException.h" + +#import "TestsAppDelegate.h" + +static OFString *module = @"OFSHA224Hash"; + +const uint8_t testfile_sha224[28] = + "\x27\x69\xD8\x04\x2D\x0F\xCA\x84\x6C\xF1\x62\x44\xBA\x0C\xBD\x46\x64" + "\x5F\x4F\x20\x02\x4D\x15\xED\x1C\x61\x1F\xF7"; + +@implementation TestsAppDelegate (SHA224HashTests) +- (void)SHA224HashTests +{ + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; + OFSHA224Hash *sha224; + OFFile *f = [OFFile fileWithPath: @"testfile.bin" + mode: @"rb"]; + + TEST(@"+[hash]", (sha224 = [OFSHA224Hash hash])) + + while (![f isAtEndOfStream]) { + char buf[64]; + size_t len = [f readIntoBuffer: buf + length: 64]; + [sha224 updateWithBuffer: buf + length: len]; + } + [f close]; + + TEST(@"-[digest]", !memcmp([sha224 digest], testfile_sha224, 28)) + + EXPECT_EXCEPTION(@"Detect invalid call of " + @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException, + [sha224 updateWithBuffer: "" + length: 1]) + + [pool drain]; +} +@end Index: tests/OFStringTests.m ================================================================== --- tests/OFStringTests.m +++ tests/OFStringTests.m @@ -538,10 +538,14 @@ isEqual: @"184dce2ec49b5422c7cfd8728864db4c"]) TEST(@"-[SHA1Hash]", [[@"asdfoobar" SHA1Hash] isEqual: @"f5f81ac0a8b5cbfdc4585ec1ad32e7b3a12b9b49"]) + TEST(@"-[SHA224Hash]", [[@"asdfoobar" SHA224Hash] + isEqual: + @"5a06822dcbd5a874f67d062b80b9d8a9cb9b5b303960b9da9290c192"]) + TEST(@"-[SHA256Hash]", [[@"asdfoobar" SHA256Hash] isEqual: @"28e65b1dcd7f6ce2ea6277b15f87b913628b5500bf7913a2bbf4cedcfa1215f6" ]) Index: tests/TestsAppDelegate.h ================================================================== --- tests/TestsAppDelegate.h +++ tests/TestsAppDelegate.h @@ -141,10 +141,14 @@ @end @interface TestsAppDelegate (OFSHA1HashTests) - (void)SHA1HashTests; @end + +@interface TestsAppDelegate (OFSHA224HashTests) +- (void)SHA224HashTests; +@end @interface TestsAppDelegate (OFSHA256HashTests) - (void)SHA256HashTests; @end Index: tests/TestsAppDelegate.m ================================================================== --- tests/TestsAppDelegate.m +++ tests/TestsAppDelegate.m @@ -339,10 +339,11 @@ [self numberTests]; [self streamTests]; #ifdef OF_HAVE_FILES [self MD5HashTests]; [self SHA1HashTests]; + [self SHA224HashTests]; [self SHA256HashTests]; [self INIFileTests]; #endif #ifdef OF_HAVE_SOCKETS [self TCPSocketTests];