From d3f7b49a5c2ca882f8961e4ebf41afec913291a9 Mon Sep 17 00:00:00 2001 From: Jonathan Schleifer Date: Fri, 3 Jan 2020 01:03:58 +0100 Subject: [PATCH] Use non-swappable memory --- CryptoPassphrase.h | 4 +- CryptoPassphrase.m | 88 +++++++++++++++++---------------------- LegacyPasswordGenerator.h | 7 ++-- LegacyPasswordGenerator.m | 58 ++++++++++++-------------- NewPasswordGenerator.h | 7 ++-- NewPasswordGenerator.m | 52 +++++++++++------------ PasswordGenerator.h | 8 ++-- 7 files changed, 101 insertions(+), 123 deletions(-) diff --git a/CryptoPassphrase.h b/CryptoPassphrase.h index 795c190..42b912a 100644 --- a/CryptoPassphrase.h +++ b/CryptoPassphrase.h @@ -1,7 +1,7 @@ /* - * 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 diff --git a/CryptoPassphrase.m b/CryptoPassphrase.m index ef26bb2..5159ee7 100644 --- a/CryptoPassphrase.m +++ b/CryptoPassphrase.m @@ -1,7 +1,7 @@ /* - * 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 @@ -64,7 +64,9 @@ showHelp(OFStream *output, bool verbose) OFMutableData *keyFile = nil; OFString *prompt; const char *promptCString; - char *passphrase; + char *passphraseCString; + size_t passphraseLength; + OFSecureData *passphrase; while ((option = [optionsParser nextOption]) != '\0') { switch (option) { @@ -143,57 +145,43 @@ showHelp(OFStream *output, bool verbose) if (keyFilePath != nil) keyFile = [OFMutableData dataWithContentsOfFile: keyFilePath]; - passphrase = getpass(promptCString); + passphraseCString = getpass(promptCString); + passphraseLength = strlen(passphraseCString); @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); - } + passphrase = [OFSecureData dataWithCount: passphraseLength + 1 + allowsSwappableMemory: false]; + memcpy(passphrase.mutableItems, passphraseCString, + passphraseLength + 1); } @finally { - of_explicit_memset(passphrase, 0, strlen(passphrase)); - - if (keyFile != nil) - of_explicit_memset(keyFile.mutableItems, 0, - keyFile.count); + 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 diff --git a/LegacyPasswordGenerator.h b/LegacyPasswordGenerator.h index 4679832..dad1735 100644 --- a/LegacyPasswordGenerator.h +++ b/LegacyPasswordGenerator.h @@ -1,7 +1,7 @@ /* - * 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 @@ -27,7 +27,6 @@ size_t _length; OFString *_site; OFData *_keyFile; - const char *_passphrase; - unsigned char *_output; + OFSecureData *_passphrase, *_output; } @end diff --git a/LegacyPasswordGenerator.m b/LegacyPasswordGenerator.m index cebe02e..c5ae33d 100644 --- a/LegacyPasswordGenerator.m +++ b/LegacyPasswordGenerator.m @@ -1,7 +1,7 @@ /* - * 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 @@ -58,19 +58,19 @@ 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 release]; + _output = nil; + _output = [[OFSecureData alloc] initWithCount: _length + 1 + allowsSwappableMemory: false]; - _output = [self allocMemoryWithSize: _length + 1]; - - passphraseLength = combinedPassphraseLength = strlen(_passphrase); + passphraseLength = combinedPassphraseLength = _passphrase.count - 1; if (_keyFile != nil) { if (SIZE_MAX - combinedPassphraseLength < _keyFile.count) @throw [OFOutOfRangeException exception]; @@ -78,36 +78,32 @@ combinedPassphraseLength += _keyFile.count; } - if ((combinedPassphrase = malloc(combinedPassphraseLength)) == NULL) - @throw [OFOutOfMemoryException - exceptionWithRequestedSize: combinedPassphraseLength]; - @try { - memcpy(combinedPassphrase, _passphrase, passphraseLength); + combinedPassphrase = [OFSecureData + dataWithCount: combinedPassphraseLength + allowsSwappableMemory: false]; + combinedPassphraseItems = combinedPassphrase.mutableItems; + memcpy(combinedPassphraseItems, _passphrase.items, passphraseLength); - if (_keyFile != nil) - memcpy(combinedPassphrase + passphraseLength, - _keyFile.items, _keyFile.count); + if (_keyFile != nil) + memcpy(combinedPassphraseItems + 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); - } + 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 diff --git a/NewPasswordGenerator.h b/NewPasswordGenerator.h index a028f3e..8ac2e52 100644 --- a/NewPasswordGenerator.h +++ b/NewPasswordGenerator.h @@ -1,7 +1,7 @@ /* - * 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 @@ -27,7 +27,6 @@ size_t _length; OFString *_site; OFData *_keyFile; - const char *_passphrase; - unsigned char *_output; + OFSecureData *_passphrase, *_output; } @end diff --git a/NewPasswordGenerator.m b/NewPasswordGenerator.m index 7542d5e..b987918 100644 --- a/NewPasswordGenerator.m +++ b/NewPasswordGenerator.m @@ -1,7 +1,7 @@ /* - * 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 @@ -45,19 +45,19 @@ 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 release]; + _output = nil; + _output = [[OFSecureData alloc] initWithCount: _length + 1 + allowsSwappableMemory: false]; - _output = [self allocMemoryWithSize: _length + 1]; - - passphraseLength = combinedPassphraseLength = strlen(_passphrase); + passphraseLength = combinedPassphraseLength = _passphrase.count - 1; if (_keyFile != nil) { if (SIZE_MAX - combinedPassphraseLength < _keyFile.count) @throw [OFOutOfRangeException exception]; @@ -65,30 +65,26 @@ combinedPassphraseLength += _keyFile.count; } - if ((combinedPassphrase = malloc(combinedPassphraseLength)) == NULL) - @throw [OFOutOfMemoryException - exceptionWithRequestedSize: combinedPassphraseLength]; - @try { - memcpy(combinedPassphrase, _passphrase, passphraseLength); + combinedPassphrase = [OFSecureData + dataWithCount: combinedPassphraseLength + allowsSwappableMemory: false]; + combinedPassphraseItems = combinedPassphrase.mutableItems; + memcpy(combinedPassphraseItems, _passphrase.items, passphraseLength); - if (_keyFile != nil) - memcpy(combinedPassphrase + passphraseLength, - _keyFile.items, _keyFile.count); + if (_keyFile != nil) + memcpy(combinedPassphraseItems + 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); - } + 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 diff --git a/PasswordGenerator.h b/PasswordGenerator.h index f680592..4f0f472 100644 --- a/PasswordGenerator.h +++ b/PasswordGenerator.h @@ -1,7 +1,7 @@ /* - * 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 @@ -26,8 +26,8 @@ @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;