1 /* $NetBSD: params.c,v 1.23 2008/05/11 03:15:21 elric Exp $ */
4 * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Roland C. Dowdeswell.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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.
32 #include <sys/cdefs.h>
34 __RCSID("$NetBSD: params.c,v 1.23 2008/05/11 03:15:21 elric Exp $");
37 #include <sys/types.h>
47 #include "pkcs5_pbkdf2.h"
51 static void params_init(struct params
*);
53 static void print_kvpair_cstr(FILE *, int, const char *, const char *);
54 static void print_kvpair_string(FILE *, int, const char *, const string_t
*);
55 static void print_kvpair_int(FILE *, int, const char *, size_t);
56 static void print_kvpair_b64(FILE *, int, int, const char *, bits_t
*);
58 static void spaces(FILE *, int);
61 #define DEFAULT_SALTLEN 128
62 #define DEFAULT_ITERATION_TIME 2000000 /* 1 second in microseconds */
64 /* crypto defaults functions */
65 static struct crypto_defaults
{
68 } crypto_defaults
[] = {
71 { "blowfish-cbc", 128 }
74 static int crypt_defaults_lookup(const char *);
81 p
= emalloc(sizeof(*p
));
87 params_init(struct params
*p
)
93 p
->keylen
= (size_t)-1;
94 p
->bsize
= (size_t)-1;
95 p
->verify_method
= VERIFY_UNKNOWN
;
101 params_free(struct params
*p
)
106 string_free(p
->algorithm
);
107 string_free(p
->ivmeth
);
108 keygen_free(p
->dep_keygen
);
109 keygen_free(p
->keygen
);
113 params_combine(struct params
*p1
, struct params
*p2
)
126 string_assign(&p
->algorithm
, p2
->algorithm
);
128 string_assign(&p
->ivmeth
, p2
->ivmeth
);
129 if (p2
->keylen
!= (size_t)-1)
130 p
->keylen
= p2
->keylen
;
131 if (p2
->bsize
!= (size_t)-1)
132 p
->bsize
= p2
->bsize
;
133 if (p2
->verify_method
!= VERIFY_UNKNOWN
)
134 p
->verify_method
= p2
->verify_method
;
136 p
->dep_keygen
= keygen_combine(p
->dep_keygen
, p2
->dep_keygen
);
137 keygen_addlist(&p
->keygen
, p2
->keygen
);
140 * at this point we should have moved all allocated data
141 * in p2 into p, so we can free it.
148 params_filldefaults(struct params
*p
)
152 if (p
->verify_method
== VERIFY_UNKNOWN
)
153 p
->verify_method
= VERIFY_NONE
;
155 p
->ivmeth
= string_fromcharstar("encblkno1");
156 if (p
->keylen
== (size_t)-1) {
157 i
= crypt_defaults_lookup(string_tocharstar(p
->algorithm
));
158 if (i
!= (size_t)-1) {
159 p
->keylen
= crypto_defaults
[i
].keylen
;
161 warnx("could not determine key length for unknown "
163 string_tocharstar(p
->algorithm
));
171 * params_verify traverses the parameters and all of the keygen methods
172 * looking for inconsistencies. It outputs warnings on non-fatal errors
173 * such as unknown encryption methods, but returns failure on fatal
174 * conditions such as a PKCS5_PBKDF2 keygen without a salt. It is intended
175 * to run before key generation.
179 params_verify(const struct params
*p
)
181 static const char *encblkno
[] = {
182 "encblkno", "encblkno1", "encblkno8"
188 warnx("unspecified algorithm");
192 * we only warn for the encryption method so that it is possible
193 * to use an older cgdconfig(8) with a new kernel that supports
194 * additional crypto algorithms.
196 if (crypt_defaults_lookup(string_tocharstar(p
->algorithm
)) == -1)
197 warnx("unknown algorithm \"%s\"(warning)",
198 string_tocharstar(p
->algorithm
));
199 /* same rationale with IV methods. */
201 warnx("unspecified IV method");
205 meth
= string_tocharstar(p
->ivmeth
);
206 for (i
= 0; i
< __arraycount(encblkno
); i
++)
207 if (strcmp(encblkno
[i
], meth
) == 0)
210 if (i
== __arraycount(encblkno
))
211 warnx("unknown IV method \"%s\" (warning)", meth
);
213 if (p
->keylen
== (size_t)-1) {
214 warnx("unspecified key length");
218 return keygen_verify(p
->keygen
);
222 params_algorithm(string_t
*in
)
224 struct params
*p
= params_new();
231 params_ivmeth(string_t
*in
)
233 struct params
*p
= params_new();
240 params_keylen(size_t in
)
242 struct params
*p
= params_new();
249 params_bsize(size_t in
)
251 struct params
*p
= params_new();
258 params_verify_method(string_t
*in
)
260 struct params
*p
= params_new();
261 const char *vm
= string_tocharstar(in
);
263 if (!strcmp("none", vm
))
264 p
->verify_method
= VERIFY_NONE
;
265 if (!strcmp("disklabel", vm
))
266 p
->verify_method
= VERIFY_DISKLABEL
;
267 if (!strcmp("ffs", vm
))
268 p
->verify_method
= VERIFY_FFS
;
269 if (!strcmp("re-enter", vm
))
270 p
->verify_method
= VERIFY_REENTER
;
274 if (p
->verify_method
== VERIFY_UNKNOWN
)
275 warnx("params_setverify_method: unrecognized "
276 "verify method \"%s\"\n", vm
);
281 params_keygen(struct keygen
*in
)
283 struct params
*p
= params_new();
290 params_dep_keygen(struct keygen
*in
)
292 struct params
*p
= params_new();
303 kg
= emalloc(sizeof(*kg
));
304 kg
->kg_method
= KEYGEN_UNKNOWN
;
305 kg
->kg_iterations
= (size_t)-1;
314 keygen_free(struct keygen
*kg
)
319 bits_free(kg
->kg_salt
);
320 bits_free(kg
->kg_key
);
321 string_free(kg
->kg_cmd
);
322 keygen_free(kg
->next
);
327 * keygen_verify traverses the keygen structures and ensures
328 * that the appropriate information is available.
332 keygen_verify(const struct keygen
*kg
)
337 switch (kg
->kg_method
) {
338 case KEYGEN_PKCS5_PBKDF2_OLD
:
339 if (kg
->kg_iterations
== (size_t)-1) {
340 warnx("keygen pkcs5_pbkdf2 must provide `iterations'");
344 warnx("keygen pkcs5_pbkdf2 does not need a `key'");
346 warnx("keygen pkcs5_pbkdf2 must provide a salt");
350 warnx("keygen pkcs5_pbkdf2 does not need a `cmd'");
352 case KEYGEN_PKCS5_PBKDF2_SHA1
:
353 if (kg
->kg_iterations
== (size_t)-1) {
354 warnx("keygen pkcs5_pbkdf2/sha1 must provide `iterations'");
358 warnx("keygen pkcs5_pbkdf2/sha1 does not need a `key'");
360 warnx("keygen pkcs5_pbkdf2/sha1 must provide a salt");
364 warnx("keygen pkcs5_pbkdf2/sha1 does not need a `cmd'");
366 case KEYGEN_STOREDKEY
:
367 if (kg
->kg_iterations
!= (size_t)-1)
368 warnx("keygen storedkey does not need `iterations'");
370 warnx("keygen storedkey must provide a key");
374 warnx("keygen storedkey does not need `salt'");
376 warnx("keygen storedkey does not need `cmd'");
378 case KEYGEN_RANDOMKEY
:
379 case KEYGEN_URANDOMKEY
:
380 if (kg
->kg_iterations
!= (size_t)-1)
381 warnx("keygen [u]randomkey does not need `iterations'");
383 warnx("keygen [u]randomkey does not need `key'");
385 warnx("keygen [u]randomkey does not need `salt'");
387 warnx("keygen [u]randomkey does not need `cmd'");
389 case KEYGEN_SHELL_CMD
:
390 if (kg
->kg_iterations
!= (size_t)-1)
391 warnx("keygen shell_cmd does not need `iterations'");
393 warnx("keygen shell_cmd does not need `key'");
395 warnx("keygen shell_cmd does not need `salt'");
397 warnx("keygen shell_cmd must provide a `cmd'");
402 return keygen_verify(kg
->next
);
406 keygen_generate(int method
)
414 kg
->kg_method
= method
;
419 * keygen_filldefaults walks the keygen list and fills in
420 * default values. The defaults may be either calibrated
421 * or randomly generated so this function is designed to be
422 * called when generating a new parameters file, not when
423 * reading a parameters file.
427 keygen_filldefaults(struct keygen
*kg
, size_t keylen
)
432 switch (kg
->kg_method
) {
433 case KEYGEN_RANDOMKEY
:
434 case KEYGEN_URANDOMKEY
:
435 case KEYGEN_SHELL_CMD
:
437 case KEYGEN_PKCS5_PBKDF2_OLD
:
438 case KEYGEN_PKCS5_PBKDF2_SHA1
:
439 kg
->kg_salt
= bits_getrandombits(DEFAULT_SALTLEN
, 1);
440 kg
->kg_iterations
= pkcs5_pbkdf2_calibrate(BITS2BYTES(keylen
),
441 DEFAULT_ITERATION_TIME
);
442 if (kg
->kg_iterations
< 1) {
443 warnx("could not calibrate pkcs5_pbkdf2");
447 case KEYGEN_STOREDKEY
:
448 /* Generate a random stored key */
449 kg
->kg_key
= bits_getrandombits(keylen
, 1);
451 warnx("can't generate random bits for storedkey");
459 return keygen_filldefaults(kg
->next
, keylen
);
463 keygen_combine(struct keygen
*kg1
, struct keygen
*kg2
)
474 if (kg2
->kg_method
!= KEYGEN_UNKNOWN
)
475 kg1
->kg_method
= kg2
->kg_method
;
477 if (kg2
->kg_iterations
!= (size_t)-1 && kg2
->kg_iterations
> 0)
478 kg1
->kg_iterations
= kg2
->kg_iterations
;
481 bits_assign(&kg1
->kg_salt
, kg2
->kg_salt
);
484 bits_assign(&kg1
->kg_key
, kg2
->kg_key
);
487 string_assign(&kg1
->kg_cmd
, kg2
->kg_cmd
);
493 keygen_method(string_t
*in
)
495 struct keygen
*kg
= keygen_new();
496 const char *kgm
= string_tocharstar(in
);
498 if (!strcmp("pkcs5_pbkdf2", kgm
))
499 kg
->kg_method
= KEYGEN_PKCS5_PBKDF2_OLD
;
500 if (!strcmp("pkcs5_pbkdf2/sha1", kgm
))
501 kg
->kg_method
= KEYGEN_PKCS5_PBKDF2_SHA1
;
502 if (!strcmp("randomkey", kgm
))
503 kg
->kg_method
= KEYGEN_RANDOMKEY
;
504 if (!strcmp("storedkey", kgm
))
505 kg
->kg_method
= KEYGEN_STOREDKEY
;
506 if (!strcmp("urandomkey", kgm
))
507 kg
->kg_method
= KEYGEN_URANDOMKEY
;
508 if (!strcmp("shell_cmd", kgm
))
509 kg
->kg_method
= KEYGEN_SHELL_CMD
;
513 if (kg
->kg_method
== KEYGEN_UNKNOWN
)
514 warnx("unrecognized key generation method \"%s\"\n", kgm
);
519 keygen_set_method(struct keygen
*kg
, string_t
*in
)
522 return keygen_combine(kg
, keygen_method(in
));
526 keygen_salt(bits_t
*in
)
528 struct keygen
*kg
= keygen_new();
535 keygen_iterations(size_t in
)
537 struct keygen
*kg
= keygen_new();
539 kg
->kg_iterations
= in
;
544 keygen_addlist(struct keygen
**l
, struct keygen
*e
)
550 for (;t
->next
; t
= t
->next
)
559 keygen_key(bits_t
*in
)
561 struct keygen
*kg
= keygen_new();
568 keygen_cmd(string_t
*in
)
570 struct keygen
*kg
= keygen_new();
587 * We deal with the deprecated keygen structure by prepending it
588 * to the list of keygens, so that the rest of the code does not
589 * have to deal with this backwards compat issue. The deprecated
590 * ``xor_key'' field may be stored in p->dep_keygen->kg_key. If
591 * it exists, we construct a storedkey keygen struct as well. Also,
592 * default the iteration count to 128 as the old code did.
596 if (p
->dep_keygen
->kg_iterations
== (size_t)-1)
597 p
->dep_keygen
->kg_iterations
= 128;
598 p
->dep_keygen
->next
= p
->keygen
;
599 if (p
->dep_keygen
->kg_key
) {
600 p
->keygen
= keygen_generate(KEYGEN_STOREDKEY
);
601 p
->keygen
->kg_key
= p
->dep_keygen
->kg_key
;
602 p
->dep_keygen
->kg_key
= NULL
;
603 p
->keygen
->next
= p
->dep_keygen
;
605 p
->keygen
= p
->dep_keygen
;
607 p
->dep_keygen
= NULL
;
613 params_cget(const char *fn
)
618 if ((f
= fopen(fn
, "r")) == NULL
) {
619 warn("failed to open params file \"%s\"", fn
);
631 spaces(FILE *f
, int len
)
639 print_kvpair_cstr(FILE *f
, int ts
, const char *key
, const char *val
)
643 (void)fprintf(f
, "%s %s;\n", key
, val
);
647 print_kvpair_string(FILE *f
, int ts
, const char *key
, const string_t
*val
)
650 print_kvpair_cstr(f
, ts
, key
, string_tocharstar(val
));
654 print_kvpair_int(FILE *f
, int ts
, const char *key
, size_t val
)
658 if (!key
|| val
== (size_t)-1)
661 if (asprintf(&tmp
, "%zu", val
) == -1)
663 print_kvpair_cstr(f
, ts
, key
, tmp
);
668 * prints out a base64 encoded k-v pair to f. It encodes the length
669 * of the bitstream as a 32bit unsigned integer in network byte order
674 print_kvpair_b64(FILE *f
, int curpos
, int ts
, const char *key
, bits_t
*val
)
685 str
= bits_encode(val
);
686 out
= string_tocharstar(str
);
690 (void)fprintf(f
, "%s ", key
);
691 curpos
+= ts
+ strlen(key
) + 1;
694 for (i
=0, pos
=curpos
; i
< len
; i
++, pos
++) {
695 if (pos
> WRAP_COL
) {
696 (void)fprintf(f
, " \\\n");
700 (void)fputc(out
[i
], f
);
702 (void)fprintf(f
, ";\n");
707 keygen_fput(struct keygen
*kg
, int ts
, FILE *f
)
713 (void)fprintf(f
, "keygen ");
714 curpos
+= strlen("keygen ");
715 switch (kg
->kg_method
) {
716 case KEYGEN_STOREDKEY
:
717 (void)fprintf(f
, "storedkey ");
718 curpos
+= strlen("storedkey ");
719 print_kvpair_b64(f
, curpos
, 0, "key", kg
->kg_key
);
721 case KEYGEN_RANDOMKEY
:
722 (void)fprintf(f
, "randomkey;\n");
724 case KEYGEN_URANDOMKEY
:
725 (void)fprintf(f
, "urandomkey;\n");
727 case KEYGEN_PKCS5_PBKDF2_OLD
:
728 (void)fprintf(f
, "pkcs5_pbkdf2 {\n");
729 print_kvpair_int(f
, ts
, "iterations", kg
->kg_iterations
);
730 print_kvpair_b64(f
, 0, ts
, "salt", kg
->kg_salt
);
731 (void)fprintf(f
, "};\n");
733 case KEYGEN_PKCS5_PBKDF2_SHA1
:
734 (void)fprintf(f
, "pkcs5_pbkdf2/sha1 {\n");
735 print_kvpair_int(f
, ts
, "iterations", kg
->kg_iterations
);
736 print_kvpair_b64(f
, 0, ts
, "salt", kg
->kg_salt
);
737 (void)fprintf(f
, "};\n");
740 warnx("keygen_fput: %d not a valid method", kg
->kg_method
);
743 return keygen_fput(kg
->next
, ts
, f
);
747 params_fput(struct params
*p
, FILE *f
)
749 int ts
= 0; /* tabstop of 0 spaces */
751 print_kvpair_string(f
, ts
, "algorithm", p
->algorithm
);
752 print_kvpair_string(f
, ts
, "iv-method", p
->ivmeth
);
753 print_kvpair_int(f
, ts
, "keylength", p
->keylen
);
754 print_kvpair_int(f
, ts
, "blocksize", p
->bsize
);
755 switch (p
->verify_method
) {
757 print_kvpair_cstr(f
, ts
, "verify_method", "none");
759 case VERIFY_DISKLABEL
:
760 print_kvpair_cstr(f
, ts
, "verify_method", "disklabel");
763 print_kvpair_cstr(f
, ts
, "verify_method", "ffs");
766 print_kvpair_cstr(f
, ts
, "verify_method", "re-enter");
769 warnx("unsupported verify_method (%d)", p
->verify_method
);
772 return keygen_fput(p
->keygen
, TAB_COL
, f
);
776 params_cput(struct params
*p
, const char *fn
)
781 if ((f
= fopen(fn
, "w")) == NULL
) {
782 warn("could not open outfile \"%s\"", fn
);
788 return params_fput(p
, f
);
792 crypt_defaults_lookup(const char *alg
)
796 for (i
=0; i
< (sizeof(crypto_defaults
) / sizeof(crypto_defaults
[0])); i
++)
797 if (!strcmp(alg
, crypto_defaults
[i
].alg
))