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