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