TlsImpl.c 11 KB

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