1 /*
2  * Copyright 2014 Andrew Ayer
3  *
4  * This file is part of git-crypt.
5  *
6  * git-crypt is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * git-crypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with git-crypt.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  * Additional permission under GNU GPL version 3 section 7:
20  *
21  * If you modify the Program, or any covered work, by linking or
22  * combining it with the OpenSSL project's OpenSSL library (or a
23  * modified version of that library), containing parts covered by the
24  * terms of the OpenSSL or SSLeay licenses, the licensors of the Program
25  * grant you additional permission to convey the resulting work.
26  * Corresponding Source for a non-source form of such a combination
27  * shall include the source code for the parts of OpenSSL used as well
28  * as that of the covered work.
29  */
30 
31 #include "key.hpp"
32 #include "util.hpp"
33 #include "crypto.hpp"
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <stdint.h>
37 #include <fstream>
38 #include <istream>
39 #include <ostream>
40 #include <sstream>
41 #include <cstring>
42 #include <stdexcept>
43 #include <vector>
44 
Entry()45 Key_file::Entry::Entry ()
46 {
47 	version = 0;
48 	explicit_memset(aes_key, 0, AES_KEY_LEN);
49 	explicit_memset(hmac_key, 0, HMAC_KEY_LEN);
50 }
51 
load(std::istream & in)52 void		Key_file::Entry::load (std::istream& in)
53 {
54 	while (true) {
55 		uint32_t	field_id;
56 		if (!read_be32(in, field_id)) {
57 			throw Malformed();
58 		}
59 		if (field_id == KEY_FIELD_END) {
60 			break;
61 		}
62 		uint32_t	field_len;
63 		if (!read_be32(in, field_len)) {
64 			throw Malformed();
65 		}
66 
67 		if (field_id == KEY_FIELD_VERSION) {
68 			if (field_len != 4) {
69 				throw Malformed();
70 			}
71 			if (!read_be32(in, version)) {
72 				throw Malformed();
73 			}
74 		} else if (field_id == KEY_FIELD_AES_KEY) {
75 			if (field_len != AES_KEY_LEN) {
76 				throw Malformed();
77 			}
78 			in.read(reinterpret_cast<char*>(aes_key), AES_KEY_LEN);
79 			if (in.gcount() != AES_KEY_LEN) {
80 				throw Malformed();
81 			}
82 		} else if (field_id == KEY_FIELD_HMAC_KEY) {
83 			if (field_len != HMAC_KEY_LEN) {
84 				throw Malformed();
85 			}
86 			in.read(reinterpret_cast<char*>(hmac_key), HMAC_KEY_LEN);
87 			if (in.gcount() != HMAC_KEY_LEN) {
88 				throw Malformed();
89 			}
90 		} else if (field_id & 1) { // unknown critical field
91 			throw Incompatible();
92 		} else {
93 			// unknown non-critical field - safe to ignore
94 			if (field_len > MAX_FIELD_LEN) {
95 				throw Malformed();
96 			}
97 			in.ignore(field_len);
98 			if (in.gcount() != static_cast<std::streamsize>(field_len)) {
99 				throw Malformed();
100 			}
101 		}
102 	}
103 }
104 
load_legacy(uint32_t arg_version,std::istream & in)105 void		Key_file::Entry::load_legacy (uint32_t arg_version, std::istream& in)
106 {
107 	version = arg_version;
108 
109 	// First comes the AES key
110 	in.read(reinterpret_cast<char*>(aes_key), AES_KEY_LEN);
111 	if (in.gcount() != AES_KEY_LEN) {
112 		throw Malformed();
113 	}
114 
115 	// Then the HMAC key
116 	in.read(reinterpret_cast<char*>(hmac_key), HMAC_KEY_LEN);
117 	if (in.gcount() != HMAC_KEY_LEN) {
118 		throw Malformed();
119 	}
120 
121 	if (in.peek() != -1) {
122 		// Trailing data is a good indication that we are not actually reading a
123 		// legacy key file.  (This is important to check since legacy key files
124 		// did not have any sort of file header.)
125 		throw Malformed();
126 	}
127 }
128 
store(std::ostream & out) const129 void		Key_file::Entry::store (std::ostream& out) const
130 {
131 	// Version
132 	write_be32(out, KEY_FIELD_VERSION);
133 	write_be32(out, 4);
134 	write_be32(out, version);
135 
136 	// AES key
137 	write_be32(out, KEY_FIELD_AES_KEY);
138 	write_be32(out, AES_KEY_LEN);
139 	out.write(reinterpret_cast<const char*>(aes_key), AES_KEY_LEN);
140 
141 	// HMAC key
142 	write_be32(out, KEY_FIELD_HMAC_KEY);
143 	write_be32(out, HMAC_KEY_LEN);
144 	out.write(reinterpret_cast<const char*>(hmac_key), HMAC_KEY_LEN);
145 
146 	// End
147 	write_be32(out, KEY_FIELD_END);
148 }
149 
generate(uint32_t arg_version)150 void		Key_file::Entry::generate (uint32_t arg_version)
151 {
152 	version = arg_version;
153 	random_bytes(aes_key, AES_KEY_LEN);
154 	random_bytes(hmac_key, HMAC_KEY_LEN);
155 }
156 
get_latest() const157 const Key_file::Entry*	Key_file::get_latest () const
158 {
159 	return is_filled() ? get(latest()) : 0;
160 }
161 
get(uint32_t version) const162 const Key_file::Entry*	Key_file::get (uint32_t version) const
163 {
164 	Map::const_iterator	it(entries.find(version));
165 	return it != entries.end() ? &it->second : 0;
166 }
167 
add(const Entry & entry)168 void		Key_file::add (const Entry& entry)
169 {
170 	entries[entry.version] = entry;
171 }
172 
173 
load_legacy(std::istream & in)174 void		Key_file::load_legacy (std::istream& in)
175 {
176 	entries[0].load_legacy(0, in);
177 }
178 
load(std::istream & in)179 void		Key_file::load (std::istream& in)
180 {
181 	unsigned char	preamble[16];
182 	in.read(reinterpret_cast<char*>(preamble), 16);
183 	if (in.gcount() != 16) {
184 		throw Malformed();
185 	}
186 	if (std::memcmp(preamble, "\0GITCRYPTKEY", 12) != 0) {
187 		throw Malformed();
188 	}
189 	if (load_be32(preamble + 12) != FORMAT_VERSION) {
190 		throw Incompatible();
191 	}
192 	load_header(in);
193 	while (in.peek() != -1) {
194 		Entry		entry;
195 		entry.load(in);
196 		add(entry);
197 	}
198 }
199 
load_header(std::istream & in)200 void		Key_file::load_header (std::istream& in)
201 {
202 	while (true) {
203 		uint32_t	field_id;
204 		if (!read_be32(in, field_id)) {
205 			throw Malformed();
206 		}
207 		if (field_id == HEADER_FIELD_END) {
208 			break;
209 		}
210 		uint32_t	field_len;
211 		if (!read_be32(in, field_len)) {
212 			throw Malformed();
213 		}
214 
215 		if (field_id == HEADER_FIELD_KEY_NAME) {
216 			if (field_len > KEY_NAME_MAX_LEN) {
217 				throw Malformed();
218 			}
219 			if (field_len == 0) {
220 				// special case field_len==0 to avoid possible undefined behavior
221 				// edge cases with an empty std::vector (particularly, &bytes[0]).
222 				key_name.clear();
223 			} else {
224 				std::vector<char>	bytes(field_len);
225 				in.read(&bytes[0], field_len);
226 				if (in.gcount() != static_cast<std::streamsize>(field_len)) {
227 					throw Malformed();
228 				}
229 				key_name.assign(&bytes[0], field_len);
230 			}
231 			if (!validate_key_name(key_name.c_str())) {
232 				key_name.clear();
233 				throw Malformed();
234 			}
235 		} else if (field_id & 1) { // unknown critical field
236 			throw Incompatible();
237 		} else {
238 			// unknown non-critical field - safe to ignore
239 			if (field_len > MAX_FIELD_LEN) {
240 				throw Malformed();
241 			}
242 			in.ignore(field_len);
243 			if (in.gcount() != static_cast<std::streamsize>(field_len)) {
244 				throw Malformed();
245 			}
246 		}
247 	}
248 }
249 
store(std::ostream & out) const250 void		Key_file::store (std::ostream& out) const
251 {
252 	out.write("\0GITCRYPTKEY", 12);
253 	write_be32(out, FORMAT_VERSION);
254 	if (!key_name.empty()) {
255 		write_be32(out, HEADER_FIELD_KEY_NAME);
256 		write_be32(out, key_name.size());
257 		out.write(key_name.data(), key_name.size());
258 	}
259 	write_be32(out, HEADER_FIELD_END);
260 	for (Map::const_iterator it(entries.begin()); it != entries.end(); ++it) {
261 		it->second.store(out);
262 	}
263 }
264 
load_from_file(const char * key_file_name)265 bool		Key_file::load_from_file (const char* key_file_name)
266 {
267 	std::ifstream	key_file_in(key_file_name, std::fstream::binary);
268 	if (!key_file_in) {
269 		return false;
270 	}
271 	load(key_file_in);
272 	return true;
273 }
274 
store_to_file(const char * key_file_name) const275 bool		Key_file::store_to_file (const char* key_file_name) const
276 {
277 	create_protected_file(key_file_name);
278 	std::ofstream	key_file_out(key_file_name, std::fstream::binary);
279 	if (!key_file_out) {
280 		return false;
281 	}
282 	store(key_file_out);
283 	key_file_out.close();
284 	if (!key_file_out) {
285 		return false;
286 	}
287 	return true;
288 }
289 
store_to_string() const290 std::string	Key_file::store_to_string () const
291 {
292 	std::ostringstream	ss;
293 	store(ss);
294 	return ss.str();
295 }
296 
generate()297 void		Key_file::generate ()
298 {
299 	uint32_t	version(is_empty() ? 0 : latest() + 1);
300 	entries[version].generate(version);
301 }
302 
latest() const303 uint32_t	Key_file::latest () const
304 {
305 	if (is_empty()) {
306 		throw std::invalid_argument("Key_file::latest");
307 	}
308 	return entries.begin()->first;
309 }
310 
validate_key_name(const char * key_name,std::string * reason)311 bool validate_key_name (const char* key_name, std::string* reason)
312 {
313 	if (!*key_name) {
314 		if (reason) { *reason = "Key name may not be empty"; }
315 		return false;
316 	}
317 
318 	if (std::strcmp(key_name, "default") == 0) {
319 		if (reason) { *reason = "`default' is not a legal key name"; }
320 		return false;
321 	}
322 	// Need to be restrictive with key names because they're used as part of a Git filter name
323 	size_t		len = 0;
324 	while (char c = *key_name++) {
325 		if (!std::isalnum(c) && c != '-' && c != '_') {
326 			if (reason) { *reason = "Key names may contain only A-Z, a-z, 0-9, '-', and '_'"; }
327 			return false;
328 		}
329 		if (++len > KEY_NAME_MAX_LEN) {
330 			if (reason) { *reason = "Key name is too long"; }
331 			return false;
332 		}
333 	}
334 	return true;
335 }
336 
337