2 Miscellaneous routines specific to Https for HttpDxe driver.
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "HttpDriver.h"
19 Returns the first occurrence of a Null-terminated ASCII sub-string in a Null-terminated
20 ASCII string and ignore case during the search process.
22 This function scans the contents of the ASCII string specified by String
23 and returns the first occurrence of SearchString and ignore case during the search process.
24 If SearchString is not found in String, then NULL is returned. If the length of SearchString
25 is zero, then String is returned.
27 If String is NULL, then ASSERT().
28 If SearchString is NULL, then ASSERT().
30 @param[in] String A pointer to a Null-terminated ASCII string.
31 @param[in] SearchString A pointer to a Null-terminated ASCII string to search for.
33 @retval NULL If the SearchString does not appear in String.
34 @retval others If there is a match return the first occurrence of SearchingString.
35 If the length of SearchString is zero,return String.
40 IN CONST CHAR8
*String
,
41 IN CONST CHAR8
*SearchString
44 CONST CHAR8
*FirstMatch
;
45 CONST CHAR8
*SearchStringTmp
;
51 // ASSERT both strings are less long than PcdMaximumAsciiStringLength
53 ASSERT (AsciiStrSize (String
) != 0);
54 ASSERT (AsciiStrSize (SearchString
) != 0);
56 if (*SearchString
== '\0') {
57 return (CHAR8
*) String
;
60 while (*String
!= '\0') {
61 SearchStringTmp
= SearchString
;
64 while ((*SearchStringTmp
!= '\0')
65 && (*String
!= '\0')) {
67 Dst
= *SearchStringTmp
;
69 if ((Src
>= 'A') && (Src
<= 'Z')) {
73 if ((Dst
>= 'A') && (Dst
<= 'Z')) {
85 if (*SearchStringTmp
== '\0') {
86 return (CHAR8
*) FirstMatch
;
89 String
= FirstMatch
+ 1;
96 The callback function to free the net buffer list.
98 @param[in] Arg The opaque parameter.
107 ASSERT (Arg
!= NULL
);
109 NetbufFreeList ((LIST_ENTRY
*) Arg
);
114 Check whether the Url is from Https.
116 @param[in] Url The pointer to a HTTP or HTTPS URL string.
118 @retval TRUE The Url is from HTTPS.
119 @retval FALSE The Url is from HTTP.
131 Tmp
= AsciiStrCaseStr (Url
, HTTPS_FLAG
);
132 if (Tmp
!= NULL
&& Tmp
== Url
) {
140 Creates a Tls child handle, open EFI_TLS_PROTOCOL and EFI_TLS_CONFIGURATION_PROTOCOL.
142 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
143 @param[out] TlsProto Pointer to the EFI_TLS_PROTOCOL instance.
144 @param[out] TlsConfiguration Pointer to the EFI_TLS_CONFIGURATION_PROTOCOL instance.
146 @return The child handle with opened EFI_TLS_PROTOCOL and EFI_TLS_CONFIGURATION_PROTOCOL.
152 IN EFI_HANDLE ImageHandle
,
153 OUT EFI_TLS_PROTOCOL
**TlsProto
,
154 OUT EFI_TLS_CONFIGURATION_PROTOCOL
**TlsConfiguration
158 EFI_SERVICE_BINDING_PROTOCOL
*TlsSb
;
159 EFI_HANDLE TlsChildHandle
;
165 // Locate TlsServiceBinding protocol.
167 gBS
->LocateProtocol (
168 &gEfiTlsServiceBindingProtocolGuid
,
176 Status
= TlsSb
->CreateChild (TlsSb
, &TlsChildHandle
);
177 if (EFI_ERROR (Status
)) {
181 Status
= gBS
->OpenProtocol (
183 &gEfiTlsProtocolGuid
,
187 EFI_OPEN_PROTOCOL_GET_PROTOCOL
189 if (EFI_ERROR (Status
)) {
190 TlsSb
->DestroyChild (TlsSb
, TlsChildHandle
);
194 Status
= gBS
->OpenProtocol (
196 &gEfiTlsConfigurationProtocolGuid
,
197 (VOID
**) TlsConfiguration
,
200 EFI_OPEN_PROTOCOL_GET_PROTOCOL
202 if (EFI_ERROR (Status
)) {
203 TlsSb
->DestroyChild (TlsSb
, TlsChildHandle
);
207 return TlsChildHandle
;
211 Create event for the TLS receive and transmit tokens which are used to receive and
212 transmit TLS related messages.
214 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
216 @retval EFI_SUCCESS The events are created successfully.
217 @retval others Other error as indicated.
223 IN OUT HTTP_PROTOCOL
*HttpInstance
228 if (!HttpInstance
->LocalAddressIsIPv6
) {
230 // For Tcp4TlsTxToken.
232 Status
= gBS
->CreateEvent (
236 &HttpInstance
->TlsIsTxDone
,
237 &HttpInstance
->Tcp4TlsTxToken
.CompletionToken
.Event
239 if (EFI_ERROR (Status
)) {
243 HttpInstance
->Tcp4TlsTxData
.Push
= TRUE
;
244 HttpInstance
->Tcp4TlsTxData
.Urgent
= FALSE
;
245 HttpInstance
->Tcp4TlsTxData
.DataLength
= 0;
246 HttpInstance
->Tcp4TlsTxData
.FragmentCount
= 1;
247 HttpInstance
->Tcp4TlsTxData
.FragmentTable
[0].FragmentLength
= HttpInstance
->Tcp4TlsTxData
.DataLength
;
248 HttpInstance
->Tcp4TlsTxData
.FragmentTable
[0].FragmentBuffer
= NULL
;
249 HttpInstance
->Tcp4TlsTxToken
.Packet
.TxData
= &HttpInstance
->Tcp4TlsTxData
;
250 HttpInstance
->Tcp4TlsTxToken
.CompletionToken
.Status
= EFI_NOT_READY
;
253 // For Tcp4TlsRxToken.
255 Status
= gBS
->CreateEvent (
259 &HttpInstance
->TlsIsRxDone
,
260 &HttpInstance
->Tcp4TlsRxToken
.CompletionToken
.Event
262 if (EFI_ERROR (Status
)) {
266 HttpInstance
->Tcp4TlsRxData
.DataLength
= 0;
267 HttpInstance
->Tcp4TlsRxData
.FragmentCount
= 1;
268 HttpInstance
->Tcp4TlsRxData
.FragmentTable
[0].FragmentLength
= HttpInstance
->Tcp4TlsRxData
.DataLength
;
269 HttpInstance
->Tcp4TlsRxData
.FragmentTable
[0].FragmentBuffer
= NULL
;
270 HttpInstance
->Tcp4TlsRxToken
.Packet
.RxData
= &HttpInstance
->Tcp4TlsRxData
;
271 HttpInstance
->Tcp4TlsRxToken
.CompletionToken
.Status
= EFI_NOT_READY
;
274 // For Tcp6TlsTxToken.
276 Status
= gBS
->CreateEvent (
280 &HttpInstance
->TlsIsTxDone
,
281 &HttpInstance
->Tcp6TlsTxToken
.CompletionToken
.Event
283 if (EFI_ERROR (Status
)) {
287 HttpInstance
->Tcp6TlsTxData
.Push
= TRUE
;
288 HttpInstance
->Tcp6TlsTxData
.Urgent
= FALSE
;
289 HttpInstance
->Tcp6TlsTxData
.DataLength
= 0;
290 HttpInstance
->Tcp6TlsTxData
.FragmentCount
= 1;
291 HttpInstance
->Tcp6TlsTxData
.FragmentTable
[0].FragmentLength
= HttpInstance
->Tcp6TlsTxData
.DataLength
;
292 HttpInstance
->Tcp6TlsTxData
.FragmentTable
[0].FragmentBuffer
= NULL
;
293 HttpInstance
->Tcp6TlsTxToken
.Packet
.TxData
= &HttpInstance
->Tcp6TlsTxData
;
294 HttpInstance
->Tcp6TlsTxToken
.CompletionToken
.Status
= EFI_NOT_READY
;
297 // For Tcp6TlsRxToken.
299 Status
= gBS
->CreateEvent (
303 &HttpInstance
->TlsIsRxDone
,
304 &HttpInstance
->Tcp6TlsRxToken
.CompletionToken
.Event
306 if (EFI_ERROR (Status
)) {
310 HttpInstance
->Tcp6TlsRxData
.DataLength
= 0;
311 HttpInstance
->Tcp6TlsRxData
.FragmentCount
= 1;
312 HttpInstance
->Tcp6TlsRxData
.FragmentTable
[0].FragmentLength
= HttpInstance
->Tcp6TlsRxData
.DataLength
;
313 HttpInstance
->Tcp6TlsRxData
.FragmentTable
[0].FragmentBuffer
= NULL
;
314 HttpInstance
->Tcp6TlsRxToken
.Packet
.RxData
= &HttpInstance
->Tcp6TlsRxData
;
315 HttpInstance
->Tcp6TlsRxToken
.CompletionToken
.Status
= EFI_NOT_READY
;
324 TlsCloseTxRxEvent (HttpInstance
);
330 Close events in the TlsTxToken and TlsRxToken.
332 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
338 IN HTTP_PROTOCOL
*HttpInstance
341 ASSERT (HttpInstance
!= NULL
);
342 if (!HttpInstance
->LocalAddressIsIPv6
) {
343 if (NULL
!= HttpInstance
->Tcp4TlsTxToken
.CompletionToken
.Event
) {
344 gBS
->CloseEvent(HttpInstance
->Tcp4TlsTxToken
.CompletionToken
.Event
);
345 HttpInstance
->Tcp4TlsTxToken
.CompletionToken
.Event
= NULL
;
348 if (NULL
!= HttpInstance
->Tcp4TlsRxToken
.CompletionToken
.Event
) {
349 gBS
->CloseEvent (HttpInstance
->Tcp4TlsRxToken
.CompletionToken
.Event
);
350 HttpInstance
->Tcp4TlsRxToken
.CompletionToken
.Event
= NULL
;
353 if (NULL
!= HttpInstance
->Tcp6TlsTxToken
.CompletionToken
.Event
) {
354 gBS
->CloseEvent(HttpInstance
->Tcp6TlsTxToken
.CompletionToken
.Event
);
355 HttpInstance
->Tcp6TlsTxToken
.CompletionToken
.Event
= NULL
;
358 if (NULL
!= HttpInstance
->Tcp6TlsRxToken
.CompletionToken
.Event
) {
359 gBS
->CloseEvent (HttpInstance
->Tcp6TlsRxToken
.CompletionToken
.Event
);
360 HttpInstance
->Tcp6TlsRxToken
.CompletionToken
.Event
= NULL
;
366 Read the TlsCaCertificate variable and configure it.
368 @param[in, out] HttpInstance The HTTP instance private data.
370 @retval EFI_SUCCESS TlsCaCertificate is configured.
371 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
372 @retval EFI_NOT_FOUND Fail to get 'TlsCaCertificate' variable.
373 @retval Others Other error as indicated.
377 TlsConfigCertificate (
378 IN OUT HTTP_PROTOCOL
*HttpInstance
385 EFI_SIGNATURE_LIST
*CertList
;
386 EFI_SIGNATURE_DATA
*Cert
;
394 // Try to read the TlsCaCertificate variable.
396 Status
= gRT
->GetVariable (
397 EFI_TLS_CA_CERTIFICATE_VARIABLE
,
398 &gEfiTlsCaCertificateGuid
,
404 if (Status
== EFI_BUFFER_TOO_SMALL
) {
406 // Allocate buffer and read the config variable.
408 CACert
= AllocatePool (CACertSize
);
409 if (CACert
== NULL
) {
410 return EFI_OUT_OF_RESOURCES
;
413 Status
= gRT
->GetVariable (
414 EFI_TLS_CA_CERTIFICATE_VARIABLE
,
415 &gEfiTlsCaCertificateGuid
,
420 if (EFI_ERROR (Status
)) {
422 // GetVariable still error or the variable is corrupted.
423 // Fall back to the default value.
427 return EFI_NOT_FOUND
;
432 // Enumerate all data and erasing the target item.
434 ItemDataSize
= (UINT32
) CACertSize
;
435 CertList
= (EFI_SIGNATURE_LIST
*) CACert
;
436 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
437 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
438 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
439 for (Index
= 0; Index
< CertCount
; Index
++) {
441 // EfiTlsConfigDataTypeCACertificate
443 Status
= HttpInstance
->TlsConfiguration
->SetData (
444 HttpInstance
->TlsConfiguration
,
445 EfiTlsConfigDataTypeCACertificate
,
447 CertList
->SignatureSize
- sizeof (Cert
->SignatureOwner
)
449 if (EFI_ERROR (Status
)) {
454 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
457 ItemDataSize
-= CertList
->SignatureListSize
;
458 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
466 Configure TLS session data.
468 @param[in, out] HttpInstance The HTTP instance private data.
470 @retval EFI_SUCCESS TLS session data is configured.
471 @retval Others Other error as indicated.
476 TlsConfigureSession (
477 IN OUT HTTP_PROTOCOL
*HttpInstance
483 // TlsConfigData initialization
485 HttpInstance
->TlsConfigData
.ConnectionEnd
= EfiTlsClient
;
486 HttpInstance
->TlsConfigData
.VerifyMethod
= EFI_TLS_VERIFY_PEER
;
487 HttpInstance
->TlsConfigData
.SessionState
= EfiTlsSessionNotStarted
;
490 // EfiTlsConnectionEnd,
491 // EfiTlsVerifyMethod
492 // EfiTlsSessionState
494 Status
= HttpInstance
->Tls
->SetSessionData (
497 &(HttpInstance
->TlsConfigData
.ConnectionEnd
),
498 sizeof (EFI_TLS_CONNECTION_END
)
500 if (EFI_ERROR (Status
)) {
504 Status
= HttpInstance
->Tls
->SetSessionData (
507 &HttpInstance
->TlsConfigData
.VerifyMethod
,
508 sizeof (EFI_TLS_VERIFY
)
510 if (EFI_ERROR (Status
)) {
514 Status
= HttpInstance
->Tls
->SetSessionData (
517 &(HttpInstance
->TlsConfigData
.SessionState
),
518 sizeof (EFI_TLS_SESSION_STATE
)
520 if (EFI_ERROR (Status
)) {
525 // Tls Config Certificate
527 Status
= TlsConfigCertificate (HttpInstance
);
528 if (EFI_ERROR (Status
)) {
529 DEBUG ((EFI_D_ERROR
, "TLS Certificate Config Error!\n"));
534 // TlsCreateTxRxEvent
536 Status
= TlsCreateTxRxEvent (HttpInstance
);
537 if (EFI_ERROR (Status
)) {
544 TlsCloseTxRxEvent (HttpInstance
);
550 Transmit the Packet by processing the associated HTTPS token.
552 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
553 @param[in] Packet The packet to transmit.
555 @retval EFI_SUCCESS The packet is transmitted.
556 @retval EFI_INVALID_PARAMETER HttpInstance is NULL or Packet is NULL.
557 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
558 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
559 @retval Others Other errors as indicated.
565 IN OUT HTTP_PROTOCOL
*HttpInstance
,
573 if ((HttpInstance
== NULL
) || (Packet
== NULL
)) {
574 return EFI_INVALID_PARAMETER
;
577 if (!HttpInstance
->LocalAddressIsIPv6
) {
578 Size
= sizeof (EFI_TCP4_TRANSMIT_DATA
) +
579 (Packet
->BlockOpNum
- 1) * sizeof (EFI_TCP4_FRAGMENT_DATA
);
581 Size
= sizeof (EFI_TCP6_TRANSMIT_DATA
) +
582 (Packet
->BlockOpNum
- 1) * sizeof (EFI_TCP6_FRAGMENT_DATA
);
585 Data
= AllocatePool (Size
);
587 return EFI_OUT_OF_RESOURCES
;
590 if (!HttpInstance
->LocalAddressIsIPv6
) {
591 ((EFI_TCP4_TRANSMIT_DATA
*) Data
)->Push
= TRUE
;
592 ((EFI_TCP4_TRANSMIT_DATA
*) Data
)->Urgent
= FALSE
;
593 ((EFI_TCP4_TRANSMIT_DATA
*) Data
)->DataLength
= Packet
->TotalSize
;
596 // Build the fragment table.
598 ((EFI_TCP4_TRANSMIT_DATA
*) Data
)->FragmentCount
= Packet
->BlockOpNum
;
602 (NET_FRAGMENT
*) &((EFI_TCP4_TRANSMIT_DATA
*) Data
)->FragmentTable
[0],
603 &((EFI_TCP4_TRANSMIT_DATA
*) Data
)->FragmentCount
606 HttpInstance
->Tcp4TlsTxToken
.Packet
.TxData
= (EFI_TCP4_TRANSMIT_DATA
*) Data
;
608 Status
= EFI_DEVICE_ERROR
;
611 // Transmit the packet.
613 Status
= HttpInstance
->Tcp4
->Transmit (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4TlsTxToken
);
614 if (EFI_ERROR (Status
)) {
618 while (!HttpInstance
->TlsIsTxDone
) {
619 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
622 HttpInstance
->TlsIsTxDone
= FALSE
;
623 Status
= HttpInstance
->Tcp4TlsTxToken
.CompletionToken
.Status
;
625 ((EFI_TCP6_TRANSMIT_DATA
*) Data
)->Push
= TRUE
;
626 ((EFI_TCP6_TRANSMIT_DATA
*) Data
)->Urgent
= FALSE
;
627 ((EFI_TCP6_TRANSMIT_DATA
*) Data
)->DataLength
= Packet
->TotalSize
;
630 // Build the fragment table.
632 ((EFI_TCP6_TRANSMIT_DATA
*) Data
)->FragmentCount
= Packet
->BlockOpNum
;
636 (NET_FRAGMENT
*) &((EFI_TCP6_TRANSMIT_DATA
*) Data
)->FragmentTable
[0],
637 &((EFI_TCP6_TRANSMIT_DATA
*) Data
)->FragmentCount
640 HttpInstance
->Tcp6TlsTxToken
.Packet
.TxData
= (EFI_TCP6_TRANSMIT_DATA
*) Data
;
642 Status
= EFI_DEVICE_ERROR
;
645 // Transmit the packet.
647 Status
= HttpInstance
->Tcp6
->Transmit (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6TlsTxToken
);
648 if (EFI_ERROR (Status
)) {
652 while (!HttpInstance
->TlsIsTxDone
) {
653 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
656 HttpInstance
->TlsIsTxDone
= FALSE
;
657 Status
= HttpInstance
->Tcp6TlsTxToken
.CompletionToken
.Status
;
667 Receive the Packet by processing the associated HTTPS token.
669 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
670 @param[in] Packet The packet to transmit.
671 @param[in] Timeout The time to wait for connection done.
673 @retval EFI_SUCCESS The Packet is received.
674 @retval EFI_INVALID_PARAMETER HttpInstance is NULL or Packet is NULL.
675 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
676 @retval EFI_TIMEOUT The operation is time out.
677 @retval Others Other error as indicated.
683 IN OUT HTTP_PROTOCOL
*HttpInstance
,
688 EFI_TCP4_RECEIVE_DATA
*Tcp4RxData
;
689 EFI_TCP6_RECEIVE_DATA
*Tcp6RxData
;
691 NET_FRAGMENT
*Fragment
;
692 UINT32 FragmentCount
;
693 UINT32 CurrentFragment
;
698 if ((HttpInstance
== NULL
) || (Packet
== NULL
)) {
699 return EFI_INVALID_PARAMETER
;
702 FragmentCount
= Packet
->BlockOpNum
;
703 Fragment
= AllocatePool (FragmentCount
* sizeof (NET_FRAGMENT
));
704 if (Fragment
== NULL
) {
705 Status
= EFI_OUT_OF_RESOURCES
;
710 // Build the fragment table.
712 NetbufBuildExt (Packet
, Fragment
, &FragmentCount
);
714 if (!HttpInstance
->LocalAddressIsIPv6
) {
715 Tcp4RxData
= HttpInstance
->Tcp4TlsRxToken
.Packet
.RxData
;
716 if (Tcp4RxData
== NULL
) {
717 return EFI_INVALID_PARAMETER
;
719 Tcp4RxData
->FragmentCount
= 1;
721 Tcp6RxData
= HttpInstance
->Tcp6TlsRxToken
.Packet
.RxData
;
722 if (Tcp6RxData
== NULL
) {
723 return EFI_INVALID_PARAMETER
;
725 Tcp6RxData
->FragmentCount
= 1;
729 Status
= EFI_SUCCESS
;
731 while (CurrentFragment
< FragmentCount
) {
732 if (!HttpInstance
->LocalAddressIsIPv6
) {
733 Tcp4RxData
->DataLength
= Fragment
[CurrentFragment
].Len
;
734 Tcp4RxData
->FragmentTable
[0].FragmentLength
= Fragment
[CurrentFragment
].Len
;
735 Tcp4RxData
->FragmentTable
[0].FragmentBuffer
= Fragment
[CurrentFragment
].Bulk
;
736 Status
= HttpInstance
->Tcp4
->Receive (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4TlsRxToken
);
738 Tcp6RxData
->DataLength
= Fragment
[CurrentFragment
].Len
;
739 Tcp6RxData
->FragmentTable
[0].FragmentLength
= Fragment
[CurrentFragment
].Len
;
740 Tcp6RxData
->FragmentTable
[0].FragmentBuffer
= Fragment
[CurrentFragment
].Bulk
;
741 Status
= HttpInstance
->Tcp6
->Receive (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6TlsRxToken
);
743 if (EFI_ERROR (Status
)) {
747 while (!HttpInstance
->TlsIsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
749 // Poll until some data is received or an error occurs.
751 if (!HttpInstance
->LocalAddressIsIPv6
) {
752 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
754 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
758 if (!HttpInstance
->TlsIsRxDone
) {
760 // Timeout occurs, cancel the receive request.
762 if (!HttpInstance
->LocalAddressIsIPv6
) {
763 HttpInstance
->Tcp4
->Cancel (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4TlsRxToken
.CompletionToken
);
765 HttpInstance
->Tcp6
->Cancel (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6TlsRxToken
.CompletionToken
);
768 Status
= EFI_TIMEOUT
;
771 HttpInstance
->TlsIsRxDone
= FALSE
;
774 if (!HttpInstance
->LocalAddressIsIPv6
) {
775 Status
= HttpInstance
->Tcp4TlsRxToken
.CompletionToken
.Status
;
776 if (EFI_ERROR (Status
)) {
780 Fragment
[CurrentFragment
].Len
-= Tcp4RxData
->FragmentTable
[0].FragmentLength
;
781 if (Fragment
[CurrentFragment
].Len
== 0) {
784 Fragment
[CurrentFragment
].Bulk
+= Tcp4RxData
->FragmentTable
[0].FragmentLength
;
787 Status
= HttpInstance
->Tcp6TlsRxToken
.CompletionToken
.Status
;
788 if (EFI_ERROR (Status
)) {
792 Fragment
[CurrentFragment
].Len
-= Tcp6RxData
->FragmentTable
[0].FragmentLength
;
793 if (Fragment
[CurrentFragment
].Len
== 0) {
796 Fragment
[CurrentFragment
].Bulk
+= Tcp6RxData
->FragmentTable
[0].FragmentLength
;
803 if (Fragment
!= NULL
) {
811 Receive one TLS PDU. An TLS PDU contains an TLS record header and it's
812 corresponding record data. These two parts will be put into two blocks of buffers in the
815 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
816 @param[out] Pdu The received TLS PDU.
817 @param[in] Timeout The time to wait for connection done.
819 @retval EFI_SUCCESS An TLS PDU is received.
820 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
821 @retval EFI_PROTOCOL_ERROR An unexpected TLS packet was received.
822 @retval Others Other errors as indicated.
828 IN OUT HTTP_PROTOCOL
*HttpInstance
,
835 LIST_ENTRY
*NbufList
;
841 TLS_RECORD_HEADER RecordHeader
;
850 NbufList
= AllocatePool (sizeof (LIST_ENTRY
));
851 if (NbufList
== NULL
) {
852 return EFI_OUT_OF_RESOURCES
;
855 InitializeListHead (NbufList
);
858 // Allocate buffer to receive one TLS header.
860 Len
= sizeof (TLS_RECORD_HEADER
);
861 PduHdr
= NetbufAlloc (Len
);
862 if (PduHdr
== NULL
) {
863 Status
= EFI_OUT_OF_RESOURCES
;
867 Header
= NetbufAllocSpace (PduHdr
, Len
, NET_BUF_TAIL
);
868 if (Header
== NULL
) {
869 Status
= EFI_OUT_OF_RESOURCES
;
874 // First step, receive one TLS header.
876 Status
= TlsCommonReceive (HttpInstance
, PduHdr
, Timeout
);
877 if (EFI_ERROR (Status
)) {
881 RecordHeader
= *(TLS_RECORD_HEADER
*) Header
;
882 if ((RecordHeader
.ContentType
== TLS_CONTENT_TYPE_HANDSHAKE
||
883 RecordHeader
.ContentType
== TLS_CONTENT_TYPE_ALERT
||
884 RecordHeader
.ContentType
== TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC
||
885 RecordHeader
.ContentType
== TLS_CONTENT_TYPE_APPLICATION_DATA
) &&
886 (RecordHeader
.Version
.Major
== 0x03) && /// Major versions are same.
887 (RecordHeader
.Version
.Minor
== TLS10_PROTOCOL_VERSION_MINOR
||
888 RecordHeader
.Version
.Minor
==TLS11_PROTOCOL_VERSION_MINOR
||
889 RecordHeader
.Version
.Minor
== TLS12_PROTOCOL_VERSION_MINOR
)
891 InsertTailList (NbufList
, &PduHdr
->List
);
893 Status
= EFI_PROTOCOL_ERROR
;
897 Len
= SwapBytes16(RecordHeader
.Length
);
906 // Allocate buffer to receive one TLS payload.
908 DataSeg
= NetbufAlloc (Len
);
909 if (DataSeg
== NULL
) {
910 Status
= EFI_OUT_OF_RESOURCES
;
914 NetbufAllocSpace (DataSeg
, Len
, NET_BUF_TAIL
);
917 // Second step, receive one TLS payload.
919 Status
= TlsCommonReceive (HttpInstance
, DataSeg
, Timeout
);
920 if (EFI_ERROR (Status
)) {
924 InsertTailList (NbufList
, &DataSeg
->List
);
928 // Form the PDU from a list of PDU.
930 *Pdu
= NetbufFromBufList (NbufList
, 0, 0, FreeNbufList
, NbufList
);
932 Status
= EFI_OUT_OF_RESOURCES
;
937 if (EFI_ERROR (Status
)) {
939 // Free the Nbufs in this NbufList and the NbufList itself.
941 FreeNbufList (NbufList
);
948 Connect one TLS session by finishing the TLS handshake process.
950 @param[in] HttpInstance The HTTP instance private data.
951 @param[in] Timeout The time to wait for connection done.
953 @retval EFI_SUCCESS The TLS session is established.
954 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
955 @retval EFI_ABORTED TLS session state is incorrect.
956 @retval Others Other error as indicated.
962 IN HTTP_PROTOCOL
*HttpInstance
,
974 UINT8
*GetSessionDataBuffer
;
975 UINTN GetSessionDataBufferSize
;
984 // Initialize TLS state.
986 HttpInstance
->TlsSessionState
= EfiTlsSessionNotStarted
;
987 Status
= HttpInstance
->Tls
->SetSessionData (
990 &(HttpInstance
->TlsSessionState
),
991 sizeof (EFI_TLS_SESSION_STATE
)
993 if (EFI_ERROR (Status
)) {
998 // Create ClientHello
1000 BufferOutSize
= DEF_BUF_LEN
;
1001 BufferOut
= AllocateZeroPool (BufferOutSize
);
1002 if (BufferOut
== NULL
) {
1003 Status
= EFI_OUT_OF_RESOURCES
;
1007 Status
= HttpInstance
->Tls
->BuildResponsePacket (
1014 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1015 FreePool (BufferOut
);
1016 BufferOut
= AllocateZeroPool (BufferOutSize
);
1017 if (BufferOut
== NULL
) {
1018 Status
= EFI_OUT_OF_RESOURCES
;
1022 Status
= HttpInstance
->Tls
->BuildResponsePacket (
1030 if (EFI_ERROR (Status
)) {
1031 FreePool (BufferOut
);
1036 // Transmit ClientHello
1038 PacketOut
= NetbufAlloc ((UINT32
) BufferOutSize
);
1039 DataOut
= NetbufAllocSpace (PacketOut
, (UINT32
) BufferOutSize
, NET_BUF_TAIL
);
1040 CopyMem (DataOut
, BufferOut
, BufferOutSize
);
1041 Status
= TlsCommonTransmit (HttpInstance
, PacketOut
);
1043 FreePool (BufferOut
);
1044 NetbufFree (PacketOut
);
1046 if (EFI_ERROR (Status
)) {
1050 while(HttpInstance
->TlsSessionState
!= EfiTlsSessionDataTransferring
&& \
1051 ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
1053 // Receive one TLS record.
1055 Status
= TlsReceiveOnePdu (HttpInstance
, &Pdu
, Timeout
);
1056 if (EFI_ERROR (Status
)) {
1060 BufferInSize
= Pdu
->TotalSize
;
1061 BufferIn
= AllocateZeroPool (BufferInSize
);
1062 if (BufferIn
== NULL
) {
1064 Status
= EFI_OUT_OF_RESOURCES
;
1068 NetbufCopy (Pdu
, 0, (UINT32
)BufferInSize
, BufferIn
);
1073 // Handle Receive data.
1075 BufferOutSize
= DEF_BUF_LEN
;
1076 BufferOut
= AllocateZeroPool (BufferOutSize
);
1077 if (BufferOut
== NULL
) {
1078 Status
= EFI_OUT_OF_RESOURCES
;
1082 Status
= HttpInstance
->Tls
->BuildResponsePacket (
1089 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1090 FreePool (BufferOut
);
1091 BufferOut
= AllocateZeroPool (BufferOutSize
);
1092 if (BufferOut
== NULL
) {
1093 FreePool (BufferIn
);
1094 Status
= EFI_OUT_OF_RESOURCES
;
1098 Status
= HttpInstance
->Tls
->BuildResponsePacket (
1107 FreePool (BufferIn
);
1109 if (EFI_ERROR (Status
)) {
1113 if (BufferOutSize
!= 0) {
1115 // Transmit the response packet.
1117 PacketOut
= NetbufAlloc ((UINT32
) BufferOutSize
);
1118 DataOut
= NetbufAllocSpace (PacketOut
, (UINT32
) BufferOutSize
, NET_BUF_TAIL
);
1119 CopyMem (DataOut
, BufferOut
, BufferOutSize
);
1121 Status
= TlsCommonTransmit (HttpInstance
, PacketOut
);
1123 NetbufFree (PacketOut
);
1125 if (EFI_ERROR (Status
)) {
1126 FreePool (BufferOut
);
1131 FreePool (BufferOut
);
1134 // Get the session state, then decide whether need to continue handle received packet.
1136 GetSessionDataBufferSize
= DEF_BUF_LEN
;
1137 GetSessionDataBuffer
= AllocateZeroPool (GetSessionDataBufferSize
);
1138 if (GetSessionDataBuffer
== NULL
) {
1139 Status
= EFI_OUT_OF_RESOURCES
;
1143 Status
= HttpInstance
->Tls
->GetSessionData (
1146 GetSessionDataBuffer
,
1147 &GetSessionDataBufferSize
1149 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1150 FreePool (GetSessionDataBuffer
);
1151 GetSessionDataBuffer
= AllocateZeroPool (GetSessionDataBufferSize
);
1152 if (GetSessionDataBuffer
== NULL
) {
1153 Status
= EFI_OUT_OF_RESOURCES
;
1157 Status
= HttpInstance
->Tls
->GetSessionData (
1160 GetSessionDataBuffer
,
1161 &GetSessionDataBufferSize
1164 if (EFI_ERROR (Status
)) {
1165 FreePool(GetSessionDataBuffer
);
1169 ASSERT(GetSessionDataBufferSize
== sizeof (EFI_TLS_SESSION_STATE
));
1170 HttpInstance
->TlsSessionState
= *(EFI_TLS_SESSION_STATE
*) GetSessionDataBuffer
;
1172 FreePool (GetSessionDataBuffer
);
1174 if(HttpInstance
->TlsSessionState
== EfiTlsSessionError
) {
1179 if (HttpInstance
->TlsSessionState
!= EfiTlsSessionDataTransferring
) {
1180 Status
= EFI_ABORTED
;
1187 Close the TLS session and send out the close notification message.
1189 @param[in] HttpInstance The HTTP instance private data.
1191 @retval EFI_SUCCESS The TLS session is closed.
1192 @retval EFI_INVALID_PARAMETER HttpInstance is NULL.
1193 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
1194 @retval Others Other error as indicated.
1200 IN HTTP_PROTOCOL
*HttpInstance
1206 UINTN BufferOutSize
;
1211 Status
= EFI_SUCCESS
;
1216 if (HttpInstance
== NULL
) {
1217 return EFI_INVALID_PARAMETER
;
1220 HttpInstance
->TlsSessionState
= EfiTlsSessionClosing
;
1222 Status
= HttpInstance
->Tls
->SetSessionData (
1225 &(HttpInstance
->TlsSessionState
),
1226 sizeof (EFI_TLS_SESSION_STATE
)
1228 if (EFI_ERROR (Status
)) {
1232 BufferOutSize
= DEF_BUF_LEN
;
1233 BufferOut
= AllocateZeroPool (BufferOutSize
);
1234 if (BufferOut
== NULL
) {
1235 Status
= EFI_OUT_OF_RESOURCES
;
1239 Status
= HttpInstance
->Tls
->BuildResponsePacket (
1246 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1247 FreePool (BufferOut
);
1248 BufferOut
= AllocateZeroPool (BufferOutSize
);
1249 if (BufferOut
== NULL
) {
1250 Status
= EFI_OUT_OF_RESOURCES
;
1254 Status
= HttpInstance
->Tls
->BuildResponsePacket (
1263 if (EFI_ERROR (Status
)) {
1264 FreePool (BufferOut
);
1268 PacketOut
= NetbufAlloc ((UINT32
) BufferOutSize
);
1269 DataOut
= NetbufAllocSpace (PacketOut
, (UINT32
) BufferOutSize
, NET_BUF_TAIL
);
1270 CopyMem (DataOut
, BufferOut
, BufferOutSize
);
1272 Status
= TlsCommonTransmit (HttpInstance
, PacketOut
);
1274 FreePool (BufferOut
);
1275 NetbufFree (PacketOut
);
1277 if (EFI_ERROR (Status
)) {
1285 Process one message according to the CryptMode.
1287 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
1288 @param[in] Message Pointer to the message buffer needed to processed.
1289 @param[in] MessageSize Pointer to the message buffer size.
1290 @param[in] ProcessMode Process mode.
1291 @param[in, out] Fragment Only one Fragment returned after the Message is
1292 processed successfully.
1294 @retval EFI_SUCCESS Message is processed successfully.
1295 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
1296 @retval Others Other errors as indicated.
1302 IN HTTP_PROTOCOL
*HttpInstance
,
1304 IN UINTN MessageSize
,
1305 IN EFI_TLS_CRYPT_MODE ProcessMode
,
1306 IN OUT NET_FRAGMENT
*Fragment
1313 EFI_TLS_FRAGMENT_DATA
*FragmentTable
;
1314 UINT32 FragmentCount
;
1315 EFI_TLS_FRAGMENT_DATA
*OriginalFragmentTable
;
1318 Status
= EFI_SUCCESS
;
1322 FragmentTable
= NULL
;
1323 OriginalFragmentTable
= NULL
;
1326 // Rebuild fragment table from BufferIn.
1329 FragmentTable
= AllocateZeroPool (FragmentCount
* sizeof (EFI_TLS_FRAGMENT_DATA
));
1330 if (FragmentTable
== NULL
) {
1331 Status
= EFI_OUT_OF_RESOURCES
;
1335 FragmentTable
->FragmentLength
= (UINT32
) MessageSize
;
1336 FragmentTable
->FragmentBuffer
= Message
;
1339 // Record the original FragmentTable.
1341 OriginalFragmentTable
= FragmentTable
;
1344 // Process the Message.
1346 Status
= HttpInstance
->Tls
->ProcessPacket (
1352 if (EFI_ERROR (Status
)) {
1357 // Calculate the size according to FragmentTable.
1359 for (Index
= 0; Index
< FragmentCount
; Index
++) {
1360 BufferSize
+= FragmentTable
[Index
].FragmentLength
;
1364 // Allocate buffer for processed data.
1366 Buffer
= AllocateZeroPool (BufferSize
);
1367 if (Buffer
== NULL
) {
1368 Status
= EFI_OUT_OF_RESOURCES
;
1373 // Copy the new FragmentTable buffer into Buffer.
1375 for (Index
= 0; Index
< FragmentCount
; Index
++) {
1377 (Buffer
+ BytesCopied
),
1378 FragmentTable
[Index
].FragmentBuffer
,
1379 FragmentTable
[Index
].FragmentLength
1381 BytesCopied
+= FragmentTable
[Index
].FragmentLength
;
1384 // Free the FragmentBuffer since it has been copied.
1386 FreePool (FragmentTable
[Index
].FragmentBuffer
);
1389 Fragment
->Len
= BufferSize
;
1390 Fragment
->Bulk
= Buffer
;
1394 if (OriginalFragmentTable
!= NULL
) {
1395 FreePool (OriginalFragmentTable
);
1396 OriginalFragmentTable
= NULL
;
1400 // Caller has the responsibility to free the FragmentTable.
1402 if (FragmentTable
!= NULL
) {
1403 FreePool (FragmentTable
);
1404 FragmentTable
= NULL
;
1411 Receive one fragment decrypted from one TLS record.
1413 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
1414 @param[in, out] Fragment The received Fragment.
1415 @param[in] Timeout The time to wait for connection done.
1417 @retval EFI_SUCCESS One fragment is received.
1418 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
1419 @retval EFI_ABORTED Something wrong decryption the message.
1420 @retval Others Other errors as indicated.
1426 IN HTTP_PROTOCOL
*HttpInstance
,
1427 IN OUT NET_FRAGMENT
*Fragment
,
1428 IN EFI_EVENT Timeout
1433 TLS_RECORD_HEADER RecordHeader
;
1436 NET_FRAGMENT TempFragment
;
1438 UINTN BufferOutSize
;
1441 UINT8
*GetSessionDataBuffer
;
1442 UINTN GetSessionDataBufferSize
;
1444 Status
= EFI_SUCCESS
;
1452 GetSessionDataBuffer
= NULL
;
1453 GetSessionDataBufferSize
= 0;
1456 // Receive only one TLS record
1458 Status
= TlsReceiveOnePdu (HttpInstance
, &Pdu
, Timeout
);
1459 if (EFI_ERROR (Status
)) {
1463 BufferInSize
= Pdu
->TotalSize
;
1464 BufferIn
= AllocateZeroPool (BufferInSize
);
1465 if (BufferIn
== NULL
) {
1466 Status
= EFI_OUT_OF_RESOURCES
;
1471 NetbufCopy (Pdu
, 0, (UINT32
) BufferInSize
, BufferIn
);
1476 // Handle Receive data.
1478 RecordHeader
= *(TLS_RECORD_HEADER
*) BufferIn
;
1480 if ((RecordHeader
.ContentType
== TLS_CONTENT_TYPE_APPLICATION_DATA
) &&
1481 (RecordHeader
.Version
.Major
== 0x03) &&
1482 (RecordHeader
.Version
.Minor
== TLS10_PROTOCOL_VERSION_MINOR
||
1483 RecordHeader
.Version
.Minor
== TLS11_PROTOCOL_VERSION_MINOR
||
1484 RecordHeader
.Version
.Minor
== TLS12_PROTOCOL_VERSION_MINOR
)
1489 Status
= TlsProcessMessage (
1497 FreePool (BufferIn
);
1499 if (EFI_ERROR (Status
)) {
1500 if (Status
== EFI_ABORTED
) {
1502 // Something wrong decryption the message.
1503 // BuildResponsePacket() will be called to generate Error Alert message and send it out.
1505 BufferOutSize
= DEF_BUF_LEN
;
1506 BufferOut
= AllocateZeroPool (BufferOutSize
);
1507 if (BufferOut
== NULL
) {
1508 Status
= EFI_OUT_OF_RESOURCES
;
1512 Status
= HttpInstance
->Tls
->BuildResponsePacket (
1519 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1520 FreePool (BufferOut
);
1521 BufferOut
= AllocateZeroPool (BufferOutSize
);
1522 if (BufferOut
== NULL
) {
1523 Status
= EFI_OUT_OF_RESOURCES
;
1527 Status
= HttpInstance
->Tls
->BuildResponsePacket (
1535 if (EFI_ERROR (Status
)) {
1536 FreePool(BufferOut
);
1540 if (BufferOutSize
!= 0) {
1541 PacketOut
= NetbufAlloc ((UINT32
)BufferOutSize
);
1542 DataOut
= NetbufAllocSpace (PacketOut
, (UINT32
) BufferOutSize
, NET_BUF_TAIL
);
1543 CopyMem (DataOut
, BufferOut
, BufferOutSize
);
1545 Status
= TlsCommonTransmit (HttpInstance
, PacketOut
);
1547 NetbufFree (PacketOut
);
1550 FreePool(BufferOut
);
1552 if (EFI_ERROR (Status
)) {
1565 ASSERT (((TLS_RECORD_HEADER
*) (TempFragment
.Bulk
))->ContentType
== TLS_CONTENT_TYPE_APPLICATION_DATA
);
1567 BufferInSize
= ((TLS_RECORD_HEADER
*) (TempFragment
.Bulk
))->Length
;
1568 BufferIn
= AllocateZeroPool (BufferInSize
);
1569 if (BufferIn
== NULL
) {
1570 Status
= EFI_OUT_OF_RESOURCES
;
1574 CopyMem (BufferIn
, TempFragment
.Bulk
+ sizeof (TLS_RECORD_HEADER
), BufferInSize
);
1577 // Free the buffer in TempFragment.
1579 FreePool (TempFragment
.Bulk
);
1581 } else if ((RecordHeader
.ContentType
== TLS_CONTENT_TYPE_ALERT
) &&
1582 (RecordHeader
.Version
.Major
== 0x03) &&
1583 (RecordHeader
.Version
.Minor
== TLS10_PROTOCOL_VERSION_MINOR
||
1584 RecordHeader
.Version
.Minor
== TLS11_PROTOCOL_VERSION_MINOR
||
1585 RecordHeader
.Version
.Minor
== TLS12_PROTOCOL_VERSION_MINOR
)
1587 BufferOutSize
= DEF_BUF_LEN
;
1588 BufferOut
= AllocateZeroPool (BufferOutSize
);
1589 if (BufferOut
== NULL
) {
1590 FreePool (BufferIn
);
1591 Status
= EFI_OUT_OF_RESOURCES
;
1595 Status
= HttpInstance
->Tls
->BuildResponsePacket (
1602 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1603 FreePool (BufferOut
);
1604 BufferOut
= AllocateZeroPool (BufferOutSize
);
1605 if (BufferOut
== NULL
) {
1606 FreePool (BufferIn
);
1607 Status
= EFI_OUT_OF_RESOURCES
;
1611 Status
= HttpInstance
->Tls
->BuildResponsePacket (
1620 FreePool (BufferIn
);
1622 if (EFI_ERROR (Status
)) {
1623 FreePool (BufferOut
);
1627 if (BufferOutSize
!= 0) {
1628 PacketOut
= NetbufAlloc ((UINT32
) BufferOutSize
);
1629 DataOut
= NetbufAllocSpace (PacketOut
, (UINT32
) BufferOutSize
, NET_BUF_TAIL
);
1630 CopyMem (DataOut
, BufferOut
, BufferOutSize
);
1632 Status
= TlsCommonTransmit (HttpInstance
, PacketOut
);
1634 NetbufFree (PacketOut
);
1637 FreePool (BufferOut
);
1640 // Get the session state.
1642 GetSessionDataBufferSize
= DEF_BUF_LEN
;
1643 GetSessionDataBuffer
= AllocateZeroPool (GetSessionDataBufferSize
);
1644 if (GetSessionDataBuffer
== NULL
) {
1645 Status
= EFI_OUT_OF_RESOURCES
;
1649 Status
= HttpInstance
->Tls
->GetSessionData (
1652 GetSessionDataBuffer
,
1653 &GetSessionDataBufferSize
1655 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1656 FreePool (GetSessionDataBuffer
);
1657 GetSessionDataBuffer
= AllocateZeroPool (GetSessionDataBufferSize
);
1658 if (GetSessionDataBuffer
== NULL
) {
1659 Status
= EFI_OUT_OF_RESOURCES
;
1663 Status
= HttpInstance
->Tls
->GetSessionData (
1666 GetSessionDataBuffer
,
1667 &GetSessionDataBufferSize
1670 if (EFI_ERROR (Status
)) {
1671 FreePool (GetSessionDataBuffer
);
1675 ASSERT(GetSessionDataBufferSize
== sizeof (EFI_TLS_SESSION_STATE
));
1676 HttpInstance
->TlsSessionState
= *(EFI_TLS_SESSION_STATE
*) GetSessionDataBuffer
;
1678 FreePool (GetSessionDataBuffer
);
1680 if(HttpInstance
->TlsSessionState
== EfiTlsSessionError
) {
1681 DEBUG ((EFI_D_ERROR
, "TLS Session State Error!\n"));
1689 Fragment
->Bulk
= BufferIn
;
1690 Fragment
->Len
= (UINT32
) BufferInSize
;