1 /* IKE modular algorithm handling interface
2 * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * RCSID $Id: ike_alg.c,v 1.6 2004/09/17 21:29:50 as Exp $
21 #include <sys/queue.h>
24 #include <freeswan/ipsec_policy.h>
26 #include "constants.h"
40 #include "connections.h"
43 #define return_on(var, val) do { var=val;goto return_out; } while(0);
46 * IKE algorithm list handling - registration and lookup
49 /* Modular IKE algorithm storage structure */
51 static struct ike_alg
*ike_alg_base
[IKE_ALG_MAX
+1] = {NULL
, NULL
};
54 * return ike_algo object by {type, id}
56 static struct ike_alg
*
57 ike_alg_find(u_int algo_type
, u_int algo_id
, u_int keysize
__attribute__((unused
)))
59 struct ike_alg
*e
= ike_alg_base
[algo_type
];
61 while (e
!= NULL
&& algo_id
> e
->algo_id
)
65 return (e
!= NULL
&& e
->algo_id
== algo_id
) ? e
: NULL
;
69 * "raw" ike_alg list adding function
72 ike_alg_add(struct ike_alg
* a
)
74 if (a
->algo_type
> IKE_ALG_MAX
)
76 plog("ike_alg: Not added, invalid algorithm type");
80 if (ike_alg_find(a
->algo_type
, a
->algo_id
, 0) != NULL
)
82 plog("ike_alg: Not added, algorithm already exists");
87 struct ike_alg
**ep
= &ike_alg_base
[a
->algo_type
];
88 struct ike_alg
*e
= *ep
;
90 while (e
!= NULL
&& a
->algo_id
> e
->algo_id
)
102 * get IKE hash algorithm
104 struct hash_desc
*ike_alg_get_hasher(u_int alg
)
106 return (struct hash_desc
*) ike_alg_find(IKE_ALG_HASH
, alg
, 0);
110 * get IKE encryption algorithm
112 struct encrypt_desc
*ike_alg_get_encrypter(u_int alg
)
114 return (struct encrypt_desc
*) ike_alg_find(IKE_ALG_ENCRYPT
, alg
, 0);
118 * check if IKE hash algorithm is present
121 ike_alg_hash_present(u_int halg
)
123 return ike_alg_get_hasher(halg
) != NULL
;
127 * check if IKE encryption algorithm is present
130 ike_alg_enc_present(u_int ealg
)
132 return ike_alg_get_encrypter(ealg
) != NULL
;
136 * Validate and register IKE hash algorithm object
139 ike_alg_register_hash(struct hash_desc
*hash_desc
)
141 const char *alg_name
= NULL
;
144 if (hash_desc
->algo_id
> OAKLEY_HASH_MAX
)
146 plog ("ike_alg: hash alg=%d > max=%d"
147 , hash_desc
->algo_id
, OAKLEY_HASH_MAX
);
148 return_on(ret
,-EINVAL
);
151 if (hash_desc
->hash_ctx_size
> sizeof (union hash_ctx
))
153 plog ("ike_alg: hash alg=%d has ctx_size=%d > hash_ctx=%d"
155 , (int)hash_desc
->hash_ctx_size
156 , (int)sizeof (union hash_ctx
));
157 return_on(ret
,-EOVERFLOW
);
160 if (!(hash_desc
->hash_init
&& hash_desc
->hash_update
&& hash_desc
->hash_final
))
162 plog ("ike_alg: hash alg=%d needs hash_init(), hash_update() and hash_final()"
163 , hash_desc
->algo_id
);
164 return_on(ret
,-EINVAL
);
167 alg_name
= enum_name(&oakley_hash_names
, hash_desc
->algo_id
);
170 plog ("ike_alg: hash alg=%d not found in constants.c:oakley_hash_names"
171 , hash_desc
->algo_id
);
177 ret
= ike_alg_add((struct ike_alg
*)hash_desc
);
179 plog("ike_alg: Activating %s hash: %s"
180 ,alg_name
, ret
== 0 ? "Ok" : "FAILED");
186 * Validate and register IKE encryption algorithm object
189 ike_alg_register_enc(struct encrypt_desc
*enc_desc
)
191 int ret
= ike_alg_add((struct ike_alg
*)enc_desc
);
193 const char *alg_name
= enum_name(&oakley_enc_names
, enc_desc
->algo_id
);
197 /* algorithm is not listed in oakley_enc_names */
198 if (alg_name
== NULL
)
200 snprintf(alg_number
, sizeof(alg_number
), "OAKLEY_ID_%d"
201 , enc_desc
->algo_id
);
202 alg_name
= alg_number
;
205 plog("ike_alg: Activating %s encryption: %s"
206 , alg_name
, ret
== 0 ? "Ok" : "FAILED");
212 * Get pfsgroup for this connection
214 const struct oakley_group_desc
*
215 ike_alg_pfsgroup(struct connection
*c
, lset_t policy
)
217 const struct oakley_group_desc
* ret
= NULL
;
219 if ((policy
& POLICY_PFS
)
221 && c
->alg_info_esp
->esp_pfsgroup
)
222 ret
= lookup_group(c
->alg_info_esp
->esp_pfsgroup
);
227 * Create an OAKLEY proposal based on alg_info and policy
230 ike_alg_db_new(struct alg_info_ike
*ai
, lset_t policy
)
232 struct db_context
*db_ctx
= NULL
;
233 struct ike_info
*ike_info
;
234 u_int ealg
, halg
, modp
, eklen
= 0;
235 struct encrypt_desc
*enc_desc
;
240 whack_log(RC_LOG_SERIOUS
, "no IKE algorithms "
241 "for this connection "
242 "(check ike algorithm string)");
245 policy
&= POLICY_ID_AUTH_MASK
;
246 db_ctx
= db_prop_new(PROTO_ISAKMP
, 8, 8 * 5);
249 ALG_INFO_IKE_FOREACH(ai
, ike_info
, i
)
251 ealg
= ike_info
->ike_ealg
;
252 halg
= ike_info
->ike_halg
;
253 modp
= ike_info
->ike_modp
;
254 eklen
= ike_info
->ike_eklen
;
256 if (!ike_alg_enc_present(ealg
))
258 DBG_log("ike_alg: ike enc ealg=%d not present"
263 if (!ike_alg_hash_present(halg
))
265 DBG_log("ike_alg: ike hash halg=%d not present"
270 enc_desc
= ike_alg_get_encrypter(ealg
);
271 passert(enc_desc
!= NULL
);
274 && (eklen
< enc_desc
->keyminlen
|| eklen
> enc_desc
->keymaxlen
))
276 DBG_log("ike_alg: ealg=%d (specified) keylen:%d, not valid min=%d, max=%d"
279 , enc_desc
->keyminlen
280 , enc_desc
->keymaxlen
285 if (policy
& POLICY_RSASIG
)
287 db_trans_add(db_ctx
, KEY_IKE
);
288 db_attr_add_values(db_ctx
, OAKLEY_ENCRYPTION_ALGORITHM
, ealg
);
289 db_attr_add_values(db_ctx
, OAKLEY_HASH_ALGORITHM
, halg
);
291 db_attr_add_values(db_ctx
, OAKLEY_KEY_LENGTH
, eklen
);
292 db_attr_add_values(db_ctx
, OAKLEY_AUTHENTICATION_METHOD
, OAKLEY_RSA_SIG
);
293 db_attr_add_values(db_ctx
, OAKLEY_GROUP_DESCRIPTION
, modp
);
296 if (policy
& POLICY_PSK
)
298 db_trans_add(db_ctx
, KEY_IKE
);
299 db_attr_add_values(db_ctx
, OAKLEY_ENCRYPTION_ALGORITHM
, ealg
);
300 db_attr_add_values(db_ctx
, OAKLEY_HASH_ALGORITHM
, halg
);
301 if (ike_info
->ike_eklen
)
302 db_attr_add_values(db_ctx
, OAKLEY_KEY_LENGTH
, ike_info
->ike_eklen
);
303 db_attr_add_values(db_ctx
, OAKLEY_AUTHENTICATION_METHOD
, OAKLEY_PRESHARED_KEY
);
304 db_attr_add_values(db_ctx
, OAKLEY_GROUP_DESCRIPTION
, modp
);
312 * Show registered IKE algorithms
320 whack_log(RC_COMMENT
, " ");
321 whack_log(RC_COMMENT
, "List of registered IKE Encryption Algorithms:");
322 whack_log(RC_COMMENT
, " ");
324 for (a
= ike_alg_base
[IKE_ALG_ENCRYPT
]; a
!= NULL
; a
= a
->algo_next
)
326 struct encrypt_desc
*desc
= (struct encrypt_desc
*)a
;
328 whack_log(RC_COMMENT
, "#%-5d %s, blocksize: %d, keylen: %d-%d-%d"
330 , enum_name(&oakley_enc_names
, a
->algo_id
)
331 , (int)desc
->enc_blocksize
*BITS_PER_BYTE
338 whack_log(RC_COMMENT
, " ");
339 whack_log(RC_COMMENT
, "List of registered IKE Hash Algorithms:");
340 whack_log(RC_COMMENT
, " ");
342 for (a
= ike_alg_base
[IKE_ALG_HASH
]; a
!= NULL
; a
= a
->algo_next
)
344 whack_log(RC_COMMENT
, "#%-5d %s, hashsize: %d"
346 , enum_name(&oakley_hash_names
, a
->algo_id
)
347 , (int)((struct hash_desc
*)a
)->hash_digest_size
*BITS_PER_BYTE
351 whack_log(RC_COMMENT
, " ");
352 whack_log(RC_COMMENT
, "List of registered IKE DH Groups:");
353 whack_log(RC_COMMENT
, " ");
355 for (i
= 0; i
< elemsof(oakley_group
); i
++)
357 const struct oakley_group_desc
*gdesc
=oakley_group
+ i
;
359 whack_log(RC_COMMENT
, "#%-5d %s, groupsize: %d"
361 , enum_name(&oakley_group_names
, gdesc
->group
)
362 , (int)gdesc
->bytes
*BITS_PER_BYTE
367 /* Show IKE algorithms for
368 * - this connection (result from ike= string)
372 ike_alg_show_connection(struct connection
*c
, const char *instance
)
379 alg_info_snprint(buf
, sizeof(buf
)-1, (struct alg_info
*)c
->alg_info_ike
);
381 , "\"%s\"%s: IKE algorithms wanted: %s"
387 alg_info_snprint_ike(buf
, sizeof(buf
)-1, c
->alg_info_ike
);
389 , "\"%s\"%s: IKE algorithms found: %s"
396 st
= state_with_serialno(c
->newest_isakmp_sa
);
399 , "\"%s\"%s: IKE algorithm newest: %s_%d-%s-%s"
402 , enum_show(&oakley_enc_names
, st
->st_oakley
.encrypt
)
403 +7 /* strlen("OAKLEY_") */
404 /* , st->st_oakley.encrypter->keydeflen */
405 , st
->st_oakley
.enckeylen
406 , enum_show(&oakley_hash_names
, st
->st_oakley
.hash
)
407 +7 /* strlen("OAKLEY_") */
408 , enum_show(&oakley_group_names
, st
->st_oakley
.group
->group
)
409 +13 /* strlen("OAKLEY_GROUP_") */
414 * ML: make F_STRICT logic consider enc,hash/auth,modp algorithms
417 ike_alg_ok_final(u_int ealg
, u_int key_len
, u_int aalg
, u_int group
418 , struct alg_info_ike
*alg_info_ike
)
421 * simple test to discard low key_len, will accept it only
422 * if specified in "esp" string
424 bool ealg_insecure
= (key_len
< 128);
427 || (alg_info_ike
&& alg_info_ike
->alg_info_flags
& ALG_INFO_F_STRICT
))
430 struct ike_info
*ike_info
;
434 ALG_INFO_IKE_FOREACH(alg_info_ike
, ike_info
, i
)
436 if (ike_info
->ike_ealg
== ealg
437 && (ike_info
->ike_eklen
== 0 || key_len
== 0 || ike_info
->ike_eklen
== key_len
)
438 && ike_info
->ike_halg
== aalg
439 && ike_info
->ike_modp
== group
)
442 loglog(RC_LOG_SERIOUS
, "You should NOT use insecure IKE algorithms (%s)!"
443 , enum_name(&oakley_enc_names
, ealg
));
448 plog("Oakley Transform [%s (%d), %s, %s] refused due to %s"
449 , enum_name(&oakley_enc_names
, ealg
), key_len
450 , enum_name(&oakley_hash_names
, aalg
)
451 , enum_name(&oakley_group_names
, group
)
453 "insecure key_len and enc. alg. not listed in \"ike\" string" : "strict flag"