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