2 * IKE modular algorithm handling interface
3 * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
5 * ike_alg.c,v 1.1.4.3 2002/05/30 03:26:08 jjo Exp
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 #include "constants.h"
41 #include "connections.h"
43 #define return_on(var, val) do { var=val;goto return_out; } while(0);
46 * Create an OAKLEY proposal based on alg_info and policy
49 ike_alg_db_new(struct alg_info_ike *ai , lset_t policy)
51 struct db_context *db_ctx = NULL;
52 struct ike_info *ike_info;
53 unsigned ealg, halg, modp, eklen=0;
54 struct encrypt_desc *enc_desc;
58 whack_log(RC_LOG_SERIOUS, "no IKE algorithms "
59 "for this connection "
60 "(check ike algorithm string)");
63 policy &= POLICY_ID_AUTH_MASK;
64 db_ctx = db_prop_new(PROTO_ISAKMP, 8, 8 * 5);
67 ALG_INFO_IKE_FOREACH(ai, ike_info, i) {
68 ealg = ike_info->ike_ealg;
69 halg = ike_info->ike_halg;
70 modp = ike_info->ike_modp;
71 eklen= ike_info->ike_eklen;
73 if (!ike_alg_enc_present(ealg)) {
74 DBG_log("%s() ike enc ealg=%d not present",
79 if (!ike_alg_hash_present(halg)) {
80 DBG_log("%s() ike hash halg=%d not present",
85 enc_desc = ike_alg_get_encrypter(ealg);
86 passert(enc_desc != NULL);
90 && eklen != enc_desc->keydeflen)
92 && (eklen < enc_desc->keyminlen
93 || eklen > enc_desc->keymaxlen))
96 "ealg=%d (specified) keylen:%d, "
106 , enc_desc->keydeflen
108 , enc_desc->keyminlen
109 , enc_desc->keymaxlen
114 if (policy & POLICY_RSASIG) {
115 db_trans_add(db_ctx, KEY_IKE);
116 db_attr_add_values(db_ctx,
117 OAKLEY_ENCRYPTION_ALGORITHM, ealg);
118 db_attr_add_values(db_ctx,
119 OAKLEY_HASH_ALGORITHM, halg);
121 db_attr_add_values(db_ctx,
122 OAKLEY_KEY_LENGTH, eklen);
123 db_attr_add_values(db_ctx,
124 OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG);
125 db_attr_add_values(db_ctx,
126 OAKLEY_GROUP_DESCRIPTION, modp);
128 if (policy & POLICY_PSK) {
129 db_trans_add(db_ctx, KEY_IKE);
130 db_attr_add_values(db_ctx,
131 OAKLEY_ENCRYPTION_ALGORITHM, ealg);
132 db_attr_add_values(db_ctx,
133 OAKLEY_HASH_ALGORITHM, halg);
134 if (ike_info->ike_eklen)
135 db_attr_add_values(db_ctx,
136 OAKLEY_KEY_LENGTH, ike_info->ike_eklen);
137 db_attr_add_values(db_ctx,
138 OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY);
139 db_attr_add_values(db_ctx,
140 OAKLEY_GROUP_DESCRIPTION, modp);
147 * Show registered IKE algorithms
150 ike_alg_show_status(void)
153 struct ike_alg *algo;
154 IKE_EALG_FOR_EACH(algo) {
155 passert(algo != NULL);
157 whack_log(RC_COMMENT, "algorithm IKE encrypt: id=%d, name=%s, blocksize=%d, keydeflen=%d"
159 , enum_name(&oakley_enc_names, alg)
160 , ((struct encrypt_desc *)algo)->enc_blocksize
161 , ((struct encrypt_desc *)algo)->keydeflen
165 IKE_HALG_FOR_EACH(algo) {
166 whack_log(RC_COMMENT, "algorithm IKE hash: id=%d, name=%s, hashsize=%d"
168 , enum_name(&oakley_hash_names, algo->algo_id)
169 , ((struct hash_desc *)algo)->hash_digest_size
172 #define IKE_DH_ALG_FOR_EACH(idx) for(idx = 0; idx != elemsof(oakley_group); idx++)
173 IKE_DH_ALG_FOR_EACH(i) {
174 const struct oakley_group_desc *gdesc=oakley_group+i;
175 whack_log(RC_COMMENT, "algorithm IKE dh group: id=%d, name=%s, bits=%d"
177 , enum_name(&oakley_group_names, gdesc->group)
178 , gdesc->bytes*BITS_PER_BYTE
183 * Show IKE algorithms for
184 * - this connection (result from ike= string)
188 ike_alg_show_connection(struct connection *c, const char *instance)
192 if (c->alg_info_ike) {
193 alg_info_snprint(buf, sizeof(buf),
194 (struct alg_info *)c->alg_info_ike);
196 , "\"%s\"%s: IKE algorithms wanted: %s"
201 if (c->alg_info_ike) {
202 alg_info_snprint_ike(buf, sizeof(buf), c->alg_info_ike);
204 , "\"%s\"%s: IKE algorithms found: %s"
209 st = state_with_serialno(c->newest_isakmp_sa);
212 , "\"%s\"%s: IKE algorithm newest: %s_%d-%s-%s"
215 , enum_show(&oakley_enc_names, st->st_oakley.encrypt)
216 +7 /* strlen("OAKLEY_") */
217 /* , st->st_oakley.encrypter->keydeflen */
218 , st->st_oakley.enckeylen
219 , enum_show(&oakley_hash_names, st->st_oakley.hash)
220 +7 /* strlen("OAKLEY_") */
221 , enum_show(&oakley_group_names, st->st_oakley.group->group)
222 +13 /* strlen("OAKLEY_GROUP_") */
225 /*==========================================================
227 * IKE algo list handling
231 *=========================================================*/
232 struct ike_alg *ike_alg_base[IKE_ALG_MAX+1] = {NULL, NULL};
233 /* check if IKE encrypt algo is present */
234 bool ike_alg_enc_present(int ealg)
236 struct encrypt_desc *enc_desc = ike_alg_get_encrypter(ealg);
237 return enc_desc ? enc_desc->enc_blocksize : 0;
239 /* check if IKE hash algo is present */
240 bool ike_alg_hash_present(int halg)
242 struct hash_desc *hash_desc = ike_alg_get_hasher(halg);
243 return hash_desc ? hash_desc->hash_digest_size : 0;
245 bool ike_alg_enc_ok(int ealg, unsigned key_len, struct alg_info_ike *alg_info_ike, const char **errp)
248 struct encrypt_desc *enc_desc;
249 char errbuf[256]="encrypt algo not found";
251 * test #1: encrypt algo must be present
253 enc_desc = ike_alg_get_encrypter(ealg);
254 if (!enc_desc) return_on(ret, FALSE);
256 * test #2: if key_len specified, it must be in range
258 if ((key_len) && ((key_len < enc_desc->keyminlen) ||
259 (key_len > enc_desc->keymaxlen))) {
260 snprintf(errbuf, sizeof(errbuf),
261 "key_len not in range: encalg=%d, "
262 "key_len=%d, keyminlen=%d, keymaxlen=%d",
267 log ("%s(): %s", __FUNCTION__, errbuf);
268 return_on(ret, FALSE);
271 * test #3: if alg_info specified AND strict flag, only
272 * only allow algo iff listed in st->alg_info_esp
274 else if (alg_info_ike && (alg_info_ike->alg_info_flags & ALG_INFO_F_STRICT) ) {
276 struct ike_info *ike_info;
277 ALG_INFO_IKE_FOREACH(alg_info_ike, ike_info, i) {
278 if ((ike_info->ike_ealg == ealg) &&
279 ((ike_info->ike_eklen==0) || (key_len==0) ||
280 (ike_info->ike_eklen==key_len))) {
281 return_on(ret, TRUE);
284 snprintf(errbuf, sizeof(errbuf),
285 "strict flag and encrypt algorithm "
286 "not in transform string list: "
288 "key_len=%d, keyminbits=%d, keymaxbits=%d",
293 log("%s(): %s", __FUNCTION__, errbuf);
294 return_on(ret, FALSE);
299 DBG_log("%s(ealg=%d,key_len=%d): "
300 "blocksize=%d, keyminlen=%d, "
301 "keydeflen=%d, keymaxlen=%d, "
305 enc_desc->enc_blocksize,
311 DBG_log("%s(ealg=%d,key_len=%d): NO",
312 __FUNCTION__, ealg, key_len);
319 * return ike_algo object by {type, id}
321 /* XXX:jjo use keysize */
323 ike_alg_find(unsigned algo_type, unsigned algo_id, unsigned keysize __attribute__((unused)))
325 struct ike_alg *e=ike_alg_base[algo_type];
326 for(;e!=NULL;e=e->algo_next) {
327 if (e->algo_id==algo_id)
335 * Main "raw" ike_alg list adding function
338 ike_alg_add(struct ike_alg* a)
341 const char *ugh="No error";
342 if (a->algo_type > IKE_ALG_MAX)
344 ugh="Invalid algo_type";
345 return_on(ret,-EINVAL);
347 if (ike_alg_find(a->algo_type, a->algo_id, 0))
349 ugh="Algorithm already exists";
350 return_on(ret,-EEXIST);
353 a->algo_next=ike_alg_base[a->algo_type];
354 ike_alg_base[a->algo_type]=a;
358 log("%s(): ERROR: %s", __FUNCTION__, ugh);
363 * Validate and register IKE hash algorithm object
366 ike_alg_register_hash(struct hash_desc *hash_desc)
368 const char *alg_name;
370 if (hash_desc->algo_id > OAKLEY_HASH_MAX) {
371 log ("%s(): hash alg=%d < max=%d",
372 __FUNCTION__, hash_desc->algo_id, OAKLEY_HASH_MAX);
373 return_on(ret,-EINVAL);
375 if (hash_desc->hash_ctx_size > sizeof (union hash_ctx)) {
376 log ("%s(): hash alg=%d has "
377 "ctx_size=%d > hash_ctx=%d",
380 hash_desc->hash_ctx_size,
381 sizeof (union hash_ctx));
382 return_on(ret,-EOVERFLOW);
384 if (!(hash_desc->hash_init&&hash_desc->hash_update&&hash_desc->hash_final)) {
385 log ("%s(): hash alg=%d needs "
386 "hash_init(), hash_update() and hash_final()",
387 __FUNCTION__, hash_desc->algo_id);
388 return_on(ret,-EINVAL);
390 alg_name=enum_name(&oakley_hash_names, hash_desc->algo_id);
392 log ("%s(): WARNING: hash alg=%d not found in "
393 "constants.c:oakley_hash_names ",
394 __FUNCTION__, hash_desc->algo_id);
400 ret=ike_alg_add((struct ike_alg *)hash_desc);
401 log("%s: Activating %s: %s (ret=%d)",
403 alg_name, ret==0? "Ok" : "FAILED", ret);
408 * Validate and register IKE encryption algorithm object
411 ike_alg_register_enc(struct encrypt_desc *enc_desc)
413 const char *alg_name;
415 if (enc_desc->algo_id > OAKLEY_ENCRYPT_MAX) {
416 log ("%s(): enc alg=%d < max=%d\n",
418 enc_desc->algo_id, OAKLEY_ENCRYPT_MAX);
419 return_on(ret, -EINVAL);
421 alg_name=enum_name(&oakley_enc_names, enc_desc->algo_id);
423 log ("%s(): WARNING: enc alg=%d not found in "
424 "constants.c:oakley_enc_names ",
425 __FUNCTION__, enc_desc->algo_id);
430 ret=ike_alg_add((struct ike_alg *)enc_desc);
431 log("%s: Activating %s: %s (ret=%d)",
433 alg_name, ret==0? "Ok" : "FAILED", ret);