@@ -18,12 +18,14 @@ #include "config.h" #include #import "OFMD5Hash.h" +#import "OFSecureData.h" #import "OFHashAlreadyCalculatedException.h" +#import "OFOutOfRangeException.h" @interface OFMD5Hash () - (void)of_resetState; @end @@ -65,23 +67,23 @@ 4, 11, 16, 23, 6, 10, 15, 21 }; static OF_INLINE void -byteSwapVectorIfBE(uint32_t *vector, uint8_t length) +byteSwapVectorIfBE(uint32_t *vector, uint_fast8_t length) { #ifdef OF_BIG_ENDIAN - for (uint8_t i = 0; i < length; i++) + for (uint_fast8_t i = 0; i < length; i++) vector[i] = OF_BSWAP32(vector[i]); #endif } static void processBlock(uint32_t *state, uint32_t *buffer) { uint32_t new[4]; - uint8_t i = 0; + uint_fast8_t i = 0; new[0] = state[0]; new[1] = state[1]; new[2] = state[2]; new[3] = state[3]; @@ -137,101 +139,120 @@ - (instancetype)init { self = [super init]; - [self of_resetState]; + @try { + _iVarsData = [[OFSecureData alloc] + initWithCount: sizeof(*_iVars)]; + _iVars = [_iVarsData items]; + + [self of_resetState]; + } @catch (id e) { + [self release]; + @throw e; + } return self; } + +- (instancetype)of_init +{ + return [super init]; +} - (void)dealloc { - [self reset]; + [_iVarsData release]; [super dealloc]; } - (id)copy { - OFMD5Hash *copy = [[OFMD5Hash alloc] init]; + OFMD5Hash *copy = [[OFMD5Hash alloc] of_init]; - memcpy(copy->_state, _state, sizeof(_state)); - copy->_bits = _bits; - memcpy(©->_buffer, &_buffer, sizeof(_buffer)); - copy->_bufferLength = _bufferLength; + copy->_iVarsData = [_iVarsData copy]; + copy->_iVars = [copy->_iVarsData items]; copy->_calculated = _calculated; return copy; } - (void)of_resetState { - _state[0] = 0x67452301; - _state[1] = 0xEFCDAB89; - _state[2] = 0x98BADCFE; - _state[3] = 0x10325476; + _iVars->state[0] = 0x67452301; + _iVars->state[1] = 0xEFCDAB89; + _iVars->state[2] = 0x98BADCFE; + _iVars->state[3] = 0x10325476; } - (void)updateWithBuffer: (const void *)buffer_ length: (size_t)length { - const uint8_t *buffer = buffer_; + const unsigned char *buffer = buffer_; if (_calculated) @throw [OFHashAlreadyCalculatedException exceptionWithObject: self]; - _bits += (length * 8); + if (length > SIZE_MAX / 8) + @throw [OFOutOfRangeException exception]; + + _iVars->bits += (length * 8); while (length > 0) { - size_t min = 64 - _bufferLength; + size_t min = 64 - _iVars->bufferLength; if (min > length) min = length; - memcpy(_buffer.bytes + _bufferLength, buffer, min); - _bufferLength += min; + memcpy(_iVars->buffer.bytes + _iVars->bufferLength, + buffer, min); + _iVars->bufferLength += min; buffer += min; length -= min; - if (_bufferLength == 64) { - processBlock(_state, _buffer.words); - _bufferLength = 0; + if (_iVars->bufferLength == 64) { + processBlock(_iVars->state, _iVars->buffer.words); + _iVars->bufferLength = 0; } } } - (const unsigned char *)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_BE((uint32_t)(_bits & 0xFFFFFFFF)); - _buffer.words[15] = OF_BSWAP32_IF_BE((uint32_t)(_bits >> 32)); - - processBlock(_state, _buffer.words); - memset(&_buffer, 0, sizeof(_buffer)); - byteSwapVectorIfBE(_state, 4); - _calculated = true; - - return (const uint8_t *)_state; + return (const unsigned char *)_iVars->state; + + _iVars->buffer.bytes[_iVars->bufferLength] = 0x80; + of_explicit_memset(_iVars->buffer.bytes + _iVars->bufferLength + 1, 0, + 64 - _iVars->bufferLength - 1); + + if (_iVars->bufferLength >= 56) { + processBlock(_iVars->state, _iVars->buffer.words); + of_explicit_memset(_iVars->buffer.bytes, 0, 64); + } + + _iVars->buffer.words[14] = + OF_BSWAP32_IF_BE((uint32_t)(_iVars->bits & 0xFFFFFFFF)); + _iVars->buffer.words[15] = + OF_BSWAP32_IF_BE((uint32_t)(_iVars->bits >> 32)); + + processBlock(_iVars->state, _iVars->buffer.words); + of_explicit_memset(&_iVars->buffer, 0, sizeof(_iVars->buffer)); + byteSwapVectorIfBE(_iVars->state, 4); + _calculated = true; + + return (const unsigned char *)_iVars->state; } - (void)reset { [self of_resetState]; - _bits = 0; - memset(&_buffer, 0, sizeof(_buffer)); - _bufferLength = 0; + _iVars->bits = 0; + of_explicit_memset(&_iVars->buffer, 0, sizeof(_iVars->buffer)); + _iVars->bufferLength = 0; _calculated = false; } @end