]> git.proxmox.com Git - mirror_edk2.git/blame - CryptoPkg/Library/TlsLib/TlsConfig.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / CryptoPkg / Library / TlsLib / TlsConfig.c
CommitLineData
264702a0
HW
1/** @file\r
2 SSL/TLS Configuration Library Wrapper Implementation over OpenSSL.\r
3\r
2ca74e1a 4Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
264702a0 5(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
2009f6b4 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
264702a0
HW
7\r
8**/\r
9\r
10#include "InternalTlsLib.h"\r
11\r
12typedef struct {\r
13 //\r
14 // IANA/IETF defined Cipher Suite ID\r
15 //\r
7c342378 16 UINT16 IanaCipher;\r
264702a0
HW
17 //\r
18 // OpenSSL-used Cipher Suite String\r
19 //\r
7c342378 20 CONST CHAR8 *OpensslCipher;\r
96015d5f
LE
21 //\r
22 // Length of OpensslCipher\r
23 //\r
7c342378 24 UINTN OpensslCipherLength;\r
ecfd37ba 25} TLS_CIPHER_MAPPING;\r
264702a0 26\r
96015d5f
LE
27//\r
28// Create a TLS_CIPHER_MAPPING initializer from IanaCipher and OpensslCipher so\r
29// that OpensslCipherLength is filled in automatically. IanaCipher must be an\r
30// integer constant expression, and OpensslCipher must be a string literal.\r
31//\r
32#define MAP(IanaCipher, OpensslCipher) \\r
33 { (IanaCipher), (OpensslCipher), sizeof (OpensslCipher) - 1 }\r
34\r
264702a0
HW
35//\r
36// The mapping table between IANA/IETF Cipher Suite definitions and\r
37// OpenSSL-used Cipher Suite name.\r
38//\r
5eadb54e
LE
39// Keep the table uniquely sorted by the IanaCipher field, in increasing order.\r
40//\r
7c342378
MK
41STATIC CONST TLS_CIPHER_MAPPING TlsCipherMappingTable[] = {\r
42 MAP (0x0001, "NULL-MD5"), /// TLS_RSA_WITH_NULL_MD5\r
43 MAP (0x0002, "NULL-SHA"), /// TLS_RSA_WITH_NULL_SHA\r
44 MAP (0x0004, "RC4-MD5"), /// TLS_RSA_WITH_RC4_128_MD5\r
45 MAP (0x0005, "RC4-SHA"), /// TLS_RSA_WITH_RC4_128_SHA\r
46 MAP (0x000A, "DES-CBC3-SHA"), /// TLS_RSA_WITH_3DES_EDE_CBC_SHA, mandatory TLS 1.1\r
47 MAP (0x0016, "DHE-RSA-DES-CBC3-SHA"), /// TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA\r
48 MAP (0x002F, "AES128-SHA"), /// TLS_RSA_WITH_AES_128_CBC_SHA, mandatory TLS 1.2\r
49 MAP (0x0030, "DH-DSS-AES128-SHA"), /// TLS_DH_DSS_WITH_AES_128_CBC_SHA\r
50 MAP (0x0031, "DH-RSA-AES128-SHA"), /// TLS_DH_RSA_WITH_AES_128_CBC_SHA\r
51 MAP (0x0033, "DHE-RSA-AES128-SHA"), /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA\r
52 MAP (0x0035, "AES256-SHA"), /// TLS_RSA_WITH_AES_256_CBC_SHA\r
53 MAP (0x0036, "DH-DSS-AES256-SHA"), /// TLS_DH_DSS_WITH_AES_256_CBC_SHA\r
54 MAP (0x0037, "DH-RSA-AES256-SHA"), /// TLS_DH_RSA_WITH_AES_256_CBC_SHA\r
55 MAP (0x0039, "DHE-RSA-AES256-SHA"), /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA\r
56 MAP (0x003B, "NULL-SHA256"), /// TLS_RSA_WITH_NULL_SHA256\r
57 MAP (0x003C, "AES128-SHA256"), /// TLS_RSA_WITH_AES_128_CBC_SHA256\r
58 MAP (0x003D, "AES256-SHA256"), /// TLS_RSA_WITH_AES_256_CBC_SHA256\r
59 MAP (0x003E, "DH-DSS-AES128-SHA256"), /// TLS_DH_DSS_WITH_AES_128_CBC_SHA256\r
60 MAP (0x003F, "DH-RSA-AES128-SHA256"), /// TLS_DH_RSA_WITH_AES_128_CBC_SHA256\r
61 MAP (0x0067, "DHE-RSA-AES128-SHA256"), /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA256\r
62 MAP (0x0068, "DH-DSS-AES256-SHA256"), /// TLS_DH_DSS_WITH_AES_256_CBC_SHA256\r
63 MAP (0x0069, "DH-RSA-AES256-SHA256"), /// TLS_DH_RSA_WITH_AES_256_CBC_SHA256\r
64 MAP (0x006B, "DHE-RSA-AES256-SHA256"), /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA256\r
bb78d969
YL
65 MAP (0x009F, "DHE-RSA-AES256-GCM-SHA384"), /// TLS_DHE_RSA_WITH_AES_256_GCM_SHA384\r
66 MAP (0xC02B, "ECDHE-ECDSA-AES128-GCM-SHA256"), /// TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\r
67 MAP (0xC02C, "ECDHE-ECDSA-AES256-GCM-SHA384"), /// TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\r
68 MAP (0xC030, "ECDHE-RSA-AES256-GCM-SHA384"), /// TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\r
69};\r
70\r
71typedef struct {\r
72 //\r
73 // TLS Algorithm\r
74 //\r
75 UINT8 Algo;\r
76 //\r
77 // TLS Algorithm name\r
78 //\r
79 CONST CHAR8 *Name;\r
80} TLS_ALGO_TO_NAME;\r
81\r
82STATIC CONST TLS_ALGO_TO_NAME TlsHashAlgoToName[] = {\r
83 { TlsHashAlgoNone, NULL },\r
84 { TlsHashAlgoMd5, "MD5" },\r
85 { TlsHashAlgoSha1, "SHA1" },\r
86 { TlsHashAlgoSha224, "SHA224" },\r
87 { TlsHashAlgoSha256, "SHA256" },\r
88 { TlsHashAlgoSha384, "SHA384" },\r
89 { TlsHashAlgoSha512, "SHA512" },\r
90};\r
91\r
92STATIC CONST TLS_ALGO_TO_NAME TlsSignatureAlgoToName[] = {\r
93 { TlsSignatureAlgoAnonymous, NULL },\r
94 { TlsSignatureAlgoRsa, "RSA" },\r
95 { TlsSignatureAlgoDsa, "DSA" },\r
96 { TlsSignatureAlgoEcdsa, "ECDSA" },\r
264702a0
HW
97};\r
98\r
99/**\r
ecfd37ba 100 Gets the OpenSSL cipher suite mapping for the supplied IANA TLS cipher suite.\r
264702a0
HW
101\r
102 @param[in] CipherId The supplied IANA TLS cipher suite ID.\r
103\r
ecfd37ba 104 @return The corresponding OpenSSL cipher suite mapping if found,\r
264702a0
HW
105 NULL otherwise.\r
106\r
107**/\r
108STATIC\r
ecfd37ba
LE
109CONST TLS_CIPHER_MAPPING *\r
110TlsGetCipherMapping (\r
7c342378 111 IN UINT16 CipherId\r
264702a0
HW
112 )\r
113{\r
7c342378
MK
114 INTN Left;\r
115 INTN Right;\r
116 INTN Middle;\r
264702a0
HW
117\r
118 //\r
5eadb54e 119 // Binary Search Cipher Mapping Table for IANA-OpenSSL Cipher Translation\r
264702a0 120 //\r
5eadb54e
LE
121 Left = 0;\r
122 Right = ARRAY_SIZE (TlsCipherMappingTable) - 1;\r
123\r
124 while (Right >= Left) {\r
125 Middle = (Left + Right) / 2;\r
126\r
127 if (CipherId == TlsCipherMappingTable[Middle].IanaCipher) {\r
128 //\r
129 // Translate IANA cipher suite ID to OpenSSL name.\r
130 //\r
131 return &TlsCipherMappingTable[Middle];\r
132 }\r
133\r
134 if (CipherId < TlsCipherMappingTable[Middle].IanaCipher) {\r
135 Right = Middle - 1;\r
136 } else {\r
7c342378 137 Left = Middle + 1;\r
264702a0
HW
138 }\r
139 }\r
140\r
141 //\r
142 // No Cipher Mapping found, return NULL.\r
143 //\r
144 return NULL;\r
145}\r
146\r
147/**\r
148 Set a new TLS/SSL method for a particular TLS object.\r
149\r
150 This function sets a new TLS/SSL method for a particular TLS object.\r
151\r
152 @param[in] Tls Pointer to a TLS object.\r
153 @param[in] MajorVer Major Version of TLS/SSL Protocol.\r
154 @param[in] MinorVer Minor Version of TLS/SSL Protocol.\r
155\r
156 @retval EFI_SUCCESS The TLS/SSL method was set successfully.\r
157 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
158 @retval EFI_UNSUPPORTED Unsupported TLS/SSL method.\r
159\r
160**/\r
161EFI_STATUS\r
162EFIAPI\r
163TlsSetVersion (\r
7c342378
MK
164 IN VOID *Tls,\r
165 IN UINT8 MajorVer,\r
166 IN UINT8 MinorVer\r
264702a0
HW
167 )\r
168{\r
169 TLS_CONNECTION *TlsConn;\r
170 UINT16 ProtoVersion;\r
171\r
172 TlsConn = (TLS_CONNECTION *)Tls;\r
7c342378 173 if ((TlsConn == NULL) || (TlsConn->Ssl == NULL)) {\r
264702a0
HW
174 return EFI_INVALID_PARAMETER;\r
175 }\r
176\r
177 ProtoVersion = (MajorVer << 8) | MinorVer;\r
178\r
179 //\r
180 // Bound TLS method to the particular specified version.\r
181 //\r
182 switch (ProtoVersion) {\r
7c342378
MK
183 case TLS1_VERSION:\r
184 //\r
185 // TLS 1.0\r
186 //\r
187 SSL_set_min_proto_version (TlsConn->Ssl, TLS1_VERSION);\r
188 SSL_set_max_proto_version (TlsConn->Ssl, TLS1_VERSION);\r
189 break;\r
190 case TLS1_1_VERSION:\r
191 //\r
192 // TLS 1.1\r
193 //\r
194 SSL_set_min_proto_version (TlsConn->Ssl, TLS1_1_VERSION);\r
195 SSL_set_max_proto_version (TlsConn->Ssl, TLS1_1_VERSION);\r
196 break;\r
197 case TLS1_2_VERSION:\r
198 //\r
199 // TLS 1.2\r
200 //\r
201 SSL_set_min_proto_version (TlsConn->Ssl, TLS1_2_VERSION);\r
202 SSL_set_max_proto_version (TlsConn->Ssl, TLS1_2_VERSION);\r
203 break;\r
204 default:\r
205 //\r
206 // Unsupported Protocol Version\r
207 //\r
208 return EFI_UNSUPPORTED;\r
264702a0
HW
209 }\r
210\r
7c342378 211 return EFI_SUCCESS;\r
264702a0
HW
212}\r
213\r
214/**\r
215 Set TLS object to work in client or server mode.\r
216\r
217 This function prepares a TLS object to work in client or server mode.\r
218\r
219 @param[in] Tls Pointer to a TLS object.\r
220 @param[in] IsServer Work in server mode.\r
221\r
222 @retval EFI_SUCCESS The TLS/SSL work mode was set successfully.\r
223 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
224 @retval EFI_UNSUPPORTED Unsupported TLS/SSL work mode.\r
225\r
226**/\r
227EFI_STATUS\r
228EFIAPI\r
229TlsSetConnectionEnd (\r
7c342378
MK
230 IN VOID *Tls,\r
231 IN BOOLEAN IsServer\r
264702a0
HW
232 )\r
233{\r
234 TLS_CONNECTION *TlsConn;\r
235\r
7c342378
MK
236 TlsConn = (TLS_CONNECTION *)Tls;\r
237 if ((TlsConn == NULL) || (TlsConn->Ssl == NULL)) {\r
264702a0
HW
238 return EFI_INVALID_PARAMETER;\r
239 }\r
240\r
241 if (!IsServer) {\r
242 //\r
243 // Set TLS to work in Client mode.\r
244 //\r
245 SSL_set_connect_state (TlsConn->Ssl);\r
246 } else {\r
247 //\r
248 // Set TLS to work in Server mode.\r
249 // It is unsupported for UEFI version currently.\r
250 //\r
7c342378 251 // SSL_set_accept_state (TlsConn->Ssl);\r
264702a0
HW
252 return EFI_UNSUPPORTED;\r
253 }\r
254\r
255 return EFI_SUCCESS;\r
256}\r
257\r
258/**\r
259 Set the ciphers list to be used by the TLS object.\r
260\r
261 This function sets the ciphers for use by a specified TLS object.\r
262\r
263 @param[in] Tls Pointer to a TLS object.\r
2167c7f7
LE
264 @param[in] CipherId Array of UINT16 cipher identifiers. Each UINT16\r
265 cipher identifier comes from the TLS Cipher Suite\r
266 Registry of the IANA, interpreting Byte1 and Byte2\r
267 in network (big endian) byte order.\r
264702a0
HW
268 @param[in] CipherNum The number of cipher in the list.\r
269\r
270 @retval EFI_SUCCESS The ciphers list was set successfully.\r
271 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
2167c7f7
LE
272 @retval EFI_UNSUPPORTED No supported TLS cipher was found in CipherId.\r
273 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
264702a0
HW
274\r
275**/\r
276EFI_STATUS\r
277EFIAPI\r
278TlsSetCipherList (\r
7c342378
MK
279 IN VOID *Tls,\r
280 IN UINT16 *CipherId,\r
281 IN UINTN CipherNum\r
264702a0
HW
282 )\r
283{\r
7c342378
MK
284 TLS_CONNECTION *TlsConn;\r
285 EFI_STATUS Status;\r
286 CONST TLS_CIPHER_MAPPING **MappedCipher;\r
287 UINTN MappedCipherBytes;\r
288 UINTN MappedCipherCount;\r
289 UINTN CipherStringSize;\r
290 UINTN Index;\r
291 CONST TLS_CIPHER_MAPPING *Mapping;\r
292 CHAR8 *CipherString;\r
293 CHAR8 *CipherStringPosition;\r
294\r
295 TlsConn = (TLS_CONNECTION *)Tls;\r
296 if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (CipherId == NULL)) {\r
264702a0
HW
297 return EFI_INVALID_PARAMETER;\r
298 }\r
299\r
2167c7f7
LE
300 //\r
301 // Allocate the MappedCipher array for recording the mappings that we find\r
302 // for the input IANA identifiers in CipherId.\r
303 //\r
7c342378
MK
304 Status = SafeUintnMult (\r
305 CipherNum,\r
306 sizeof (*MappedCipher),\r
307 &MappedCipherBytes\r
308 );\r
2167c7f7
LE
309 if (EFI_ERROR (Status)) {\r
310 return EFI_OUT_OF_RESOURCES;\r
311 }\r
7c342378 312\r
2167c7f7
LE
313 MappedCipher = AllocatePool (MappedCipherBytes);\r
314 if (MappedCipher == NULL) {\r
315 return EFI_OUT_OF_RESOURCES;\r
316 }\r
264702a0 317\r
2167c7f7
LE
318 //\r
319 // Map the cipher IDs, and count the number of bytes for the full\r
320 // CipherString.\r
321 //\r
322 MappedCipherCount = 0;\r
7c342378 323 CipherStringSize = 0;\r
264702a0
HW
324 for (Index = 0; Index < CipherNum; Index++) {\r
325 //\r
2167c7f7 326 // Look up the IANA-to-OpenSSL mapping.\r
264702a0 327 //\r
2167c7f7 328 Mapping = TlsGetCipherMapping (CipherId[Index]);\r
ecfd37ba 329 if (Mapping == NULL) {\r
7c342378
MK
330 DEBUG ((\r
331 DEBUG_VERBOSE,\r
332 "%a:%a: skipping CipherId=0x%04x\n",\r
333 gEfiCallerBaseName,\r
334 __FUNCTION__,\r
335 CipherId[Index]\r
336 ));\r
264702a0 337 //\r
2167c7f7
LE
338 // Skipping the cipher is valid because CipherId is an ordered\r
339 // preference list of ciphers, thus we can filter it as long as we\r
340 // don't change the relative order of elements on it.\r
264702a0 341 //\r
2167c7f7
LE
342 continue;\r
343 }\r
7c342378 344\r
2167c7f7
LE
345 //\r
346 // Accumulate Mapping->OpensslCipherLength into CipherStringSize. If this\r
347 // is not the first successful mapping, account for a colon (":") prefix\r
348 // too.\r
349 //\r
350 if (MappedCipherCount > 0) {\r
351 Status = SafeUintnAdd (CipherStringSize, 1, &CipherStringSize);\r
352 if (EFI_ERROR (Status)) {\r
353 Status = EFI_OUT_OF_RESOURCES;\r
354 goto FreeMappedCipher;\r
355 }\r
356 }\r
7c342378
MK
357\r
358 Status = SafeUintnAdd (\r
359 CipherStringSize,\r
360 Mapping->OpensslCipherLength,\r
361 &CipherStringSize\r
362 );\r
2167c7f7
LE
363 if (EFI_ERROR (Status)) {\r
364 Status = EFI_OUT_OF_RESOURCES;\r
365 goto FreeMappedCipher;\r
264702a0 366 }\r
7c342378 367\r
2167c7f7
LE
368 //\r
369 // Record the mapping.\r
370 //\r
371 MappedCipher[MappedCipherCount++] = Mapping;\r
372 }\r
373\r
374 //\r
375 // Verify that at least one IANA cipher ID could be mapped; account for the\r
376 // terminating NUL character in CipherStringSize; allocate CipherString.\r
377 //\r
378 if (MappedCipherCount == 0) {\r
7c342378
MK
379 DEBUG ((\r
380 DEBUG_ERROR,\r
381 "%a:%a: no CipherId could be mapped\n",\r
382 gEfiCallerBaseName,\r
383 __FUNCTION__\r
384 ));\r
2167c7f7
LE
385 Status = EFI_UNSUPPORTED;\r
386 goto FreeMappedCipher;\r
387 }\r
7c342378 388\r
2167c7f7
LE
389 Status = SafeUintnAdd (CipherStringSize, 1, &CipherStringSize);\r
390 if (EFI_ERROR (Status)) {\r
391 Status = EFI_OUT_OF_RESOURCES;\r
392 goto FreeMappedCipher;\r
393 }\r
7c342378 394\r
2167c7f7
LE
395 CipherString = AllocatePool (CipherStringSize);\r
396 if (CipherString == NULL) {\r
397 Status = EFI_OUT_OF_RESOURCES;\r
398 goto FreeMappedCipher;\r
399 }\r
264702a0 400\r
2167c7f7
LE
401 //\r
402 // Go over the collected mappings and populate CipherString.\r
403 //\r
404 CipherStringPosition = CipherString;\r
405 for (Index = 0; Index < MappedCipherCount; Index++) {\r
406 Mapping = MappedCipher[Index];\r
407 //\r
408 // Append the colon (":") prefix except for the first mapping, then append\r
409 // Mapping->OpensslCipher.\r
410 //\r
411 if (Index > 0) {\r
412 *(CipherStringPosition++) = ':';\r
413 }\r
7c342378
MK
414\r
415 CopyMem (\r
416 CipherStringPosition,\r
417 Mapping->OpensslCipher,\r
418 Mapping->OpensslCipherLength\r
419 );\r
2167c7f7 420 CipherStringPosition += Mapping->OpensslCipherLength;\r
264702a0
HW
421 }\r
422\r
2167c7f7
LE
423 //\r
424 // NUL-terminate CipherString.\r
425 //\r
426 *(CipherStringPosition++) = '\0';\r
427 ASSERT (CipherStringPosition == CipherString + CipherStringSize);\r
428\r
429 //\r
430 // Log CipherString for debugging. CipherString can be very long if the\r
431 // caller provided a large CipherId array, so log CipherString in segments of\r
432 // 79 non-newline characters. (MAX_DEBUG_MESSAGE_LENGTH is usually 0x100 in\r
433 // DebugLib instances.)\r
434 //\r
e3b855f2 435 DEBUG_CODE_BEGIN ();\r
7c342378
MK
436 UINTN FullLength;\r
437 UINTN SegmentLength;\r
438\r
439 FullLength = CipherStringSize - 1;\r
440 DEBUG ((\r
441 DEBUG_VERBOSE,\r
442 "%a:%a: CipherString={\n",\r
443 gEfiCallerBaseName,\r
444 __FUNCTION__\r
445 ));\r
446 for (CipherStringPosition = CipherString;\r
447 CipherStringPosition < CipherString + FullLength;\r
448 CipherStringPosition += SegmentLength)\r
449 {\r
450 SegmentLength = FullLength - (CipherStringPosition - CipherString);\r
451 if (SegmentLength > 79) {\r
452 SegmentLength = 79;\r
2167c7f7 453 }\r
7c342378
MK
454\r
455 DEBUG ((DEBUG_VERBOSE, "%.*a\n", SegmentLength, CipherStringPosition));\r
456 }\r
457\r
458 DEBUG ((DEBUG_VERBOSE, "}\n"));\r
459 //\r
460 // Restore the pre-debug value of CipherStringPosition by skipping over the\r
461 // trailing NUL.\r
462 //\r
463 CipherStringPosition++;\r
464 ASSERT (CipherStringPosition == CipherString + CipherStringSize);\r
e3b855f2 465 DEBUG_CODE_END ();\r
264702a0
HW
466\r
467 //\r
468 // Sets the ciphers for use by the Tls object.\r
469 //\r
470 if (SSL_set_cipher_list (TlsConn->Ssl, CipherString) <= 0) {\r
2167c7f7
LE
471 Status = EFI_UNSUPPORTED;\r
472 goto FreeCipherString;\r
264702a0
HW
473 }\r
474\r
2167c7f7
LE
475 Status = EFI_SUCCESS;\r
476\r
477FreeCipherString:\r
478 FreePool (CipherString);\r
479\r
480FreeMappedCipher:\r
dd00f92b 481 FreePool ((VOID *)MappedCipher);\r
2167c7f7
LE
482\r
483 return Status;\r
264702a0
HW
484}\r
485\r
486/**\r
487 Set the compression method for TLS/SSL operations.\r
488\r
489 This function handles TLS/SSL integrated compression methods.\r
490\r
491 @param[in] CompMethod The compression method ID.\r
492\r
493 @retval EFI_SUCCESS The compression method for the communication was\r
494 set successfully.\r
495 @retval EFI_UNSUPPORTED Unsupported compression method.\r
496\r
497**/\r
498EFI_STATUS\r
499EFIAPI\r
500TlsSetCompressionMethod (\r
7c342378 501 IN UINT8 CompMethod\r
264702a0
HW
502 )\r
503{\r
504 COMP_METHOD *Cm;\r
505 INTN Ret;\r
506\r
507 Cm = NULL;\r
508 Ret = 0;\r
509\r
510 if (CompMethod == 0) {\r
511 //\r
512 // TLS defines one standard compression method, CompressionMethod.null (0),\r
513 // which specifies that data exchanged via the record protocol will not be compressed.\r
514 // So, return EFI_SUCCESS directly (RFC 3749).\r
515 //\r
516 return EFI_SUCCESS;\r
517 } else if (CompMethod == 1) {\r
7c342378 518 Cm = COMP_zlib ();\r
264702a0
HW
519 } else {\r
520 return EFI_UNSUPPORTED;\r
521 }\r
522\r
523 //\r
524 // Adds the compression method to the list of available\r
525 // compression methods.\r
526 //\r
527 Ret = SSL_COMP_add_compression_method (CompMethod, Cm);\r
528 if (Ret != 0) {\r
529 return EFI_UNSUPPORTED;\r
530 }\r
531\r
532 return EFI_SUCCESS;\r
533}\r
534\r
535/**\r
536 Set peer certificate verification mode for the TLS connection.\r
537\r
538 This function sets the verification mode flags for the TLS connection.\r
539\r
540 @param[in] Tls Pointer to the TLS object.\r
541 @param[in] VerifyMode A set of logically or'ed verification mode flags.\r
542\r
543**/\r
544VOID\r
545EFIAPI\r
546TlsSetVerify (\r
7c342378
MK
547 IN VOID *Tls,\r
548 IN UINT32 VerifyMode\r
264702a0
HW
549 )\r
550{\r
551 TLS_CONNECTION *TlsConn;\r
552\r
7c342378
MK
553 TlsConn = (TLS_CONNECTION *)Tls;\r
554 if ((TlsConn == NULL) || (TlsConn->Ssl == NULL)) {\r
264702a0
HW
555 return;\r
556 }\r
557\r
558 //\r
559 // Set peer certificate verification parameters with NULL callback.\r
560 //\r
561 SSL_set_verify (TlsConn->Ssl, VerifyMode, NULL);\r
562}\r
563\r
2ca74e1a
WJ
564/**\r
565 Set the specified host name to be verified.\r
566\r
567 @param[in] Tls Pointer to the TLS object.\r
568 @param[in] Flags The setting flags during the validation.\r
569 @param[in] HostName The specified host name to be verified.\r
570\r
571 @retval EFI_SUCCESS The HostName setting was set successfully.\r
572 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
573 @retval EFI_ABORTED Invalid HostName setting.\r
574\r
575**/\r
576EFI_STATUS\r
577EFIAPI\r
578TlsSetVerifyHost (\r
7c342378
MK
579 IN VOID *Tls,\r
580 IN UINT32 Flags,\r
581 IN CHAR8 *HostName\r
2ca74e1a
WJ
582 )\r
583{\r
7c342378
MK
584 TLS_CONNECTION *TlsConn;\r
585 X509_VERIFY_PARAM *VerifyParam;\r
586 UINTN BinaryAddressSize;\r
587 UINT8 BinaryAddress[MAX (NS_INADDRSZ, NS_IN6ADDRSZ)];\r
588 INTN ParamStatus;\r
589\r
590 TlsConn = (TLS_CONNECTION *)Tls;\r
591 if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (HostName == NULL)) {\r
592 return EFI_INVALID_PARAMETER;\r
2ca74e1a
WJ
593 }\r
594\r
7c342378 595 SSL_set_hostflags (TlsConn->Ssl, Flags);\r
2ca74e1a 596\r
1e72b1fb
LE
597 VerifyParam = SSL_get0_param (TlsConn->Ssl);\r
598 ASSERT (VerifyParam != NULL);\r
599\r
600 BinaryAddressSize = 0;\r
601 if (inet_pton (AF_INET6, HostName, BinaryAddress) == 1) {\r
602 BinaryAddressSize = NS_IN6ADDRSZ;\r
603 } else if (inet_pton (AF_INET, HostName, BinaryAddress) == 1) {\r
604 BinaryAddressSize = NS_INADDRSZ;\r
2ca74e1a
WJ
605 }\r
606\r
1e72b1fb 607 if (BinaryAddressSize > 0) {\r
7c342378
MK
608 DEBUG ((\r
609 DEBUG_VERBOSE,\r
610 "%a:%a: parsed \"%a\" as an IPv%c address "\r
611 "literal\n",\r
612 gEfiCallerBaseName,\r
613 __FUNCTION__,\r
614 HostName,\r
615 (UINTN)((BinaryAddressSize == NS_IN6ADDRSZ) ? '6' : '4')\r
616 ));\r
617 ParamStatus = X509_VERIFY_PARAM_set1_ip (\r
618 VerifyParam,\r
619 BinaryAddress,\r
620 BinaryAddressSize\r
621 );\r
1e72b1fb
LE
622 } else {\r
623 ParamStatus = X509_VERIFY_PARAM_set1_host (VerifyParam, HostName, 0);\r
624 }\r
625\r
626 return (ParamStatus == 1) ? EFI_SUCCESS : EFI_ABORTED;\r
2ca74e1a
WJ
627}\r
628\r
264702a0
HW
629/**\r
630 Sets a TLS/SSL session ID to be used during TLS/SSL connect.\r
631\r
632 This function sets a session ID to be used when the TLS/SSL connection is\r
633 to be established.\r
634\r
635 @param[in] Tls Pointer to the TLS object.\r
636 @param[in] SessionId Session ID data used for session resumption.\r
637 @param[in] SessionIdLen Length of Session ID in bytes.\r
638\r
639 @retval EFI_SUCCESS Session ID was set successfully.\r
640 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
641 @retval EFI_UNSUPPORTED No available session for ID setting.\r
642\r
643**/\r
644EFI_STATUS\r
645EFIAPI\r
646TlsSetSessionId (\r
7c342378
MK
647 IN VOID *Tls,\r
648 IN UINT8 *SessionId,\r
649 IN UINT16 SessionIdLen\r
264702a0
HW
650 )\r
651{\r
652 TLS_CONNECTION *TlsConn;\r
653 SSL_SESSION *Session;\r
654\r
7c342378 655 TlsConn = (TLS_CONNECTION *)Tls;\r
264702a0
HW
656 Session = NULL;\r
657\r
7c342378 658 if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (SessionId == NULL)) {\r
264702a0
HW
659 return EFI_INVALID_PARAMETER;\r
660 }\r
661\r
662 Session = SSL_get_session (TlsConn->Ssl);\r
663 if (Session == NULL) {\r
664 return EFI_UNSUPPORTED;\r
665 }\r
666\r
667 SSL_SESSION_set1_id (Session, (const unsigned char *)SessionId, SessionIdLen);\r
668\r
669 return EFI_SUCCESS;\r
670}\r
671\r
672/**\r
673 Adds the CA to the cert store when requesting Server or Client authentication.\r
674\r
675 This function adds the CA certificate to the list of CAs when requesting\r
676 Server or Client authentication for the chosen TLS connection.\r
677\r
678 @param[in] Tls Pointer to the TLS object.\r
679 @param[in] Data Pointer to the data buffer of a DER-encoded binary\r
680 X.509 certificate or PEM-encoded X.509 certificate.\r
681 @param[in] DataSize The size of data buffer in bytes.\r
682\r
683 @retval EFI_SUCCESS The operation succeeded.\r
684 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
685 @retval EFI_OUT_OF_RESOURCES Required resources could not be allocated.\r
686 @retval EFI_ABORTED Invalid X.509 certificate.\r
687\r
688**/\r
689EFI_STATUS\r
690EFIAPI\r
691TlsSetCaCertificate (\r
7c342378
MK
692 IN VOID *Tls,\r
693 IN VOID *Data,\r
694 IN UINTN DataSize\r
264702a0
HW
695 )\r
696{\r
697 BIO *BioCert;\r
698 X509 *Cert;\r
699 X509_STORE *X509Store;\r
700 EFI_STATUS Status;\r
701 TLS_CONNECTION *TlsConn;\r
702 SSL_CTX *SslCtx;\r
703 INTN Ret;\r
704 UINTN ErrorCode;\r
705\r
706 BioCert = NULL;\r
707 Cert = NULL;\r
708 X509Store = NULL;\r
709 Status = EFI_SUCCESS;\r
7c342378 710 TlsConn = (TLS_CONNECTION *)Tls;\r
264702a0
HW
711 Ret = 0;\r
712\r
7c342378 713 if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (Data == NULL) || (DataSize == 0)) {\r
264702a0
HW
714 return EFI_INVALID_PARAMETER;\r
715 }\r
716\r
717 //\r
718 // DER-encoded binary X.509 certificate or PEM-encoded X.509 certificate.\r
719 // Determine whether certificate is from DER encoding, if so, translate it to X509 structure.\r
720 //\r
7c342378 721 Cert = d2i_X509 (NULL, (const unsigned char **)&Data, (long)DataSize);\r
264702a0
HW
722 if (Cert == NULL) {\r
723 //\r
724 // Certificate is from PEM encoding.\r
725 //\r
726 BioCert = BIO_new (BIO_s_mem ());\r
727 if (BioCert == NULL) {\r
728 Status = EFI_OUT_OF_RESOURCES;\r
729 goto ON_EXIT;\r
730 }\r
731\r
7c342378 732 if (BIO_write (BioCert, Data, (UINT32)DataSize) <= 0) {\r
264702a0
HW
733 Status = EFI_ABORTED;\r
734 goto ON_EXIT;\r
735 }\r
736\r
737 Cert = PEM_read_bio_X509 (BioCert, NULL, NULL, NULL);\r
738 if (Cert == NULL) {\r
739 Status = EFI_ABORTED;\r
740 goto ON_EXIT;\r
741 }\r
742 }\r
743\r
744 SslCtx = SSL_get_SSL_CTX (TlsConn->Ssl);\r
745 X509Store = SSL_CTX_get_cert_store (SslCtx);\r
746 if (X509Store == NULL) {\r
7c342378
MK
747 Status = EFI_ABORTED;\r
748 goto ON_EXIT;\r
264702a0
HW
749 }\r
750\r
751 //\r
752 // Add certificate to X509 store\r
753 //\r
754 Ret = X509_STORE_add_cert (X509Store, Cert);\r
755 if (Ret != 1) {\r
756 ErrorCode = ERR_peek_last_error ();\r
757 //\r
758 // Ignore "already in table" errors\r
759 //\r
7c342378
MK
760 if (!((ERR_GET_FUNC (ErrorCode) == X509_F_X509_STORE_ADD_CERT) &&\r
761 (ERR_GET_REASON (ErrorCode) == X509_R_CERT_ALREADY_IN_HASH_TABLE)))\r
762 {\r
264702a0
HW
763 Status = EFI_ABORTED;\r
764 goto ON_EXIT;\r
765 }\r
766 }\r
767\r
768ON_EXIT:\r
769 if (BioCert != NULL) {\r
770 BIO_free (BioCert);\r
771 }\r
772\r
773 if (Cert != NULL) {\r
774 X509_free (Cert);\r
775 }\r
776\r
777 return Status;\r
778}\r
779\r
780/**\r
781 Loads the local public certificate into the specified TLS object.\r
782\r
783 This function loads the X.509 certificate into the specified TLS object\r
784 for TLS negotiation.\r
785\r
786 @param[in] Tls Pointer to the TLS object.\r
787 @param[in] Data Pointer to the data buffer of a DER-encoded binary\r
788 X.509 certificate or PEM-encoded X.509 certificate.\r
789 @param[in] DataSize The size of data buffer in bytes.\r
790\r
791 @retval EFI_SUCCESS The operation succeeded.\r
792 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
793 @retval EFI_OUT_OF_RESOURCES Required resources could not be allocated.\r
794 @retval EFI_ABORTED Invalid X.509 certificate.\r
795\r
796**/\r
797EFI_STATUS\r
798EFIAPI\r
799TlsSetHostPublicCert (\r
7c342378
MK
800 IN VOID *Tls,\r
801 IN VOID *Data,\r
802 IN UINTN DataSize\r
264702a0
HW
803 )\r
804{\r
805 BIO *BioCert;\r
806 X509 *Cert;\r
807 EFI_STATUS Status;\r
808 TLS_CONNECTION *TlsConn;\r
809\r
810 BioCert = NULL;\r
811 Cert = NULL;\r
812 Status = EFI_SUCCESS;\r
7c342378 813 TlsConn = (TLS_CONNECTION *)Tls;\r
264702a0 814\r
7c342378 815 if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (Data == NULL) || (DataSize == 0)) {\r
264702a0
HW
816 return EFI_INVALID_PARAMETER;\r
817 }\r
818\r
819 //\r
820 // DER-encoded binary X.509 certificate or PEM-encoded X.509 certificate.\r
821 // Determine whether certificate is from DER encoding, if so, translate it to X509 structure.\r
822 //\r
7c342378 823 Cert = d2i_X509 (NULL, (const unsigned char **)&Data, (long)DataSize);\r
264702a0
HW
824 if (Cert == NULL) {\r
825 //\r
826 // Certificate is from PEM encoding.\r
827 //\r
828 BioCert = BIO_new (BIO_s_mem ());\r
829 if (BioCert == NULL) {\r
830 Status = EFI_OUT_OF_RESOURCES;\r
831 goto ON_EXIT;\r
832 }\r
833\r
7c342378 834 if (BIO_write (BioCert, Data, (UINT32)DataSize) <= 0) {\r
264702a0
HW
835 Status = EFI_ABORTED;\r
836 goto ON_EXIT;\r
837 }\r
838\r
839 Cert = PEM_read_bio_X509 (BioCert, NULL, NULL, NULL);\r
840 if (Cert == NULL) {\r
841 Status = EFI_ABORTED;\r
842 goto ON_EXIT;\r
843 }\r
844 }\r
845\r
846 if (SSL_use_certificate (TlsConn->Ssl, Cert) != 1) {\r
847 Status = EFI_ABORTED;\r
848 goto ON_EXIT;\r
849 }\r
850\r
851ON_EXIT:\r
852 if (BioCert != NULL) {\r
853 BIO_free (BioCert);\r
854 }\r
855\r
856 if (Cert != NULL) {\r
857 X509_free (Cert);\r
858 }\r
859\r
860 return Status;\r
861}\r
862\r
863/**\r
864 Adds the local private key to the specified TLS object.\r
865\r
bb78d969 866 This function adds the local private key (DER-encoded or PEM-encoded or PKCS#8 private\r
264702a0
HW
867 key) into the specified TLS object for TLS negotiation.\r
868\r
869 @param[in] Tls Pointer to the TLS object.\r
bb78d969
YL
870 @param[in] Data Pointer to the data buffer of a DER-encoded or PEM-encoded\r
871 or PKCS#8 private key.\r
872 @param[in] DataSize The size of data buffer in bytes.\r
873 @param[in] Password Pointer to NULL-terminated private key password, set it to NULL\r
874 if private key not encrypted.\r
875\r
876 @retval EFI_SUCCESS The operation succeeded.\r
877 @retval EFI_UNSUPPORTED This function is not supported.\r
878 @retval EFI_ABORTED Invalid private key data.\r
879\r
880**/\r
881EFI_STATUS\r
882EFIAPI\r
883TlsSetHostPrivateKeyEx (\r
884 IN VOID *Tls,\r
885 IN VOID *Data,\r
886 IN UINTN DataSize,\r
887 IN VOID *Password OPTIONAL\r
888 )\r
889{\r
890 TLS_CONNECTION *TlsConn;\r
891 BIO *Bio;\r
892 EVP_PKEY *Pkey;\r
893 BOOLEAN Verify;\r
894\r
895 TlsConn = (TLS_CONNECTION *)Tls;\r
896\r
897 if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (Data == NULL) || (DataSize == 0)) {\r
898 return EFI_INVALID_PARAMETER;\r
899 }\r
900\r
901 // Try to parse the private key in DER format or un-encrypted PKC#8\r
902 if (SSL_use_PrivateKey_ASN1 (\r
903 EVP_PKEY_RSA,\r
904 TlsConn->Ssl,\r
905 Data,\r
906 (long)DataSize\r
907 ) == 1)\r
908 {\r
909 goto verify;\r
910 }\r
911\r
912 if (SSL_use_PrivateKey_ASN1 (\r
913 EVP_PKEY_DSA,\r
914 TlsConn->Ssl,\r
915 Data,\r
916 (long)DataSize\r
917 ) == 1)\r
918 {\r
919 goto verify;\r
920 }\r
921\r
922 if (SSL_use_PrivateKey_ASN1 (\r
923 EVP_PKEY_EC,\r
924 TlsConn->Ssl,\r
925 Data,\r
926 (long)DataSize\r
927 ) == 1)\r
928 {\r
929 goto verify;\r
930 }\r
931\r
932 // Try to parse the private key in PEM format or encrypted PKC#8\r
933 Bio = BIO_new_mem_buf (Data, (int)DataSize);\r
934 if (Bio != NULL) {\r
935 Verify = FALSE;\r
936 Pkey = PEM_read_bio_PrivateKey (Bio, NULL, NULL, Password);\r
937 if ((Pkey != NULL) && (SSL_use_PrivateKey (TlsConn->Ssl, Pkey) == 1)) {\r
938 Verify = TRUE;\r
939 }\r
940\r
941 EVP_PKEY_free (Pkey);\r
942 BIO_free (Bio);\r
943\r
944 if (Verify) {\r
945 goto verify;\r
946 }\r
947 }\r
948\r
949 return EFI_ABORTED;\r
950\r
951verify:\r
952 if (SSL_check_private_key (TlsConn->Ssl) == 1) {\r
953 return EFI_SUCCESS;\r
954 }\r
955\r
956 return EFI_ABORTED;\r
957}\r
958\r
959/**\r
960 Adds the local private key to the specified TLS object.\r
961\r
962 This function adds the local private key (DER-encoded or PEM-encoded or PKCS#8 private\r
963 key) into the specified TLS object for TLS negotiation.\r
964\r
965 @param[in] Tls Pointer to the TLS object.\r
966 @param[in] Data Pointer to the data buffer of a DER-encoded or PEM-encoded\r
264702a0
HW
967 or PKCS#8 private key.\r
968 @param[in] DataSize The size of data buffer in bytes.\r
969\r
970 @retval EFI_SUCCESS The operation succeeded.\r
971 @retval EFI_UNSUPPORTED This function is not supported.\r
972 @retval EFI_ABORTED Invalid private key data.\r
973\r
974**/\r
975EFI_STATUS\r
976EFIAPI\r
977TlsSetHostPrivateKey (\r
7c342378
MK
978 IN VOID *Tls,\r
979 IN VOID *Data,\r
980 IN UINTN DataSize\r
264702a0
HW
981 )\r
982{\r
bb78d969 983 return TlsSetHostPrivateKeyEx (Tls, Data, DataSize, NULL);\r
264702a0
HW
984}\r
985\r
986/**\r
987 Adds the CA-supplied certificate revocation list for certificate validation.\r
988\r
989 This function adds the CA-supplied certificate revocation list data for\r
990 certificate validity checking.\r
991\r
992 @param[in] Data Pointer to the data buffer of a DER-encoded CRL data.\r
993 @param[in] DataSize The size of data buffer in bytes.\r
994\r
995 @retval EFI_SUCCESS The operation succeeded.\r
996 @retval EFI_UNSUPPORTED This function is not supported.\r
997 @retval EFI_ABORTED Invalid CRL data.\r
998\r
999**/\r
1000EFI_STATUS\r
1001EFIAPI\r
1002TlsSetCertRevocationList (\r
7c342378
MK
1003 IN VOID *Data,\r
1004 IN UINTN DataSize\r
264702a0
HW
1005 )\r
1006{\r
1007 return EFI_UNSUPPORTED;\r
1008}\r
1009\r
bb78d969
YL
1010/**\r
1011 Set the signature algorithm list to used by the TLS object.\r
1012\r
1013 This function sets the signature algorithms for use by a specified TLS object.\r
1014\r
1015 @param[in] Tls Pointer to a TLS object.\r
1016 @param[in] Data Array of UINT8 of signature algorithms. The array consists of\r
1017 pairs of the hash algorithm and the signature algorithm as defined\r
1018 in RFC 5246\r
1019 @param[in] DataSize The length the SignatureAlgoList. Must be divisible by 2.\r
1020\r
1021 @retval EFI_SUCCESS The signature algorithm list was set successfully.\r
1022 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
1023 @retval EFI_UNSUPPORTED No supported TLS signature algorithm was found in SignatureAlgoList\r
1024 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
1025\r
1026**/\r
1027EFI_STATUS\r
1028EFIAPI\r
1029TlsSetSignatureAlgoList (\r
1030 IN VOID *Tls,\r
1031 IN UINT8 *Data,\r
1032 IN UINTN DataSize\r
1033 )\r
1034{\r
1035 TLS_CONNECTION *TlsConn;\r
1036 UINTN Index;\r
1037 UINTN SignAlgoStrSize;\r
1038 CHAR8 *SignAlgoStr;\r
1039 CHAR8 *Pos;\r
1040 UINT8 *SignatureAlgoList;\r
1041 EFI_STATUS Status;\r
1042\r
1043 TlsConn = (TLS_CONNECTION *)Tls;\r
1044\r
1045 if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (Data == NULL) || (DataSize < 3) ||\r
1046 ((DataSize % 2) == 0) || (Data[0] != DataSize - 1))\r
1047 {\r
1048 return EFI_INVALID_PARAMETER;\r
1049 }\r
1050\r
1051 SignatureAlgoList = Data + 1;\r
1052 SignAlgoStrSize = 0;\r
1053 for (Index = 0; Index < Data[0]; Index += 2) {\r
1054 CONST CHAR8 *Tmp;\r
1055\r
1056 if (SignatureAlgoList[Index] >= ARRAY_SIZE (TlsHashAlgoToName)) {\r
1057 return EFI_INVALID_PARAMETER;\r
1058 }\r
1059\r
1060 Tmp = TlsHashAlgoToName[SignatureAlgoList[Index]].Name;\r
1061 if (!Tmp) {\r
1062 return EFI_INVALID_PARAMETER;\r
1063 }\r
1064\r
1065 // Add 1 for the '+'\r
1066 SignAlgoStrSize += AsciiStrLen (Tmp) + 1;\r
1067\r
1068 if (SignatureAlgoList[Index + 1] >= ARRAY_SIZE (TlsSignatureAlgoToName)) {\r
1069 return EFI_INVALID_PARAMETER;\r
1070 }\r
1071\r
1072 Tmp = TlsSignatureAlgoToName[SignatureAlgoList[Index + 1]].Name;\r
1073 if (!Tmp) {\r
1074 return EFI_INVALID_PARAMETER;\r
1075 }\r
1076\r
1077 // Add 1 for the ':' or for the NULL terminator\r
1078 SignAlgoStrSize += AsciiStrLen (Tmp) + 1;\r
1079 }\r
1080\r
1081 if (!SignAlgoStrSize) {\r
1082 return EFI_UNSUPPORTED;\r
1083 }\r
1084\r
1085 SignAlgoStr = AllocatePool (SignAlgoStrSize);\r
1086 if (SignAlgoStr == NULL) {\r
1087 return EFI_OUT_OF_RESOURCES;\r
1088 }\r
1089\r
1090 Pos = SignAlgoStr;\r
1091 for (Index = 0; Index < Data[0]; Index += 2) {\r
1092 CONST CHAR8 *Tmp;\r
1093\r
1094 Tmp = TlsHashAlgoToName[SignatureAlgoList[Index]].Name;\r
1095 CopyMem (Pos, Tmp, AsciiStrLen (Tmp));\r
1096 Pos += AsciiStrLen (Tmp);\r
1097 *Pos++ = '+';\r
1098\r
1099 Tmp = TlsSignatureAlgoToName[SignatureAlgoList[Index + 1]].Name;\r
1100 CopyMem (Pos, Tmp, AsciiStrLen (Tmp));\r
1101 Pos += AsciiStrLen (Tmp);\r
1102 *Pos++ = ':';\r
1103 }\r
1104\r
1105 *(Pos - 1) = '\0';\r
1106\r
1107 if (SSL_set1_sigalgs_list (TlsConn->Ssl, SignAlgoStr) < 1) {\r
1108 Status = EFI_INVALID_PARAMETER;\r
1109 } else {\r
1110 Status = EFI_SUCCESS;\r
1111 }\r
1112\r
1113 FreePool (SignAlgoStr);\r
1114 return Status;\r
1115}\r
1116\r
1117/**\r
1118 Set the EC curve to be used for TLS flows\r
1119\r
1120 This function sets the EC curve to be used for TLS flows.\r
1121\r
1122 @param[in] Tls Pointer to a TLS object.\r
1123 @param[in] Data An EC named curve as defined in section 5.1.1 of RFC 4492.\r
1124 @param[in] DataSize Size of Data, it should be sizeof (UINT32)\r
1125\r
1126 @retval EFI_SUCCESS The EC curve was set successfully.\r
1127 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
1128 @retval EFI_UNSUPPORTED The requested TLS EC curve is not supported\r
1129\r
1130**/\r
1131EFI_STATUS\r
1132EFIAPI\r
1133TlsSetEcCurve (\r
1134 IN VOID *Tls,\r
1135 IN UINT8 *Data,\r
1136 IN UINTN DataSize\r
1137 )\r
1138{\r
bb78d969
YL
1139 TLS_CONNECTION *TlsConn;\r
1140 EC_KEY *EcKey;\r
1141 INT32 Nid;\r
1142 INT32 Ret;\r
1143\r
1144 TlsConn = (TLS_CONNECTION *)Tls;\r
1145\r
1146 if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (Data == NULL) || (DataSize != sizeof (UINT32))) {\r
1147 return EFI_INVALID_PARAMETER;\r
1148 }\r
1149\r
1150 switch (*((UINT32 *)Data)) {\r
1151 case TlsEcNamedCurveSecp256r1:\r
1152 return EFI_UNSUPPORTED;\r
1153 case TlsEcNamedCurveSecp384r1:\r
1154 Nid = NID_secp384r1;\r
1155 break;\r
1156 case TlsEcNamedCurveSecp521r1:\r
1157 Nid = NID_secp521r1;\r
1158 break;\r
1159 case TlsEcNamedCurveX25519:\r
1160 Nid = NID_X25519;\r
1161 break;\r
1162 case TlsEcNamedCurveX448:\r
1163 Nid = NID_X448;\r
1164 break;\r
1165 default:\r
1166 return EFI_UNSUPPORTED;\r
1167 }\r
1168\r
1169 if (SSL_set1_curves (TlsConn->Ssl, &Nid, 1) != 1) {\r
dd00f92b 1170 return EFI_UNSUPPORTED;\r
bb78d969
YL
1171 }\r
1172\r
1173 EcKey = EC_KEY_new_by_curve_name (Nid);\r
1174 if (EcKey == NULL) {\r
dd00f92b 1175 return EFI_UNSUPPORTED;\r
bb78d969
YL
1176 }\r
1177\r
1178 Ret = SSL_set_tmp_ecdh (TlsConn->Ssl, EcKey);\r
1179 EC_KEY_free (EcKey);\r
1180\r
1181 if (Ret != 1) {\r
dd00f92b 1182 return EFI_UNSUPPORTED;\r
bb78d969
YL
1183 }\r
1184\r
1185 return EFI_SUCCESS;\r
bb78d969
YL
1186}\r
1187\r
264702a0
HW
1188/**\r
1189 Gets the protocol version used by the specified TLS connection.\r
1190\r
1191 This function returns the protocol version used by the specified TLS\r
1192 connection.\r
1193\r
9c14f76b
JW
1194 If Tls is NULL, then ASSERT().\r
1195\r
264702a0
HW
1196 @param[in] Tls Pointer to the TLS object.\r
1197\r
1198 @return The protocol version of the specified TLS connection.\r
1199\r
1200**/\r
1201UINT16\r
1202EFIAPI\r
1203TlsGetVersion (\r
7c342378 1204 IN VOID *Tls\r
264702a0
HW
1205 )\r
1206{\r
1207 TLS_CONNECTION *TlsConn;\r
1208\r
7c342378 1209 TlsConn = (TLS_CONNECTION *)Tls;\r
264702a0
HW
1210\r
1211 ASSERT (TlsConn != NULL);\r
1212\r
1213 return (UINT16)(SSL_version (TlsConn->Ssl));\r
1214}\r
1215\r
1216/**\r
1217 Gets the connection end of the specified TLS connection.\r
1218\r
1219 This function returns the connection end (as client or as server) used by\r
1220 the specified TLS connection.\r
1221\r
9c14f76b
JW
1222 If Tls is NULL, then ASSERT().\r
1223\r
264702a0
HW
1224 @param[in] Tls Pointer to the TLS object.\r
1225\r
1226 @return The connection end used by the specified TLS connection.\r
1227\r
1228**/\r
1229UINT8\r
1230EFIAPI\r
1231TlsGetConnectionEnd (\r
7c342378 1232 IN VOID *Tls\r
264702a0
HW
1233 )\r
1234{\r
1235 TLS_CONNECTION *TlsConn;\r
1236\r
7c342378 1237 TlsConn = (TLS_CONNECTION *)Tls;\r
264702a0
HW
1238\r
1239 ASSERT (TlsConn != NULL);\r
1240\r
1241 return (UINT8)SSL_is_server (TlsConn->Ssl);\r
1242}\r
1243\r
1244/**\r
1245 Gets the cipher suite used by the specified TLS connection.\r
1246\r
1247 This function returns current cipher suite used by the specified\r
1248 TLS connection.\r
1249\r
1250 @param[in] Tls Pointer to the TLS object.\r
1251 @param[in,out] CipherId The cipher suite used by the TLS object.\r
1252\r
1253 @retval EFI_SUCCESS The cipher suite was returned successfully.\r
1254 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
1255 @retval EFI_UNSUPPORTED Unsupported cipher suite.\r
1256\r
1257**/\r
1258EFI_STATUS\r
1259EFIAPI\r
1260TlsGetCurrentCipher (\r
7c342378
MK
1261 IN VOID *Tls,\r
1262 IN OUT UINT16 *CipherId\r
264702a0
HW
1263 )\r
1264{\r
1265 TLS_CONNECTION *TlsConn;\r
1266 CONST SSL_CIPHER *Cipher;\r
1267\r
7c342378 1268 TlsConn = (TLS_CONNECTION *)Tls;\r
264702a0
HW
1269 Cipher = NULL;\r
1270\r
7c342378 1271 if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (CipherId == NULL)) {\r
264702a0
HW
1272 return EFI_INVALID_PARAMETER;\r
1273 }\r
1274\r
1275 Cipher = SSL_get_current_cipher (TlsConn->Ssl);\r
1276 if (Cipher == NULL) {\r
1277 return EFI_UNSUPPORTED;\r
1278 }\r
1279\r
1280 *CipherId = (SSL_CIPHER_get_id (Cipher)) & 0xFFFF;\r
1281\r
1282 return EFI_SUCCESS;\r
1283}\r
1284\r
1285/**\r
1286 Gets the compression methods used by the specified TLS connection.\r
1287\r
1288 This function returns current integrated compression methods used by\r
1289 the specified TLS connection.\r
1290\r
1291 @param[in] Tls Pointer to the TLS object.\r
1292 @param[in,out] CompressionId The current compression method used by\r
1293 the TLS object.\r
1294\r
1295 @retval EFI_SUCCESS The compression method was returned successfully.\r
1296 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
1297 @retval EFI_ABORTED Invalid Compression method.\r
1298 @retval EFI_UNSUPPORTED This function is not supported.\r
1299\r
1300**/\r
1301EFI_STATUS\r
1302EFIAPI\r
1303TlsGetCurrentCompressionId (\r
7c342378
MK
1304 IN VOID *Tls,\r
1305 IN OUT UINT8 *CompressionId\r
264702a0
HW
1306 )\r
1307{\r
1308 return EFI_UNSUPPORTED;\r
1309}\r
1310\r
1311/**\r
1312 Gets the verification mode currently set in the TLS connection.\r
1313\r
1314 This function returns the peer verification mode currently set in the\r
1315 specified TLS connection.\r
1316\r
9c14f76b
JW
1317 If Tls is NULL, then ASSERT().\r
1318\r
264702a0
HW
1319 @param[in] Tls Pointer to the TLS object.\r
1320\r
1321 @return The verification mode set in the specified TLS connection.\r
1322\r
1323**/\r
1324UINT32\r
1325EFIAPI\r
1326TlsGetVerify (\r
7c342378 1327 IN VOID *Tls\r
264702a0
HW
1328 )\r
1329{\r
1330 TLS_CONNECTION *TlsConn;\r
1331\r
7c342378 1332 TlsConn = (TLS_CONNECTION *)Tls;\r
264702a0
HW
1333\r
1334 ASSERT (TlsConn != NULL);\r
1335\r
1336 return SSL_get_verify_mode (TlsConn->Ssl);\r
1337}\r
1338\r
1339/**\r
1340 Gets the session ID used by the specified TLS connection.\r
1341\r
1342 This function returns the TLS/SSL session ID currently used by the\r
1343 specified TLS connection.\r
1344\r
1345 @param[in] Tls Pointer to the TLS object.\r
1346 @param[in,out] SessionId Buffer to contain the returned session ID.\r
1347 @param[in,out] SessionIdLen The length of Session ID in bytes.\r
1348\r
1349 @retval EFI_SUCCESS The Session ID was returned successfully.\r
1350 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
1351 @retval EFI_UNSUPPORTED Invalid TLS/SSL session.\r
1352\r
1353**/\r
1354EFI_STATUS\r
1355EFIAPI\r
1356TlsGetSessionId (\r
7c342378
MK
1357 IN VOID *Tls,\r
1358 IN OUT UINT8 *SessionId,\r
1359 IN OUT UINT16 *SessionIdLen\r
264702a0
HW
1360 )\r
1361{\r
1362 TLS_CONNECTION *TlsConn;\r
1363 SSL_SESSION *Session;\r
1364 CONST UINT8 *SslSessionId;\r
1365\r
7c342378 1366 TlsConn = (TLS_CONNECTION *)Tls;\r
264702a0
HW
1367 Session = NULL;\r
1368\r
7c342378 1369 if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (SessionId == NULL) || (SessionIdLen == NULL)) {\r
264702a0
HW
1370 return EFI_INVALID_PARAMETER;\r
1371 }\r
1372\r
1373 Session = SSL_get_session (TlsConn->Ssl);\r
1374 if (Session == NULL) {\r
1375 return EFI_UNSUPPORTED;\r
1376 }\r
1377\r
1378 SslSessionId = SSL_SESSION_get_id (Session, (unsigned int *)SessionIdLen);\r
1379 CopyMem (SessionId, SslSessionId, *SessionIdLen);\r
1380\r
1381 return EFI_SUCCESS;\r
1382}\r
1383\r
1384/**\r
1385 Gets the client random data used in the specified TLS connection.\r
1386\r
1387 This function returns the TLS/SSL client random data currently used in\r
1388 the specified TLS connection.\r
1389\r
1390 @param[in] Tls Pointer to the TLS object.\r
1391 @param[in,out] ClientRandom Buffer to contain the returned client\r
1392 random data (32 bytes).\r
1393\r
1394**/\r
1395VOID\r
1396EFIAPI\r
1397TlsGetClientRandom (\r
7c342378
MK
1398 IN VOID *Tls,\r
1399 IN OUT UINT8 *ClientRandom\r
264702a0
HW
1400 )\r
1401{\r
1402 TLS_CONNECTION *TlsConn;\r
1403\r
7c342378 1404 TlsConn = (TLS_CONNECTION *)Tls;\r
264702a0 1405\r
7c342378 1406 if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (ClientRandom == NULL)) {\r
264702a0
HW
1407 return;\r
1408 }\r
1409\r
1410 SSL_get_client_random (TlsConn->Ssl, ClientRandom, SSL3_RANDOM_SIZE);\r
1411}\r
1412\r
1413/**\r
1414 Gets the server random data used in the specified TLS connection.\r
1415\r
1416 This function returns the TLS/SSL server random data currently used in\r
1417 the specified TLS connection.\r
1418\r
1419 @param[in] Tls Pointer to the TLS object.\r
1420 @param[in,out] ServerRandom Buffer to contain the returned server\r
1421 random data (32 bytes).\r
1422\r
1423**/\r
1424VOID\r
1425EFIAPI\r
1426TlsGetServerRandom (\r
7c342378
MK
1427 IN VOID *Tls,\r
1428 IN OUT UINT8 *ServerRandom\r
264702a0
HW
1429 )\r
1430{\r
1431 TLS_CONNECTION *TlsConn;\r
1432\r
7c342378 1433 TlsConn = (TLS_CONNECTION *)Tls;\r
264702a0 1434\r
7c342378 1435 if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (ServerRandom == NULL)) {\r
264702a0
HW
1436 return;\r
1437 }\r
1438\r
1439 SSL_get_server_random (TlsConn->Ssl, ServerRandom, SSL3_RANDOM_SIZE);\r
1440}\r
1441\r
1442/**\r
1443 Gets the master key data used in the specified TLS connection.\r
1444\r
1445 This function returns the TLS/SSL master key material currently used in\r
1446 the specified TLS connection.\r
1447\r
1448 @param[in] Tls Pointer to the TLS object.\r
1449 @param[in,out] KeyMaterial Buffer to contain the returned key material.\r
1450\r
1451 @retval EFI_SUCCESS Key material was returned successfully.\r
1452 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
1453 @retval EFI_UNSUPPORTED Invalid TLS/SSL session.\r
1454\r
1455**/\r
1456EFI_STATUS\r
1457EFIAPI\r
1458TlsGetKeyMaterial (\r
7c342378
MK
1459 IN VOID *Tls,\r
1460 IN OUT UINT8 *KeyMaterial\r
264702a0
HW
1461 )\r
1462{\r
1463 TLS_CONNECTION *TlsConn;\r
1464 SSL_SESSION *Session;\r
1465\r
7c342378 1466 TlsConn = (TLS_CONNECTION *)Tls;\r
264702a0
HW
1467 Session = NULL;\r
1468\r
7c342378 1469 if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (KeyMaterial == NULL)) {\r
264702a0
HW
1470 return EFI_INVALID_PARAMETER;\r
1471 }\r
1472\r
1473 Session = SSL_get_session (TlsConn->Ssl);\r
1474\r
1475 if (Session == NULL) {\r
1476 return EFI_UNSUPPORTED;\r
1477 }\r
1478\r
1479 SSL_SESSION_get_master_key (Session, KeyMaterial, SSL3_MASTER_SECRET_SIZE);\r
1480\r
1481 return EFI_SUCCESS;\r
1482}\r
1483\r
1484/**\r
1485 Gets the CA Certificate from the cert store.\r
1486\r
1487 This function returns the CA certificate for the chosen\r
1488 TLS connection.\r
1489\r
1490 @param[in] Tls Pointer to the TLS object.\r
1491 @param[out] Data Pointer to the data buffer to receive the CA\r
1492 certificate data sent to the client.\r
1493 @param[in,out] DataSize The size of data buffer in bytes.\r
1494\r
1495 @retval EFI_SUCCESS The operation succeeded.\r
1496 @retval EFI_UNSUPPORTED This function is not supported.\r
1497 @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data.\r
1498\r
1499**/\r
1500EFI_STATUS\r
1501EFIAPI\r
1502TlsGetCaCertificate (\r
7c342378
MK
1503 IN VOID *Tls,\r
1504 OUT VOID *Data,\r
1505 IN OUT UINTN *DataSize\r
264702a0
HW
1506 )\r
1507{\r
1508 return EFI_UNSUPPORTED;\r
1509}\r
1510\r
1511/**\r
1512 Gets the local public Certificate set in the specified TLS object.\r
1513\r
1514 This function returns the local public certificate which was currently set\r
1515 in the specified TLS object.\r
1516\r
1517 @param[in] Tls Pointer to the TLS object.\r
1518 @param[out] Data Pointer to the data buffer to receive the local\r
1519 public certificate.\r
1520 @param[in,out] DataSize The size of data buffer in bytes.\r
1521\r
1522 @retval EFI_SUCCESS The operation succeeded.\r
1523 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
1524 @retval EFI_NOT_FOUND The certificate is not found.\r
1525 @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data.\r
1526\r
1527**/\r
1528EFI_STATUS\r
1529EFIAPI\r
1530TlsGetHostPublicCert (\r
7c342378
MK
1531 IN VOID *Tls,\r
1532 OUT VOID *Data,\r
1533 IN OUT UINTN *DataSize\r
264702a0
HW
1534 )\r
1535{\r
1536 X509 *Cert;\r
1537 TLS_CONNECTION *TlsConn;\r
1538\r
1539 Cert = NULL;\r
7c342378 1540 TlsConn = (TLS_CONNECTION *)Tls;\r
264702a0 1541\r
7c342378 1542 if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (DataSize == NULL) || ((*DataSize != 0) && (Data == NULL))) {\r
264702a0
HW
1543 return EFI_INVALID_PARAMETER;\r
1544 }\r
1545\r
7c342378 1546 Cert = SSL_get_certificate (TlsConn->Ssl);\r
264702a0
HW
1547 if (Cert == NULL) {\r
1548 return EFI_NOT_FOUND;\r
1549 }\r
1550\r
1551 //\r
1552 // Only DER encoding is supported currently.\r
1553 //\r
7c342378
MK
1554 if (*DataSize < (UINTN)i2d_X509 (Cert, NULL)) {\r
1555 *DataSize = (UINTN)i2d_X509 (Cert, NULL);\r
264702a0
HW
1556 return EFI_BUFFER_TOO_SMALL;\r
1557 }\r
1558\r
7c342378 1559 *DataSize = (UINTN)i2d_X509 (Cert, (unsigned char **)&Data);\r
264702a0
HW
1560\r
1561 return EFI_SUCCESS;\r
1562}\r
1563\r
1564/**\r
1565 Gets the local private key set in the specified TLS object.\r
1566\r
1567 This function returns the local private key data which was currently set\r
1568 in the specified TLS object.\r
1569\r
1570 @param[in] Tls Pointer to the TLS object.\r
1571 @param[out] Data Pointer to the data buffer to receive the local\r
1572 private key data.\r
1573 @param[in,out] DataSize The size of data buffer in bytes.\r
1574\r
1575 @retval EFI_SUCCESS The operation succeeded.\r
1576 @retval EFI_UNSUPPORTED This function is not supported.\r
1577 @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data.\r
1578\r
1579**/\r
1580EFI_STATUS\r
1581EFIAPI\r
1582TlsGetHostPrivateKey (\r
7c342378
MK
1583 IN VOID *Tls,\r
1584 OUT VOID *Data,\r
1585 IN OUT UINTN *DataSize\r
264702a0
HW
1586 )\r
1587{\r
1588 return EFI_UNSUPPORTED;\r
1589}\r
1590\r
1591/**\r
1592 Gets the CA-supplied certificate revocation list data set in the specified\r
1593 TLS object.\r
1594\r
1595 This function returns the CA-supplied certificate revocation list data which\r
1596 was currently set in the specified TLS object.\r
1597\r
1598 @param[out] Data Pointer to the data buffer to receive the CRL data.\r
1599 @param[in,out] DataSize The size of data buffer in bytes.\r
1600\r
1601 @retval EFI_SUCCESS The operation succeeded.\r
1602 @retval EFI_UNSUPPORTED This function is not supported.\r
1603 @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data.\r
1604\r
1605**/\r
1606EFI_STATUS\r
1607EFIAPI\r
1608TlsGetCertRevocationList (\r
7c342378
MK
1609 OUT VOID *Data,\r
1610 IN OUT UINTN *DataSize\r
264702a0
HW
1611 )\r
1612{\r
1613 return EFI_UNSUPPORTED;\r
1614}\r
bb78d969
YL
1615\r
1616/**\r
1617 Derive keying material from a TLS connection.\r
1618\r
1619 This function exports keying material using the mechanism described in RFC\r
1620 5705.\r
1621\r
1622 @param[in] Tls Pointer to the TLS object\r
1623 @param[in] Label Description of the key for the PRF function\r
1624 @param[in] Context Optional context\r
1625 @param[in] ContextLen The length of the context value in bytes\r
1626 @param[out] KeyBuffer Buffer to hold the output of the TLS-PRF\r
1627 @param[in] KeyBufferLen The length of the KeyBuffer\r
1628\r
1629 @retval EFI_SUCCESS The operation succeeded.\r
1630 @retval EFI_INVALID_PARAMETER The TLS object is invalid.\r
1631 @retval EFI_PROTOCOL_ERROR Some other error occurred.\r
1632\r
1633**/\r
1634EFI_STATUS\r
1635EFIAPI\r
1636TlsGetExportKey (\r
1637 IN VOID *Tls,\r
1638 IN CONST VOID *Label,\r
1639 IN CONST VOID *Context,\r
1640 IN UINTN ContextLen,\r
1641 OUT VOID *KeyBuffer,\r
1642 IN UINTN KeyBufferLen\r
1643 )\r
1644{\r
1645 TLS_CONNECTION *TlsConn;\r
1646\r
1647 TlsConn = (TLS_CONNECTION *)Tls;\r
1648\r
1649 if ((TlsConn == NULL) || (TlsConn->Ssl == NULL)) {\r
1650 return EFI_INVALID_PARAMETER;\r
1651 }\r
1652\r
1653 return SSL_export_keying_material (\r
1654 TlsConn->Ssl,\r
1655 KeyBuffer,\r
1656 KeyBufferLen,\r
1657 Label,\r
1658 AsciiStrLen (Label),\r
1659 Context,\r
1660 ContextLen,\r
1661 Context != NULL\r
1662 ) == 1 ?\r
1663 EFI_SUCCESS : EFI_PROTOCOL_ERROR;\r
1664}\r