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