xref: /netbsd-src/sbin/cgdconfig/params.c (revision d16b7486a53dcb8072b60ec6fcb4373a2d0c27b7)
1 /* $NetBSD: params.c,v 1.34 2022/08/12 10:49:35 riastradh Exp $ */
2 
3 /*-
4  * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Roland C. Dowdeswell.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 #ifndef lint
34 __RCSID("$NetBSD: params.c,v 1.34 2022/08/12 10:49:35 riastradh Exp $");
35 #endif
36 
37 #include <sys/types.h>
38 #include <sys/param.h>
39 
40 #include <sys/sha2.h>
41 #include <sys/stat.h>
42 
43 #include <err.h>
44 #include <errno.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <util.h>
49 #include <uuid.h>
50 
51 #ifdef HAVE_ARGON2
52 #include <argon2.h>
53 #include "argon2_utils.h"
54 #endif
55 
56 #include "params.h"
57 #include "pkcs5_pbkdf2.h"
58 #include "utils.h"
59 #include "cgdconfig.h"
60 #include "extern.h"
61 
62 static void	params_init(struct params *);
63 
64 static void	print_kvpair_cstr(FILE *, int, const char *, const char *);
65 static void	print_kvpair_string(FILE *, int, const char *, const string_t *);
66 static void	print_kvpair_int(FILE *, int, const char *, size_t);
67 static void	print_kvpair_b64(FILE *, int, int, const char *, bits_t *);
68 
69 static void	spaces(FILE *, int);
70 
71 /* keygen defaults */
72 #define DEFAULT_SALTLEN		128
73 #define DEFAULT_ITERATION_TIME	2000000		/* 1 second in microseconds */
74 
75 /* crypto defaults functions */
76 static struct crypto_defaults {
77 	char	alg[32];
78 	int	keylen;
79 } crypto_defaults[] = {
80 	{ "adiantum",		256 },
81 	{ "aes-cbc",		128 },
82 	{ "aes-xts",		256 },
83 	{ "3des-cbc",		192 },
84 	{ "blowfish-cbc",	128 }
85 };
86 
87 static int	crypt_defaults_lookup(const char *);
88 
89 struct params *
90 params_new(void)
91 {
92 	struct params	*p;
93 
94 	p = emalloc(sizeof(*p));
95 	params_init(p);
96 	return p;
97 }
98 
99 static void
100 params_init(struct params *p)
101 {
102 
103 	p->algorithm = NULL;
104 	p->ivmeth = NULL;
105 	p->key = NULL;
106 	p->keylen = (size_t)-1;
107 	p->bsize = (size_t)-1;
108 	p->verify_method = VERIFY_UNKNOWN;
109 	p->dep_keygen = NULL;
110 	p->keygen = NULL;
111 }
112 
113 void
114 params_free(struct params *p)
115 {
116 
117 	if (!p)
118 		return;
119 	string_free(p->algorithm);
120 	string_free(p->ivmeth);
121 	keygen_free(p->dep_keygen);
122 	keygen_free(p->keygen);
123 }
124 
125 struct params *
126 params_combine(struct params *p1, struct params *p2)
127 {
128 	struct params *p;
129 
130 	if (p1)
131 		p = p1;
132 	else
133 		p = params_new();
134 
135 	if (!p2)
136 		return p;
137 
138 	if (p2->algorithm)
139 		string_assign(&p->algorithm, p2->algorithm);
140 	if (p2->ivmeth)
141 		string_assign(&p->ivmeth, p2->ivmeth);
142 	if (p2->keylen != (size_t)-1)
143 		p->keylen = p2->keylen;
144 	if (p2->bsize != (size_t)-1)
145 		p->bsize = p2->bsize;
146 	if (p2->verify_method != VERIFY_UNKNOWN)
147 		p->verify_method = p2->verify_method;
148 
149 	p->dep_keygen = keygen_combine(p->dep_keygen, p2->dep_keygen);
150 	keygen_addlist(&p->keygen, p2->keygen);
151 
152 	/*
153 	 * at this point we should have moved all allocated data
154 	 * in p2 into p, so we can free it.
155 	 */
156 	free(p2);
157 	return p;
158 }
159 
160 int
161 params_filldefaults(struct params *p)
162 {
163 	size_t	i;
164 
165 	if (p->verify_method == VERIFY_UNKNOWN)
166 		p->verify_method = VERIFY_NONE;
167 	if (!p->ivmeth)
168 		p->ivmeth = string_fromcharstar("encblkno1");
169 	if (p->keylen == (size_t)-1) {
170 		if (p->algorithm == NULL)
171 			return -1;
172 		i = crypt_defaults_lookup(string_tocharstar(p->algorithm));
173 		if (i != (size_t)-1) {
174 			p->keylen = crypto_defaults[i].keylen;
175 		} else {
176 			warnx("could not determine key length for unknown "
177 			    "algorithm \"%s\"",
178 			    string_tocharstar(p->algorithm));
179 			return -1;
180 		}
181 	}
182 	return 0;
183 }
184 
185 /*
186  * params_verify traverses the parameters and all of the keygen methods
187  * looking for inconsistencies.  It outputs warnings on non-fatal errors
188  * such as unknown encryption methods, but returns failure on fatal
189  * conditions such as a PKCS5_PBKDF2 keygen without a salt.  It is intended
190  * to run before key generation.
191  */
192 
193 int
194 params_verify(const struct params *p)
195 {
196 	static const char *encblkno[] = {
197 	    "encblkno", "encblkno1", "encblkno8"
198 	};
199 	static size_t i;
200 	const char *meth;
201 
202 	if (!p->algorithm) {
203 		warnx("unspecified algorithm");
204 		return 0;
205 	}
206 	/*
207 	 * we only warn for the encryption method so that it is possible
208 	 * to use an older cgdconfig(8) with a new kernel that supports
209 	 * additional crypto algorithms.
210 	 */
211 	if (crypt_defaults_lookup(string_tocharstar(p->algorithm)) == -1)
212 		warnx("unknown algorithm \"%s\"(warning)",
213 		    string_tocharstar(p->algorithm));
214 	/* same rationale with IV methods. */
215 	if (!p->ivmeth) {
216 		warnx("unspecified IV method");
217 		return 0;
218 	}
219 
220 	meth = string_tocharstar(p->ivmeth);
221 	for (i = 0; i < __arraycount(encblkno); i++)
222 		if (strcmp(encblkno[i], meth) == 0)
223 			break;
224 
225 	if (i == __arraycount(encblkno))
226 		warnx("unknown IV method \"%s\" (warning)", meth);
227 
228 	if (p->keylen == (size_t)-1) {
229 		warnx("unspecified key length");
230 		return 0;
231 	}
232 
233 	return keygen_verify(p->keygen);
234 }
235 
236 struct params *
237 params_algorithm(string_t *in)
238 {
239 	struct params *p = params_new();
240 
241 	p->algorithm = in;
242 	return p;
243 }
244 
245 struct params *
246 params_ivmeth(string_t *in)
247 {
248 	struct params *p = params_new();
249 
250 	p->ivmeth = in;
251 	return p;
252 }
253 
254 struct params *
255 params_keylen(size_t in)
256 {
257 	struct params *p = params_new();
258 
259 	p->keylen = in;
260 	return p;
261 }
262 
263 struct params *
264 params_bsize(size_t in)
265 {
266 	struct params *p = params_new();
267 
268 	p->bsize = in;
269 	return p;
270 }
271 
272 struct params *
273 params_verify_method(string_t *in)
274 {
275 	struct params *p = params_new();
276 	const char *vm = string_tocharstar(in);
277 
278 	if (!strcmp("none", vm))
279 		p->verify_method = VERIFY_NONE;
280 	if (!strcmp("disklabel", vm))
281 		p->verify_method = VERIFY_DISKLABEL;
282 	if (!strcmp("ffs", vm))
283 		p->verify_method = VERIFY_FFS;
284 	if (!strcmp("re-enter", vm))
285 		p->verify_method = VERIFY_REENTER;
286 	if (!strcmp("mbr", vm))
287 		p->verify_method = VERIFY_MBR;
288 	if (!strcmp("gpt", vm))
289 		p->verify_method = VERIFY_GPT;
290 
291 	string_free(in);
292 
293 	if (p->verify_method == VERIFY_UNKNOWN)
294 		warnx("params_setverify_method: unrecognized "
295 		    "verify method \"%s\"", vm);
296 	return p;
297 }
298 
299 struct params *
300 params_keygen(struct keygen *in)
301 {
302 	struct params *p = params_new();
303 
304 	p->keygen = in;
305 	return p;
306 }
307 
308 struct params *
309 params_dep_keygen(struct keygen *in)
310 {
311 	struct params *p = params_new();
312 
313 	p->dep_keygen = in;
314 	return p;
315 }
316 
317 struct keygen *
318 keygen_new(void)
319 {
320 	struct keygen *kg;
321 
322 	kg = emalloc(sizeof(*kg));
323 	kg->kg_method = KEYGEN_UNKNOWN;
324 	kg->kg_iterations = (size_t)-1;
325 	kg->kg_memory = (size_t)-1;
326 	kg->kg_parallelism = (size_t)-1;
327 	kg->kg_version = (size_t)-1;
328 	kg->kg_salt = NULL;
329 	kg->kg_key = NULL;
330 	kg->kg_cmd = NULL;
331 	kg->kg_sharedid = NULL;
332 	kg->kg_sharedalg = SHARED_ALG_UNKNOWN;
333 	kg->kg_sharedlen = (size_t)-1;
334 	kg->kg_sharedinfo = NULL;
335 	kg->next = NULL;
336 	return kg;
337 }
338 
339 void
340 keygen_free(struct keygen *kg)
341 {
342 
343 	if (!kg)
344 		return;
345 	bits_free(kg->kg_salt);
346 	bits_free(kg->kg_key);
347 	string_free(kg->kg_cmd);
348 	string_free(kg->kg_sharedid);
349 	bits_free(kg->kg_sharedinfo);
350 	keygen_free(kg->next);
351 	free(kg);
352 }
353 
354 /*
355  * keygen_verify traverses the keygen structures and ensures
356  * that the appropriate information is available.
357  */
358 
359 int
360 keygen_verify(const struct keygen *kg)
361 {
362 
363 	if (!kg)
364 		return 1;
365 	switch (kg->kg_method) {
366 #ifdef HAVE_ARGON2
367 	case KEYGEN_ARGON2ID:
368 		if (kg->kg_iterations == (size_t)-1) {
369 			warnx("keygen argon2id must provide `iterations'");
370 			return 0;
371 		}
372 		if (kg->kg_memory == (size_t)-1) {
373 			warnx("keygen argon2id must provide `memory'");
374 			return 0;
375 		}
376 		if (kg->kg_parallelism == (size_t)-1) {
377 			warnx("keygen argon2id must provide `parallelism'");
378 			return 0;
379 		}
380 		if (kg->kg_version == (size_t)-1) {
381 			warnx("keygen argon2id must provide `version'");
382 			return 0;
383 		}
384 		if (kg->kg_cmd)
385 			warnx("keygen argon2id does not need a `cmd'");
386 		if (kg->kg_key)
387 			warnx("keygen argon2id does not need a `key'");
388 		if (!kg->kg_salt) {
389 			warnx("keygen argon2id must provide a salt");
390 			return 0;
391 		}
392 		break;
393 #endif
394 	case KEYGEN_PKCS5_PBKDF2_OLD:
395 		if (kg->kg_iterations == (size_t)-1) {
396 			warnx("keygen pkcs5_pbkdf2 must provide `iterations'");
397 			return 0;
398 		}
399 		if (kg->kg_key)
400 			warnx("keygen pkcs5_pbkdf2 does not need a `key'");
401 		if (!kg->kg_salt) {
402 			warnx("keygen pkcs5_pbkdf2 must provide a salt");
403 			return 0;
404 		}
405 		if (kg->kg_cmd)
406 			warnx("keygen pkcs5_pbkdf2 does not need a `cmd'");
407 		break;
408 	case KEYGEN_PKCS5_PBKDF2_SHA1:
409 		if (kg->kg_iterations == (size_t)-1) {
410 			warnx("keygen pkcs5_pbkdf2/sha1 must provide `iterations'");
411 			return 0;
412 		}
413 		if (kg->kg_key)
414 			warnx("keygen pkcs5_pbkdf2/sha1 does not need a `key'");
415 		if (!kg->kg_salt) {
416 			warnx("keygen pkcs5_pbkdf2/sha1 must provide a salt");
417 			return 0;
418 		}
419 		if (kg->kg_cmd)
420 			warnx("keygen pkcs5_pbkdf2/sha1 does not need a `cmd'");
421 		break;
422 	case KEYGEN_STOREDKEY:
423 		if (kg->kg_iterations != (size_t)-1)
424 			warnx("keygen storedkey does not need `iterations'");
425 		if (!kg->kg_key) {
426 			warnx("keygen storedkey must provide a key");
427 			return 0;
428 		}
429 		if (kg->kg_salt)
430 			warnx("keygen storedkey does not need `salt'");
431 		if (kg->kg_cmd)
432 			warnx("keygen storedkey does not need `cmd'");
433 		break;
434 	case KEYGEN_RANDOMKEY:
435 	case KEYGEN_URANDOMKEY:
436 		if (kg->kg_iterations != (size_t)-1)
437 			warnx("keygen [u]randomkey does not need `iterations'");
438 		if (kg->kg_key)
439 			warnx("keygen [u]randomkey does not need `key'");
440 		if (kg->kg_salt)
441 			warnx("keygen [u]randomkey does not need `salt'");
442 		if (kg->kg_cmd)
443 			warnx("keygen [u]randomkey does not need `cmd'");
444 		if (kg->kg_sharedid)
445 			warnx("keygen [u]randomkey makes no sense shared");
446 		break;
447 	case KEYGEN_SHELL_CMD:
448 		if (kg->kg_iterations != (size_t)-1)
449 			warnx("keygen shell_cmd does not need `iterations'");
450 		if (kg->kg_key)
451 			warnx("keygen shell_cmd does not need `key'");
452 		if (kg->kg_salt)
453 			warnx("keygen shell_cmd does not need `salt'");
454 		if (!kg->kg_cmd) {
455 			warnx("keygen shell_cmd must provide a `cmd'");
456 			return 0;
457 		}
458 		break;
459 	}
460 	return keygen_verify(kg->next);
461 }
462 
463 struct keygen *
464 keygen_generate(int method)
465 {
466 	struct keygen *kg;
467 
468 	kg = keygen_new();
469 	if (!kg)
470 		return NULL;
471 
472 	kg->kg_method = method;
473 	return kg;
474 }
475 
476 /*
477  * keygen_filldefaults walks the keygen list and fills in
478  * default values.  The defaults may be either calibrated
479  * or randomly generated so this function is designed to be
480  * called when generating a new parameters file, not when
481  * reading a parameters file.
482  */
483 
484 int
485 keygen_filldefaults(struct keygen *kg, size_t keylen)
486 {
487 
488 	if (!kg)
489 		return 0;
490 	switch (kg->kg_method) {
491 	case KEYGEN_RANDOMKEY:
492 	case KEYGEN_URANDOMKEY:
493 	case KEYGEN_SHELL_CMD:
494 		break;
495 #ifdef HAVE_ARGON2
496 	case KEYGEN_ARGON2ID:
497 		kg->kg_version = ARGON2_VERSION_NUMBER;
498 		kg->kg_salt = bits_getrandombits(DEFAULT_SALTLEN, 1);
499 		argon2id_calibrate(BITS2BYTES(keylen), DEFAULT_SALTLEN,
500 		    &kg->kg_iterations, &kg->kg_memory, &kg->kg_parallelism);
501 		break;
502 #endif
503 	case KEYGEN_PKCS5_PBKDF2_OLD:
504 	case KEYGEN_PKCS5_PBKDF2_SHA1:
505 		kg->kg_salt = bits_getrandombits(DEFAULT_SALTLEN, 1);
506 		kg->kg_iterations = pkcs5_pbkdf2_calibrate(BITS2BYTES(keylen),
507 		    DEFAULT_ITERATION_TIME);
508 		if (kg->kg_iterations < 1) {
509 			warnx("could not calibrate pkcs5_pbkdf2");
510 			return -1;
511 		}
512 		break;
513 	case KEYGEN_STOREDKEY:
514 		/* Generate a random stored key */
515 		kg->kg_key = bits_getrandombits(keylen, 1);
516 		if (!kg->kg_key) {
517 			warnx("can't generate random bits for storedkey");
518 			return -1;
519 		}
520 		break;
521 	default:
522 		return -1;
523 	}
524 
525 	return keygen_filldefaults(kg->next, keylen);
526 }
527 
528 /*
529  * Strip the storedkey entries in preparation for inserting a shared
530  * clause with a newly generated info string to derive this key from
531  * KDF.  The result is that the key generated here is independent of
532  * whatever storedkeys were involved in the old one, so there is no
533  * need to keep them around,
534  */
535 void
536 keygen_stripstored(struct keygen **kgp)
537 {
538 	struct keygen *kg, *to_free = NULL;
539 
540 	while ((kg = *kgp) != NULL) {
541 		if (kg->kg_method == KEYGEN_STOREDKEY) {
542 			*kgp = kg->next;
543 			kg->next = to_free;
544 			to_free = kg;
545 		} else {
546 			kgp = &kg->next;
547 		}
548 	}
549 	keygen_free(to_free);
550 }
551 
552 int
553 keygen_makeshared(struct keygen *kg0)
554 {
555 	struct keygen *kg;
556 
557 	for (kg = kg0; kg != NULL; kg = kg->next) {
558 		switch (kg->kg_method) {
559 		case KEYGEN_RANDOMKEY:
560 		case KEYGEN_URANDOMKEY:
561 			warnx("(u)randomkey keygen cannot be shared");
562 			return -1;
563 		case KEYGEN_SHELL_CMD:
564 #ifdef HAVE_ARGON2
565 		case KEYGEN_ARGON2ID:
566 #endif
567 		case KEYGEN_PKCS5_PBKDF2_OLD:
568 		case KEYGEN_PKCS5_PBKDF2_SHA1:
569 			break;
570 		case KEYGEN_STOREDKEY:
571 			warnx("storedkey does not make sense as shared");
572 			return -1;
573 		default:
574 			return -1;
575 		}
576 		if (kg->kg_sharedid != NULL) {
577 			warnx("keygen already shared");
578 			return -1;
579 		}
580 	}
581 	for (kg = kg0; kg != NULL; kg = kg->next) {
582 		struct uuid id;
583 		char *idstr;
584 		uint32_t status;
585 
586 		if (uuidgen(&id, 1) == -1) {
587 			warn("uuidgen");
588 			return -1;
589 		}
590 		uuid_to_string(&id, &idstr, &status);
591 		if (status != uuid_s_ok) {
592 			warnx("uuid_to_string: %"PRIu32, status);
593 			return -1;
594 		}
595 
596 		kg->kg_sharedid = string_fromcharstar(idstr);
597 		kg->kg_sharedalg = SHARED_ALG_HKDF_HMAC_SHA256;
598 		kg->kg_sharedlen = 8*SHA256_DIGEST_LENGTH;
599 		kg->kg_sharedinfo = bits_getrandombits(DEFAULT_SALTLEN, 0);
600 
601 		free(idstr);
602 	}
603 	return 0;
604 }
605 
606 int
607 keygen_tweakshared(struct keygen *kg0)
608 {
609 	struct keygen *kg;
610 
611 	for (kg = kg0; kg != NULL; kg = kg->next) {
612 		switch (kg->kg_method) {
613 		case KEYGEN_RANDOMKEY:
614 		case KEYGEN_URANDOMKEY:
615 			warnx("(u)randomkey keygen cannot be shared");
616 			return -1;
617 		case KEYGEN_SHELL_CMD:
618 #ifdef HAVE_ARGON2
619 		case KEYGEN_ARGON2ID:
620 #endif
621 		case KEYGEN_PKCS5_PBKDF2_OLD:
622 		case KEYGEN_PKCS5_PBKDF2_SHA1:
623 			break;
624 		case KEYGEN_STOREDKEY:
625 			warnx("storedkey does not make sense as shared");
626 			return -1;
627 		default:
628 			return -1;
629 		}
630 		if (kg->kg_sharedid == NULL) {
631 			warnx("keygen not shared");
632 			return -1;
633 		}
634 	}
635 	for (kg = kg0; kg != NULL; kg = kg->next) {
636 		if (kg->kg_method == KEYGEN_STOREDKEY)
637 			continue;
638 		bits_free(kg->kg_sharedinfo);
639 		kg->kg_sharedinfo = bits_getrandombits(DEFAULT_SALTLEN, 0);
640 	}
641 	return 0;
642 }
643 
644 struct keygen *
645 keygen_combine(struct keygen *kg1, struct keygen *kg2)
646 {
647 	if (!kg1 && !kg2)
648 		return NULL;
649 
650 	if (!kg1)
651 		kg1 = keygen_new();
652 
653 	if (!kg2)
654 		return kg1;
655 
656 	if (kg2->kg_method != KEYGEN_UNKNOWN)
657 		kg1->kg_method = kg2->kg_method;
658 
659 	if (kg2->kg_iterations != (size_t)-1 && kg2->kg_iterations > 0)
660 		kg1->kg_iterations = kg2->kg_iterations;
661 
662 	if (kg2->kg_memory != (size_t)-1 && kg2->kg_memory > 0)
663 		kg1->kg_memory = kg2->kg_memory;
664 
665 	if (kg2->kg_parallelism != (size_t)-1 && kg2->kg_parallelism > 0)
666 		kg1->kg_parallelism = kg2->kg_parallelism;
667 
668 	if (kg2->kg_version != (size_t)-1 && kg2->kg_version > 0)
669 		kg1->kg_version = kg2->kg_version;
670 
671 	if (kg2->kg_salt)
672 		bits_assign(&kg1->kg_salt, kg2->kg_salt);
673 
674 	if (kg2->kg_key)
675 		bits_assign(&kg1->kg_key, kg2->kg_key);
676 
677 	if (kg2->kg_cmd)
678 		string_assign(&kg1->kg_cmd, kg2->kg_cmd);
679 
680 	if (kg2->kg_sharedid)
681 		string_assign(&kg1->kg_sharedid, kg2->kg_sharedid);
682 	if (kg2->kg_sharedalg != SHARED_ALG_UNKNOWN) {
683 		kg1->kg_sharedalg = kg2->kg_sharedalg;
684 		kg1->kg_sharedlen = kg2->kg_sharedlen;
685 	}
686 	if (kg2->kg_sharedinfo)
687 		bits_assign(&kg1->kg_sharedinfo, kg2->kg_sharedinfo);
688 
689 	return kg1;
690 }
691 
692 struct keygen *
693 keygen_method(string_t *in)
694 {
695 	struct keygen *kg = keygen_new();
696 	const char *kgm = string_tocharstar(in);
697 
698 #ifdef HAVE_ARGON2
699 	if (!strcmp("argon2id", kgm))
700 		kg->kg_method = KEYGEN_ARGON2ID;
701 #endif
702 	if (!strcmp("pkcs5_pbkdf2", kgm))
703 		kg->kg_method = KEYGEN_PKCS5_PBKDF2_OLD;
704 	if (!strcmp("pkcs5_pbkdf2/sha1", kgm))
705 		kg->kg_method = KEYGEN_PKCS5_PBKDF2_SHA1;
706 	if (!strcmp("randomkey", kgm))
707 		kg->kg_method = KEYGEN_RANDOMKEY;
708 	if (!strcmp("storedkey", kgm))
709 		kg->kg_method = KEYGEN_STOREDKEY;
710 	if (!strcmp("urandomkey", kgm))
711 		kg->kg_method = KEYGEN_URANDOMKEY;
712 	if (!strcmp("shell_cmd", kgm))
713 		kg->kg_method = KEYGEN_SHELL_CMD;
714 
715 	string_free(in);
716 
717 	if (kg->kg_method == KEYGEN_UNKNOWN)
718 		warnx("unrecognized key generation method \"%s\"", kgm);
719 	return kg;
720 }
721 
722 struct keygen *
723 keygen_set_method(struct keygen *kg, string_t *in)
724 {
725 
726 	return keygen_combine(kg, keygen_method(in));
727 }
728 
729 struct keygen *
730 keygen_salt(bits_t *in)
731 {
732 	struct keygen *kg = keygen_new();
733 
734 	kg->kg_salt = in;
735 	return kg;
736 }
737 
738 struct keygen *
739 keygen_iterations(size_t in)
740 {
741 	struct keygen *kg = keygen_new();
742 
743 	kg->kg_iterations = in;
744 	return kg;
745 }
746 
747 struct keygen *
748 keygen_memory(size_t in)
749 {
750 	struct keygen *kg = keygen_new();
751 
752 	kg->kg_memory = in;
753 	return kg;
754 }
755 
756 struct keygen *
757 keygen_parallelism(size_t in)
758 {
759 	struct keygen *kg = keygen_new();
760 
761 	kg->kg_parallelism = in;
762 	return kg;
763 }
764 
765 struct keygen *
766 keygen_version(size_t in)
767 {
768 	struct keygen *kg = keygen_new();
769 
770 	kg->kg_version = in;
771 	return kg;
772 }
773 
774 void
775 keygen_addlist(struct keygen **l, struct keygen *e)
776 {
777 	struct keygen *t;
778 
779 	if (*l) {
780 		t = *l;
781 		for (;t->next; t = t->next)
782 			;
783 		t->next = e;
784 	} else {
785 		*l = e;
786 	}
787 }
788 
789 struct keygen *
790 keygen_key(bits_t *in)
791 {
792 	struct keygen *kg = keygen_new();
793 
794 	kg->kg_key = in;
795 	return kg;
796 }
797 
798 struct keygen *
799 keygen_cmd(string_t *in)
800 {
801 	struct keygen *kg = keygen_new();
802 
803 	kg->kg_cmd = in;
804 	return kg;
805 }
806 
807 struct keygen *
808 keygen_shared(string_t *id, string_t *alg, bits_t *info)
809 {
810 	struct keygen *kg = keygen_new();
811 	const char *algname = string_tocharstar(alg);
812 
813 	if (!strcmp("hkdf-hmac-sha256", algname)) {
814 		kg->kg_sharedalg = SHARED_ALG_HKDF_HMAC_SHA256;
815 		kg->kg_sharedlen = 8*SHA256_DIGEST_LENGTH;
816 	}
817 
818 	if (kg->kg_sharedalg == SHARED_ALG_UNKNOWN) {
819 		warnx("unrecognized shared key derivation algorithm \"%s\"",
820 		    algname);
821 	}
822 
823 	kg->kg_sharedid = id;
824 	kg->kg_sharedinfo = info;
825 	return kg;
826 }
827 
828 struct params *
829 params_fget(FILE *f)
830 {
831 	struct params *p;
832 
833 	p = cgdparsefile(f);
834 
835 	if (!p)
836 		return NULL;
837 
838 	/*
839 	 * We deal with the deprecated keygen structure by prepending it
840 	 * to the list of keygens, so that the rest of the code does not
841 	 * have to deal with this backwards compat issue.  The deprecated
842 	 * ``xor_key'' field may be stored in p->dep_keygen->kg_key.  If
843 	 * it exists, we construct a storedkey keygen struct as well.  Also,
844 	 * default the iteration count to 128 as the old code did.
845 	 */
846 
847 	if (p->dep_keygen) {
848 		if (p->dep_keygen->kg_iterations == (size_t)-1)
849 			p->dep_keygen->kg_iterations = 128;
850 		p->dep_keygen->next = p->keygen;
851 		if (p->dep_keygen->kg_key) {
852 			p->keygen = keygen_generate(KEYGEN_STOREDKEY);
853 			p->keygen->kg_key = p->dep_keygen->kg_key;
854 			p->dep_keygen->kg_key = NULL;
855 			p->keygen->next = p->dep_keygen;
856 		} else {
857 			p->keygen = p->dep_keygen;
858 		}
859 		p->dep_keygen = NULL;
860 	}
861 	return p;
862 }
863 
864 struct params *
865 params_cget(const char *fn)
866 {
867 	struct params	*p;
868 	FILE		*f;
869 	char		filename[MAXPATHLEN];
870 
871 	if ((f = fopen(fn, "r")) == NULL && fn[0] != '/') {
872 		snprintf(filename, sizeof(filename), "%s/%s",
873 		    CGDCONFIG_DIR, fn);
874 		fn = filename;
875 		f = fopen(fn, "r");
876 	}
877 
878 	if (f == NULL) {
879 		warn("failed to open params file \"%s\"", fn);
880 		return NULL;
881 	}
882 	p = params_fget(f);
883 	(void)fclose(f);
884 	return p;
885 }
886 
887 #define WRAP_COL	50
888 #define TAB_COL		8
889 
890 static void
891 spaces(FILE *f, int len)
892 {
893 
894 	while (len-- > 0)
895 		(void)fputc(' ', f);
896 }
897 
898 static void
899 print_kvpair_cstr(FILE *f, int ts, const char *key, const char *val)
900 {
901 
902 	spaces(f, ts);
903 	(void)fprintf(f, "%s %s;\n", key, val);
904 }
905 
906 static void
907 print_kvpair_string(FILE *f, int ts, const char *key, const string_t *val)
908 {
909 
910 	print_kvpair_cstr(f, ts, key, string_tocharstar(val));
911 }
912 
913 static void
914 print_kvpair_int(FILE *f, int ts, const char *key, size_t val)
915 {
916 	char	*tmp;
917 
918 	if (!key || val == (size_t)-1)
919 		return;
920 
921 	if (asprintf(&tmp, "%zu", val) == -1)
922 		err(1, NULL);
923 	print_kvpair_cstr(f, ts, key, tmp);
924 	free(tmp);
925 }
926 
927 /*
928  * prints out a base64 encoded k-v pair to f.  It encodes the length
929  * of the bitstream as a 32bit unsigned integer in network byte order
930  * up front.
931  */
932 
933 static void
934 print_kvpair_b64(FILE *f, int curpos, int ts, const char *key, bits_t *val)
935 {
936 	string_t	*str;
937 	int		 i;
938 	int		 len;
939 	int		 pos;
940 	const char	*out;
941 
942 	if (!key || !val)
943 		return;
944 
945 	str = bits_encode(val);
946 	out = string_tocharstar(str);
947 	len = strlen(out);
948 
949 	spaces(f, ts);
950 	(void)fprintf(f, "%s ", key);
951 	curpos += ts + strlen(key) + 1;
952 	ts = curpos;
953 
954 	for (i=0, pos=curpos; i < len; i++, pos++) {
955 		if (pos > WRAP_COL) {
956 			(void)fprintf(f, " \\\n");
957 			spaces(f, ts);
958 			pos = ts;
959 		}
960 		(void)fputc(out[i], f);
961 	}
962 	(void)fprintf(f, ";\n");
963 	string_free(str);
964 }
965 
966 static void
967 print_shared(FILE *f, int ts, struct keygen *kg)
968 {
969 	static const char *const sharedalgs[] = {
970 		[SHARED_ALG_UNKNOWN] = "unknown",
971 		[SHARED_ALG_HKDF_HMAC_SHA256] = "hkdf-hmac-sha256",
972 	};
973 
974 	if (kg->kg_sharedid == NULL ||
975 	    kg->kg_sharedalg < 0 ||
976 	    (size_t)kg->kg_sharedalg >= __arraycount(sharedalgs))
977 		return;
978 	fprintf(f, "%*sshared \"%s\" \\\n", ts, "",
979 	    string_tocharstar(kg->kg_sharedid));
980 	ts += 4;
981 	fprintf(f, "%*salgorithm %s \\\n", ts, "",
982 	    sharedalgs[kg->kg_sharedalg]);
983 	print_kvpair_b64(f, 0, ts, "subkey", kg->kg_sharedinfo);
984 }
985 
986 int
987 keygen_fput(struct keygen *kg, int ts, FILE *f)
988 {
989 	int	curpos = 0;
990 
991 	if (!kg)
992 		return 0;
993 	(void)fprintf(f, "keygen ");
994 	curpos += strlen("keygen ");
995 	switch (kg->kg_method) {
996 	case KEYGEN_STOREDKEY:
997 		(void)fprintf(f, "storedkey ");
998 		curpos += strlen("storedkey ");
999 		print_kvpair_b64(f, curpos, 0, "key", kg->kg_key);
1000 		break;
1001 	case KEYGEN_RANDOMKEY:
1002 		(void)fprintf(f, "randomkey;\n");
1003 		break;
1004 	case KEYGEN_URANDOMKEY:
1005 		(void)fprintf(f, "urandomkey;\n");
1006 		break;
1007 #ifdef HAVE_ARGON2
1008 	case KEYGEN_ARGON2ID:
1009 		(void)fprintf(f, "argon2id {\n");
1010 		print_kvpair_int(f, ts, "iterations", kg->kg_iterations);
1011 		print_kvpair_int(f, ts, "memory", kg->kg_memory);
1012 		print_kvpair_int(f, ts, "parallelism", kg->kg_parallelism);
1013 		print_kvpair_int(f, ts, "version", kg->kg_version);
1014 		print_kvpair_b64(f, 0, ts, "salt", kg->kg_salt);
1015 		print_shared(f, ts, kg);
1016 		(void)fprintf(f, "};\n");
1017 		break;
1018 #endif
1019 	case KEYGEN_PKCS5_PBKDF2_OLD:
1020 		(void)fprintf(f, "pkcs5_pbkdf2 {\n");
1021 		print_kvpair_int(f, ts, "iterations", kg->kg_iterations);
1022 		print_kvpair_b64(f, 0, ts, "salt", kg->kg_salt);
1023 		print_shared(f, ts, kg);
1024 		(void)fprintf(f, "};\n");
1025 		break;
1026 	case KEYGEN_PKCS5_PBKDF2_SHA1:
1027 		(void)fprintf(f, "pkcs5_pbkdf2/sha1 {\n");
1028 		print_kvpair_int(f, ts, "iterations", kg->kg_iterations);
1029 		print_kvpair_b64(f, 0, ts, "salt", kg->kg_salt);
1030 		print_shared(f, ts, kg);
1031 		(void)fprintf(f, "};\n");
1032 		break;
1033 	default:
1034 		warnx("keygen_fput: %d not a valid method", kg->kg_method);
1035 		break;
1036 	}
1037 	return keygen_fput(kg->next, ts, f);
1038 }
1039 
1040 int
1041 params_fput(struct params *p, FILE *f)
1042 {
1043 	int	ts = 0;		/* tabstop of 0 spaces */
1044 
1045 	print_kvpair_string(f, ts, "algorithm", p->algorithm);
1046 	print_kvpair_string(f, ts, "iv-method", p->ivmeth);
1047 	print_kvpair_int(f, ts, "keylength", p->keylen);
1048 	print_kvpair_int(f, ts, "blocksize", p->bsize);
1049 	switch (p->verify_method) {
1050 	case VERIFY_NONE:
1051 		print_kvpair_cstr(f, ts, "verify_method", "none");
1052 		break;
1053 	case VERIFY_DISKLABEL:
1054 		print_kvpair_cstr(f, ts, "verify_method", "disklabel");
1055 		break;
1056 	case VERIFY_FFS:
1057 		print_kvpair_cstr(f, ts, "verify_method", "ffs");
1058 		break;
1059 	case VERIFY_REENTER:
1060 		print_kvpair_cstr(f, ts, "verify_method", "re-enter");
1061 		break;
1062 	case VERIFY_MBR:
1063 		print_kvpair_cstr(f, ts, "verify_method", "mbr");
1064 		break;
1065 	case VERIFY_GPT:
1066 		print_kvpair_cstr(f, ts, "verify_method", "gpt");
1067 		break;
1068 	default:
1069 		warnx("unsupported verify_method (%d)", p->verify_method);
1070 		return -1;
1071 	}
1072 	return keygen_fput(p->keygen, TAB_COL, f);
1073 }
1074 
1075 int
1076 params_cput(struct params *p, const char *fn)
1077 {
1078 	FILE	*f;
1079 
1080 	if (fn && *fn) {
1081 		if ((f = fopen(fn, "w")) == NULL) {
1082 			warn("could not open outfile \"%s\"", fn);
1083 			return -1;
1084 		}
1085 	} else {
1086 		f = stdout;
1087 	}
1088 	return params_fput(p, f);
1089 }
1090 
1091 static int
1092 crypt_defaults_lookup(const char *alg)
1093 {
1094 	unsigned	i;
1095 
1096 	for (i=0; i < (sizeof(crypto_defaults) / sizeof(crypto_defaults[0])); i++)
1097 		if (!strcmp(alg, crypto_defaults[i].alg))
1098 			return i;
1099 
1100 	return -1;
1101 }
1102