Home | History | Annotate | Download | only in TlsDxe
      1 /** @file
      2   Implementation of EFI TLS Protocol Interfaces.
      3 
      4   Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
      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       //
    526       ASSERT (((TLS_RECORD_HEADER *) RequestBuffer)->ContentType == TLS_CONTENT_TYPE_ALERT);
    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 }
    633