]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/TlsDxe/TlsProtocol.c
NetworkPkg/TlsDxe: Add the support of host validation to TlsDxe driver (CVE-2019...
[mirror_edk2.git] / NetworkPkg / TlsDxe / TlsProtocol.c
CommitLineData
7618784b
HW
1/** @file\r
2 Implementation of EFI TLS Protocol Interfaces.\r
3\r
703e7ab2 4 Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
7618784b 5\r
ecf98fbc 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7618784b
HW
7\r
8**/\r
9\r
10#include "TlsImpl.h"\r
11\r
12EFI_TLS_PROTOCOL mTlsProtocol = {\r
13 TlsSetSessionData,\r
14 TlsGetSessionData,\r
15 TlsBuildResponsePacket,\r
16 TlsProcessPacket\r
17};\r
18\r
19/**\r
20 Set TLS session data.\r
21\r
22 The SetSessionData() function set data for a new TLS session. All session data should\r
23 be set before BuildResponsePacket() invoked.\r
24\r
25 @param[in] This Pointer to the EFI_TLS_PROTOCOL instance.\r
26 @param[in] DataType TLS session data type.\r
27 @param[in] Data Pointer to session data.\r
28 @param[in] DataSize Total size of session data.\r
29\r
30 @retval EFI_SUCCESS The TLS session data is set successfully.\r
31 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
32 This is NULL.\r
33 Data is NULL.\r
34 DataSize is 0.\r
44eb9740 35 DataSize is invalid for DataType.\r
7618784b
HW
36 @retval EFI_UNSUPPORTED The DataType is unsupported.\r
37 @retval EFI_ACCESS_DENIED If the DataType is one of below:\r
38 EfiTlsClientRandom\r
39 EfiTlsServerRandom\r
40 EfiTlsKeyMaterial\r
41 @retval EFI_NOT_READY Current TLS session state is NOT\r
42 EfiTlsSessionStateNotStarted.\r
43 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.\r
44**/\r
45EFI_STATUS\r
46EFIAPI\r
47TlsSetSessionData (\r
48 IN EFI_TLS_PROTOCOL *This,\r
49 IN EFI_TLS_SESSION_DATA_TYPE DataType,\r
50 IN VOID *Data,\r
51 IN UINTN DataSize\r
52 )\r
53{\r
54 EFI_STATUS Status;\r
55 TLS_INSTANCE *Instance;\r
56 UINT16 *CipherId;\r
b1c81b6e 57 CONST EFI_TLS_CIPHER *TlsCipherList;\r
44eb9740 58 UINTN CipherCount;\r
703e7ab2
WJ
59 CONST EFI_TLS_VERIFY_HOST *TlsVerifyHost;\r
60 EFI_TLS_VERIFY VerifyMethod;\r
61 UINTN VerifyMethodSize;\r
7618784b
HW
62 UINTN Index;\r
63\r
64 EFI_TPL OldTpl;\r
65\r
703e7ab2
WJ
66 Status = EFI_SUCCESS;\r
67 CipherId = NULL;\r
68 VerifyMethodSize = sizeof (EFI_TLS_VERIFY);\r
7618784b
HW
69\r
70 if (This == NULL || Data == NULL || DataSize == 0) {\r
71 return EFI_INVALID_PARAMETER;\r
72 }\r
73\r
74 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
75\r
76 Instance = TLS_INSTANCE_FROM_PROTOCOL (This);\r
77\r
78 if (DataType != EfiTlsSessionState && Instance->TlsSessionState != EfiTlsSessionNotStarted){\r
79 Status = EFI_NOT_READY;\r
80 goto ON_EXIT;\r
81 }\r
82\r
83 switch (DataType) {\r
84 //\r
85 // Session Configuration\r
86 //\r
87 case EfiTlsVersion:\r
88 if (DataSize != sizeof (EFI_TLS_VERSION)) {\r
89 Status = EFI_INVALID_PARAMETER;\r
90 goto ON_EXIT;\r
91 }\r
92\r
93 Status = TlsSetVersion (Instance->TlsConn, ((EFI_TLS_VERSION *) Data)->Major, ((EFI_TLS_VERSION *) Data)->Minor);\r
94 break;\r
95 case EfiTlsConnectionEnd:\r
96 if (DataSize != sizeof (EFI_TLS_CONNECTION_END)) {\r
97 Status = EFI_INVALID_PARAMETER;\r
98 goto ON_EXIT;\r
99 }\r
100\r
101 Status = TlsSetConnectionEnd (Instance->TlsConn, *((EFI_TLS_CONNECTION_END *) Data));\r
102 break;\r
103 case EfiTlsCipherList:\r
44eb9740
LE
104 if (DataSize % sizeof (EFI_TLS_CIPHER) != 0) {\r
105 Status = EFI_INVALID_PARAMETER;\r
106 goto ON_EXIT;\r
107 }\r
108\r
7618784b
HW
109 CipherId = AllocatePool (DataSize);\r
110 if (CipherId == NULL) {\r
111 Status = EFI_OUT_OF_RESOURCES;\r
112 goto ON_EXIT;\r
113 }\r
114\r
b1c81b6e 115 TlsCipherList = (CONST EFI_TLS_CIPHER *) Data;\r
44eb9740
LE
116 CipherCount = DataSize / sizeof (EFI_TLS_CIPHER);\r
117 for (Index = 0; Index < CipherCount; Index++) {\r
b1c81b6e
LE
118 CipherId[Index] = ((TlsCipherList[Index].Data1 << 8) |\r
119 TlsCipherList[Index].Data2);\r
7618784b
HW
120 }\r
121\r
44eb9740 122 Status = TlsSetCipherList (Instance->TlsConn, CipherId, CipherCount);\r
7618784b
HW
123\r
124 FreePool (CipherId);\r
125 break;\r
126 case EfiTlsCompressionMethod:\r
127 //\r
128 // TLS seems only define one CompressionMethod.null, which specifies that data exchanged via the\r
129 // record protocol will not be compressed.\r
130 // More information from OpenSSL: http://www.openssl.org/docs/manmaster/ssl/SSL_COMP_add_compression_method.html\r
131 // The TLS RFC does however not specify compression methods or their corresponding identifiers,\r
132 // so there is currently no compatible way to integrate compression with unknown peers.\r
133 // It is therefore currently not recommended to integrate compression into applications.\r
134 // Applications for non-public use may agree on certain compression methods.\r
135 // Using different compression methods with the same identifier will lead to connection failure.\r
136 //\r
137 for (Index = 0; Index < DataSize / sizeof (EFI_TLS_COMPRESSION); Index++) {\r
138 Status = TlsSetCompressionMethod (*((UINT8 *) Data + Index));\r
139 if (EFI_ERROR (Status)) {\r
140 break;\r
141 }\r
142 }\r
143\r
144 break;\r
145 case EfiTlsExtensionData:\r
146 Status = EFI_UNSUPPORTED;\r
147 goto ON_EXIT;\r
148 case EfiTlsVerifyMethod:\r
149 if (DataSize != sizeof (EFI_TLS_VERIFY)) {\r
150 Status = EFI_INVALID_PARAMETER;\r
151 goto ON_EXIT;\r
152 }\r
153\r
154 TlsSetVerify (Instance->TlsConn, *((UINT32 *) Data));\r
703e7ab2
WJ
155 break;\r
156 case EfiTlsVerifyHost:\r
157 if (DataSize != sizeof (EFI_TLS_VERIFY_HOST)) {\r
158 Status = EFI_INVALID_PARAMETER;\r
159 goto ON_EXIT;\r
160 }\r
161\r
162 TlsVerifyHost = (CONST EFI_TLS_VERIFY_HOST *) Data;\r
163\r
164 if ((TlsVerifyHost->Flags & EFI_TLS_VERIFY_FLAG_ALWAYS_CHECK_SUBJECT) != 0 &&\r
165 (TlsVerifyHost->Flags & EFI_TLS_VERIFY_FLAG_NEVER_CHECK_SUBJECT) != 0) {\r
166 Status = EFI_INVALID_PARAMETER;\r
167 goto ON_EXIT;\r
168 }\r
169\r
170 if ((TlsVerifyHost->Flags & EFI_TLS_VERIFY_FLAG_NO_WILDCARDS) != 0 &&\r
171 ((TlsVerifyHost->Flags & EFI_TLS_VERIFY_FLAG_NO_PARTIAL_WILDCARDS) != 0 ||\r
172 (TlsVerifyHost->Flags & EFI_TLS_VERIFY_FLAG_MULTI_LABEL_WILDCARDS) != 0)) {\r
173 Status = EFI_INVALID_PARAMETER;\r
174 goto ON_EXIT;\r
175 }\r
176\r
177 Status = This->GetSessionData (This, EfiTlsVerifyMethod, &VerifyMethod, &VerifyMethodSize);\r
178 if (EFI_ERROR (Status)) {\r
179 goto ON_EXIT;\r
180 }\r
181\r
182 if ((VerifyMethod & EFI_TLS_VERIFY_PEER) == 0) {\r
183 Status = EFI_INVALID_PARAMETER;\r
184 goto ON_EXIT;\r
185 }\r
186\r
187 Status = TlsSetVerifyHost (Instance->TlsConn, TlsVerifyHost->Flags, TlsVerifyHost->HostName);\r
188\r
7618784b
HW
189 break;\r
190 case EfiTlsSessionID:\r
191 if (DataSize != sizeof (EFI_TLS_SESSION_ID)) {\r
192 Status = EFI_INVALID_PARAMETER;\r
193 goto ON_EXIT;\r
194 }\r
195\r
196 Status = TlsSetSessionId (\r
197 Instance->TlsConn,\r
198 ((EFI_TLS_SESSION_ID *) Data)->Data,\r
199 ((EFI_TLS_SESSION_ID *) Data)->Length\r
200 );\r
201 break;\r
202 case EfiTlsSessionState:\r
203 if (DataSize != sizeof (EFI_TLS_SESSION_STATE)) {\r
204 Status = EFI_INVALID_PARAMETER;\r
205 goto ON_EXIT;\r
206 }\r
207\r
208 Instance->TlsSessionState = *(EFI_TLS_SESSION_STATE *) Data;\r
209 break;\r
210 //\r
211 // Session information\r
212 //\r
213 case EfiTlsClientRandom:\r
214 Status = EFI_ACCESS_DENIED;\r
215 break;\r
216 case EfiTlsServerRandom:\r
217 Status = EFI_ACCESS_DENIED;\r
218 break;\r
219 case EfiTlsKeyMaterial:\r
220 Status = EFI_ACCESS_DENIED;\r
221 break;\r
222 //\r
223 // Unsupported type.\r
224 //\r
225 default:\r
226 Status = EFI_UNSUPPORTED;\r
227 }\r
228\r
229ON_EXIT:\r
230 gBS->RestoreTPL (OldTpl);\r
231 return Status;\r
232}\r
233\r
234/**\r
235 Get TLS session data.\r
236\r
237 The GetSessionData() function return the TLS session information.\r
238\r
239 @param[in] This Pointer to the EFI_TLS_PROTOCOL instance.\r
240 @param[in] DataType TLS session data type.\r
241 @param[in, out] Data Pointer to session data.\r
242 @param[in, out] DataSize Total size of session data. On input, it means\r
243 the size of Data buffer. On output, it means the size\r
244 of copied Data buffer if EFI_SUCCESS, and means the\r
245 size of desired Data buffer if EFI_BUFFER_TOO_SMALL.\r
246\r
247 @retval EFI_SUCCESS The TLS session data is got successfully.\r
248 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
249 This is NULL.\r
250 DataSize is NULL.\r
251 Data is NULL if *DataSize is not zero.\r
252 @retval EFI_UNSUPPORTED The DataType is unsupported.\r
253 @retval EFI_NOT_FOUND The TLS session data is not found.\r
254 @retval EFI_NOT_READY The DataType is not ready in current session state.\r
255 @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the data.\r
256**/\r
257EFI_STATUS\r
258EFIAPI\r
259TlsGetSessionData (\r
260 IN EFI_TLS_PROTOCOL *This,\r
261 IN EFI_TLS_SESSION_DATA_TYPE DataType,\r
262 IN OUT VOID *Data, OPTIONAL\r
263 IN OUT UINTN *DataSize\r
264 )\r
265{\r
266 EFI_STATUS Status;\r
267 TLS_INSTANCE *Instance;\r
268\r
269 EFI_TPL OldTpl;\r
270\r
271 Status = EFI_SUCCESS;\r
272\r
273 if (This == NULL || DataSize == NULL || (Data == NULL && *DataSize != 0)) {\r
274 return EFI_INVALID_PARAMETER;\r
275 }\r
276\r
277 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
278\r
279 Instance = TLS_INSTANCE_FROM_PROTOCOL (This);\r
280\r
281 if (Instance->TlsSessionState == EfiTlsSessionNotStarted &&\r
282 (DataType == EfiTlsSessionID || DataType == EfiTlsClientRandom ||\r
283 DataType == EfiTlsServerRandom || DataType == EfiTlsKeyMaterial)) {\r
284 Status = EFI_NOT_READY;\r
285 goto ON_EXIT;\r
286 }\r
287\r
288 switch (DataType) {\r
289 case EfiTlsVersion:\r
290 if (*DataSize < sizeof (EFI_TLS_VERSION)) {\r
291 *DataSize = sizeof (EFI_TLS_VERSION);\r
292 Status = EFI_BUFFER_TOO_SMALL;\r
293 goto ON_EXIT;\r
294 }\r
295 *DataSize = sizeof (EFI_TLS_VERSION);\r
296 *((UINT16 *) Data) = HTONS (TlsGetVersion (Instance->TlsConn));\r
297 break;\r
298 case EfiTlsConnectionEnd:\r
299 if (*DataSize < sizeof (EFI_TLS_CONNECTION_END)) {\r
300 *DataSize = sizeof (EFI_TLS_CONNECTION_END);\r
301 Status = EFI_BUFFER_TOO_SMALL;\r
302 goto ON_EXIT;\r
303 }\r
304 *DataSize = sizeof (EFI_TLS_CONNECTION_END);\r
305 *((UINT8 *) Data) = TlsGetConnectionEnd (Instance->TlsConn);\r
306 break;\r
307 case EfiTlsCipherList:\r
308 //\r
309 // Get the current session cipher suite.\r
310 //\r
311 if (*DataSize < sizeof (EFI_TLS_CIPHER)) {\r
312 *DataSize = sizeof (EFI_TLS_CIPHER);\r
313 Status = EFI_BUFFER_TOO_SMALL;\r
314 goto ON_EXIT;\r
315 }\r
316 *DataSize = sizeof(EFI_TLS_CIPHER);\r
317 Status = TlsGetCurrentCipher (Instance->TlsConn, (UINT16 *) Data);\r
318 *((UINT16 *) Data) = HTONS (*((UINT16 *) Data));\r
319 break;\r
320 case EfiTlsCompressionMethod:\r
321 //\r
322 // Get the current session compression method.\r
323 //\r
324 if (*DataSize < sizeof (EFI_TLS_COMPRESSION)) {\r
325 *DataSize = sizeof (EFI_TLS_COMPRESSION);\r
326 Status = EFI_BUFFER_TOO_SMALL;\r
327 goto ON_EXIT;\r
328 }\r
329 *DataSize = sizeof (EFI_TLS_COMPRESSION);\r
330 Status = TlsGetCurrentCompressionId (Instance->TlsConn, (UINT8 *) Data);\r
331 break;\r
332 case EfiTlsExtensionData:\r
333 Status = EFI_UNSUPPORTED;\r
334 goto ON_EXIT;\r
335 case EfiTlsVerifyMethod:\r
336 if (*DataSize < sizeof (EFI_TLS_VERIFY)) {\r
337 *DataSize = sizeof (EFI_TLS_VERIFY);\r
338 Status = EFI_BUFFER_TOO_SMALL;\r
339 goto ON_EXIT;\r
340 }\r
341 *DataSize = sizeof (EFI_TLS_VERIFY);\r
342 *((UINT32 *) Data) = TlsGetVerify (Instance->TlsConn);\r
343 break;\r
344 case EfiTlsSessionID:\r
345 if (*DataSize < sizeof (EFI_TLS_SESSION_ID)) {\r
346 *DataSize = sizeof (EFI_TLS_SESSION_ID);\r
347 Status = EFI_BUFFER_TOO_SMALL;\r
348 goto ON_EXIT;\r
349 }\r
350 *DataSize = sizeof (EFI_TLS_SESSION_ID);\r
351 Status = TlsGetSessionId (\r
352 Instance->TlsConn,\r
353 ((EFI_TLS_SESSION_ID *) Data)->Data,\r
354 &(((EFI_TLS_SESSION_ID *) Data)->Length)\r
355 );\r
356 break;\r
357 case EfiTlsSessionState:\r
358 if (*DataSize < sizeof (EFI_TLS_SESSION_STATE)) {\r
359 *DataSize = sizeof (EFI_TLS_SESSION_STATE);\r
360 Status = EFI_BUFFER_TOO_SMALL;\r
361 goto ON_EXIT;\r
362 }\r
363 *DataSize = sizeof (EFI_TLS_SESSION_STATE);\r
364 CopyMem (Data, &Instance->TlsSessionState, *DataSize);\r
365 break;\r
366 case EfiTlsClientRandom:\r
367 if (*DataSize < sizeof (EFI_TLS_RANDOM)) {\r
368 *DataSize = sizeof (EFI_TLS_RANDOM);\r
369 Status = EFI_BUFFER_TOO_SMALL;\r
370 goto ON_EXIT;\r
371 }\r
372 *DataSize = sizeof (EFI_TLS_RANDOM);\r
373 TlsGetClientRandom (Instance->TlsConn, (UINT8 *) Data);\r
374 break;\r
375 case EfiTlsServerRandom:\r
376 if (*DataSize < sizeof (EFI_TLS_RANDOM)) {\r
377 *DataSize = sizeof (EFI_TLS_RANDOM);\r
378 Status = EFI_BUFFER_TOO_SMALL;\r
379 goto ON_EXIT;\r
380 }\r
381 *DataSize = sizeof (EFI_TLS_RANDOM);\r
382 TlsGetServerRandom (Instance->TlsConn, (UINT8 *) Data);\r
383 break;\r
384 case EfiTlsKeyMaterial:\r
385 if (*DataSize < sizeof (EFI_TLS_MASTER_SECRET)) {\r
386 *DataSize = sizeof (EFI_TLS_MASTER_SECRET);\r
387 Status = EFI_BUFFER_TOO_SMALL;\r
388 goto ON_EXIT;\r
389 }\r
390 *DataSize = sizeof (EFI_TLS_MASTER_SECRET);\r
391 Status = TlsGetKeyMaterial (Instance->TlsConn, (UINT8 *) Data);\r
392 break;\r
393 //\r
394 // Unsupported type.\r
395 //\r
396 default:\r
397 Status = EFI_UNSUPPORTED;\r
398 }\r
399\r
400ON_EXIT:\r
401 gBS->RestoreTPL (OldTpl);\r
402 return Status;\r
403}\r
404\r
405/**\r
406 Build response packet according to TLS state machine. This function is only valid for\r
407 alert, handshake and change_cipher_spec content type.\r
408\r
409 The BuildResponsePacket() function builds TLS response packet in response to the TLS\r
410 request packet specified by RequestBuffer and RequestSize. If RequestBuffer is NULL and\r
411 RequestSize is 0, and TLS session status is EfiTlsSessionNotStarted, the TLS session\r
412 will be initiated and the response packet needs to be ClientHello. If RequestBuffer is\r
413 NULL and RequestSize is 0, and TLS session status is EfiTlsSessionClosing, the TLS\r
414 session will be closed and response packet needs to be CloseNotify. If RequestBuffer is\r
415 NULL and RequestSize is 0, and TLS session status is EfiTlsSessionError, the TLS\r
416 session has errors and the response packet needs to be Alert message based on error\r
417 type.\r
418\r
419 @param[in] This Pointer to the EFI_TLS_PROTOCOL instance.\r
420 @param[in] RequestBuffer Pointer to the most recently received TLS packet. NULL\r
421 means TLS need initiate the TLS session and response\r
422 packet need to be ClientHello.\r
423 @param[in] RequestSize Packet size in bytes for the most recently received TLS\r
424 packet. 0 is only valid when RequestBuffer is NULL.\r
425 @param[out] Buffer Pointer to the buffer to hold the built packet.\r
426 @param[in, out] BufferSize Pointer to the buffer size in bytes. On input, it is\r
427 the buffer size provided by the caller. On output, it\r
428 is the buffer size in fact needed to contain the\r
429 packet.\r
430\r
431 @retval EFI_SUCCESS The required TLS packet is built successfully.\r
432 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
433 This is NULL.\r
434 RequestBuffer is NULL but RequestSize is NOT 0.\r
435 RequestSize is 0 but RequestBuffer is NOT NULL.\r
436 BufferSize is NULL.\r
437 Buffer is NULL if *BufferSize is not zero.\r
438 @retval EFI_BUFFER_TOO_SMALL BufferSize is too small to hold the response packet.\r
439 @retval EFI_NOT_READY Current TLS session state is NOT ready to build\r
440 ResponsePacket.\r
441 @retval EFI_ABORTED Something wrong build response packet.\r
442**/\r
443EFI_STATUS\r
444EFIAPI\r
445TlsBuildResponsePacket (\r
446 IN EFI_TLS_PROTOCOL *This,\r
447 IN UINT8 *RequestBuffer, OPTIONAL\r
448 IN UINTN RequestSize, OPTIONAL\r
449 OUT UINT8 *Buffer, OPTIONAL\r
450 IN OUT UINTN *BufferSize\r
451 )\r
452{\r
453 EFI_STATUS Status;\r
454 TLS_INSTANCE *Instance;\r
455 EFI_TPL OldTpl;\r
456\r
457 Status = EFI_SUCCESS;\r
458\r
459 if ((This == NULL) || (BufferSize == NULL) ||\r
460 (RequestBuffer == NULL && RequestSize != 0) ||\r
461 (RequestBuffer != NULL && RequestSize == 0) ||\r
462 (Buffer == NULL && *BufferSize !=0)) {\r
463 return EFI_INVALID_PARAMETER;\r
464 }\r
465\r
466 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
467\r
468 Instance = TLS_INSTANCE_FROM_PROTOCOL (This);\r
469\r
470 if(RequestBuffer == NULL && RequestSize == 0) {\r
471 switch (Instance->TlsSessionState) {\r
472 case EfiTlsSessionNotStarted:\r
473 //\r
474 // ClientHello.\r
475 //\r
476 Status = TlsDoHandshake (\r
477 Instance->TlsConn,\r
478 NULL,\r
479 0,\r
480 Buffer,\r
481 BufferSize\r
482 );\r
483 if (EFI_ERROR (Status)) {\r
484 goto ON_EXIT;\r
485 }\r
486\r
487 //\r
488 // *BufferSize should not be zero when ClientHello.\r
489 //\r
490 if (*BufferSize == 0) {\r
491 Status = EFI_ABORTED;\r
492 goto ON_EXIT;\r
493 }\r
494\r
495 Instance->TlsSessionState = EfiTlsSessionHandShaking;\r
496\r
497 break;\r
498 case EfiTlsSessionClosing:\r
499 //\r
500 // TLS session will be closed and response packet needs to be CloseNotify.\r
501 //\r
502 Status = TlsCloseNotify (\r
503 Instance->TlsConn,\r
504 Buffer,\r
505 BufferSize\r
506 );\r
507 if (EFI_ERROR (Status)) {\r
508 goto ON_EXIT;\r
509 }\r
510\r
511 //\r
512 // *BufferSize should not be zero when build CloseNotify message.\r
513 //\r
514 if (*BufferSize == 0) {\r
515 Status = EFI_ABORTED;\r
516 goto ON_EXIT;\r
517 }\r
518\r
519 break;\r
520 case EfiTlsSessionError:\r
521 //\r
522 // TLS session has errors and the response packet needs to be Alert\r
523 // message based on error type.\r
524 //\r
525 Status = TlsHandleAlert (\r
526 Instance->TlsConn,\r
527 NULL,\r
528 0,\r
529 Buffer,\r
530 BufferSize\r
531 );\r
532 if (EFI_ERROR (Status)) {\r
533 goto ON_EXIT;\r
534 }\r
535\r
536 break;\r
537 default:\r
538 //\r
539 // Current TLS session state is NOT ready to build ResponsePacket.\r
540 //\r
541 Status = EFI_NOT_READY;\r
542 }\r
543 } else {\r
544 //\r
545 // 1. Received packet may have multiple TLS record messages.\r
546 // 2. One TLS record message may have multiple handshake protocol.\r
547 // 3. Some errors may be happened in handshake.\r
548 // TlsDoHandshake() can handle all of those cases.\r
549 //\r
550 if (TlsInHandshake (Instance->TlsConn)) {\r
551 Status = TlsDoHandshake (\r
552 Instance->TlsConn,\r
553 RequestBuffer,\r
554 RequestSize,\r
555 Buffer,\r
556 BufferSize\r
557 );\r
558 if (EFI_ERROR (Status)) {\r
559 goto ON_EXIT;\r
560 }\r
561\r
562 if (!TlsInHandshake (Instance->TlsConn)) {\r
563 Instance->TlsSessionState = EfiTlsSessionDataTransferring;\r
564 }\r
565 } else {\r
566 //\r
567 // Must be alert message, Decrypt it and build the ResponsePacket.\r
568 //\r
569 ASSERT (((TLS_RECORD_HEADER *) RequestBuffer)->ContentType == TlsContentTypeAlert);\r
570\r
571 Status = TlsHandleAlert (\r
572 Instance->TlsConn,\r
573 RequestBuffer,\r
574 RequestSize,\r
575 Buffer,\r
576 BufferSize\r
577 );\r
578 if (EFI_ERROR (Status)) {\r
579 if (Status != EFI_BUFFER_TOO_SMALL) {\r
580 Instance->TlsSessionState = EfiTlsSessionError;\r
581 }\r
582\r
583 goto ON_EXIT;\r
584 }\r
585 }\r
586 }\r
587\r
588ON_EXIT:\r
589 gBS->RestoreTPL (OldTpl);\r
590 return Status;\r
591}\r
592\r
593/**\r
594 Decrypt or encrypt TLS packet during session. This function is only valid after\r
595 session connected and for application_data content type.\r
596\r
597 The ProcessPacket () function process each inbound or outbound TLS APP packet.\r
598\r
599 @param[in] This Pointer to the EFI_TLS_PROTOCOL instance.\r
600 @param[in, out] FragmentTable Pointer to a list of fragment. The caller will take\r
601 responsible to handle the original FragmentTable while\r
602 it may be reallocated in TLS driver. If CryptMode is\r
603 EfiTlsEncrypt, on input these fragments contain the TLS\r
604 header and plain text TLS APP payload; on output these\r
605 fragments contain the TLS header and cipher text TLS\r
606 APP payload. If CryptMode is EfiTlsDecrypt, on input\r
607 these fragments contain the TLS header and cipher text\r
608 TLS APP payload; on output these fragments contain the\r
609 TLS header and plain text TLS APP payload.\r
610 @param[in] FragmentCount Number of fragment.\r
611 @param[in] CryptMode Crypt mode.\r
612\r
613 @retval EFI_SUCCESS The operation completed successfully.\r
614 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
615 This is NULL.\r
616 FragmentTable is NULL.\r
617 FragmentCount is NULL.\r
618 CryptoMode is invalid.\r
619 @retval EFI_NOT_READY Current TLS session state is NOT\r
620 EfiTlsSessionDataTransferring.\r
621 @retval EFI_ABORTED Something wrong decryption the message. TLS session\r
622 status will become EfiTlsSessionError. The caller need\r
623 call BuildResponsePacket() to generate Error Alert\r
624 message and send it out.\r
625 @retval EFI_OUT_OF_RESOURCES No enough resource to finish the operation.\r
626**/\r
627EFI_STATUS\r
628EFIAPI\r
629TlsProcessPacket (\r
630 IN EFI_TLS_PROTOCOL *This,\r
631 IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable,\r
632 IN UINT32 *FragmentCount,\r
633 IN EFI_TLS_CRYPT_MODE CryptMode\r
634 )\r
635{\r
636 EFI_STATUS Status;\r
637 TLS_INSTANCE *Instance;\r
638\r
639 EFI_TPL OldTpl;\r
640\r
641 Status = EFI_SUCCESS;\r
642\r
643 if (This == NULL || FragmentTable == NULL || FragmentCount == NULL) {\r
644 return EFI_INVALID_PARAMETER;\r
645 }\r
646\r
647 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
648\r
649 Instance = TLS_INSTANCE_FROM_PROTOCOL (This);\r
650\r
651 if (Instance->TlsSessionState != EfiTlsSessionDataTransferring) {\r
652 Status = EFI_NOT_READY;\r
653 goto ON_EXIT;\r
654 }\r
655\r
656 //\r
657 // Packet sent or received may have multiple TLS record messages (Application data type).\r
658 // So,on input these fragments contain the TLS header and TLS APP payload;\r
659 // on output these fragments also contain the TLS header and TLS APP payload.\r
660 //\r
661 switch (CryptMode) {\r
662 case EfiTlsEncrypt:\r
663 Status = TlsEncryptPacket (Instance, FragmentTable, FragmentCount);\r
664 break;\r
665 case EfiTlsDecrypt:\r
666 Status = TlsDecryptPacket (Instance, FragmentTable, FragmentCount);\r
667 break;\r
668 default:\r
669 return EFI_INVALID_PARAMETER;\r
670 }\r
671\r
672ON_EXIT:\r
673 gBS->RestoreTPL (OldTpl);\r
674 return Status;\r
675}\r
676\r