]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/HttpDxe/HttpsSupport.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / NetworkPkg / HttpDxe / HttpsSupport.c
CommitLineData
7618784b
HW
1/** @file\r
2 Miscellaneous routines specific to Https for HttpDxe driver.\r
3\r
7ff68b5e 4Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
7618784b 5(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
ecf98fbc 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
7618784b
HW
7\r
8**/\r
9\r
10#include "HttpDriver.h"\r
11\r
12/**\r
13 Returns the first occurrence of a Null-terminated ASCII sub-string in a Null-terminated\r
14 ASCII string and ignore case during the search process.\r
15\r
16 This function scans the contents of the ASCII string specified by String\r
17 and returns the first occurrence of SearchString and ignore case during the search process.\r
18 If SearchString is not found in String, then NULL is returned. If the length of SearchString\r
19 is zero, then String is returned.\r
20\r
21 If String is NULL, then ASSERT().\r
22 If SearchString is NULL, then ASSERT().\r
23\r
24 @param[in] String A pointer to a Null-terminated ASCII string.\r
25 @param[in] SearchString A pointer to a Null-terminated ASCII string to search for.\r
26\r
27 @retval NULL If the SearchString does not appear in String.\r
28 @retval others If there is a match return the first occurrence of SearchingString.\r
29 If the length of SearchString is zero,return String.\r
30\r
31**/\r
32CHAR8 *\r
33AsciiStrCaseStr (\r
d1050b9d
MK
34 IN CONST CHAR8 *String,\r
35 IN CONST CHAR8 *SearchString\r
7618784b
HW
36 )\r
37{\r
d1050b9d
MK
38 CONST CHAR8 *FirstMatch;\r
39 CONST CHAR8 *SearchStringTmp;\r
7618784b 40\r
d1050b9d
MK
41 CHAR8 Src;\r
42 CHAR8 Dst;\r
7618784b
HW
43\r
44 //\r
45 // ASSERT both strings are less long than PcdMaximumAsciiStringLength\r
46 //\r
47 ASSERT (AsciiStrSize (String) != 0);\r
48 ASSERT (AsciiStrSize (SearchString) != 0);\r
49\r
50 if (*SearchString == '\0') {\r
d1050b9d 51 return (CHAR8 *)String;\r
7618784b
HW
52 }\r
53\r
54 while (*String != '\0') {\r
55 SearchStringTmp = SearchString;\r
d1050b9d 56 FirstMatch = String;\r
7618784b 57\r
d1050b9d
MK
58 while ( (*SearchStringTmp != '\0')\r
59 && (*String != '\0'))\r
60 {\r
7618784b
HW
61 Src = *String;\r
62 Dst = *SearchStringTmp;\r
63\r
64 if ((Src >= 'A') && (Src <= 'Z')) {\r
1e4725e5 65 Src += ('a' - 'A');\r
7618784b
HW
66 }\r
67\r
68 if ((Dst >= 'A') && (Dst <= 'Z')) {\r
1e4725e5 69 Dst += ('a' - 'A');\r
7618784b
HW
70 }\r
71\r
72 if (Src != Dst) {\r
73 break;\r
74 }\r
75\r
76 String++;\r
77 SearchStringTmp++;\r
78 }\r
79\r
80 if (*SearchStringTmp == '\0') {\r
d1050b9d 81 return (CHAR8 *)FirstMatch;\r
7618784b
HW
82 }\r
83\r
84 String = FirstMatch + 1;\r
85 }\r
86\r
87 return NULL;\r
88}\r
89\r
90/**\r
91 The callback function to free the net buffer list.\r
92\r
93 @param[in] Arg The opaque parameter.\r
94\r
95**/\r
96VOID\r
97EFIAPI\r
98FreeNbufList (\r
d1050b9d 99 IN VOID *Arg\r
7618784b
HW
100 )\r
101{\r
102 ASSERT (Arg != NULL);\r
103\r
d1050b9d 104 NetbufFreeList ((LIST_ENTRY *)Arg);\r
7618784b
HW
105 FreePool (Arg);\r
106}\r
107\r
108/**\r
109 Check whether the Url is from Https.\r
110\r
111 @param[in] Url The pointer to a HTTP or HTTPS URL string.\r
112\r
113 @retval TRUE The Url is from HTTPS.\r
114 @retval FALSE The Url is from HTTP.\r
115\r
116**/\r
117BOOLEAN\r
118IsHttpsUrl (\r
d1050b9d 119 IN CHAR8 *Url\r
7618784b
HW
120 )\r
121{\r
122 CHAR8 *Tmp;\r
123\r
124 Tmp = NULL;\r
125\r
126 Tmp = AsciiStrCaseStr (Url, HTTPS_FLAG);\r
d1050b9d 127 if ((Tmp != NULL) && (Tmp == Url)) {\r
7618784b
HW
128 return TRUE;\r
129 }\r
130\r
131 return FALSE;\r
132}\r
133\r
134/**\r
135 Creates a Tls child handle, open EFI_TLS_PROTOCOL and EFI_TLS_CONFIGURATION_PROTOCOL.\r
136\r
137 @param[in] ImageHandle The firmware allocated handle for the UEFI image.\r
45ea8a0c 138 @param[out] TlsSb Pointer to the TLS SERVICE_BINDING_PROTOCOL.\r
7618784b
HW
139 @param[out] TlsProto Pointer to the EFI_TLS_PROTOCOL instance.\r
140 @param[out] TlsConfiguration Pointer to the EFI_TLS_CONFIGURATION_PROTOCOL instance.\r
141\r
142 @return The child handle with opened EFI_TLS_PROTOCOL and EFI_TLS_CONFIGURATION_PROTOCOL.\r
143\r
144**/\r
145EFI_HANDLE\r
146EFIAPI\r
147TlsCreateChild (\r
d1050b9d
MK
148 IN EFI_HANDLE ImageHandle,\r
149 OUT EFI_SERVICE_BINDING_PROTOCOL **TlsSb,\r
150 OUT EFI_TLS_PROTOCOL **TlsProto,\r
151 OUT EFI_TLS_CONFIGURATION_PROTOCOL **TlsConfiguration\r
7618784b
HW
152 )\r
153{\r
d1050b9d
MK
154 EFI_STATUS Status;\r
155 EFI_HANDLE TlsChildHandle;\r
7618784b 156\r
7618784b
HW
157 TlsChildHandle = 0;\r
158\r
159 //\r
160 // Locate TlsServiceBinding protocol.\r
161 //\r
162 gBS->LocateProtocol (\r
d1050b9d
MK
163 &gEfiTlsServiceBindingProtocolGuid,\r
164 NULL,\r
165 (VOID **)TlsSb\r
166 );\r
45ea8a0c 167 if (*TlsSb == NULL) {\r
7618784b
HW
168 return NULL;\r
169 }\r
170\r
45ea8a0c 171 Status = (*TlsSb)->CreateChild (*TlsSb, &TlsChildHandle);\r
7618784b
HW
172 if (EFI_ERROR (Status)) {\r
173 return NULL;\r
174 }\r
175\r
176 Status = gBS->OpenProtocol (\r
177 TlsChildHandle,\r
178 &gEfiTlsProtocolGuid,\r
d1050b9d 179 (VOID **)TlsProto,\r
7618784b
HW
180 ImageHandle,\r
181 TlsChildHandle,\r
182 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
183 );\r
184 if (EFI_ERROR (Status)) {\r
45ea8a0c 185 (*TlsSb)->DestroyChild (*TlsSb, TlsChildHandle);\r
7618784b
HW
186 return NULL;\r
187 }\r
188\r
189 Status = gBS->OpenProtocol (\r
190 TlsChildHandle,\r
191 &gEfiTlsConfigurationProtocolGuid,\r
d1050b9d 192 (VOID **)TlsConfiguration,\r
7618784b
HW
193 ImageHandle,\r
194 TlsChildHandle,\r
195 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
196 );\r
197 if (EFI_ERROR (Status)) {\r
45ea8a0c 198 (*TlsSb)->DestroyChild (*TlsSb, TlsChildHandle);\r
7618784b
HW
199 return NULL;\r
200 }\r
201\r
202 return TlsChildHandle;\r
203}\r
204\r
205/**\r
206 Create event for the TLS receive and transmit tokens which are used to receive and\r
207 transmit TLS related messages.\r
208\r
209 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
210\r
211 @retval EFI_SUCCESS The events are created successfully.\r
212 @retval others Other error as indicated.\r
213\r
214**/\r
215EFI_STATUS\r
216EFIAPI\r
217TlsCreateTxRxEvent (\r
d1050b9d 218 IN OUT HTTP_PROTOCOL *HttpInstance\r
7618784b
HW
219 )\r
220{\r
d1050b9d 221 EFI_STATUS Status;\r
7618784b
HW
222\r
223 if (!HttpInstance->LocalAddressIsIPv6) {\r
224 //\r
225 // For Tcp4TlsTxToken.\r
226 //\r
227 Status = gBS->CreateEvent (\r
228 EVT_NOTIFY_SIGNAL,\r
229 TPL_NOTIFY,\r
230 HttpCommonNotify,\r
231 &HttpInstance->TlsIsTxDone,\r
232 &HttpInstance->Tcp4TlsTxToken.CompletionToken.Event\r
233 );\r
234 if (EFI_ERROR (Status)) {\r
235 goto ERROR;\r
236 }\r
237\r
d1050b9d
MK
238 HttpInstance->Tcp4TlsTxData.Push = TRUE;\r
239 HttpInstance->Tcp4TlsTxData.Urgent = FALSE;\r
240 HttpInstance->Tcp4TlsTxData.DataLength = 0;\r
241 HttpInstance->Tcp4TlsTxData.FragmentCount = 1;\r
7618784b
HW
242 HttpInstance->Tcp4TlsTxData.FragmentTable[0].FragmentLength = HttpInstance->Tcp4TlsTxData.DataLength;\r
243 HttpInstance->Tcp4TlsTxData.FragmentTable[0].FragmentBuffer = NULL;\r
d1050b9d
MK
244 HttpInstance->Tcp4TlsTxToken.Packet.TxData = &HttpInstance->Tcp4TlsTxData;\r
245 HttpInstance->Tcp4TlsTxToken.CompletionToken.Status = EFI_NOT_READY;\r
7618784b
HW
246\r
247 //\r
248 // For Tcp4TlsRxToken.\r
249 //\r
250 Status = gBS->CreateEvent (\r
251 EVT_NOTIFY_SIGNAL,\r
252 TPL_NOTIFY,\r
253 HttpCommonNotify,\r
254 &HttpInstance->TlsIsRxDone,\r
255 &HttpInstance->Tcp4TlsRxToken.CompletionToken.Event\r
256 );\r
257 if (EFI_ERROR (Status)) {\r
258 goto ERROR;\r
259 }\r
260\r
d1050b9d
MK
261 HttpInstance->Tcp4TlsRxData.DataLength = 0;\r
262 HttpInstance->Tcp4TlsRxData.FragmentCount = 1;\r
263 HttpInstance->Tcp4TlsRxData.FragmentTable[0].FragmentLength = HttpInstance->Tcp4TlsRxData.DataLength;\r
264 HttpInstance->Tcp4TlsRxData.FragmentTable[0].FragmentBuffer = NULL;\r
265 HttpInstance->Tcp4TlsRxToken.Packet.RxData = &HttpInstance->Tcp4TlsRxData;\r
266 HttpInstance->Tcp4TlsRxToken.CompletionToken.Status = EFI_NOT_READY;\r
7618784b
HW
267 } else {\r
268 //\r
269 // For Tcp6TlsTxToken.\r
270 //\r
271 Status = gBS->CreateEvent (\r
272 EVT_NOTIFY_SIGNAL,\r
273 TPL_NOTIFY,\r
274 HttpCommonNotify,\r
275 &HttpInstance->TlsIsTxDone,\r
276 &HttpInstance->Tcp6TlsTxToken.CompletionToken.Event\r
277 );\r
278 if (EFI_ERROR (Status)) {\r
279 goto ERROR;\r
280 }\r
281\r
d1050b9d
MK
282 HttpInstance->Tcp6TlsTxData.Push = TRUE;\r
283 HttpInstance->Tcp6TlsTxData.Urgent = FALSE;\r
284 HttpInstance->Tcp6TlsTxData.DataLength = 0;\r
285 HttpInstance->Tcp6TlsTxData.FragmentCount = 1;\r
7618784b
HW
286 HttpInstance->Tcp6TlsTxData.FragmentTable[0].FragmentLength = HttpInstance->Tcp6TlsTxData.DataLength;\r
287 HttpInstance->Tcp6TlsTxData.FragmentTable[0].FragmentBuffer = NULL;\r
d1050b9d
MK
288 HttpInstance->Tcp6TlsTxToken.Packet.TxData = &HttpInstance->Tcp6TlsTxData;\r
289 HttpInstance->Tcp6TlsTxToken.CompletionToken.Status = EFI_NOT_READY;\r
7618784b
HW
290\r
291 //\r
292 // For Tcp6TlsRxToken.\r
293 //\r
294 Status = gBS->CreateEvent (\r
295 EVT_NOTIFY_SIGNAL,\r
296 TPL_NOTIFY,\r
297 HttpCommonNotify,\r
298 &HttpInstance->TlsIsRxDone,\r
299 &HttpInstance->Tcp6TlsRxToken.CompletionToken.Event\r
300 );\r
301 if (EFI_ERROR (Status)) {\r
302 goto ERROR;\r
303 }\r
304\r
d1050b9d
MK
305 HttpInstance->Tcp6TlsRxData.DataLength = 0;\r
306 HttpInstance->Tcp6TlsRxData.FragmentCount = 1;\r
307 HttpInstance->Tcp6TlsRxData.FragmentTable[0].FragmentLength = HttpInstance->Tcp6TlsRxData.DataLength;\r
308 HttpInstance->Tcp6TlsRxData.FragmentTable[0].FragmentBuffer = NULL;\r
309 HttpInstance->Tcp6TlsRxToken.Packet.RxData = &HttpInstance->Tcp6TlsRxData;\r
310 HttpInstance->Tcp6TlsRxToken.CompletionToken.Status = EFI_NOT_READY;\r
7618784b
HW
311 }\r
312\r
313 return Status;\r
314\r
315ERROR:\r
316 //\r
317 // Error handling\r
318 //\r
319 TlsCloseTxRxEvent (HttpInstance);\r
320\r
321 return Status;\r
322}\r
323\r
324/**\r
325 Close events in the TlsTxToken and TlsRxToken.\r
326\r
327 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
328\r
329**/\r
330VOID\r
331EFIAPI\r
332TlsCloseTxRxEvent (\r
d1050b9d 333 IN HTTP_PROTOCOL *HttpInstance\r
7618784b
HW
334 )\r
335{\r
336 ASSERT (HttpInstance != NULL);\r
337 if (!HttpInstance->LocalAddressIsIPv6) {\r
338 if (NULL != HttpInstance->Tcp4TlsTxToken.CompletionToken.Event) {\r
d1050b9d 339 gBS->CloseEvent (HttpInstance->Tcp4TlsTxToken.CompletionToken.Event);\r
7618784b
HW
340 HttpInstance->Tcp4TlsTxToken.CompletionToken.Event = NULL;\r
341 }\r
342\r
343 if (NULL != HttpInstance->Tcp4TlsRxToken.CompletionToken.Event) {\r
344 gBS->CloseEvent (HttpInstance->Tcp4TlsRxToken.CompletionToken.Event);\r
345 HttpInstance->Tcp4TlsRxToken.CompletionToken.Event = NULL;\r
346 }\r
347 } else {\r
348 if (NULL != HttpInstance->Tcp6TlsTxToken.CompletionToken.Event) {\r
d1050b9d 349 gBS->CloseEvent (HttpInstance->Tcp6TlsTxToken.CompletionToken.Event);\r
7618784b
HW
350 HttpInstance->Tcp6TlsTxToken.CompletionToken.Event = NULL;\r
351 }\r
352\r
353 if (NULL != HttpInstance->Tcp6TlsRxToken.CompletionToken.Event) {\r
354 gBS->CloseEvent (HttpInstance->Tcp6TlsRxToken.CompletionToken.Event);\r
355 HttpInstance->Tcp6TlsRxToken.CompletionToken.Event = NULL;\r
356 }\r
357 }\r
358}\r
359\r
360/**\r
361 Read the TlsCaCertificate variable and configure it.\r
362\r
363 @param[in, out] HttpInstance The HTTP instance private data.\r
364\r
365 @retval EFI_SUCCESS TlsCaCertificate is configured.\r
366 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.\r
367 @retval EFI_NOT_FOUND Fail to get 'TlsCaCertificate' variable.\r
368 @retval Others Other error as indicated.\r
369\r
370**/\r
371EFI_STATUS\r
372TlsConfigCertificate (\r
d1050b9d 373 IN OUT HTTP_PROTOCOL *HttpInstance\r
7618784b
HW
374 )\r
375{\r
376 EFI_STATUS Status;\r
377 UINT8 *CACert;\r
378 UINTN CACertSize;\r
379 UINT32 Index;\r
380 EFI_SIGNATURE_LIST *CertList;\r
381 EFI_SIGNATURE_DATA *Cert;\r
0fd13678 382 UINTN CertArraySizeInBytes;\r
7618784b
HW
383 UINTN CertCount;\r
384 UINT32 ItemDataSize;\r
385\r
386 CACert = NULL;\r
387 CACertSize = 0;\r
388\r
389 //\r
390 // Try to read the TlsCaCertificate variable.\r
391 //\r
d1050b9d
MK
392 Status = gRT->GetVariable (\r
393 EFI_TLS_CA_CERTIFICATE_VARIABLE,\r
394 &gEfiTlsCaCertificateGuid,\r
395 NULL,\r
396 &CACertSize,\r
397 NULL\r
398 );\r
7618784b 399\r
d1050b9d 400 if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {\r
7618784b
HW
401 return Status;\r
402 }\r
403\r
404 //\r
405 // Allocate buffer and read the config variable.\r
406 //\r
407 CACert = AllocatePool (CACertSize);\r
408 if (CACert == NULL) {\r
409 return EFI_OUT_OF_RESOURCES;\r
410 }\r
411\r
412 Status = gRT->GetVariable (\r
413 EFI_TLS_CA_CERTIFICATE_VARIABLE,\r
414 &gEfiTlsCaCertificateGuid,\r
415 NULL,\r
416 &CACertSize,\r
417 CACert\r
418 );\r
419 if (EFI_ERROR (Status)) {\r
420 //\r
421 // GetVariable still error or the variable is corrupted.\r
7618784b 422 //\r
6f3487a7 423 goto FreeCACert;\r
7618784b
HW
424 }\r
425\r
426 ASSERT (CACert != NULL);\r
427\r
0fd13678
LE
428 //\r
429 // Sanity check\r
430 //\r
d1050b9d
MK
431 Status = EFI_INVALID_PARAMETER;\r
432 CertCount = 0;\r
433 ItemDataSize = (UINT32)CACertSize;\r
0fd13678
LE
434 while (ItemDataSize > 0) {\r
435 if (ItemDataSize < sizeof (EFI_SIGNATURE_LIST)) {\r
d1050b9d
MK
436 DEBUG ((\r
437 DEBUG_ERROR,\r
438 "%a: truncated EFI_SIGNATURE_LIST header\n",\r
439 __FUNCTION__\r
440 ));\r
0fd13678
LE
441 goto FreeCACert;\r
442 }\r
443\r
d1050b9d 444 CertList = (EFI_SIGNATURE_LIST *)(CACert + (CACertSize - ItemDataSize));\r
0fd13678
LE
445\r
446 if (CertList->SignatureListSize < sizeof (EFI_SIGNATURE_LIST)) {\r
d1050b9d
MK
447 DEBUG ((\r
448 DEBUG_ERROR,\r
0fd13678 449 "%a: SignatureListSize too small for EFI_SIGNATURE_LIST\n",\r
d1050b9d
MK
450 __FUNCTION__\r
451 ));\r
0fd13678
LE
452 goto FreeCACert;\r
453 }\r
454\r
455 if (CertList->SignatureListSize > ItemDataSize) {\r
d1050b9d
MK
456 DEBUG ((\r
457 DEBUG_ERROR,\r
458 "%a: truncated EFI_SIGNATURE_LIST body\n",\r
459 __FUNCTION__\r
460 ));\r
0fd13678
LE
461 goto FreeCACert;\r
462 }\r
463\r
464 if (!CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
d1050b9d
MK
465 DEBUG ((\r
466 DEBUG_ERROR,\r
467 "%a: only X509 certificates are supported\n",\r
468 __FUNCTION__\r
469 ));\r
0fd13678
LE
470 Status = EFI_UNSUPPORTED;\r
471 goto FreeCACert;\r
472 }\r
473\r
474 if (CertList->SignatureHeaderSize != 0) {\r
d1050b9d
MK
475 DEBUG ((\r
476 DEBUG_ERROR,\r
477 "%a: SignatureHeaderSize must be 0 for X509\n",\r
478 __FUNCTION__\r
479 ));\r
0fd13678
LE
480 goto FreeCACert;\r
481 }\r
482\r
483 if (CertList->SignatureSize < sizeof (EFI_SIGNATURE_DATA)) {\r
d1050b9d
MK
484 DEBUG ((\r
485 DEBUG_ERROR,\r
486 "%a: SignatureSize too small for EFI_SIGNATURE_DATA\n",\r
487 __FUNCTION__\r
488 ));\r
0fd13678
LE
489 goto FreeCACert;\r
490 }\r
491\r
492 CertArraySizeInBytes = (CertList->SignatureListSize -\r
493 sizeof (EFI_SIGNATURE_LIST));\r
494 if (CertArraySizeInBytes % CertList->SignatureSize != 0) {\r
d1050b9d
MK
495 DEBUG ((\r
496 DEBUG_ERROR,\r
0fd13678 497 "%a: EFI_SIGNATURE_DATA array not a multiple of SignatureSize\n",\r
d1050b9d
MK
498 __FUNCTION__\r
499 ));\r
0fd13678
LE
500 goto FreeCACert;\r
501 }\r
502\r
d1050b9d 503 CertCount += CertArraySizeInBytes / CertList->SignatureSize;\r
0fd13678
LE
504 ItemDataSize -= CertList->SignatureListSize;\r
505 }\r
d1050b9d 506\r
0fd13678
LE
507 if (CertCount == 0) {\r
508 DEBUG ((DEBUG_ERROR, "%a: no X509 certificates provided\n", __FUNCTION__));\r
509 goto FreeCACert;\r
510 }\r
511\r
7618784b
HW
512 //\r
513 // Enumerate all data and erasing the target item.\r
514 //\r
d1050b9d
MK
515 ItemDataSize = (UINT32)CACertSize;\r
516 CertList = (EFI_SIGNATURE_LIST *)CACert;\r
7618784b 517 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
d1050b9d
MK
518 Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
519 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
7618784b
HW
520 for (Index = 0; Index < CertCount; Index++) {\r
521 //\r
522 // EfiTlsConfigDataTypeCACertificate\r
523 //\r
524 Status = HttpInstance->TlsConfiguration->SetData (\r
525 HttpInstance->TlsConfiguration,\r
526 EfiTlsConfigDataTypeCACertificate,\r
527 Cert->SignatureData,\r
528 CertList->SignatureSize - sizeof (Cert->SignatureOwner)\r
529 );\r
530 if (EFI_ERROR (Status)) {\r
6f3487a7 531 goto FreeCACert;\r
7618784b
HW
532 }\r
533\r
d1050b9d 534 Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)Cert + CertList->SignatureSize);\r
7618784b
HW
535 }\r
536\r
537 ItemDataSize -= CertList->SignatureListSize;\r
d1050b9d 538 CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize);\r
7618784b
HW
539 }\r
540\r
6f3487a7 541FreeCACert:\r
7618784b
HW
542 FreePool (CACert);\r
543 return Status;\r
544}\r
545\r
7ff68b5e
JW
546/**\r
547 Read the HttpTlsCipherList variable and configure it for HTTPS session.\r
548\r
549 @param[in, out] HttpInstance The HTTP instance private data.\r
550\r
551 @retval EFI_SUCCESS The prefered HTTP TLS CipherList is configured.\r
552 @retval EFI_NOT_FOUND Fail to get 'HttpTlsCipherList' variable.\r
553 @retval EFI_INVALID_PARAMETER The contents of variable are invalid.\r
554 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.\r
555\r
556 @retval Others Other error as indicated.\r
557\r
558**/\r
559EFI_STATUS\r
560TlsConfigCipherList (\r
d1050b9d 561 IN OUT HTTP_PROTOCOL *HttpInstance\r
7ff68b5e
JW
562 )\r
563{\r
d1050b9d
MK
564 EFI_STATUS Status;\r
565 UINT8 *CipherList;\r
566 UINTN CipherListSize;\r
7ff68b5e
JW
567\r
568 CipherList = NULL;\r
569 CipherListSize = 0;\r
570\r
571 //\r
572 // Try to read the HttpTlsCipherList variable.\r
573 //\r
d1050b9d
MK
574 Status = gRT->GetVariable (\r
575 EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE,\r
576 &gEdkiiHttpTlsCipherListGuid,\r
577 NULL,\r
578 &CipherListSize,\r
579 NULL\r
580 );\r
7ff68b5e
JW
581 ASSERT (EFI_ERROR (Status));\r
582 if (Status != EFI_BUFFER_TOO_SMALL) {\r
583 return Status;\r
584 }\r
585\r
586 if (CipherListSize % sizeof (EFI_TLS_CIPHER) != 0) {\r
587 return EFI_INVALID_PARAMETER;\r
588 }\r
589\r
590 //\r
591 // Allocate buffer and read the config variable.\r
592 //\r
593 CipherList = AllocatePool (CipherListSize);\r
594 if (CipherList == NULL) {\r
595 return EFI_OUT_OF_RESOURCES;\r
596 }\r
597\r
598 Status = gRT->GetVariable (\r
599 EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE,\r
600 &gEdkiiHttpTlsCipherListGuid,\r
601 NULL,\r
602 &CipherListSize,\r
603 CipherList\r
604 );\r
605 if (EFI_ERROR (Status)) {\r
606 //\r
607 // GetVariable still error or the variable is corrupted.\r
608 //\r
609 goto ON_EXIT;\r
610 }\r
611\r
612 ASSERT (CipherList != NULL);\r
613\r
614 Status = HttpInstance->Tls->SetSessionData (\r
615 HttpInstance->Tls,\r
616 EfiTlsCipherList,\r
617 CipherList,\r
618 CipherListSize\r
619 );\r
620\r
f75a7f56 621ON_EXIT:\r
7ff68b5e 622 FreePool (CipherList);\r
f75a7f56 623\r
7ff68b5e
JW
624 return Status;\r
625}\r
626\r
7618784b
HW
627/**\r
628 Configure TLS session data.\r
629\r
630 @param[in, out] HttpInstance The HTTP instance private data.\r
631\r
632 @retval EFI_SUCCESS TLS session data is configured.\r
633 @retval Others Other error as indicated.\r
634\r
635**/\r
636EFI_STATUS\r
637EFIAPI\r
638TlsConfigureSession (\r
d1050b9d 639 IN OUT HTTP_PROTOCOL *HttpInstance\r
7618784b
HW
640 )\r
641{\r
d1050b9d 642 EFI_STATUS Status;\r
7618784b
HW
643\r
644 //\r
645 // TlsConfigData initialization\r
646 //\r
e2fc5081
WJ
647 HttpInstance->TlsConfigData.ConnectionEnd = EfiTlsClient;\r
648 HttpInstance->TlsConfigData.VerifyMethod = EFI_TLS_VERIFY_PEER;\r
6f9e83f7 649 HttpInstance->TlsConfigData.VerifyHost.Flags = EFI_TLS_VERIFY_FLAG_NONE;\r
e2fc5081
WJ
650 HttpInstance->TlsConfigData.VerifyHost.HostName = HttpInstance->RemoteHost;\r
651 HttpInstance->TlsConfigData.SessionState = EfiTlsSessionNotStarted;\r
7618784b
HW
652\r
653 //\r
654 // EfiTlsConnectionEnd,\r
e2fc5081
WJ
655 // EfiTlsVerifyMethod,\r
656 // EfiTlsVerifyHost,\r
7618784b
HW
657 // EfiTlsSessionState\r
658 //\r
659 Status = HttpInstance->Tls->SetSessionData (\r
660 HttpInstance->Tls,\r
661 EfiTlsConnectionEnd,\r
662 &(HttpInstance->TlsConfigData.ConnectionEnd),\r
663 sizeof (EFI_TLS_CONNECTION_END)\r
664 );\r
665 if (EFI_ERROR (Status)) {\r
666 return Status;\r
667 }\r
668\r
669 Status = HttpInstance->Tls->SetSessionData (\r
670 HttpInstance->Tls,\r
671 EfiTlsVerifyMethod,\r
672 &HttpInstance->TlsConfigData.VerifyMethod,\r
673 sizeof (EFI_TLS_VERIFY)\r
674 );\r
675 if (EFI_ERROR (Status)) {\r
676 return Status;\r
677 }\r
678\r
e2fc5081
WJ
679 Status = HttpInstance->Tls->SetSessionData (\r
680 HttpInstance->Tls,\r
681 EfiTlsVerifyHost,\r
682 &HttpInstance->TlsConfigData.VerifyHost,\r
683 sizeof (EFI_TLS_VERIFY_HOST)\r
684 );\r
685 if (EFI_ERROR (Status)) {\r
686 return Status;\r
687 }\r
688\r
7618784b
HW
689 Status = HttpInstance->Tls->SetSessionData (\r
690 HttpInstance->Tls,\r
691 EfiTlsSessionState,\r
692 &(HttpInstance->TlsConfigData.SessionState),\r
693 sizeof (EFI_TLS_SESSION_STATE)\r
694 );\r
695 if (EFI_ERROR (Status)) {\r
696 return Status;\r
697 }\r
698\r
7ff68b5e
JW
699 //\r
700 // Tls Cipher List\r
701 //\r
702 Status = TlsConfigCipherList (HttpInstance);\r
d1050b9d 703 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
c49ca4a2 704 DEBUG ((DEBUG_ERROR, "TlsConfigCipherList: return %r error.\n", Status));\r
7ff68b5e
JW
705 return Status;\r
706 }\r
707\r
7618784b
HW
708 //\r
709 // Tls Config Certificate\r
710 //\r
711 Status = TlsConfigCertificate (HttpInstance);\r
712 if (EFI_ERROR (Status)) {\r
c49ca4a2 713 DEBUG ((DEBUG_ERROR, "TLS Certificate Config Error!\n"));\r
7618784b
HW
714 return Status;\r
715 }\r
716\r
717 //\r
718 // TlsCreateTxRxEvent\r
719 //\r
720 Status = TlsCreateTxRxEvent (HttpInstance);\r
721 if (EFI_ERROR (Status)) {\r
722 goto ERROR;\r
723 }\r
724\r
725 return Status;\r
726\r
727ERROR:\r
728 TlsCloseTxRxEvent (HttpInstance);\r
729\r
730 return Status;\r
731}\r
732\r
733/**\r
734 Transmit the Packet by processing the associated HTTPS token.\r
735\r
736 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
737 @param[in] Packet The packet to transmit.\r
738\r
739 @retval EFI_SUCCESS The packet is transmitted.\r
740 @retval EFI_INVALID_PARAMETER HttpInstance is NULL or Packet is NULL.\r
741 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.\r
742 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
743 @retval Others Other errors as indicated.\r
744\r
745**/\r
746EFI_STATUS\r
747EFIAPI\r
748TlsCommonTransmit (\r
d1050b9d
MK
749 IN OUT HTTP_PROTOCOL *HttpInstance,\r
750 IN NET_BUF *Packet\r
7618784b
HW
751 )\r
752{\r
d1050b9d
MK
753 EFI_STATUS Status;\r
754 VOID *Data;\r
755 UINTN Size;\r
7618784b
HW
756\r
757 if ((HttpInstance == NULL) || (Packet == NULL)) {\r
758 return EFI_INVALID_PARAMETER;\r
759 }\r
760\r
761 if (!HttpInstance->LocalAddressIsIPv6) {\r
762 Size = sizeof (EFI_TCP4_TRANSMIT_DATA) +\r
763 (Packet->BlockOpNum - 1) * sizeof (EFI_TCP4_FRAGMENT_DATA);\r
764 } else {\r
765 Size = sizeof (EFI_TCP6_TRANSMIT_DATA) +\r
766 (Packet->BlockOpNum - 1) * sizeof (EFI_TCP6_FRAGMENT_DATA);\r
767 }\r
768\r
769 Data = AllocatePool (Size);\r
770 if (Data == NULL) {\r
771 return EFI_OUT_OF_RESOURCES;\r
772 }\r
773\r
774 if (!HttpInstance->LocalAddressIsIPv6) {\r
d1050b9d
MK
775 ((EFI_TCP4_TRANSMIT_DATA *)Data)->Push = TRUE;\r
776 ((EFI_TCP4_TRANSMIT_DATA *)Data)->Urgent = FALSE;\r
777 ((EFI_TCP4_TRANSMIT_DATA *)Data)->DataLength = Packet->TotalSize;\r
7618784b
HW
778\r
779 //\r
780 // Build the fragment table.\r
781 //\r
d1050b9d 782 ((EFI_TCP4_TRANSMIT_DATA *)Data)->FragmentCount = Packet->BlockOpNum;\r
7618784b
HW
783\r
784 NetbufBuildExt (\r
785 Packet,\r
d1050b9d
MK
786 (NET_FRAGMENT *)&((EFI_TCP4_TRANSMIT_DATA *)Data)->FragmentTable[0],\r
787 &((EFI_TCP4_TRANSMIT_DATA *)Data)->FragmentCount\r
7618784b
HW
788 );\r
789\r
d1050b9d 790 HttpInstance->Tcp4TlsTxToken.Packet.TxData = (EFI_TCP4_TRANSMIT_DATA *)Data;\r
7618784b
HW
791\r
792 Status = EFI_DEVICE_ERROR;\r
793\r
794 //\r
795 // Transmit the packet.\r
796 //\r
d1050b9d 797 Status = HttpInstance->Tcp4->Transmit (HttpInstance->Tcp4, &HttpInstance->Tcp4TlsTxToken);\r
7618784b
HW
798 if (EFI_ERROR (Status)) {\r
799 goto ON_EXIT;\r
800 }\r
801\r
802 while (!HttpInstance->TlsIsTxDone) {\r
803 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
804 }\r
805\r
806 HttpInstance->TlsIsTxDone = FALSE;\r
d1050b9d 807 Status = HttpInstance->Tcp4TlsTxToken.CompletionToken.Status;\r
7618784b 808 } else {\r
d1050b9d
MK
809 ((EFI_TCP6_TRANSMIT_DATA *)Data)->Push = TRUE;\r
810 ((EFI_TCP6_TRANSMIT_DATA *)Data)->Urgent = FALSE;\r
811 ((EFI_TCP6_TRANSMIT_DATA *)Data)->DataLength = Packet->TotalSize;\r
7618784b
HW
812\r
813 //\r
814 // Build the fragment table.\r
815 //\r
d1050b9d 816 ((EFI_TCP6_TRANSMIT_DATA *)Data)->FragmentCount = Packet->BlockOpNum;\r
7618784b
HW
817\r
818 NetbufBuildExt (\r
819 Packet,\r
d1050b9d
MK
820 (NET_FRAGMENT *)&((EFI_TCP6_TRANSMIT_DATA *)Data)->FragmentTable[0],\r
821 &((EFI_TCP6_TRANSMIT_DATA *)Data)->FragmentCount\r
7618784b
HW
822 );\r
823\r
d1050b9d 824 HttpInstance->Tcp6TlsTxToken.Packet.TxData = (EFI_TCP6_TRANSMIT_DATA *)Data;\r
7618784b
HW
825\r
826 Status = EFI_DEVICE_ERROR;\r
827\r
828 //\r
829 // Transmit the packet.\r
830 //\r
d1050b9d 831 Status = HttpInstance->Tcp6->Transmit (HttpInstance->Tcp6, &HttpInstance->Tcp6TlsTxToken);\r
7618784b
HW
832 if (EFI_ERROR (Status)) {\r
833 goto ON_EXIT;\r
834 }\r
835\r
836 while (!HttpInstance->TlsIsTxDone) {\r
837 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
838 }\r
839\r
840 HttpInstance->TlsIsTxDone = FALSE;\r
d1050b9d 841 Status = HttpInstance->Tcp6TlsTxToken.CompletionToken.Status;\r
7618784b
HW
842 }\r
843\r
844ON_EXIT:\r
845 FreePool (Data);\r
846\r
847 return Status;\r
848}\r
849\r
850/**\r
851 Receive the Packet by processing the associated HTTPS token.\r
852\r
853 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
854 @param[in] Packet The packet to transmit.\r
855 @param[in] Timeout The time to wait for connection done.\r
856\r
857 @retval EFI_SUCCESS The Packet is received.\r
858 @retval EFI_INVALID_PARAMETER HttpInstance is NULL or Packet is NULL.\r
859 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.\r
860 @retval EFI_TIMEOUT The operation is time out.\r
861 @retval Others Other error as indicated.\r
862\r
863**/\r
864EFI_STATUS\r
865EFIAPI\r
866TlsCommonReceive (\r
d1050b9d
MK
867 IN OUT HTTP_PROTOCOL *HttpInstance,\r
868 IN NET_BUF *Packet,\r
869 IN EFI_EVENT Timeout\r
7618784b
HW
870 )\r
871{\r
d1050b9d
MK
872 EFI_TCP4_RECEIVE_DATA *Tcp4RxData;\r
873 EFI_TCP6_RECEIVE_DATA *Tcp6RxData;\r
874 EFI_STATUS Status;\r
875 NET_FRAGMENT *Fragment;\r
876 UINT32 FragmentCount;\r
877 UINT32 CurrentFragment;\r
7618784b
HW
878\r
879 Tcp4RxData = NULL;\r
880 Tcp6RxData = NULL;\r
881\r
882 if ((HttpInstance == NULL) || (Packet == NULL)) {\r
883 return EFI_INVALID_PARAMETER;\r
884 }\r
885\r
886 FragmentCount = Packet->BlockOpNum;\r
887 Fragment = AllocatePool (FragmentCount * sizeof (NET_FRAGMENT));\r
888 if (Fragment == NULL) {\r
889 Status = EFI_OUT_OF_RESOURCES;\r
890 goto ON_EXIT;\r
891 }\r
892\r
893 //\r
894 // Build the fragment table.\r
895 //\r
896 NetbufBuildExt (Packet, Fragment, &FragmentCount);\r
897\r
898 if (!HttpInstance->LocalAddressIsIPv6) {\r
899 Tcp4RxData = HttpInstance->Tcp4TlsRxToken.Packet.RxData;\r
900 if (Tcp4RxData == NULL) {\r
901 return EFI_INVALID_PARAMETER;\r
902 }\r
d1050b9d
MK
903\r
904 Tcp4RxData->FragmentCount = 1;\r
7618784b
HW
905 } else {\r
906 Tcp6RxData = HttpInstance->Tcp6TlsRxToken.Packet.RxData;\r
907 if (Tcp6RxData == NULL) {\r
908 return EFI_INVALID_PARAMETER;\r
909 }\r
d1050b9d
MK
910\r
911 Tcp6RxData->FragmentCount = 1;\r
7618784b
HW
912 }\r
913\r
d1050b9d
MK
914 CurrentFragment = 0;\r
915 Status = EFI_SUCCESS;\r
7618784b
HW
916\r
917 while (CurrentFragment < FragmentCount) {\r
918 if (!HttpInstance->LocalAddressIsIPv6) {\r
d1050b9d
MK
919 Tcp4RxData->DataLength = Fragment[CurrentFragment].Len;\r
920 Tcp4RxData->FragmentTable[0].FragmentLength = Fragment[CurrentFragment].Len;\r
921 Tcp4RxData->FragmentTable[0].FragmentBuffer = Fragment[CurrentFragment].Bulk;\r
922 Status = HttpInstance->Tcp4->Receive (HttpInstance->Tcp4, &HttpInstance->Tcp4TlsRxToken);\r
7618784b 923 } else {\r
d1050b9d
MK
924 Tcp6RxData->DataLength = Fragment[CurrentFragment].Len;\r
925 Tcp6RxData->FragmentTable[0].FragmentLength = Fragment[CurrentFragment].Len;\r
926 Tcp6RxData->FragmentTable[0].FragmentBuffer = Fragment[CurrentFragment].Bulk;\r
927 Status = HttpInstance->Tcp6->Receive (HttpInstance->Tcp6, &HttpInstance->Tcp6TlsRxToken);\r
7618784b 928 }\r
d1050b9d 929\r
7618784b
HW
930 if (EFI_ERROR (Status)) {\r
931 goto ON_EXIT;\r
932 }\r
933\r
934 while (!HttpInstance->TlsIsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
935 //\r
936 // Poll until some data is received or an error occurs.\r
937 //\r
938 if (!HttpInstance->LocalAddressIsIPv6) {\r
939 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
940 } else {\r
941 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
942 }\r
943 }\r
944\r
945 if (!HttpInstance->TlsIsRxDone) {\r
946 //\r
947 // Timeout occurs, cancel the receive request.\r
948 //\r
949 if (!HttpInstance->LocalAddressIsIPv6) {\r
950 HttpInstance->Tcp4->Cancel (HttpInstance->Tcp4, &HttpInstance->Tcp4TlsRxToken.CompletionToken);\r
951 } else {\r
952 HttpInstance->Tcp6->Cancel (HttpInstance->Tcp6, &HttpInstance->Tcp6TlsRxToken.CompletionToken);\r
953 }\r
954\r
955 Status = EFI_TIMEOUT;\r
956 goto ON_EXIT;\r
957 } else {\r
958 HttpInstance->TlsIsRxDone = FALSE;\r
959 }\r
960\r
961 if (!HttpInstance->LocalAddressIsIPv6) {\r
962 Status = HttpInstance->Tcp4TlsRxToken.CompletionToken.Status;\r
963 if (EFI_ERROR (Status)) {\r
964 goto ON_EXIT;\r
965 }\r
966\r
967 Fragment[CurrentFragment].Len -= Tcp4RxData->FragmentTable[0].FragmentLength;\r
968 if (Fragment[CurrentFragment].Len == 0) {\r
969 CurrentFragment++;\r
970 } else {\r
971 Fragment[CurrentFragment].Bulk += Tcp4RxData->FragmentTable[0].FragmentLength;\r
972 }\r
973 } else {\r
974 Status = HttpInstance->Tcp6TlsRxToken.CompletionToken.Status;\r
975 if (EFI_ERROR (Status)) {\r
976 goto ON_EXIT;\r
977 }\r
978\r
979 Fragment[CurrentFragment].Len -= Tcp6RxData->FragmentTable[0].FragmentLength;\r
980 if (Fragment[CurrentFragment].Len == 0) {\r
981 CurrentFragment++;\r
982 } else {\r
983 Fragment[CurrentFragment].Bulk += Tcp6RxData->FragmentTable[0].FragmentLength;\r
984 }\r
985 }\r
986 }\r
987\r
988ON_EXIT:\r
989\r
990 if (Fragment != NULL) {\r
991 FreePool (Fragment);\r
992 }\r
993\r
994 return Status;\r
995}\r
996\r
997/**\r
ba3b642d 998 Receive one TLS PDU. An TLS PDU contains an TLS record header and its\r
7618784b
HW
999 corresponding record data. These two parts will be put into two blocks of buffers in the\r
1000 net buffer.\r
1001\r
1002 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
1003 @param[out] Pdu The received TLS PDU.\r
1004 @param[in] Timeout The time to wait for connection done.\r
1005\r
1006 @retval EFI_SUCCESS An TLS PDU is received.\r
1007 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.\r
1008 @retval EFI_PROTOCOL_ERROR An unexpected TLS packet was received.\r
1009 @retval Others Other errors as indicated.\r
1010\r
1011**/\r
1012EFI_STATUS\r
1013EFIAPI\r
1014TlsReceiveOnePdu (\r
d1050b9d
MK
1015 IN OUT HTTP_PROTOCOL *HttpInstance,\r
1016 OUT NET_BUF **Pdu,\r
1017 IN EFI_EVENT Timeout\r
7618784b
HW
1018 )\r
1019{\r
d1050b9d 1020 EFI_STATUS Status;\r
7618784b 1021\r
d1050b9d 1022 LIST_ENTRY *NbufList;\r
7618784b 1023\r
d1050b9d 1024 UINT32 Len;\r
7618784b 1025\r
d1050b9d
MK
1026 NET_BUF *PduHdr;\r
1027 UINT8 *Header;\r
1028 TLS_RECORD_HEADER RecordHeader;\r
7618784b 1029\r
d1050b9d 1030 NET_BUF *DataSeg;\r
7618784b
HW
1031\r
1032 NbufList = NULL;\r
1033 PduHdr = NULL;\r
1034 Header = NULL;\r
1035 DataSeg = NULL;\r
1036\r
1037 NbufList = AllocatePool (sizeof (LIST_ENTRY));\r
1038 if (NbufList == NULL) {\r
1039 return EFI_OUT_OF_RESOURCES;\r
1040 }\r
1041\r
1042 InitializeListHead (NbufList);\r
1043\r
1044 //\r
1045 // Allocate buffer to receive one TLS header.\r
1046 //\r
d1050b9d
MK
1047 Len = TLS_RECORD_HEADER_LENGTH;\r
1048 PduHdr = NetbufAlloc (Len);\r
7618784b
HW
1049 if (PduHdr == NULL) {\r
1050 Status = EFI_OUT_OF_RESOURCES;\r
1051 goto ON_EXIT;\r
1052 }\r
1053\r
1054 Header = NetbufAllocSpace (PduHdr, Len, NET_BUF_TAIL);\r
1055 if (Header == NULL) {\r
1056 Status = EFI_OUT_OF_RESOURCES;\r
1057 goto ON_EXIT;\r
1058 }\r
1059\r
1060 //\r
1061 // First step, receive one TLS header.\r
1062 //\r
1063 Status = TlsCommonReceive (HttpInstance, PduHdr, Timeout);\r
1064 if (EFI_ERROR (Status)) {\r
1065 goto ON_EXIT;\r
1066 }\r
1067\r
d1050b9d
MK
1068 RecordHeader = *(TLS_RECORD_HEADER *)Header;\r
1069 if (((RecordHeader.ContentType == TlsContentTypeHandshake) ||\r
1070 (RecordHeader.ContentType == TlsContentTypeAlert) ||\r
1071 (RecordHeader.ContentType == TlsContentTypeChangeCipherSpec) ||\r
1072 (RecordHeader.ContentType == TlsContentTypeApplicationData)) &&\r
1073 (RecordHeader.Version.Major == 0x03) && /// Major versions are same.\r
1074 ((RecordHeader.Version.Minor == TLS10_PROTOCOL_VERSION_MINOR) ||\r
1075 (RecordHeader.Version.Minor == TLS11_PROTOCOL_VERSION_MINOR) ||\r
1076 (RecordHeader.Version.Minor == TLS12_PROTOCOL_VERSION_MINOR))\r
1077 )\r
1078 {\r
7618784b
HW
1079 InsertTailList (NbufList, &PduHdr->List);\r
1080 } else {\r
1081 Status = EFI_PROTOCOL_ERROR;\r
1082 goto ON_EXIT;\r
1083 }\r
1084\r
d1050b9d 1085 Len = SwapBytes16 (RecordHeader.Length);\r
7618784b
HW
1086 if (Len == 0) {\r
1087 //\r
1088 // No TLS payload.\r
1089 //\r
1090 goto FORM_PDU;\r
1091 }\r
1092\r
1093 //\r
1094 // Allocate buffer to receive one TLS payload.\r
1095 //\r
1096 DataSeg = NetbufAlloc (Len);\r
1097 if (DataSeg == NULL) {\r
1098 Status = EFI_OUT_OF_RESOURCES;\r
1099 goto ON_EXIT;\r
1100 }\r
1101\r
1102 NetbufAllocSpace (DataSeg, Len, NET_BUF_TAIL);\r
1103\r
1104 //\r
1105 // Second step, receive one TLS payload.\r
1106 //\r
1107 Status = TlsCommonReceive (HttpInstance, DataSeg, Timeout);\r
1108 if (EFI_ERROR (Status)) {\r
1109 goto ON_EXIT;\r
1110 }\r
1111\r
1112 InsertTailList (NbufList, &DataSeg->List);\r
1113\r
1114FORM_PDU:\r
1115 //\r
1116 // Form the PDU from a list of PDU.\r
1117 //\r
1118 *Pdu = NetbufFromBufList (NbufList, 0, 0, FreeNbufList, NbufList);\r
1119 if (*Pdu == NULL) {\r
1120 Status = EFI_OUT_OF_RESOURCES;\r
1121 }\r
1122\r
1123ON_EXIT:\r
1124\r
1125 if (EFI_ERROR (Status)) {\r
1126 //\r
1127 // Free the Nbufs in this NbufList and the NbufList itself.\r
1128 //\r
1129 FreeNbufList (NbufList);\r
1130 }\r
1131\r
1132 return Status;\r
1133}\r
1134\r
1135/**\r
1136 Connect one TLS session by finishing the TLS handshake process.\r
1137\r
1138 @param[in] HttpInstance The HTTP instance private data.\r
1139 @param[in] Timeout The time to wait for connection done.\r
1140\r
1141 @retval EFI_SUCCESS The TLS session is established.\r
1142 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.\r
1143 @retval EFI_ABORTED TLS session state is incorrect.\r
1144 @retval Others Other error as indicated.\r
1145\r
1146**/\r
1147EFI_STATUS\r
1148EFIAPI\r
1149TlsConnectSession (\r
d1050b9d
MK
1150 IN HTTP_PROTOCOL *HttpInstance,\r
1151 IN EFI_EVENT Timeout\r
7618784b
HW
1152 )\r
1153{\r
d1050b9d
MK
1154 EFI_STATUS Status;\r
1155 UINT8 *BufferOut;\r
1156 UINTN BufferOutSize;\r
1157 NET_BUF *PacketOut;\r
1158 UINT8 *DataOut;\r
1159 NET_BUF *Pdu;\r
1160 UINT8 *BufferIn;\r
1161 UINTN BufferInSize;\r
1162 UINT8 *GetSessionDataBuffer;\r
1163 UINTN GetSessionDataBufferSize;\r
1164\r
1165 BufferOut = NULL;\r
1166 PacketOut = NULL;\r
1167 DataOut = NULL;\r
1168 Pdu = NULL;\r
1169 BufferIn = NULL;\r
7618784b
HW
1170\r
1171 //\r
1172 // Initialize TLS state.\r
1173 //\r
1174 HttpInstance->TlsSessionState = EfiTlsSessionNotStarted;\r
d1050b9d
MK
1175 Status = HttpInstance->Tls->SetSessionData (\r
1176 HttpInstance->Tls,\r
1177 EfiTlsSessionState,\r
1178 &(HttpInstance->TlsSessionState),\r
1179 sizeof (EFI_TLS_SESSION_STATE)\r
1180 );\r
7618784b
HW
1181 if (EFI_ERROR (Status)) {\r
1182 return Status;\r
1183 }\r
1184\r
1185 //\r
1186 // Create ClientHello\r
1187 //\r
1188 BufferOutSize = DEF_BUF_LEN;\r
d1050b9d 1189 BufferOut = AllocateZeroPool (BufferOutSize);\r
7618784b
HW
1190 if (BufferOut == NULL) {\r
1191 Status = EFI_OUT_OF_RESOURCES;\r
1192 return Status;\r
1193 }\r
1194\r
1195 Status = HttpInstance->Tls->BuildResponsePacket (\r
1196 HttpInstance->Tls,\r
1197 NULL,\r
1198 0,\r
1199 BufferOut,\r
1200 &BufferOutSize\r
1201 );\r
1202 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1203 FreePool (BufferOut);\r
1204 BufferOut = AllocateZeroPool (BufferOutSize);\r
1205 if (BufferOut == NULL) {\r
1206 Status = EFI_OUT_OF_RESOURCES;\r
1207 return Status;\r
1208 }\r
1209\r
1210 Status = HttpInstance->Tls->BuildResponsePacket (\r
1211 HttpInstance->Tls,\r
1212 NULL,\r
1213 0,\r
1214 BufferOut,\r
1215 &BufferOutSize\r
1216 );\r
1217 }\r
d1050b9d 1218\r
7618784b
HW
1219 if (EFI_ERROR (Status)) {\r
1220 FreePool (BufferOut);\r
1221 return Status;\r
1222 }\r
1223\r
1224 //\r
1225 // Transmit ClientHello\r
1226 //\r
d1050b9d
MK
1227 PacketOut = NetbufAlloc ((UINT32)BufferOutSize);\r
1228 DataOut = NetbufAllocSpace (PacketOut, (UINT32)BufferOutSize, NET_BUF_TAIL);\r
7618784b
HW
1229 if (DataOut == NULL) {\r
1230 FreePool (BufferOut);\r
1231 return EFI_OUT_OF_RESOURCES;\r
1232 }\r
1233\r
1234 CopyMem (DataOut, BufferOut, BufferOutSize);\r
1235 Status = TlsCommonTransmit (HttpInstance, PacketOut);\r
1236\r
1237 FreePool (BufferOut);\r
1238 NetbufFree (PacketOut);\r
1239\r
1240 if (EFI_ERROR (Status)) {\r
1241 return Status;\r
1242 }\r
1243\r
d1050b9d
MK
1244 while (HttpInstance->TlsSessionState != EfiTlsSessionDataTransferring && \\r
1245 ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout))))\r
1246 {\r
7618784b
HW
1247 //\r
1248 // Receive one TLS record.\r
1249 //\r
1250 Status = TlsReceiveOnePdu (HttpInstance, &Pdu, Timeout);\r
1251 if (EFI_ERROR (Status)) {\r
1252 return Status;\r
1253 }\r
1254\r
1255 BufferInSize = Pdu->TotalSize;\r
d1050b9d 1256 BufferIn = AllocateZeroPool (BufferInSize);\r
7618784b
HW
1257 if (BufferIn == NULL) {\r
1258 NetbufFree (Pdu);\r
1259 Status = EFI_OUT_OF_RESOURCES;\r
1260 return Status;\r
1261 }\r
1262\r
1263 NetbufCopy (Pdu, 0, (UINT32)BufferInSize, BufferIn);\r
1264\r
1265 NetbufFree (Pdu);\r
1266\r
1267 //\r
1268 // Handle Receive data.\r
1269 //\r
1270 BufferOutSize = DEF_BUF_LEN;\r
d1050b9d 1271 BufferOut = AllocateZeroPool (BufferOutSize);\r
7618784b
HW
1272 if (BufferOut == NULL) {\r
1273 Status = EFI_OUT_OF_RESOURCES;\r
1274 return Status;\r
1275 }\r
1276\r
1277 Status = HttpInstance->Tls->BuildResponsePacket (\r
1278 HttpInstance->Tls,\r
1279 BufferIn,\r
1280 BufferInSize,\r
1281 BufferOut,\r
1282 &BufferOutSize\r
1283 );\r
1284 if (Status == EFI_BUFFER_TOO_SMALL) {\r
d1050b9d
MK
1285 FreePool (BufferOut);\r
1286 BufferOut = AllocateZeroPool (BufferOutSize);\r
1287 if (BufferOut == NULL) {\r
1288 FreePool (BufferIn);\r
1289 Status = EFI_OUT_OF_RESOURCES;\r
1290 return Status;\r
1291 }\r
1292\r
1293 Status = HttpInstance->Tls->BuildResponsePacket (\r
1294 HttpInstance->Tls,\r
1295 BufferIn,\r
1296 BufferInSize,\r
1297 BufferOut,\r
1298 &BufferOutSize\r
1299 );\r
7618784b
HW
1300 }\r
1301\r
1302 FreePool (BufferIn);\r
1303\r
1304 if (EFI_ERROR (Status)) {\r
1305 FreePool (BufferOut);\r
1306 return Status;\r
1307 }\r
1308\r
1309 if (BufferOutSize != 0) {\r
1310 //\r
1311 // Transmit the response packet.\r
1312 //\r
d1050b9d
MK
1313 PacketOut = NetbufAlloc ((UINT32)BufferOutSize);\r
1314 DataOut = NetbufAllocSpace (PacketOut, (UINT32)BufferOutSize, NET_BUF_TAIL);\r
7618784b
HW
1315 if (DataOut == NULL) {\r
1316 FreePool (BufferOut);\r
1317 return EFI_OUT_OF_RESOURCES;\r
1318 }\r
1319\r
1320 CopyMem (DataOut, BufferOut, BufferOutSize);\r
1321\r
1322 Status = TlsCommonTransmit (HttpInstance, PacketOut);\r
1323\r
1324 NetbufFree (PacketOut);\r
1325\r
1326 if (EFI_ERROR (Status)) {\r
1327 FreePool (BufferOut);\r
1328 return Status;\r
1329 }\r
1330 }\r
1331\r
1332 FreePool (BufferOut);\r
1333\r
1334 //\r
1335 // Get the session state, then decide whether need to continue handle received packet.\r
1336 //\r
1337 GetSessionDataBufferSize = DEF_BUF_LEN;\r
d1050b9d 1338 GetSessionDataBuffer = AllocateZeroPool (GetSessionDataBufferSize);\r
7618784b
HW
1339 if (GetSessionDataBuffer == NULL) {\r
1340 Status = EFI_OUT_OF_RESOURCES;\r
1341 return Status;\r
1342 }\r
1343\r
1344 Status = HttpInstance->Tls->GetSessionData (\r
1345 HttpInstance->Tls,\r
1346 EfiTlsSessionState,\r
1347 GetSessionDataBuffer,\r
1348 &GetSessionDataBufferSize\r
1349 );\r
1350 if (Status == EFI_BUFFER_TOO_SMALL) {\r
d1050b9d
MK
1351 FreePool (GetSessionDataBuffer);\r
1352 GetSessionDataBuffer = AllocateZeroPool (GetSessionDataBufferSize);\r
1353 if (GetSessionDataBuffer == NULL) {\r
1354 Status = EFI_OUT_OF_RESOURCES;\r
1355 return Status;\r
1356 }\r
1357\r
1358 Status = HttpInstance->Tls->GetSessionData (\r
1359 HttpInstance->Tls,\r
1360 EfiTlsSessionState,\r
1361 GetSessionDataBuffer,\r
1362 &GetSessionDataBufferSize\r
1363 );\r
7618784b 1364 }\r
d1050b9d 1365\r
7618784b 1366 if (EFI_ERROR (Status)) {\r
d1050b9d 1367 FreePool (GetSessionDataBuffer);\r
7618784b
HW
1368 return Status;\r
1369 }\r
1370\r
d1050b9d
MK
1371 ASSERT (GetSessionDataBufferSize == sizeof (EFI_TLS_SESSION_STATE));\r
1372 HttpInstance->TlsSessionState = *(EFI_TLS_SESSION_STATE *)GetSessionDataBuffer;\r
7618784b
HW
1373\r
1374 FreePool (GetSessionDataBuffer);\r
1375\r
d1050b9d 1376 if (HttpInstance->TlsSessionState == EfiTlsSessionError) {\r
7618784b
HW
1377 return EFI_ABORTED;\r
1378 }\r
1379 }\r
1380\r
1381 if (HttpInstance->TlsSessionState != EfiTlsSessionDataTransferring) {\r
1382 Status = EFI_ABORTED;\r
1383 }\r
1384\r
1385 return Status;\r
1386}\r
1387\r
1388/**\r
1389 Close the TLS session and send out the close notification message.\r
1390\r
1391 @param[in] HttpInstance The HTTP instance private data.\r
1392\r
1393 @retval EFI_SUCCESS The TLS session is closed.\r
1394 @retval EFI_INVALID_PARAMETER HttpInstance is NULL.\r
1395 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.\r
1396 @retval Others Other error as indicated.\r
1397\r
1398**/\r
1399EFI_STATUS\r
1400EFIAPI\r
1401TlsCloseSession (\r
d1050b9d 1402 IN HTTP_PROTOCOL *HttpInstance\r
7618784b
HW
1403 )\r
1404{\r
d1050b9d 1405 EFI_STATUS Status;\r
7618784b 1406\r
d1050b9d
MK
1407 UINT8 *BufferOut;\r
1408 UINTN BufferOutSize;\r
7618784b 1409\r
d1050b9d
MK
1410 NET_BUF *PacketOut;\r
1411 UINT8 *DataOut;\r
7618784b
HW
1412\r
1413 Status = EFI_SUCCESS;\r
1414 BufferOut = NULL;\r
1415 PacketOut = NULL;\r
1416 DataOut = NULL;\r
1417\r
1418 if (HttpInstance == NULL) {\r
1419 return EFI_INVALID_PARAMETER;\r
1420 }\r
1421\r
1422 HttpInstance->TlsSessionState = EfiTlsSessionClosing;\r
1423\r
1424 Status = HttpInstance->Tls->SetSessionData (\r
1425 HttpInstance->Tls,\r
1426 EfiTlsSessionState,\r
1427 &(HttpInstance->TlsSessionState),\r
1428 sizeof (EFI_TLS_SESSION_STATE)\r
1429 );\r
1430 if (EFI_ERROR (Status)) {\r
1431 return Status;\r
1432 }\r
1433\r
1434 BufferOutSize = DEF_BUF_LEN;\r
d1050b9d 1435 BufferOut = AllocateZeroPool (BufferOutSize);\r
7618784b
HW
1436 if (BufferOut == NULL) {\r
1437 Status = EFI_OUT_OF_RESOURCES;\r
1438 return Status;\r
1439 }\r
1440\r
1441 Status = HttpInstance->Tls->BuildResponsePacket (\r
1442 HttpInstance->Tls,\r
1443 NULL,\r
1444 0,\r
1445 BufferOut,\r
1446 &BufferOutSize\r
1447 );\r
1448 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1449 FreePool (BufferOut);\r
1450 BufferOut = AllocateZeroPool (BufferOutSize);\r
1451 if (BufferOut == NULL) {\r
1452 Status = EFI_OUT_OF_RESOURCES;\r
1453 return Status;\r
1454 }\r
1455\r
1456 Status = HttpInstance->Tls->BuildResponsePacket (\r
1457 HttpInstance->Tls,\r
1458 NULL,\r
1459 0,\r
1460 BufferOut,\r
1461 &BufferOutSize\r
1462 );\r
1463 }\r
1464\r
1465 if (EFI_ERROR (Status)) {\r
1466 FreePool (BufferOut);\r
1467 return Status;\r
1468 }\r
1469\r
d1050b9d
MK
1470 PacketOut = NetbufAlloc ((UINT32)BufferOutSize);\r
1471 DataOut = NetbufAllocSpace (PacketOut, (UINT32)BufferOutSize, NET_BUF_TAIL);\r
7618784b
HW
1472 if (DataOut == NULL) {\r
1473 FreePool (BufferOut);\r
1474 return EFI_OUT_OF_RESOURCES;\r
1475 }\r
1476\r
1477 CopyMem (DataOut, BufferOut, BufferOutSize);\r
1478\r
1479 Status = TlsCommonTransmit (HttpInstance, PacketOut);\r
1480\r
1481 FreePool (BufferOut);\r
1482 NetbufFree (PacketOut);\r
1483\r
1484 return Status;\r
1485}\r
1486\r
1487/**\r
1488 Process one message according to the CryptMode.\r
1489\r
1490 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
f75a7f56 1491 @param[in] Message Pointer to the message buffer needed to processed.\r
07bd82d4
JW
1492 If ProcessMode is EfiTlsEncrypt, the message contain the TLS\r
1493 header and plain text TLS APP payload.\r
f75a7f56 1494 If ProcessMode is EfiTlsDecrypt, the message contain the TLS\r
07bd82d4 1495 header and cipher text TLS APP payload.\r
7618784b
HW
1496 @param[in] MessageSize Pointer to the message buffer size.\r
1497 @param[in] ProcessMode Process mode.\r
1498 @param[in, out] Fragment Only one Fragment returned after the Message is\r
1499 processed successfully.\r
f75a7f56 1500 If ProcessMode is EfiTlsEncrypt, the fragment contain the TLS\r
07bd82d4 1501 header and cipher text TLS APP payload.\r
f75a7f56 1502 If ProcessMode is EfiTlsDecrypt, the fragment contain the TLS\r
07bd82d4 1503 header and plain text TLS APP payload.\r
7618784b
HW
1504\r
1505 @retval EFI_SUCCESS Message is processed successfully.\r
1506 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.\r
1507 @retval Others Other errors as indicated.\r
1508\r
1509**/\r
1510EFI_STATUS\r
1511EFIAPI\r
1512TlsProcessMessage (\r
d1050b9d
MK
1513 IN HTTP_PROTOCOL *HttpInstance,\r
1514 IN UINT8 *Message,\r
1515 IN UINTN MessageSize,\r
1516 IN EFI_TLS_CRYPT_MODE ProcessMode,\r
1517 IN OUT NET_FRAGMENT *Fragment\r
7618784b
HW
1518 )\r
1519{\r
d1050b9d
MK
1520 EFI_STATUS Status;\r
1521 UINT8 *Buffer;\r
1522 UINT32 BufferSize;\r
1523 UINT32 BytesCopied;\r
1524 EFI_TLS_FRAGMENT_DATA *FragmentTable;\r
1525 UINT32 FragmentCount;\r
1526 EFI_TLS_FRAGMENT_DATA *OriginalFragmentTable;\r
1527 UINTN Index;\r
1528\r
1529 Status = EFI_SUCCESS;\r
1530 Buffer = NULL;\r
1531 BufferSize = 0;\r
1532 BytesCopied = 0;\r
1533 FragmentTable = NULL;\r
1534 OriginalFragmentTable = NULL;\r
7618784b
HW
1535\r
1536 //\r
1537 // Rebuild fragment table from BufferIn.\r
1538 //\r
1539 FragmentCount = 1;\r
1540 FragmentTable = AllocateZeroPool (FragmentCount * sizeof (EFI_TLS_FRAGMENT_DATA));\r
1541 if (FragmentTable == NULL) {\r
1542 Status = EFI_OUT_OF_RESOURCES;\r
1543 goto ON_EXIT;\r
1544 }\r
1545\r
d1050b9d 1546 FragmentTable->FragmentLength = (UINT32)MessageSize;\r
7618784b
HW
1547 FragmentTable->FragmentBuffer = Message;\r
1548\r
1549 //\r
1550 // Record the original FragmentTable.\r
1551 //\r
1552 OriginalFragmentTable = FragmentTable;\r
1553\r
1554 //\r
1555 // Process the Message.\r
1556 //\r
1557 Status = HttpInstance->Tls->ProcessPacket (\r
1558 HttpInstance->Tls,\r
1559 &FragmentTable,\r
1560 &FragmentCount,\r
1561 ProcessMode\r
1562 );\r
1563 if (EFI_ERROR (Status)) {\r
1564 goto ON_EXIT;\r
1565 }\r
1566\r
1567 //\r
1568 // Calculate the size according to FragmentTable.\r
1569 //\r
1570 for (Index = 0; Index < FragmentCount; Index++) {\r
1571 BufferSize += FragmentTable[Index].FragmentLength;\r
1572 }\r
1573\r
1574 //\r
1575 // Allocate buffer for processed data.\r
1576 //\r
1577 Buffer = AllocateZeroPool (BufferSize);\r
1578 if (Buffer == NULL) {\r
1579 Status = EFI_OUT_OF_RESOURCES;\r
1580 goto ON_EXIT;\r
1581 }\r
1582\r
1583 //\r
1584 // Copy the new FragmentTable buffer into Buffer.\r
1585 //\r
1586 for (Index = 0; Index < FragmentCount; Index++) {\r
1587 CopyMem (\r
1588 (Buffer + BytesCopied),\r
1589 FragmentTable[Index].FragmentBuffer,\r
1590 FragmentTable[Index].FragmentLength\r
1591 );\r
1592 BytesCopied += FragmentTable[Index].FragmentLength;\r
1593\r
1594 //\r
1595 // Free the FragmentBuffer since it has been copied.\r
1596 //\r
1597 FreePool (FragmentTable[Index].FragmentBuffer);\r
1598 }\r
1599\r
1600 Fragment->Len = BufferSize;\r
1601 Fragment->Bulk = Buffer;\r
1602\r
1603ON_EXIT:\r
1604\r
1605 if (OriginalFragmentTable != NULL) {\r
d1050b9d 1606 if ( FragmentTable == OriginalFragmentTable) {\r
07bd82d4
JW
1607 FragmentTable = NULL;\r
1608 }\r
d1050b9d 1609\r
7618784b
HW
1610 FreePool (OriginalFragmentTable);\r
1611 OriginalFragmentTable = NULL;\r
1612 }\r
1613\r
1614 //\r
1615 // Caller has the responsibility to free the FragmentTable.\r
1616 //\r
1617 if (FragmentTable != NULL) {\r
1618 FreePool (FragmentTable);\r
1619 FragmentTable = NULL;\r
1620 }\r
1621\r
1622 return Status;\r
1623}\r
1624\r
1625/**\r
1626 Receive one fragment decrypted from one TLS record.\r
1627\r
1628 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
1629 @param[in, out] Fragment The received Fragment.\r
1630 @param[in] Timeout The time to wait for connection done.\r
1631\r
1632 @retval EFI_SUCCESS One fragment is received.\r
1633 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.\r
1634 @retval EFI_ABORTED Something wrong decryption the message.\r
1635 @retval Others Other errors as indicated.\r
1636\r
1637**/\r
1638EFI_STATUS\r
1639EFIAPI\r
1640HttpsReceive (\r
d1050b9d
MK
1641 IN HTTP_PROTOCOL *HttpInstance,\r
1642 IN OUT NET_FRAGMENT *Fragment,\r
1643 IN EFI_EVENT Timeout\r
7618784b
HW
1644 )\r
1645{\r
d1050b9d
MK
1646 EFI_STATUS Status;\r
1647 NET_BUF *Pdu;\r
1648 TLS_RECORD_HEADER RecordHeader;\r
1649 UINT8 *BufferIn;\r
1650 UINTN BufferInSize;\r
1651 NET_FRAGMENT TempFragment;\r
1652 UINT8 *BufferOut;\r
1653 UINTN BufferOutSize;\r
1654 NET_BUF *PacketOut;\r
1655 UINT8 *DataOut;\r
1656 UINT8 *GetSessionDataBuffer;\r
1657 UINTN GetSessionDataBufferSize;\r
7618784b
HW
1658\r
1659 Status = EFI_SUCCESS;\r
1660 Pdu = NULL;\r
1661 BufferIn = NULL;\r
1662 BufferInSize = 0;\r
1663 BufferOut = NULL;\r
1664 BufferOutSize = 0;\r
1665 PacketOut = NULL;\r
1666 DataOut = NULL;\r
1667 GetSessionDataBuffer = NULL;\r
1668 GetSessionDataBufferSize = 0;\r
1669\r
1670 //\r
1671 // Receive only one TLS record\r
1672 //\r
1673 Status = TlsReceiveOnePdu (HttpInstance, &Pdu, Timeout);\r
1674 if (EFI_ERROR (Status)) {\r
1675 return Status;\r
1676 }\r
1677\r
1678 BufferInSize = Pdu->TotalSize;\r
d1050b9d 1679 BufferIn = AllocateZeroPool (BufferInSize);\r
7618784b
HW
1680 if (BufferIn == NULL) {\r
1681 Status = EFI_OUT_OF_RESOURCES;\r
1682 NetbufFree (Pdu);\r
1683 return Status;\r
1684 }\r
1685\r
d1050b9d 1686 NetbufCopy (Pdu, 0, (UINT32)BufferInSize, BufferIn);\r
7618784b
HW
1687\r
1688 NetbufFree (Pdu);\r
1689\r
1690 //\r
1691 // Handle Receive data.\r
1692 //\r
d1050b9d 1693 RecordHeader = *(TLS_RECORD_HEADER *)BufferIn;\r
7618784b
HW
1694\r
1695 if ((RecordHeader.ContentType == TlsContentTypeApplicationData) &&\r
d1050b9d
MK
1696 (RecordHeader.Version.Major == 0x03) &&\r
1697 ((RecordHeader.Version.Minor == TLS10_PROTOCOL_VERSION_MINOR) ||\r
1698 (RecordHeader.Version.Minor == TLS11_PROTOCOL_VERSION_MINOR) ||\r
1699 (RecordHeader.Version.Minor == TLS12_PROTOCOL_VERSION_MINOR))\r
1700 )\r
1701 {\r
7618784b
HW
1702 //\r
1703 // Decrypt Packet.\r
1704 //\r
1705 Status = TlsProcessMessage (\r
1706 HttpInstance,\r
1707 BufferIn,\r
1708 BufferInSize,\r
1709 EfiTlsDecrypt,\r
1710 &TempFragment\r
1711 );\r
1712\r
1713 FreePool (BufferIn);\r
1714\r
1715 if (EFI_ERROR (Status)) {\r
1716 if (Status == EFI_ABORTED) {\r
1717 //\r
1718 // Something wrong decryption the message.\r
1719 // BuildResponsePacket() will be called to generate Error Alert message and send it out.\r
1720 //\r
1721 BufferOutSize = DEF_BUF_LEN;\r
d1050b9d 1722 BufferOut = AllocateZeroPool (BufferOutSize);\r
7618784b
HW
1723 if (BufferOut == NULL) {\r
1724 Status = EFI_OUT_OF_RESOURCES;\r
1725 return Status;\r
1726 }\r
1727\r
1728 Status = HttpInstance->Tls->BuildResponsePacket (\r
1729 HttpInstance->Tls,\r
1730 NULL,\r
1731 0,\r
1732 BufferOut,\r
1733 &BufferOutSize\r
1734 );\r
1735 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1736 FreePool (BufferOut);\r
1737 BufferOut = AllocateZeroPool (BufferOutSize);\r
1738 if (BufferOut == NULL) {\r
1739 Status = EFI_OUT_OF_RESOURCES;\r
1740 return Status;\r
1741 }\r
1742\r
1743 Status = HttpInstance->Tls->BuildResponsePacket (\r
1744 HttpInstance->Tls,\r
1745 NULL,\r
1746 0,\r
1747 BufferOut,\r
1748 &BufferOutSize\r
1749 );\r
1750 }\r
d1050b9d 1751\r
7618784b 1752 if (EFI_ERROR (Status)) {\r
d1050b9d 1753 FreePool (BufferOut);\r
7618784b
HW
1754 return Status;\r
1755 }\r
1756\r
1757 if (BufferOutSize != 0) {\r
1758 PacketOut = NetbufAlloc ((UINT32)BufferOutSize);\r
d1050b9d 1759 DataOut = NetbufAllocSpace (PacketOut, (UINT32)BufferOutSize, NET_BUF_TAIL);\r
7618784b
HW
1760 if (DataOut == NULL) {\r
1761 FreePool (BufferOut);\r
1762 return EFI_OUT_OF_RESOURCES;\r
1763 }\r
1764\r
1765 CopyMem (DataOut, BufferOut, BufferOutSize);\r
1766\r
1767 Status = TlsCommonTransmit (HttpInstance, PacketOut);\r
1768\r
1769 NetbufFree (PacketOut);\r
1770 }\r
1771\r
d1050b9d 1772 FreePool (BufferOut);\r
7618784b
HW
1773\r
1774 if (EFI_ERROR (Status)) {\r
1775 return Status;\r
1776 }\r
1777\r
1778 return EFI_ABORTED;\r
1779 }\r
1780\r
1781 return Status;\r
1782 }\r
1783\r
1784 //\r
1785 // Parsing buffer.\r
1786 //\r
d1050b9d 1787 ASSERT (((TLS_RECORD_HEADER *)(TempFragment.Bulk))->ContentType == TlsContentTypeApplicationData);\r
7618784b 1788\r
d1050b9d
MK
1789 BufferInSize = ((TLS_RECORD_HEADER *)(TempFragment.Bulk))->Length;\r
1790 BufferIn = AllocateZeroPool (BufferInSize);\r
7618784b
HW
1791 if (BufferIn == NULL) {\r
1792 Status = EFI_OUT_OF_RESOURCES;\r
1793 return Status;\r
1794 }\r
1795\r
07bd82d4 1796 CopyMem (BufferIn, TempFragment.Bulk + TLS_RECORD_HEADER_LENGTH, BufferInSize);\r
7618784b
HW
1797\r
1798 //\r
1799 // Free the buffer in TempFragment.\r
1800 //\r
1801 FreePool (TempFragment.Bulk);\r
7618784b 1802 } else if ((RecordHeader.ContentType == TlsContentTypeAlert) &&\r
d1050b9d
MK
1803 (RecordHeader.Version.Major == 0x03) &&\r
1804 ((RecordHeader.Version.Minor == TLS10_PROTOCOL_VERSION_MINOR) ||\r
1805 (RecordHeader.Version.Minor == TLS11_PROTOCOL_VERSION_MINOR) ||\r
1806 (RecordHeader.Version.Minor == TLS12_PROTOCOL_VERSION_MINOR))\r
1807 )\r
1808 {\r
7618784b 1809 BufferOutSize = DEF_BUF_LEN;\r
d1050b9d 1810 BufferOut = AllocateZeroPool (BufferOutSize);\r
7618784b
HW
1811 if (BufferOut == NULL) {\r
1812 FreePool (BufferIn);\r
1813 Status = EFI_OUT_OF_RESOURCES;\r
1814 return Status;\r
1815 }\r
1816\r
1817 Status = HttpInstance->Tls->BuildResponsePacket (\r
1818 HttpInstance->Tls,\r
1819 BufferIn,\r
1820 BufferInSize,\r
1821 BufferOut,\r
1822 &BufferOutSize\r
1823 );\r
1824 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1825 FreePool (BufferOut);\r
1826 BufferOut = AllocateZeroPool (BufferOutSize);\r
1827 if (BufferOut == NULL) {\r
1828 FreePool (BufferIn);\r
1829 Status = EFI_OUT_OF_RESOURCES;\r
1830 return Status;\r
1831 }\r
1832\r
1833 Status = HttpInstance->Tls->BuildResponsePacket (\r
1834 HttpInstance->Tls,\r
1835 BufferIn,\r
1836 BufferInSize,\r
1837 BufferOut,\r
1838 &BufferOutSize\r
1839 );\r
1840 }\r
1841\r
1842 FreePool (BufferIn);\r
1843\r
1844 if (EFI_ERROR (Status)) {\r
1845 FreePool (BufferOut);\r
1846 return Status;\r
1847 }\r
1848\r
1849 if (BufferOutSize != 0) {\r
d1050b9d
MK
1850 PacketOut = NetbufAlloc ((UINT32)BufferOutSize);\r
1851 DataOut = NetbufAllocSpace (PacketOut, (UINT32)BufferOutSize, NET_BUF_TAIL);\r
7618784b
HW
1852 if (DataOut == NULL) {\r
1853 FreePool (BufferOut);\r
1854 return EFI_OUT_OF_RESOURCES;\r
1855 }\r
1856\r
1857 CopyMem (DataOut, BufferOut, BufferOutSize);\r
1858\r
1859 Status = TlsCommonTransmit (HttpInstance, PacketOut);\r
1860\r
1861 NetbufFree (PacketOut);\r
1862 }\r
1863\r
1864 FreePool (BufferOut);\r
1865\r
1866 //\r
1867 // Get the session state.\r
1868 //\r
1869 GetSessionDataBufferSize = DEF_BUF_LEN;\r
d1050b9d 1870 GetSessionDataBuffer = AllocateZeroPool (GetSessionDataBufferSize);\r
7618784b
HW
1871 if (GetSessionDataBuffer == NULL) {\r
1872 Status = EFI_OUT_OF_RESOURCES;\r
1873 return Status;\r
1874 }\r
1875\r
1876 Status = HttpInstance->Tls->GetSessionData (\r
1877 HttpInstance->Tls,\r
1878 EfiTlsSessionState,\r
1879 GetSessionDataBuffer,\r
1880 &GetSessionDataBufferSize\r
1881 );\r
1882 if (Status == EFI_BUFFER_TOO_SMALL) {\r
d1050b9d
MK
1883 FreePool (GetSessionDataBuffer);\r
1884 GetSessionDataBuffer = AllocateZeroPool (GetSessionDataBufferSize);\r
1885 if (GetSessionDataBuffer == NULL) {\r
1886 Status = EFI_OUT_OF_RESOURCES;\r
1887 return Status;\r
1888 }\r
1889\r
1890 Status = HttpInstance->Tls->GetSessionData (\r
1891 HttpInstance->Tls,\r
1892 EfiTlsSessionState,\r
1893 GetSessionDataBuffer,\r
1894 &GetSessionDataBufferSize\r
1895 );\r
7618784b 1896 }\r
d1050b9d 1897\r
7618784b
HW
1898 if (EFI_ERROR (Status)) {\r
1899 FreePool (GetSessionDataBuffer);\r
1900 return Status;\r
1901 }\r
1902\r
d1050b9d
MK
1903 ASSERT (GetSessionDataBufferSize == sizeof (EFI_TLS_SESSION_STATE));\r
1904 HttpInstance->TlsSessionState = *(EFI_TLS_SESSION_STATE *)GetSessionDataBuffer;\r
7618784b
HW
1905\r
1906 FreePool (GetSessionDataBuffer);\r
1907\r
d1050b9d 1908 if (HttpInstance->TlsSessionState == EfiTlsSessionError) {\r
c49ca4a2 1909 DEBUG ((DEBUG_ERROR, "TLS Session State Error!\n"));\r
7618784b
HW
1910 return EFI_ABORTED;\r
1911 }\r
1912\r
d1050b9d 1913 BufferIn = NULL;\r
7618784b
HW
1914 BufferInSize = 0;\r
1915 }\r
1916\r
1917 Fragment->Bulk = BufferIn;\r
d1050b9d 1918 Fragment->Len = (UINT32)BufferInSize;\r
7618784b
HW
1919\r
1920 return Status;\r
1921}\r