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