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  p->esph = (ESPHdr *)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)) {
75  return TM_ECODE_FAILED;
76  }
77 
78  SCLogDebug("ESP spi: %" PRIu32 " sequence: %" PRIu32, ESP_GET_SPI(p), ESP_GET_SEQUENCE(p));
79 
80  FlowSetupPacket(p);
81 
82  return TM_ECODE_OK;
83 }
84 
85 #ifdef UNITTESTS
86 
87 #include "util-unittest.h"
88 
89 /** \test Successful decoding */
90 static int DecodeESPTest01(void)
91 {
92  uint8_t raw_esp[] = { 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x08 };
93 
95  FAIL_IF_NULL(p);
96 
97  ThreadVars tv;
99 
100  memset(&tv, 0, sizeof(ThreadVars));
101  memset(&dtv, 0, sizeof(DecodeThreadVars));
102 
103  int ret = DecodeESP(&tv, &dtv, p, raw_esp, sizeof(raw_esp));
104  FAIL_IF(ret != TM_ECODE_OK);
105 
106  FAIL_IF(p->proto != IPPROTO_ESP);
107  FAIL_IF(p->payload_len != sizeof(raw_esp) - ESP_HEADER_LEN);
108  FAIL_IF(ESP_GET_SPI(p) != 0x7b);
109  FAIL_IF(ESP_GET_SEQUENCE(p) != 0x08);
110 
111  SCFree(p);
112 
113  PASS;
114 }
115 
116 /** \test Successful decoding, with payload data */
117 static int DecodeESPTest02(void)
118 {
119  uint8_t raw_esp[] = { 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x08, 0xFF, 0xFF };
120 
121  Packet *p = PacketGetFromAlloc();
122  FAIL_IF_NULL(p);
123 
124  ThreadVars tv;
126 
127  memset(&tv, 0, sizeof(ThreadVars));
128  memset(&dtv, 0, sizeof(DecodeThreadVars));
129 
130  int ret = DecodeESP(&tv, &dtv, p, raw_esp, sizeof(raw_esp));
131  FAIL_IF(ret != TM_ECODE_OK);
132 
133  FAIL_IF(p->proto != IPPROTO_ESP);
134  FAIL_IF(p->payload_len != sizeof(raw_esp) - ESP_HEADER_LEN);
135  FAIL_IF(memcmp(p->payload, raw_esp + ESP_HEADER_LEN, p->payload_len) != 0);
136  FAIL_IF(ESP_GET_SPI(p) != 0x7b);
137  FAIL_IF(ESP_GET_SEQUENCE(p) != 0x08);
138 
139  SCFree(p);
140 
141  PASS;
142 }
143 
144 /** \test Failure decoding, not enough data */
145 static int DecodeESPTest03(void)
146 {
147  uint8_t raw_esp[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
148 
149  Packet *p = PacketGetFromAlloc();
150  FAIL_IF_NULL(p);
151 
152  ThreadVars tv;
154 
155  memset(&tv, 0, sizeof(ThreadVars));
156  memset(&dtv, 0, sizeof(DecodeThreadVars));
157 
158  int ret = DecodeESP(&tv, &dtv, p, raw_esp, sizeof(raw_esp));
159  FAIL_IF(ret != TM_ECODE_FAILED);
160 
161  // expect ESP_PKT_TOO_SMALL
163 
164  SCFree(p);
165 
166  PASS;
167 }
168 
169 /** \test Failure decoding, no data */
170 static int DecodeESPTest04(void)
171 {
172  uint8_t raw_esp[] = {};
173 
174  Packet *p = PacketGetFromAlloc();
175  FAIL_IF_NULL(p);
176 
177  ThreadVars tv;
179 
180  memset(&tv, 0, sizeof(ThreadVars));
181  memset(&dtv, 0, sizeof(DecodeThreadVars));
182 
183  int ret = DecodeESP(&tv, &dtv, p, raw_esp, sizeof(raw_esp));
184  FAIL_IF(ret != TM_ECODE_FAILED);
185 
186  // expect ESP_PKT_TOO_SMALL
188 
189  SCFree(p);
190 
191  PASS;
192 }
193 #endif /* UNITTESTS */
194 
196 {
197 #ifdef UNITTESTS
198  UtRegisterTest("DecodeESPTest01", DecodeESPTest01);
199  UtRegisterTest("DecodeESPTest02", DecodeESPTest02);
200  UtRegisterTest("DecodeESPTest03", DecodeESPTest03);
201  UtRegisterTest("DecodeESPTest04", DecodeESPTest04);
202 #endif /* UNITTESTS */
203 }
204 
205 /**
206  * @}
207  */
Packet_::proto
uint8_t proto
Definition: decode.h:459
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:195
StatsIncr
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition: counters.c:167
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:919
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
Packet_::payload
uint8_t * payload
Definition: decode.h:586
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:85
Packet_::payload_len
uint16_t payload_len
Definition: decode.h:587
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:84
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
ESP_PKT_TOO_SMALL
@ ESP_PKT_TOO_SMALL
Definition: decode-events.h:166
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:437
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: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:717
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:229
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:685
ENGINE_SET_INVALID_EVENT
#define ENGINE_SET_INVALID_EVENT(p, e)
Definition: decode.h:912
flow.h
Packet_::esph
ESPHdr * esph
Definition: decode.h:573
CLEAR_ESP_PACKET
#define CLEAR_ESP_PACKET(p)
Definition: decode-esp.h:43
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:103
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:520