]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/TlsDxe/TlsImpl.c
NetworkPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / NetworkPkg / TlsDxe / TlsImpl.c
1 /** @file
2 The Miscellaneous Routines for TlsDxe driver.
3
4 Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "TlsImpl.h"
11
12 /**
13 Encrypt the message listed in fragment.
14
15 @param[in] TlsInstance The pointer to the TLS instance.
16 @param[in, out] FragmentTable Pointer to a list of fragment.
17 On input these fragments contain the TLS header and
18 plain text TLS payload;
19 On output these fragments contain the TLS header and
20 cipher text TLS payload.
21 @param[in] FragmentCount Number of fragment.
22
23 @retval EFI_SUCCESS The operation completed successfully.
24 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
25 @retval EFI_ABORTED TLS session state is incorrect.
26 @retval Others Other errors as indicated.
27 **/
28 EFI_STATUS
29 TlsEncryptPacket (
30 IN TLS_INSTANCE *TlsInstance,
31 IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable,
32 IN UINT32 *FragmentCount
33 )
34 {
35 EFI_STATUS Status;
36 UINTN Index;
37 UINT32 BytesCopied;
38 UINT32 BufferInSize;
39 UINT8 *BufferIn;
40 UINT8 *BufferInPtr;
41 TLS_RECORD_HEADER *RecordHeaderIn;
42 UINT16 ThisPlainMessageSize;
43 TLS_RECORD_HEADER *TempRecordHeader;
44 UINT16 ThisMessageSize;
45 UINT32 BufferOutSize;
46 UINT8 *BufferOut;
47 UINT32 RecordCount;
48 INTN Ret;
49
50 Status = EFI_SUCCESS;
51 BytesCopied = 0;
52 BufferInSize = 0;
53 BufferIn = NULL;
54 BufferInPtr = NULL;
55 RecordHeaderIn = NULL;
56 TempRecordHeader = NULL;
57 BufferOutSize = 0;
58 BufferOut = NULL;
59 RecordCount = 0;
60 Ret = 0;
61
62 //
63 // Calculate the size according to the fragment table.
64 //
65 for (Index = 0; Index < *FragmentCount; Index++) {
66 BufferInSize += (*FragmentTable)[Index].FragmentLength;
67 }
68
69 //
70 // Allocate buffer for processing data.
71 //
72 BufferIn = AllocateZeroPool (BufferInSize);
73 if (BufferIn == NULL) {
74 Status = EFI_OUT_OF_RESOURCES;
75 goto ERROR;
76 }
77
78 //
79 // Copy all TLS plain record header and payload into BufferIn.
80 //
81 for (Index = 0; Index < *FragmentCount; Index++) {
82 CopyMem (
83 (BufferIn + BytesCopied),
84 (*FragmentTable)[Index].FragmentBuffer,
85 (*FragmentTable)[Index].FragmentLength
86 );
87 BytesCopied += (*FragmentTable)[Index].FragmentLength;
88 }
89
90 //
91 // Count TLS record number.
92 //
93 BufferInPtr = BufferIn;
94 while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) {
95 RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr;
96 if (RecordHeaderIn->ContentType != TlsContentTypeApplicationData || RecordHeaderIn->Length > TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH) {
97 Status = EFI_INVALID_PARAMETER;
98 goto ERROR;
99 }
100 BufferInPtr += TLS_RECORD_HEADER_LENGTH + RecordHeaderIn->Length;
101 RecordCount ++;
102 }
103
104 //
105 // Allocate enough buffer to hold TLS Ciphertext.
106 //
107 BufferOut = AllocateZeroPool (RecordCount * (TLS_RECORD_HEADER_LENGTH + TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH));
108 if (BufferOut == NULL) {
109 Status = EFI_OUT_OF_RESOURCES;
110 goto ERROR;
111 }
112
113 //
114 // Parsing buffer. Received packet may have multiple TLS record messages.
115 //
116 BufferInPtr = BufferIn;
117 TempRecordHeader = (TLS_RECORD_HEADER *) BufferOut;
118 while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) {
119 RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr;
120
121 ThisPlainMessageSize = RecordHeaderIn->Length;
122
123 TlsWrite (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn + 1), ThisPlainMessageSize);
124
125 Ret = TlsCtrlTrafficOut (TlsInstance->TlsConn, (UINT8 *)(TempRecordHeader), TLS_RECORD_HEADER_LENGTH + TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH);
126
127 if (Ret > 0) {
128 ThisMessageSize = (UINT16) Ret;
129 } else {
130 //
131 // No data was successfully encrypted, continue to encrypt other messages.
132 //
133 DEBUG ((EFI_D_WARN, "TlsEncryptPacket: No data read from TLS object.\n"));
134
135 ThisMessageSize = 0;
136 }
137
138 BufferOutSize += ThisMessageSize;
139
140 BufferInPtr += TLS_RECORD_HEADER_LENGTH + ThisPlainMessageSize;
141 TempRecordHeader = (TLS_RECORD_HEADER *)((UINT8 *)TempRecordHeader + ThisMessageSize);
142 }
143
144 FreePool (BufferIn);
145 BufferIn = NULL;
146
147 //
148 // The caller will be responsible to handle the original fragment table.
149 //
150 *FragmentTable = AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA));
151 if (*FragmentTable == NULL) {
152 Status = EFI_OUT_OF_RESOURCES;
153 goto ERROR;
154 }
155
156 (*FragmentTable)[0].FragmentBuffer = BufferOut;
157 (*FragmentTable)[0].FragmentLength = BufferOutSize;
158 *FragmentCount = 1;
159
160 return Status;
161
162 ERROR:
163
164 if (BufferIn != NULL) {
165 FreePool (BufferIn);
166 BufferIn = NULL;
167 }
168
169 if (BufferOut != NULL) {
170 FreePool (BufferOut);
171 BufferOut = NULL;
172 }
173
174 return Status;
175 }
176
177 /**
178 Decrypt the message listed in fragment.
179
180 @param[in] TlsInstance The pointer to the TLS instance.
181 @param[in, out] FragmentTable Pointer to a list of fragment.
182 On input these fragments contain the TLS header and
183 cipher text TLS payload;
184 On output these fragments contain the TLS header and
185 plain text TLS payload.
186 @param[in] FragmentCount Number of fragment.
187
188 @retval EFI_SUCCESS The operation completed successfully.
189 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
190 @retval EFI_ABORTED TLS session state is incorrect.
191 @retval Others Other errors as indicated.
192 **/
193 EFI_STATUS
194 TlsDecryptPacket (
195 IN TLS_INSTANCE *TlsInstance,
196 IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable,
197 IN UINT32 *FragmentCount
198 )
199 {
200 EFI_STATUS Status;
201 UINTN Index;
202 UINT32 BytesCopied;
203 UINT8 *BufferIn;
204 UINT32 BufferInSize;
205 UINT8 *BufferInPtr;
206 TLS_RECORD_HEADER *RecordHeaderIn;
207 UINT16 ThisCipherMessageSize;
208 TLS_RECORD_HEADER *TempRecordHeader;
209 UINT16 ThisPlainMessageSize;
210 UINT8 *BufferOut;
211 UINT32 BufferOutSize;
212 UINT32 RecordCount;
213 INTN Ret;
214
215 Status = EFI_SUCCESS;
216 BytesCopied = 0;
217 BufferIn = NULL;
218 BufferInSize = 0;
219 BufferInPtr = NULL;
220 RecordHeaderIn = NULL;
221 TempRecordHeader = NULL;
222 BufferOut = NULL;
223 BufferOutSize = 0;
224 RecordCount = 0;
225 Ret = 0;
226
227 //
228 // Calculate the size according to the fragment table.
229 //
230 for (Index = 0; Index < *FragmentCount; Index++) {
231 BufferInSize += (*FragmentTable)[Index].FragmentLength;
232 }
233
234 //
235 // Allocate buffer for processing data
236 //
237 BufferIn = AllocateZeroPool (BufferInSize);
238 if (BufferIn == NULL) {
239 Status = EFI_OUT_OF_RESOURCES;
240 goto ERROR;
241 }
242
243 //
244 // Copy all TLS plain record header and payload to BufferIn
245 //
246 for (Index = 0; Index < *FragmentCount; Index++) {
247 CopyMem (
248 (BufferIn + BytesCopied),
249 (*FragmentTable)[Index].FragmentBuffer,
250 (*FragmentTable)[Index].FragmentLength
251 );
252 BytesCopied += (*FragmentTable)[Index].FragmentLength;
253 }
254
255 //
256 // Count TLS record number.
257 //
258 BufferInPtr = BufferIn;
259 while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) {
260 RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr;
261 if (RecordHeaderIn->ContentType != TlsContentTypeApplicationData || NTOHS (RecordHeaderIn->Length) > TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH) {
262 Status = EFI_INVALID_PARAMETER;
263 goto ERROR;
264 }
265 BufferInPtr += TLS_RECORD_HEADER_LENGTH + NTOHS (RecordHeaderIn->Length);
266 RecordCount ++;
267 }
268
269 //
270 // Allocate enough buffer to hold TLS Plaintext.
271 //
272 BufferOut = AllocateZeroPool (RecordCount * (TLS_RECORD_HEADER_LENGTH + TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH));
273 if (BufferOut == NULL) {
274 Status = EFI_OUT_OF_RESOURCES;
275 goto ERROR;
276 }
277
278 //
279 // Parsing buffer. Received packet may have multiple TLS record messages.
280 //
281 BufferInPtr = BufferIn;
282 TempRecordHeader = (TLS_RECORD_HEADER *) BufferOut;
283 while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) {
284 RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr;
285
286 ThisCipherMessageSize = NTOHS (RecordHeaderIn->Length);
287
288 Ret = TlsCtrlTrafficIn (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn), TLS_RECORD_HEADER_LENGTH + ThisCipherMessageSize);
289 if (Ret != TLS_RECORD_HEADER_LENGTH + ThisCipherMessageSize) {
290 TlsInstance->TlsSessionState = EfiTlsSessionError;
291 Status = EFI_ABORTED;
292 goto ERROR;
293 }
294
295 Ret = 0;
296 Ret = TlsRead (TlsInstance->TlsConn, (UINT8 *) (TempRecordHeader + 1), TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH);
297
298 if (Ret > 0) {
299 ThisPlainMessageSize = (UINT16) Ret;
300 } else {
301 //
302 // No data was successfully decrypted, continue to decrypt other messages.
303 //
304 DEBUG ((EFI_D_WARN, "TlsDecryptPacket: No data read from TLS object.\n"));
305
306 ThisPlainMessageSize = 0;
307 }
308
309 CopyMem (TempRecordHeader, RecordHeaderIn, TLS_RECORD_HEADER_LENGTH);
310 TempRecordHeader->Length = ThisPlainMessageSize;
311 BufferOutSize += TLS_RECORD_HEADER_LENGTH + ThisPlainMessageSize;
312
313 BufferInPtr += TLS_RECORD_HEADER_LENGTH + ThisCipherMessageSize;
314 TempRecordHeader = (TLS_RECORD_HEADER *)((UINT8 *)TempRecordHeader + TLS_RECORD_HEADER_LENGTH + ThisPlainMessageSize);
315 }
316
317 FreePool (BufferIn);
318 BufferIn = NULL;
319
320 //
321 // The caller will be responsible to handle the original fragment table
322 //
323 *FragmentTable = AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA));
324 if (*FragmentTable == NULL) {
325 Status = EFI_OUT_OF_RESOURCES;
326 goto ERROR;
327 }
328
329 (*FragmentTable)[0].FragmentBuffer = BufferOut;
330 (*FragmentTable)[0].FragmentLength = BufferOutSize;
331 *FragmentCount = 1;
332
333 return Status;
334
335 ERROR:
336
337 if (BufferIn != NULL) {
338 FreePool (BufferIn);
339 BufferIn = NULL;
340 }
341
342 if (BufferOut != NULL) {
343 FreePool (BufferOut);
344 BufferOut = NULL;
345 }
346
347 return Status;
348 }
349