suricata
decode-esp.c
Go to the documentation of this file.
1 /* Copyright (C) 2020-2021 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 #include "util-validate.h"
35 
36 static int DecodeESPPacket(ThreadVars *tv, Packet *p, const uint8_t *pkt, uint16_t len)
37 {
38  DEBUG_VALIDATE_BUG_ON(pkt == NULL);
39 
40  if (unlikely(len < ESP_HEADER_LEN)) {
42  return -1;
43  }
44 
45  (void)PacketSetESP(p, pkt);
46 
47  p->payload = (uint8_t *)pkt + sizeof(ESPHdr);
48  p->payload_len = len - sizeof(ESPHdr);
49 
50  p->proto = IPPROTO_ESP;
51 
52  return 0;
53 }
54 
55 /**
56  * \brief Function to decode IPSEC-ESP packets
57  * \param tv thread vars
58  * \param dtv decoder thread vars
59  * \param p packet
60  * \param pkt raw packet data
61  * \param len length in bytes of pkt array
62  * \retval TM_ECODE_OK or TM_ECODE_FAILED on serious error
63  */
64 int DecodeESP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
65 {
66  DEBUG_VALIDATE_BUG_ON(pkt == NULL);
67 
69 
70  if (!PacketIncreaseCheckLayers(p)) {
71  return TM_ECODE_FAILED;
72  }
73  if (unlikely(DecodeESPPacket(tv, p, pkt, len) < 0)) {
74  PacketClearL4(p);
75  return TM_ECODE_FAILED;
76  }
77 
78  SCLogDebug("ESP spi: %" PRIu32 " sequence: %" PRIu32, ESP_GET_SPI(PacketGetESP(p)),
79  ESP_GET_SEQUENCE(PacketGetESP(p)));
80 
81  FlowSetupPacket(p);
82 
83  return TM_ECODE_OK;
84 }
85 
86 #ifdef UNITTESTS
87 
88 #include "util-unittest.h"
89 
90 /** \test Successful decoding */
91 static int DecodeESPTest01(void)
92 {
93  uint8_t raw_esp[] = { 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x08 };
94 
96  FAIL_IF_NULL(p);
97 
98  ThreadVars tv;
100 
101  memset(&tv, 0, sizeof(ThreadVars));
102  memset(&dtv, 0, sizeof(DecodeThreadVars));
103 
104  int ret = DecodeESP(&tv, &dtv, p, raw_esp, sizeof(raw_esp));
105  FAIL_IF(ret != TM_ECODE_OK);
106 
107  FAIL_IF(p->proto != IPPROTO_ESP);
108  FAIL_IF(p->payload_len != sizeof(raw_esp) - ESP_HEADER_LEN);
109  FAIL_IF(ESP_GET_SPI(PacketGetESP(p)) != 0x7b);
110  FAIL_IF(ESP_GET_SEQUENCE(PacketGetESP(p)) != 0x08);
111 
112  SCFree(p);
113 
114  PASS;
115 }
116 
117 /** \test Successful decoding, with payload data */
118 static int DecodeESPTest02(void)
119 {
120  uint8_t raw_esp[] = { 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x08, 0xFF, 0xFF };
121 
122  Packet *p = PacketGetFromAlloc();
123  FAIL_IF_NULL(p);
124 
125  ThreadVars tv;
127 
128  memset(&tv, 0, sizeof(ThreadVars));
129  memset(&dtv, 0, sizeof(DecodeThreadVars));
130 
131  int ret = DecodeESP(&tv, &dtv, p, raw_esp, sizeof(raw_esp));
132  FAIL_IF(ret != TM_ECODE_OK);
133 
134  FAIL_IF(p->proto != IPPROTO_ESP);
135  FAIL_IF(p->payload_len != sizeof(raw_esp) - ESP_HEADER_LEN);
136  FAIL_IF(memcmp(p->payload, raw_esp + ESP_HEADER_LEN, p->payload_len) != 0);
137  FAIL_IF(ESP_GET_SPI(PacketGetESP(p)) != 0x7b);
138  FAIL_IF(ESP_GET_SEQUENCE(PacketGetESP(p)) != 0x08);
139 
140  SCFree(p);
141 
142  PASS;
143 }
144 
145 /** \test Failure decoding, not enough data */
146 static int DecodeESPTest03(void)
147 {
148  uint8_t raw_esp[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
149 
150  Packet *p = PacketGetFromAlloc();
151  FAIL_IF_NULL(p);
152 
153  ThreadVars tv;
155 
156  memset(&tv, 0, sizeof(ThreadVars));
157  memset(&dtv, 0, sizeof(DecodeThreadVars));
158 
159  int ret = DecodeESP(&tv, &dtv, p, raw_esp, sizeof(raw_esp));
160  FAIL_IF(ret != TM_ECODE_FAILED);
161 
162  // expect ESP_PKT_TOO_SMALL
164 
165  SCFree(p);
166 
167  PASS;
168 }
169 
170 /** \test Failure decoding, no data */
171 static int DecodeESPTest04(void)
172 {
173  uint8_t raw_esp[] = {};
174 
175  Packet *p = PacketGetFromAlloc();
176  FAIL_IF_NULL(p);
177 
178  ThreadVars tv;
180 
181  memset(&tv, 0, sizeof(ThreadVars));
182  memset(&dtv, 0, sizeof(DecodeThreadVars));
183 
184  int ret = DecodeESP(&tv, &dtv, p, raw_esp, sizeof(raw_esp));
185  FAIL_IF(ret != TM_ECODE_FAILED);
186 
187  // expect ESP_PKT_TOO_SMALL
189 
190  SCFree(p);
191 
192  PASS;
193 }
194 #endif /* UNITTESTS */
195 
197 {
198 #ifdef UNITTESTS
199  UtRegisterTest("DecodeESPTest01", DecodeESPTest01);
200  UtRegisterTest("DecodeESPTest02", DecodeESPTest02);
201  UtRegisterTest("DecodeESPTest03", DecodeESPTest03);
202  UtRegisterTest("DecodeESPTest04", DecodeESPTest04);
203 #endif /* UNITTESTS */
204 }
205 
206 /**
207  * @}
208  */
ESP_GET_SPI
#define ESP_GET_SPI(esph)
Get the spi field off a packet.
Definition: decode-esp.h:29
Packet_::proto
uint8_t proto
Definition: decode.h:497
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:196
StatsIncr
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition: counters.c:166
ESP_PKT_TOO_SMALL
@ ESP_PKT_TOO_SMALL
Definition: decode-events.h:166
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:64
ENGINE_ISSET_EVENT
#define ENGINE_ISSET_EVENT(p, e)
Definition: decode.h:1163
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
Packet_::payload
uint8_t * payload
Definition: decode.h:573
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:81
Packet_::payload_len
uint16_t payload_len
Definition: decode.h:574
util-unittest.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:80
ESP_GET_SEQUENCE
#define ESP_GET_SEQUENCE(esph)
Get the sequence field off a packet.
Definition: decode-esp.h:31
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:57
Packet_
Definition: decode.h:475
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:33
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
suricata-common.h
DecodeThreadVars_::counter_esp
uint16_t counter_esp
Definition: decode.h:963
decode-esp.h
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
util-validate.h
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:232
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:931
ENGINE_SET_INVALID_EVENT
#define ENGINE_SET_INVALID_EVENT(p, e)
Definition: decode.h:1156
flow.h
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:102
FlowSetupPacket
void FlowSetupPacket(Packet *p)
prepare packet for a life with flow Set PKT_WANTS_FLOW flag to indicate workers should do a flow look...
Definition: flow-hash.c:521