source: trunk/packages/xen-3.1/xen-3.1/tools/vnet/vnet-module/sa.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 17 years ago

Add xen and xen-common

File size: 19.5 KB
Line 
1/*
2 * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it 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.
8 *
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
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free software Foundation, Inc.,
16 * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
17 *
18 */
19#include <linux/config.h>
20#include <linux/kernel.h>
21
22#include <tunnel.h>
23#include <vnet.h>
24#include <sa.h>
25#include <sa_algorithm.h>
26
27#include "hash_table.h"
28#include "allocate.h"
29
30#define MODULE_NAME "IPSEC"
31#define DEBUG 1
32#undef DEBUG
33#include "debug.h"
34
35/** @file IPSEC Security Association (SA).
36 */
37
38/** Maximum number of protocols.*/
39#define INET_PROTOCOL_MAX 256
40
41/** Table of SA types indexed by protocol. */
42static SAType *sa_type[INET_PROTOCOL_MAX] = {};
43
44/** Hash a protocol number.
45 *
46 * @param protocol protocol number
47 * @return hashcode
48 */
49static inline unsigned char InetProtocol_hash(int protocol){
50    return (protocol) & (INET_PROTOCOL_MAX - 1);
51}
52
53/** Register an SA type.
54 * It is an error if an SA type is already registered for the protocol.
55 *
56 * @param type SA type
57 * @return 0 on success, error code otherwise
58 */
59int SAType_add(SAType *type){
60    int err = -EINVAL;
61    int hash;
62    if(!type) goto exit;
63    hash = InetProtocol_hash(type->protocol);
64    if(sa_type[hash]) goto exit;
65    err = 0;
66    sa_type[hash] = type;
67  exit:
68    return err;
69}
70
71/** Deregister an SA type.
72 * It is an error if no SA type is registered for the protocol.
73 *
74 * @param type SA type
75 * @return 0 on success, error code otherwise
76 */
77int SAType_del(SAType *type){
78    int err = -EINVAL;
79    int hash;
80    if(!type) goto exit;
81    hash = InetProtocol_hash(type->protocol);
82    if(!sa_type[hash]) goto exit;
83    err = 0;
84    sa_type[hash] = NULL;
85  exit:
86    return err;
87}
88
89int SAType_get(int protocol, SAType **type){
90   int err = -ENOENT;
91   int hash;
92   hash = InetProtocol_hash(protocol);
93   *type = sa_type[hash];
94   if(!*type) goto exit;
95   err = 0;
96  exit:
97   return err;
98}
99
100/* Defeat compiler warnings about unused functions. */
101static int sa_key_check(SAKey *key, enum sa_alg_type type) __attribute__((unused));
102static u32 random_spi(void) __attribute__((unused));
103static u32 generate_key(u32 key, u32 offset, u32 spi) __attribute__((unused));
104
105/** Check a key has an acceptable length for an algorithm.
106 *
107 * @param key key
108 * @param type algorithm
109 * @return 0 on success, error code otherwise
110 */
111static int sa_key_check(SAKey *key, enum sa_alg_type type){
112    return 0;
113}
114
115static unsigned long sa_spi_counter = 0;
116
117/** Mangle some input to generate output.
118 * This is used to derive spis and keying material from secrets,
119 * so it probably ought to be cryptographically strong.
120 * Probably ought to use a good hash (sha1) or cipher (aes).
121 *
122 * @param input input bytes
123 * @param n number of bytes
124 * @return mangled value
125 */
126static u32 mangle(void *input, int n){
127    return hash_hvoid(0, input, n);
128}
129
130/** Generate a random spi.
131 * Uses a hashed counter.
132 *
133 * @return spi
134 */
135static u32 random_spi(void){
136    u32 spi;
137    do{
138        spi = sa_spi_counter++;
139        spi = mangle(&spi, sizeof(spi));
140    } while(!spi);
141    return spi;
142}
143
144 /** Generate a spi for a given protocol and address, using a secret key.
145  * The offset is used when it is necessary to generate more than one spi
146  * for the same protocol and address.
147  *
148  * @param key key
149  * @param offset offset
150  * @param protocol protocol
151  * @param addr IP address
152  * @return spi
153  */
154static u32 generate_spi(u32 key, u32 offset, u32 protocol, u32 addr){
155    u32 input[] = { key, offset, protocol, addr };
156    return mangle(input, sizeof(input));
157}
158
159/** Generate keying material for a given spi, based on a
160 * secret.
161 *
162 * @param key secret
163 * @param offset offset
164 * @param spi spi
165 * @return keying material
166 */
167static u32 generate_key(u32 key, u32 offset, u32 spi){
168    u32 input[] = { key, offset, spi };
169    return mangle(input, sizeof(input));
170}   
171
172/** Allocate a spi.
173 * Want to use random ones.
174 * So check for ones not in use.
175 *
176 * When using static keying, both ends need to agree on key.
177 * How does that work? Also, will suddenly get traffic using a spi,
178 * and will have to create SA then. Or need to create in advance.
179 * But can't do that because don't know peers.
180 * When get message on a spi that doesn't exist - do what?
181 * Use a spi related to the destination addr and a secret.
182 * Then receiver can check if spi is ok and create SA on demand.
183 * Use hash of key, protocol, addr to generate. Then have to check
184 * for in-use because of potential collisions. Receiver can do the
185 * same hash and check spi is in usable range. Then derive keys from
186 * the spi (using another secret).
187 *
188 * @param key spi generation key
189 * @param protocol protocol
190 * @param addr IP address
191 * @param spip return parameter for spi
192 * @return 0 on success, error code otherwise
193 */
194int sa_spi_alloc(u32 key, u32 protocol, u32 addr, u32 *spip){
195    int err = 0;
196    int i = 0, n = 100;
197    u32 spi;
198    for(i = 0; i < n; i++, spi++){
199        spi = generate_spi(key, i, protocol, addr);
200        if(!spi) continue;
201        if(!sa_table_lookup_spi(spi, protocol, addr)){
202            *spip = spi;
203            goto exit;
204        }
205    }
206    err = -ENOMEM;
207  exit:
208    return err;
209}
210
211/** Table of SAs. Indexed by unique id and spi/protocol/addr triple.
212 */
213static HashTable *sa_table = NULL;
214
215static u32 sa_id = 1;
216
217/** Hash an SA id.
218 *
219 * @param id SA id
220 * @return hashcode
221 */
222static inline Hashcode sa_table_hash_id(u32 id){
223    return hash_hvoid(0, &id, sizeof(id));
224}
225
226/** Hash SA spi/protocol/addr.
227 *
228 * @param spi spi
229 * @param protocol protocol
230 * @param addr IP address
231 * @return hashcode
232 */
233static inline Hashcode sa_table_hash_spi(u32 spi, u32 protocol, u32 addr){
234    u32 a[] = { spi, protocol, addr };
235    return hash_hvoid(0, a, sizeof(a));
236}
237
238/** Test if an SA entry has a given value.
239 *
240 * @param arg contains SA pointer
241 * @param table hashtable
242 * @param entry entry containing SA
243 * @return 1 if it does, 0 otherwise
244 */
245static int sa_table_state_fn(TableArg arg, HashTable *table, HTEntry *entry){
246    return entry->value == arg.ptr;
247}
248
249/** Test if an SA entry has a given id.
250 *
251 * @param arg contains SA id
252 * @param table hashtable
253 * @param entry entry containing SA
254 * @return 1 if it does, 0 otherwise
255 */
256static int sa_table_id_fn(TableArg arg, HashTable *table, HTEntry *entry){
257    SAState *state = entry->value;
258    u32 id = arg.ul;
259    return state->ident.id == id;
260}
261
262/** Test if an SA entry has a given spi/protocol/addr.
263 *
264 * @param arg contains SAIdent pointer
265 * @param table hashtable
266 * @param entry entry containing SA
267 * @return 1 if it does, 0 otherwise
268 */
269static int sa_table_spi_fn(TableArg arg, HashTable *table, HTEntry *entry){
270    SAState *state = entry->value;
271    SAIdent *ident = arg.ptr;
272    return state->ident.spi      == ident->spi
273        && state->ident.protocol == ident->protocol
274        && state->ident.addr     == ident->addr;
275}
276
277/** Free an SA entry. Decrements the SA refcount and frees the entry.
278 *
279 * @param table containing table
280 * @param entry to free
281 */
282static void sa_table_free_fn(HashTable *table, HTEntry *entry){
283    if(!entry) return;
284    if(entry->value){
285        SAState *state = entry->value;
286        SAState_decref(state);
287    }
288    deallocate(entry);
289}
290
291/** Initialize the SA table.
292 *
293 * @return 0 on success, error code otherwise
294 */
295int sa_table_init(void){
296    int err = 0;
297    sa_table = HashTable_new(0);
298    if(!sa_table){
299        err = -ENOMEM;
300        goto exit;
301    }
302    sa_table->entry_free_fn = sa_table_free_fn;
303
304  exit:
305    return err;
306}
307
308void sa_table_exit(void){
309    HashTable_free(sa_table);
310}
311
312/** Remove an SA from the table.
313 *
314 * @param state SA
315 */
316int sa_table_delete(SAState *state){
317    int count = 0;
318    Hashcode h1, h2;
319    TableArg arg = { .ptr = state };
320    // Remove by id.
321    h1 = sa_table_hash_id(state->ident.id);
322    count += HashTable_remove_entry(sa_table, h1, sa_table_state_fn, arg);
323    // Remove by spi/protocol/addr if spi nonzero.
324    if(!state->ident.spi) goto exit;
325    h2 = sa_table_hash_spi(state->ident.spi, state->ident.protocol, state->ident.addr);
326    if(h1 == h2) goto exit;
327    count += HashTable_remove_entry(sa_table, h2, sa_table_state_fn, arg);
328  exit:
329    return count;
330}
331
332/** Add an SA to the table.
333 * The SA is indexed by id and spi/protocol/addr (if the spi is non-zero).
334 *
335 * @param state SA
336 * @return 0 on success, error code otherwise
337 */
338int sa_table_add(SAState *state){
339    int err = 0;
340    Hashcode h1, h2;
341    int entries = 0;
342
343    dprintf(">\n");
344    // Index by id.
345    h1 = sa_table_hash_id(state->ident.id);
346    if(!HashTable_add_entry(sa_table, h1, HKEY(state->ident.id), state)){
347        err = -ENOMEM;
348        goto exit;
349    }
350    entries++;
351    SAState_incref(state);
352    // Index by spi/protocol/addr if spi non-zero.
353    if(state->ident.spi){
354        h2 = sa_table_hash_spi(state->ident.spi, state->ident.protocol, state->ident.addr);
355        if(h1 != h2){
356            if(!HashTable_add_entry(sa_table, h2, HKEY(state->ident.id), state)){
357                err = -ENOMEM;
358                goto exit;
359            }
360            entries++;
361            SAState_incref(state);
362        }
363    }
364  exit:
365    if(err && entries){
366        sa_table_delete(state);
367    }
368    dprintf("< err=%d\n", err);
369    return err;
370}
371
372
373/** Find an SA by spi/protocol/addr.
374 * Increments the SA refcount on success.
375 *
376 * @param spi spi
377 * @param protocol protocol
378 * @param addr IP address
379 * @return SA or NULL
380 */
381SAState * sa_table_lookup_spi(u32 spi, u32 protocol, u32 addr){
382    SAState *state = NULL;
383    Hashcode h;
384    SAIdent id = {
385        .spi      = spi,
386        .protocol = protocol,
387        .addr     = addr };
388    TableArg arg = { .ptr = &id };
389    HTEntry *entry = NULL;
390
391    h = sa_table_hash_spi(spi, protocol, addr);
392    entry = HashTable_find_entry(sa_table, h, sa_table_spi_fn, arg);
393    if(entry){
394        state = entry->value;
395        SAState_incref(state);
396    }
397    return state;
398}
399
400/** Find an SA by unique id.
401 * Increments the SA refcount on success.
402 *
403 * @param id id
404 * @return SA or NULL
405 */
406SAState * sa_table_lookup_id(u32 id){
407    Hashcode h;
408    TableArg arg = { .ul = id };
409    HTEntry *entry = NULL;
410    SAState *state = NULL;
411
412    dprintf("> id=%u\n", id);
413    h = sa_table_hash_id(id);
414    entry = HashTable_find_entry(sa_table, h, sa_table_id_fn, arg);
415    if(entry){
416        state = entry->value;
417        SAState_incref(state);
418    }
419    dprintf("< state=%p\n", state);
420    return state;
421}
422
423/** Replace an existing SA by another in the table.
424 * The existing SA is not removed if the new one cannot be added.
425 *
426 * @param existing SA to replace
427 * @param state new SA
428 * @return 0 on success, error code otherwise
429 */
430static int sa_table_replace(SAState *existing, SAState *state){
431    int err = 0;
432    // Need check for in-use?
433   
434    dprintf(">\n");
435    if(existing->keying.state != SA_STATE_ACQUIRE){
436        err = -EINVAL;
437        goto exit;
438    }
439    // replace it.
440    err = sa_table_add(state);
441    if(err) goto exit;
442    sa_table_delete(existing);
443  exit:
444    dprintf("< err=%d\n", err);
445    return err;
446}
447
448/** Allocate an SA.
449 *
450 * @return SA or NULL
451 */
452SAState *SAState_alloc(void){
453    SAState *state;
454   
455    dprintf(">\n");
456    state = kmalloc(sizeof(SAState), GFP_ATOMIC);
457    if(!state) goto exit;
458    *state = (SAState){};
459    atomic_set(&state->refcount, 1);
460    state->lock = SPIN_LOCK_UNLOCKED;
461  exit:
462    dprintf("< state=%p\n", state);
463    return state;
464}
465
466/** Create an SA in initial state.
467 * It has no spi and its keying state is acquire.
468 * It must have a unique id, protocol and address.
469 * At some point it should get updated with a complete SA.
470 *
471 * @param ident SA identifier
472 * @param statep return parameter for new SA
473 * @return 0 on success, error code otherwise
474 */
475int SAState_init(SAIdent *ident, SAState **statep){
476    int err = 0;
477    SAState *state = NULL;
478   
479    if(ident->spi || !ident->id){
480        err = -EINVAL;
481        goto exit;
482    }
483    state = SAState_alloc();
484    if (!state){
485        err = -ENOMEM;
486        goto exit;
487    }
488    state->ident = *ident;
489    state->keying.state = SA_STATE_ACQUIRE;
490  exit:
491    return err;
492}
493
494/** Create a complete SA, with spi and cipher suite.
495 *
496 * @param info SA parameters
497 * @param statep return parameter for new SA
498 * @return 0 on success, error code otherwise
499 */
500int SAState_create(SAInfo *info, SAState **statep){
501    int err = 0;
502    SAState *state = NULL;
503
504    dprintf(">\n");
505    state = SAState_alloc();
506    if (!state){
507        err = -ENOMEM;
508        goto exit;
509    }
510    state->ident = info->ident;
511    state->limits = info->limits;
512    state->digest = info->digest;
513    state->cipher = info->cipher;
514    state->compress = info->compress;
515    state->security = info->security;
516    err = SAType_get(state->ident.protocol, &state->type);
517    if (err) goto exit;
518    err = state->type->init(state, NULL);
519    if (err) goto exit;
520    state->keying.state = SA_STATE_VALID;
521  exit:
522    if(err){
523        SAState_decref(state);
524        state = NULL;
525    }
526    *statep = state;
527    dprintf("< err=%d\n", err);
528    return err;
529}
530
531/** Create an SA for the given spi etc.
532 * For now we fix the cipher suite and the keys.
533 * Digest is SHA1 HMAC with a 128-bit key.
534 * Cipher is AES (Rijndael) in CBC mode with a 128-bit key.
535 *
536 * The cipher suite and keys should really come from policy, with the
537 * possibility of negotiating them with the peer (using IKE).
538 * Negotiation creates difficulties though - because the SA cannot
539 * be created immediately we have to be able to queue packets
540 * while the SA is being negotiated.
541 *
542 * @param spi spi
543 * @param protocol protocol
544 * @param addr address
545 * @param sa return parameter for SA
546 * @return 0 on success, error code otherwise
547 */
548int sa_create(int security, u32 spi, u32 protocol, u32 addr, SAState **sa){
549    int err = 0;
550    SAInfo info = {};
551    char *digest_name = "sha1";
552    char *digest_key = "0123456789abcdef";
553    int digest_key_n = strlen(digest_key);
554    char *cipher_name= "aes";
555    char *cipher_key = "0123456789ABCDEF";
556    int cipher_key_n = strlen(cipher_key);
557
558    dprintf("> security=%d spi=%u protocol=%u addr=" IPFMT "\n",
559            security, spi, protocol, NIPQUAD(addr));
560    if(!spi){
561        spi = generate_spi(0, 0, protocol, addr);
562    }
563    dprintf("> info...\n");
564    info.ident.id = sa_id++;
565    info.ident.spi = spi;
566    info.ident.protocol = protocol;
567    info.ident.addr = addr;
568    info.security = security;
569
570    //sa_algorithm_probe_all();
571
572    dprintf("> digest name=%s key_n=%d\n", digest_name, digest_key_n);
573    strcpy(info.digest.name, digest_name);
574    info.digest.bits = digest_key_n * 8;
575    memcpy(info.digest.key, digest_key, digest_key_n);
576
577    if(security & SA_CONF){
578        dprintf("> cipher name=%s key_n=%d\n", cipher_name, cipher_key_n);
579        strcpy(info.cipher.name, cipher_name);
580        info.cipher.bits = cipher_key_n * 8;
581        memcpy(info.cipher.key, cipher_key, cipher_key_n);
582    } else {
583        dprintf("> cipher name=%s key_n=%d\n", "cipher_null", 0);
584        strcpy(info.cipher.name, "cipher_null");
585        info.cipher.bits = 0;
586        memset(info.cipher.key, 0, sizeof(info.cipher.key));
587    }
588
589    err = sa_set(&info, 0, sa);
590    dprintf("< err=%d\n", err);
591    return err;
592}
593
594/** Create or update an SA.
595 * The SA is added to the table.
596 *
597 * @param info SA parameters
598 * @param update create if zero, update otherwise
599 * @return 0 on success, error code otherwise
600 */
601int sa_set(SAInfo *info, int update, SAState **val){
602    int err = 0;
603    SAState *state = NULL;
604    SAState *existing = NULL;
605
606    dprintf("> info=%p update=%d val=%p\n", info, update, val);
607    existing = sa_table_lookup_id(info->ident.id);
608    if(update && !existing){
609        err = -ENOENT;
610    } else if(!update && existing){
611        err = -EINVAL;
612    }
613    if(err) goto exit;
614    err = SAState_create(info, &state);
615    if (err) goto exit;
616    if(existing){
617        err = sa_table_replace(existing, state);
618    } else {
619        err = sa_table_add(state);
620    }
621  exit:
622    if(existing) SAState_decref(existing);
623    if(val && !err){
624        *val = state;
625    } else {
626        SAState_decref(state);
627    }
628    dprintf("< err=%d\n", err);
629    return err;
630}
631
632/** Delete an SA. Removes it from the SA table.
633 * It is an error if no SA with the given id exists.
634 *
635 * @param id SA id
636 * @return 0 on success, error code otherwise
637 */
638int sa_delete(int id){
639    int err = 0;
640    SAState *state;
641    state = sa_table_lookup_id(id);
642    if (!state){
643        err = -ENOENT;
644        goto exit;
645    }
646    sa_table_delete(state);
647    SAState_decref(state);
648  exit:
649    return err;
650}
651/** Determine ESP security mode for a new SA.
652 *
653 * @param spi incoming spi
654 * @param protocol incoming protocol
655 * @param addr source address
656 * @return security level or negative error code
657 *
658 * @todo Need to check spi, and do some lookup for security params.
659 */
660int vnet_sa_security(u32 spi, int protocol, u32 addr){
661    extern int vnet_security_default;
662    int security = vnet_security_default;
663    dprintf("< security=%x\n", security);
664    return security;
665}
666
667/** Create a new SA for incoming traffic.
668 *
669 * @param spi incoming spi
670 * @param protocol incoming protocol
671 * @param addr source address
672 * @param sa return parameter for SA
673 * @return 0 on success, error code otherwise
674 */
675int vnet_sa_create(u32 spi, int protocol, u32 addr, SAState **sa){
676    int err = 0;
677    int security = vnet_sa_security(spi, protocol, addr);
678    if(security < 0){
679        err = security;
680        goto exit;
681    }
682    err = sa_create(security, spi, protocol, addr, sa);
683  exit:
684    return err;
685}
686/** Open function for SA tunnels.
687 *
688 * @param tunnel to open
689 * @return 0 on success, error code otherwise
690 */
691static int sa_tunnel_open(Tunnel *tunnel){
692    int err = 0;
693    //dprintf(">\n");
694    //dprintf("< err=%d\n", err);
695    return err;
696}
697
698/** Close function for SA tunnels.
699 *
700 * @param tunnel to close (OK if null)
701 */
702static void sa_tunnel_close(Tunnel *tunnel){
703    SAState *sa;
704    if(!tunnel) return;
705    sa = tunnel->data;
706    if(!sa) return;
707    SAState_decref(sa);
708    tunnel->data = NULL;
709}
710
711/** Packet send function for SA tunnels.
712 *
713 * @param tunnel to send on
714 * @param skb packet to send
715 * @return 0 on success, negative error code on error
716 */
717static int sa_tunnel_send(Tunnel *tunnel, struct sk_buff *skb){
718    int err = -EINVAL;
719    SAState *sa;
720    if(!tunnel){
721        wprintf("> Null tunnel!\n");
722        goto exit;
723    }
724    sa = tunnel->data;
725    if(!sa){
726        wprintf("> Null SA!\n");
727        goto exit;
728    }
729    err = SAState_send(sa, skb, tunnel->base);
730  exit:
731    return err;
732}
733
734/** Functions used by SA tunnels. */
735static TunnelType _sa_tunnel_type = {
736    .name       = "SA",
737    .open       = sa_tunnel_open,
738    .close      = sa_tunnel_close,
739    .send       = sa_tunnel_send
740};
741
742/** Functions used by SA tunnels. */
743TunnelType *sa_tunnel_type = &_sa_tunnel_type;
744
745int sa_tunnel_create(Vnet *info, VarpAddr *addr, Tunnel *base, Tunnel **tunnel){
746    int err = 0;
747    SAState *sa = NULL;
748    //FIXME: Assuming IPv4 for now.
749    u32 ipaddr = addr->u.ip4.s_addr;
750    err = Tunnel_create(sa_tunnel_type, &info->vnet, addr, base, tunnel);
751    if(err) goto exit;
752    err = sa_create(info->security, 0, IPPROTO_ESP, ipaddr, &sa);
753    if(err) goto exit;
754    (*tunnel)->data = sa;
755  exit:
756    return err;
757}
Note: See TracBrowser for help on using the repository browser.