suricata
decode-esp.c
Go to the documentation of this file.
1 /* Copyright (C) 2020 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \ingroup decode
20  *
21  * @{
22  */
23 
24 /**
25  * \file
26  *
27  * Decode Encapsulating Security Payload (ESP)
28  */
29 
30 #include "suricata-common.h"
31 #include "decode-esp.h"
32 #include "flow.h"
33 
34 static int DecodeESPPacket(ThreadVars *tv, Packet *p, const uint8_t *pkt, uint16_t len)
35 {
36  if (unlikely(len < ESP_HEADER_LEN)) {
38  return -1;
39  }
40 
41  p->esph = (ESPHdr *)pkt;
42 
43  p->payload = (uint8_t *)pkt + sizeof(ESPHdr);
44  p->payload_len = len - sizeof(ESPHdr);
45 
46  p->proto = IPPROTO_ESP;
47 
48  return 0;
49 }
50 
51 /**
52  * \brief Function to decode IPSEC-ESP packets
53  * \param tv thread vars
54  * \param dtv decoder thread vars
55  * \param p packet
56  * \param pkt raw packet data
57  * \param len length in bytes of pkt array
58  * \retval TM_ECODE_OK or TM_ECODE_FAILED on serious error
59  */
60 int DecodeESP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
61 {
63 
64  if (!PacketIncreaseCheckLayers(p)) {
65  return TM_ECODE_FAILED;
66  }
67  if (unlikely(DecodeESPPacket(tv, p, pkt, len) < 0)) {
69  return TM_ECODE_FAILED;
70  }
71 
72  SCLogDebug("ESP spi: %" PRIu32 " sequence: %" PRIu32, ESP_GET_SPI(p), ESP_GET_SEQUENCE(p));
73 
74  FlowSetupPacket(p);
75 
76  return TM_ECODE_OK;
77 }
78 
79 #ifdef UNITTESTS
80 
81 #include "util-unittest.h"
82 
83 /** \test Successful decoding */
84 static int DecodeESPTest01(void)
85 {
86  uint8_t raw_esp[] = { 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x08 };
87 
89  FAIL_IF_NULL(p);
90 
91  ThreadVars tv;
93 
94  memset(&tv, 0, sizeof(ThreadVars));
95  memset(&dtv, 0, sizeof(DecodeThreadVars));
96 
97  int ret = DecodeESP(&tv, &dtv, p, raw_esp, sizeof(raw_esp));
98  FAIL_IF(ret != TM_ECODE_OK);
99 
100  FAIL_IF(p->proto != IPPROTO_ESP);
101  FAIL_IF(p->payload_len != sizeof(raw_esp) - ESP_HEADER_LEN);
102  FAIL_IF(ESP_GET_SPI(p) != 0x7b);
103  FAIL_IF(ESP_GET_SEQUENCE(p) != 0x08);
104 
105  SCFree(p);
106 
107  PASS;
108 }
109 
110 /** \test Successful decoding, with payload data */
111 static int DecodeESPTest02(void)
112 {
113  uint8_t raw_esp[] = { 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x08, 0xFF, 0xFF };
114 
115  Packet *p = PacketGetFromAlloc();
116  FAIL_IF_NULL(p);
117 
118  ThreadVars tv;
120 
121  memset(&tv, 0, sizeof(ThreadVars));
122  memset(&dtv, 0, sizeof(DecodeThreadVars));
123 
124  int ret = DecodeESP(&tv, &dtv, p, raw_esp, sizeof(raw_esp));
125  FAIL_IF(ret != TM_ECODE_OK);
126 
127  FAIL_IF(p->proto != IPPROTO_ESP);
128  FAIL_IF(p->payload_len != sizeof(raw_esp) - ESP_HEADER_LEN);
129  FAIL_IF(memcmp(p->payload, raw_esp + ESP_HEADER_LEN, p->payload_len) != 0);
130  FAIL_IF(ESP_GET_SPI(p) != 0x7b);
131  FAIL_IF(ESP_GET_SEQUENCE(p) != 0x08);
132 
133  SCFree(p);
134 
135  PASS;
136 }
137 
138 /** \test Failure decoding, not enough data */
139 static int DecodeESPTest03(void)
140 {
141  uint8_t raw_esp[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
142 
143  Packet *p = PacketGetFromAlloc();
144  FAIL_IF_NULL(p);
145 
146  ThreadVars tv;
148 
149  memset(&tv, 0, sizeof(ThreadVars));
150  memset(&dtv, 0, sizeof(DecodeThreadVars));
151 
152  int ret = DecodeESP(&tv, &dtv, p, raw_esp, sizeof(raw_esp));
153  FAIL_IF(ret != TM_ECODE_FAILED);
154 
155  // expect ESP_PKT_TOO_SMALL
157 
158  SCFree(p);
159 
160  PASS;
161 }
162 
163 /** \test Failure decoding, no data */
164 static int DecodeESPTest04(void)
165 {
166  uint8_t raw_esp[] = {};
167 
168  Packet *p = PacketGetFromAlloc();
169  FAIL_IF_NULL(p);
170 
171  ThreadVars tv;
173 
174  memset(&tv, 0, sizeof(ThreadVars));
175  memset(&dtv, 0, sizeof(DecodeThreadVars));
176 
177  int ret = DecodeESP(&tv, &dtv, p, raw_esp, sizeof(raw_esp));
178  FAIL_IF(ret != TM_ECODE_FAILED);
179 
180  // expect ESP_PKT_TOO_SMALL
182 
183  SCFree(p);
184 
185  PASS;
186 }
187 #endif /* UNITTESTS */
188 
190 {
191 #ifdef UNITTESTS
192  UtRegisterTest("DecodeESPTest01", DecodeESPTest01);
193  UtRegisterTest("DecodeESPTest02", DecodeESPTest02);
194  UtRegisterTest("DecodeESPTest03", DecodeESPTest03);
195  UtRegisterTest("DecodeESPTest04", DecodeESPTest04);
196 #endif /* UNITTESTS */
197 }
198 
199 /**
200  * @}
201  */
Packet_::proto
uint8_t proto
Definition: decode.h:437
len
uint8_t len
Definition: app-layer-dnp3.h:2
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
DecodeESPRegisterTests
void DecodeESPRegisterTests(void)
Definition: decode-esp.c:189
StatsIncr
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition: counters.c:169
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
DecodeESP
int DecodeESP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
Function to decode IPSEC-ESP packets.
Definition: decode-esp.c:60
ENGINE_ISSET_EVENT
#define ENGINE_ISSET_EVENT(p, e)
Definition: decode.h:1035
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
Packet_::payload
uint8_t * payload
Definition: decode.h:552
ESP_PKT_TOO_SMALL
@ ESP_PKT_TOO_SMALL
Definition: decode-events.h:161
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:81
Packet_::payload_len
uint16_t payload_len
Definition: decode.h:553
util-unittest.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression to true.
Definition: util-unittest.h:82
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:80
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
ESP_HEADER_LEN
#define ESP_HEADER_LEN
size of the ESP header
Definition: decode-esp.h:26
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
Packet_
Definition: decode.h:415
ESP_GET_SPI
#define ESP_GET_SPI(p)
Get the spi field off a packet.
Definition: decode-esp.h:32
ESP_GET_SEQUENCE
#define ESP_GET_SEQUENCE(p)
Get the sequence field off a packet.
Definition: decode-esp.h:35
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:30
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
suricata-common.h
DecodeThreadVars_::counter_esp
uint16_t counter_esp
Definition: decode.h:666
decode-esp.h
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:29
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:150
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:639
ENGINE_SET_INVALID_EVENT
#define ENGINE_SET_INVALID_EVENT(p, e)
Definition: decode.h:1028
flow.h
Packet_::esph
ESPHdr * esph
Definition: decode.h:538
CLEAR_ESP_PACKET
#define CLEAR_ESP_PACKET(p)
Definition: decode-esp.h:43
FlowSetupPacket
void FlowSetupPacket(Packet *p)
prepare packet for a life with flow Set PKT_WANTS_FLOW flag to incidate workers should do a flow look...
Definition: flow-hash.c:431