1 /* $KAME: algorithm.c,v 1.25 2002/06/10 20:01:21 itojun Exp $ */
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/param.h>
33 #include <sys/types.h>
42 #include "crypto_openssl.h"
44 #include "algorithm.h"
46 #include "isakmp_var.h"
48 #include "ipsec_doi.h"
51 static struct hash_algorithm oakley_hashdef
[] = {
52 { "md5", algtype_md5
, OAKLEY_ATTR_HASH_ALG_MD5
,
53 eay_md5_init
, eay_md5_update
,
54 eay_md5_final
, eay_md5_hashlen
,
56 { "sha1", algtype_sha1
, OAKLEY_ATTR_HASH_ALG_SHA
,
57 eay_sha1_init
, eay_sha1_update
,
58 eay_sha1_final
, eay_sha1_hashlen
,
60 { "sha2_256", algtype_sha2_256
, OAKLEY_ATTR_HASH_ALG_SHA2_256
,
61 eay_sha2_256_init
, eay_sha2_256_update
,
62 eay_sha2_256_final
, eay_sha2_256_hashlen
,
64 { "sha2_384", algtype_sha2_384
, OAKLEY_ATTR_HASH_ALG_SHA2_384
,
65 eay_sha2_384_init
, eay_sha2_384_update
,
66 eay_sha2_384_final
, eay_sha2_384_hashlen
,
68 { "sha2_512", algtype_sha2_512
, OAKLEY_ATTR_HASH_ALG_SHA2_512
,
69 eay_sha2_512_init
, eay_sha2_512_update
,
70 eay_sha2_512_final
, eay_sha2_512_hashlen
,
74 static struct hmac_algorithm oakley_hmacdef
[] = {
75 { "hmac_md5", algtype_md5
, OAKLEY_ATTR_HASH_ALG_MD5
,
76 eay_hmacmd5_init
, eay_hmacmd5_update
,
77 eay_hmacmd5_final
, NULL
,
79 { "hmac_sha1", algtype_sha1
, OAKLEY_ATTR_HASH_ALG_SHA
,
80 eay_hmacsha1_init
, eay_hmacsha1_update
,
81 eay_hmacsha1_final
, NULL
,
83 { "hmac_sha2_256", algtype_sha2_256
, OAKLEY_ATTR_HASH_ALG_SHA2_256
,
84 eay_hmacsha2_256_init
, eay_hmacsha2_256_update
,
85 eay_hmacsha2_256_final
, NULL
,
86 eay_hmacsha2_256_one
, },
87 { "hmac_sha2_384", algtype_sha2_384
, OAKLEY_ATTR_HASH_ALG_SHA2_384
,
88 eay_hmacsha2_384_init
, eay_hmacsha2_384_update
,
89 eay_hmacsha2_384_final
, NULL
,
90 eay_hmacsha2_384_one
, },
91 { "hmac_sha2_512", algtype_sha2_512
, OAKLEY_ATTR_HASH_ALG_SHA2_512
,
92 eay_hmacsha2_512_init
, eay_hmacsha2_512_update
,
93 eay_hmacsha2_512_final
, NULL
,
94 eay_hmacsha2_512_one
, },
97 static struct enc_algorithm oakley_encdef
[] = {
98 { "des", algtype_des
, OAKLEY_ATTR_ENC_ALG_DES
, 8,
99 eay_des_encrypt
, eay_des_decrypt
,
100 eay_des_weakkey
, eay_des_keylen
, },
101 #ifdef HAVE_OPENSSL_IDEA_H
102 { "idea", algtype_idea
, OAKLEY_ATTR_ENC_ALG_IDEA
, 8,
103 eay_idea_encrypt
, eay_idea_decrypt
,
104 eay_idea_weakkey
, eay_idea_keylen
, },
106 { "blowfish", algtype_blowfish
, OAKLEY_ATTR_ENC_ALG_BLOWFISH
, 8,
107 eay_bf_encrypt
, eay_bf_decrypt
,
108 eay_bf_weakkey
, eay_bf_keylen
, },
109 #ifdef HAVE_OPENSSL_RC5_H
110 { "rc5", algtype_rc5
, OAKLEY_ATTR_ENC_ALG_RC5
, 8,
111 eay_rc5_encrypt
, eay_rc5_decrypt
,
112 eay_rc5_weakkey
, eay_rc5_keylen
, },
114 { "3des", algtype_3des
, OAKLEY_ATTR_ENC_ALG_3DES
, 8,
115 eay_3des_encrypt
, eay_3des_decrypt
,
116 eay_3des_weakkey
, eay_3des_keylen
, },
117 { "cast", algtype_cast128
, OAKLEY_ATTR_ENC_ALG_CAST
, 8,
118 eay_cast_encrypt
, eay_cast_decrypt
,
119 eay_cast_weakkey
, eay_cast_keylen
, },
120 { "aes", algtype_rijndael
, OAKLEY_ATTR_ENC_ALG_AES
, 16,
121 eay_aes_encrypt
, eay_aes_decrypt
,
122 eay_aes_weakkey
, eay_aes_keylen
, },
125 static struct enc_algorithm ipsec_encdef
[] = {
126 { "des-iv64", algtype_des_iv64
, IPSECDOI_ESP_DES_IV64
, 8,
128 NULL
, eay_des_keylen
, },
129 { "des", algtype_des
, IPSECDOI_ESP_DES
, 8,
131 NULL
, eay_des_keylen
, },
132 { "3des", algtype_3des
, IPSECDOI_ESP_3DES
, 8,
134 NULL
, eay_3des_keylen
, },
135 #ifdef HAVE_OPENSSL_RC5_H
136 { "rc5", algtype_rc5
, IPSECDOI_ESP_RC5
, 8,
138 NULL
, eay_rc5_keylen
, },
140 { "cast", algtype_cast128
, IPSECDOI_ESP_CAST
, 8,
142 NULL
, eay_cast_keylen
, },
143 { "blowfish", algtype_blowfish
, IPSECDOI_ESP_BLOWFISH
, 8,
145 NULL
, eay_bf_keylen
, },
146 { "des-iv32", algtype_des_iv32
, IPSECDOI_ESP_DES_IV32
, 8,
148 NULL
, eay_des_keylen
, },
149 { "null", algtype_null_enc
, IPSECDOI_ESP_NULL
, 8,
151 NULL
, eay_null_keylen
, },
152 { "rijndael", algtype_rijndael
, IPSECDOI_ESP_RIJNDAEL
, 16,
154 NULL
, eay_aes_keylen
, },
155 { "twofish", algtype_twofish
, IPSECDOI_ESP_TWOFISH
, 16,
157 NULL
, eay_twofish_keylen
, },
158 #ifdef HAVE_OPENSSL_IDEA_H
159 { "3idea", algtype_3idea
, IPSECDOI_ESP_3IDEA
, 8,
162 { "idea", algtype_idea
, IPSECDOI_ESP_IDEA
, 8,
166 { "rc4", algtype_rc4
, IPSECDOI_ESP_RC4
, 8,
171 static struct hmac_algorithm ipsec_hmacdef
[] = {
172 { "md5", algtype_hmac_md5
, IPSECDOI_ATTR_AUTH_HMAC_MD5
,
174 NULL
, eay_md5_hashlen
,
176 { "sha1", algtype_hmac_sha1
, IPSECDOI_ATTR_AUTH_HMAC_SHA1
,
178 NULL
, eay_sha1_hashlen
,
180 { "kpdk", algtype_kpdk
, IPSECDOI_ATTR_AUTH_KPDK
,
182 NULL
, eay_kpdk_hashlen
,
184 { "null", algtype_non_auth
, IPSECDOI_ATTR_AUTH_NONE
,
186 NULL
, eay_null_hashlen
,
188 { "hmac_sha2_256", algtype_hmac_sha2_256
, IPSECDOI_ATTR_SHA2_256
,
190 NULL
, eay_sha2_256_hashlen
,
192 { "hmac_sha2_384", algtype_hmac_sha2_384
, IPSECDOI_ATTR_SHA2_384
,
194 NULL
, eay_sha2_384_hashlen
,
196 { "hmac_sha2_512", algtype_hmac_sha2_512
, IPSECDOI_ATTR_SHA2_512
,
198 NULL
, eay_sha2_512_hashlen
,
202 static struct misc_algorithm ipsec_compdef
[] = {
203 { "oui", algtype_oui
, IPSECDOI_IPCOMP_OUI
, },
204 { "deflate", algtype_deflate
, IPSECDOI_IPCOMP_DEFLATE
, },
205 { "lzs", algtype_lzs
, IPSECDOI_IPCOMP_LZS
, },
208 static struct misc_algorithm oakley_authdef
[] = {
209 { "psk", algtype_psk
, OAKLEY_ATTR_AUTH_METHOD_PSKEY
, },
210 { "dsssig", algtype_dsssig
, OAKLEY_ATTR_AUTH_METHOD_DSSSIG
, },
211 { "rsasig", algtype_rsasig
, OAKLEY_ATTR_AUTH_METHOD_RSASIG
, },
212 { "rsaenc", algtype_rsaenc
, OAKLEY_ATTR_AUTH_METHOD_RSAENC
, },
213 { "rsarev", algtype_rsarev
, OAKLEY_ATTR_AUTH_METHOD_RSAREV
, },
214 { "gssapi_krb", algtype_gssapikrb
, OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB
, },
217 static struct dh_algorithm oakley_dhdef
[] = {
218 { "modp768", algtype_modp768
, OAKLEY_ATTR_GRP_DESC_MODP768
,
220 { "modp1024", algtype_modp1024
, OAKLEY_ATTR_GRP_DESC_MODP1024
,
222 { "modp1536", algtype_modp1536
, OAKLEY_ATTR_GRP_DESC_MODP1536
,
224 { "modp2048", algtype_modp2048
, OAKLEY_ATTR_GRP_DESC_MODP2048
,
226 { "modp3072", algtype_modp3072
, OAKLEY_ATTR_GRP_DESC_MODP3072
,
228 { "modp4096", algtype_modp4096
, OAKLEY_ATTR_GRP_DESC_MODP4096
,
230 { "modp6144", algtype_modp6144
, OAKLEY_ATTR_GRP_DESC_MODP6144
,
232 { "modp8192", algtype_modp8192
, OAKLEY_ATTR_GRP_DESC_MODP8192
,
236 static struct hash_algorithm
*alg_oakley_hashdef
__P((int));
237 static struct hmac_algorithm
*alg_oakley_hmacdef
__P((int));
238 static struct enc_algorithm
*alg_oakley_encdef
__P((int));
239 static struct enc_algorithm
*alg_ipsec_encdef
__P((int));
240 static struct hmac_algorithm
*alg_ipsec_hmacdef
__P((int));
241 static struct dh_algorithm
*alg_oakley_dhdef
__P((int));
243 /* oakley hash algorithm */
244 static struct hash_algorithm
*
245 alg_oakley_hashdef(doi
)
250 for (i
= 0; i
< ARRAYLEN(oakley_hashdef
); i
++)
251 if (doi
== oakley_hashdef
[i
].doi
) {
252 plog(LLV_DEBUG
, LOCATION
, NULL
, "hash(%s)\n",
253 oakley_hashdef
[i
].name
);
254 return &oakley_hashdef
[i
];
260 alg_oakley_hashdef_ok(doi
)
263 struct hash_algorithm
*f
;
265 f
= alg_oakley_hashdef(doi
);
273 alg_oakley_hashdef_doi(type
)
278 for (i
= 0; i
< ARRAYLEN(oakley_hashdef
); i
++)
279 if (type
== oakley_hashdef
[i
].type
) {
280 res
= oakley_hashdef
[i
].doi
;
287 alg_oakley_hashdef_hashlen(doi
)
290 struct hash_algorithm
*f
;
292 f
= alg_oakley_hashdef(doi
);
293 if (f
== NULL
|| f
->hashlen
== NULL
)
296 return (f
->hashlen
)();
300 alg_oakley_hashdef_one(doi
, buf
)
304 struct hash_algorithm
*f
;
306 f
= alg_oakley_hashdef(doi
);
307 if (f
== NULL
|| f
->hashlen
== NULL
)
310 return (f
->one
)(buf
);
313 /* oakley hmac algorithm */
314 static struct hmac_algorithm
*
315 alg_oakley_hmacdef(doi
)
320 for (i
= 0; i
< ARRAYLEN(oakley_hmacdef
); i
++)
321 if (doi
== oakley_hmacdef
[i
].doi
) {
322 plog(LLV_DEBUG
, LOCATION
, NULL
, "hmac(%s)\n",
323 oakley_hmacdef
[i
].name
);
324 return &oakley_hmacdef
[i
];
330 alg_oakley_hmacdef_doi(type
)
335 for (i
= 0; i
< ARRAYLEN(oakley_hmacdef
); i
++)
336 if (type
== oakley_hmacdef
[i
].type
) {
337 res
= oakley_hmacdef
[i
].doi
;
344 alg_oakley_hmacdef_one(doi
, key
, buf
)
348 struct hmac_algorithm
*f
;
351 struct timeval start
, end
;
354 f
= alg_oakley_hmacdef(doi
);
355 if (f
== NULL
|| f
->one
== NULL
)
359 gettimeofday(&start
, NULL
);
362 res
= (f
->one
)(key
, buf
);
365 gettimeofday(&end
, NULL
);
366 syslog(LOG_NOTICE
, "%s(%s size=%d): %8.6f", __func__
,
367 f
->name
, buf
->l
, timedelta(&start
, &end
));
373 /* oakley encryption algorithm */
374 static struct enc_algorithm
*
375 alg_oakley_encdef(doi
)
380 for (i
= 0; i
< ARRAYLEN(oakley_encdef
); i
++)
381 if (doi
== oakley_encdef
[i
].doi
) {
382 plog(LLV_DEBUG
, LOCATION
, NULL
, "encription(%s)\n",
383 oakley_encdef
[i
].name
);
384 return &oakley_encdef
[i
];
390 alg_oakley_encdef_ok(doi
)
393 struct enc_algorithm
*f
;
395 f
= alg_oakley_encdef(doi
);
403 alg_oakley_encdef_doi(type
)
408 for (i
= 0; i
< ARRAYLEN(oakley_encdef
); i
++)
409 if (type
== oakley_encdef
[i
].type
) {
410 res
= oakley_encdef
[i
].doi
;
417 alg_oakley_encdef_keylen(doi
, len
)
420 struct enc_algorithm
*f
;
422 f
= alg_oakley_encdef(doi
);
423 if (f
== NULL
|| f
->keylen
== NULL
)
426 return (f
->keylen
)(len
);
430 alg_oakley_encdef_blocklen(doi
)
433 struct enc_algorithm
*f
;
435 f
= alg_oakley_encdef(doi
);
443 alg_oakley_encdef_decrypt(doi
, buf
, key
, iv
)
445 vchar_t
*buf
, *key
, *iv
;
448 struct enc_algorithm
*f
;
450 struct timeval start
, end
;
453 f
= alg_oakley_encdef(doi
);
454 if (f
== NULL
|| f
->decrypt
== NULL
)
458 gettimeofday(&start
, NULL
);
461 res
= (f
->decrypt
)(buf
, key
, iv
);
464 gettimeofday(&end
, NULL
);
465 syslog(LOG_NOTICE
, "%s(%s klen=%d size=%d): %8.6f", __func__
,
466 f
->name
, key
->l
<< 3, buf
->l
, timedelta(&start
, &end
));
472 alg_oakley_encdef_encrypt(doi
, buf
, key
, iv
)
474 vchar_t
*buf
, *key
, *iv
;
477 struct enc_algorithm
*f
;
479 struct timeval start
, end
;
482 f
= alg_oakley_encdef(doi
);
483 if (f
== NULL
|| f
->encrypt
== NULL
)
487 gettimeofday(&start
, NULL
);
490 res
= (f
->encrypt
)(buf
, key
, iv
);
493 gettimeofday(&end
, NULL
);
494 syslog(LOG_NOTICE
, "%s(%s klen=%d size=%d): %8.6f", __func__
,
495 f
->name
, key
->l
<< 3, buf
->l
, timedelta(&start
, &end
));
500 /* ipsec encryption algorithm */
501 static struct enc_algorithm
*
502 alg_ipsec_encdef(doi
)
507 for (i
= 0; i
< ARRAYLEN(ipsec_encdef
); i
++)
508 if (doi
== ipsec_encdef
[i
].doi
) {
509 plog(LLV_DEBUG
, LOCATION
, NULL
, "encription(%s)\n",
510 ipsec_encdef
[i
].name
);
511 return &ipsec_encdef
[i
];
517 alg_ipsec_encdef_doi(type
)
522 for (i
= 0; i
< ARRAYLEN(ipsec_encdef
); i
++)
523 if (type
== ipsec_encdef
[i
].type
) {
524 res
= ipsec_encdef
[i
].doi
;
531 alg_ipsec_encdef_keylen(doi
, len
)
534 struct enc_algorithm
*f
;
536 f
= alg_ipsec_encdef(doi
);
537 if (f
== NULL
|| f
->keylen
== NULL
)
540 return (f
->keylen
)(len
);
543 /* ipsec hmac algorithm */
544 static struct hmac_algorithm
*
545 alg_ipsec_hmacdef(doi
)
550 for (i
= 0; i
< ARRAYLEN(ipsec_hmacdef
); i
++)
551 if (doi
== ipsec_hmacdef
[i
].doi
) {
552 plog(LLV_DEBUG
, LOCATION
, NULL
, "hmac(%s)\n",
553 oakley_hmacdef
[i
].name
);
554 return &ipsec_hmacdef
[i
];
560 alg_ipsec_hmacdef_doi(type
)
565 for (i
= 0; i
< ARRAYLEN(ipsec_hmacdef
); i
++)
566 if (type
== ipsec_hmacdef
[i
].type
) {
567 res
= ipsec_hmacdef
[i
].doi
;
574 alg_ipsec_hmacdef_hashlen(doi
)
577 struct hmac_algorithm
*f
;
579 f
= alg_ipsec_hmacdef(doi
);
580 if (f
== NULL
|| f
->hashlen
== NULL
)
583 return (f
->hashlen
)();
588 alg_ipsec_compdef_doi(type
)
593 for (i
= 0; i
< ARRAYLEN(ipsec_compdef
); i
++)
594 if (type
== ipsec_compdef
[i
].type
) {
595 res
= ipsec_compdef
[i
].doi
;
602 static struct dh_algorithm
*
603 alg_oakley_dhdef(doi
)
608 for (i
= 0; i
< ARRAYLEN(oakley_dhdef
); i
++)
609 if (doi
== oakley_dhdef
[i
].doi
) {
610 plog(LLV_DEBUG
, LOCATION
, NULL
, "hmac(%s)\n",
611 oakley_dhdef
[i
].name
);
612 return &oakley_dhdef
[i
];
618 alg_oakley_dhdef_ok(doi
)
621 struct dh_algorithm
*f
;
623 f
= alg_oakley_dhdef(doi
);
631 alg_oakley_dhdef_doi(type
)
636 for (i
= 0; i
< ARRAYLEN(oakley_dhdef
); i
++)
637 if (type
== oakley_dhdef
[i
].type
) {
638 res
= oakley_dhdef
[i
].doi
;
645 alg_oakley_dhdef_group(doi
)
648 struct dh_algorithm
*f
;
650 f
= alg_oakley_dhdef(doi
);
651 if (f
== NULL
|| f
->dhgroup
== NULL
)
657 /* authentication method */
659 alg_oakley_authdef_doi(type
)
664 for (i
= 0; i
< ARRAYLEN(oakley_authdef
); i
++)
665 if (type
== oakley_authdef
[i
].type
) {
666 res
= oakley_authdef
[i
].doi
;
673 * give the default key length
675 * 0: fixed key cipher, key length not allowed
676 * positive: default key length
679 default_keylen(class, type
)
684 case algclass_isakmp_enc
:
685 case algclass_ipsec_enc
:
692 case algtype_blowfish
:
694 case algtype_cast128
:
695 case algtype_rijndael
:
696 case algtype_twofish
:
709 check_keylen(class, type
, len
)
710 int class, type
, len
;
715 case algclass_isakmp_enc
:
716 case algclass_ipsec_enc
:
719 /* unknown class, punt */
720 plog(LLV_ERROR
, LOCATION
, NULL
,
721 "unknown algclass %d\n", class);
725 /* key length must be multiple of 8 bytes - RFC2451 2.2 */
727 case algtype_blowfish
:
729 case algtype_cast128
:
730 case algtype_rijndael
:
731 case algtype_twofish
:
733 plog(LLV_ERROR
, LOCATION
, NULL
,
734 "key length %d is not multiple of 8\n", len
);
740 /* key length range */
743 case algtype_blowfish
:
744 if (len
< 40 || 448 < len
)
748 if (len
< 40 || 2040 < len
)
751 case algtype_cast128
:
752 if (len
< 40 || 128 < len
)
755 case algtype_rijndael
:
756 if (!(len
== 128 || len
== 192 || len
== 256))
759 case algtype_twofish
:
760 if (len
< 40 || 256 < len
)
765 plog(LLV_ERROR
, LOCATION
, NULL
,
766 "key length is not allowed");
772 plog(LLV_ERROR
, LOCATION
, NULL
,
773 "key length out of range\n");
781 * convert algorithm type to DOI value.
786 algtype2doi(class, type
)
792 case algclass_ipsec_enc
:
793 res
= alg_ipsec_encdef_doi(type
);
795 case algclass_ipsec_auth
:
796 res
= alg_ipsec_hmacdef_doi(type
);
798 case algclass_ipsec_comp
:
799 res
= alg_ipsec_compdef_doi(type
);
801 case algclass_isakmp_enc
:
802 res
= alg_oakley_encdef_doi(type
);
804 case algclass_isakmp_hash
:
805 res
= alg_oakley_hashdef_doi(type
);
807 case algclass_isakmp_dh
:
808 res
= alg_oakley_dhdef_doi(type
);
810 case algclass_isakmp_ameth
:
811 res
= alg_oakley_authdef_doi(type
);
818 * convert algorithm class to DOI value.
827 case algclass_ipsec_enc
:
828 return IPSECDOI_PROTO_IPSEC_ESP
;
829 case algclass_ipsec_auth
:
830 return IPSECDOI_ATTR_AUTH
;
831 case algclass_ipsec_comp
:
832 return IPSECDOI_PROTO_IPCOMP
;
833 case algclass_isakmp_enc
:
834 return OAKLEY_ATTR_ENC_ALG
;
835 case algclass_isakmp_hash
:
836 return OAKLEY_ATTR_HASH_ALG
;
837 case algclass_isakmp_dh
:
838 return OAKLEY_ATTR_GRP_DESC
;
839 case algclass_isakmp_ameth
:
840 return OAKLEY_ATTR_AUTH_METHOD
;