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