Index: CryptoPassphrase.h ================================================================== --- CryptoPassphrase.h +++ CryptoPassphrase.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 - 2019 Jonathan Schleifer + * Copyright (c) 2016 - 2020 Jonathan Schleifer * - * https://heap.zone/git/cryptopassphrase.git + * https://nil.im/git/cryptopassphrase.git * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice is present in all copies. * Index: CryptoPassphrase.m ================================================================== --- CryptoPassphrase.m +++ CryptoPassphrase.m @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 - 2019 Jonathan Schleifer + * Copyright (c) 2016 - 2020 Jonathan Schleifer * - * https://heap.zone/git/cryptopassphrase.git + * https://nil.im/git/cryptopassphrase.git * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice is present in all copies. * @@ -62,11 +62,13 @@ [OFOptionsParser parserWithOptions: options]; of_unichar_t option; OFMutableData *keyFile = nil; OFString *prompt; const char *promptCString; - char *passphrase; + char *passphraseCString; + size_t passphraseLength; + OFSecureData *passphrase; while ((option = [optionsParser nextOption]) != '\0') { switch (option) { case 'h': showHelp(of_stdout, true); @@ -141,59 +143,45 @@ promptCString = [prompt cStringWithEncoding: [OFLocale encoding]]; if (keyFilePath != nil) keyFile = [OFMutableData dataWithContentsOfFile: keyFilePath]; - passphrase = getpass(promptCString); - @try { - if (_repeat) { - char *passphraseCopy = of_strdup(passphrase); - - if (passphraseCopy == NULL) - @throw [OFOutOfMemoryException exception]; - - @try { - of_string_encoding_t encoding = - [OFLocale encoding]; - - prompt = [OFString stringWithFormat: - @"Repeat passphrase for site \"%@\": ", - generator.site]; - passphrase = getpass( - [prompt cStringWithEncoding: encoding]); - - if (strcmp(passphrase, passphraseCopy) != 0) { - [of_stderr writeString: - @"Passphrases do not match!\n"]; - [OFApplication terminateWithStatus: 1]; - } - } @finally { - of_explicit_memset(passphraseCopy, 0, - strlen(passphraseCopy)); - free(passphraseCopy); - } - } - - generator.keyFile = keyFile; - generator.passphrase = passphrase; - - [generator derivePassword]; - @try { - [of_stdout writeBuffer: generator.output - length: generator.length]; - [of_stdout writeBuffer: "\n" - length: 1]; - } @finally { - of_explicit_memset(generator.output, 0, - generator.length); - } - } @finally { - of_explicit_memset(passphrase, 0, strlen(passphrase)); - - if (keyFile != nil) - of_explicit_memset(keyFile.mutableItems, 0, - keyFile.count); - } + passphraseCString = getpass(promptCString); + passphraseLength = strlen(passphraseCString); + @try { + passphrase = [OFSecureData dataWithCount: passphraseLength + 1 + allowsSwappableMemory: false]; + memcpy(passphrase.mutableItems, passphraseCString, + passphraseLength + 1); + } @finally { + of_explicit_memset(passphraseCString, '\0', passphraseLength); + } + + if (_repeat) { + of_string_encoding_t encoding = [OFLocale encoding]; + + prompt = [OFString stringWithFormat: + @"Repeat passphrase for site \"%@\": ", generator.site]; + passphraseCString = + getpass([prompt cStringWithEncoding: encoding]); + + if (strcmp(passphraseCString, passphrase.items) != 0) { + [of_stderr writeString: @"Passphrases do not match!\n"]; + [OFApplication terminateWithStatus: 1]; + } + + of_explicit_memset(passphraseCString, '\0', + strlen(passphraseCString)); + } + + generator.keyFile = keyFile; + generator.passphrase = passphrase; + + [generator derivePassword]; + [of_stdout writeBuffer: generator.output.items + length: generator.length]; + [of_stdout writeBuffer: "\n" + length: 1]; [OFApplication terminate]; } @end Index: LegacyPasswordGenerator.h ================================================================== --- LegacyPasswordGenerator.h +++ LegacyPasswordGenerator.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 - 2019 Jonathan Schleifer + * Copyright (c) 2016 - 2020 Jonathan Schleifer * - * https://heap.zone/git/cryptopassphrase.git + * https://nil.im/git/cryptopassphrase.git * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice is present in all copies. * @@ -25,9 +25,8 @@ @interface LegacyPasswordGenerator: OFObject { size_t _length; OFString *_site; OFData *_keyFile; - const char *_passphrase; - unsigned char *_output; + OFSecureData *_passphrase, *_output; } @end Index: LegacyPasswordGenerator.m ================================================================== --- LegacyPasswordGenerator.m +++ LegacyPasswordGenerator.m @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 - 2019 Jonathan Schleifer + * Copyright (c) 2016 - 2020 Jonathan Schleifer * - * https://heap.zone/git/cryptopassphrase.git + * https://nil.im/git/cryptopassphrase.git * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice is present in all copies. * @@ -56,58 +56,54 @@ - (void)derivePassword { OFSHA256Hash *siteHash = [OFSHA256Hash cryptoHashWithAllowsSwappableMemory: true]; size_t passphraseLength, combinedPassphraseLength; - char *combinedPassphrase; + OFSecureData *combinedPassphrase; + char *combinedPassphraseItems; + unsigned char *outputItems; [siteHash updateWithBuffer: _site.UTF8String length: _site.UTF8StringLength]; - if (_output != NULL) { - of_explicit_memset(_output, 0, _length); - [self freeMemory: _output]; - } - - _output = [self allocMemoryWithSize: _length + 1]; - - passphraseLength = combinedPassphraseLength = strlen(_passphrase); + [_output release]; + _output = nil; + _output = [[OFSecureData alloc] initWithCount: _length + 1 + allowsSwappableMemory: false]; + + passphraseLength = combinedPassphraseLength = _passphrase.count - 1; if (_keyFile != nil) { if (SIZE_MAX - combinedPassphraseLength < _keyFile.count) @throw [OFOutOfRangeException exception]; combinedPassphraseLength += _keyFile.count; } - if ((combinedPassphrase = malloc(combinedPassphraseLength)) == NULL) - @throw [OFOutOfMemoryException - exceptionWithRequestedSize: combinedPassphraseLength]; - @try { - memcpy(combinedPassphrase, _passphrase, passphraseLength); - - if (_keyFile != nil) - memcpy(combinedPassphrase + passphraseLength, - _keyFile.items, _keyFile.count); - - of_scrypt(8, 524288, 2, siteHash.digest, - [siteHash.class digestSize], combinedPassphrase, - combinedPassphraseLength, _output, _length, true); - } @finally { - of_explicit_memset(combinedPassphrase, 0, - combinedPassphraseLength); - free(combinedPassphrase); - } + combinedPassphrase = [OFSecureData + dataWithCount: combinedPassphraseLength + allowsSwappableMemory: false]; + combinedPassphraseItems = combinedPassphrase.mutableItems; + memcpy(combinedPassphraseItems, _passphrase.items, passphraseLength); + + if (_keyFile != nil) + memcpy(combinedPassphraseItems + passphraseLength, + _keyFile.items, _keyFile.count); + + outputItems = _output.mutableItems; + of_scrypt(8, 524288, 2, siteHash.digest, [siteHash.class digestSize], + combinedPassphraseItems, combinedPassphraseLength, outputItems, + _length, true); /* * This has a bias, however, this is what scrypt-genpass does and the * legacy mode wants to be compatible to scrypt-genpass. */ - _output[0] = "abcdefghijklmnopqrstuvwxyz"[_output[0] % 26]; - _output[1] = "0123456789"[_output[1] % 10]; - _output[2] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[_output[2] % 26]; + outputItems[0] = "abcdefghijklmnopqrstuvwxyz"[outputItems[0] % 26]; + outputItems[1] = "0123456789"[outputItems[1] % 10]; + outputItems[2] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[outputItems[2] % 26]; for (size_t i = 3; i < _length; i++) - _output[i] = "abcdefghijklmnopqrstuvwxyz" + outputItems[i] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789"[_output[i] % (26 + 26 + 10)]; + "0123456789"[outputItems[i] % (26 + 26 + 10)]; } @end Index: NewPasswordGenerator.h ================================================================== --- NewPasswordGenerator.h +++ NewPasswordGenerator.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 - 2019 Jonathan Schleifer + * Copyright (c) 2016 - 2020 Jonathan Schleifer * - * https://heap.zone/git/cryptopassphrase.git + * https://nil.im/git/cryptopassphrase.git * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice is present in all copies. * @@ -25,9 +25,8 @@ @interface NewPasswordGenerator: OFObject { size_t _length; OFString *_site; OFData *_keyFile; - const char *_passphrase; - unsigned char *_output; + OFSecureData *_passphrase, *_output; } @end Index: NewPasswordGenerator.m ================================================================== --- NewPasswordGenerator.m +++ NewPasswordGenerator.m @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 - 2019 Jonathan Schleifer + * Copyright (c) 2016 - 2020 Jonathan Schleifer * - * https://heap.zone/git/cryptopassphrase.git + * https://nil.im/git/cryptopassphrase.git * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice is present in all copies. * @@ -43,52 +43,48 @@ - (void)derivePassword { OFSHA384Hash *siteHash = [OFSHA384Hash cryptoHashWithAllowsSwappableMemory: true]; size_t passphraseLength, combinedPassphraseLength; - char *combinedPassphrase; + OFSecureData *combinedPassphrase; + char *combinedPassphraseItems; + unsigned char *outputItems; [siteHash updateWithBuffer: _site.UTF8String length: _site.UTF8StringLength]; - if (_output != NULL) { - of_explicit_memset(_output, 0, _length); - [self freeMemory: _output]; - } - - _output = [self allocMemoryWithSize: _length + 1]; - - passphraseLength = combinedPassphraseLength = strlen(_passphrase); + [_output release]; + _output = nil; + _output = [[OFSecureData alloc] initWithCount: _length + 1 + allowsSwappableMemory: false]; + + passphraseLength = combinedPassphraseLength = _passphrase.count - 1; if (_keyFile != nil) { if (SIZE_MAX - combinedPassphraseLength < _keyFile.count) @throw [OFOutOfRangeException exception]; combinedPassphraseLength += _keyFile.count; } - if ((combinedPassphrase = malloc(combinedPassphraseLength)) == NULL) - @throw [OFOutOfMemoryException - exceptionWithRequestedSize: combinedPassphraseLength]; - @try { - memcpy(combinedPassphrase, _passphrase, passphraseLength); - - if (_keyFile != nil) - memcpy(combinedPassphrase + passphraseLength, - _keyFile.items, _keyFile.count); - - of_scrypt(8, 524288, 2, siteHash.digest, - [siteHash.class digestSize], combinedPassphrase, - combinedPassphraseLength, _output, _length, true); - } @finally { - of_explicit_memset(combinedPassphrase, 0, - combinedPassphraseLength); - free(combinedPassphrase); - } + combinedPassphrase = [OFSecureData + dataWithCount: combinedPassphraseLength + allowsSwappableMemory: false]; + combinedPassphraseItems = combinedPassphrase.mutableItems; + memcpy(combinedPassphraseItems, _passphrase.items, passphraseLength); + + if (_keyFile != nil) + memcpy(combinedPassphraseItems + passphraseLength, + _keyFile.items, _keyFile.count); + + outputItems = _output.mutableItems; + of_scrypt(8, 524288, 2, siteHash.digest, [siteHash.class digestSize], + combinedPassphraseItems, combinedPassphraseLength, outputItems, + _length, true); for (size_t i = 0; i < _length; i++) - _output[i] = + outputItems[i] = "123456789" "abcdefghijkmnopqrstuvwxyz" "ABCDEFGHJKLMNPQRSTUVWXYZ" - "#$%-=?"[_output[i] & 0x3F]; + "#$%-=?"[outputItems[i] & 0x3F]; } @end Index: PasswordGenerator.h ================================================================== --- PasswordGenerator.h +++ PasswordGenerator.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 - 2019 Jonathan Schleifer + * Copyright (c) 2016 - 2020 Jonathan Schleifer * - * https://heap.zone/git/cryptopassphrase.git + * https://nil.im/git/cryptopassphrase.git * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice is present in all copies. * @@ -24,11 +24,11 @@ @protocol PasswordGenerator @property (nonatomic) size_t length; @property (copy, nonatomic) OFString *site; @property (retain, nonatomic) OFData *keyFile; -@property (nonatomic) const char *passphrase; -@property (readonly, nonatomic) unsigned char *output; +@property (retain) OFSecureData *passphrase; +@property (readonly, nonatomic) OFSecureData *output; + (instancetype)generator; - (void)derivePassword; @end