1 /* $NetBSD: algorithm.c,v 1.12 2025/03/08 16:39:08 christos 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(int);
294 static struct hmac_algorithm *alg_oakley_hmacdef(int);
295 static struct enc_algorithm *alg_oakley_encdef(int);
296 static struct enc_algorithm *alg_ipsec_encdef(int);
297 static struct hmac_algorithm *alg_ipsec_hmacdef(int);
298 static struct dh_algorithm *alg_oakley_dhdef(int);
299
300 /* oakley hash algorithm */
301 static struct hash_algorithm *
alg_oakley_hashdef(int doi)302 alg_oakley_hashdef(int doi)
303 {
304
305 for (size_t i = 0; i < ARRAYLEN(oakley_hashdef); i++)
306 if (doi == oakley_hashdef[i].doi) {
307 plog(LLV_DEBUG, LOCATION, NULL, "hash(%s)\n",
308 oakley_hashdef[i].name);
309 return &oakley_hashdef[i];
310 }
311 return NULL;
312 }
313
314 int
alg_oakley_hashdef_ok(int doi)315 alg_oakley_hashdef_ok(int doi)
316 {
317 struct hash_algorithm *f;
318
319 f = alg_oakley_hashdef(doi);
320 if (f == NULL)
321 return 0;
322
323 return 1;
324 }
325
326 int
alg_oakley_hashdef_doi(int type)327 alg_oakley_hashdef_doi(int type)
328 {
329 int res = -1;
330
331 for (size_t i = 0; i < ARRAYLEN(oakley_hashdef); i++)
332 if (type == oakley_hashdef[i].type) {
333 res = oakley_hashdef[i].doi;
334 break;
335 }
336 return res;
337 }
338
339 int
alg_oakley_hashdef_hashlen(int doi)340 alg_oakley_hashdef_hashlen(int doi)
341 {
342 struct hash_algorithm *f;
343
344 f = alg_oakley_hashdef(doi);
345 if (f == NULL || f->hashlen == NULL)
346 return 0;
347
348 return (f->hashlen)();
349 }
350
351 const char *
alg_oakley_hashdef_name(int doi)352 alg_oakley_hashdef_name(int doi)
353 {
354 struct hash_algorithm *f;
355
356 f = alg_oakley_hashdef(doi);
357 if (f == NULL)
358 return "*UNKNOWN*";
359
360 return f->name;
361 }
362
363 vchar_t *
alg_oakley_hashdef_one(int doi,vchar_t * buf)364 alg_oakley_hashdef_one(int doi, vchar_t *buf)
365 {
366 struct hash_algorithm *f;
367
368 f = alg_oakley_hashdef(doi);
369 if (f == NULL || f->hashlen == NULL)
370 return NULL;
371
372 return (f->one)(buf);
373 }
374
375 /* oakley hmac algorithm */
376 static struct hmac_algorithm *
alg_oakley_hmacdef(int doi)377 alg_oakley_hmacdef(int doi)
378 {
379
380 for (size_t i = 0; i < ARRAYLEN(oakley_hmacdef); i++)
381 if (doi == oakley_hmacdef[i].doi) {
382 plog(LLV_DEBUG, LOCATION, NULL, "hmac(%s)\n",
383 oakley_hmacdef[i].name);
384 return &oakley_hmacdef[i];
385 }
386 return NULL;
387 }
388
389 int
alg_oakley_hmacdef_doi(int type)390 alg_oakley_hmacdef_doi(int type)
391 {
392 int res = -1;
393
394 for (size_t i = 0; i < ARRAYLEN(oakley_hmacdef); i++)
395 if (type == oakley_hmacdef[i].type) {
396 res = oakley_hmacdef[i].doi;
397 break;
398 }
399 return res;
400 }
401
402 vchar_t *
alg_oakley_hmacdef_one(int doi,vchar_t * key,vchar_t * buf)403 alg_oakley_hmacdef_one(int doi, vchar_t *key, vchar_t *buf)
404 {
405 struct hmac_algorithm *f;
406 vchar_t *res;
407 #ifdef ENABLE_STATS
408 struct timeval start, end;
409 #endif
410
411 f = alg_oakley_hmacdef(doi);
412 if (f == NULL || f->one == NULL)
413 return NULL;
414
415 #ifdef ENABLE_STATS
416 gettimeofday(&start, NULL);
417 #endif
418
419 res = (f->one)(key, buf);
420
421 #ifdef ENABLE_STATS
422 gettimeofday(&end, NULL);
423 syslog(LOG_NOTICE, "%s(%s size=%zu): %8.6f", __func__,
424 f->name, buf->l, timedelta(&start, &end));
425 #endif
426
427 return res;
428 }
429
430 /* oakley encryption algorithm */
431 static struct enc_algorithm *
alg_oakley_encdef(int doi)432 alg_oakley_encdef(int doi)
433 {
434
435 for (size_t i = 0; i < ARRAYLEN(oakley_encdef); i++)
436 if (doi == oakley_encdef[i].doi) {
437 plog(LLV_DEBUG, LOCATION, NULL, "encryption(%s)\n",
438 oakley_encdef[i].name);
439 return &oakley_encdef[i];
440 }
441 return NULL;
442 }
443
444 int
alg_oakley_encdef_ok(int doi)445 alg_oakley_encdef_ok(int doi)
446 {
447 struct enc_algorithm *f;
448
449 f = alg_oakley_encdef(doi);
450 if (f == NULL)
451 return 0;
452
453 return 1;
454 }
455
456 int
alg_oakley_encdef_doi(int type)457 alg_oakley_encdef_doi(int type)
458 {
459 int res = -1;
460
461 for (size_t i = 0; i < ARRAYLEN(oakley_encdef); i++)
462 if (type == oakley_encdef[i].type) {
463 res = oakley_encdef[i].doi;
464 break;
465 }
466 return res;
467 }
468
469 int
alg_oakley_encdef_keylen(int doi,int len)470 alg_oakley_encdef_keylen(int doi, int len)
471 {
472 struct enc_algorithm *f;
473
474 f = alg_oakley_encdef(doi);
475 if (f == NULL || f->keylen == NULL)
476 return -1;
477
478 return (f->keylen)(len);
479 }
480
481 int
alg_oakley_encdef_blocklen(int doi)482 alg_oakley_encdef_blocklen(int doi)
483 {
484 struct enc_algorithm *f;
485
486 f = alg_oakley_encdef(doi);
487 if (f == NULL)
488 return -1;
489
490 return f->blocklen;
491 }
492
493 const char *
alg_oakley_encdef_name(int doi)494 alg_oakley_encdef_name(int doi)
495 {
496 struct enc_algorithm *f;
497
498 f = alg_oakley_encdef(doi);
499 if (f == NULL)
500 return "*UNKNOWN*";
501
502 return f->name;
503 }
504
505 vchar_t *
alg_oakley_encdef_decrypt(int doi,vchar_t * buf,vchar_t * key,vchar_t * iv)506 alg_oakley_encdef_decrypt(int doi, vchar_t *buf, vchar_t *key, vchar_t *iv)
507 {
508 vchar_t *res;
509 struct enc_algorithm *f;
510 #ifdef ENABLE_STATS
511 struct timeval start, end;
512 #endif
513
514 f = alg_oakley_encdef(doi);
515 if (f == NULL || f->decrypt == NULL)
516 return NULL;
517
518 #ifdef ENABLE_STATS
519 gettimeofday(&start, NULL);
520 #endif
521
522 res = (f->decrypt)(buf, key, iv);
523
524 #ifdef ENABLE_STATS
525 gettimeofday(&end, NULL);
526 syslog(LOG_NOTICE, "%s(%s klen=%zu size=%zu): %8.6f", __func__,
527 f->name, key->l << 3, buf->l, timedelta(&start, &end));
528 #endif
529 return res;
530 }
531
532 vchar_t *
alg_oakley_encdef_encrypt(int doi,vchar_t * buf,vchar_t * key,vchar_t * iv)533 alg_oakley_encdef_encrypt(int doi, vchar_t *buf, vchar_t *key, vchar_t *iv)
534 {
535 vchar_t *res;
536 struct enc_algorithm *f;
537 #ifdef ENABLE_STATS
538 struct timeval start, end;
539 #endif
540
541 f = alg_oakley_encdef(doi);
542 if (f == NULL || f->encrypt == NULL)
543 return NULL;
544
545 #ifdef ENABLE_STATS
546 gettimeofday(&start, NULL);
547 #endif
548
549 res = (f->encrypt)(buf, key, iv);
550
551 #ifdef ENABLE_STATS
552 gettimeofday(&end, NULL);
553 syslog(LOG_NOTICE, "%s(%s klen=%zu size=%zu): %8.6f", __func__,
554 f->name, key->l << 3, buf->l, timedelta(&start, &end));
555 #endif
556 return res;
557 }
558
559 /* ipsec encryption algorithm */
560 static struct enc_algorithm *
alg_ipsec_encdef(int doi)561 alg_ipsec_encdef(int doi)
562 {
563
564 for (size_t i = 0; i < ARRAYLEN(ipsec_encdef); i++)
565 if (doi == ipsec_encdef[i].doi) {
566 plog(LLV_DEBUG, LOCATION, NULL, "encryption(%s)\n",
567 ipsec_encdef[i].name);
568 return &ipsec_encdef[i];
569 }
570 return NULL;
571 }
572
573 int
alg_ipsec_encdef_doi(int type)574 alg_ipsec_encdef_doi(int type)
575 {
576 int res = -1;
577
578 for (size_t i = 0; i < ARRAYLEN(ipsec_encdef); i++)
579 if (type == ipsec_encdef[i].type) {
580 res = ipsec_encdef[i].doi;
581 break;
582 }
583 return res;
584 }
585
586 int
alg_ipsec_encdef_keylen(int doi,int len)587 alg_ipsec_encdef_keylen(int doi, int len)
588 {
589 struct enc_algorithm *f;
590
591 f = alg_ipsec_encdef(doi);
592 if (f == NULL || f->keylen == NULL)
593 return -1;
594
595 return (f->keylen)(len);
596 }
597
598 /* ipsec hmac algorithm */
599 static struct hmac_algorithm *
alg_ipsec_hmacdef(int doi)600 alg_ipsec_hmacdef(int doi)
601 {
602
603 for (size_t i = 0; i < ARRAYLEN(ipsec_hmacdef); i++)
604 if (doi == ipsec_hmacdef[i].doi) {
605 plog(LLV_DEBUG, LOCATION, NULL, "hmac(%s)\n",
606 ipsec_hmacdef[i].name);
607 return &ipsec_hmacdef[i];
608 }
609 return NULL;
610 }
611
612 int
alg_ipsec_hmacdef_doi(int type)613 alg_ipsec_hmacdef_doi(int type)
614 {
615 int res = -1;
616
617 for (size_t i = 0; i < ARRAYLEN(ipsec_hmacdef); i++)
618 if (type == ipsec_hmacdef[i].type) {
619 res = ipsec_hmacdef[i].doi;
620 break;
621 }
622 return res;
623 }
624
625 int
alg_ipsec_hmacdef_hashlen(int doi)626 alg_ipsec_hmacdef_hashlen(int doi)
627 {
628 struct hmac_algorithm *f;
629
630 f = alg_ipsec_hmacdef(doi);
631 if (f == NULL || f->hashlen == NULL)
632 return -1;
633
634 return (f->hashlen)();
635 }
636
637 /* ip compression */
638 int
alg_ipsec_compdef_doi(int type)639 alg_ipsec_compdef_doi(int type)
640 {
641 int res = -1;
642
643 for (size_t i = 0; i < ARRAYLEN(ipsec_compdef); i++)
644 if (type == ipsec_compdef[i].type) {
645 res = ipsec_compdef[i].doi;
646 break;
647 }
648 return res;
649 }
650
651 /* dh algorithm */
652 static struct dh_algorithm *
alg_oakley_dhdef(int doi)653 alg_oakley_dhdef(int doi)
654 {
655
656 for (size_t i = 0; i < ARRAYLEN(oakley_dhdef); i++)
657 if (doi == oakley_dhdef[i].doi) {
658 plog(LLV_DEBUG, LOCATION, NULL, "hmac(%s)\n",
659 oakley_dhdef[i].name);
660 return &oakley_dhdef[i];
661 }
662 return NULL;
663 }
664
665 int
alg_oakley_dhdef_ok(int doi)666 alg_oakley_dhdef_ok(int doi)
667 {
668 struct dh_algorithm *f;
669
670 f = alg_oakley_dhdef(doi);
671 if (f == NULL)
672 return 0;
673
674 return 1;
675 }
676
677 int
alg_oakley_dhdef_doi(int type)678 alg_oakley_dhdef_doi(int type)
679 {
680 int res = -1;
681
682 for (size_t i = 0; i < ARRAYLEN(oakley_dhdef); i++)
683 if (type == oakley_dhdef[i].type) {
684 res = oakley_dhdef[i].doi;
685 break;
686 }
687 return res;
688 }
689
690 struct dhgroup *
alg_oakley_dhdef_group(int doi)691 alg_oakley_dhdef_group(int doi)
692 {
693 struct dh_algorithm *f;
694
695 f = alg_oakley_dhdef(doi);
696 if (f == NULL || f->dhgroup == NULL)
697 return NULL;
698
699 return f->dhgroup;
700 }
701
702 const char *
alg_oakley_dhdef_name(int doi)703 alg_oakley_dhdef_name(int doi)
704 {
705 struct dh_algorithm *f;
706
707 f = alg_oakley_dhdef(doi);
708 if (f == NULL)
709 return "*UNKNOWN*";
710 return f->name;
711 }
712
713 /* authentication method */
714 int
alg_oakley_authdef_doi(int type)715 alg_oakley_authdef_doi(int type)
716 {
717 int res = -1;
718
719 for (size_t i = 0; i < ARRAYLEN(oakley_authdef); i++)
720 if (type == oakley_authdef[i].type) {
721 res = oakley_authdef[i].doi;
722 break;
723 }
724 return res;
725 }
726
727 const char *
alg_oakley_authdef_name(int doi)728 alg_oakley_authdef_name(int doi)
729 {
730
731 for (size_t i = 0; i < ARRAYLEN(oakley_authdef); i++)
732 if (doi == oakley_authdef[i].doi) {
733 return oakley_authdef[i].name;
734 }
735 return "*UNKNOWN*";
736 }
737
738 /*
739 * give the default key length
740 * OUT: -1: NG
741 * 0: fixed key cipher, key length not allowed
742 * positive: default key length
743 */
744 int
default_keylen(int class,int type)745 default_keylen(int class, int type)
746 {
747
748 switch (class) {
749 case algclass_isakmp_enc:
750 case algclass_ipsec_enc:
751 break;
752 default:
753 return 0;
754 }
755
756 switch (type) {
757 case algtype_blowfish:
758 case algtype_rc5:
759 case algtype_cast128:
760 case algtype_aes:
761 case algtype_aesgcm16:
762 case algtype_twofish:
763 case algtype_camellia:
764 return 128;
765 default:
766 return 0;
767 }
768 }
769
770 /*
771 * check key length
772 * OUT: -1: NG
773 * 0: OK
774 */
775 int
check_keylen(int class,int type,int len)776 check_keylen(int class, int type, int len)
777 {
778 int badrange;
779
780 switch (class) {
781 case algclass_isakmp_enc:
782 case algclass_ipsec_enc:
783 break;
784 default:
785 /* unknown class, punt */
786 plog(LLV_ERROR, LOCATION, NULL,
787 "unknown algclass %d\n", class);
788 return -1;
789 }
790
791 /* key length must be multiple of 8 bytes - RFC2451 2.2 */
792 switch (type) {
793 case algtype_blowfish:
794 case algtype_rc5:
795 case algtype_cast128:
796 case algtype_aes:
797 case algtype_aesgcm16:
798 case algtype_twofish:
799 case algtype_camellia:
800 if (len % 8 != 0) {
801 plog(LLV_ERROR, LOCATION, NULL,
802 "key length %d is not multiple of 8\n", len);
803 return -1;
804 }
805 break;
806 }
807
808 /* key length range */
809 badrange = 0;
810 switch (type) {
811 case algtype_blowfish:
812 if (len < 40 || 448 < len)
813 badrange++;
814 break;
815 case algtype_rc5:
816 if (len < 40 || 2040 < len)
817 badrange++;
818 break;
819 case algtype_cast128:
820 if (len < 40 || 128 < len)
821 badrange++;
822 break;
823 case algtype_aes:
824 if (!(len == 128 || len == 192 || len == 256))
825 badrange++;
826 break;
827 case algtype_aesgcm16:
828 if (!(len == 128 || len == 192 || len == 256))
829 badrange++;
830 break;
831 case algtype_twofish:
832 if (len < 40 || 256 < len)
833 badrange++;
834 break;
835 case algtype_camellia:
836 if (!(len == 128 || len == 192 || len == 256))
837 badrange++;
838 break;
839 default:
840 if (len) {
841 plog(LLV_ERROR, LOCATION, NULL,
842 "key length is not allowed");
843 return -1;
844 }
845 break;
846 }
847 if (badrange) {
848 plog(LLV_ERROR, LOCATION, NULL,
849 "key length out of range\n");
850 return -1;
851 }
852
853 return 0;
854 }
855
856 /*
857 * convert algorithm type to DOI value.
858 * OUT -1 : NG
859 * other: converted.
860 */
861 int
algtype2doi(int class,int type)862 algtype2doi(int class, int type)
863 {
864 int res = -1;
865
866 switch (class) {
867 case algclass_ipsec_enc:
868 res = alg_ipsec_encdef_doi(type);
869 break;
870 case algclass_ipsec_auth:
871 res = alg_ipsec_hmacdef_doi(type);
872 break;
873 case algclass_ipsec_comp:
874 res = alg_ipsec_compdef_doi(type);
875 break;
876 case algclass_isakmp_enc:
877 res = alg_oakley_encdef_doi(type);
878 break;
879 case algclass_isakmp_hash:
880 res = alg_oakley_hashdef_doi(type);
881 break;
882 case algclass_isakmp_dh:
883 res = alg_oakley_dhdef_doi(type);
884 break;
885 case algclass_isakmp_ameth:
886 res = alg_oakley_authdef_doi(type);
887 break;
888 }
889 return res;
890 }
891
892 /*
893 * convert algorithm class to DOI value.
894 * OUT -1 : NG
895 * other: converted.
896 */
897 int
algclass2doi(int class)898 algclass2doi(int class)
899 {
900 switch (class) {
901 case algclass_ipsec_enc:
902 return IPSECDOI_PROTO_IPSEC_ESP;
903 case algclass_ipsec_auth:
904 return IPSECDOI_ATTR_AUTH;
905 case algclass_ipsec_comp:
906 return IPSECDOI_PROTO_IPCOMP;
907 case algclass_isakmp_enc:
908 return OAKLEY_ATTR_ENC_ALG;
909 case algclass_isakmp_hash:
910 return OAKLEY_ATTR_HASH_ALG;
911 case algclass_isakmp_dh:
912 return OAKLEY_ATTR_GRP_DESC;
913 case algclass_isakmp_ameth:
914 return OAKLEY_ATTR_AUTH_METHOD;
915 default:
916 return -1;
917 }
918 /*NOTREACHED*/
919 return -1;
920 }
921