Index: Makefile ================================================================== --- Makefile +++ Makefile @@ -10,13 +10,19 @@ config.status \ extra.mk include buildsys.mk +.PHONY: docs tarball + utils tests: src -tarball: +docs: + rm -fr docs + doxygen >/dev/null + +tarball: docs echo "Generating tarball for version ${PACKAGE_VERSION}..." rm -fr objfw-${PACKAGE_VERSION} objfw-${PACKAGE_VERSION}.tar \ objfw-${PACKAGE_VERSION}.tar.gz fossil tarball --name objfw-${PACKAGE_VERSION} current - \ --exclude '.fossil-settings/*,.gitignore,.travis.yml' | \ Index: src/OFDNSResolver.h ================================================================== --- src/OFDNSResolver.h +++ src/OFDNSResolver.h @@ -63,11 +63,13 @@ /*! The server returned an error that the domain does not exist */ OF_DNS_RESOLVER_ERROR_SERVER_NAME_ERROR, /*! The server does not have support for the requested query */ OF_DNS_RESOLVER_ERROR_SERVER_NOT_IMPLEMENTED, /*! The server refused the query */ - OF_DNS_RESOLVER_ERROR_SERVER_REFUSED + OF_DNS_RESOLVER_ERROR_SERVER_REFUSED, + /*! There was no name server to query */ + OF_DNS_RESOLVER_ERROR_NO_NAME_SERVER } of_dns_resolver_error_t; /*! * @protocol OFDNSResolverQueryDelegate OFDNSResolver.h ObjFW/OFDNSResolver.h * Index: src/OFDNSResolver.m ================================================================== --- src/OFDNSResolver.m +++ src/OFDNSResolver.m @@ -816,10 +816,21 @@ ID = [OFNumber numberWithUInt16: (uint16_t)of_random()]; } while ([_queries objectForKey: ID] != nil); if (query.domainName.UTF8StringLength > 253) @throw [OFOutOfRangeException exception]; + + if (_settings->_nameServers.count == 0) { + id exception = [OFDNSQueryFailedException + exceptionWithQuery: query + error: OF_DNS_RESOLVER_ERROR_NO_NAME_SERVER]; + [delegate resolver: self + didPerformQuery: query + response: nil + exception: exception]; + return; + } context = [[[OFDNSResolverContext alloc] initWithQuery: query ID: ID settings: _settings @@ -878,16 +889,14 @@ exception = [OFDNSQueryFailedException exceptionWithQuery: context->_query error: OF_DNS_RESOLVER_ERROR_TIMEOUT]; - if ([context->_delegate respondsToSelector: - @selector(resolver:didPerformQuery:response:exception:)]) - [context->_delegate resolver: self - didPerformQuery: context->_query - response: nil - exception: exception]; + [context->_delegate resolver: self + didPerformQuery: context->_query + response: nil + exception: exception]; } - (bool)of_handleResponseBuffer: (unsigned char *)buffer length: (size_t)length sender: (const of_socket_address_t *)sender @@ -1039,16 +1048,14 @@ } if (exception != nil) response = nil; - if ([context->_delegate respondsToSelector: - @selector(resolver:didPerformQuery:response:exception:)]) - [context->_delegate resolver: self - didPerformQuery: context->_query - response: response - exception: exception]; + [context->_delegate resolver: self + didPerformQuery: context->_query + response: response + exception: exception]; return false; } - (bool)socket: (OFDatagramSocket *)sock @@ -1273,18 +1280,16 @@ exception = [OFDNSQueryFailedException exceptionWithQuery: context->_query error: OF_DNS_RESOLVER_ERROR_CANCELED]; - if ([context->_delegate respondsToSelector: - @selector(resolver:didPerformQuery:response:exception:)]) - [context->_delegate resolver: self - didPerformQuery: context->_query - response: nil - exception: exception]; + [context->_delegate resolver: self + didPerformQuery: context->_query + response: nil + exception: exception]; } [_queries removeAllObjects]; objc_autoreleasePoolPop(pool); } @end Index: src/exceptions/OFDNSQueryFailedException.m ================================================================== --- src/exceptions/OFDNSQueryFailedException.m +++ src/exceptions/OFDNSQueryFailedException.m @@ -42,10 +42,12 @@ case OF_DNS_RESOLVER_ERROR_SERVER_NOT_IMPLEMENTED: return @"The server does not have support for the requested " @"query."; case OF_DNS_RESOLVER_ERROR_SERVER_REFUSED: return @"The server refused the query."; + case OF_DNS_RESOLVER_ERROR_NO_NAME_SERVER: + return @"There was no name server to query."; default: return @"Unknown error."; } } Index: src/pbkdf2.h ================================================================== --- src/pbkdf2.h +++ src/pbkdf2.h @@ -28,10 +28,38 @@ /*! @file */ @class OFHMAC; +/*! + * @brief The parameters for @ref of_pbkdf2. + */ +typedef struct of_pbkdf2_parameters_t { + /*! @brief The HMAC to use to derive a key. */ + OFHMAC *HMAC; + /*! @brief The number of iterations to perform. */ + size_t iterations; + /*! @brief The salt to derive a key with. */ + const unsigned char *salt; + /*! @brief The length of the salt. */ + size_t saltLength; + /*! @brief The password to derive a key from. */ + const char *password; + /*! @brief The length of the password. */ + size_t passwordLength; + /*! @brief The buffer to write the key to. */ + unsigned char *key; + /*! + * @brief The desired length for the derived key. + * + * @ref key needs to have enough storage. + */ + size_t keyLength; + /*! @brief Whether data may be stored in swappable memory. */ + bool allowsSwappableMemory; +} of_pbkdf2_parameters_t; + #ifdef __cplusplus extern "C" { #endif /*! * @brief Derives a key from a password and a salt using PBKDF2. @@ -38,25 +66,13 @@ * * @note This will call @ref OFHMAC::reset on the `HMAC` first, making it * possible to reuse the `HMAC`, but also meaning all previous results * from the `HMAC` get invalidated if they have not been copied. * - * @param HMAC The HMAC to use to derive a key - * @param iterations The number of iterations to perform - * @param salt The salt to derive a key with - * @param saltLength The length of the salt - * @param password The password to derive a key from - * @param passwordLength The length of the password - * @param key The buffer to write the key to - * @param keyLength The desired length for the derived key (`key` needs to have - * enough storage) - * @param allowsSwappableMemory Whether data may be stored in swappable memory + * @param param The parameters to use */ -extern void of_pbkdf2(OFHMAC *HMAC, size_t iterations, - const unsigned char *salt, size_t saltLength, - const char *password, size_t passwordLength, - unsigned char *key, size_t keyLength, bool allowsSwappableMemory); +extern void of_pbkdf2(of_pbkdf2_parameters_t param); #ifdef __cplusplus } #endif OF_ASSUME_NONNULL_END Index: src/pbkdf2.m ================================================================== --- src/pbkdf2.m +++ src/pbkdf2.m @@ -26,79 +26,79 @@ #import "OFOutOfMemoryException.h" #import "OFOutOfRangeException.h" #import "pbkdf2.h" -void of_pbkdf2(OFHMAC *HMAC, size_t iterations, - const unsigned char *salt, size_t saltLength, - const char *password, size_t passwordLength, - unsigned char *key, size_t keyLength, bool allowsSwappableMemory) +void +of_pbkdf2(of_pbkdf2_parameters_t param) { void *pool = objc_autoreleasePoolPush(); - size_t blocks, digestSize = HMAC.digestSize; + size_t blocks, digestSize = param.HMAC.digestSize; OFSecureData *buffer = [OFSecureData dataWithCount: digestSize - allowsSwappableMemory: allowsSwappableMemory]; + allowsSwappableMemory: param.allowsSwappableMemory]; OFSecureData *digest = [OFSecureData dataWithCount: digestSize - allowsSwappableMemory: allowsSwappableMemory]; + allowsSwappableMemory: param.allowsSwappableMemory]; unsigned char *bufferItems = buffer.mutableItems; unsigned char *digestItems = digest.mutableItems; OFSecureData *extendedSalt; unsigned char *extendedSaltItems; - if (HMAC == nil || iterations == 0 || salt == NULL || - password == NULL || key == NULL || keyLength == 0) + if (param.HMAC == nil || param.iterations == 0 || param.salt == NULL || + param.password == NULL || param.key == NULL || param.keyLength == 0) @throw [OFInvalidArgumentException exception]; - blocks = keyLength / digestSize; - if (keyLength % digestSize != 0) + blocks = param.keyLength / digestSize; + if (param.keyLength % digestSize != 0) blocks++; - if (saltLength > SIZE_MAX - 4 || blocks > UINT32_MAX) + if (param.saltLength > SIZE_MAX - 4 || blocks > UINT32_MAX) @throw [OFOutOfRangeException exception]; - extendedSalt = [OFSecureData dataWithCount: saltLength + 4 - allowsSwappableMemory: allowsSwappableMemory]; + extendedSalt = [OFSecureData + dataWithCount: param.saltLength + 4 + allowsSwappableMemory: param.allowsSwappableMemory]; extendedSaltItems = extendedSalt.mutableItems; @try { uint32_t i = OF_BSWAP32_IF_LE(1); - [HMAC setKey: password - length: passwordLength]; + [param.HMAC setKey: param.password + length: param.passwordLength]; - memcpy(extendedSaltItems, salt, saltLength); + memcpy(extendedSaltItems, param.salt, param.saltLength); - while (keyLength > 0) { + while (param.keyLength > 0) { size_t length; - memcpy(extendedSaltItems + saltLength, &i, 4); - - [HMAC reset]; - [HMAC updateWithBuffer: extendedSaltItems - length: saltLength + 4]; - memcpy(bufferItems, HMAC.digest, digestSize); - memcpy(digestItems, HMAC.digest, digestSize); - - for (size_t j = 1; j < iterations; j++) { - [HMAC reset]; - [HMAC updateWithBuffer: digestItems - length: digestSize]; - memcpy(digestItems, HMAC.digest, digestSize); + memcpy(extendedSaltItems + param.saltLength, &i, 4); + + [param.HMAC reset]; + [param.HMAC updateWithBuffer: extendedSaltItems + length: param.saltLength + 4]; + memcpy(bufferItems, param.HMAC.digest, digestSize); + memcpy(digestItems, param.HMAC.digest, digestSize); + + for (size_t j = 1; j < param.iterations; j++) { + [param.HMAC reset]; + [param.HMAC updateWithBuffer: digestItems + length: digestSize]; + memcpy(digestItems, param.HMAC.digest, + digestSize); for (size_t k = 0; k < digestSize; k++) bufferItems[k] ^= digestItems[k]; } length = digestSize; - if (length > keyLength) - length = keyLength; + if (length > param.keyLength) + length = param.keyLength; - memcpy(key, bufferItems, length); - key += length; - keyLength -= length; + memcpy(param.key, bufferItems, length); + param.key += length; + param.keyLength -= length; i = OF_BSWAP32_IF_LE(OF_BSWAP32_IF_LE(i) + 1); } } @catch (id e) { [extendedSalt zero]; @@ -105,10 +105,10 @@ [buffer zero]; [digest zero]; @throw e; } @finally { - [HMAC zero]; + [param.HMAC zero]; } objc_autoreleasePoolPop(pool); } Index: src/runtime/exception.m ================================================================== --- src/runtime/exception.m +++ src/runtime/exception.m @@ -752,12 +752,13 @@ e->exception.class = GNUCOBJC_EXCEPTION_CLASS; e->exception.cleanup = (emergency ? emergencyExceptionCleanup : cleanup); e->object = object; - if (_Unwind_RaiseException(&e->exception) == _URC_END_OF_STACK && - uncaughtExceptionHandler != NULL) + _Unwind_RaiseException(&e->exception); + + if (uncaughtExceptionHandler != NULL) uncaughtExceptionHandler(object); OBJC_ERROR("_Unwind_RaiseException() returned!") } Index: src/scrypt.h ================================================================== --- src/scrypt.h +++ src/scrypt.h @@ -28,10 +28,40 @@ /*! @file */ @class OFHMAC; +/*! + * @brief The parameters for @ref of_scrypt. + */ +typedef struct of_scrypt_parameters_t { + /*! @brief The block size to use. */ + size_t blockSize; + /*! @brief The CPU/memory cost factor to use. */ + size_t costFactor; + /*! @brief The parallelization to use. */ + size_t parallelization; + /*! @brief The salt to derive a key with. */ + const unsigned char *salt; + /*! @brief The length of the salt. */ + size_t saltLength; + /*! @brief The password to derive a key from. */ + const char *password; + /*! @brief The length of the password. */ + size_t passwordLength; + /*! @brief The buffer to write the key to. */ + unsigned char *key; + /*! + * @brief The desired length for the derived key. + * + * @ref key needs to have enough storage. + */ + size_t keyLength; + /*! @brief Whether data may be stored in swappable memory. */ + bool allowsSwappableMemory; +} of_scrypt_parameters_t; + #ifdef __cplusplus extern "C" { #endif extern void of_salsa20_8_core(uint32_t buffer[_Nonnull 16]); extern void of_scrypt_block_mix(uint32_t *output, const uint32_t *input, @@ -40,26 +70,13 @@ size_t costFactor, uint32_t *tmp); /*! * @brief Derives a key from a password and a salt using scrypt. * - * @param blockSize The block size to use - * @param costFactor The CPU/memory cost factor to use - * @param parallelization The parallelization to use - * @param salt The salt to derive a key with - * @param saltLength The length of the salt - * @param password The password to derive a key from - * @param passwordLength The length of the password - * @param key The buffer to write the key to - * @param keyLength The desired length for the derived key (`key` needs to have - * enough storage) - * @param allowsSwappableMemory Whether data may be stored in swappable memory + * @param param The parameters to use */ -extern void of_scrypt(size_t blockSize, size_t costFactor, - size_t parallelization, const unsigned char *salt, size_t saltLength, - const char *password, size_t passwordLength, - unsigned char *key, size_t keyLength, bool allowsSwappableMemory); +extern void of_scrypt(of_scrypt_parameters_t param); #ifdef __cplusplus } #endif OF_ASSUME_NONNULL_END Index: src/scrypt.m ================================================================== --- src/scrypt.m +++ src/scrypt.m @@ -83,12 +83,12 @@ { uint32_t tmp[16]; /* Check defined here and executed in of_scrypt() */ #define OVERFLOW_CHECK_1 \ - if (blockSize > SIZE_MAX / 2 || \ - 2 * blockSize - 1 > SIZE_MAX / 16) \ + if (param.blockSize > SIZE_MAX / 2 || \ + 2 * param.blockSize - 1 > SIZE_MAX / 16) \ @throw [OFOutOfRangeException exception]; memcpy(tmp, input + (2 * blockSize - 1) * 16, 64); for (size_t i = 0; i < 2 * blockSize; i++) { @@ -110,12 +110,12 @@ void of_scrypt_romix(uint32_t *buffer, size_t blockSize, size_t costFactor, uint32_t *tmp) { /* Check defined here and executed in of_scrypt() */ -#define OVERFLOW_CHECK_2 \ - if (blockSize > SIZE_MAX / 128 / costFactor) \ +#define OVERFLOW_CHECK_2 \ + if (param.blockSize > SIZE_MAX / 128 / param.costFactor) \ @throw [OFOutOfRangeException exception]; uint32_t *tmp2 = tmp + 32 * blockSize; memcpy(tmp, buffer, 128 * blockSize); @@ -137,20 +137,19 @@ if (i < costFactor - 1) memcpy(tmp, buffer, 128 * blockSize); } } -void of_scrypt(size_t blockSize, size_t costFactor, - size_t parallelization, const unsigned char *salt, size_t saltLength, - const char *password, size_t passwordLength, - unsigned char *key, size_t keyLength, bool allowsSwappableMemory) +void +of_scrypt(of_scrypt_parameters_t param) { OFSecureData *tmp = nil, *buffer = nil; OFHMAC *HMAC = nil; - if (blockSize == 0 || costFactor <= 1 || - (costFactor & (costFactor - 1)) != 0 || parallelization == 0) + if (param.blockSize == 0 || param.costFactor <= 1 || + (param.costFactor & (param.costFactor - 1)) != 0 || + param.parallelization == 0) @throw [OFInvalidArgumentException exception]; /* * These are defined by the functions above. They are defined there so * that the check is next to the code and easy to verify, but actually @@ -160,45 +159,63 @@ OVERFLOW_CHECK_2 @try { uint32_t *tmpItems, *bufferItems; - if (costFactor > SIZE_MAX - 1 || - (costFactor + 1) > SIZE_MAX / 128) + if (param.costFactor > SIZE_MAX - 1 || + (param.costFactor + 1) > SIZE_MAX / 128) @throw [OFOutOfRangeException exception]; tmp = [[OFSecureData alloc] - initWithItemSize: blockSize - count: (costFactor + 1) * 128 - allowsSwappableMemory: allowsSwappableMemory]; + initWithItemSize: param.blockSize + count: (param.costFactor + 1) * 128 + allowsSwappableMemory: param.allowsSwappableMemory]; tmpItems = tmp.mutableItems; - if (parallelization > SIZE_MAX / 128) + if (param.parallelization > SIZE_MAX / 128) @throw [OFOutOfRangeException exception]; buffer = [[OFSecureData alloc] - initWithItemSize: blockSize - count: parallelization * 128 - allowsSwappableMemory: allowsSwappableMemory]; + initWithItemSize: param.blockSize + count: param.parallelization * 128 + allowsSwappableMemory: param.allowsSwappableMemory]; bufferItems = buffer.mutableItems; HMAC = [[OFHMAC alloc] initWithHashClass: [OFSHA256Hash class] - allowsSwappableMemory: allowsSwappableMemory]; - - of_pbkdf2(HMAC, 1, salt, saltLength, password, passwordLength, - (unsigned char *)bufferItems, - parallelization * 128 * blockSize, allowsSwappableMemory); - - for (size_t i = 0; i < parallelization; i++) - of_scrypt_romix(bufferItems + i * 32 * blockSize, - blockSize, costFactor, tmpItems); - - of_pbkdf2(HMAC, 1, (unsigned char *)bufferItems, - parallelization * 128 * blockSize, password, passwordLength, - key, keyLength, allowsSwappableMemory); + allowsSwappableMemory: param.allowsSwappableMemory]; + + of_pbkdf2((of_pbkdf2_parameters_t){ + .HMAC = HMAC, + .iterations = 1, + .salt = param.salt, + .saltLength = param.saltLength, + .password = param.password, + .passwordLength = param.passwordLength, + .key = (unsigned char *)bufferItems, + .keyLength = param.parallelization * 128 * + param.blockSize, + .allowsSwappableMemory = param.allowsSwappableMemory + }); + + for (size_t i = 0; i < param.parallelization; i++) + of_scrypt_romix(bufferItems + i * 32 * param.blockSize, + param.blockSize, param.costFactor, tmpItems); + + of_pbkdf2((of_pbkdf2_parameters_t){ + .HMAC = HMAC, + .iterations = 1, + .salt = (unsigned char *)bufferItems, + .saltLength = param.parallelization * 128 * + param.blockSize, + .password = param.password, + .passwordLength = param.passwordLength, + .key = param.key, + .keyLength = param.keyLength, + .allowsSwappableMemory = param.allowsSwappableMemory + }); } @finally { [tmp release]; [buffer release]; [HMAC release]; } } Index: tests/PBKDF2Tests.m ================================================================== --- tests/PBKDF2Tests.m +++ tests/PBKDF2Tests.m @@ -32,47 +32,96 @@ unsigned char key[25]; /* Test vectors from RFC 6070 */ TEST(@"PBKDF2-SHA1, 1 iteration", - R(of_pbkdf2(HMAC, 1, (unsigned char *)"salt", 4, "password", 8, key, - 20, true)) && - memcmp(key, "\x0C\x60\xC8\x0F\x96\x1F\x0E\x71\xF3\xA9\xB5\x24\xAF" - "\x60\x12\x06\x2F\xE0\x37\xA6", 20) == 0) + R(of_pbkdf2((of_pbkdf2_parameters_t){ + .HMAC = HMAC, + .iterations = 1, + .salt = (unsigned char *)"salt", + .saltLength = 4, + .password = "password", + .passwordLength = 8, + .key = key, + .keyLength = 20, + .allowsSwappableMemory = true + })) && memcmp(key, "\x0C\x60\xC8\x0F\x96\x1F\x0E\x71\xF3\xA9\xB5" + "\x24\xAF\x60\x12\x06\x2F\xE0\x37\xA6", 20) == 0) TEST(@"PBKDF2-SHA1, 2 iterations", - R(of_pbkdf2(HMAC, 2, (unsigned char *)"salt", 4, "password", 8, key, - 20, true)) && - memcmp(key, "\xEA\x6C\x01\x4D\xC7\x2D\x6F\x8C\xCD\x1E\xD9\x2A\xCE" - "\x1D\x41\xF0\xD8\xDE\x89\x57", 20) == 0) + R(of_pbkdf2((of_pbkdf2_parameters_t){ + .HMAC = HMAC, + .iterations = 2, + .salt = (unsigned char *)"salt", + .saltLength = 4, + .password = "password", + .passwordLength = 8, + .key = key, + .keyLength = 20, + .allowsSwappableMemory = true + })) && memcmp(key, "\xEA\x6C\x01\x4D\xC7\x2D\x6F\x8C\xCD\x1E\xD9" + "\x2A\xCE\x1D\x41\xF0\xD8\xDE\x89\x57", 20) == 0) TEST(@"PBKDF2-SHA1, 4096 iterations", - R(of_pbkdf2(HMAC, 4096, (unsigned char *)"salt", 4, "password", 8, - key, 20, true)) && - memcmp(key, "\x4B\x00\x79\x01\xB7\x65\x48\x9A\xBE\xAD\x49\xD9\x26" - "\xF7\x21\xD0\x65\xA4\x29\xC1", 20) == 0) + R(of_pbkdf2((of_pbkdf2_parameters_t){ + .HMAC = HMAC, + .iterations = 4096, + .salt = (unsigned char *)"salt", + .saltLength = 4, + .password = "password", + .passwordLength = 8, + .key = key, + .keyLength = 20, + .allowsSwappableMemory = true + })) && memcmp(key, "\x4B\x00\x79\x01\xB7\x65\x48\x9A\xBE\xAD\x49" + "\xD9\x26\xF7\x21\xD0\x65\xA4\x29\xC1", 20) == 0) /* This test takes too long, even on a fast machine. */ #if 0 TEST(@"PBKDF2-SHA1, 16777216 iterations", - R(of_pbkdf2(HMAC, 16777216, (unsigned char *)"salt", 4, "password", - 8, key, 20, true)) && - memcmp(key, "\xEE\xFE\x3D\x61\xCD\x4D\xA4\xE4\xE9\x94\x5B\x3D\x6B" - "\xA2\x15\x8C\x26\x34\xE9\x84", 20) == 0) + R(of_pbkdf2((of_pbkdf2_parameters_t){ + .HMAC = HMAC, + .iterations = 16777216, + .salt = (unsigned char *)"salt", + .saltLength = 4, + .password = "password", + .passwordLength = 8, + .key = key, + .keyLength = 20, + .allowsSwappableMemory = true + })) && memcmp(key, "\xEE\xFE\x3D\x61\xCD\x4D\xA4\xE4\xE9\x94\x5B" + "\x3D\x6B\xA2\x15\x8C\x26\x34\xE9\x84", 20) == 0) #endif TEST(@"PBKDF2-SHA1, 4096 iterations, key > 1 block", - R(of_pbkdf2(HMAC, 4096, - (unsigned char *)"saltSALTsaltSALTsaltSALTsaltSALTsalt", 36, - "passwordPASSWORDpassword", 24, key, 25, true)) && + R(of_pbkdf2((of_pbkdf2_parameters_t){ + .HMAC = HMAC, + .iterations = 4096, + .salt = (unsigned char *)"saltSALTsaltSALTsalt" + "SALTsaltSALTsalt", + .saltLength = 36, + .password = "passwordPASSWORDpassword", + .passwordLength = 24, + .key = key, + .keyLength = 25, + .allowsSwappableMemory = true + })) && memcmp(key, "\x3D\x2E\xEC\x4F\xE4\x1C\x84\x9B\x80\xC8\xD8\x36\x62" - "\xC0\xE4\x4A\x8B\x29\x1A\x96\x4C\xF2\xF0\x70\x38", 25) == 0) + "\xC0\xE4\x4A\x8B\x29\x1A\x96\x4C\xF2\xF0\x70\x38", 25) == 0) TEST(@"PBKDF2-SHA1, 4096 iterations, key < 1 block", - R(of_pbkdf2(HMAC, 4096, (unsigned char *)"sa\0lt", 5, "pass\0word", - 9, key, 16, true)) && - memcmp(key, "\x56\xFA\x6A\xA7\x55\x48\x09\x9D\xCC\x37\xD7\xF0\x34" - "\x25\xE0\xC3", 16) == 0) + R(of_pbkdf2((of_pbkdf2_parameters_t){ + .HMAC = HMAC, + .iterations = 4096, + .salt = (unsigned char *)"sa\0lt", + .saltLength = 5, + .password = "pass\0word", + .passwordLength = 9, + .key = key, + .keyLength = 16, + .allowsSwappableMemory = true + })) && memcmp(key, "\x56\xFA\x6A\xA7\x55\x48\x09\x9D\xCC\x37\xD7" + "\xF0\x34\x25\xE0\xC3", 16) == 0) objc_autoreleasePoolPop(pool); } @end Index: tests/ScryptTests.m ================================================================== --- tests/ScryptTests.m +++ tests/ScryptTests.m @@ -154,28 +154,66 @@ R(memcpy(ROMixBuffer, ROMixInput, 128)) && R(of_scrypt_romix(ROMixBuffer, 1, 16, ROMixTmp)) && memcmp(ROMixBuffer, ROMixOutput, 128) == 0) TEST(@"scrypt test vector #1", - R(of_scrypt(1, 16, 1, (unsigned char *)"", 0, "", 0, output, 64, - true)) && memcmp(output, testVector1, 64) == 0) + R(of_scrypt((of_scrypt_parameters_t){ + .blockSize = 1, + .costFactor = 16, + .parallelization = 1, + .salt = (unsigned char *)"", + .saltLength = 0, + .password = "", + .passwordLength = 0, + .key = output, + .keyLength = 64, + .allowsSwappableMemory = true + })) && memcmp(output, testVector1, 64) == 0) TEST(@"scrypt test vector #2", - R(of_scrypt(8, 1024, 16, (unsigned char *)"NaCl", 4, "password", 8, - output, 64, true)) && memcmp(output, testVector2, 64) == 0) + R(of_scrypt((of_scrypt_parameters_t){ + .blockSize = 8, + .costFactor = 1024, + .parallelization = 16, + .salt = (unsigned char *)"NaCl", + .saltLength = 4, + .password = "password", + .passwordLength = 8, + .key = output, + .keyLength = 64, + .allowsSwappableMemory = true + })) && memcmp(output, testVector2, 64) == 0) TEST(@"scrypt test vector #3", - R(of_scrypt(8, 16384, 1, (unsigned char *)"SodiumChloride", 14, - "pleaseletmein", 13, output, 64, true)) && - memcmp(output, testVector3, 64) == 0) + R(of_scrypt((of_scrypt_parameters_t){ + .blockSize = 8, + .costFactor = 16384, + .parallelization = 1, + .salt = (unsigned char *)"SodiumChloride", + .saltLength = 14, + .password = "pleaseletmein", + .passwordLength = 13, + .key = output, + .keyLength = 64, + .allowsSwappableMemory = true + })) && memcmp(output, testVector3, 64) == 0) /* The forth test vector is too expensive to include it in the tests. */ #if 0 TEST(@"scrypt test vector #4", - R(of_scrypt(8, 1048576, 1, (unsigned char *)"SodiumChloride", 14, - "pleaseletmein", 13, output, 64, true)) && - memcmp(output, testVector4, 64) == 0) + R(of_scrypt((of_scrypt_parameters_t){ + .blockSize = 8, + .costFactor = 1048576, + .parallelization = 1, + .salt = (unsigned char *)"SodiumChloride", + .saltLength = 14, + .password = "pleaseletmein", + .passwordLength = 13, + .key = output, + .keyLength = 64, + .allowsSwappableMemory = true + })) && memcmp(output, testVector4, 64) == 0) #endif objc_autoreleasePoolPop(pool); } @end