• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
TlsEncryptPacket(IN TLS_INSTANCE * TlsInstance,IN OUT EFI_TLS_FRAGMENT_DATA ** FragmentTable,IN UINT32 * FragmentCount)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
TlsDecryptPacket(IN TLS_INSTANCE * TlsInstance,IN OUT EFI_TLS_FRAGMENT_DATA ** FragmentTable,IN UINT32 * FragmentCount)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