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