1/* $NetBSD: params.c,v 1.23 2008/05/11 03:15:21 elric 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.23 2008/05/11 03:15:21 elric Exp $");
35#endif
36
37#include <sys/types.h>
38
39#include <err.h>
40#include <errno.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <util.h>
45
46#include "params.h"
47#include "pkcs5_pbkdf2.h"
48#include "utils.h"
49#include "extern.h"
50
51static void	params_init(struct params *);
52
53static void	print_kvpair_cstr(FILE *, int, const char *, const char *);
54static void	print_kvpair_string(FILE *, int, const char *, const string_t *);
55static void	print_kvpair_int(FILE *, int, const char *, size_t);
56static void	print_kvpair_b64(FILE *, int, int, const char *, bits_t *);
57
58static void	spaces(FILE *, int);
59
60/* keygen defaults */
61#define DEFAULT_SALTLEN		128
62#define DEFAULT_ITERATION_TIME	2000000		/* 1 second in microseconds */
63
64/* crypto defaults functions */
65static struct crypto_defaults {
66	char	alg[32];
67	int	keylen;
68} crypto_defaults[] = {
69	{ "aes-cbc",		128 },
70	{ "3des-cbc",		192 },
71	{ "blowfish-cbc",	128 }
72};
73
74static int	crypt_defaults_lookup(const char *);
75
76struct params *
77params_new(void)
78{
79	struct params	*p;
80
81	p = emalloc(sizeof(*p));
82	params_init(p);
83	return p;
84}
85
86static void
87params_init(struct params *p)
88{
89
90	p->algorithm = NULL;
91	p->ivmeth = NULL;
92	p->key = NULL;
93	p->keylen = (size_t)-1;
94	p->bsize = (size_t)-1;
95	p->verify_method = VERIFY_UNKNOWN;
96	p->dep_keygen = NULL;
97	p->keygen = NULL;
98}
99
100void
101params_free(struct params *p)
102{
103
104	if (!p)
105		return;
106	string_free(p->algorithm);
107	string_free(p->ivmeth);
108	keygen_free(p->dep_keygen);
109	keygen_free(p->keygen);
110}
111
112struct params *
113params_combine(struct params *p1, struct params *p2)
114{
115	struct params *p;
116
117	if (p1)
118		p = p1;
119	else
120		p = params_new();
121
122	if (!p2)
123		return p;
124
125	if (p2->algorithm)
126		string_assign(&p->algorithm, p2->algorithm);
127	if (p2->ivmeth)
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;
135
136	p->dep_keygen = keygen_combine(p->dep_keygen, p2->dep_keygen);
137	keygen_addlist(&p->keygen, p2->keygen);
138
139	/*
140	 * at this point we should have moved all allocated data
141	 * in p2 into p, so we can free it.
142	 */
143	free(p2);
144	return p;
145}
146
147int
148params_filldefaults(struct params *p)
149{
150	size_t	i;
151
152	if (p->verify_method == VERIFY_UNKNOWN)
153		p->verify_method = VERIFY_NONE;
154	if (!p->ivmeth)
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;
160		} else {
161			warnx("could not determine key length for unknown "
162			    "algorithm \"%s\"",
163			    string_tocharstar(p->algorithm));
164			return -1;
165		}
166	}
167	return 0;
168}
169
170/*
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.
176 */
177
178int
179params_verify(const struct params *p)
180{
181	static const char *encblkno[] = {
182	    "encblkno", "encblkno1", "encblkno8"
183	};
184	static size_t i;
185	const char *meth;
186
187	if (!p->algorithm) {
188		warnx("unspecified algorithm");
189		return 0;
190	}
191	/*
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.
195	 */
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. */
200	if (!p->ivmeth) {
201		warnx("unspecified IV method");
202		return 0;
203	}
204
205	meth = string_tocharstar(p->ivmeth);
206	for (i = 0; i < __arraycount(encblkno); i++)
207		if (strcmp(encblkno[i], meth) == 0)
208			break;
209
210	if (i == __arraycount(encblkno))
211		warnx("unknown IV method \"%s\" (warning)", meth);
212
213	if (p->keylen == (size_t)-1) {
214		warnx("unspecified key length");
215		return 0;
216	}
217
218	return keygen_verify(p->keygen);
219}
220
221struct params *
222params_algorithm(string_t *in)
223{
224	struct params *p = params_new();
225
226	p->algorithm = in;
227	return p;
228}
229
230struct params *
231params_ivmeth(string_t *in)
232{
233	struct params *p = params_new();
234
235	p->ivmeth = in;
236	return p;
237}
238
239struct params *
240params_keylen(size_t in)
241{
242	struct params *p = params_new();
243
244	p->keylen = in;
245	return p;
246}
247
248struct params *
249params_bsize(size_t in)
250{
251	struct params *p = params_new();
252
253	p->bsize = in;
254	return p;
255}
256
257struct params *
258params_verify_method(string_t *in)
259{
260	struct params *p = params_new();
261	const char *vm = string_tocharstar(in);
262
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;
271
272	string_free(in);
273
274	if (p->verify_method == VERIFY_UNKNOWN)
275		warnx("params_setverify_method: unrecognized "
276		    "verify method \"%s\"\n", vm);
277	return p;
278}
279
280struct params *
281params_keygen(struct keygen *in)
282{
283	struct params *p = params_new();
284
285	p->keygen = in;
286	return p;
287}
288
289struct params *
290params_dep_keygen(struct keygen *in)
291{
292	struct params *p = params_new();
293
294	p->dep_keygen = in;
295	return p;
296}
297
298struct keygen *
299keygen_new(void)
300{
301	struct keygen *kg;
302
303	kg = emalloc(sizeof(*kg));
304	kg->kg_method = KEYGEN_UNKNOWN;
305	kg->kg_iterations = (size_t)-1;
306	kg->kg_salt = NULL;
307	kg->kg_key = NULL;
308	kg->kg_cmd = NULL;
309	kg->next = NULL;
310	return kg;
311}
312
313void
314keygen_free(struct keygen *kg)
315{
316
317	if (!kg)
318		return;
319	bits_free(kg->kg_salt);
320	bits_free(kg->kg_key);
321	string_free(kg->kg_cmd);
322	keygen_free(kg->next);
323	free(kg);
324}
325
326/*
327 * keygen_verify traverses the keygen structures and ensures
328 * that the appropriate information is available.
329 */
330
331int
332keygen_verify(const struct keygen *kg)
333{
334
335	if (!kg)
336		return 1;
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'");
341			return 0;
342		}
343		if (kg->kg_key)
344			warnx("keygen pkcs5_pbkdf2 does not need a `key'");
345		if (!kg->kg_salt) {
346			warnx("keygen pkcs5_pbkdf2 must provide a salt");
347			return 0;
348		}
349		if (kg->kg_cmd)
350			warnx("keygen pkcs5_pbkdf2 does not need a `cmd'");
351		break;
352	case KEYGEN_PKCS5_PBKDF2_SHA1:
353		if (kg->kg_iterations == (size_t)-1) {
354			warnx("keygen pkcs5_pbkdf2/sha1 must provide `iterations'");
355			return 0;
356		}
357		if (kg->kg_key)
358			warnx("keygen pkcs5_pbkdf2/sha1 does not need a `key'");
359		if (!kg->kg_salt) {
360			warnx("keygen pkcs5_pbkdf2/sha1 must provide a salt");
361			return 0;
362		}
363		if (kg->kg_cmd)
364			warnx("keygen pkcs5_pbkdf2/sha1 does not need a `cmd'");
365		break;
366	case KEYGEN_STOREDKEY:
367		if (kg->kg_iterations != (size_t)-1)
368			warnx("keygen storedkey does not need `iterations'");
369		if (!kg->kg_key) {
370			warnx("keygen storedkey must provide a key");
371			return 0;
372		}
373		if (kg->kg_salt)
374			warnx("keygen storedkey does not need `salt'");
375		if (kg->kg_cmd)
376			warnx("keygen storedkey does not need `cmd'");
377		break;
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'");
382		if (kg->kg_key)
383			warnx("keygen [u]randomkey does not need `key'");
384		if (kg->kg_salt)
385			warnx("keygen [u]randomkey does not need `salt'");
386		if (kg->kg_cmd)
387			warnx("keygen [u]randomkey does not need `cmd'");
388		break;
389	case KEYGEN_SHELL_CMD:
390		if (kg->kg_iterations != (size_t)-1)
391			warnx("keygen shell_cmd does not need `iterations'");
392		if (kg->kg_key)
393			warnx("keygen shell_cmd does not need `key'");
394		if (kg->kg_salt)
395			warnx("keygen shell_cmd does not need `salt'");
396		if (!kg->kg_cmd) {
397			warnx("keygen shell_cmd must provide a `cmd'");
398			return 0;
399		}
400		break;
401	}
402	return keygen_verify(kg->next);
403}
404
405struct keygen *
406keygen_generate(int method)
407{
408	struct keygen *kg;
409
410	kg = keygen_new();
411	if (!kg)
412		return NULL;
413
414	kg->kg_method = method;
415	return kg;
416}
417
418/*
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.
424 */
425
426int
427keygen_filldefaults(struct keygen *kg, size_t keylen)
428{
429
430	if (!kg)
431		return 0;
432	switch (kg->kg_method) {
433	case KEYGEN_RANDOMKEY:
434	case KEYGEN_URANDOMKEY:
435	case KEYGEN_SHELL_CMD:
436		break;
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");
444			return -1;
445		}
446		break;
447	case KEYGEN_STOREDKEY:
448		/* Generate a random stored key */
449		kg->kg_key = bits_getrandombits(keylen, 1);
450		if (!kg->kg_key) {
451			warnx("can't generate random bits for storedkey");
452			return -1;
453		}
454		break;
455	default:
456		return -1;
457	}
458
459	return keygen_filldefaults(kg->next, keylen);
460}
461
462struct keygen *
463keygen_combine(struct keygen *kg1, struct keygen *kg2)
464{
465	if (!kg1 && !kg2)
466		return NULL;
467
468	if (!kg1)
469		kg1 = keygen_new();
470
471	if (!kg2)
472		return kg1;
473
474	if (kg2->kg_method != KEYGEN_UNKNOWN)
475		kg1->kg_method = kg2->kg_method;
476
477	if (kg2->kg_iterations != (size_t)-1 && kg2->kg_iterations > 0)
478		kg1->kg_iterations = kg2->kg_iterations;
479
480	if (kg2->kg_salt)
481		bits_assign(&kg1->kg_salt, kg2->kg_salt);
482
483	if (kg2->kg_key)
484		bits_assign(&kg1->kg_key, kg2->kg_key);
485
486	if (kg2->kg_cmd)
487		string_assign(&kg1->kg_cmd, kg2->kg_cmd);
488
489	return kg1;
490}
491
492struct keygen *
493keygen_method(string_t *in)
494{
495	struct keygen *kg = keygen_new();
496	const char *kgm = string_tocharstar(in);
497
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;
510
511	string_free(in);
512
513	if (kg->kg_method == KEYGEN_UNKNOWN)
514		warnx("unrecognized key generation method \"%s\"\n", kgm);
515	return kg;
516}
517
518struct keygen *
519keygen_set_method(struct keygen *kg, string_t *in)
520{
521
522	return keygen_combine(kg, keygen_method(in));
523}
524
525struct keygen *
526keygen_salt(bits_t *in)
527{
528	struct keygen *kg = keygen_new();
529
530	kg->kg_salt = in;
531	return kg;
532}
533
534struct keygen *
535keygen_iterations(size_t in)
536{
537	struct keygen *kg = keygen_new();
538
539	kg->kg_iterations = in;
540	return kg;
541}
542
543void
544keygen_addlist(struct keygen **l, struct keygen *e)
545{
546	struct keygen *t;
547
548	if (*l) {
549		t = *l;
550		for (;t->next; t = t->next)
551			;
552		t->next = e;
553	} else {
554		*l = e;
555	}
556}
557
558struct keygen *
559keygen_key(bits_t *in)
560{
561	struct keygen *kg = keygen_new();
562
563	kg->kg_key = in;
564	return kg;
565}
566
567struct keygen *
568keygen_cmd(string_t *in)
569{
570	struct keygen *kg = keygen_new();
571
572	kg->kg_cmd = in;
573	return kg;
574}
575
576struct params *
577params_fget(FILE *f)
578{
579	struct params *p;
580
581	p = cgdparsefile(f);
582
583	if (!p)
584		return NULL;
585
586	/*
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.
593	 */
594
595	if (p->dep_keygen) {
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;
604		} else {
605			p->keygen = p->dep_keygen;
606		}
607		p->dep_keygen = NULL;
608	}
609	return p;
610}
611
612struct params *
613params_cget(const char *fn)
614{
615	struct params	*p;
616	FILE		*f;
617
618	if ((f = fopen(fn, "r")) == NULL) {
619		warn("failed to open params file \"%s\"", fn);
620		return NULL;
621	}
622	p = params_fget(f);
623	(void)fclose(f);
624	return p;
625}
626
627#define WRAP_COL	50
628#define TAB_COL		8
629
630static void
631spaces(FILE *f, int len)
632{
633
634	while (len-- > 0)
635		(void)fputc(' ', f);
636}
637
638static void
639print_kvpair_cstr(FILE *f, int ts, const char *key, const char *val)
640{
641
642	spaces(f, ts);
643	(void)fprintf(f, "%s %s;\n", key, val);
644}
645
646static void
647print_kvpair_string(FILE *f, int ts, const char *key, const string_t *val)
648{
649
650	print_kvpair_cstr(f, ts, key, string_tocharstar(val));
651}
652
653static void
654print_kvpair_int(FILE *f, int ts, const char *key, size_t val)
655{
656	char	*tmp;
657
658	if (!key || val == (size_t)-1)
659		return;
660
661	if (asprintf(&tmp, "%zu", val) == -1)
662		err(1, NULL);
663	print_kvpair_cstr(f, ts, key, tmp);
664	free(tmp);
665}
666
667/*
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
670 * up front.
671 */
672
673static void
674print_kvpair_b64(FILE *f, int curpos, int ts, const char *key, bits_t *val)
675{
676	string_t	*str;
677	int		 i;
678	int		 len;
679	int		 pos;
680	const char	*out;
681
682	if (!key || !val)
683		return;
684
685	str = bits_encode(val);
686	out = string_tocharstar(str);
687	len = strlen(out);
688
689	spaces(f, ts);
690	(void)fprintf(f, "%s ", key);
691	curpos += ts + strlen(key) + 1;
692	ts = curpos;
693
694	for (i=0, pos=curpos; i < len; i++, pos++) {
695		if (pos > WRAP_COL) {
696			(void)fprintf(f, " \\\n");
697			spaces(f, ts);
698			pos = ts;
699		}
700		(void)fputc(out[i], f);
701	}
702	(void)fprintf(f, ";\n");
703	string_free(str);
704}
705
706int
707keygen_fput(struct keygen *kg, int ts, FILE *f)
708{
709	int	curpos = 0;
710
711	if (!kg)
712		return 0;
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);
720		break;
721	case KEYGEN_RANDOMKEY:
722		(void)fprintf(f, "randomkey;\n");
723		break;
724	case KEYGEN_URANDOMKEY:
725		(void)fprintf(f, "urandomkey;\n");
726		break;
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");
732		break;
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");
738		break;
739	default:
740		warnx("keygen_fput: %d not a valid method", kg->kg_method);
741		break;
742	}
743	return keygen_fput(kg->next, ts, f);
744}
745
746int
747params_fput(struct params *p, FILE *f)
748{
749	int	ts = 0;		/* tabstop of 0 spaces */
750
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) {
756	case VERIFY_NONE:
757		print_kvpair_cstr(f, ts, "verify_method", "none");
758		break;
759	case VERIFY_DISKLABEL:
760		print_kvpair_cstr(f, ts, "verify_method", "disklabel");
761		break;
762	case VERIFY_FFS:
763		print_kvpair_cstr(f, ts, "verify_method", "ffs");
764		break;
765	case VERIFY_REENTER:
766		print_kvpair_cstr(f, ts, "verify_method", "re-enter");
767		break;
768	default:
769		warnx("unsupported verify_method (%d)", p->verify_method);
770		return -1;
771	}
772	return keygen_fput(p->keygen, TAB_COL, f);
773}
774
775int
776params_cput(struct params *p, const char *fn)
777{
778	FILE	*f;
779
780	if (fn && *fn) {
781		if ((f = fopen(fn, "w")) == NULL) {
782			warn("could not open outfile \"%s\"", fn);
783			return -1;
784		}
785	} else {
786		f = stdout;
787	}
788	return params_fput(p, f);
789}
790
791static int
792crypt_defaults_lookup(const char *alg)
793{
794	unsigned	i;
795
796	for (i=0; i < (sizeof(crypto_defaults) / sizeof(crypto_defaults[0])); i++)
797		if (!strcmp(alg, crypto_defaults[i].alg))
798			return i;
799
800	return -1;
801}
802