📄 ipsec_esp.c
字号:
/* * processing code for ESP * Copyright (C) 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */char ipsec_esp_c_version[] = "RCSID $Id: ipsec_esp.c,v 1.8 2004/09/14 00:22:57 mcr Exp $";#include <linux/config.h>#include <linux/version.h>#define __NO_VERSION__#include <linux/module.h>#include <linux/kernel.h> /* printk() */#include "openswan/ipsec_param.h"#ifdef MALLOC_SLAB# include <linux/slab.h> /* kmalloc() */#else /* MALLOC_SLAB */# include <linux/malloc.h> /* kmalloc() */#endif /* MALLOC_SLAB */#include <linux/errno.h> /* error codes */#include <linux/types.h> /* size_t */#include <linux/interrupt.h> /* mark_bh */#include <linux/netdevice.h> /* struct device, and other headers */#include <linux/etherdevice.h> /* eth_type_trans */#include <linux/ip.h> /* struct iphdr */#include <linux/skbuff.h>#include <openswan.h>#ifdef SPINLOCK# ifdef SPINLOCK_23# include <linux/spinlock.h> /* *lock* */# else /* SPINLOCK_23 */# include <asm/spinlock.h> /* *lock* */# endif /* SPINLOCK_23 */#endif /* SPINLOCK */#ifdef NET_21# include <asm/uaccess.h># include <linux/in6.h># define proto_priv cb#endif /* NET21 */#include <asm/checksum.h>#include <net/ip.h>#include <net/protocol.h>#include "openswan/radij.h"#include "openswan/ipsec_encap.h"#include "openswan/ipsec_sa.h"#include "openswan/ipsec_radij.h"#include "openswan/ipsec_xform.h"#include "openswan/ipsec_tunnel.h"#include "openswan/ipsec_rcv.h"#include "openswan/ipsec_xmit.h"#include "openswan/ipsec_auth.h"#ifdef CONFIG_KLIPS_ESP#include "openswan/ipsec_esp.h"#endif /* CONFIG_KLIPS_ESP */#include "openswan/ipsec_proto.h"#include "openswan/ipsec_alg.h"#ifdef CONFIG_KLIPS_ESPenum ipsec_rcv_valueipsec_rcv_esp_checks(struct ipsec_rcv_state *irs, struct sk_buff *skb){ __u8 proto; int len; /* packet length */ len = skb->len; proto = irs->ipp->protocol; /* XXX this will need to be 8 for IPv6 */ if ((proto == IPPROTO_ESP) && ((len - irs->iphlen) % 4)) { printk("klips_error:ipsec_rcv: " "got packet with content length = %d from %s -- should be on 4 octet boundary, packet dropped\n", len - irs->iphlen, irs->ipsaddr_txt); if(irs->stats) { irs->stats->rx_errors++; } return IPSEC_RCV_BADLEN; } if(skb->len < (irs->hard_header_len + sizeof(struct iphdr) + sizeof(struct esphdr))) { KLIPS_PRINT(debug_rcv & DB_RX_INAU, "klips_debug:ipsec_rcv: " "runt esp packet of skb->len=%d received from %s, dropped.\n", skb->len, irs->ipsaddr_txt); if(irs->stats) { irs->stats->rx_errors++; } return IPSEC_RCV_BADLEN; } irs->protostuff.espstuff.espp = (struct esphdr *)(skb->data + irs->iphlen); irs->said.spi = irs->protostuff.espstuff.espp->esp_spi; return IPSEC_RCV_OK;}enum ipsec_rcv_valueipsec_rcv_esp_decrypt_setup(struct ipsec_rcv_state *irs, struct sk_buff *skb, __u32 *replay, unsigned char **authenticator){ struct esphdr *espp = irs->protostuff.espstuff.espp; KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "packet from %s received with seq=%d (iv)=0x%08x%08x iplen=%d esplen=%d sa=%s\n", irs->ipsaddr_txt, (__u32)ntohl(espp->esp_rpl), (__u32)ntohl(*((__u32 *)(espp->esp_iv) )), (__u32)ntohl(*((__u32 *)(espp->esp_iv) + 1)), irs->len, irs->ilen, irs->sa_len ? irs->sa : " (error)"); *replay = ntohl(espp->esp_rpl); *authenticator = &(skb->data[irs->len - irs->authlen]); return IPSEC_RCV_OK;}enum ipsec_rcv_valueipsec_rcv_esp_authcalc(struct ipsec_rcv_state *irs, struct sk_buff *skb){ struct auth_alg *aa; struct esphdr *espp = irs->protostuff.espstuff.espp; union { MD5_CTX md5; SHA1_CTX sha1; } tctx;#ifdef CONFIG_KLIPS_ALG if (irs->ipsp->ips_alg_auth) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "ipsec_alg hashing proto=%d... ", irs->said.proto); if(irs->said.proto == IPPROTO_ESP) { ipsec_alg_sa_esp_hash(irs->ipsp, (caddr_t)espp, irs->ilen, irs->hash, AHHMAC_HASHLEN); return IPSEC_RCV_OK; } return IPSEC_RCV_BADPROTO; }#endif aa = irs->authfuncs; /* copy the initialized keying material */ memcpy(&tctx, irs->ictx, irs->ictx_len); (*aa->update)((void *)&tctx, (caddr_t)espp, irs->ilen); (*aa->final)(irs->hash, (void *)&tctx); memcpy(&tctx, irs->octx, irs->octx_len); (*aa->update)((void *)&tctx, irs->hash, aa->hashlen); (*aa->final)(irs->hash, (void *)&tctx); return IPSEC_RCV_OK;}enum ipsec_rcv_valueipsec_rcv_esp_decrypt(struct ipsec_rcv_state *irs){ struct ipsec_sa *ipsp = irs->ipsp; struct esphdr *espp = irs->protostuff.espstuff.espp; int esphlen = 0; __u8 *idat; /* pointer to content to be decrypted/authenticated */ __u32 iv[2]; int pad = 0, padlen; int badpad = 0; int i; struct sk_buff *skb;#ifdef CONFIG_KLIPS_ALG struct ipsec_alg_enc *ixt_e=NULL;#endif /* CONFIG_KLIPS_ALG */ skb=irs->skb; idat = skb->data + irs->iphlen;#ifdef CONFIG_KLIPS_ALG if ((ixt_e=ipsp->ips_alg_enc)) { esphlen = ESP_HEADER_LEN + ixt_e->ixt_ivlen/8; KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "encalg=%d esphlen=%d\n", ipsp->ips_encalg, esphlen); } else#endif /* CONFIG_KLIPS_ALG */ switch(ipsp->ips_encalg) { case ESP_3DES: iv[0] = *((__u32 *)(espp->esp_iv) ); iv[1] = *((__u32 *)(espp->esp_iv) + 1); esphlen = sizeof(struct esphdr); break; default: ipsp->ips_errs.ips_alg_errs += 1; if(irs->stats) { irs->stats->rx_errors++; } return IPSEC_RCV_ESP_BADALG; } idat += esphlen; irs->ilen -= esphlen;#ifdef CONFIG_KLIPS_ALG if (ixt_e) { if (ipsec_alg_esp_encrypt(ipsp, idat, irs->ilen, espp->esp_iv, IPSEC_ALG_DECRYPT) <= 0) { printk("klips_error:ipsec_rcv: " "got packet with esplen = %d " "from %s -- should be on " "ENC(%d) octet boundary, " "packet dropped\n", irs->ilen, irs->ipsaddr_txt, ipsp->ips_encalg); if(irs->stats) { irs->stats->rx_errors++; } return IPSEC_RCV_BAD_DECRYPT; } } else#endif /* CONFIG_KLIPS_ALG */ switch(ipsp->ips_encalg) { case ESP_3DES: if ((irs->ilen) % 8) { ipsp->ips_errs.ips_encsize_errs += 1; printk("klips_error:ipsec_rcv: " "got packet with esplen = %d from %s -- should be on 8 octet boundary, packet dropped\n", irs->ilen, irs->ipsaddr_txt); if(irs->stats) { irs->stats->rx_errors++; } return IPSEC_RCV_3DES_BADBLOCKING; } des_ede3_cbc_encrypt((des_cblock *)idat, (des_cblock *)idat, irs->ilen, ((struct des_eks *)(ipsp->ips_key_e))[0].ks, ((struct des_eks *)(ipsp->ips_key_e))[1].ks, ((struct des_eks *)(ipsp->ips_key_e))[2].ks, (des_cblock *)iv, 0); break; } ipsec_rcv_dmp("postdecrypt", skb->data, skb->len); irs->next_header = idat[irs->ilen - 1]; padlen = idat[irs->ilen - 2]; pad = padlen + 2 + irs->authlen; KLIPS_PRINT(debug_rcv & DB_RX_IPAD, "klips_debug:ipsec_rcv: " "padlen=%d, contents: 0x<offset>: 0x<value> 0x<value> ...\n", padlen); for (i = 1; i <= padlen; i++) { if((i % 16) == 1) { KLIPS_PRINT(debug_rcv & DB_RX_IPAD, "klips_debug: %02x:", i - 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -