summaryrefslogtreecommitdiffstats
path: root/NetworkPkg/IpSecDxe/IkePacket.c
blob: a4f67ac9be718b8cffc2e27329337b839b6b155c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
/** @file
  IKE Packet related operation.

  Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>

  SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#include "IpSecDebug.h"
#include "Ikev2/Utility.h"

/**
  Allocate a buffer for the IKE_PACKET and intitalize its Header and payloadlist.

  @return The pointer of the IKE_PACKET.

**/
IKE_PACKET *
IkePacketAlloc (
  VOID
  )
{
  IKE_PACKET  *IkePacket;

  IkePacket = (IKE_PACKET *) AllocateZeroPool (sizeof (IKE_PACKET));
  if (IkePacket == NULL) {
    return NULL;
  }

  IkePacket->RefCount = 1;
  InitializeListHead (&IkePacket->PayloadList);

  IkePacket->Header = (IKE_HEADER *) AllocateZeroPool (sizeof (IKE_HEADER));
  if (IkePacket->Header == NULL) {
    FreePool (IkePacket);
    return NULL;
  }
  return IkePacket;
}

/**
  Free the IkePacket by the specified IKE_PACKET pointer.

  @param[in]  IkePacket  The pointer of the IKE_PACKET to be freed.

**/
VOID
IkePacketFree (
  IN IKE_PACKET *IkePacket
  )
{
  LIST_ENTRY  *Entry;
  IKE_PAYLOAD *IkePayload;

  if (IkePacket == NULL) {
    return;
  }
  //
  // Check if the Packet is referred by others.
  //
  if (--IkePacket->RefCount == 0) {
    //
    // Free IkePacket header
    //
    if (!IkePacket->IsHdrExt && IkePacket->Header != NULL) {
      FreePool (IkePacket->Header);
    }
    //
    // Free the PayloadsBuff
    //
    if (!IkePacket->IsPayloadsBufExt && IkePacket->PayloadsBuf != NULL) {
      FreePool (IkePacket->PayloadsBuf);
    }
    //
    // Iterate payloadlist and free all payloads
    //
    for (Entry = (IkePacket)->PayloadList.ForwardLink; Entry != &(IkePacket)->PayloadList;) {
      IkePayload  = IKE_PAYLOAD_BY_PACKET (Entry);
      Entry       = Entry->ForwardLink;

      IkePayloadFree (IkePayload);
    }

    FreePool (IkePacket);
  }
}

/**
  Callback funtion of NetbufFromExt()

  @param[in]  Arg  The data passed from the NetBufFromExe().

**/
VOID
EFIAPI
IkePacketNetbufFree (
  IN VOID  *Arg
  )
{
  //
  // TODO: add something if need.
  //
}

/**
  Copy the NetBuf into a IKE_PACKET sturcture.

  Create a IKE_PACKET and fill the received IKE header into the header of IKE_PACKET
  and copy the recieved packet without IKE HEADER to the PayloadBuf of IKE_PACKET.

  @param[in]  Netbuf      The pointer of the Netbuf which contains the whole received
                          IKE packet.

  @return The pointer of the IKE_PACKET which contains the received packet.

**/
IKE_PACKET *
IkePacketFromNetbuf (
  IN NET_BUF *Netbuf
  )
{
  IKE_PACKET  *IkePacket;

  IkePacket = NULL;
  if (Netbuf->TotalSize < sizeof (IKE_HEADER)) {
    goto Error;
  }

  IkePacket = IkePacketAlloc ();
  if (IkePacket == NULL) {
    return NULL;
  }
  //
  // Copy the IKE header from Netbuf to IkePacket->Hdr
  //
  NetbufCopy (Netbuf, 0, sizeof (IKE_HEADER), (UINT8 *) IkePacket->Header);
  //
  // Net order to host order
  //
  IkeHdrNetToHost (IkePacket->Header);
  if (IkePacket->Header->Length < Netbuf->TotalSize) {
    goto Error;
  }

  IkePacket->PayloadTotalSize = IkePacket->Header->Length - sizeof (IKE_HEADER);
  IkePacket->PayloadsBuf      = (UINT8 *) AllocateZeroPool (IkePacket->PayloadTotalSize);

  if (IkePacket->PayloadsBuf == NULL) {
    goto Error;
  }
  //
  // Copy the IKE packet without the header into the IkePacket->PayloadsBuf.
  //
  NetbufCopy (Netbuf, sizeof (IKE_HEADER), (UINT32) IkePacket->PayloadTotalSize, IkePacket->PayloadsBuf);
  return IkePacket;

Error:
  if (IkePacket != NULL) {
    IkePacketFree (IkePacket);
  }

  return NULL;
}

/**
  Convert the format from IKE_PACKET to NetBuf.

  @param[in]  SessionCommon  Pointer of related IKE_COMMON_SESSION
  @param[in]  IkePacket      Pointer of IKE_PACKET to be copy to NetBuf
  @param[in]  IkeType        The IKE type to pointer the packet is for which IKE
                             phase. Now it supports IKE_SA_TYPE, IKE_CHILDSA_TYPE,
                             IKE_INFO_TYPE.

  @return a pointer of Netbuff which contains the IKE_PACKE in network order.

**/
NET_BUF *
IkeNetbufFromPacket (
  IN UINT8               *SessionCommon,
  IN IKE_PACKET          *IkePacket,
  IN UINTN               IkeType
  )
{
  NET_BUF       *Netbuf;
  NET_FRAGMENT  *Fragments;
  UINTN         Index;
  UINTN         NumPayloads;
  LIST_ENTRY    *PacketEntry;
  LIST_ENTRY    *Entry;
  IKE_PAYLOAD   *IkePayload;
  EFI_STATUS    RetStatus;

  RetStatus = EFI_SUCCESS;

  if (!IkePacket->IsEncoded) {
    IkePacket->IsEncoded = TRUE;
    //
    // Convert Host order to Network order for IKE_PACKET header and payloads
    // Encryption payloads if needed
    //
    if (((IKEV2_SESSION_COMMON *) SessionCommon)->IkeVer == 2) {
      RetStatus = Ikev2EncodePacket ((IKEV2_SESSION_COMMON *) SessionCommon, IkePacket, IkeType);
      if (EFI_ERROR (RetStatus)) {
        return NULL;
      }

    } else {
      //
      // If IKEv1 support, check it here.
      //
      return NULL;
    }
  }

  NumPayloads = 0;
  //
  // Get the number of the payloads
  //
  NET_LIST_FOR_EACH (PacketEntry, &(IkePacket)->PayloadList) {

    NumPayloads++;
  }
  //
  // Allocate the Framgents according to the numbers of the IkePayload
  //
  Fragments = (NET_FRAGMENT *) AllocateZeroPool ((1 + NumPayloads) * sizeof (NET_FRAGMENT));
  if (Fragments == NULL) {
    return NULL;
  }

  Fragments[0].Bulk = (UINT8 *) IkePacket->Header;
  Fragments[0].Len  = sizeof (IKE_HEADER);
  Index             = 0;

  //
  // Set payloads to the Framgments.
  //
  NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) {
    IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);

    Fragments[Index + 1].Bulk = IkePayload->PayloadBuf;
    Fragments[Index + 1].Len  = (UINT32) IkePayload->PayloadSize;
    Index++;
  }

  Netbuf = NetbufFromExt (
             Fragments,
             (UINT32) (NumPayloads + 1),
             0,
             0,
             IkePacketNetbufFree,
             NULL
             );

  FreePool (Fragments);
  return Netbuf;
}