📄 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.13.2.4 2006/05/06 03:07:38 ken 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 */#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_DEBUG#define ESP_DMP(_x,_y,_z) if(debug_rcv && sysctl_ipsec_debug_verbose) ipsec_dmp_block(_x,_y,_z)#else#define ESP_DMP(_x,_y,_z)#endif#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->h.raw; 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; //unsigned char *idat = (unsigned char *)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->h.raw[irs->ilen]); 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; 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; } aa = irs->authfuncs; /* copy the initialized keying material */ memcpy(&tctx, irs->ictx, irs->ictx_len);#ifdef HASH_DEBUG ESP_DMP("ictx", irs->ictx, irs->ictx_len); ESP_DMP("mac_esp", (caddr_t)espp, irs->ilen);#endif (*aa->update)((void *)&tctx, (caddr_t)espp, irs->ilen); (*aa->final)(irs->hash, (void *)&tctx);#ifdef HASH_DEBUG ESP_DMP("hash1", irs->hash, aa->hashlen);#endif memcpy(&tctx, irs->octx, irs->octx_len);#ifdef HASH_DEBUG ESP_DMP("octx", irs->octx, irs->octx_len);#endif (*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 i; int pad = 0, padlen; int badpad = 0; int esphlen = 0; __u8 *idat; /* pointer to content to be decrypted/authenticated */ int encaplen = 0; struct sk_buff *skb; struct ipsec_alg_enc *ixt_e=NULL; skb=irs->skb; idat = skb->h.raw; /* encaplen is the distance between the end of the IP * header and the beginning of the ESP header. * on ESP headers it is zero, but on UDP-encap ESP * it includes the space for the UDP header. * * Note: UDP-encap code has already moved the * skb->data forward to accomodate this. */ encaplen = idat - (skb->nh.raw + irs->iphlen); ixt_e=ipsp->ips_alg_enc; esphlen = ESP_HEADER_LEN + ixt_e->ixt_common.ixt_support.ias_ivlen/8; KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "encalg=%d esphlen=%d\n", ipsp->ips_encalg, esphlen); idat += esphlen; irs->ilen -= esphlen; if (ipsec_alg_esp_encrypt(ipsp, idat, irs->ilen, espp->esp_iv, IPSEC_ALG_DECRYPT) <= 0) { KLIPS_ERROR(debug_rcv, "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; } ESP_DMP("postdecrypt", idat, irs->ilen); 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); } KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD, " %02x", idat[irs->ilen - 2 - padlen + i - 1]); if(i != idat[irs->ilen - 2 - padlen + i - 1]) { badpad = 1; } if((i % 16) == 0) { KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD, "\n"); } } if((i % 16) != 1) { KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD, "\n"); } if(badpad) { KLIPS_PRINT(debug_rcv & DB_RX_IPAD, "klips_debug:ipsec_rcv: " "warning, decrypted packet from %s has bad padding\n", irs->ipsaddr_txt); KLIPS_PRINT(debug_rcv & DB_RX_IPAD, "klips_debug:ipsec_rcv: " "...may be bad decryption -- not dropped\n"); ipsp->ips_errs.ips_encpad_errs += 1; } KLIPS_PRINT(debug_rcv & DB_RX_IPAD, "klips_debug:ipsec_rcv: " "packet decrypted from %s: next_header = %d, padding = %d\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -