CryptoPassphrase  Check-in [d5ba7b8a87]

Overview
Comment:Use non-swappable memory
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: d5ba7b8a87c38520b2c0ca103b585c38b1f8d84ac98b295f1029b3359fdd3388
User & Date: js on 2020-01-03 00:03:58
Other Links: manifest | tags
Context
2020-01-03
00:19
iOS: Update to recent changes check-in: 496f11bd4b user: js tags: trunk
00:03
Use non-swappable memory check-in: d5ba7b8a87 user: js tags: trunk
2019-12-28
22:46
Adjust to ObjFW changes check-in: 31d77b5098 user: js tags: trunk
Changes

Modified CryptoPassphrase.h from [4c913f774e] to [3050e24daf].

1
2

3
4

5
6
7
8
9
10
11
1

2
3

4
5
6
7
8
9
10
11

-
+

-
+







/*
 * Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
 * Copyright (c) 2016 - 2020 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

Modified CryptoPassphrase.m from [af2775fb50] to [d60a88125c].

1
2

3
4

5
6
7
8
9
10
11
1

2
3

4
5
6
7
8
9
10
11

-
+

-
+







/*
 * Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
 * Copyright (c) 2016 - 2020 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60
61
62
63
64
65
66
67



68
69
70
71
72
73
74
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74
75
76







-
+
+
+







	};
	OFOptionsParser *optionsParser =
	    [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);

			[OFApplication terminate];
139
140
141
142
143
144
145
146


147
148
149
150







151
152
153
154
155


156
157
158
159


160
161
162


163
164
165


166
167
168
169
170
171





172
173
174

175
176
177


178
179

180
181
182
183
184




185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
141
142
143
144
145
146
147

148
149
150



151
152
153
154
155
156
157


158


159
160

161


162
163



164
165
166


167
168






169
170
171
172
173



174
175


176
177
178

179





180
181
182
183











184
185
186
187







-
+
+

-
-
-
+
+
+
+
+
+
+
-
-

-
-
+
+
-

-
-
+
+
-
-
-
+
+

-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
-
-
-
+

-
-
+
+

-
+
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-




	prompt = [OFString stringWithFormat: @"Passphrase for site \"%@\": ",
					     generator.site];
	promptCString = [prompt cStringWithEncoding: [OFLocale encoding]];

	if (keyFilePath != nil)
		keyFile = [OFMutableData dataWithContentsOfFile: keyFilePath];

	passphrase = getpass(promptCString);
	passphraseCString = getpass(promptCString);
	passphraseLength = strlen(passphraseCString);
	@try {
		if (_repeat) {
			char *passphraseCopy = of_strdup(passphrase);

		passphrase = [OFSecureData dataWithCount: passphraseLength + 1
				   allowsSwappableMemory: false];
		memcpy(passphrase.mutableItems, passphraseCString,
		    passphraseLength + 1);
	} @finally {
		of_explicit_memset(passphraseCString, '\0', passphraseLength);
	}
			if (passphraseCopy == NULL)
				@throw [OFOutOfMemoryException exception];

			@try {
				of_string_encoding_t encoding =
	if (_repeat) {
		of_string_encoding_t encoding = [OFLocale encoding];
				    [OFLocale encoding];

				prompt = [OFString stringWithFormat:
				    @"Repeat passphrase for site \"%@\": ",
		prompt = [OFString stringWithFormat:
		    @"Repeat passphrase for site \"%@\": ", generator.site];
				    generator.site];
				passphrase = getpass(
				    [prompt cStringWithEncoding: encoding]);
		passphraseCString =
		    getpass([prompt cStringWithEncoding: encoding]);

				if (strcmp(passphrase, passphraseCopy) != 0) {
					[of_stderr writeString:
		if (strcmp(passphraseCString, passphrase.items) != 0) {
			[of_stderr writeString: @"Passphrases do not match!\n"];
					    @"Passphrases do not match!\n"];
					[OFApplication terminateWithStatus: 1];
				}
			} @finally {
				of_explicit_memset(passphraseCopy, 0,
				    strlen(passphraseCopy));
			[OFApplication terminateWithStatus: 1];
		}

		of_explicit_memset(passphraseCString, '\0',
		    strlen(passphraseCString));
				free(passphraseCopy);
			}
		}
	}

		generator.keyFile = keyFile;
		generator.passphrase = passphrase;
	generator.keyFile = keyFile;
	generator.passphrase = passphrase;

		[generator derivePassword];
	[generator derivePassword];
		@try {
			[of_stdout writeBuffer: generator.output
					length: generator.length];
			[of_stdout writeBuffer: "\n"
					length: 1];
	[of_stdout writeBuffer: generator.output.items
			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);
	}

	[OFApplication terminate];
}
@end

Modified LegacyPasswordGenerator.h from [8b2f2b2c68] to [ecf25f2249].

1
2

3
4

5
6
7
8
9
10
11
1

2
3

4
5
6
7
8
9
10
11

-
+

-
+







/*
 * Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
 * Copyright (c) 2016 - 2020 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
24
25
26
27
28
29
30

31
32
33
23
24
25
26
27
28
29

30

31
32







-
+
-


#import "PasswordGenerator.h"

@interface LegacyPasswordGenerator: OFObject <PasswordGenerator>
{
	size_t _length;
	OFString *_site;
	OFData *_keyFile;
	const char *_passphrase;
	OFSecureData *_passphrase, *_output;
	unsigned char *_output;
}
@end

Modified LegacyPasswordGenerator.m from [c0c1315d5a] to [d5c5dfec12].

1
2

3
4

5
6
7
8
9
10
11
1

2
3

4
5
6
7
8
9
10
11

-
+

-
+







/*
 * Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
 * Copyright (c) 2016 - 2020 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54
55
56
57
58
59
60

61


62
63
64
65
66

67
68

69
70
71


72
73

74
75
76
77
78
79
80
81

82
83
84
85




86
87
88
89



90

91
92
93



94
95
96
97
98
99
100
101
102
103
104
105
106



107
108
109

110
111

112
113
54
55
56
57
58
59
60
61

62
63
64
65
66
67

68


69



70
71
72

73
74
75
76
77
78
79
80

81




82
83
84
85
86



87
88
89
90
91



92
93
94





95
96
97
98
99



100
101
102
103
104

105
106

107
108
109







+
-
+
+




-
+
-
-
+
-
-
-
+
+

-
+







-
+
-
-
-
-
+
+
+
+

-
-
-
+
+
+

+
-
-
-
+
+
+
-
-
-
-
-





-
-
-
+
+
+


-
+

-
+


}

- (void)derivePassword
{
	OFSHA256Hash *siteHash = [OFSHA256Hash
	    cryptoHashWithAllowsSwappableMemory: true];
	size_t passphraseLength, combinedPassphraseLength;
	OFSecureData *combinedPassphrase;
	char *combinedPassphrase;
	char *combinedPassphraseItems;
	unsigned char *outputItems;

	[siteHash updateWithBuffer: _site.UTF8String
			    length: _site.UTF8StringLength];

	if (_output != NULL) {
	[_output release];
		of_explicit_memset(_output, 0, _length);
		[self freeMemory: _output];
	_output = nil;
	}

	_output = [self allocMemoryWithSize: _length + 1];
	_output = [[OFSecureData alloc] initWithCount: _length + 1
				allowsSwappableMemory: false];

	passphraseLength = combinedPassphraseLength = strlen(_passphrase);
	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)
	combinedPassphrase = [OFSecureData
		@throw [OFOutOfMemoryException
		    exceptionWithRequestedSize: combinedPassphraseLength];
	@try {
		memcpy(combinedPassphrase, _passphrase, passphraseLength);
		    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);

	outputItems = _output.mutableItems;
		of_scrypt(8, 524288, 2, siteHash.digest,
		    [siteHash.class digestSize], combinedPassphrase,
		    combinedPassphraseLength, _output, _length, true);
	of_scrypt(8, 524288, 2, siteHash.digest, [siteHash.class digestSize],
	    combinedPassphraseItems, combinedPassphraseLength, outputItems,
	    _length, true);
	} @finally {
		of_explicit_memset(combinedPassphrase, 0,
		    combinedPassphraseLength);
		free(combinedPassphrase);
	}

	/*
	 * 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

Modified NewPasswordGenerator.h from [9f48bbafee] to [9d87dde63d].

1
2

3
4

5
6
7
8
9
10
11
1

2
3

4
5
6
7
8
9
10
11

-
+

-
+







/*
 * Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
 * Copyright (c) 2016 - 2020 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
24
25
26
27
28
29
30

31
32
33
23
24
25
26
27
28
29

30

31
32







-
+
-


#import "PasswordGenerator.h"

@interface NewPasswordGenerator: OFObject <PasswordGenerator>
{
	size_t _length;
	OFString *_site;
	OFData *_keyFile;
	const char *_passphrase;
	OFSecureData *_passphrase, *_output;
	unsigned char *_output;
}
@end

Modified NewPasswordGenerator.m from [37a8c168df] to [17ced95bbb].

1
2

3
4

5
6
7
8
9
10
11
1

2
3

4
5
6
7
8
9
10
11

-
+

-
+







/*
 * Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
 * Copyright (c) 2016 - 2020 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41
42
43
44
45
46
47

48


49
50
51
52
53

54
55

56
57
58


59
60

61
62
63
64
65
66
67
68

69
70
71
72




73
74
75
76



77

78
79
80



81
82
83
84
85

86
87
88

89
90
91
92

93
94
41
42
43
44
45
46
47
48

49
50
51
52
53
54

55


56



57
58
59

60
61
62
63
64
65
66
67

68




69
70
71
72
73



74
75
76
77
78



79
80
81





82

83

84
85
86
87

88
89
90







+
-
+
+




-
+
-
-
+
-
-
-
+
+

-
+







-
+
-
-
-
-
+
+
+
+

-
-
-
+
+
+

+
-
-
-
+
+
+
-
-
-
-
-
+
-

-
+



-
+


}

- (void)derivePassword
{
	OFSHA384Hash *siteHash = [OFSHA384Hash
	    cryptoHashWithAllowsSwappableMemory: true];
	size_t passphraseLength, combinedPassphraseLength;
	OFSecureData *combinedPassphrase;
	char *combinedPassphrase;
	char *combinedPassphraseItems;
	unsigned char *outputItems;

	[siteHash updateWithBuffer: _site.UTF8String
			    length: _site.UTF8StringLength];

	if (_output != NULL) {
	[_output release];
		of_explicit_memset(_output, 0, _length);
		[self freeMemory: _output];
	_output = nil;
	}

	_output = [self allocMemoryWithSize: _length + 1];
	_output = [[OFSecureData alloc] initWithCount: _length + 1
				allowsSwappableMemory: false];

	passphraseLength = combinedPassphraseLength = strlen(_passphrase);
	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)
	combinedPassphrase = [OFSecureData
		@throw [OFOutOfMemoryException
		    exceptionWithRequestedSize: combinedPassphraseLength];
	@try {
		memcpy(combinedPassphrase, _passphrase, passphraseLength);
		    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);

	outputItems = _output.mutableItems;
		of_scrypt(8, 524288, 2, siteHash.digest,
		    [siteHash.class digestSize], combinedPassphrase,
		    combinedPassphraseLength, _output, _length, true);
	of_scrypt(8, 524288, 2, siteHash.digest, [siteHash.class digestSize],
	    combinedPassphraseItems, combinedPassphraseLength, outputItems,
	    _length, true);
	} @finally {
		of_explicit_memset(combinedPassphrase, 0,
		    combinedPassphraseLength);
		free(combinedPassphrase);
	}


	for (size_t i = 0; i < _length; i++)
		_output[i] =
		outputItems[i] =
		    "123456789"
		    "abcdefghijkmnopqrstuvwxyz"
		    "ABCDEFGHJKLMNPQRSTUVWXYZ"
		    "#$%-=?"[_output[i] & 0x3F];
		    "#$%-=?"[outputItems[i] & 0x3F];
}
@end

Modified PasswordGenerator.h from [331c2d1755] to [2fc83e5fa2].

1
2

3
4

5
6
7
8
9
10
11
1

2
3

4
5
6
7
8
9
10
11

-
+

-
+







/*
 * Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
 * Copyright (c) 2016 - 2020 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
23
24
25
26
27
28
29
30


31
32
33
34
22
23
24
25
26
27
28


29
30
31
32
33
34







-
-
+
+





#import <ObjFW/ObjFW.h>

@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