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