]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/TlsDxe/TlsImpl.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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
101 BufferInPtr += TLS_RECORD_HEADER_LENGTH + RecordHeaderIn->Length;
102 RecordCount++;
103 }
104
105 //
106 // Allocate enough buffer to hold TLS Ciphertext.
107 //
108 BufferOut = AllocateZeroPool (RecordCount * (TLS_RECORD_HEADER_LENGTH + TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH));
109 if (BufferOut == NULL) {
110 Status = EFI_OUT_OF_RESOURCES;
111 goto ERROR;
112 }
113
114 //
115 // Parsing buffer. Received packet may have multiple TLS record messages.
116 //
117 BufferInPtr = BufferIn;
118 TempRecordHeader = (TLS_RECORD_HEADER *)BufferOut;
119 while ((UINTN)BufferInPtr < (UINTN)BufferIn + BufferInSize) {
120 RecordHeaderIn = (TLS_RECORD_HEADER *)BufferInPtr;
121
122 ThisPlainMessageSize = RecordHeaderIn->Length;
123
124 TlsWrite (TlsInstance->TlsConn, (UINT8 *)(RecordHeaderIn + 1), ThisPlainMessageSize);
125
126 Ret = TlsCtrlTrafficOut (TlsInstance->TlsConn, (UINT8 *)(TempRecordHeader), TLS_RECORD_HEADER_LENGTH + TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH);
127
128 if (Ret > 0) {
129 ThisMessageSize = (UINT16)Ret;
130 } else {
131 //
132 // No data was successfully encrypted, continue to encrypt other messages.
133 //
134 DEBUG ((DEBUG_WARN, "TlsEncryptPacket: No data read from TLS object.\n"));
135
136 ThisMessageSize = 0;
137 }
138
139 BufferOutSize += ThisMessageSize;
140
141 BufferInPtr += TLS_RECORD_HEADER_LENGTH + ThisPlainMessageSize;
142 TempRecordHeader = (TLS_RECORD_HEADER *)((UINT8 *)TempRecordHeader + ThisMessageSize);
143 }
144
145 FreePool (BufferIn);
146 BufferIn = NULL;
147
148 //
149 // The caller will be responsible to handle the original fragment table.
150 //
151 *FragmentTable = AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA));
152 if (*FragmentTable == NULL) {
153 Status = EFI_OUT_OF_RESOURCES;
154 goto ERROR;
155 }
156
157 (*FragmentTable)[0].FragmentBuffer = BufferOut;
158 (*FragmentTable)[0].FragmentLength = BufferOutSize;
159 *FragmentCount = 1;
160
161 return Status;
162
163 ERROR:
164
165 if (BufferIn != NULL) {
166 FreePool (BufferIn);
167 BufferIn = NULL;
168 }
169
170 if (BufferOut != NULL) {
171 FreePool (BufferOut);
172 BufferOut = NULL;
173 }
174
175 return Status;
176 }
177
178 /**
179 Decrypt the message listed in fragment.
180
181 @param[in] TlsInstance The pointer to the TLS instance.
182 @param[in, out] FragmentTable Pointer to a list of fragment.
183 On input these fragments contain the TLS header and
184 cipher text TLS payload;
185 On output these fragments contain the TLS header and
186 plain text TLS payload.
187 @param[in] FragmentCount Number of fragment.
188
189 @retval EFI_SUCCESS The operation completed successfully.
190 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
191 @retval EFI_ABORTED TLS session state is incorrect.
192 @retval Others Other errors as indicated.
193 **/
194 EFI_STATUS
195 TlsDecryptPacket (
196 IN TLS_INSTANCE *TlsInstance,
197 IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable,
198 IN UINT32 *FragmentCount
199 )
200 {
201 EFI_STATUS Status;
202 UINTN Index;
203 UINT32 BytesCopied;
204 UINT8 *BufferIn;
205 UINT32 BufferInSize;
206 UINT8 *BufferInPtr;
207 TLS_RECORD_HEADER *RecordHeaderIn;
208 UINT16 ThisCipherMessageSize;
209 TLS_RECORD_HEADER *TempRecordHeader;
210 UINT16 ThisPlainMessageSize;
211 UINT8 *BufferOut;
212 UINT32 BufferOutSize;
213 UINT32 RecordCount;
214 INTN Ret;
215
216 Status = EFI_SUCCESS;
217 BytesCopied = 0;
218 BufferIn = NULL;
219 BufferInSize = 0;
220 BufferInPtr = NULL;
221 RecordHeaderIn = NULL;
222 TempRecordHeader = NULL;
223 BufferOut = NULL;
224 BufferOutSize = 0;
225 RecordCount = 0;
226 Ret = 0;
227
228 //
229 // Calculate the size according to the fragment table.
230 //
231 for (Index = 0; Index < *FragmentCount; Index++) {
232 BufferInSize += (*FragmentTable)[Index].FragmentLength;
233 }
234
235 //
236 // Allocate buffer for processing data
237 //
238 BufferIn = AllocateZeroPool (BufferInSize);
239 if (BufferIn == NULL) {
240 Status = EFI_OUT_OF_RESOURCES;
241 goto ERROR;
242 }
243
244 //
245 // Copy all TLS plain record header and payload to BufferIn
246 //
247 for (Index = 0; Index < *FragmentCount; Index++) {
248 CopyMem (
249 (BufferIn + BytesCopied),
250 (*FragmentTable)[Index].FragmentBuffer,
251 (*FragmentTable)[Index].FragmentLength
252 );
253 BytesCopied += (*FragmentTable)[Index].FragmentLength;
254 }
255
256 //
257 // Count TLS record number.
258 //
259 BufferInPtr = BufferIn;
260 while ((UINTN)BufferInPtr < (UINTN)BufferIn + BufferInSize) {
261 RecordHeaderIn = (TLS_RECORD_HEADER *)BufferInPtr;
262 if ((RecordHeaderIn->ContentType != TlsContentTypeApplicationData) || (NTOHS (RecordHeaderIn->Length) > TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH)) {
263 Status = EFI_INVALID_PARAMETER;
264 goto ERROR;
265 }
266
267 BufferInPtr += TLS_RECORD_HEADER_LENGTH + NTOHS (RecordHeaderIn->Length);
268 RecordCount++;
269 }
270
271 //
272 // Allocate enough buffer to hold TLS Plaintext.
273 //
274 BufferOut = AllocateZeroPool (RecordCount * (TLS_RECORD_HEADER_LENGTH + TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH));
275 if (BufferOut == NULL) {
276 Status = EFI_OUT_OF_RESOURCES;
277 goto ERROR;
278 }
279
280 //
281 // Parsing buffer. Received packet may have multiple TLS record messages.
282 //
283 BufferInPtr = BufferIn;
284 TempRecordHeader = (TLS_RECORD_HEADER *)BufferOut;
285 while ((UINTN)BufferInPtr < (UINTN)BufferIn + BufferInSize) {
286 RecordHeaderIn = (TLS_RECORD_HEADER *)BufferInPtr;
287
288 ThisCipherMessageSize = NTOHS (RecordHeaderIn->Length);
289
290 Ret = TlsCtrlTrafficIn (TlsInstance->TlsConn, (UINT8 *)(RecordHeaderIn), TLS_RECORD_HEADER_LENGTH + ThisCipherMessageSize);
291 if (Ret != TLS_RECORD_HEADER_LENGTH + ThisCipherMessageSize) {
292 TlsInstance->TlsSessionState = EfiTlsSessionError;
293 Status = EFI_ABORTED;
294 goto ERROR;
295 }
296
297 Ret = 0;
298 Ret = TlsRead (TlsInstance->TlsConn, (UINT8 *)(TempRecordHeader + 1), TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH);
299
300 if (Ret > 0) {
301 ThisPlainMessageSize = (UINT16)Ret;
302 } else {
303 //
304 // No data was successfully decrypted, continue to decrypt other messages.
305 //
306 DEBUG ((DEBUG_WARN, "TlsDecryptPacket: No data read from TLS object.\n"));
307
308 ThisPlainMessageSize = 0;
309 }
310
311 CopyMem (TempRecordHeader, RecordHeaderIn, TLS_RECORD_HEADER_LENGTH);
312 TempRecordHeader->Length = ThisPlainMessageSize;
313 BufferOutSize += TLS_RECORD_HEADER_LENGTH + ThisPlainMessageSize;
314
315 BufferInPtr += TLS_RECORD_HEADER_LENGTH + ThisCipherMessageSize;
316 TempRecordHeader = (TLS_RECORD_HEADER *)((UINT8 *)TempRecordHeader + TLS_RECORD_HEADER_LENGTH + ThisPlainMessageSize);
317 }
318
319 FreePool (BufferIn);
320 BufferIn = NULL;
321
322 //
323 // The caller will be responsible to handle the original fragment table
324 //
325 *FragmentTable = AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA));
326 if (*FragmentTable == NULL) {
327 Status = EFI_OUT_OF_RESOURCES;
328 goto ERROR;
329 }
330
331 (*FragmentTable)[0].FragmentBuffer = BufferOut;
332 (*FragmentTable)[0].FragmentLength = BufferOutSize;
333 *FragmentCount = 1;
334
335 return Status;
336
337 ERROR:
338
339 if (BufferIn != NULL) {
340 FreePool (BufferIn);
341 BufferIn = NULL;
342 }
343
344 if (BufferOut != NULL) {
345 FreePool (BufferOut);
346 BufferOut = NULL;
347 }
348
349 return Status;
350 }