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