1 /* $NetBSD: params.c,v 1.35 2024/05/12 18:02:16 christos 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.35 2024/05/12 18:02:16 christos 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 *
params_new(void)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
params_init(struct params * p)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
params_free(struct params * p)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 *
params_combine(struct params * p1,struct params * p2)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
params_filldefaults(struct params * p)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
params_verify(const struct params * p)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 *
params_algorithm(string_t * in)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 *
params_ivmeth(string_t * in)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 *
params_keylen(size_t in)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 *
params_bsize(size_t in)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 *
params_verify_method(string_t * in)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 #ifdef HAVE_ZFS
291           if (!strcmp("zfs", vm))
292                     p->verify_method = VERIFY_ZFS;
293 #endif
294 
295           string_free(in);
296 
297           if (p->verify_method == VERIFY_UNKNOWN)
298                     warnx("params_setverify_method: unrecognized "
299                         "verify method \"%s\"", vm);
300           return p;
301 }
302 
303 struct params *
params_keygen(struct keygen * in)304 params_keygen(struct keygen *in)
305 {
306           struct params *p = params_new();
307 
308           p->keygen = in;
309           return p;
310 }
311 
312 struct params *
params_dep_keygen(struct keygen * in)313 params_dep_keygen(struct keygen *in)
314 {
315           struct params *p = params_new();
316 
317           p->dep_keygen = in;
318           return p;
319 }
320 
321 struct keygen *
keygen_new(void)322 keygen_new(void)
323 {
324           struct keygen *kg;
325 
326           kg = emalloc(sizeof(*kg));
327           kg->kg_method = KEYGEN_UNKNOWN;
328           kg->kg_iterations = (size_t)-1;
329           kg->kg_memory = (size_t)-1;
330           kg->kg_parallelism = (size_t)-1;
331           kg->kg_version = (size_t)-1;
332           kg->kg_salt = NULL;
333           kg->kg_key = NULL;
334           kg->kg_cmd = NULL;
335           kg->kg_sharedid = NULL;
336           kg->kg_sharedalg = SHARED_ALG_UNKNOWN;
337           kg->kg_sharedlen = (size_t)-1;
338           kg->kg_sharedinfo = NULL;
339           kg->next = NULL;
340           return kg;
341 }
342 
343 void
keygen_free(struct keygen * kg)344 keygen_free(struct keygen *kg)
345 {
346 
347           if (!kg)
348                     return;
349           bits_free(kg->kg_salt);
350           bits_free(kg->kg_key);
351           string_free(kg->kg_cmd);
352           string_free(kg->kg_sharedid);
353           bits_free(kg->kg_sharedinfo);
354           keygen_free(kg->next);
355           free(kg);
356 }
357 
358 /*
359  * keygen_verify traverses the keygen structures and ensures
360  * that the appropriate information is available.
361  */
362 
363 int
keygen_verify(const struct keygen * kg)364 keygen_verify(const struct keygen *kg)
365 {
366 
367           if (!kg)
368                     return 1;
369           switch (kg->kg_method) {
370 #ifdef HAVE_ARGON2
371           case KEYGEN_ARGON2ID:
372                     if (kg->kg_iterations == (size_t)-1) {
373                               warnx("keygen argon2id must provide `iterations'");
374                               return 0;
375                     }
376                     if (kg->kg_memory == (size_t)-1) {
377                               warnx("keygen argon2id must provide `memory'");
378                               return 0;
379                     }
380                     if (kg->kg_parallelism == (size_t)-1) {
381                               warnx("keygen argon2id must provide `parallelism'");
382                               return 0;
383                     }
384                     if (kg->kg_version == (size_t)-1) {
385                               warnx("keygen argon2id must provide `version'");
386                               return 0;
387                     }
388                     if (kg->kg_cmd)
389                               warnx("keygen argon2id does not need a `cmd'");
390                     if (kg->kg_key)
391                               warnx("keygen argon2id does not need a `key'");
392                     if (!kg->kg_salt) {
393                               warnx("keygen argon2id must provide a salt");
394                               return 0;
395                     }
396                     break;
397 #endif
398           case KEYGEN_PKCS5_PBKDF2_OLD:
399                     if (kg->kg_iterations == (size_t)-1) {
400                               warnx("keygen pkcs5_pbkdf2 must provide `iterations'");
401                               return 0;
402                     }
403                     if (kg->kg_key)
404                               warnx("keygen pkcs5_pbkdf2 does not need a `key'");
405                     if (!kg->kg_salt) {
406                               warnx("keygen pkcs5_pbkdf2 must provide a salt");
407                               return 0;
408                     }
409                     if (kg->kg_cmd)
410                               warnx("keygen pkcs5_pbkdf2 does not need a `cmd'");
411                     break;
412           case KEYGEN_PKCS5_PBKDF2_SHA1:
413                     if (kg->kg_iterations == (size_t)-1) {
414                               warnx("keygen pkcs5_pbkdf2/sha1 must provide `iterations'");
415                               return 0;
416                     }
417                     if (kg->kg_key)
418                               warnx("keygen pkcs5_pbkdf2/sha1 does not need a `key'");
419                     if (!kg->kg_salt) {
420                               warnx("keygen pkcs5_pbkdf2/sha1 must provide a salt");
421                               return 0;
422                     }
423                     if (kg->kg_cmd)
424                               warnx("keygen pkcs5_pbkdf2/sha1 does not need a `cmd'");
425                     break;
426           case KEYGEN_STOREDKEY:
427                     if (kg->kg_iterations != (size_t)-1)
428                               warnx("keygen storedkey does not need `iterations'");
429                     if (!kg->kg_key) {
430                               warnx("keygen storedkey must provide a key");
431                               return 0;
432                     }
433                     if (kg->kg_salt)
434                               warnx("keygen storedkey does not need `salt'");
435                     if (kg->kg_cmd)
436                               warnx("keygen storedkey does not need `cmd'");
437                     break;
438           case KEYGEN_RANDOMKEY:
439           case KEYGEN_URANDOMKEY:
440                     if (kg->kg_iterations != (size_t)-1)
441                               warnx("keygen [u]randomkey does not need `iterations'");
442                     if (kg->kg_key)
443                               warnx("keygen [u]randomkey does not need `key'");
444                     if (kg->kg_salt)
445                               warnx("keygen [u]randomkey does not need `salt'");
446                     if (kg->kg_cmd)
447                               warnx("keygen [u]randomkey does not need `cmd'");
448                     if (kg->kg_sharedid)
449                               warnx("keygen [u]randomkey makes no sense shared");
450                     break;
451           case KEYGEN_SHELL_CMD:
452                     if (kg->kg_iterations != (size_t)-1)
453                               warnx("keygen shell_cmd does not need `iterations'");
454                     if (kg->kg_key)
455                               warnx("keygen shell_cmd does not need `key'");
456                     if (kg->kg_salt)
457                               warnx("keygen shell_cmd does not need `salt'");
458                     if (!kg->kg_cmd) {
459                               warnx("keygen shell_cmd must provide a `cmd'");
460                               return 0;
461                     }
462                     break;
463           }
464           return keygen_verify(kg->next);
465 }
466 
467 struct keygen *
keygen_generate(int method)468 keygen_generate(int method)
469 {
470           struct keygen *kg;
471 
472           kg = keygen_new();
473           if (!kg)
474                     return NULL;
475 
476           kg->kg_method = method;
477           return kg;
478 }
479 
480 /*
481  * keygen_filldefaults walks the keygen list and fills in
482  * default values.  The defaults may be either calibrated
483  * or randomly generated so this function is designed to be
484  * called when generating a new parameters file, not when
485  * reading a parameters file.
486  */
487 
488 int
keygen_filldefaults(struct keygen * kg,size_t keylen)489 keygen_filldefaults(struct keygen *kg, size_t keylen)
490 {
491 
492           if (!kg)
493                     return 0;
494           switch (kg->kg_method) {
495           case KEYGEN_RANDOMKEY:
496           case KEYGEN_URANDOMKEY:
497           case KEYGEN_SHELL_CMD:
498                     break;
499 #ifdef HAVE_ARGON2
500           case KEYGEN_ARGON2ID:
501                     kg->kg_version = ARGON2_VERSION_NUMBER;
502                     kg->kg_salt = bits_getrandombits(DEFAULT_SALTLEN, 1);
503                     argon2id_calibrate(BITS2BYTES(keylen), DEFAULT_SALTLEN,
504                         &kg->kg_iterations, &kg->kg_memory, &kg->kg_parallelism);
505                     break;
506 #endif
507           case KEYGEN_PKCS5_PBKDF2_OLD:
508           case KEYGEN_PKCS5_PBKDF2_SHA1:
509                     kg->kg_salt = bits_getrandombits(DEFAULT_SALTLEN, 1);
510                     kg->kg_iterations = pkcs5_pbkdf2_calibrate(BITS2BYTES(keylen),
511                         DEFAULT_ITERATION_TIME);
512                     if (kg->kg_iterations < 1) {
513                               warnx("could not calibrate pkcs5_pbkdf2");
514                               return -1;
515                     }
516                     break;
517           case KEYGEN_STOREDKEY:
518                     /* Generate a random stored key */
519                     kg->kg_key = bits_getrandombits(keylen, 1);
520                     if (!kg->kg_key) {
521                               warnx("can't generate random bits for storedkey");
522                               return -1;
523                     }
524                     break;
525           default:
526                     return -1;
527           }
528 
529           return keygen_filldefaults(kg->next, keylen);
530 }
531 
532 /*
533  * Strip the storedkey entries in preparation for inserting a shared
534  * clause with a newly generated info string to derive this key from
535  * KDF.  The result is that the key generated here is independent of
536  * whatever storedkeys were involved in the old one, so there is no
537  * need to keep them around,
538  */
539 void
keygen_stripstored(struct keygen ** kgp)540 keygen_stripstored(struct keygen **kgp)
541 {
542           struct keygen *kg, *to_free = NULL;
543 
544           while ((kg = *kgp) != NULL) {
545                     if (kg->kg_method == KEYGEN_STOREDKEY) {
546                               *kgp = kg->next;
547                               kg->next = to_free;
548                               to_free = kg;
549                     } else {
550                               kgp = &kg->next;
551                     }
552           }
553           keygen_free(to_free);
554 }
555 
556 int
keygen_makeshared(struct keygen * kg0)557 keygen_makeshared(struct keygen *kg0)
558 {
559           struct keygen *kg;
560 
561           for (kg = kg0; kg != NULL; kg = kg->next) {
562                     switch (kg->kg_method) {
563                     case KEYGEN_RANDOMKEY:
564                     case KEYGEN_URANDOMKEY:
565                               warnx("(u)randomkey keygen cannot be shared");
566                               return -1;
567                     case KEYGEN_SHELL_CMD:
568 #ifdef HAVE_ARGON2
569                     case KEYGEN_ARGON2ID:
570 #endif
571                     case KEYGEN_PKCS5_PBKDF2_OLD:
572                     case KEYGEN_PKCS5_PBKDF2_SHA1:
573                               break;
574                     case KEYGEN_STOREDKEY:
575                               warnx("storedkey does not make sense as shared");
576                               return -1;
577                     default:
578                               return -1;
579                     }
580                     if (kg->kg_sharedid != NULL) {
581                               warnx("keygen already shared");
582                               return -1;
583                     }
584           }
585           for (kg = kg0; kg != NULL; kg = kg->next) {
586                     struct uuid id;
587                     char *idstr;
588                     uint32_t status;
589 
590                     if (uuidgen(&id, 1) == -1) {
591                               warn("uuidgen");
592                               return -1;
593                     }
594                     uuid_to_string(&id, &idstr, &status);
595                     if (status != uuid_s_ok) {
596                               warnx("uuid_to_string: %"PRIu32, status);
597                               return -1;
598                     }
599 
600                     kg->kg_sharedid = string_fromcharstar(idstr);
601                     kg->kg_sharedalg = SHARED_ALG_HKDF_HMAC_SHA256;
602                     kg->kg_sharedlen = 8*SHA256_DIGEST_LENGTH;
603                     kg->kg_sharedinfo = bits_getrandombits(DEFAULT_SALTLEN, 0);
604 
605                     free(idstr);
606           }
607           return 0;
608 }
609 
610 int
keygen_tweakshared(struct keygen * kg0)611 keygen_tweakshared(struct keygen *kg0)
612 {
613           struct keygen *kg;
614 
615           for (kg = kg0; kg != NULL; kg = kg->next) {
616                     switch (kg->kg_method) {
617                     case KEYGEN_RANDOMKEY:
618                     case KEYGEN_URANDOMKEY:
619                               warnx("(u)randomkey keygen cannot be shared");
620                               return -1;
621                     case KEYGEN_SHELL_CMD:
622 #ifdef HAVE_ARGON2
623                     case KEYGEN_ARGON2ID:
624 #endif
625                     case KEYGEN_PKCS5_PBKDF2_OLD:
626                     case KEYGEN_PKCS5_PBKDF2_SHA1:
627                               break;
628                     case KEYGEN_STOREDKEY:
629                               warnx("storedkey does not make sense as shared");
630                               return -1;
631                     default:
632                               return -1;
633                     }
634                     if (kg->kg_sharedid == NULL) {
635                               warnx("keygen not shared");
636                               return -1;
637                     }
638           }
639           for (kg = kg0; kg != NULL; kg = kg->next) {
640                     if (kg->kg_method == KEYGEN_STOREDKEY)
641                               continue;
642                     bits_free(kg->kg_sharedinfo);
643                     kg->kg_sharedinfo = bits_getrandombits(DEFAULT_SALTLEN, 0);
644           }
645           return 0;
646 }
647 
648 struct keygen *
keygen_combine(struct keygen * kg1,struct keygen * kg2)649 keygen_combine(struct keygen *kg1, struct keygen *kg2)
650 {
651           if (!kg1 && !kg2)
652                     return NULL;
653 
654           if (!kg1)
655                     kg1 = keygen_new();
656 
657           if (!kg2)
658                     return kg1;
659 
660           if (kg2->kg_method != KEYGEN_UNKNOWN)
661                     kg1->kg_method = kg2->kg_method;
662 
663           if (kg2->kg_iterations != (size_t)-1 && kg2->kg_iterations > 0)
664                     kg1->kg_iterations = kg2->kg_iterations;
665 
666           if (kg2->kg_memory != (size_t)-1 && kg2->kg_memory > 0)
667                     kg1->kg_memory = kg2->kg_memory;
668 
669           if (kg2->kg_parallelism != (size_t)-1 && kg2->kg_parallelism > 0)
670                     kg1->kg_parallelism = kg2->kg_parallelism;
671 
672           if (kg2->kg_version != (size_t)-1 && kg2->kg_version > 0)
673                     kg1->kg_version = kg2->kg_version;
674 
675           if (kg2->kg_salt)
676                     bits_assign(&kg1->kg_salt, kg2->kg_salt);
677 
678           if (kg2->kg_key)
679                     bits_assign(&kg1->kg_key, kg2->kg_key);
680 
681           if (kg2->kg_cmd)
682                     string_assign(&kg1->kg_cmd, kg2->kg_cmd);
683 
684           if (kg2->kg_sharedid)
685                     string_assign(&kg1->kg_sharedid, kg2->kg_sharedid);
686           if (kg2->kg_sharedalg != SHARED_ALG_UNKNOWN) {
687                     kg1->kg_sharedalg = kg2->kg_sharedalg;
688                     kg1->kg_sharedlen = kg2->kg_sharedlen;
689           }
690           if (kg2->kg_sharedinfo)
691                     bits_assign(&kg1->kg_sharedinfo, kg2->kg_sharedinfo);
692 
693           return kg1;
694 }
695 
696 struct keygen *
keygen_method(string_t * in)697 keygen_method(string_t *in)
698 {
699           struct keygen *kg = keygen_new();
700           const char *kgm = string_tocharstar(in);
701 
702 #ifdef HAVE_ARGON2
703           if (!strcmp("argon2id", kgm))
704                     kg->kg_method = KEYGEN_ARGON2ID;
705 #endif
706           if (!strcmp("pkcs5_pbkdf2", kgm))
707                     kg->kg_method = KEYGEN_PKCS5_PBKDF2_OLD;
708           if (!strcmp("pkcs5_pbkdf2/sha1", kgm))
709                     kg->kg_method = KEYGEN_PKCS5_PBKDF2_SHA1;
710           if (!strcmp("randomkey", kgm))
711                     kg->kg_method = KEYGEN_RANDOMKEY;
712           if (!strcmp("storedkey", kgm))
713                     kg->kg_method = KEYGEN_STOREDKEY;
714           if (!strcmp("urandomkey", kgm))
715                     kg->kg_method = KEYGEN_URANDOMKEY;
716           if (!strcmp("shell_cmd", kgm))
717                     kg->kg_method = KEYGEN_SHELL_CMD;
718 
719           string_free(in);
720 
721           if (kg->kg_method == KEYGEN_UNKNOWN)
722                     warnx("unrecognized key generation method \"%s\"", kgm);
723           return kg;
724 }
725 
726 struct keygen *
keygen_set_method(struct keygen * kg,string_t * in)727 keygen_set_method(struct keygen *kg, string_t *in)
728 {
729 
730           return keygen_combine(kg, keygen_method(in));
731 }
732 
733 struct keygen *
keygen_salt(bits_t * in)734 keygen_salt(bits_t *in)
735 {
736           struct keygen *kg = keygen_new();
737 
738           kg->kg_salt = in;
739           return kg;
740 }
741 
742 struct keygen *
keygen_iterations(size_t in)743 keygen_iterations(size_t in)
744 {
745           struct keygen *kg = keygen_new();
746 
747           kg->kg_iterations = in;
748           return kg;
749 }
750 
751 struct keygen *
keygen_memory(size_t in)752 keygen_memory(size_t in)
753 {
754           struct keygen *kg = keygen_new();
755 
756           kg->kg_memory = in;
757           return kg;
758 }
759 
760 struct keygen *
keygen_parallelism(size_t in)761 keygen_parallelism(size_t in)
762 {
763           struct keygen *kg = keygen_new();
764 
765           kg->kg_parallelism = in;
766           return kg;
767 }
768 
769 struct keygen *
keygen_version(size_t in)770 keygen_version(size_t in)
771 {
772           struct keygen *kg = keygen_new();
773 
774           kg->kg_version = in;
775           return kg;
776 }
777 
778 void
keygen_addlist(struct keygen ** l,struct keygen * e)779 keygen_addlist(struct keygen **l, struct keygen *e)
780 {
781           struct keygen *t;
782 
783           if (*l) {
784                     t = *l;
785                     for (;t->next; t = t->next)
786                               ;
787                     t->next = e;
788           } else {
789                     *l = e;
790           }
791 }
792 
793 struct keygen *
keygen_key(bits_t * in)794 keygen_key(bits_t *in)
795 {
796           struct keygen *kg = keygen_new();
797 
798           kg->kg_key = in;
799           return kg;
800 }
801 
802 struct keygen *
keygen_cmd(string_t * in)803 keygen_cmd(string_t *in)
804 {
805           struct keygen *kg = keygen_new();
806 
807           kg->kg_cmd = in;
808           return kg;
809 }
810 
811 struct keygen *
keygen_shared(string_t * id,string_t * alg,bits_t * info)812 keygen_shared(string_t *id, string_t *alg, bits_t *info)
813 {
814           struct keygen *kg = keygen_new();
815           const char *algname = string_tocharstar(alg);
816 
817           if (!strcmp("hkdf-hmac-sha256", algname)) {
818                     kg->kg_sharedalg = SHARED_ALG_HKDF_HMAC_SHA256;
819                     kg->kg_sharedlen = 8*SHA256_DIGEST_LENGTH;
820           }
821 
822           if (kg->kg_sharedalg == SHARED_ALG_UNKNOWN) {
823                     warnx("unrecognized shared key derivation algorithm \"%s\"",
824                         algname);
825           }
826 
827           kg->kg_sharedid = id;
828           kg->kg_sharedinfo = info;
829           return kg;
830 }
831 
832 struct params *
params_fget(FILE * f)833 params_fget(FILE *f)
834 {
835           struct params *p;
836 
837           p = cgdparsefile(f);
838 
839           if (!p)
840                     return NULL;
841 
842           /*
843            * We deal with the deprecated keygen structure by prepending it
844            * to the list of keygens, so that the rest of the code does not
845            * have to deal with this backwards compat issue.  The deprecated
846            * ``xor_key'' field may be stored in p->dep_keygen->kg_key.  If
847            * it exists, we construct a storedkey keygen struct as well.  Also,
848            * default the iteration count to 128 as the old code did.
849            */
850 
851           if (p->dep_keygen) {
852                     if (p->dep_keygen->kg_iterations == (size_t)-1)
853                               p->dep_keygen->kg_iterations = 128;
854                     p->dep_keygen->next = p->keygen;
855                     if (p->dep_keygen->kg_key) {
856                               p->keygen = keygen_generate(KEYGEN_STOREDKEY);
857                               p->keygen->kg_key = p->dep_keygen->kg_key;
858                               p->dep_keygen->kg_key = NULL;
859                               p->keygen->next = p->dep_keygen;
860                     } else {
861                               p->keygen = p->dep_keygen;
862                     }
863                     p->dep_keygen = NULL;
864           }
865           return p;
866 }
867 
868 struct params *
params_cget(const char * fn)869 params_cget(const char *fn)
870 {
871           struct params       *p;
872           FILE                *f;
873           char                filename[MAXPATHLEN];
874 
875           if ((f = fopen(fn, "r")) == NULL && fn[0] != '/') {
876                     snprintf(filename, sizeof(filename), "%s/%s",
877                         CGDCONFIG_DIR, fn);
878                     fn = filename;
879                     f = fopen(fn, "r");
880           }
881 
882           if (f == NULL) {
883                     warn("failed to open params file \"%s\"", fn);
884                     return NULL;
885           }
886           p = params_fget(f);
887           (void)fclose(f);
888           return p;
889 }
890 
891 #define WRAP_COL    50
892 #define TAB_COL               8
893 
894 static void
spaces(FILE * f,int len)895 spaces(FILE *f, int len)
896 {
897 
898           while (len-- > 0)
899                     (void)fputc(' ', f);
900 }
901 
902 static void
print_kvpair_cstr(FILE * f,int ts,const char * key,const char * val)903 print_kvpair_cstr(FILE *f, int ts, const char *key, const char *val)
904 {
905 
906           spaces(f, ts);
907           (void)fprintf(f, "%s %s;\n", key, val);
908 }
909 
910 static void
print_kvpair_string(FILE * f,int ts,const char * key,const string_t * val)911 print_kvpair_string(FILE *f, int ts, const char *key, const string_t *val)
912 {
913 
914           print_kvpair_cstr(f, ts, key, string_tocharstar(val));
915 }
916 
917 static void
print_kvpair_int(FILE * f,int ts,const char * key,size_t val)918 print_kvpair_int(FILE *f, int ts, const char *key, size_t val)
919 {
920           char      *tmp;
921 
922           if (!key || val == (size_t)-1)
923                     return;
924 
925           if (asprintf(&tmp, "%zu", val) == -1)
926                     err(1, NULL);
927           print_kvpair_cstr(f, ts, key, tmp);
928           free(tmp);
929 }
930 
931 /*
932  * prints out a base64 encoded k-v pair to f.  It encodes the length
933  * of the bitstream as a 32bit unsigned integer in network byte order
934  * up front.
935  */
936 
937 static void
print_kvpair_b64(FILE * f,int curpos,int ts,const char * key,bits_t * val)938 print_kvpair_b64(FILE *f, int curpos, int ts, const char *key, bits_t *val)
939 {
940           string_t  *str;
941           int                  i;
942           int                  len;
943           int                  pos;
944           const char          *out;
945 
946           if (!key || !val)
947                     return;
948 
949           str = bits_encode(val);
950           out = string_tocharstar(str);
951           len = strlen(out);
952 
953           spaces(f, ts);
954           (void)fprintf(f, "%s ", key);
955           curpos += ts + strlen(key) + 1;
956           ts = curpos;
957 
958           for (i=0, pos=curpos; i < len; i++, pos++) {
959                     if (pos > WRAP_COL) {
960                               (void)fprintf(f, " \\\n");
961                               spaces(f, ts);
962                               pos = ts;
963                     }
964                     (void)fputc(out[i], f);
965           }
966           (void)fprintf(f, ";\n");
967           string_free(str);
968 }
969 
970 static void
print_shared(FILE * f,int ts,struct keygen * kg)971 print_shared(FILE *f, int ts, struct keygen *kg)
972 {
973           static const char *const sharedalgs[] = {
974                     [SHARED_ALG_UNKNOWN] = "unknown",
975                     [SHARED_ALG_HKDF_HMAC_SHA256] = "hkdf-hmac-sha256",
976           };
977 
978           if (kg->kg_sharedid == NULL ||
979               kg->kg_sharedalg < 0 ||
980               (size_t)kg->kg_sharedalg >= __arraycount(sharedalgs))
981                     return;
982           fprintf(f, "%*sshared \"%s\" \\\n", ts, "",
983               string_tocharstar(kg->kg_sharedid));
984           ts += 4;
985           fprintf(f, "%*salgorithm %s \\\n", ts, "",
986               sharedalgs[kg->kg_sharedalg]);
987           print_kvpair_b64(f, 0, ts, "subkey", kg->kg_sharedinfo);
988 }
989 
990 int
keygen_fput(struct keygen * kg,int ts,FILE * f)991 keygen_fput(struct keygen *kg, int ts, FILE *f)
992 {
993           int       curpos = 0;
994 
995           if (!kg)
996                     return 0;
997           (void)fprintf(f, "keygen ");
998           curpos += strlen("keygen ");
999           switch (kg->kg_method) {
1000           case KEYGEN_STOREDKEY:
1001                     (void)fprintf(f, "storedkey ");
1002                     curpos += strlen("storedkey ");
1003                     print_kvpair_b64(f, curpos, 0, "key", kg->kg_key);
1004                     break;
1005           case KEYGEN_RANDOMKEY:
1006                     (void)fprintf(f, "randomkey;\n");
1007                     break;
1008           case KEYGEN_URANDOMKEY:
1009                     (void)fprintf(f, "urandomkey;\n");
1010                     break;
1011 #ifdef HAVE_ARGON2
1012           case KEYGEN_ARGON2ID:
1013                     (void)fprintf(f, "argon2id {\n");
1014                     print_kvpair_int(f, ts, "iterations", kg->kg_iterations);
1015                     print_kvpair_int(f, ts, "memory", kg->kg_memory);
1016                     print_kvpair_int(f, ts, "parallelism", kg->kg_parallelism);
1017                     print_kvpair_int(f, ts, "version", kg->kg_version);
1018                     print_kvpair_b64(f, 0, ts, "salt", kg->kg_salt);
1019                     print_shared(f, ts, kg);
1020                     (void)fprintf(f, "};\n");
1021                     break;
1022 #endif
1023           case KEYGEN_PKCS5_PBKDF2_OLD:
1024                     (void)fprintf(f, "pkcs5_pbkdf2 {\n");
1025                     print_kvpair_int(f, ts, "iterations", kg->kg_iterations);
1026                     print_kvpair_b64(f, 0, ts, "salt", kg->kg_salt);
1027                     print_shared(f, ts, kg);
1028                     (void)fprintf(f, "};\n");
1029                     break;
1030           case KEYGEN_PKCS5_PBKDF2_SHA1:
1031                     (void)fprintf(f, "pkcs5_pbkdf2/sha1 {\n");
1032                     print_kvpair_int(f, ts, "iterations", kg->kg_iterations);
1033                     print_kvpair_b64(f, 0, ts, "salt", kg->kg_salt);
1034                     print_shared(f, ts, kg);
1035                     (void)fprintf(f, "};\n");
1036                     break;
1037           default:
1038                     warnx("keygen_fput: %d not a valid method", kg->kg_method);
1039                     break;
1040           }
1041           return keygen_fput(kg->next, ts, f);
1042 }
1043 
1044 int
params_fput(struct params * p,FILE * f)1045 params_fput(struct params *p, FILE *f)
1046 {
1047           int       ts = 0;             /* tabstop of 0 spaces */
1048 
1049           print_kvpair_string(f, ts, "algorithm", p->algorithm);
1050           print_kvpair_string(f, ts, "iv-method", p->ivmeth);
1051           print_kvpair_int(f, ts, "keylength", p->keylen);
1052           print_kvpair_int(f, ts, "blocksize", p->bsize);
1053           switch (p->verify_method) {
1054           case VERIFY_NONE:
1055                     print_kvpair_cstr(f, ts, "verify_method", "none");
1056                     break;
1057           case VERIFY_DISKLABEL:
1058                     print_kvpair_cstr(f, ts, "verify_method", "disklabel");
1059                     break;
1060           case VERIFY_FFS:
1061                     print_kvpair_cstr(f, ts, "verify_method", "ffs");
1062                     break;
1063           case VERIFY_REENTER:
1064                     print_kvpair_cstr(f, ts, "verify_method", "re-enter");
1065                     break;
1066           case VERIFY_MBR:
1067                     print_kvpair_cstr(f, ts, "verify_method", "mbr");
1068                     break;
1069           case VERIFY_GPT:
1070                     print_kvpair_cstr(f, ts, "verify_method", "gpt");
1071                     break;
1072 #ifdef HAVE_ZFS
1073           case VERIFY_ZFS:
1074                     print_kvpair_cstr(f, ts, "verify_method", "zfs");
1075                     break;
1076 #endif
1077           default:
1078                     warnx("unsupported verify_method (%d)", p->verify_method);
1079                     return -1;
1080           }
1081           return keygen_fput(p->keygen, TAB_COL, f);
1082 }
1083 
1084 int
params_cput(struct params * p,const char * fn)1085 params_cput(struct params *p, const char *fn)
1086 {
1087           FILE      *f;
1088 
1089           if (fn && *fn) {
1090                     if ((f = fopen(fn, "w")) == NULL) {
1091                               warn("could not open outfile \"%s\"", fn);
1092                               return -1;
1093                     }
1094           } else {
1095                     f = stdout;
1096           }
1097           return params_fput(p, f);
1098 }
1099 
1100 static int
crypt_defaults_lookup(const char * alg)1101 crypt_defaults_lookup(const char *alg)
1102 {
1103           unsigned  i;
1104 
1105           for (i=0; i < (sizeof(crypto_defaults) / sizeof(crypto_defaults[0])); i++)
1106                     if (!strcmp(alg, crypto_defaults[i].alg))
1107                               return i;
1108 
1109           return -1;
1110 }
1111