1 /* $NetBSD: algorithm.c,v 1.10 2021/08/09 19:57:57 andvar Exp $ */
2
3 /* Id: algorithm.c,v 1.15 2006/05/23 20:23:09 manubsd Exp */
4
5 /*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #include "config.h"
35
36 #include <sys/param.h>
37 #include <sys/types.h>
38 #include <stdlib.h>
39
40 #include "var.h"
41 #include "misc.h"
42 #include "vmbuf.h"
43 #include "plog.h"
44 #include "debug.h"
45
46 #include "crypto_openssl.h"
47 #include "dhgroup.h"
48 #include "algorithm.h"
49 #include "oakley.h"
50 #include "isakmp_var.h"
51 #include "isakmp.h"
52 #include "ipsec_doi.h"
53 #include "gcmalloc.h"
54
55 static struct hash_algorithm oakley_hashdef[] = {
56 { "md5", algtype_md5, OAKLEY_ATTR_HASH_ALG_MD5,
57 eay_md5_init, eay_md5_update,
58 eay_md5_final, eay_md5_hashlen,
59 eay_md5_one, },
60 { "sha1", algtype_sha1, OAKLEY_ATTR_HASH_ALG_SHA,
61 eay_sha1_init, eay_sha1_update,
62 eay_sha1_final, eay_sha1_hashlen,
63 eay_sha1_one, },
64 #ifdef WITH_SHA2
65 { "sha2_256", algtype_sha2_256, OAKLEY_ATTR_HASH_ALG_SHA2_256,
66 eay_sha2_256_init, eay_sha2_256_update,
67 eay_sha2_256_final, eay_sha2_256_hashlen,
68 eay_sha2_256_one, },
69 { "sha2_384", algtype_sha2_384, OAKLEY_ATTR_HASH_ALG_SHA2_384,
70 eay_sha2_384_init, eay_sha2_384_update,
71 eay_sha2_384_final, eay_sha2_384_hashlen,
72 eay_sha2_384_one, },
73 { "sha2_512", algtype_sha2_512, OAKLEY_ATTR_HASH_ALG_SHA2_512,
74 eay_sha2_512_init, eay_sha2_512_update,
75 eay_sha2_512_final, eay_sha2_512_hashlen,
76 eay_sha2_512_one, },
77 #endif
78 };
79
80 static struct hmac_algorithm oakley_hmacdef[] = {
81 { "hmac_md5", algtype_md5, OAKLEY_ATTR_HASH_ALG_MD5,
82 eay_hmacmd5_init, eay_hmacmd5_update,
83 eay_hmacmd5_final, NULL,
84 eay_hmacmd5_one, },
85 { "hmac_sha1", algtype_sha1, OAKLEY_ATTR_HASH_ALG_SHA,
86 eay_hmacsha1_init, eay_hmacsha1_update,
87 eay_hmacsha1_final, NULL,
88 eay_hmacsha1_one, },
89 #ifdef WITH_SHA2
90 { "hmac_sha2_256", algtype_sha2_256, OAKLEY_ATTR_HASH_ALG_SHA2_256,
91 eay_hmacsha2_256_init, eay_hmacsha2_256_update,
92 eay_hmacsha2_256_final, NULL,
93 eay_hmacsha2_256_one, },
94 { "hmac_sha2_384", algtype_sha2_384, OAKLEY_ATTR_HASH_ALG_SHA2_384,
95 eay_hmacsha2_384_init, eay_hmacsha2_384_update,
96 eay_hmacsha2_384_final, NULL,
97 eay_hmacsha2_384_one, },
98 { "hmac_sha2_512", algtype_sha2_512, OAKLEY_ATTR_HASH_ALG_SHA2_512,
99 eay_hmacsha2_512_init, eay_hmacsha2_512_update,
100 eay_hmacsha2_512_final, NULL,
101 eay_hmacsha2_512_one, },
102 #endif
103 };
104
105 static struct enc_algorithm oakley_encdef[] = {
106 { "des", algtype_des, OAKLEY_ATTR_ENC_ALG_DES, 8,
107 eay_des_encrypt, eay_des_decrypt,
108 eay_des_weakkey, eay_des_keylen, },
109 #ifdef HAVE_OPENSSL_IDEA_H
110 { "idea", algtype_idea, OAKLEY_ATTR_ENC_ALG_IDEA, 8,
111 eay_idea_encrypt, eay_idea_decrypt,
112 eay_idea_weakkey, eay_idea_keylen, },
113 #endif
114 { "blowfish", algtype_blowfish, OAKLEY_ATTR_ENC_ALG_BLOWFISH, 8,
115 eay_bf_encrypt, eay_bf_decrypt,
116 eay_bf_weakkey, eay_bf_keylen, },
117 #ifdef HAVE_OPENSSL_RC5_H
118 { "rc5", algtype_rc5, OAKLEY_ATTR_ENC_ALG_RC5, 8,
119 eay_rc5_encrypt, eay_rc5_decrypt,
120 eay_rc5_weakkey, eay_rc5_keylen, },
121 #endif
122 { "3des", algtype_3des, OAKLEY_ATTR_ENC_ALG_3DES, 8,
123 eay_3des_encrypt, eay_3des_decrypt,
124 eay_3des_weakkey, eay_3des_keylen, },
125 { "cast", algtype_cast128, OAKLEY_ATTR_ENC_ALG_CAST, 8,
126 eay_cast_encrypt, eay_cast_decrypt,
127 eay_cast_weakkey, eay_cast_keylen, },
128 { "aes", algtype_aes, OAKLEY_ATTR_ENC_ALG_AES, 16,
129 eay_aes_encrypt, eay_aes_decrypt,
130 eay_aes_weakkey, eay_aes_keylen, },
131 #ifdef HAVE_OPENSSL_CAMELLIA_H
132 { "camellia", algtype_camellia, OAKLEY_ATTR_ENC_ALG_CAMELLIA, 16,
133 eay_camellia_encrypt, eay_camellia_decrypt,
134 eay_camellia_weakkey, eay_camellia_keylen, },
135 #endif
136 };
137
138 static struct enc_algorithm ipsec_encdef[] = {
139 { "des-iv64", algtype_des_iv64, IPSECDOI_ESP_DES_IV64, 8,
140 NULL, NULL,
141 NULL, eay_des_keylen, },
142 { "des", algtype_des, IPSECDOI_ESP_DES, 8,
143 NULL, NULL,
144 NULL, eay_des_keylen, },
145 { "3des", algtype_3des, IPSECDOI_ESP_3DES, 8,
146 NULL, NULL,
147 NULL, eay_3des_keylen, },
148 #ifdef HAVE_OPENSSL_RC5_H
149 { "rc5", algtype_rc5, IPSECDOI_ESP_RC5, 8,
150 NULL, NULL,
151 NULL, eay_rc5_keylen, },
152 #endif
153 { "cast", algtype_cast128, IPSECDOI_ESP_CAST, 8,
154 NULL, NULL,
155 NULL, eay_cast_keylen, },
156 { "blowfish", algtype_blowfish, IPSECDOI_ESP_BLOWFISH, 8,
157 NULL, NULL,
158 NULL, eay_bf_keylen, },
159 { "des-iv32", algtype_des_iv32, IPSECDOI_ESP_DES_IV32, 8,
160 NULL, NULL,
161 NULL, eay_des_keylen, },
162 { "null", algtype_null_enc, IPSECDOI_ESP_NULL, 8,
163 NULL, NULL,
164 NULL, eay_null_keylen, },
165 { "aes", algtype_aes, IPSECDOI_ESP_AES, 16,
166 NULL, NULL,
167 NULL, eay_aes_keylen, },
168 { "aes_gcm_16", algtype_aesgcm16, IPSECDOI_ESP_AESGCM16, 16,
169 NULL, NULL,
170 NULL, eay_aesgcm_keylen, },
171 { "twofish", algtype_twofish, IPSECDOI_ESP_TWOFISH, 16,
172 NULL, NULL,
173 NULL, eay_twofish_keylen, },
174 #ifdef HAVE_OPENSSL_IDEA_H
175 { "3idea", algtype_3idea, IPSECDOI_ESP_3IDEA, 8,
176 NULL, NULL,
177 NULL, NULL, },
178 { "idea", algtype_idea, IPSECDOI_ESP_IDEA, 8,
179 NULL, NULL,
180 NULL, NULL, },
181 #endif
182 { "rc4", algtype_rc4, IPSECDOI_ESP_RC4, 8,
183 NULL, NULL,
184 NULL, NULL, },
185 #ifdef HAVE_OPENSSL_CAMELLIA_H
186 { "camellia", algtype_camellia, IPSECDOI_ESP_CAMELLIA, 16,
187 NULL, NULL,
188 NULL, eay_camellia_keylen, },
189 #endif
190 };
191
192 static struct hmac_algorithm ipsec_hmacdef[] = {
193 { "md5", algtype_hmac_md5, IPSECDOI_ATTR_AUTH_HMAC_MD5,
194 NULL, NULL,
195 NULL, eay_md5_hashlen,
196 NULL, },
197 { "sha1", algtype_hmac_sha1, IPSECDOI_ATTR_AUTH_HMAC_SHA1,
198 NULL, NULL,
199 NULL, eay_sha1_hashlen,
200 NULL, },
201 { "kpdk", algtype_kpdk, IPSECDOI_ATTR_AUTH_KPDK,
202 NULL, NULL,
203 NULL, eay_kpdk_hashlen,
204 NULL, },
205 { "null", algtype_non_auth, IPSECDOI_ATTR_AUTH_NONE,
206 NULL, NULL,
207 NULL, eay_null_hashlen,
208 NULL, },
209 #ifdef WITH_SHA2
210 { "hmac_sha2_256", algtype_hmac_sha2_256,IPSECDOI_ATTR_AUTH_HMAC_SHA2_256,
211 NULL, NULL,
212 NULL, eay_sha2_256_hashlen,
213 NULL, },
214 { "hmac_sha2_384", algtype_hmac_sha2_384,IPSECDOI_ATTR_AUTH_HMAC_SHA2_384,
215 NULL, NULL,
216 NULL, eay_sha2_384_hashlen,
217 NULL, },
218 { "hmac_sha2_512", algtype_hmac_sha2_512,IPSECDOI_ATTR_AUTH_HMAC_SHA2_512,
219 NULL, NULL,
220 NULL, eay_sha2_512_hashlen,
221 NULL, },
222 #endif
223 };
224
225 static struct misc_algorithm ipsec_compdef[] = {
226 { "oui", algtype_oui, IPSECDOI_IPCOMP_OUI, },
227 { "deflate", algtype_deflate, IPSECDOI_IPCOMP_DEFLATE, },
228 { "lzs", algtype_lzs, IPSECDOI_IPCOMP_LZS, },
229 };
230
231 /*
232 * In case of asymmetric modes (hybrid xauth), what's racoon mode of
233 * operations ; it seems that the proposal should always use the
234 * initiator half (unless a server initiates a connection, which is
235 * not handled, and probably not useful).
236 */
237 static struct misc_algorithm oakley_authdef[] = {
238 { "pre_shared_key", algtype_psk, OAKLEY_ATTR_AUTH_METHOD_PSKEY, },
239 { "dsssig", algtype_dsssig, OAKLEY_ATTR_AUTH_METHOD_DSSSIG, },
240 { "rsasig", algtype_rsasig, OAKLEY_ATTR_AUTH_METHOD_RSASIG, },
241 { "rsaenc", algtype_rsaenc, OAKLEY_ATTR_AUTH_METHOD_RSAENC, },
242 { "rsarev", algtype_rsarev, OAKLEY_ATTR_AUTH_METHOD_RSAREV, },
243
244 { "gssapi_krb", algtype_gssapikrb,
245 OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB, },
246
247 #ifdef ENABLE_HYBRID
248 { "hybrid_rsa_server", algtype_hybrid_rsa_s,
249 OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R, },
250
251 { "hybrid_dss_server", algtype_hybrid_dss_s,
252 OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R, },
253
254 { "xauth_psk_server", algtype_xauth_psk_s,
255 OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R, },
256
257 { "xauth_rsa_server", algtype_xauth_rsa_s,
258 OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R, },
259
260 { "hybrid_rsa_client", algtype_hybrid_rsa_c,
261 OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I, },
262
263 { "hybrid_dss_client", algtype_hybrid_dss_c,
264 OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I, },
265
266 { "xauth_psk_client", algtype_xauth_psk_c,
267 OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I, },
268
269 { "xauth_rsa_client", algtype_xauth_rsa_c,
270 OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I, },
271 #endif
272 };
273
274 static struct dh_algorithm oakley_dhdef[] = {
275 { "modp768", algtype_modp768, OAKLEY_ATTR_GRP_DESC_MODP768,
276 &dh_modp768, },
277 { "modp1024", algtype_modp1024, OAKLEY_ATTR_GRP_DESC_MODP1024,
278 &dh_modp1024, },
279 { "modp1536", algtype_modp1536, OAKLEY_ATTR_GRP_DESC_MODP1536,
280 &dh_modp1536, },
281 { "modp2048", algtype_modp2048, OAKLEY_ATTR_GRP_DESC_MODP2048,
282 &dh_modp2048, },
283 { "modp3072", algtype_modp3072, OAKLEY_ATTR_GRP_DESC_MODP3072,
284 &dh_modp3072, },
285 { "modp4096", algtype_modp4096, OAKLEY_ATTR_GRP_DESC_MODP4096,
286 &dh_modp4096, },
287 { "modp6144", algtype_modp6144, OAKLEY_ATTR_GRP_DESC_MODP6144,
288 &dh_modp6144, },
289 { "modp8192", algtype_modp8192, OAKLEY_ATTR_GRP_DESC_MODP8192,
290 &dh_modp8192, },
291 };
292
293 static struct hash_algorithm *alg_oakley_hashdef __P((int));
294 static struct hmac_algorithm *alg_oakley_hmacdef __P((int));
295 static struct enc_algorithm *alg_oakley_encdef __P((int));
296 static struct enc_algorithm *alg_ipsec_encdef __P((int));
297 static struct hmac_algorithm *alg_ipsec_hmacdef __P((int));
298 static struct dh_algorithm *alg_oakley_dhdef __P((int));
299
300 /* oakley hash algorithm */
301 static struct hash_algorithm *
alg_oakley_hashdef(doi)302 alg_oakley_hashdef(doi)
303 int doi;
304 {
305 int i;
306
307 for (i = 0; i < ARRAYLEN(oakley_hashdef); i++)
308 if (doi == oakley_hashdef[i].doi) {
309 plog(LLV_DEBUG, LOCATION, NULL, "hash(%s)\n",
310 oakley_hashdef[i].name);
311 return &oakley_hashdef[i];
312 }
313 return NULL;
314 }
315
316 int
alg_oakley_hashdef_ok(doi)317 alg_oakley_hashdef_ok(doi)
318 int doi;
319 {
320 struct hash_algorithm *f;
321
322 f = alg_oakley_hashdef(doi);
323 if (f == NULL)
324 return 0;
325
326 return 1;
327 }
328
329 int
alg_oakley_hashdef_doi(type)330 alg_oakley_hashdef_doi(type)
331 int type;
332 {
333 int i, res = -1;
334
335 for (i = 0; i < ARRAYLEN(oakley_hashdef); i++)
336 if (type == oakley_hashdef[i].type) {
337 res = oakley_hashdef[i].doi;
338 break;
339 }
340 return res;
341 }
342
343 int
alg_oakley_hashdef_hashlen(doi)344 alg_oakley_hashdef_hashlen(doi)
345 int doi;
346 {
347 struct hash_algorithm *f;
348
349 f = alg_oakley_hashdef(doi);
350 if (f == NULL || f->hashlen == NULL)
351 return 0;
352
353 return (f->hashlen)();
354 }
355
356 const char *
alg_oakley_hashdef_name(doi)357 alg_oakley_hashdef_name (doi)
358 int doi;
359 {
360 struct hash_algorithm *f;
361
362 f = alg_oakley_hashdef(doi);
363 if (f == NULL)
364 return "*UNKNOWN*";
365
366 return f->name;
367 }
368
369 vchar_t *
alg_oakley_hashdef_one(doi,buf)370 alg_oakley_hashdef_one(doi, buf)
371 int doi;
372 vchar_t *buf;
373 {
374 struct hash_algorithm *f;
375
376 f = alg_oakley_hashdef(doi);
377 if (f == NULL || f->hashlen == NULL)
378 return NULL;
379
380 return (f->one)(buf);
381 }
382
383 /* oakley hmac algorithm */
384 static struct hmac_algorithm *
alg_oakley_hmacdef(doi)385 alg_oakley_hmacdef(doi)
386 int doi;
387 {
388 int i;
389
390 for (i = 0; i < ARRAYLEN(oakley_hmacdef); i++)
391 if (doi == oakley_hmacdef[i].doi) {
392 plog(LLV_DEBUG, LOCATION, NULL, "hmac(%s)\n",
393 oakley_hmacdef[i].name);
394 return &oakley_hmacdef[i];
395 }
396 return NULL;
397 }
398
399 int
alg_oakley_hmacdef_doi(type)400 alg_oakley_hmacdef_doi(type)
401 int type;
402 {
403 int i, res = -1;
404
405 for (i = 0; i < ARRAYLEN(oakley_hmacdef); i++)
406 if (type == oakley_hmacdef[i].type) {
407 res = oakley_hmacdef[i].doi;
408 break;
409 }
410 return res;
411 }
412
413 vchar_t *
alg_oakley_hmacdef_one(doi,key,buf)414 alg_oakley_hmacdef_one(doi, key, buf)
415 int doi;
416 vchar_t *key, *buf;
417 {
418 struct hmac_algorithm *f;
419 vchar_t *res;
420 #ifdef ENABLE_STATS
421 struct timeval start, end;
422 #endif
423
424 f = alg_oakley_hmacdef(doi);
425 if (f == NULL || f->one == NULL)
426 return NULL;
427
428 #ifdef ENABLE_STATS
429 gettimeofday(&start, NULL);
430 #endif
431
432 res = (f->one)(key, buf);
433
434 #ifdef ENABLE_STATS
435 gettimeofday(&end, NULL);
436 syslog(LOG_NOTICE, "%s(%s size=%zu): %8.6f", __func__,
437 f->name, buf->l, timedelta(&start, &end));
438 #endif
439
440 return res;
441 }
442
443 /* oakley encryption algorithm */
444 static struct enc_algorithm *
alg_oakley_encdef(doi)445 alg_oakley_encdef(doi)
446 int doi;
447 {
448 int i;
449
450 for (i = 0; i < ARRAYLEN(oakley_encdef); i++)
451 if (doi == oakley_encdef[i].doi) {
452 plog(LLV_DEBUG, LOCATION, NULL, "encryption(%s)\n",
453 oakley_encdef[i].name);
454 return &oakley_encdef[i];
455 }
456 return NULL;
457 }
458
459 int
alg_oakley_encdef_ok(doi)460 alg_oakley_encdef_ok(doi)
461 int doi;
462 {
463 struct enc_algorithm *f;
464
465 f = alg_oakley_encdef(doi);
466 if (f == NULL)
467 return 0;
468
469 return 1;
470 }
471
472 int
alg_oakley_encdef_doi(type)473 alg_oakley_encdef_doi(type)
474 int type;
475 {
476 int i, res = -1;
477
478 for (i = 0; i < ARRAYLEN(oakley_encdef); i++)
479 if (type == oakley_encdef[i].type) {
480 res = oakley_encdef[i].doi;
481 break;
482 }
483 return res;
484 }
485
486 int
alg_oakley_encdef_keylen(doi,len)487 alg_oakley_encdef_keylen(doi, len)
488 int doi, len;
489 {
490 struct enc_algorithm *f;
491
492 f = alg_oakley_encdef(doi);
493 if (f == NULL || f->keylen == NULL)
494 return -1;
495
496 return (f->keylen)(len);
497 }
498
499 int
alg_oakley_encdef_blocklen(doi)500 alg_oakley_encdef_blocklen(doi)
501 int doi;
502 {
503 struct enc_algorithm *f;
504
505 f = alg_oakley_encdef(doi);
506 if (f == NULL)
507 return -1;
508
509 return f->blocklen;
510 }
511
512 const char *
alg_oakley_encdef_name(doi)513 alg_oakley_encdef_name (doi)
514 int doi;
515 {
516 struct enc_algorithm *f;
517
518 f = alg_oakley_encdef(doi);
519 if (f == NULL)
520 return "*UNKNOWN*";
521
522 return f->name;
523 }
524
525 vchar_t *
alg_oakley_encdef_decrypt(doi,buf,key,iv)526 alg_oakley_encdef_decrypt(doi, buf, key, iv)
527 int doi;
528 vchar_t *buf, *key, *iv;
529 {
530 vchar_t *res;
531 struct enc_algorithm *f;
532 #ifdef ENABLE_STATS
533 struct timeval start, end;
534 #endif
535
536 f = alg_oakley_encdef(doi);
537 if (f == NULL || f->decrypt == NULL)
538 return NULL;
539
540 #ifdef ENABLE_STATS
541 gettimeofday(&start, NULL);
542 #endif
543
544 res = (f->decrypt)(buf, key, iv);
545
546 #ifdef ENABLE_STATS
547 gettimeofday(&end, NULL);
548 syslog(LOG_NOTICE, "%s(%s klen=%zu size=%zu): %8.6f", __func__,
549 f->name, key->l << 3, buf->l, timedelta(&start, &end));
550 #endif
551 return res;
552 }
553
554 vchar_t *
alg_oakley_encdef_encrypt(doi,buf,key,iv)555 alg_oakley_encdef_encrypt(doi, buf, key, iv)
556 int doi;
557 vchar_t *buf, *key, *iv;
558 {
559 vchar_t *res;
560 struct enc_algorithm *f;
561 #ifdef ENABLE_STATS
562 struct timeval start, end;
563 #endif
564
565 f = alg_oakley_encdef(doi);
566 if (f == NULL || f->encrypt == NULL)
567 return NULL;
568
569 #ifdef ENABLE_STATS
570 gettimeofday(&start, NULL);
571 #endif
572
573 res = (f->encrypt)(buf, key, iv);
574
575 #ifdef ENABLE_STATS
576 gettimeofday(&end, NULL);
577 syslog(LOG_NOTICE, "%s(%s klen=%zu size=%zu): %8.6f", __func__,
578 f->name, key->l << 3, buf->l, timedelta(&start, &end));
579 #endif
580 return res;
581 }
582
583 /* ipsec encryption algorithm */
584 static struct enc_algorithm *
alg_ipsec_encdef(doi)585 alg_ipsec_encdef(doi)
586 int doi;
587 {
588 int i;
589
590 for (i = 0; i < ARRAYLEN(ipsec_encdef); i++)
591 if (doi == ipsec_encdef[i].doi) {
592 plog(LLV_DEBUG, LOCATION, NULL, "encryption(%s)\n",
593 ipsec_encdef[i].name);
594 return &ipsec_encdef[i];
595 }
596 return NULL;
597 }
598
599 int
alg_ipsec_encdef_doi(type)600 alg_ipsec_encdef_doi(type)
601 int type;
602 {
603 int i, res = -1;
604
605 for (i = 0; i < ARRAYLEN(ipsec_encdef); i++)
606 if (type == ipsec_encdef[i].type) {
607 res = ipsec_encdef[i].doi;
608 break;
609 }
610 return res;
611 }
612
613 int
alg_ipsec_encdef_keylen(doi,len)614 alg_ipsec_encdef_keylen(doi, len)
615 int doi, len;
616 {
617 struct enc_algorithm *f;
618
619 f = alg_ipsec_encdef(doi);
620 if (f == NULL || f->keylen == NULL)
621 return -1;
622
623 return (f->keylen)(len);
624 }
625
626 /* ipsec hmac algorithm */
627 static struct hmac_algorithm *
alg_ipsec_hmacdef(doi)628 alg_ipsec_hmacdef(doi)
629 int doi;
630 {
631 int i;
632
633 for (i = 0; i < ARRAYLEN(ipsec_hmacdef); i++)
634 if (doi == ipsec_hmacdef[i].doi) {
635 plog(LLV_DEBUG, LOCATION, NULL, "hmac(%s)\n",
636 ipsec_hmacdef[i].name);
637 return &ipsec_hmacdef[i];
638 }
639 return NULL;
640 }
641
642 int
alg_ipsec_hmacdef_doi(type)643 alg_ipsec_hmacdef_doi(type)
644 int type;
645 {
646 int i, res = -1;
647
648 for (i = 0; i < ARRAYLEN(ipsec_hmacdef); i++)
649 if (type == ipsec_hmacdef[i].type) {
650 res = ipsec_hmacdef[i].doi;
651 break;
652 }
653 return res;
654 }
655
656 int
alg_ipsec_hmacdef_hashlen(doi)657 alg_ipsec_hmacdef_hashlen(doi)
658 int doi;
659 {
660 struct hmac_algorithm *f;
661
662 f = alg_ipsec_hmacdef(doi);
663 if (f == NULL || f->hashlen == NULL)
664 return -1;
665
666 return (f->hashlen)();
667 }
668
669 /* ip compression */
670 int
alg_ipsec_compdef_doi(type)671 alg_ipsec_compdef_doi(type)
672 int type;
673 {
674 int i, res = -1;
675
676 for (i = 0; i < ARRAYLEN(ipsec_compdef); i++)
677 if (type == ipsec_compdef[i].type) {
678 res = ipsec_compdef[i].doi;
679 break;
680 }
681 return res;
682 }
683
684 /* dh algorithm */
685 static struct dh_algorithm *
alg_oakley_dhdef(doi)686 alg_oakley_dhdef(doi)
687 int doi;
688 {
689 int i;
690
691 for (i = 0; i < ARRAYLEN(oakley_dhdef); i++)
692 if (doi == oakley_dhdef[i].doi) {
693 plog(LLV_DEBUG, LOCATION, NULL, "hmac(%s)\n",
694 oakley_dhdef[i].name);
695 return &oakley_dhdef[i];
696 }
697 return NULL;
698 }
699
700 int
alg_oakley_dhdef_ok(doi)701 alg_oakley_dhdef_ok(doi)
702 int doi;
703 {
704 struct dh_algorithm *f;
705
706 f = alg_oakley_dhdef(doi);
707 if (f == NULL)
708 return 0;
709
710 return 1;
711 }
712
713 int
alg_oakley_dhdef_doi(type)714 alg_oakley_dhdef_doi(type)
715 int type;
716 {
717 int i, res = -1;
718
719 for (i = 0; i < ARRAYLEN(oakley_dhdef); i++)
720 if (type == oakley_dhdef[i].type) {
721 res = oakley_dhdef[i].doi;
722 break;
723 }
724 return res;
725 }
726
727 struct dhgroup *
alg_oakley_dhdef_group(doi)728 alg_oakley_dhdef_group(doi)
729 int doi;
730 {
731 struct dh_algorithm *f;
732
733 f = alg_oakley_dhdef(doi);
734 if (f == NULL || f->dhgroup == NULL)
735 return NULL;
736
737 return f->dhgroup;
738 }
739
740 const char *
alg_oakley_dhdef_name(doi)741 alg_oakley_dhdef_name (doi)
742 int doi;
743 {
744 struct dh_algorithm *f;
745
746 f = alg_oakley_dhdef(doi);
747 if (f == NULL)
748 return "*UNKNOWN*";
749 return f->name;
750 }
751
752 /* authentication method */
753 int
alg_oakley_authdef_doi(type)754 alg_oakley_authdef_doi(type)
755 int type;
756 {
757 int i, res = -1;
758
759 for (i = 0; i < ARRAYLEN(oakley_authdef); i++)
760 if (type == oakley_authdef[i].type) {
761 res = oakley_authdef[i].doi;
762 break;
763 }
764 return res;
765 }
766
767 const char *
alg_oakley_authdef_name(doi)768 alg_oakley_authdef_name (doi)
769 int doi;
770 {
771 int i;
772
773 for (i = 0; i < ARRAYLEN(oakley_authdef); i++)
774 if (doi == oakley_authdef[i].doi) {
775 return oakley_authdef[i].name;
776 }
777 return "*UNKNOWN*";
778 }
779
780 /*
781 * give the default key length
782 * OUT: -1: NG
783 * 0: fixed key cipher, key length not allowed
784 * positive: default key length
785 */
786 int
default_keylen(class,type)787 default_keylen(class, type)
788 int class, type;
789 {
790
791 switch (class) {
792 case algclass_isakmp_enc:
793 case algclass_ipsec_enc:
794 break;
795 default:
796 return 0;
797 }
798
799 switch (type) {
800 case algtype_blowfish:
801 case algtype_rc5:
802 case algtype_cast128:
803 case algtype_aes:
804 case algtype_aesgcm16:
805 case algtype_twofish:
806 case algtype_camellia:
807 return 128;
808 default:
809 return 0;
810 }
811 }
812
813 /*
814 * check key length
815 * OUT: -1: NG
816 * 0: OK
817 */
818 int
check_keylen(class,type,len)819 check_keylen(class, type, len)
820 int class, type, len;
821 {
822 int badrange;
823
824 switch (class) {
825 case algclass_isakmp_enc:
826 case algclass_ipsec_enc:
827 break;
828 default:
829 /* unknown class, punt */
830 plog(LLV_ERROR, LOCATION, NULL,
831 "unknown algclass %d\n", class);
832 return -1;
833 }
834
835 /* key length must be multiple of 8 bytes - RFC2451 2.2 */
836 switch (type) {
837 case algtype_blowfish:
838 case algtype_rc5:
839 case algtype_cast128:
840 case algtype_aes:
841 case algtype_aesgcm16:
842 case algtype_twofish:
843 case algtype_camellia:
844 if (len % 8 != 0) {
845 plog(LLV_ERROR, LOCATION, NULL,
846 "key length %d is not multiple of 8\n", len);
847 return -1;
848 }
849 break;
850 }
851
852 /* key length range */
853 badrange = 0;
854 switch (type) {
855 case algtype_blowfish:
856 if (len < 40 || 448 < len)
857 badrange++;
858 break;
859 case algtype_rc5:
860 if (len < 40 || 2040 < len)
861 badrange++;
862 break;
863 case algtype_cast128:
864 if (len < 40 || 128 < len)
865 badrange++;
866 break;
867 case algtype_aes:
868 if (!(len == 128 || len == 192 || len == 256))
869 badrange++;
870 break;
871 case algtype_aesgcm16:
872 if (!(len == 128 || len == 192 || len == 256))
873 badrange++;
874 break;
875 case algtype_twofish:
876 if (len < 40 || 256 < len)
877 badrange++;
878 break;
879 case algtype_camellia:
880 if (!(len == 128 || len == 192 || len == 256))
881 badrange++;
882 break;
883 default:
884 if (len) {
885 plog(LLV_ERROR, LOCATION, NULL,
886 "key length is not allowed");
887 return -1;
888 }
889 break;
890 }
891 if (badrange) {
892 plog(LLV_ERROR, LOCATION, NULL,
893 "key length out of range\n");
894 return -1;
895 }
896
897 return 0;
898 }
899
900 /*
901 * convert algorithm type to DOI value.
902 * OUT -1 : NG
903 * other: converted.
904 */
905 int
algtype2doi(class,type)906 algtype2doi(class, type)
907 int class, type;
908 {
909 int res = -1;
910
911 switch (class) {
912 case algclass_ipsec_enc:
913 res = alg_ipsec_encdef_doi(type);
914 break;
915 case algclass_ipsec_auth:
916 res = alg_ipsec_hmacdef_doi(type);
917 break;
918 case algclass_ipsec_comp:
919 res = alg_ipsec_compdef_doi(type);
920 break;
921 case algclass_isakmp_enc:
922 res = alg_oakley_encdef_doi(type);
923 break;
924 case algclass_isakmp_hash:
925 res = alg_oakley_hashdef_doi(type);
926 break;
927 case algclass_isakmp_dh:
928 res = alg_oakley_dhdef_doi(type);
929 break;
930 case algclass_isakmp_ameth:
931 res = alg_oakley_authdef_doi(type);
932 break;
933 }
934 return res;
935 }
936
937 /*
938 * convert algorithm class to DOI value.
939 * OUT -1 : NG
940 * other: converted.
941 */
942 int
algclass2doi(class)943 algclass2doi(class)
944 int class;
945 {
946 switch (class) {
947 case algclass_ipsec_enc:
948 return IPSECDOI_PROTO_IPSEC_ESP;
949 case algclass_ipsec_auth:
950 return IPSECDOI_ATTR_AUTH;
951 case algclass_ipsec_comp:
952 return IPSECDOI_PROTO_IPCOMP;
953 case algclass_isakmp_enc:
954 return OAKLEY_ATTR_ENC_ALG;
955 case algclass_isakmp_hash:
956 return OAKLEY_ATTR_HASH_ALG;
957 case algclass_isakmp_dh:
958 return OAKLEY_ATTR_GRP_DESC;
959 case algclass_isakmp_ameth:
960 return OAKLEY_ATTR_AUTH_METHOD;
961 default:
962 return -1;
963 }
964 /*NOTREACHED*/
965 return -1;
966 }
967