]> git.proxmox.com Git - mirror_edk2.git/blob - CryptoPkg/Library/TlsLib/TlsConfig.c
CryptoPkg/TlsLib: rewrite TlsSetCipherList()
[mirror_edk2.git] / CryptoPkg / Library / TlsLib / TlsConfig.c
1 /** @file
2 SSL/TLS Configuration Library Wrapper Implementation over OpenSSL.
3
4 Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "InternalTlsLib.h"
17
18 typedef struct {
19 //
20 // IANA/IETF defined Cipher Suite ID
21 //
22 UINT16 IanaCipher;
23 //
24 // OpenSSL-used Cipher Suite String
25 //
26 CONST CHAR8 *OpensslCipher;
27 //
28 // Length of OpensslCipher
29 //
30 UINTN OpensslCipherLength;
31 } TLS_CIPHER_MAPPING;
32
33 //
34 // Create a TLS_CIPHER_MAPPING initializer from IanaCipher and OpensslCipher so
35 // that OpensslCipherLength is filled in automatically. IanaCipher must be an
36 // integer constant expression, and OpensslCipher must be a string literal.
37 //
38 #define MAP(IanaCipher, OpensslCipher) \
39 { (IanaCipher), (OpensslCipher), sizeof (OpensslCipher) - 1 }
40
41 //
42 // The mapping table between IANA/IETF Cipher Suite definitions and
43 // OpenSSL-used Cipher Suite name.
44 //
45 // Keep the table uniquely sorted by the IanaCipher field, in increasing order.
46 //
47 STATIC CONST TLS_CIPHER_MAPPING TlsCipherMappingTable[] = {
48 MAP ( 0x0001, "NULL-MD5" ), /// TLS_RSA_WITH_NULL_MD5
49 MAP ( 0x0002, "NULL-SHA" ), /// TLS_RSA_WITH_NULL_SHA
50 MAP ( 0x0004, "RC4-MD5" ), /// TLS_RSA_WITH_RC4_128_MD5
51 MAP ( 0x0005, "RC4-SHA" ), /// TLS_RSA_WITH_RC4_128_SHA
52 MAP ( 0x000A, "DES-CBC3-SHA" ), /// TLS_RSA_WITH_3DES_EDE_CBC_SHA, mandatory TLS 1.1
53 MAP ( 0x0016, "DHE-RSA-DES-CBC3-SHA" ), /// TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
54 MAP ( 0x002F, "AES128-SHA" ), /// TLS_RSA_WITH_AES_128_CBC_SHA, mandatory TLS 1.2
55 MAP ( 0x0030, "DH-DSS-AES128-SHA" ), /// TLS_DH_DSS_WITH_AES_128_CBC_SHA
56 MAP ( 0x0031, "DH-RSA-AES128-SHA" ), /// TLS_DH_RSA_WITH_AES_128_CBC_SHA
57 MAP ( 0x0033, "DHE-RSA-AES128-SHA" ), /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA
58 MAP ( 0x0035, "AES256-SHA" ), /// TLS_RSA_WITH_AES_256_CBC_SHA
59 MAP ( 0x0036, "DH-DSS-AES256-SHA" ), /// TLS_DH_DSS_WITH_AES_256_CBC_SHA
60 MAP ( 0x0037, "DH-RSA-AES256-SHA" ), /// TLS_DH_RSA_WITH_AES_256_CBC_SHA
61 MAP ( 0x0039, "DHE-RSA-AES256-SHA" ), /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA
62 MAP ( 0x003B, "NULL-SHA256" ), /// TLS_RSA_WITH_NULL_SHA256
63 MAP ( 0x003C, "AES128-SHA256" ), /// TLS_RSA_WITH_AES_128_CBC_SHA256
64 MAP ( 0x003D, "AES256-SHA256" ), /// TLS_RSA_WITH_AES_256_CBC_SHA256
65 MAP ( 0x003E, "DH-DSS-AES128-SHA256" ), /// TLS_DH_DSS_WITH_AES_128_CBC_SHA256
66 MAP ( 0x003F, "DH-RSA-AES128-SHA256" ), /// TLS_DH_RSA_WITH_AES_128_CBC_SHA256
67 MAP ( 0x0067, "DHE-RSA-AES128-SHA256" ), /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
68 MAP ( 0x0068, "DH-DSS-AES256-SHA256" ), /// TLS_DH_DSS_WITH_AES_256_CBC_SHA256
69 MAP ( 0x0069, "DH-RSA-AES256-SHA256" ), /// TLS_DH_RSA_WITH_AES_256_CBC_SHA256
70 MAP ( 0x006B, "DHE-RSA-AES256-SHA256" ), /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
71 };
72
73 /**
74 Gets the OpenSSL cipher suite mapping for the supplied IANA TLS cipher suite.
75
76 @param[in] CipherId The supplied IANA TLS cipher suite ID.
77
78 @return The corresponding OpenSSL cipher suite mapping if found,
79 NULL otherwise.
80
81 **/
82 STATIC
83 CONST TLS_CIPHER_MAPPING *
84 TlsGetCipherMapping (
85 IN UINT16 CipherId
86 )
87 {
88 INTN Left;
89 INTN Right;
90 INTN Middle;
91
92 //
93 // Binary Search Cipher Mapping Table for IANA-OpenSSL Cipher Translation
94 //
95 Left = 0;
96 Right = ARRAY_SIZE (TlsCipherMappingTable) - 1;
97
98 while (Right >= Left) {
99 Middle = (Left + Right) / 2;
100
101 if (CipherId == TlsCipherMappingTable[Middle].IanaCipher) {
102 //
103 // Translate IANA cipher suite ID to OpenSSL name.
104 //
105 return &TlsCipherMappingTable[Middle];
106 }
107
108 if (CipherId < TlsCipherMappingTable[Middle].IanaCipher) {
109 Right = Middle - 1;
110 } else {
111 Left = Middle + 1;
112 }
113 }
114
115 //
116 // No Cipher Mapping found, return NULL.
117 //
118 return NULL;
119 }
120
121 /**
122 Set a new TLS/SSL method for a particular TLS object.
123
124 This function sets a new TLS/SSL method for a particular TLS object.
125
126 @param[in] Tls Pointer to a TLS object.
127 @param[in] MajorVer Major Version of TLS/SSL Protocol.
128 @param[in] MinorVer Minor Version of TLS/SSL Protocol.
129
130 @retval EFI_SUCCESS The TLS/SSL method was set successfully.
131 @retval EFI_INVALID_PARAMETER The parameter is invalid.
132 @retval EFI_UNSUPPORTED Unsupported TLS/SSL method.
133
134 **/
135 EFI_STATUS
136 EFIAPI
137 TlsSetVersion (
138 IN VOID *Tls,
139 IN UINT8 MajorVer,
140 IN UINT8 MinorVer
141 )
142 {
143 TLS_CONNECTION *TlsConn;
144 UINT16 ProtoVersion;
145
146 TlsConn = (TLS_CONNECTION *)Tls;
147 if (TlsConn == NULL || TlsConn->Ssl == NULL) {
148 return EFI_INVALID_PARAMETER;
149 }
150
151 ProtoVersion = (MajorVer << 8) | MinorVer;
152
153 //
154 // Bound TLS method to the particular specified version.
155 //
156 switch (ProtoVersion) {
157 case TLS1_VERSION:
158 //
159 // TLS 1.0
160 //
161 SSL_set_min_proto_version (TlsConn->Ssl, TLS1_VERSION);
162 SSL_set_max_proto_version (TlsConn->Ssl, TLS1_VERSION);
163 break;
164 case TLS1_1_VERSION:
165 //
166 // TLS 1.1
167 //
168 SSL_set_min_proto_version (TlsConn->Ssl, TLS1_1_VERSION);
169 SSL_set_max_proto_version (TlsConn->Ssl, TLS1_1_VERSION);
170 break;
171 case TLS1_2_VERSION:
172 //
173 // TLS 1.2
174 //
175 SSL_set_min_proto_version (TlsConn->Ssl, TLS1_2_VERSION);
176 SSL_set_max_proto_version (TlsConn->Ssl, TLS1_2_VERSION);
177 break;
178 default:
179 //
180 // Unsupported Protocol Version
181 //
182 return EFI_UNSUPPORTED;
183 }
184
185 return EFI_SUCCESS;;
186 }
187
188 /**
189 Set TLS object to work in client or server mode.
190
191 This function prepares a TLS object to work in client or server mode.
192
193 @param[in] Tls Pointer to a TLS object.
194 @param[in] IsServer Work in server mode.
195
196 @retval EFI_SUCCESS The TLS/SSL work mode was set successfully.
197 @retval EFI_INVALID_PARAMETER The parameter is invalid.
198 @retval EFI_UNSUPPORTED Unsupported TLS/SSL work mode.
199
200 **/
201 EFI_STATUS
202 EFIAPI
203 TlsSetConnectionEnd (
204 IN VOID *Tls,
205 IN BOOLEAN IsServer
206 )
207 {
208 TLS_CONNECTION *TlsConn;
209
210 TlsConn = (TLS_CONNECTION *) Tls;
211 if (TlsConn == NULL || TlsConn->Ssl == NULL) {
212 return EFI_INVALID_PARAMETER;
213 }
214
215 if (!IsServer) {
216 //
217 // Set TLS to work in Client mode.
218 //
219 SSL_set_connect_state (TlsConn->Ssl);
220 } else {
221 //
222 // Set TLS to work in Server mode.
223 // It is unsupported for UEFI version currently.
224 //
225 //SSL_set_accept_state (TlsConn->Ssl);
226 return EFI_UNSUPPORTED;
227 }
228
229 return EFI_SUCCESS;
230 }
231
232 /**
233 Set the ciphers list to be used by the TLS object.
234
235 This function sets the ciphers for use by a specified TLS object.
236
237 @param[in] Tls Pointer to a TLS object.
238 @param[in] CipherId Array of UINT16 cipher identifiers. Each UINT16
239 cipher identifier comes from the TLS Cipher Suite
240 Registry of the IANA, interpreting Byte1 and Byte2
241 in network (big endian) byte order.
242 @param[in] CipherNum The number of cipher in the list.
243
244 @retval EFI_SUCCESS The ciphers list was set successfully.
245 @retval EFI_INVALID_PARAMETER The parameter is invalid.
246 @retval EFI_UNSUPPORTED No supported TLS cipher was found in CipherId.
247 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
248
249 **/
250 EFI_STATUS
251 EFIAPI
252 TlsSetCipherList (
253 IN VOID *Tls,
254 IN UINT16 *CipherId,
255 IN UINTN CipherNum
256 )
257 {
258 TLS_CONNECTION *TlsConn;
259 EFI_STATUS Status;
260 CONST TLS_CIPHER_MAPPING **MappedCipher;
261 UINTN MappedCipherBytes;
262 UINTN MappedCipherCount;
263 UINTN CipherStringSize;
264 UINTN Index;
265 CONST TLS_CIPHER_MAPPING *Mapping;
266 CHAR8 *CipherString;
267 CHAR8 *CipherStringPosition;
268
269 TlsConn = (TLS_CONNECTION *) Tls;
270 if (TlsConn == NULL || TlsConn->Ssl == NULL || CipherId == NULL) {
271 return EFI_INVALID_PARAMETER;
272 }
273
274 //
275 // Allocate the MappedCipher array for recording the mappings that we find
276 // for the input IANA identifiers in CipherId.
277 //
278 Status = SafeUintnMult (CipherNum, sizeof (*MappedCipher),
279 &MappedCipherBytes);
280 if (EFI_ERROR (Status)) {
281 return EFI_OUT_OF_RESOURCES;
282 }
283 MappedCipher = AllocatePool (MappedCipherBytes);
284 if (MappedCipher == NULL) {
285 return EFI_OUT_OF_RESOURCES;
286 }
287
288 //
289 // Map the cipher IDs, and count the number of bytes for the full
290 // CipherString.
291 //
292 MappedCipherCount = 0;
293 CipherStringSize = 0;
294 for (Index = 0; Index < CipherNum; Index++) {
295 //
296 // Look up the IANA-to-OpenSSL mapping.
297 //
298 Mapping = TlsGetCipherMapping (CipherId[Index]);
299 if (Mapping == NULL) {
300 DEBUG ((DEBUG_VERBOSE, "%a:%a: skipping CipherId=0x%04x\n",
301 gEfiCallerBaseName, __FUNCTION__, CipherId[Index]));
302 //
303 // Skipping the cipher is valid because CipherId is an ordered
304 // preference list of ciphers, thus we can filter it as long as we
305 // don't change the relative order of elements on it.
306 //
307 continue;
308 }
309 //
310 // Accumulate Mapping->OpensslCipherLength into CipherStringSize. If this
311 // is not the first successful mapping, account for a colon (":") prefix
312 // too.
313 //
314 if (MappedCipherCount > 0) {
315 Status = SafeUintnAdd (CipherStringSize, 1, &CipherStringSize);
316 if (EFI_ERROR (Status)) {
317 Status = EFI_OUT_OF_RESOURCES;
318 goto FreeMappedCipher;
319 }
320 }
321 Status = SafeUintnAdd (CipherStringSize, Mapping->OpensslCipherLength,
322 &CipherStringSize);
323 if (EFI_ERROR (Status)) {
324 Status = EFI_OUT_OF_RESOURCES;
325 goto FreeMappedCipher;
326 }
327 //
328 // Record the mapping.
329 //
330 MappedCipher[MappedCipherCount++] = Mapping;
331 }
332
333 //
334 // Verify that at least one IANA cipher ID could be mapped; account for the
335 // terminating NUL character in CipherStringSize; allocate CipherString.
336 //
337 if (MappedCipherCount == 0) {
338 DEBUG ((DEBUG_ERROR, "%a:%a: no CipherId could be mapped\n",
339 gEfiCallerBaseName, __FUNCTION__));
340 Status = EFI_UNSUPPORTED;
341 goto FreeMappedCipher;
342 }
343 Status = SafeUintnAdd (CipherStringSize, 1, &CipherStringSize);
344 if (EFI_ERROR (Status)) {
345 Status = EFI_OUT_OF_RESOURCES;
346 goto FreeMappedCipher;
347 }
348 CipherString = AllocatePool (CipherStringSize);
349 if (CipherString == NULL) {
350 Status = EFI_OUT_OF_RESOURCES;
351 goto FreeMappedCipher;
352 }
353
354 //
355 // Go over the collected mappings and populate CipherString.
356 //
357 CipherStringPosition = CipherString;
358 for (Index = 0; Index < MappedCipherCount; Index++) {
359 Mapping = MappedCipher[Index];
360 //
361 // Append the colon (":") prefix except for the first mapping, then append
362 // Mapping->OpensslCipher.
363 //
364 if (Index > 0) {
365 *(CipherStringPosition++) = ':';
366 }
367 CopyMem (CipherStringPosition, Mapping->OpensslCipher,
368 Mapping->OpensslCipherLength);
369 CipherStringPosition += Mapping->OpensslCipherLength;
370 }
371
372 //
373 // NUL-terminate CipherString.
374 //
375 *(CipherStringPosition++) = '\0';
376 ASSERT (CipherStringPosition == CipherString + CipherStringSize);
377
378 //
379 // Log CipherString for debugging. CipherString can be very long if the
380 // caller provided a large CipherId array, so log CipherString in segments of
381 // 79 non-newline characters. (MAX_DEBUG_MESSAGE_LENGTH is usually 0x100 in
382 // DebugLib instances.)
383 //
384 DEBUG_CODE (
385 UINTN FullLength;
386 UINTN SegmentLength;
387
388 FullLength = CipherStringSize - 1;
389 DEBUG ((DEBUG_VERBOSE, "%a:%a: CipherString={\n", gEfiCallerBaseName,
390 __FUNCTION__));
391 for (CipherStringPosition = CipherString;
392 CipherStringPosition < CipherString + FullLength;
393 CipherStringPosition += SegmentLength) {
394 SegmentLength = FullLength - (CipherStringPosition - CipherString);
395 if (SegmentLength > 79) {
396 SegmentLength = 79;
397 }
398 DEBUG ((DEBUG_VERBOSE, "%.*a\n", SegmentLength, CipherStringPosition));
399 }
400 DEBUG ((DEBUG_VERBOSE, "}\n"));
401 //
402 // Restore the pre-debug value of CipherStringPosition by skipping over the
403 // trailing NUL.
404 //
405 CipherStringPosition++;
406 ASSERT (CipherStringPosition == CipherString + CipherStringSize);
407 );
408
409 //
410 // Sets the ciphers for use by the Tls object.
411 //
412 if (SSL_set_cipher_list (TlsConn->Ssl, CipherString) <= 0) {
413 Status = EFI_UNSUPPORTED;
414 goto FreeCipherString;
415 }
416
417 Status = EFI_SUCCESS;
418
419 FreeCipherString:
420 FreePool (CipherString);
421
422 FreeMappedCipher:
423 FreePool (MappedCipher);
424
425 return Status;
426 }
427
428 /**
429 Set the compression method for TLS/SSL operations.
430
431 This function handles TLS/SSL integrated compression methods.
432
433 @param[in] CompMethod The compression method ID.
434
435 @retval EFI_SUCCESS The compression method for the communication was
436 set successfully.
437 @retval EFI_UNSUPPORTED Unsupported compression method.
438
439 **/
440 EFI_STATUS
441 EFIAPI
442 TlsSetCompressionMethod (
443 IN UINT8 CompMethod
444 )
445 {
446 COMP_METHOD *Cm;
447 INTN Ret;
448
449 Cm = NULL;
450 Ret = 0;
451
452 if (CompMethod == 0) {
453 //
454 // TLS defines one standard compression method, CompressionMethod.null (0),
455 // which specifies that data exchanged via the record protocol will not be compressed.
456 // So, return EFI_SUCCESS directly (RFC 3749).
457 //
458 return EFI_SUCCESS;
459 } else if (CompMethod == 1) {
460 Cm = COMP_zlib();
461 } else {
462 return EFI_UNSUPPORTED;
463 }
464
465 //
466 // Adds the compression method to the list of available
467 // compression methods.
468 //
469 Ret = SSL_COMP_add_compression_method (CompMethod, Cm);
470 if (Ret != 0) {
471 return EFI_UNSUPPORTED;
472 }
473
474 return EFI_SUCCESS;
475 }
476
477 /**
478 Set peer certificate verification mode for the TLS connection.
479
480 This function sets the verification mode flags for the TLS connection.
481
482 @param[in] Tls Pointer to the TLS object.
483 @param[in] VerifyMode A set of logically or'ed verification mode flags.
484
485 **/
486 VOID
487 EFIAPI
488 TlsSetVerify (
489 IN VOID *Tls,
490 IN UINT32 VerifyMode
491 )
492 {
493 TLS_CONNECTION *TlsConn;
494
495 TlsConn = (TLS_CONNECTION *) Tls;
496 if (TlsConn == NULL || TlsConn->Ssl == NULL) {
497 return;
498 }
499
500 //
501 // Set peer certificate verification parameters with NULL callback.
502 //
503 SSL_set_verify (TlsConn->Ssl, VerifyMode, NULL);
504 }
505
506 /**
507 Sets a TLS/SSL session ID to be used during TLS/SSL connect.
508
509 This function sets a session ID to be used when the TLS/SSL connection is
510 to be established.
511
512 @param[in] Tls Pointer to the TLS object.
513 @param[in] SessionId Session ID data used for session resumption.
514 @param[in] SessionIdLen Length of Session ID in bytes.
515
516 @retval EFI_SUCCESS Session ID was set successfully.
517 @retval EFI_INVALID_PARAMETER The parameter is invalid.
518 @retval EFI_UNSUPPORTED No available session for ID setting.
519
520 **/
521 EFI_STATUS
522 EFIAPI
523 TlsSetSessionId (
524 IN VOID *Tls,
525 IN UINT8 *SessionId,
526 IN UINT16 SessionIdLen
527 )
528 {
529 TLS_CONNECTION *TlsConn;
530 SSL_SESSION *Session;
531
532 TlsConn = (TLS_CONNECTION *) Tls;
533 Session = NULL;
534
535 if (TlsConn == NULL || TlsConn->Ssl == NULL || SessionId == NULL) {
536 return EFI_INVALID_PARAMETER;
537 }
538
539 Session = SSL_get_session (TlsConn->Ssl);
540 if (Session == NULL) {
541 return EFI_UNSUPPORTED;
542 }
543
544 SSL_SESSION_set1_id (Session, (const unsigned char *)SessionId, SessionIdLen);
545
546 return EFI_SUCCESS;
547 }
548
549 /**
550 Adds the CA to the cert store when requesting Server or Client authentication.
551
552 This function adds the CA certificate to the list of CAs when requesting
553 Server or Client authentication for the chosen TLS connection.
554
555 @param[in] Tls Pointer to the TLS object.
556 @param[in] Data Pointer to the data buffer of a DER-encoded binary
557 X.509 certificate or PEM-encoded X.509 certificate.
558 @param[in] DataSize The size of data buffer in bytes.
559
560 @retval EFI_SUCCESS The operation succeeded.
561 @retval EFI_INVALID_PARAMETER The parameter is invalid.
562 @retval EFI_OUT_OF_RESOURCES Required resources could not be allocated.
563 @retval EFI_ABORTED Invalid X.509 certificate.
564
565 **/
566 EFI_STATUS
567 EFIAPI
568 TlsSetCaCertificate (
569 IN VOID *Tls,
570 IN VOID *Data,
571 IN UINTN DataSize
572 )
573 {
574 BIO *BioCert;
575 X509 *Cert;
576 X509_STORE *X509Store;
577 EFI_STATUS Status;
578 TLS_CONNECTION *TlsConn;
579 SSL_CTX *SslCtx;
580 INTN Ret;
581 UINTN ErrorCode;
582
583 BioCert = NULL;
584 Cert = NULL;
585 X509Store = NULL;
586 Status = EFI_SUCCESS;
587 TlsConn = (TLS_CONNECTION *) Tls;
588 Ret = 0;
589
590 if (TlsConn == NULL || TlsConn->Ssl == NULL || Data == NULL || DataSize == 0) {
591 return EFI_INVALID_PARAMETER;
592 }
593
594 //
595 // DER-encoded binary X.509 certificate or PEM-encoded X.509 certificate.
596 // Determine whether certificate is from DER encoding, if so, translate it to X509 structure.
597 //
598 Cert = d2i_X509 (NULL, (const unsigned char ** )&Data, (long) DataSize);
599 if (Cert == NULL) {
600 //
601 // Certificate is from PEM encoding.
602 //
603 BioCert = BIO_new (BIO_s_mem ());
604 if (BioCert == NULL) {
605 Status = EFI_OUT_OF_RESOURCES;
606 goto ON_EXIT;
607 }
608
609 if (BIO_write (BioCert, Data, (UINT32) DataSize) <= 0) {
610 Status = EFI_ABORTED;
611 goto ON_EXIT;
612 }
613
614 Cert = PEM_read_bio_X509 (BioCert, NULL, NULL, NULL);
615 if (Cert == NULL) {
616 Status = EFI_ABORTED;
617 goto ON_EXIT;
618 }
619 }
620
621 SslCtx = SSL_get_SSL_CTX (TlsConn->Ssl);
622 X509Store = SSL_CTX_get_cert_store (SslCtx);
623 if (X509Store == NULL) {
624 Status = EFI_ABORTED;
625 goto ON_EXIT;
626 }
627
628 //
629 // Add certificate to X509 store
630 //
631 Ret = X509_STORE_add_cert (X509Store, Cert);
632 if (Ret != 1) {
633 ErrorCode = ERR_peek_last_error ();
634 //
635 // Ignore "already in table" errors
636 //
637 if (!(ERR_GET_FUNC (ErrorCode) == X509_F_X509_STORE_ADD_CERT &&
638 ERR_GET_REASON (ErrorCode) == X509_R_CERT_ALREADY_IN_HASH_TABLE)) {
639 Status = EFI_ABORTED;
640 goto ON_EXIT;
641 }
642 }
643
644 ON_EXIT:
645 if (BioCert != NULL) {
646 BIO_free (BioCert);
647 }
648
649 if (Cert != NULL) {
650 X509_free (Cert);
651 }
652
653 return Status;
654 }
655
656 /**
657 Loads the local public certificate into the specified TLS object.
658
659 This function loads the X.509 certificate into the specified TLS object
660 for TLS negotiation.
661
662 @param[in] Tls Pointer to the TLS object.
663 @param[in] Data Pointer to the data buffer of a DER-encoded binary
664 X.509 certificate or PEM-encoded X.509 certificate.
665 @param[in] DataSize The size of data buffer in bytes.
666
667 @retval EFI_SUCCESS The operation succeeded.
668 @retval EFI_INVALID_PARAMETER The parameter is invalid.
669 @retval EFI_OUT_OF_RESOURCES Required resources could not be allocated.
670 @retval EFI_ABORTED Invalid X.509 certificate.
671
672 **/
673 EFI_STATUS
674 EFIAPI
675 TlsSetHostPublicCert (
676 IN VOID *Tls,
677 IN VOID *Data,
678 IN UINTN DataSize
679 )
680 {
681 BIO *BioCert;
682 X509 *Cert;
683 EFI_STATUS Status;
684 TLS_CONNECTION *TlsConn;
685
686 BioCert = NULL;
687 Cert = NULL;
688 Status = EFI_SUCCESS;
689 TlsConn = (TLS_CONNECTION *) Tls;
690
691 if (TlsConn == NULL || TlsConn->Ssl == NULL || Data == NULL || DataSize == 0) {
692 return EFI_INVALID_PARAMETER;
693 }
694
695 //
696 // DER-encoded binary X.509 certificate or PEM-encoded X.509 certificate.
697 // Determine whether certificate is from DER encoding, if so, translate it to X509 structure.
698 //
699 Cert = d2i_X509 (NULL, (const unsigned char ** )&Data, (long) DataSize);
700 if (Cert == NULL) {
701 //
702 // Certificate is from PEM encoding.
703 //
704 BioCert = BIO_new (BIO_s_mem ());
705 if (BioCert == NULL) {
706 Status = EFI_OUT_OF_RESOURCES;
707 goto ON_EXIT;
708 }
709
710 if (BIO_write (BioCert, Data, (UINT32) DataSize) <= 0) {
711 Status = EFI_ABORTED;
712 goto ON_EXIT;
713 }
714
715 Cert = PEM_read_bio_X509 (BioCert, NULL, NULL, NULL);
716 if (Cert == NULL) {
717 Status = EFI_ABORTED;
718 goto ON_EXIT;
719 }
720 }
721
722 if (SSL_use_certificate (TlsConn->Ssl, Cert) != 1) {
723 Status = EFI_ABORTED;
724 goto ON_EXIT;
725 }
726
727 ON_EXIT:
728 if (BioCert != NULL) {
729 BIO_free (BioCert);
730 }
731
732 if (Cert != NULL) {
733 X509_free (Cert);
734 }
735
736 return Status;
737 }
738
739 /**
740 Adds the local private key to the specified TLS object.
741
742 This function adds the local private key (PEM-encoded RSA or PKCS#8 private
743 key) into the specified TLS object for TLS negotiation.
744
745 @param[in] Tls Pointer to the TLS object.
746 @param[in] Data Pointer to the data buffer of a PEM-encoded RSA
747 or PKCS#8 private key.
748 @param[in] DataSize The size of data buffer in bytes.
749
750 @retval EFI_SUCCESS The operation succeeded.
751 @retval EFI_UNSUPPORTED This function is not supported.
752 @retval EFI_ABORTED Invalid private key data.
753
754 **/
755 EFI_STATUS
756 EFIAPI
757 TlsSetHostPrivateKey (
758 IN VOID *Tls,
759 IN VOID *Data,
760 IN UINTN DataSize
761 )
762 {
763 return EFI_UNSUPPORTED;
764 }
765
766 /**
767 Adds the CA-supplied certificate revocation list for certificate validation.
768
769 This function adds the CA-supplied certificate revocation list data for
770 certificate validity checking.
771
772 @param[in] Data Pointer to the data buffer of a DER-encoded CRL data.
773 @param[in] DataSize The size of data buffer in bytes.
774
775 @retval EFI_SUCCESS The operation succeeded.
776 @retval EFI_UNSUPPORTED This function is not supported.
777 @retval EFI_ABORTED Invalid CRL data.
778
779 **/
780 EFI_STATUS
781 EFIAPI
782 TlsSetCertRevocationList (
783 IN VOID *Data,
784 IN UINTN DataSize
785 )
786 {
787 return EFI_UNSUPPORTED;
788 }
789
790 /**
791 Gets the protocol version used by the specified TLS connection.
792
793 This function returns the protocol version used by the specified TLS
794 connection.
795
796 If Tls is NULL, then ASSERT().
797
798 @param[in] Tls Pointer to the TLS object.
799
800 @return The protocol version of the specified TLS connection.
801
802 **/
803 UINT16
804 EFIAPI
805 TlsGetVersion (
806 IN VOID *Tls
807 )
808 {
809 TLS_CONNECTION *TlsConn;
810
811 TlsConn = (TLS_CONNECTION *) Tls;
812
813 ASSERT (TlsConn != NULL);
814
815 return (UINT16)(SSL_version (TlsConn->Ssl));
816 }
817
818 /**
819 Gets the connection end of the specified TLS connection.
820
821 This function returns the connection end (as client or as server) used by
822 the specified TLS connection.
823
824 If Tls is NULL, then ASSERT().
825
826 @param[in] Tls Pointer to the TLS object.
827
828 @return The connection end used by the specified TLS connection.
829
830 **/
831 UINT8
832 EFIAPI
833 TlsGetConnectionEnd (
834 IN VOID *Tls
835 )
836 {
837 TLS_CONNECTION *TlsConn;
838
839 TlsConn = (TLS_CONNECTION *) Tls;
840
841 ASSERT (TlsConn != NULL);
842
843 return (UINT8)SSL_is_server (TlsConn->Ssl);
844 }
845
846 /**
847 Gets the cipher suite used by the specified TLS connection.
848
849 This function returns current cipher suite used by the specified
850 TLS connection.
851
852 @param[in] Tls Pointer to the TLS object.
853 @param[in,out] CipherId The cipher suite used by the TLS object.
854
855 @retval EFI_SUCCESS The cipher suite was returned successfully.
856 @retval EFI_INVALID_PARAMETER The parameter is invalid.
857 @retval EFI_UNSUPPORTED Unsupported cipher suite.
858
859 **/
860 EFI_STATUS
861 EFIAPI
862 TlsGetCurrentCipher (
863 IN VOID *Tls,
864 IN OUT UINT16 *CipherId
865 )
866 {
867 TLS_CONNECTION *TlsConn;
868 CONST SSL_CIPHER *Cipher;
869
870 TlsConn = (TLS_CONNECTION *) Tls;
871 Cipher = NULL;
872
873 if (TlsConn == NULL || TlsConn->Ssl == NULL || CipherId == NULL) {
874 return EFI_INVALID_PARAMETER;
875 }
876
877 Cipher = SSL_get_current_cipher (TlsConn->Ssl);
878 if (Cipher == NULL) {
879 return EFI_UNSUPPORTED;
880 }
881
882 *CipherId = (SSL_CIPHER_get_id (Cipher)) & 0xFFFF;
883
884 return EFI_SUCCESS;
885 }
886
887 /**
888 Gets the compression methods used by the specified TLS connection.
889
890 This function returns current integrated compression methods used by
891 the specified TLS connection.
892
893 @param[in] Tls Pointer to the TLS object.
894 @param[in,out] CompressionId The current compression method used by
895 the TLS object.
896
897 @retval EFI_SUCCESS The compression method was returned successfully.
898 @retval EFI_INVALID_PARAMETER The parameter is invalid.
899 @retval EFI_ABORTED Invalid Compression method.
900 @retval EFI_UNSUPPORTED This function is not supported.
901
902 **/
903 EFI_STATUS
904 EFIAPI
905 TlsGetCurrentCompressionId (
906 IN VOID *Tls,
907 IN OUT UINT8 *CompressionId
908 )
909 {
910 return EFI_UNSUPPORTED;
911 }
912
913 /**
914 Gets the verification mode currently set in the TLS connection.
915
916 This function returns the peer verification mode currently set in the
917 specified TLS connection.
918
919 If Tls is NULL, then ASSERT().
920
921 @param[in] Tls Pointer to the TLS object.
922
923 @return The verification mode set in the specified TLS connection.
924
925 **/
926 UINT32
927 EFIAPI
928 TlsGetVerify (
929 IN VOID *Tls
930 )
931 {
932 TLS_CONNECTION *TlsConn;
933
934 TlsConn = (TLS_CONNECTION *) Tls;
935
936 ASSERT (TlsConn != NULL);
937
938 return SSL_get_verify_mode (TlsConn->Ssl);
939 }
940
941 /**
942 Gets the session ID used by the specified TLS connection.
943
944 This function returns the TLS/SSL session ID currently used by the
945 specified TLS connection.
946
947 @param[in] Tls Pointer to the TLS object.
948 @param[in,out] SessionId Buffer to contain the returned session ID.
949 @param[in,out] SessionIdLen The length of Session ID in bytes.
950
951 @retval EFI_SUCCESS The Session ID was returned successfully.
952 @retval EFI_INVALID_PARAMETER The parameter is invalid.
953 @retval EFI_UNSUPPORTED Invalid TLS/SSL session.
954
955 **/
956 EFI_STATUS
957 EFIAPI
958 TlsGetSessionId (
959 IN VOID *Tls,
960 IN OUT UINT8 *SessionId,
961 IN OUT UINT16 *SessionIdLen
962 )
963 {
964 TLS_CONNECTION *TlsConn;
965 SSL_SESSION *Session;
966 CONST UINT8 *SslSessionId;
967
968 TlsConn = (TLS_CONNECTION *) Tls;
969 Session = NULL;
970
971 if (TlsConn == NULL || TlsConn->Ssl == NULL || SessionId == NULL || SessionIdLen == NULL) {
972 return EFI_INVALID_PARAMETER;
973 }
974
975 Session = SSL_get_session (TlsConn->Ssl);
976 if (Session == NULL) {
977 return EFI_UNSUPPORTED;
978 }
979
980 SslSessionId = SSL_SESSION_get_id (Session, (unsigned int *)SessionIdLen);
981 CopyMem (SessionId, SslSessionId, *SessionIdLen);
982
983 return EFI_SUCCESS;
984 }
985
986 /**
987 Gets the client random data used in the specified TLS connection.
988
989 This function returns the TLS/SSL client random data currently used in
990 the specified TLS connection.
991
992 @param[in] Tls Pointer to the TLS object.
993 @param[in,out] ClientRandom Buffer to contain the returned client
994 random data (32 bytes).
995
996 **/
997 VOID
998 EFIAPI
999 TlsGetClientRandom (
1000 IN VOID *Tls,
1001 IN OUT UINT8 *ClientRandom
1002 )
1003 {
1004 TLS_CONNECTION *TlsConn;
1005
1006 TlsConn = (TLS_CONNECTION *) Tls;
1007
1008 if (TlsConn == NULL || TlsConn->Ssl == NULL || ClientRandom == NULL) {
1009 return;
1010 }
1011
1012 SSL_get_client_random (TlsConn->Ssl, ClientRandom, SSL3_RANDOM_SIZE);
1013 }
1014
1015 /**
1016 Gets the server random data used in the specified TLS connection.
1017
1018 This function returns the TLS/SSL server random data currently used in
1019 the specified TLS connection.
1020
1021 @param[in] Tls Pointer to the TLS object.
1022 @param[in,out] ServerRandom Buffer to contain the returned server
1023 random data (32 bytes).
1024
1025 **/
1026 VOID
1027 EFIAPI
1028 TlsGetServerRandom (
1029 IN VOID *Tls,
1030 IN OUT UINT8 *ServerRandom
1031 )
1032 {
1033 TLS_CONNECTION *TlsConn;
1034
1035 TlsConn = (TLS_CONNECTION *) Tls;
1036
1037 if (TlsConn == NULL || TlsConn->Ssl == NULL || ServerRandom == NULL) {
1038 return;
1039 }
1040
1041 SSL_get_server_random (TlsConn->Ssl, ServerRandom, SSL3_RANDOM_SIZE);
1042 }
1043
1044 /**
1045 Gets the master key data used in the specified TLS connection.
1046
1047 This function returns the TLS/SSL master key material currently used in
1048 the specified TLS connection.
1049
1050 @param[in] Tls Pointer to the TLS object.
1051 @param[in,out] KeyMaterial Buffer to contain the returned key material.
1052
1053 @retval EFI_SUCCESS Key material was returned successfully.
1054 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1055 @retval EFI_UNSUPPORTED Invalid TLS/SSL session.
1056
1057 **/
1058 EFI_STATUS
1059 EFIAPI
1060 TlsGetKeyMaterial (
1061 IN VOID *Tls,
1062 IN OUT UINT8 *KeyMaterial
1063 )
1064 {
1065 TLS_CONNECTION *TlsConn;
1066 SSL_SESSION *Session;
1067
1068 TlsConn = (TLS_CONNECTION *) Tls;
1069 Session = NULL;
1070
1071 if (TlsConn == NULL || TlsConn->Ssl == NULL || KeyMaterial == NULL) {
1072 return EFI_INVALID_PARAMETER;
1073 }
1074
1075 Session = SSL_get_session (TlsConn->Ssl);
1076
1077 if (Session == NULL) {
1078 return EFI_UNSUPPORTED;
1079 }
1080
1081 SSL_SESSION_get_master_key (Session, KeyMaterial, SSL3_MASTER_SECRET_SIZE);
1082
1083 return EFI_SUCCESS;
1084 }
1085
1086 /**
1087 Gets the CA Certificate from the cert store.
1088
1089 This function returns the CA certificate for the chosen
1090 TLS connection.
1091
1092 @param[in] Tls Pointer to the TLS object.
1093 @param[out] Data Pointer to the data buffer to receive the CA
1094 certificate data sent to the client.
1095 @param[in,out] DataSize The size of data buffer in bytes.
1096
1097 @retval EFI_SUCCESS The operation succeeded.
1098 @retval EFI_UNSUPPORTED This function is not supported.
1099 @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data.
1100
1101 **/
1102 EFI_STATUS
1103 EFIAPI
1104 TlsGetCaCertificate (
1105 IN VOID *Tls,
1106 OUT VOID *Data,
1107 IN OUT UINTN *DataSize
1108 )
1109 {
1110 return EFI_UNSUPPORTED;
1111 }
1112
1113 /**
1114 Gets the local public Certificate set in the specified TLS object.
1115
1116 This function returns the local public certificate which was currently set
1117 in the specified TLS object.
1118
1119 @param[in] Tls Pointer to the TLS object.
1120 @param[out] Data Pointer to the data buffer to receive the local
1121 public certificate.
1122 @param[in,out] DataSize The size of data buffer in bytes.
1123
1124 @retval EFI_SUCCESS The operation succeeded.
1125 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1126 @retval EFI_NOT_FOUND The certificate is not found.
1127 @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data.
1128
1129 **/
1130 EFI_STATUS
1131 EFIAPI
1132 TlsGetHostPublicCert (
1133 IN VOID *Tls,
1134 OUT VOID *Data,
1135 IN OUT UINTN *DataSize
1136 )
1137 {
1138 X509 *Cert;
1139 TLS_CONNECTION *TlsConn;
1140
1141 Cert = NULL;
1142 TlsConn = (TLS_CONNECTION *) Tls;
1143
1144 if (TlsConn == NULL || TlsConn->Ssl == NULL || DataSize == NULL || (*DataSize != 0 && Data == NULL)) {
1145 return EFI_INVALID_PARAMETER;
1146 }
1147
1148 Cert = SSL_get_certificate(TlsConn->Ssl);
1149 if (Cert == NULL) {
1150 return EFI_NOT_FOUND;
1151 }
1152
1153 //
1154 // Only DER encoding is supported currently.
1155 //
1156 if (*DataSize < (UINTN) i2d_X509 (Cert, NULL)) {
1157 *DataSize = (UINTN) i2d_X509 (Cert, NULL);
1158 return EFI_BUFFER_TOO_SMALL;
1159 }
1160
1161 *DataSize = (UINTN) i2d_X509 (Cert, (unsigned char **) &Data);
1162
1163 return EFI_SUCCESS;
1164 }
1165
1166 /**
1167 Gets the local private key set in the specified TLS object.
1168
1169 This function returns the local private key data which was currently set
1170 in the specified TLS object.
1171
1172 @param[in] Tls Pointer to the TLS object.
1173 @param[out] Data Pointer to the data buffer to receive the local
1174 private key data.
1175 @param[in,out] DataSize The size of data buffer in bytes.
1176
1177 @retval EFI_SUCCESS The operation succeeded.
1178 @retval EFI_UNSUPPORTED This function is not supported.
1179 @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data.
1180
1181 **/
1182 EFI_STATUS
1183 EFIAPI
1184 TlsGetHostPrivateKey (
1185 IN VOID *Tls,
1186 OUT VOID *Data,
1187 IN OUT UINTN *DataSize
1188 )
1189 {
1190 return EFI_UNSUPPORTED;
1191 }
1192
1193 /**
1194 Gets the CA-supplied certificate revocation list data set in the specified
1195 TLS object.
1196
1197 This function returns the CA-supplied certificate revocation list data which
1198 was currently set in the specified TLS object.
1199
1200 @param[out] Data Pointer to the data buffer to receive the CRL data.
1201 @param[in,out] DataSize The size of data buffer in bytes.
1202
1203 @retval EFI_SUCCESS The operation succeeded.
1204 @retval EFI_UNSUPPORTED This function is not supported.
1205 @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data.
1206
1207 **/
1208 EFI_STATUS
1209 EFIAPI
1210 TlsGetCertRevocationList (
1211 OUT VOID *Data,
1212 IN OUT UINTN *DataSize
1213 )
1214 {
1215 return EFI_UNSUPPORTED;
1216 }
1217