Home | History | Annotate | Download | only in TlsDxe
      1 /** @file
      2   The Miscellaneous Routines for TlsDxe driver.
      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 /**
     19   Encrypt the message listed in fragment.
     20 
     21   @param[in]       TlsInstance    The pointer to the TLS instance.
     22   @param[in, out]  FragmentTable  Pointer to a list of fragment.
     23                                   On input these fragments contain the TLS header and
     24                                   plain text TLS payload;
     25                                   On output these fragments contain the TLS header and
     26                                   cipher text TLS payload.
     27   @param[in]       FragmentCount  Number of fragment.
     28 
     29   @retval EFI_SUCCESS             The operation completed successfully.
     30   @retval EFI_OUT_OF_RESOURCES    Can't allocate memory resources.
     31   @retval EFI_ABORTED             TLS session state is incorrect.
     32   @retval Others                  Other errors as indicated.
     33 **/
     34 EFI_STATUS
     35 TlsEncryptPacket (
     36   IN     TLS_INSTANCE                  *TlsInstance,
     37   IN OUT EFI_TLS_FRAGMENT_DATA         **FragmentTable,
     38   IN     UINT32                        *FragmentCount
     39   )
     40 {
     41   EFI_STATUS          Status;
     42   UINTN               Index;
     43   UINT32              BytesCopied;
     44   UINT32              BufferInSize;
     45   UINT8               *BufferIn;
     46   UINT8               *BufferInPtr;
     47   TLS_RECORD_HEADER   *RecordHeaderIn;
     48   UINT16              ThisPlainMessageSize;
     49   TLS_RECORD_HEADER   *TempRecordHeader;
     50   UINT16              ThisMessageSize;
     51   UINT32              BufferOutSize;
     52   UINT8               *BufferOut;
     53   INTN                Ret;
     54 
     55   Status           = EFI_SUCCESS;
     56   BytesCopied      = 0;
     57   BufferInSize     = 0;
     58   BufferIn         = NULL;
     59   BufferInPtr      = NULL;
     60   RecordHeaderIn   = NULL;
     61   TempRecordHeader = NULL;
     62   BufferOutSize    = 0;
     63   BufferOut        = NULL;
     64   Ret              = 0;
     65 
     66   //
     67   // Calculate the size according to the fragment table.
     68   //
     69   for (Index = 0; Index < *FragmentCount; Index++) {
     70     BufferInSize += (*FragmentTable)[Index].FragmentLength;
     71   }
     72 
     73   //
     74   // Allocate buffer for processing data.
     75   //
     76   BufferIn = AllocateZeroPool (BufferInSize);
     77   if (BufferIn == NULL) {
     78     Status = EFI_OUT_OF_RESOURCES;
     79     goto ERROR;
     80   }
     81 
     82   //
     83   // Copy all TLS plain record header and payload into BufferIn.
     84   //
     85   for (Index = 0; Index < *FragmentCount; Index++) {
     86     CopyMem (
     87       (BufferIn + BytesCopied),
     88       (*FragmentTable)[Index].FragmentBuffer,
     89       (*FragmentTable)[Index].FragmentLength
     90       );
     91     BytesCopied += (*FragmentTable)[Index].FragmentLength;
     92   }
     93 
     94   BufferOut = AllocateZeroPool (MAX_BUFFER_SIZE);
     95   if (BufferOut == NULL) {
     96     Status = EFI_OUT_OF_RESOURCES;
     97     goto ERROR;
     98   }
     99 
    100   //
    101   // Parsing buffer.
    102   //
    103   BufferInPtr = BufferIn;
    104   TempRecordHeader = (TLS_RECORD_HEADER *) BufferOut;
    105   while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) {
    106     RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr;
    107 
    108     if (RecordHeaderIn->ContentType != TLS_CONTENT_TYPE_APPLICATION_DATA) {
    109       Status = EFI_INVALID_PARAMETER;
    110       goto ERROR;
    111     }
    112 
    113     ThisPlainMessageSize = RecordHeaderIn->Length;
    114 
    115     TlsWrite (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn + 1), ThisPlainMessageSize);
    116 
    117     Ret = TlsCtrlTrafficOut (TlsInstance->TlsConn, (UINT8 *)(TempRecordHeader), MAX_BUFFER_SIZE - BufferOutSize);
    118 
    119     if (Ret > 0) {
    120       ThisMessageSize = (UINT16) Ret;
    121     } else {
    122       //
    123       // No data was successfully encrypted, continue to encrypt other messages.
    124       //
    125       DEBUG ((EFI_D_WARN, "TlsEncryptPacket: No data read from TLS object.\n"));
    126 
    127       ThisMessageSize = 0;
    128     }
    129 
    130     BufferOutSize += ThisMessageSize;
    131 
    132     BufferInPtr += RECORD_HEADER_LEN + ThisPlainMessageSize;
    133     TempRecordHeader += ThisMessageSize;
    134   }
    135 
    136   FreePool (BufferIn);
    137   BufferIn = NULL;
    138 
    139   //
    140   // The caller will be responsible to handle the original fragment table.
    141   //
    142   *FragmentTable = AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA));
    143   if (*FragmentTable == NULL) {
    144     Status = EFI_OUT_OF_RESOURCES;
    145     goto ERROR;
    146   }
    147 
    148   (*FragmentTable)[0].FragmentBuffer  = BufferOut;
    149   (*FragmentTable)[0].FragmentLength  = BufferOutSize;
    150   *FragmentCount                      = 1;
    151 
    152   return Status;
    153 
    154 ERROR:
    155 
    156   if (BufferIn != NULL) {
    157     FreePool (BufferIn);
    158     BufferIn = NULL;
    159   }
    160 
    161   if (BufferOut != NULL) {
    162     FreePool (BufferOut);
    163     BufferOut = NULL;
    164   }
    165 
    166   return Status;
    167 }
    168 
    169 /**
    170   Decrypt the message listed in fragment.
    171 
    172   @param[in]       TlsInstance    The pointer to the TLS instance.
    173   @param[in, out]  FragmentTable  Pointer to a list of fragment.
    174                                   On input these fragments contain the TLS header and
    175                                   cipher text TLS payload;
    176                                   On output these fragments contain the TLS header and
    177                                   plain text TLS payload.
    178   @param[in]       FragmentCount  Number of fragment.
    179 
    180   @retval EFI_SUCCESS             The operation completed successfully.
    181   @retval EFI_OUT_OF_RESOURCES    Can't allocate memory resources.
    182   @retval EFI_ABORTED             TLS session state is incorrect.
    183   @retval Others                  Other errors as indicated.
    184 **/
    185 EFI_STATUS
    186 TlsDecryptPacket (
    187   IN     TLS_INSTANCE                  *TlsInstance,
    188   IN OUT EFI_TLS_FRAGMENT_DATA         **FragmentTable,
    189   IN     UINT32                        *FragmentCount
    190   )
    191 {
    192   EFI_STATUS          Status;
    193   UINTN               Index;
    194   UINT32              BytesCopied;
    195   UINT8               *BufferIn;
    196   UINT32              BufferInSize;
    197   UINT8               *BufferInPtr;
    198   TLS_RECORD_HEADER   *RecordHeaderIn;
    199   UINT16              ThisCipherMessageSize;
    200   TLS_RECORD_HEADER   *TempRecordHeader;
    201   UINT16              ThisPlainMessageSize;
    202   UINT8               *BufferOut;
    203   UINT32              BufferOutSize;
    204   INTN                Ret;
    205 
    206   Status           = EFI_SUCCESS;
    207   BytesCopied      = 0;
    208   BufferIn         = NULL;
    209   BufferInSize     = 0;
    210   BufferInPtr      = NULL;
    211   RecordHeaderIn   = NULL;
    212   TempRecordHeader = NULL;
    213   BufferOut        = NULL;
    214   BufferOutSize    = 0;
    215   Ret              = 0;
    216 
    217   //
    218   // Calculate the size according to the fragment table.
    219   //
    220   for (Index = 0; Index < *FragmentCount; Index++) {
    221     BufferInSize += (*FragmentTable)[Index].FragmentLength;
    222   }
    223 
    224   //
    225   // Allocate buffer for processing data
    226   //
    227   BufferIn = AllocateZeroPool (BufferInSize);
    228   if (BufferIn == NULL) {
    229     Status = EFI_OUT_OF_RESOURCES;
    230     goto ERROR;
    231   }
    232 
    233   //
    234   // Copy all TLS plain record header and payload to BufferIn
    235   //
    236   for (Index = 0; Index < *FragmentCount; Index++) {
    237     CopyMem (
    238       (BufferIn + BytesCopied),
    239       (*FragmentTable)[Index].FragmentBuffer,
    240       (*FragmentTable)[Index].FragmentLength
    241       );
    242     BytesCopied += (*FragmentTable)[Index].FragmentLength;
    243   }
    244 
    245   BufferOut = AllocateZeroPool (MAX_BUFFER_SIZE);
    246   if (BufferOut == NULL) {
    247     Status = EFI_OUT_OF_RESOURCES;
    248     goto ERROR;
    249   }
    250 
    251   //
    252   // Parsing buffer. Received packet may have multiple TLS record messages.
    253   //
    254   BufferInPtr = BufferIn;
    255   TempRecordHeader = (TLS_RECORD_HEADER *) BufferOut;
    256   while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) {
    257     RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr;
    258 
    259     if (RecordHeaderIn->ContentType != TLS_CONTENT_TYPE_APPLICATION_DATA) {
    260       Status = EFI_INVALID_PARAMETER;
    261       goto ERROR;
    262     }
    263 
    264     ThisCipherMessageSize = NTOHS (RecordHeaderIn->Length);
    265 
    266     Ret = TlsCtrlTrafficIn (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn), RECORD_HEADER_LEN + ThisCipherMessageSize);
    267     if (Ret != RECORD_HEADER_LEN + ThisCipherMessageSize) {
    268       TlsInstance->TlsSessionState = EfiTlsSessionError;
    269       Status = EFI_ABORTED;
    270       goto ERROR;
    271     }
    272 
    273     Ret = 0;
    274     Ret = TlsRead (TlsInstance->TlsConn, (UINT8 *) (TempRecordHeader + 1), MAX_BUFFER_SIZE - BufferOutSize);
    275 
    276     if (Ret > 0) {
    277       ThisPlainMessageSize = (UINT16) Ret;
    278     } else {
    279       //
    280       // No data was successfully decrypted, continue to decrypt other messages.
    281       //
    282       DEBUG ((EFI_D_WARN, "TlsDecryptPacket: No data read from TLS object.\n"));
    283 
    284       ThisPlainMessageSize = 0;
    285     }
    286 
    287     CopyMem (TempRecordHeader, RecordHeaderIn, RECORD_HEADER_LEN);
    288     TempRecordHeader->Length = ThisPlainMessageSize;
    289     BufferOutSize += RECORD_HEADER_LEN + ThisPlainMessageSize;
    290 
    291     BufferInPtr += RECORD_HEADER_LEN + ThisCipherMessageSize;
    292     TempRecordHeader += RECORD_HEADER_LEN + ThisPlainMessageSize;
    293   }
    294 
    295   FreePool (BufferIn);
    296   BufferIn = NULL;
    297 
    298   //
    299   // The caller will be responsible to handle the original fragment table
    300   //
    301   *FragmentTable = AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA));
    302   if (*FragmentTable == NULL) {
    303     Status = EFI_OUT_OF_RESOURCES;
    304     goto ERROR;
    305   }
    306 
    307   (*FragmentTable)[0].FragmentBuffer  = BufferOut;
    308   (*FragmentTable)[0].FragmentLength  = BufferOutSize;
    309   *FragmentCount                      = 1;
    310 
    311   return Status;
    312 
    313 ERROR:
    314 
    315   if (BufferIn != NULL) {
    316     FreePool (BufferIn);
    317     BufferIn = NULL;
    318   }
    319 
    320   if (BufferOut != NULL) {
    321     FreePool (BufferOut);
    322     BufferOut = NULL;
    323   }
    324 
    325   return Status;
    326 }
    327